[css-lists] Add list-style-type: <string>

This patch extends the syntax of the list-style-type property to accept
arbitrary string values in order to customize the marker contents.

I have followed the same approach as https://crrev.com/c/879135 did for
the display property. When a string is specified for list-style-type,
the patch sets it to a special EListStyleType::kString, and the string
is stored in an extra field. As a result of this split, list-style-type
doesn't use as much auto generated code now, e.g. EListStyleType is not
automatically generated.

Intent to Implement and Ship: list-style-type: <string>
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/GojYpoeDbqc

Spec: https://drafts.csswg.org/css-lists/#valdef-list-style-type-string

Bug: 687946

TEST=third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005a.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005b.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-computed.html
TEST=third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-valid.html
TEST=third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001a.html
TEST=third_party/blink/web_tests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001b.html

This patch makes some ::marker tests in css-pseudo fail, but this is
expected because ::marker has not been implemented yet.

Change-Id: I5743b99bc1a8e66679235874623c82650860ea29
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1841472
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Reviewed-by: Morten Stenshorne <mstensho@chromium.org>
Reviewed-by: Koji Ishii <kojii@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704563}
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 02aebb6..4924191 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2104,9 +2104,8 @@
     },
     {
       name: "list-style-type",
-      property_methods: ["CSSValueFromComputedStyleInternal"],
+      property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
       inherited: true,
-      field_template: "keyword",
       keywords: [
         "disc", "circle", "square", "decimal", "decimal-leading-zero",
         "arabic-indic", "bengali", "cambodian", "khmer", "devanagari",
@@ -2122,7 +2121,7 @@
         "simp-chinese-informal", "trad-chinese-formal", "trad-chinese-informal",
         "hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "none"
       ],
-      default_value: "disc",
+      style_builder_custom_functions: ["initial", "inherit", "value"],
     },
     {
       name: "margin-bottom",
diff --git a/third_party/blink/renderer/core/css/css_value_id_mappings.h b/third_party/blink/renderer/core/css/css_value_id_mappings.h
index ffa22b63c..c6490c8 100644
--- a/third_party/blink/renderer/core/css/css_value_id_mappings.h
+++ b/third_party/blink/renderer/core/css/css_value_id_mappings.h
@@ -174,6 +174,130 @@
 }
 
 template <>
+inline EListStyleType CssValueIDToPlatformEnum(CSSValueID v) {
+  switch (v) {
+    case CSSValueID::kDisc:
+      return EListStyleType::kDisc;
+    case CSSValueID::kCircle:
+      return EListStyleType::kCircle;
+    case CSSValueID::kSquare:
+      return EListStyleType::kSquare;
+    case CSSValueID::kDecimal:
+      return EListStyleType::kDecimal;
+    case CSSValueID::kDecimalLeadingZero:
+      return EListStyleType::kDecimalLeadingZero;
+    case CSSValueID::kArabicIndic:
+      return EListStyleType::kArabicIndic;
+    case CSSValueID::kBengali:
+      return EListStyleType::kBengali;
+    case CSSValueID::kCambodian:
+      return EListStyleType::kCambodian;
+    case CSSValueID::kKhmer:
+      return EListStyleType::kKhmer;
+    case CSSValueID::kDevanagari:
+      return EListStyleType::kDevanagari;
+    case CSSValueID::kGujarati:
+      return EListStyleType::kGujarati;
+    case CSSValueID::kGurmukhi:
+      return EListStyleType::kGurmukhi;
+    case CSSValueID::kKannada:
+      return EListStyleType::kKannada;
+    case CSSValueID::kLao:
+      return EListStyleType::kLao;
+    case CSSValueID::kMalayalam:
+      return EListStyleType::kMalayalam;
+    case CSSValueID::kMongolian:
+      return EListStyleType::kMongolian;
+    case CSSValueID::kMyanmar:
+      return EListStyleType::kMyanmar;
+    case CSSValueID::kOriya:
+      return EListStyleType::kOriya;
+    case CSSValueID::kPersian:
+      return EListStyleType::kPersian;
+    case CSSValueID::kUrdu:
+      return EListStyleType::kUrdu;
+    case CSSValueID::kTelugu:
+      return EListStyleType::kTelugu;
+    case CSSValueID::kTibetan:
+      return EListStyleType::kTibetan;
+    case CSSValueID::kThai:
+      return EListStyleType::kThai;
+    case CSSValueID::kLowerRoman:
+      return EListStyleType::kLowerRoman;
+    case CSSValueID::kUpperRoman:
+      return EListStyleType::kUpperRoman;
+    case CSSValueID::kLowerGreek:
+      return EListStyleType::kLowerGreek;
+    case CSSValueID::kLowerAlpha:
+      return EListStyleType::kLowerAlpha;
+    case CSSValueID::kLowerLatin:
+      return EListStyleType::kLowerLatin;
+    case CSSValueID::kUpperAlpha:
+      return EListStyleType::kUpperAlpha;
+    case CSSValueID::kUpperLatin:
+      return EListStyleType::kUpperLatin;
+    case CSSValueID::kCjkEarthlyBranch:
+      return EListStyleType::kCjkEarthlyBranch;
+    case CSSValueID::kCjkHeavenlyStem:
+      return EListStyleType::kCjkHeavenlyStem;
+    case CSSValueID::kEthiopicHalehame:
+      return EListStyleType::kEthiopicHalehame;
+    case CSSValueID::kEthiopicHalehameAm:
+      return EListStyleType::kEthiopicHalehameAm;
+    case CSSValueID::kEthiopicHalehameTiEr:
+      return EListStyleType::kEthiopicHalehameTiEr;
+    case CSSValueID::kEthiopicHalehameTiEt:
+      return EListStyleType::kEthiopicHalehameTiEt;
+    case CSSValueID::kHangul:
+      return EListStyleType::kHangul;
+    case CSSValueID::kHangulConsonant:
+      return EListStyleType::kHangulConsonant;
+    case CSSValueID::kKoreanHangulFormal:
+      return EListStyleType::kKoreanHangulFormal;
+    case CSSValueID::kKoreanHanjaFormal:
+      return EListStyleType::kKoreanHanjaFormal;
+    case CSSValueID::kKoreanHanjaInformal:
+      return EListStyleType::kKoreanHanjaInformal;
+    case CSSValueID::kHebrew:
+      return EListStyleType::kHebrew;
+    case CSSValueID::kArmenian:
+      return EListStyleType::kArmenian;
+    case CSSValueID::kLowerArmenian:
+      return EListStyleType::kLowerArmenian;
+    case CSSValueID::kUpperArmenian:
+      return EListStyleType::kUpperArmenian;
+    case CSSValueID::kGeorgian:
+      return EListStyleType::kGeorgian;
+    case CSSValueID::kCjkIdeographic:
+      return EListStyleType::kCjkIdeographic;
+    case CSSValueID::kSimpChineseFormal:
+      return EListStyleType::kSimpChineseFormal;
+    case CSSValueID::kSimpChineseInformal:
+      return EListStyleType::kSimpChineseInformal;
+    case CSSValueID::kTradChineseFormal:
+      return EListStyleType::kTradChineseFormal;
+    case CSSValueID::kTradChineseInformal:
+      return EListStyleType::kTradChineseInformal;
+    case CSSValueID::kHiragana:
+      return EListStyleType::kHiragana;
+    case CSSValueID::kKatakana:
+      return EListStyleType::kKatakana;
+    case CSSValueID::kHiraganaIroha:
+      return EListStyleType::kHiraganaIroha;
+    case CSSValueID::kKatakanaIroha:
+      return EListStyleType::kKatakanaIroha;
+    case CSSValueID::kNone:
+      return EListStyleType::kNone;
+    default:
+      NOTREACHED();
+      break;
+  }
+
+  NOTREACHED();
+  return EListStyleType::kDisc;
+}
+
+template <>
 inline EUserSelect CssValueIDToPlatformEnum(CSSValueID v) {
   if (v == CSSValueID::kAuto)
     return EUserSelect::kAuto;
@@ -233,6 +357,130 @@
   return CSSValueID::kInline;
 }
 
+template <>
+inline CSSValueID PlatformEnumToCSSValueID(EListStyleType v) {
+  switch (v) {
+    case EListStyleType::kDisc:
+      return CSSValueID::kDisc;
+    case EListStyleType::kCircle:
+      return CSSValueID::kCircle;
+    case EListStyleType::kSquare:
+      return CSSValueID::kSquare;
+    case EListStyleType::kDecimal:
+      return CSSValueID::kDecimal;
+    case EListStyleType::kDecimalLeadingZero:
+      return CSSValueID::kDecimalLeadingZero;
+    case EListStyleType::kArabicIndic:
+      return CSSValueID::kArabicIndic;
+    case EListStyleType::kBengali:
+      return CSSValueID::kBengali;
+    case EListStyleType::kCambodian:
+      return CSSValueID::kCambodian;
+    case EListStyleType::kKhmer:
+      return CSSValueID::kKhmer;
+    case EListStyleType::kDevanagari:
+      return CSSValueID::kDevanagari;
+    case EListStyleType::kGujarati:
+      return CSSValueID::kGujarati;
+    case EListStyleType::kGurmukhi:
+      return CSSValueID::kGurmukhi;
+    case EListStyleType::kKannada:
+      return CSSValueID::kKannada;
+    case EListStyleType::kLao:
+      return CSSValueID::kLao;
+    case EListStyleType::kMalayalam:
+      return CSSValueID::kMalayalam;
+    case EListStyleType::kMongolian:
+      return CSSValueID::kMongolian;
+    case EListStyleType::kMyanmar:
+      return CSSValueID::kMyanmar;
+    case EListStyleType::kOriya:
+      return CSSValueID::kOriya;
+    case EListStyleType::kPersian:
+      return CSSValueID::kPersian;
+    case EListStyleType::kUrdu:
+      return CSSValueID::kUrdu;
+    case EListStyleType::kTelugu:
+      return CSSValueID::kTelugu;
+    case EListStyleType::kTibetan:
+      return CSSValueID::kTibetan;
+    case EListStyleType::kThai:
+      return CSSValueID::kThai;
+    case EListStyleType::kLowerRoman:
+      return CSSValueID::kLowerRoman;
+    case EListStyleType::kUpperRoman:
+      return CSSValueID::kUpperRoman;
+    case EListStyleType::kLowerGreek:
+      return CSSValueID::kLowerGreek;
+    case EListStyleType::kLowerAlpha:
+      return CSSValueID::kLowerAlpha;
+    case EListStyleType::kLowerLatin:
+      return CSSValueID::kLowerLatin;
+    case EListStyleType::kUpperAlpha:
+      return CSSValueID::kUpperAlpha;
+    case EListStyleType::kUpperLatin:
+      return CSSValueID::kUpperLatin;
+    case EListStyleType::kCjkEarthlyBranch:
+      return CSSValueID::kCjkEarthlyBranch;
+    case EListStyleType::kCjkHeavenlyStem:
+      return CSSValueID::kCjkHeavenlyStem;
+    case EListStyleType::kEthiopicHalehame:
+      return CSSValueID::kEthiopicHalehame;
+    case EListStyleType::kEthiopicHalehameAm:
+      return CSSValueID::kEthiopicHalehameAm;
+    case EListStyleType::kEthiopicHalehameTiEr:
+      return CSSValueID::kEthiopicHalehameTiEr;
+    case EListStyleType::kEthiopicHalehameTiEt:
+      return CSSValueID::kEthiopicHalehameTiEt;
+    case EListStyleType::kHangul:
+      return CSSValueID::kHangul;
+    case EListStyleType::kHangulConsonant:
+      return CSSValueID::kHangulConsonant;
+    case EListStyleType::kKoreanHangulFormal:
+      return CSSValueID::kKoreanHangulFormal;
+    case EListStyleType::kKoreanHanjaFormal:
+      return CSSValueID::kKoreanHanjaFormal;
+    case EListStyleType::kKoreanHanjaInformal:
+      return CSSValueID::kKoreanHanjaInformal;
+    case EListStyleType::kHebrew:
+      return CSSValueID::kHebrew;
+    case EListStyleType::kArmenian:
+      return CSSValueID::kArmenian;
+    case EListStyleType::kLowerArmenian:
+      return CSSValueID::kLowerArmenian;
+    case EListStyleType::kUpperArmenian:
+      return CSSValueID::kUpperArmenian;
+    case EListStyleType::kGeorgian:
+      return CSSValueID::kGeorgian;
+    case EListStyleType::kCjkIdeographic:
+      return CSSValueID::kCjkIdeographic;
+    case EListStyleType::kSimpChineseFormal:
+      return CSSValueID::kSimpChineseFormal;
+    case EListStyleType::kSimpChineseInformal:
+      return CSSValueID::kSimpChineseInformal;
+    case EListStyleType::kTradChineseFormal:
+      return CSSValueID::kTradChineseFormal;
+    case EListStyleType::kTradChineseInformal:
+      return CSSValueID::kTradChineseInformal;
+    case EListStyleType::kHiragana:
+      return CSSValueID::kHiragana;
+    case EListStyleType::kKatakana:
+      return CSSValueID::kKatakana;
+    case EListStyleType::kHiraganaIroha:
+      return CSSValueID::kHiraganaIroha;
+    case EListStyleType::kKatakanaIroha:
+      return CSSValueID::kKatakanaIroha;
+    case EListStyleType::kNone:
+      return CSSValueID::kNone;
+    case EListStyleType::kString:
+      NOTREACHED();
+      break;
+  }
+
+  NOTREACHED();
+  return CSSValueID::kDisc;
+}
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
index eecdcb0..63a9668 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -1095,6 +1095,7 @@
 bool CSSParserFastPaths::IsPartialKeywordPropertyID(CSSPropertyID property_id) {
   switch (property_id) {
     case CSSPropertyID::kDisplay:
+    case CSSPropertyID::kListStyleType:
       return true;
     default:
       return false;
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 890be20..c00a12c 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -3778,14 +3778,53 @@
   return CSSIdentifierValue::Create(style.ListStylePosition());
 }
 
+const CSSValue* ListStyleType::ParseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&) const {
+  // NOTE: All the keyword values for the list-style-type property are handled
+  // by the CSSParserFastPaths.
+  return css_property_parser_helpers::ConsumeString(range);
+}
+
 const CSSValue* ListStyleType::CSSValueFromComputedStyleInternal(
     const ComputedStyle& style,
     const SVGComputedStyle&,
     const LayoutObject*,
     bool allow_visited_style) const {
+  if (style.ListStyleType() == EListStyleType::kString)
+    return MakeGarbageCollected<CSSStringValue>(style.ListStyleStringValue());
   return CSSIdentifierValue::Create(style.ListStyleType());
 }
 
+void ListStyleType::ApplyInitial(StyleResolverState& state) const {
+  state.Style()->SetListStyleType(
+      ComputedStyleInitialValues::InitialListStyleType());
+  state.Style()->SetListStyleStringValue(
+      ComputedStyleInitialValues::InitialListStyleStringValue());
+}
+
+void ListStyleType::ApplyInherit(StyleResolverState& state) const {
+  state.Style()->SetListStyleType(state.ParentStyle()->ListStyleType());
+  state.Style()->SetListStyleStringValue(
+      state.ParentStyle()->ListStyleStringValue());
+}
+
+void ListStyleType::ApplyValue(StyleResolverState& state,
+                               const CSSValue& value) const {
+  if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+    state.Style()->SetListStyleType(
+        identifier_value->ConvertTo<EListStyleType>());
+    state.Style()->SetListStyleStringValue(
+        ComputedStyleInitialValues::InitialListStyleStringValue());
+    return;
+  }
+
+  state.Style()->SetListStyleType(EListStyleType::kString);
+  state.Style()->SetListStyleStringValue(
+      AtomicString(To<CSSStringValue>(value).Value()));
+}
+
 bool MarginBlockEnd::IsLayoutDependent(const ComputedStyle* style,
                                        LayoutObject* layout_object) const {
   return layout_object && layout_object->IsBox();
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.cc b/third_party/blink/renderer/core/layout/layout_list_marker.cc
index 15986960..6ef9788 100644
--- a/third_party/blink/renderer/core/layout/layout_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/layout_list_marker.cc
@@ -84,7 +84,10 @@
                                        const ComputedStyle& new_style) {
   if (Style() &&
       (new_style.ListStylePosition() != StyleRef().ListStylePosition() ||
-       new_style.ListStyleType() != StyleRef().ListStyleType())) {
+       new_style.ListStyleType() != StyleRef().ListStyleType() ||
+       (new_style.ListStyleType() == EListStyleType::kString &&
+        new_style.ListStyleStringValue() !=
+            StyleRef().ListStyleStringValue()))) {
     SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
         layout_invalidation_reason::kStyleChange);
   }
@@ -201,21 +204,31 @@
       text_ = list_marker_text::GetText(StyleRef().ListStyleType(),
                                         list_item_->Value());
       break;
+    case ListStyleCategory::kStaticString:
+      text_ = StyleRef().ListStyleStringValue();
+      break;
   }
 }
 
 String LayoutListMarker::TextAlternative() const {
+  if (GetListStyleCategory() == ListStyleCategory::kStaticString)
+    return text_;
   UChar suffix =
       list_marker_text::Suffix(StyleRef().ListStyleType(), list_item_->Value());
   // Return suffix after the marker text, even in RTL, reflecting speech order.
   return text_ + suffix + ' ';
 }
 
-LayoutUnit LayoutListMarker::GetWidthOfTextWithSuffix() const {
+LayoutUnit LayoutListMarker::GetWidthOfText(ListStyleCategory category) const {
+  // TODO(crbug.com/1012289): this code doesn't support bidi algorithm.
   if (text_.IsEmpty())
     return LayoutUnit();
   const Font& font = StyleRef().GetFont();
   LayoutUnit item_width = LayoutUnit(font.Width(TextRun(text_)));
+  if (category == ListStyleCategory::kStaticString) {
+    // Don't add a suffix.
+    return item_width;
+  }
   // TODO(wkorman): Look into constructing a text run for both text and suffix
   // and painting them together.
   UChar suffix[2] = {
@@ -242,14 +255,16 @@
   }
 
   LayoutUnit logical_width;
-  switch (GetListStyleCategory()) {
+  ListStyleCategory category = GetListStyleCategory();
+  switch (category) {
     case ListStyleCategory::kNone:
       break;
     case ListStyleCategory::kSymbol:
       logical_width = WidthOfSymbol(StyleRef());
       break;
     case ListStyleCategory::kLanguage:
-      logical_width = GetWidthOfTextWithSuffix();
+    case ListStyleCategory::kStaticString:
+      logical_width = GetWidthOfText(category);
       break;
   }
 
@@ -395,6 +410,8 @@
   switch (type) {
     case EListStyleType::kNone:
       return ListStyleCategory::kNone;
+    case EListStyleType::kString:
+      return ListStyleCategory::kStaticString;
     case EListStyleType::kDisc:
     case EListStyleType::kCircle:
     case EListStyleType::kSquare:
@@ -468,18 +485,20 @@
     return LayoutRect(LayoutPoint(), ImageBulletSize());
 
   LayoutRect relative_rect;
-  switch (GetListStyleCategory()) {
+  ListStyleCategory category = GetListStyleCategory();
+  switch (category) {
     case ListStyleCategory::kNone:
       return LayoutRect();
     case ListStyleCategory::kSymbol:
       return RelativeSymbolMarkerRect(StyleRef(), Size().Width());
-    case ListStyleCategory::kLanguage: {
+    case ListStyleCategory::kLanguage:
+    case ListStyleCategory::kStaticString: {
       const SimpleFontData* font_data = StyleRef().GetFont().PrimaryFont();
       DCHECK(font_data);
       if (!font_data)
         return relative_rect;
       relative_rect =
-          LayoutRect(LayoutUnit(), LayoutUnit(), GetWidthOfTextWithSuffix(),
+          LayoutRect(LayoutUnit(), LayoutUnit(), GetWidthOfText(category),
                      LayoutUnit(font_data->GetFontMetrics().Height()));
       break;
     }
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.h b/third_party/blink/renderer/core/layout/layout_list_marker.h
index 69c6ed6..68d1a29 100644
--- a/third_party/blink/renderer/core/layout/layout_list_marker.h
+++ b/third_party/blink/renderer/core/layout/layout_list_marker.h
@@ -46,7 +46,7 @@
 
   // A reduced set of list style categories allowing for more concise expression
   // of list style specific logic.
-  enum class ListStyleCategory { kNone, kSymbol, kLanguage };
+  enum class ListStyleCategory { kNone, kSymbol, kLanguage, kStaticString };
 
   // Returns the list's style as one of a reduced high level categorical set of
   // styles.
@@ -113,7 +113,7 @@
 
   bool IsText() const { return !IsImage(); }
 
-  LayoutUnit GetWidthOfTextWithSuffix() const;
+  LayoutUnit GetWidthOfText(ListStyleCategory) const;
   void UpdateMargins();
   void UpdateContent();
 
diff --git a/third_party/blink/renderer/core/layout/list_marker_text.cc b/third_party/blink/renderer/core/layout/list_marker_text.cc
index 4d76b7e..174c83e 100644
--- a/third_party/blink/renderer/core/layout/list_marker_text.cc
+++ b/third_party/blink/renderer/core/layout/list_marker_text.cc
@@ -515,6 +515,9 @@
     case EListStyleType::kUpperAlpha:
     case EListStyleType::kUpperLatin:
       return (count < 1) ? EListStyleType::kDecimal : type;
+    case EListStyleType::kString:
+      NOTREACHED();
+      break;
   }
 
   NOTREACHED();
@@ -590,6 +593,9 @@
     case EListStyleType::kKoreanHanjaFormal:
     case EListStyleType::kKoreanHanjaInformal:
       return 0x3001;
+    case EListStyleType::kString:
+      NOTREACHED();
+      break;
   }
 
   NOTREACHED();
@@ -924,6 +930,10 @@
       return ToGeorgian(count);
     case EListStyleType::kHebrew:
       return ToHebrew(count);
+
+    case EListStyleType::kString:
+      NOTREACHED();
+      break;
   }
 
   NOTREACHED();
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
index 60052f7..a7d551b 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
@@ -53,7 +53,10 @@
 
   UpdateMarker();
 
-  if (old_style && old_style->ListStyleType() != StyleRef().ListStyleType())
+  if (old_style && (old_style->ListStyleType() != StyleRef().ListStyleType() ||
+                    (StyleRef().ListStyleType() == EListStyleType::kString &&
+                     old_style->ListStyleStringValue() !=
+                         StyleRef().ListStyleStringValue())))
     ListStyleTypeChanged();
 }
 
@@ -152,6 +155,11 @@
         LayoutListMarker::InlineMarginsForInside(style, IsMarkerImage());
     marker_style->SetMarginStart(Length::Fixed(margins.first));
     marker_style->SetMarginEnd(Length::Fixed(margins.second));
+    // Markers should have unicode-bidi:isolate according to the spec
+    // (https://drafts.csswg.org/css-lists/#ua-stylesheet).
+    // Note this is only relevant for inside markers with arbitrary strings.
+    if (style.ListStyleType() == EListStyleType::kString)
+      marker_style->SetUnicodeBidi(UnicodeBidi::kIsolate);
   } else {
     if (marker_ && !marker_->IsLayoutBlockFlow())
       DestroyMarker();
@@ -212,11 +220,15 @@
   switch (style.ListStyleType()) {
     case EListStyleType::kNone:
       return kStatic;
+    case EListStyleType::kString: {
+      text->Append(style.ListStyleStringValue());
+      return kStatic;
+    }
     case EListStyleType::kDisc:
     case EListStyleType::kCircle:
     case EListStyleType::kSquare:
       // value is ignored for these types
-      text->Append(list_marker_text::GetText(Style()->ListStyleType(), 0));
+      text->Append(list_marker_text::GetText(style.ListStyleType(), 0));
       if (format == kWithSuffix)
         text->Append(' ');
       return kSymbolValue;
@@ -273,9 +285,9 @@
     case EListStyleType::kUpperRoman:
     case EListStyleType::kUrdu: {
       int value = Value();
-      text->Append(list_marker_text::GetText(Style()->ListStyleType(), value));
+      text->Append(list_marker_text::GetText(style.ListStyleType(), value));
       if (format == kWithSuffix) {
-        text->Append(list_marker_text::Suffix(Style()->ListStyleType(), value));
+        text->Append(list_marker_text::Suffix(style.ListStyleType(), value));
         text->Append(' ');
       }
       return kOrdinalValue;
diff --git a/third_party/blink/renderer/core/paint/list_marker_painter.cc b/third_party/blink/renderer/core/paint/list_marker_painter.cc
index 5c2c56f..3d0509e 100644
--- a/third_party/blink/renderer/core/paint/list_marker_painter.cc
+++ b/third_party/blink/renderer/core/paint/list_marker_painter.cc
@@ -155,6 +155,13 @@
     text_run.SetText(reversed_text.ToString());
   }
 
+  if (style_category == LayoutListMarker::ListStyleCategory::kStaticString) {
+    // Don't add a suffix.
+    context.DrawText(font, text_run_paint_info, text_origin, kInvalidDOMNodeId);
+    context.GetPaintController().SetTextPainted();
+    return;
+  }
+
   const UChar suffix =
       list_marker_text::Suffix(layout_list_marker_.StyleRef().ListStyleType(),
                                layout_list_marker_.ListItem()->Value());
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index 5b1ba87..dec1ac5 100644
--- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -215,7 +215,11 @@
         methods_to_diff: [
           {
             method: "ListStyleType()",
-            field_dependencies: ["list-style-type"]
+            field_dependencies: ["ListStyleType"]
+          },
+          {
+            method: "ListStyleStringValue()",
+            field_dependencies: ["ListStyleStringValue"]
           },
           {
             method: "ListStylePosition()",
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
index 5b8ddb3..d30a535 100644
--- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
+++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -989,5 +989,37 @@
       default_value: "false",
       custom_compare: true,
     },
+    {
+      name: "ListStyleType",
+      inherited: true,
+      field_template: "keyword",
+      type_name: "EListStyleType",
+      keywords: [
+        "disc", "circle", "square", "decimal", "decimal-leading-zero",
+        "arabic-indic", "bengali", "cambodian", "khmer", "devanagari",
+        "gujarati", "gurmukhi", "kannada", "lao", "malayalam", "mongolian",
+        "myanmar", "oriya", "persian", "urdu", "telugu", "tibetan", "thai",
+        "lower-roman", "upper-roman", "lower-greek", "lower-alpha",
+        "lower-latin", "upper-alpha", "upper-latin", "cjk-earthly-branch",
+        "cjk-heavenly-stem", "ethiopic-halehame", "ethiopic-halehame-am",
+        "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "hangul",
+        "hangul-consonant", "korean-hangul-formal", "korean-hanja-formal",
+        "korean-hanja-informal", "hebrew", "armenian", "lower-armenian",
+        "upper-armenian", "georgian", "cjk-ideographic", "simp-chinese-formal",
+        "simp-chinese-informal", "trad-chinese-formal", "trad-chinese-informal",
+        "hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "none",
+        "string",
+      ],
+      default_value: "disc",
+    },
+    {
+      name: "ListStyleStringValue",
+      inherited: true,
+      field_template: "external",
+      field_group: "*",
+      type_name: "AtomicString",
+      include_paths: ["third_party/blink/renderer/platform/wtf/text/atomic_string.h"],
+      default_value: "g_null_atom",
+    },
   ],
 }
diff --git a/third_party/blink/renderer/core/style/counter_content.h b/third_party/blink/renderer/core/style/counter_content.h
index 9bd35e9..49f86a5 100644
--- a/third_party/blink/renderer/core/style/counter_content.h
+++ b/third_party/blink/renderer/core/style/counter_content.h
@@ -37,7 +37,9 @@
   CounterContent(const AtomicString& identifier,
                  EListStyleType style,
                  const AtomicString& separator)
-      : identifier_(identifier), list_style_(style), separator_(separator) {}
+      : identifier_(identifier), list_style_(style), separator_(separator) {
+    DCHECK_NE(style, EListStyleType::kString);
+  }
 
   const AtomicString& Identifier() const { return identifier_; }
   EListStyleType ListStyle() const { return list_style_; }
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
index b95c2633..b45a2ab 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
@@ -250,6 +250,11 @@
 ### external/wpt/css/filter-effects/
 crbug.com/591099 external/wpt/css/filter-effects/filtered-inline-applies-to-float.html [ Failure ]
 
+### external/wpt/css/css-lists/
+crbug.com/1012294 external/wpt/css/css-lists/list-style-type-string-003.html [ Pass ]
+crbug.com/1012289 external/wpt/css/css-lists/list-style-type-string-005a.html [ Failure ]
+crbug.com/1012289 external/wpt/css/css-lists/list-style-type-string-006.html [ Failure ]
+
 ### external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Failure ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 9389cec..6d7669f 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -705,6 +705,7 @@
 crbug.com/591099 external/wpt/css/css-text/shaping/shaping-011.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-inline-006.html [ Failure ]
 crbug.com/1002815 external/wpt/css/cssom-view/offsetTopLeft-trailing-space-inline.html [ Failure ]
+crbug.com/1012294 external/wpt/css/css-lists/list-style-type-string-003.html [ Failure ]
 crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ]
@@ -1802,6 +1803,7 @@
 crbug.com/995106 external/wpt/css/css-lists/inline-list.html [ Failure ]
 crbug.com/995106 external/wpt/css/css-lists/inline-list-marker.html [ Failure ]
 crbug.com/995106 external/wpt/css/css-lists/inline-list-with-table-child.html [ Failure ]
+crbug.com/1012289 external/wpt/css/css-lists/list-style-type-string-005b.html [ Failure ]
 
 # ====== Style team owned tests to here ======
 
@@ -2949,12 +2951,6 @@
 crbug.com/1012627 [ Win7 ] external/wpt/css/css-text/line-breaking/line-breaking-021.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
-crbug.com/626703 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001a.html [ Failure ]
-crbug.com/626703 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001a.html [ Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001a.html [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001b.html [ Failure ]
-crbug.com/626703 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001b.html [ Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/lists-3/list-style-type-string-001b.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/clear-site-data/storage.https.html [ Timeout ]
 crbug.com/626703 [ Mac ] external/wpt/clear-site-data/storage.https.html [ Timeout ]
 crbug.com/626703 [ Win ] external/wpt/clear-site-data/storage.https.html [ Timeout ]
@@ -4066,6 +4062,11 @@
 crbug.com/792446 external/wpt/css/css-multicol/multicol-span-float-001.xht [ Failure ]
 crbug.com/964183 external/wpt/css/css-multicol/multicol-width-005.html [ Failure ]
 
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-002.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-003.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-003b.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-004.html [ Failure ]
+crbug.com/457718 external/wpt/css/css-pseudo/marker-content-005.html [ Failure ]
 crbug.com/457718 external/wpt/css/css-pseudo/marker-content-006.html [ Failure ]
 crbug.com/457718 external/wpt/css/css-pseudo/marker-content-007.html [ Failure ]
 crbug.com/457718 external/wpt/css/css-pseudo/marker-content-008.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002-ref.html
new file mode 100644
index 0000000..8694b5f54
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>CSS Reference: String value of list-style-type with outside position</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <style>
+    .list { list-style: none }
+    .list > ::before {
+      content: "";
+      display: inline-block;
+      width: 0px;
+      direction: rtl;
+      white-space: pre;
+    }
+    .list > :nth-child(2)::before { content: "foo" }
+    .list > :nth-child(3)::before { content: "foobar"; }
+    .list > :nth-child(4)::before { content: "some very long text that is not going to fit and will overflow"; }
+  </style>
+</head>
+<body>
+  <ol class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ol>
+  <ul class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002.html
new file mode 100644
index 0000000..6f00d8a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-002.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>String value of list-style-type with outside position</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <link rel="help" href="https://drafts.csswg.org/css-lists-3/#valdef-list-style-type-string">
+  <link rel="match" href="list-style-type-string-002-ref.html">
+  <meta name="assert" content="This test checks that list-style-type can set the marker string when the marker is positioned outside.">
+  <style>
+    .list { list-style-type: "" }
+    .list > :nth-child(2) { list-style-type: "foo" }
+    .list > :nth-child(3) { list-style-type: "foobar"; }
+    .list > :nth-child(4) { list-style-type: "some very long text that is not going to fit and will overflow"; }
+  </style>
+</head>
+<body>
+  <ol class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ol>
+  <ul class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003-ref.html
new file mode 100644
index 0000000..ea3601b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>CSS Reference: String value of list-style-type with RTL direction</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <style>
+    .list {
+      list-style: none;
+      direction: rtl;
+    }
+    .list > ::before {
+      content: "";
+      display: inline-block;
+      width: 0px;
+      direction: ltr;
+      white-space: pre;
+    }
+    .list > :nth-child(2)::before { content: "foo" }
+    .list > :nth-child(3)::before { content: "foobar"; }
+    .list > :nth-child(4)::before { content: "some very long text that is not going to fit and will overflow"; }
+  </style>
+</head>
+<body>
+  <ol class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ol>
+  <ul class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003.html
new file mode 100644
index 0000000..94467ca
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-003.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>String value of list-style-type with RTL direction</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <link rel="help" href="https://drafts.csswg.org/css-lists-3/#valdef-list-style-type-string">
+  <link rel="match" href="list-style-type-string-003-ref.html">
+  <meta name="assert" content="This test checks that list-style-type can set the marker string when the direction is RTL.">
+  <style>
+    .list {
+      list-style-type: "";
+      direction: rtl;
+    }
+    .list > :nth-child(2) { list-style-type: "foo" }
+    .list > :nth-child(3) { list-style-type: "foobar"; }
+    .list > :nth-child(4) { list-style-type: "some very long text that is not going to fit and will overflow"; }
+  </style>
+</head>
+<body>
+  <ol class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ol>
+  <ul class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004-ref.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004-ref.html
new file mode 100644
index 0000000..3a828b2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>CSS Test: String value of list-style-type changing dynamically</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <style>
+    .list { list-style-type: "bar" }
+  </style>
+</head>
+<body>
+  <ol class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ol>
+  <ul class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004.html
new file mode 100644
index 0000000..922a4ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-004.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<head>
+  <meta charset="UTF-8">
+  <title>CSS Test: String value of list-style-type changing dynamically</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <link rel="help" href="https://drafts.csswg.org/css-lists-3/#valdef-list-style-type-string">
+  <link rel="match" href="list-style-type-string-004-ref.html">
+  <meta name="assert" content="This test checks that the marker text is updated when list-style-type changes.">
+  <style>
+    .list { list-style-type: "foo" }
+  </style>
+</head>
+<body>
+  <ol class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ol>
+  <ul class="list">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+  </ul>
+  <script src="/common/reftest-wait.js"></script>
+  <script>
+    "use strict";
+    addEventListener("load", function() {
+      requestAnimationFrame(() => {
+        for (const list of document.querySelectorAll(".list")) {
+          list.style.listStyleType = '"bar"';
+        }
+        takeScreenshot();
+      });
+    }, {once: true});
+  </script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005-ref.html
new file mode 100644
index 0000000..703ceff
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005-ref.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>CSS Reference: String value of list-style-type with bidi text</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <style>
+    .list {
+      width: 50%;
+      box-sizing: border-box;
+      float: left;
+      padding-inline-start: 14ch;
+      margin: 0;
+      line-height: 1.6;
+      list-style: none;
+    }
+    .rtl { direction: rtl }
+    .list > ::before {
+      unicode-bidi: isolate;
+      display: inline-flex;
+      flex-direction: row-reverse;
+      width: 0px;
+      white-space: pre;
+    }
+    .list > :nth-child(1)::before { content: "\627 \644 " }
+    .list > :nth-child(2)::before { content: "\61 \627 \644 " }
+    .list > :nth-child(3)::before { content: "\627 \644 \62 " }
+    .list > :nth-child(4)::before { content: "\61 \627 \644 \62 " }
+    .list > :nth-child(5)::before { content: "\61 \62 \627 \644 " }
+    .list > :nth-child(6)::before { content: "\627 \644 \61 \62 " }
+    .list > :nth-child(7)::before { content: "\31 \627 \644 " }
+    .list > :nth-child(8)::before { content: "\627 \644 \32 " }
+    .list > :nth-child(9)::before { content: "\31 \627 \644 \32 " }
+    .list > :nth-child(10)::before { content: "\31 \32 \627 \644 " }
+    .list > :nth-child(11)::before { content: "\627 \644 \31 \32 " }
+  </style>
+</head>
+<body>
+  <ol class="list ltr">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ol>
+  <ul class="list rtl">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005a.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005a.html
new file mode 100644
index 0000000..725cdee
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005a.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>String value of list-style-type with bidi text</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <link rel="help" href="https://drafts.csswg.org/css-lists-3/#valdef-list-style-type-string">
+  <link rel="match" href="list-style-type-string-005-ref.html">
+  <meta name="assert" content="This test checks that the bidi algorithm runs for markers.">
+  <style>
+    .list {
+      width: 50%;
+      box-sizing: border-box;
+      float: left;
+      padding-inline-start: 14ch;
+      margin: 0;
+      line-height: 1.6;
+    }
+    .rtl { direction: rtl }
+    .list > :nth-child(1) { list-style-type: "\627 \644 " }
+    .list > :nth-child(2) { list-style-type: "\61 \627 \644 " }
+    .list > :nth-child(3) { list-style-type: "\627 \644 \62 " }
+    .list > :nth-child(4) { list-style-type: "\61 \627 \644 \62 " }
+    .list > :nth-child(5) { list-style-type: "\61 \62 \627 \644 " }
+    .list > :nth-child(6) { list-style-type: "\627 \644 \61 \62 " }
+    .list > :nth-child(7) { list-style-type: "\31 \627 \644 " }
+    .list > :nth-child(8) { list-style-type: "\627 \644 \32 " }
+    .list > :nth-child(9) { list-style-type: "\31 \627 \644 \32 " }
+    .list > :nth-child(10) { list-style-type: "\31 \32 \627 \644 " }
+    .list > :nth-child(11) { list-style-type: "\627 \644 \31 \32 " }
+  </style>
+</head>
+<body>
+  <ol class="list ltr">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ol>
+  <ul class="list rtl">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005b.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005b.html
new file mode 100644
index 0000000..ca984b6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-005b.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>String value of list-style-type with bidi text in multicol</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <link rel="help" href="https://drafts.csswg.org/css-lists-3/#valdef-list-style-type-string">
+  <link rel="match" href="list-style-type-string-005-ref.html">
+  <meta name="assert" content="This test checks that the bidi algorithm runs for markers in multicol.">
+  <style>
+    body { column-count: 2 }
+    .list {
+      padding-inline-start: 14ch;
+      margin: 0;
+      line-height: 1.6;
+    }
+    .rtl { direction: rtl }
+    .list > :nth-child(1) { list-style-type: "\627 \644 " }
+    .list > :nth-child(2) { list-style-type: "\61 \627 \644 " }
+    .list > :nth-child(3) { list-style-type: "\627 \644 \62 " }
+    .list > :nth-child(4) { list-style-type: "\61 \627 \644 \62 " }
+    .list > :nth-child(5) { list-style-type: "\61 \62 \627 \644 " }
+    .list > :nth-child(6) { list-style-type: "\627 \644 \61 \62 " }
+    .list > :nth-child(7) { list-style-type: "\31 \627 \644 " }
+    .list > :nth-child(8) { list-style-type: "\627 \644 \32 " }
+    .list > :nth-child(9) { list-style-type: "\31 \627 \644 \32 " }
+    .list > :nth-child(10) { list-style-type: "\31 \32 \627 \644 " }
+    .list > :nth-child(11) { list-style-type: "\627 \644 \31 \32 " }
+  </style>
+</head>
+<body>
+  <ol class="list ltr">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ol>
+  <ul class="list rtl">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006-ref.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006-ref.html
new file mode 100644
index 0000000..5c0a5132
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006-ref.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>CSS Reference: String value of list-style-type with bidi text inside</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <style>
+    .list {
+      width: 50%;
+      box-sizing: border-box;
+      float: left;
+      padding-inline-start: 14ch;
+      margin: 0;
+      line-height: 1.6;
+      list-style: none;
+    }
+    .rtl { direction: rtl }
+    .list > ::before { unicode-bidi: isolate }
+    .list > :nth-child(1)::before { content: "\627 \644 " }
+    .list > :nth-child(2)::before { content: "\61 \627 \644 " }
+    .list > :nth-child(3)::before { content: "\627 \644 \62 " }
+    .list > :nth-child(4)::before { content: "\61 \627 \644 \62 " }
+    .list > :nth-child(5)::before { content: "\61 \62 \627 \644 " }
+    .list > :nth-child(6)::before { content: "\627 \644 \61 \62 " }
+    .list > :nth-child(7)::before { content: "\31 \627 \644 " }
+    .list > :nth-child(8)::before { content: "\627 \644 \32 " }
+    .list > :nth-child(9)::before { content: "\31 \627 \644 \32 " }
+    .list > :nth-child(10)::before { content: "\31 \32 \627 \644 " }
+    .list > :nth-child(11)::before { content: "\627 \644 \31 \32 " }
+  </style>
+</head>
+<body>
+  <ol class="list ltr">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ol>
+  <ul class="list rtl">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006.html b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006.html
new file mode 100644
index 0000000..7f6904b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/list-style-type-string-006.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>String value of list-style-type with bidi text inside</title>
+  <link rel="author" title="Oriol Brufau" href="mailto:obrufau@gmail.com">
+  <link rel="help" href="https://drafts.csswg.org/css-lists-3/#valdef-list-style-type-string">
+  <link rel="match" href="list-style-type-string-006-ref.html">
+  <meta name="assert" content="This test checks that the bidi algorithm runs for markers with unicode-bidi:isolate, so that the text inside the marker is isolated from the text outside. This is only relevant when the marker is positioned inside.">
+  <style>
+    .list {
+      list-style-position: inside;
+      width: 50%;
+      box-sizing: border-box;
+      float: left;
+      padding-inline-start: 14ch;
+      margin: 0;
+      line-height: 1.6;
+    }
+    .rtl { direction: rtl }
+    .list > :nth-child(1) { list-style-type: "\627 \644 " }
+    .list > :nth-child(2) { list-style-type: "\61 \627 \644 " }
+    .list > :nth-child(3) { list-style-type: "\627 \644 \62 " }
+    .list > :nth-child(4) { list-style-type: "\61 \627 \644 \62 " }
+    .list > :nth-child(5) { list-style-type: "\61 \62 \627 \644 " }
+    .list > :nth-child(6) { list-style-type: "\627 \644 \61 \62 " }
+    .list > :nth-child(7) { list-style-type: "\31 \627 \644 " }
+    .list > :nth-child(8) { list-style-type: "\627 \644 \32 " }
+    .list > :nth-child(9) { list-style-type: "\31 \627 \644 \32 " }
+    .list > :nth-child(10) { list-style-type: "\31 \32 \627 \644 " }
+    .list > :nth-child(11) { list-style-type: "\627 \644 \31 \32 " }
+  </style>
+</head>
+<body>
+  <ol class="list ltr">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ol>
+  <ul class="list rtl">
+    <li>item 1</li>
+    <li>item 2</li>
+    <li>item 3</li>
+    <li>item 4</li>
+    <li>item 5</li>
+    <li>item 6</li>
+    <li>item 7</li>
+    <li>item 8</li>
+    <li>item 9</li>
+    <li>item 10</li>
+    <li>item 11</li>
+  </ul>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-computed-expected.txt
index eabf33a..2ee6f4c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-computed-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-computed-expected.txt
@@ -14,8 +14,8 @@
 PASS Property list-style-type value 'georgian' computes to 'georgian'
 PASS Property list-style-type value 'lower-alpha' computes to 'lower-alpha'
 PASS Property list-style-type value 'upper-alpha' computes to 'upper-alpha'
-FAIL Property list-style-type value '"marker string"' computes to '"marker string"' assert_equals: expected "\"marker string\"" but got "disc"
-FAIL Property list-style-type value '"Note: "' computes to '"Note: "' assert_equals: expected "\"Note: \"" but got "disc"
+PASS Property list-style-type value '"marker string"' computes to '"marker string"'
+PASS Property list-style-type value '"Note: "' computes to '"Note: "'
 FAIL Property list-style-type value 'counter-Style-Name' computes to 'counter-Style-Name' assert_equals: expected "counter-Style-Name" but got "disc"
 FAIL Property list-style-type value 'CounterStyleName' computes to 'CounterStyleName' assert_equals: expected "CounterStyleName" but got "disc"
 FAIL Property list-style-type value 'symbols(cyclic "string")' computes to 'symbols(cyclic "string")' assert_equals: expected "symbols(cyclic \"string\")" but got "disc"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-valid-expected.txt
index b19f911..1687a52 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-valid-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-lists/parsing/list-style-type-valid-expected.txt
@@ -14,8 +14,8 @@
 PASS e.style['list-style-type'] = "georgian" should set the property value
 PASS e.style['list-style-type'] = "lower-alpha" should set the property value
 PASS e.style['list-style-type'] = "upper-alpha" should set the property value
-FAIL e.style['list-style-type'] = "\"marker string\"" should set the property value assert_not_equals: property should be set got disallowed value ""
-FAIL e.style['list-style-type'] = "\"Note: \"" should set the property value assert_not_equals: property should be set got disallowed value ""
+PASS e.style['list-style-type'] = "\"marker string\"" should set the property value
+PASS e.style['list-style-type'] = "\"Note: \"" should set the property value
 FAIL e.style['list-style-type'] = "counter-Style-Name" should set the property value assert_not_equals: property should be set got disallowed value ""
 FAIL e.style['list-style-type'] = "CounterStyleName" should set the property value assert_not_equals: property should be set got disallowed value ""
 FAIL e.style['list-style-type'] = "symbols(cyclic \"string\")" should set the property value assert_not_equals: property should be set got disallowed value ""
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/list-style-type-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/list-style-type-expected.txt
index af42e02..59617c5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/list-style-type-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/list-style-type-expected.txt
@@ -12,7 +12,7 @@
 PASS Setting 'list-style-type' to a position throws TypeError
 PASS Setting 'list-style-type' to a URL throws TypeError
 PASS Setting 'list-style-type' to a transform throws TypeError
-FAIL 'list-style-type' does not supported '"Note: "' assert_not_equals: Unsupported value must not be null got disallowed value null
+PASS 'list-style-type' does not supported '"Note: "'
 FAIL 'list-style-type' does not supported 'symbols("*" "A" "B" "C")' assert_not_equals: Unsupported value must not be null got disallowed value null
 Harness: the test ran to completion.