summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/selectors
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/css/selectors')
-rw-r--r--testing/web-platform/tests/css/selectors/META.yml6
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/cssom.html64
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html4
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml10
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html5
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml11
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/semantics.html269
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/syntax.html146
-rw-r--r--testing/web-platform/tests/css/selectors/attribute-selectors/style-attribute-selector.html130
-rw-r--r--testing/web-platform/tests/css/selectors/case-insensitive-parent-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/case-insensitive-parent.html17
-rw-r--r--testing/web-platform/tests/css/selectors/child-indexed-no-parent-ref.html18
-rw-r--r--testing/web-platform/tests/css/selectors/child-indexed-no-parent.html50
-rw-r--r--testing/web-platform/tests/css/selectors/child-indexed-pseudo-class.html55
-rw-r--r--testing/web-platform/tests/css/selectors/dir-pseudo-in-has.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-pseudo-on-bdi-element.html80
-rw-r--r--testing/web-platform/tests/css/selectors/dir-pseudo-on-input-element.html203
-rw-r--r--testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element-ref.html18
-rw-r--r--testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element.html28
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-auto-direction-change-001.html34
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-auto.html93
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-001-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-001.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-002.html28
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-003-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-003.html24
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-004-ref.html17
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-change-004.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-ltr-001.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-ltr-002.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-ltr-003.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-querySelector.html71
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-rtl-001.html25
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-white-space-001-ref.html18
-rw-r--r--testing/web-platform/tests/css/selectors/dir-selector-white-space-001.html27
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-01-ref.html33
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-01a.html38
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-01b.html55
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-02-ref.html31
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-02a.html35
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-02b.html46
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-03-ref.html18
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-03a.html20
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-03b.html34
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-04-ref.html24
-rw-r--r--testing/web-platform/tests/css/selectors/dir-style-04.html42
-rw-r--r--testing/web-platform/tests/css/selectors/eof-right-after-selector-crash.html5
-rw-r--r--testing/web-platform/tests/css/selectors/eof-some-after-selector-crash.html5
-rw-r--r--testing/web-platform/tests/css/selectors/first-child.html52
-rw-r--r--testing/web-platform/tests/css/selectors/first-letter-flag-001-ref.html12
-rw-r--r--testing/web-platform/tests/css/selectors/first-letter-flag-001.html16
-rw-r--r--testing/web-platform/tests/css/selectors/first-line-bidi-001-ref.html99
-rw-r--r--testing/web-platform/tests/css/selectors/first-line-bidi-001.html102
-rw-r--r--testing/web-platform/tests/css/selectors/first-line-bidi-002-ref.html99
-rw-r--r--testing/web-platform/tests/css/selectors/first-line-bidi-002.html103
-rw-r--r--testing/web-platform/tests/css/selectors/first-of-type.html90
-rw-r--r--testing/web-platform/tests/css/selectors/floating-first-letter-05d0.html20
-rw-r--r--testing/web-platform/tests/css/selectors/floating-first-letter-feff.html17
-rw-r--r--testing/web-platform/tests/css/selectors/floating-first-letter-ref.html14
-rw-r--r--testing/web-platform/tests/css/selectors/focus-display-none-001.html50
-rw-r--r--testing/web-platform/tests/css/selectors/focus-in-focus-event-001.html43
-rw-r--r--testing/web-platform/tests/css/selectors/focus-in-focusin-event-001.html41
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-001.html57
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-002.html103
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-003.html101
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-004.html100
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-005.html54
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-006.html62
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-007.html85
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-008.html66
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-009.html45
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-010.html49
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-011.html70
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-012.html69
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-013.html62
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-014.html43
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-015.html47
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-016.html56
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-017-2.html93
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-017.html44
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-018-2.html98
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-018.html49
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-019.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-020.html62
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-021.html67
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-022.tentative.html34
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-023.html33
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-024.html39
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-025.html47
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-026.html31
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-027.html28
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-001.html54
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-002.tentative.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-003.tentative.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-004.html62
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-005.html63
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-006.tentative.html65
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-007.tentative.html66
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-008-b.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-008.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-009.html65
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-010.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-011.html65
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-012.html63
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-013.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-014.html63
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-015.html64
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-016.tentative.html72
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-017.tentative.html74
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-018.html71
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-019.html72
-rw-r--r--testing/web-platform/tests/css/selectors/focus-visible-script-focus-020.html70
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-001-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-001.html37
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-002.html37
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-003.html43
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-004.html48
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-005.html49
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-006-ref.html32
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-006.html49
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-007-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-007.html33
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-008.html33
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-009.html158
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-010.html38
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-011-ref.html26
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-011.html38
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-012-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-012.html36
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-013-ref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-013.html33
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-display-none-001.html58
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-001-ref.html14
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-001.html39
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-002.html40
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-003.html42
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-004.html48
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-005.html57
-rw-r--r--testing/web-platform/tests/css/selectors/focus-within-shadow-006.html45
-rw-r--r--testing/web-platform/tests/css/selectors/has-argument-with-explicit-scope.html69
-rw-r--r--testing/web-platform/tests/css/selectors/has-basic.html81
-rw-r--r--testing/web-platform/tests/css/selectors/has-display-none-checked-ref.html3
-rw-r--r--testing/web-platform/tests/css/selectors/has-display-none-checked.html28
-rw-r--r--testing/web-platform/tests/css/selectors/has-matches-to-uninserted-elements.html37
-rw-r--r--testing/web-platform/tests/css/selectors/has-relative-argument.html184
-rw-r--r--testing/web-platform/tests/css/selectors/has-sibling-chrome-crash.html10
-rw-r--r--testing/web-platform/tests/css/selectors/has-specificity.html50
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-001-ref.html21
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-001.html26
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-002-ref.html21
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-002.html26
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-003-ref.html29
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-003.html30
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-004-ref.html29
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-004.html30
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-005-ref.html28
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-005.html29
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-006-ref.html28
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-006.html29
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-007-ref.html24
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-007.html27
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001.html20
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002.html20
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003.html21
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004.html21
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005.html20
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006.html20
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007.html20
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008.html20
-rw-r--r--testing/web-platform/tests/css/selectors/has-visited-ref.html27
-rw-r--r--testing/web-platform/tests/css/selectors/has-visited.html28
-rw-r--r--testing/web-platform/tests/css/selectors/hash-collision.html45
-rw-r--r--testing/web-platform/tests/css/selectors/historical-xmlid.xht22
-rw-r--r--testing/web-platform/tests/css/selectors/hover-001-manual.html48
-rw-r--r--testing/web-platform/tests/css/selectors/hover-002.html47
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/META.yml2
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/README2
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-001.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-002.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-004.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-005.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-006.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-007.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-008.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-009.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-010.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-011.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-012.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-014.html38
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-015.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-016.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-021.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-022.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-024.html40
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-025.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-026.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-027.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-028.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-029.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-030.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-031.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-032.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-034.html39
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-035.html40
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-036.html40
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-041.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-042.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-044.html32
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-045.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-046.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-047.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-048.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-049.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-050.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-051.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-052.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-054.html31
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-055.html32
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-056.html32
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries-ref.html7
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries.html28
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-disconnected.html24
-rw-r--r--testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-empty-attribute.xhtml26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal-ref.html10
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal.html14
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/any-link-pseudo.html36
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html149
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/attribute.html234
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/child-indexed-pseudo-classes-in-has.html116
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/class-id-attr-ref.html9
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/class-id-attr.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/crashtests/nth-child-of-attribute-crash.html22
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/defined-in-has.html37
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/defined.html76
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/dir-pseudo-class-in-has.html36
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/empty-pseudo-in-has.html45
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/enabled-disabled.html51
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/first-child-last-child.html57
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/fullscreen-pseudo-class-in-has.html53
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-append-first-node.html40
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-complexity.html80
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-css-nesting-shared.html105
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-in-adjacent-position.html312
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-in-ancestor-position.html320
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-in-parent-position.html300
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-in-sibling-position.html312
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-invalidation-after-removing-non-first-element.html31
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-invalidation-for-wiping-an-element.html42
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-pseudo-element.html30
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-sibling-insertion-removal.html209
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-sibling.html149
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-side-effect.html43
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-unstyled.html77
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-with-nesting-parent-containing-hover.html55
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-with-not.html107
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-with-nth-child.html67
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/has-with-pseudo-class.html99
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/host-context-pseudo-class-in-has.html56
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/host-pseudo-class-in-has.html51
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/input-pseudo-classes-in-has.html170
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/insert-sibling-001.html39
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/insert-sibling-002.html41
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/insert-sibling-003.html44
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/insert-sibling-004.html43
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-complex-in-has.html379
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-sibling-relationship-in-has.html311
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/is.html139
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-document-element.html27
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-multiple-document-elements.html32
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-xhtml.xhtml43
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has.html38
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/link-pseudo-class-in-has.html48
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/link-pseudo-in-has.html97
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/location-pseudo-classes-in-has.html29
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html79
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/media-pseudo-classes-in-has.html114
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/modal-pseudo-class-in-has.html81
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes-ref.html10
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes-ref.html10
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/not-001.html41
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/not-002.html133
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-complex-in-has.html375
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-sibling-relationship-in-has.html49
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor-ref.html12
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor.html23
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root-ref.html7
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root.html29
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html452
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom.html462
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-ref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-prefix.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-ref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has-ref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-id-prefix.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-ids.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-is.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html9
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root.html21
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-is.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class.html31
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling-ref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html14
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-containing-ancestor.html23
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root-ref.html7
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root.html29
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-prefix.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-id-prefix.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-ids.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-is.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root-ref.html8
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root.html23
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-is.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class.html31
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes-ref.html12
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes.html25
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/part-dir.html63
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/part-lang.html73
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/part-pseudo-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/part-pseudo.html22
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/placeholder-shown.html34
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/quirks-mode-stylesheet-dynamic-add-001.html27
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/selectorText-dynamic-001.html24
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-001.html26
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002-ref.html7
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002.html23
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/sibling.html139
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/state-in-has.html58
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/subject-has-invalidation-with-display-none-anchor-element.html29
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/target-pseudo-in-has.html103
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/typed-child-indexed-pseudo-classes-in-has.html131
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/user-action-pseudo-classes-in-has.html136
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/user-valid-user-invalid.html57
-rw-r--r--testing/web-platform/tests/css/selectors/invalidation/where.html108
-rw-r--r--testing/web-platform/tests/css/selectors/is-default-ns-001.html23
-rw-r--r--testing/web-platform/tests/css/selectors/is-default-ns-002.html21
-rw-r--r--testing/web-platform/tests/css/selectors/is-default-ns-003.html29
-rw-r--r--testing/web-platform/tests/css/selectors/is-nested.html72
-rw-r--r--testing/web-platform/tests/css/selectors/is-specificity-shadow.html18
-rw-r--r--testing/web-platform/tests/css/selectors/is-specificity.html41
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-basic.html41
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-error-recovery.html49
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-not.html45
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-pseudo-classes.html37
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-pseudo-elements-ref.html32
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-pseudo-elements.html33
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-shadow.html62
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-visited-ref.html66
-rw-r--r--testing/web-platform/tests/css/selectors/is-where-visited.html67
-rw-r--r--testing/web-platform/tests/css/selectors/last-child.html52
-rw-r--r--testing/web-platform/tests/css/selectors/last-of-type.html89
-rw-r--r--testing/web-platform/tests/css/selectors/media/media-loading-state.html62
-rw-r--r--testing/web-platform/tests/css/selectors/media/media-playback-state.html73
-rw-r--r--testing/web-platform/tests/css/selectors/media/sound-state.html45
-rw-r--r--testing/web-platform/tests/css/selectors/missing-right-token.html31
-rw-r--r--testing/web-platform/tests/css/selectors/modal-pseudo-class.html59
-rw-r--r--testing/web-platform/tests/css/selectors/not-complex.html46
-rw-r--r--testing/web-platform/tests/css/selectors/not-default-ns-001.html27
-rw-r--r--testing/web-platform/tests/css/selectors/not-default-ns-002.html25
-rw-r--r--testing/web-platform/tests/css/selectors/not-default-ns-003.html29
-rw-r--r--testing/web-platform/tests/css/selectors/not-links-ref.html17
-rw-r--r--testing/web-platform/tests/css/selectors/not-links.html25
-rw-r--r--testing/web-platform/tests/css/selectors/not-specificity.html50
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child-ref.html56
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child.html75
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-attribute.html42
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-classname-002.html41
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-classname-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-classname.html26
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2-ref.html46
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2.html52
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-ref.html46
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children.html57
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-ref.html14
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-complex-selector.html25
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-compound-selector-ref.html18
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-compound-selector.html29
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-has.html42
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-nesting-ref.html17
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-nesting.html28
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of-ref.html31
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of.html56
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-not.html42
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-nth-child.html41
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-pseudo-ref.html9
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-pseudo.html19
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-tagname-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-tagname.html26
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-of-universal-selector.html41
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-1-ref.html17
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-1.html40
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-2-ref.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-2.html47
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-3-ref.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-3.html51
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-4-ref.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-child-specificity-4.html51
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-classname-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-classname.html26
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector-ref.html14
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector.html24
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector-ref.html19
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector.html29
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-nesting.html28
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-no-space-after-of.html56
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2-ref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2.html25
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-tagname-ref.html16
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-of-tagname.html26
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-1-ref.html17
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-1.html40
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-2-ref.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-2.html47
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-3-ref.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-3.html51
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-4-ref.html23
-rw-r--r--testing/web-platform/tests/css/selectors/nth-last-child-specificity-4.html51
-rw-r--r--testing/web-platform/tests/css/selectors/nth-of-invalid.html55
-rw-r--r--testing/web-platform/tests/css/selectors/nth-of-type-namespace.html48
-rw-r--r--testing/web-platform/tests/css/selectors/of-type-selectors-ref.xhtml37
-rw-r--r--testing/web-platform/tests/css/selectors/of-type-selectors.xhtml42
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-1.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-10.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-11.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111b.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-118.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-119.xml31
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-120.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-121.xml28
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-122.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-13.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132b.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133b.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134b.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135b.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136b.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14.xml28
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140b.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141b.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142b.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143b.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-144.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145a.xml33
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145b.xml33
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146a.xml39
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146b.xml39
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147a.xml39
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147b.xml39
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-148.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149b.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14c.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14d.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14e.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-150.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-151.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-152.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-153.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-154.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155a.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155d.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156b.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-157.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-158.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-159.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-16.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-160.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-161.xml47
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166a.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167a.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168a.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169a.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-17.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170a.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170b.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170d.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-171.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172a.xml30
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172b.xml31
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173a.xml30
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173b.xml30
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174a.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174b.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175a.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175b.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-176.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177a.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177b.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-178.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179a.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18.xml61
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-180a.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-181.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-182.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-183.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184-ref.xht13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184a.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184b.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184c.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184d.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184e.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184f.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18a.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18b.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19b.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-2.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-20.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21b.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21c.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-22.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-25.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27a.xml27
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27b.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28.xml98
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28b.xml99
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29.xml99
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29b.xml99
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-30.xml32
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-31.xml32
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-32.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-33.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-34.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-35.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-36.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-37.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-38.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39a.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39b.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39c.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3a.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-4.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41a.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42a.xml13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43b.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44.xml29
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44b.xml29
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44d.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45c.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46b.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-47.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-48.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-49.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-5.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-50.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-51.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-52.xml28
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-53.xml28
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-54.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-55.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-56.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57b.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-59.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-6.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-60.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-61.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-62.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-63.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-64.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-65.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66.xml25
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66b.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-67.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-70.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72b.xml17
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73.xml99
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73b.xml100
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74.xml100
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74b.xml101
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75.xml33
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75b.xml33
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76.xml33
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76b.xml33
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77b.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78b.xml36
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-79.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7b.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-8.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-80.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81b.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82b.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83-ref.xml10
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-86.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87b.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88b.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-89.xml19
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-9.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90b.xml18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-91.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-92.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-93.xml15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-95.xml22
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96b.xml26
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97b.xml20
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98b.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99.xml24
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99b.xml23
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1b.xml39
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d2.xml42
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d3.xml44
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d4.xml35
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/bq-u-u-u-green.xht15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-g-u.xht15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u-u.xht15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u.xht14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-u-g-g.xht15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-g-u-u-g.xht16
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-u-g-g.xht15
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/seven-green-divs.xht18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/this-address-p-p-p-lime-background.xht18
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-background.xht13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-color.xht12
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background-offset.xht14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background.xht12
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/this-test-has-passed-desc.xht13
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/three-p-lime-background-except-middle.xht14
-rw-r--r--testing/web-platform/tests/css/selectors/old-tests/reference/three-paragraph-lime-characters.xht13
-rw-r--r--testing/web-platform/tests/css/selectors/only-child.html61
-rw-r--r--testing/web-platform/tests/css/selectors/only-of-type.html64
-rw-r--r--testing/web-platform/tests/css/selectors/open-closed-pseudo.html69
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/invalid-pseudos.html25
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-anplusb.html76
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-attribute.html30
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-child.html11
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-class.html15
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-descendant.html13
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-focus-visible.html13
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html19
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-has-forgiving-selector.html15
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-has.html40
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-id.html13
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-is-where.html50
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-is.html18
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-not.html37
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-part.html39
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-sibling.html12
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-slotted.html27
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-state.html35
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-universal.html14
-rw-r--r--testing/web-platform/tests/css/selectors/parsing/parse-where.html18
-rw-r--r--testing/web-platform/tests/css/selectors/placeholder-shown.html41
-rw-r--r--testing/web-platform/tests/css/selectors/pseudo-enabled-disabled.html51
-rw-r--r--testing/web-platform/tests/css/selectors/query/query-is.html57
-rw-r--r--testing/web-platform/tests/css/selectors/query/query-where.html57
-rw-r--r--testing/web-platform/tests/css/selectors/remove-hovered-element-ref.html4
-rw-r--r--testing/web-platform/tests/css/selectors/remove-hovered-element.html40
-rw-r--r--testing/web-platform/tests/css/selectors/resources/blue15x15.pngbin0 -> 185 bytes
-rw-r--r--testing/web-platform/tests/css/selectors/root-siblings.html19
-rw-r--r--testing/web-platform/tests/css/selectors/scope-selector.html37
-rw-r--r--testing/web-platform/tests/css/selectors/scope-without-scoping.html23
-rw-r--r--testing/web-platform/tests/css/selectors/selection-image-001-no-selection-noref.html7
-rw-r--r--testing/web-platform/tests/css/selectors/selection-image-001-noref.html15
-rw-r--r--testing/web-platform/tests/css/selectors/selection-image-001.html24
-rw-r--r--testing/web-platform/tests/css/selectors/selection-image-002.html16
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-emptify-placeholder.html22
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001.html25
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002.html25
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003.html25
-rw-r--r--testing/web-platform/tests/css/selectors/selector-read-write-type-change-001-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-read-write-type-change-001.html20
-rw-r--r--testing/web-platform/tests/css/selectors/selector-read-write-type-change-002-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-read-write-type-change-002.html25
-rw-r--r--testing/web-platform/tests/css/selectors/selector-required-ref.html22
-rw-r--r--testing/web-platform/tests/css/selectors/selector-required-type-change-001-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-required-type-change-001.html20
-rw-r--r--testing/web-platform/tests/css/selectors/selector-required-type-change-002-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selector-required-type-change-002.html25
-rw-r--r--testing/web-platform/tests/css/selectors/selector-required.html26
-rw-r--r--testing/web-platform/tests/css/selectors/selector-structural-pseudo-root-ref.html7
-rw-r--r--testing/web-platform/tests/css/selectors/selector-structural-pseudo-root.html8
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-000-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-000.html13
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-001.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-002.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-003.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-004.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-005.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-006.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-007.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-008.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-009.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-010.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-011.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-012.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-013.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-014.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-015.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-016.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-017.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-018.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-019.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-020.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-021.html15
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-022.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-023.html15
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-024.html14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-4/lang-025.html16
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-attr-many-ref.html5
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-attr-many.html60
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-attr-white-space-001-ref.html11
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-attr-white-space-001.html19
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-case-sensitive-001.html40
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-empty-001-ref.xml40
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-empty-001.xml47
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-namespace-001-ref.xml14
-rw-r--r--testing/web-platform/tests/css/selectors/selectors-namespace-001.xml21
-rw-r--r--testing/web-platform/tests/css/selectors/sharing-in-svg-use-ref.html13
-rw-r--r--testing/web-platform/tests/css/selectors/sharing-in-svg-use.html25
-rw-r--r--testing/web-platform/tests/css/selectors/spurious-brace-crash.html5
-rw-r--r--testing/web-platform/tests/css/selectors/user-invalid.html196
-rw-r--r--testing/web-platform/tests/css/selectors/user-valid.html154
-rw-r--r--testing/web-platform/tests/css/selectors/valid-invalid-form-fieldset.html75
-rw-r--r--testing/web-platform/tests/css/selectors/visited-inheritance-ref.html14
-rw-r--r--testing/web-platform/tests/css/selectors/visited-inheritance.html19
-rw-r--r--testing/web-platform/tests/css/selectors/visited-part-crash.html8
-rw-r--r--testing/web-platform/tests/css/selectors/webkit-pseudo-element.html48
-rw-r--r--testing/web-platform/tests/css/selectors/x-pseudo-element.html22
-rw-r--r--testing/web-platform/tests/css/selectors/xml-class-selector-ref.xml16
-rw-r--r--testing/web-platform/tests/css/selectors/xml-class-selector.xml21
869 files changed, 32196 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/selectors/META.yml b/testing/web-platform/tests/css/selectors/META.yml
new file mode 100644
index 0000000000..8e506d671d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/META.yml
@@ -0,0 +1,6 @@
+spec: https://drafts.csswg.org/selectors/
+suggested_reviewers:
+ - fantasai
+ - frivoal
+ - plinss
+ - tabatkins
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/cssom.html b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/cssom.html
new file mode 100644
index 0000000000..74e7b9645f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/cssom.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<title>Selectors: CSSOM of case-sensitivity attribute selector</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#attribute-case">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function new_sheet(use_media) {
+ var style = document.getElementsByTagName('style')[0];
+ if (style)
+ style.parentNode.removeChild(style);
+ style = document.createElement('style');
+ document.head.appendChild(style);
+ if (use_media) {
+ style.textContent = '@media all {}';
+ return style.sheet.cssRules[0];
+ }
+ return style.sheet;
+}
+
+var tests = [
+ // test input, expected serialization
+ ['[foo="bar"] /* sanity check */', '[foo="bar"]'],
+ ['[foo="bar" i]', '[foo="bar" i]'],
+ ['[foo="bar" /**/ i]', '[foo="bar" i]'],
+ ['[foo="bar"/**/i]', '[foo="bar" i]'],
+ ['[*|foo="bar" i]', '[*|foo="bar" i]'],
+ ['[foo="bar" s]', '[foo="bar" s]'],
+ ['[foo="bar" /**/ s]', '[foo="bar" s]'],
+ ['[foo="bar"/**/s]', '[foo="bar" s]'],
+ ['[*|foo="bar" s]', '[*|foo="bar" s]'],
+]
+
+tests.forEach(function(arr) {
+ var input = arr[0];
+ var expected = arr[1];
+ ["", " in @media"].forEach(function(use_media) {
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule(input + ' {}', 0);
+ assert_equals(sheet.cssRules.length, 1);
+ }, input + ' insertRule' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule(input + ' {}', 0);
+ assert_equals(sheet.cssRules[0].cssText.substr(0, expected.length), expected);
+ }, input + ' getting CSSRule#cssText' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule(input + ' {}', 0);
+ assert_equals(sheet.cssRules[0].selectorText, expected);
+ }, input + ' getting CSSStyleRule#selectorText' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule('foobar {}', 0);
+ sheet.cssRules[0].selectorText = input;
+ assert_equals(sheet.cssRules[0].selectorText, expected);
+ }, input + ' setting CSSStyleRule#selectorText' + use_media);
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html
new file mode 100644
index 0000000000..b6c3dfe4ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html
@@ -0,0 +1,4 @@
+<style></style>
+<script>
+var mode = "quirks mode";
+</script>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml
new file mode 100644
index 0000000000..f4d40fb852
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style></style>
+</head>
+<body>
+<script>
+var mode = "XML";
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html
new file mode 100644
index 0000000000..a7ec7e2e04
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html
@@ -0,0 +1,5 @@
+<style></style>
+<div id=test foo="BAR" baz="quux"></div>
+<script>
+var mode = "quirks mode";
+</script>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml
new file mode 100644
index 0000000000..b90c277746
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style></style>
+</head>
+<body>
+<div id="test" foo="BAR" baz="quux"/>
+<script>
+var mode = "XML";
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/semantics.html b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/semantics.html
new file mode 100644
index 0000000000..262e601b5d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/semantics.html
@@ -0,0 +1,269 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Selectors: semantics of case-sensitivity attribute selector</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#attribute-case">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style></style>
+<div id=log></div>
+<iframe id="quirks" src="resources/semantics-quirks.html"></iframe>
+<iframe id="xml" src="resources/semantics-xml.xhtml"></iframe>
+<script>
+setup({explicit_done:true});
+var match = [
+ // [selector, attrs...] (each attr is [ns, name, value])
+ ["[foo='BAR'] /* sanity check (match) */", ["", "foo", "BAR"]],
+ ["[foo='bar'] /* sanity check (match) */", ["", "foo", "bar"]],
+ ["[align='left'] /* sanity check (match) */", ["", "align", "left"]],
+ ["[class~='a'] /* sanity check (match) */", ["", "class", "X a b"]],
+ ["[class~='A'] /* sanity check (match) */", ["", "class", "x A B"]],
+ ["[id^='a'] /* sanity check (match) */", ["", "id", "ab"]],
+ ["[id$='A'] /* sanity check (match) */", ["", "id", "XA"]],
+ ["[lang|='a'] /* sanity check (match) */", ["", "lang", "a-b"]],
+ ["[lang*='A'] /* sanity check (match) */", ["", "lang", "XAB"]],
+ ["@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A'] /* sanity check (match) */",
+ ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ // Case-insensitive matching.
+ ["[foo='bar' i]", ["", "foo", "BAR"]],
+ ["[foo='' i]", ["", "foo", ""]],
+ ["[foo='a\u0308' i] /* COMBINING in both */", ["", "foo", "A\u0308"]],
+ ["[foo='A\u0308' i] /* COMBINING in both */", ["", "foo", "a\u0308"]],
+ ["[*|foo='bar' i]", ["", "foo", "x"], ["a", "foo", "x"], ["b", "foo", "BAR"], ["c", "foo", "x"]],
+ ["[*|foo='bar' i]", ["", "foo", "BAR"], ["a", "foo", "x"], ["b", "foo", "x"], ["c", "foo", "x"]],
+ ["[align='left' i]", ["", "align", "LEFT"]],
+ ["[align='LEFT' i]", ["", "align", "left"]],
+ ["[class~='a' i]", ["", "class", "X A B"]],
+ ["[class~='A' i]", ["", "class", "x a b"]],
+ ["[id^='a' i]", ["", "id", "AB"]],
+ ["[id$='A' i]", ["", "id", "xa"]],
+ ["[lang|='a' i]", ["", "lang", "A-B"]],
+ ["[lang*='A' i]", ["", "lang", "xab"]],
+ ["[*|lang='a' i]", ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ ["[*|lang='A' i]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' i]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["[foo='bar' i][foo='bar' i]", ["", "foo", "BAR"]],
+ ["[foo='BAR'][foo='bar' i]", ["", "foo", "BAR"]],
+ ["[foo='bar' i][foo='BAR']", ["", "foo", "BAR"]],
+ // Case-sensitive matching.
+ ["[foo='bar' s]", ["", "foo", "bar"]],
+ ["[foo='' s]", ["", "foo", ""]],
+ ["[foo='a\u0308' s] /* COMBINING in both */", ["", "foo", "a\u0308"]],
+ ["[*|foo='bar' s]", ["", "foo", "x"], ["a", "foo", "x"], ["b", "foo", "bar"], ["c", "foo", "x"]],
+ ["[*|foo='bar' s]", ["", "foo", "bar"], ["a", "foo", "x"], ["b", "foo", "x"], ["c", "foo", "x"]],
+ ["[align='left' s]", ["", "align", "left"]],
+ ["[align='LEFT' s]", ["", "align", "LEFT"]],
+ ["[class~='a' s]", ["", "class", "x a b"]],
+ ["[class~='A' s]", ["", "class", "X A B"]],
+ ["[id^='a' s]", ["", "id", "ab"]],
+ ["[id$='A' s]", ["", "id", "XA"]],
+ ["[lang|='a' s]", ["", "lang", "a-b"]],
+ ["[lang*='A' s]", ["", "lang", "XAB"]],
+ ["[*|lang='a' s]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["[*|lang='A' s]", ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ ["@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' s]", ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ ["[foo='BAR' s][foo='BAR' s]", ["", "foo", "BAR"]],
+];
+
+var matchHTMLOnly = [
+ ["[align='left'] /* sanity check (match HTML) */", ["", "align", "LEFT"]],
+ ["[align='LEFT'] /* sanity check (match HTML) */", ["", "align", "left"]],
+ ["[lang|='a'] /* sanity check (match HTML) */", ["", "lang", "A-B"]],
+ ["[lang*='A'] /* sanity check (match HTML) */", ["", "lang", "xab"]],
+];
+
+var nomatch = [
+ ["[missingattr] /* sanity check (no match) */", ["", "foo", "BAR"]],
+ ["[foo='bar'] /* sanity check (no match) */", ["", "foo", "BAR"]],
+ ["[class~='a'] /* sanity check (no match) */", ["", "class", "X A B"]],
+ ["[class~='A'] /* sanity check (no match) */", ["", "class", "x a b"]],
+ ["[id^='a'] /* sanity check (no match) */", ["", "id", "AB"]],
+ ["[id$='A']", ["", "id", "xa"]],
+ ["[*|lang='a'] /* sanity check (no match) */",
+ ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ ["[*|lang='A'] /* sanity check (no match) */",
+ ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A'] /* sanity check (no match) */",
+ ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ // Case-insensitive matching.
+ ["[foo='' i]", ["", "foo", "BAR"]],
+ ["[foo='\u0000' i] /* \\0 in selector */", ["", "foo", ""]],
+ ["[foo='' i] /* \\0 in attribute */", ["", "foo", "\u0000"]],
+ ["[foo='\u00E4' i]", ["", "foo", "\u00C4"]],
+ ["[foo='\u00C4' i]", ["", "foo", "\u00E4"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00C4"]],
+ ["[foo~='a\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00E4"]],
+ ["[foo^='A\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00C4"]],
+ ["[foo$='A\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00E4"]],
+ ["[foo*='\u00E4' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo|='\u00E4' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='\u00C4' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='\u00C4' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "a"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "A"]],
+ ["[foo='A\u0308' i] /* COMBINING in selector */", ["", "foo", "a"]],
+ ["[foo='A\u0308' i] /* COMBINING in selector */", ["", "foo", "A"]],
+ ["[foo='a' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='A' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='a' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='A' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='i' i]", ["", "foo", "\u0130"]],
+ ["[foo='i' i]", ["", "foo", "\u0131"]],
+ ["[foo='I' i]", ["", "foo", "\u0130"]],
+ ["[foo='I' i]", ["", "foo", "\u0131"]],
+ ["[foo='\u0130' i]", ["", "foo", "i"]],
+ ["[foo='\u0131' i]", ["", "foo", "i"]],
+ ["[foo='\u0130' i]", ["", "foo", "I"]],
+ ["[foo='\u0131' i]", ["", "foo", "I"]],
+ ["[foo='bar' i]", ["", "foo", "x"], ["a", "foo", "BAR"]],
+ ["[|foo='bar' i]", ["", "foo", "x"], ["a", "foo", "BAR"]],
+ ["[foo='bar' i]", ["", "FOO", "bar"]],
+ ["[foo='\t' i] /* tab in selector */", ["", "foo", " "]],
+ ["[foo=' ' i] /* tab in attribute */", ["", "foo", "\t"]],
+ ["@namespace x 'a'; [x|foo='' i]", ["A", "foo", ""]],
+ ["@namespace x 'A'; [x|foo='' i]", ["a", "foo", ""]],
+ ["[foo='bar' i][foo='bar']", ["", "foo", "BAR"]],
+ ["[foo='bar' i]", ["", "baz", "BAR"]],
+ ["[foo^='é' i]", ["", "foo", "É"]],
+ ["[foo$='é' i]", ["", "foo", "É"]],
+ ["[foo*='é' i]", ["", "foo", "É"]],
+ ["[foo|='é' i]", ["", "foo", "É"]],
+ ["[foo^='É' i]", ["", "foo", "é"]],
+ ["[foo$='É' i]", ["", "foo", "é"]],
+ ["[foo*='É' i]", ["", "foo", "é"]],
+ ["[foo|='É' i]", ["", "foo", "é"]],
+ // Case-sensitive matching
+ ["[foo='' s]", ["", "foo", "BAR"]],
+ ["[foo='\u0000' s] /* \\0 in selector */", ["", "foo", ""]],
+ ["[foo='' s] /* \\0 in attribute */", ["", "foo", "\u0000"]],
+ ["[foo='\u00E4' s]", ["", "foo", "\u00C4"]],
+ ["[foo='\u00C4' s]", ["", "foo", "\u00E4"]],
+ ["[foo='a\u0308' s] /* COMBINING in selector */", ["", "foo", "\u00C4"]],
+ ["[foo~='a\u0308' s] /* COMBINING in selector */", ["", "foo", "\u00E4"]],
+ ["[foo^='A\u0308' s] /* COMBINING in selector */", ["", "foo", "\u00C4"]],
+ ["[foo$='A\u0308' s] /* COMBINING in selector */", ["", "foo", "\u00E4"]],
+ ["[foo*='\u00E4' s] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo|='\u00E4' s] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='\u00C4' s] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='\u00C4' s] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='a\u0308' s] /* COMBINING in selector */", ["", "foo", "a"]],
+ ["[foo='a\u0308' s] /* COMBINING in selector */", ["", "foo", "A"]],
+ ["[foo='A\u0308' s] /* COMBINING in selector */", ["", "foo", "a"]],
+ ["[foo='A\u0308' s] /* COMBINING in selector */", ["", "foo", "A"]],
+ ["[foo='a' s] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='A' s] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='a' s] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='A' s] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='i' s]", ["", "foo", "\u0130"]],
+ ["[foo='i' s]", ["", "foo", "\u0131"]],
+ ["[foo='I' s]", ["", "foo", "\u0130"]],
+ ["[foo='I' s]", ["", "foo", "\u0131"]],
+ ["[foo='\u0130' s]", ["", "foo", "i"]],
+ ["[foo='\u0131' s]", ["", "foo", "i"]],
+ ["[foo='\u0130' s]", ["", "foo", "I"]],
+ ["[foo='\u0131' s]", ["", "foo", "I"]],
+ ["[foo='bar' s]", ["", "foo", "x"], ["a", "foo", "BAR"]],
+ ["[|foo='bar' s]", ["", "foo", "x"], ["a", "foo", "BAR"]],
+ ["[foo='bar' s]", ["", "FOO", "bar"]],
+ ["[foo='\t' s] /* tab in selector */", ["", "foo", " "]],
+ ["[foo=' ' s] /* tab in attribute */", ["", "foo", "\t"]],
+ ["@namespace x 'a'; [x|foo='' s]", ["A", "foo", ""]],
+ ["@namespace x 'A'; [x|foo='' s]", ["a", "foo", ""]],
+ ["[foo='bar' s][foo='bar']", ["", "foo", "BAR"]],
+ ["[foo='bar' s]", ["", "baz", "BAR"]],
+ ["[foo='bar' s]", ["", "foo", "BAR"]],
+ ["[foo='a\u0308' s] /* COMBINING in both */", ["", "foo", "A\u0308"]],
+ ["[foo='A\u0308' s] /* COMBINING in both */", ["", "foo", "a\u0308"]],
+ ["[*|foo='bar' s]", ["", "foo", "x"], ["a", "foo", "x"], ["b", "foo", "BAR"], ["c", "foo", "x"]],
+ ["[*|foo='bar' s]", ["", "foo", "BAR"], ["a", "foo", "x"], ["b", "foo", "x"], ["c", "foo", "x"]],
+ ["[align='left' s]", ["", "align", "LEFT"]],
+ ["[align='LEFT' s]", ["", "align", "left"]],
+ ["[class~='a' s]", ["", "class", "X A B"]],
+ ["[class~='A' s]", ["", "class", "x a b"]],
+ ["[id^='a' s]", ["", "id", "AB"]],
+ ["[id$='A' s]", ["", "id", "xa"]],
+ ["[lang|='a' s]", ["", "lang", "A-B"]],
+ ["[lang*='A' s]", ["", "lang", "xab"]],
+ ["[*|lang='a' s]", ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ ["[*|lang='A' s]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' s]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["[foo='bar' s][foo='bar' s]", ["", "foo", "BAR"]],
+ ["[foo='BAR' s][foo='bar']", ["", "foo", "BAR"]],
+ ["[foo='bar'][foo='BAR' s]", ["", "foo", "BAR"]],
+ ["[foo='BAR'][foo='bar' s]", ["", "foo", "BAR"]],
+ ["[foo='bar' s][foo='BAR']", ["", "foo", "bar"]],
+];
+var mode = "standards mode";
+function format_attrs(attrs) {
+ var rv = [];
+ attrs.forEach(function(attr) {
+ var str = "";
+ var ns = attr[0];
+ var name = attr[1];
+ var value = attr[2];
+ if (ns)
+ str += "{" + ns + "}";
+ str += name + "=\"" + value + "\"";
+ rv.push(str);
+ });
+ return rv.join(" ");
+}
+onload = function() {
+ var quirks = document.getElementById('quirks').contentWindow;
+ var xml = document.getElementById('xml').contentWindow;
+ [window, quirks, xml].forEach(function(global) {
+ var style = global.document.getElementsByTagName('style')[0];
+ var elm;
+ function clean_slate() {
+ style.textContent = '';
+ if (elm)
+ elm.parentNode.removeChild(elm);
+ elm = global.document.createElement('div');
+ global.document.body.appendChild(elm);
+ }
+ function set_attrs(attrs) {
+ attrs.forEach(function(attr) {
+ elm.setAttributeNS(attr[0], attr[1], attr[2]);
+ });
+ }
+ var localMatch = match.slice();
+ if (global != xml) {
+ localMatch.push(...matchHTMLOnly);
+ }
+ localMatch.forEach(function(arr) {
+ var s = arr[0];
+ var attrs = arr.slice(1);
+ var ns_decl = s.substr(0, "@namespace".length) == "@namespace";
+ test(function() {
+ clean_slate();
+ set_attrs(attrs);
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, (ns_decl ? 2 : 1), 'rule didn\'t parse into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'hidden', 'selector didn\'t match');
+ }, s + ' <div ' + format_attrs(attrs) + '> in ' + global.mode);
+ if (!ns_decl) {
+ test(function() {
+ assert_equals(global.document.querySelector(s), elm, 'selector didn\'t match');
+ }, s + ' <div ' + format_attrs(attrs) + '> with querySelector in ' + global.mode);
+ }
+ });
+ nomatch.forEach(function(arr) {
+ var s = arr[0];
+ var attrs = arr.slice(1);
+ var ns_decl = s.substr(0, "@namespace".length) == "@namespace";
+ test(function() {
+ clean_slate();
+ set_attrs(attrs);
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, (ns_decl ? 2 : 1), 'rule didn\'t parse into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'selector matched');
+ }, s + ' <div ' + format_attrs(attrs) + '> in ' + global.mode);
+ if (!ns_decl) {
+ test(function() {
+ assert_equals(global.document.querySelector(s), null, 'selector matched');
+ }, s + ' <div ' + format_attrs(attrs) + '> with querySelector in ' + global.mode);
+ }
+ });
+ });
+ done();
+};
+</script>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/syntax.html b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/syntax.html
new file mode 100644
index 0000000000..e62c13a034
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/attribute-case/syntax.html
@@ -0,0 +1,146 @@
+<!doctype html>
+<title>Selectors: syntax of case-sensitivity attribute selector</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#attribute-case">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style></style>
+<div id=log></div>
+<div id=test foo="BAR" baz="quux"></div>
+<iframe id="quirks" src="resources/syntax-quirks.html"></iframe>
+<iframe id="xml" src="resources/syntax-xml.xhtml"></iframe>
+<script>
+setup({explicit_done:true});
+var valid = [
+ "[foo='BAR'] /* sanity check (valid) */",
+ "[baz='quux'] /* sanity check (valid) */",
+ // Case-insensitive selectors.
+ "[foo='bar' i]",
+ "[foo='bar' I]",
+ "[foo=bar i]",
+ '[foo="bar" i]',
+ "[foo='bar'i]",
+ "[foo='bar'i ]",
+ "[foo='bar' i ]",
+ "[foo='bar' /**/ i]",
+ "[foo='bar' i /**/ ]",
+ "[foo='bar'/**/i/**/]",
+ "[foo=bar/**/i]",
+ "[foo='bar'\ti\t] /* \\t */",
+ "[foo='bar'\ni\n] /* \\n */",
+ "[foo='bar'\ri\r] /* \\r */",
+ "[foo='bar' \\i]",
+ "[foo='bar' \\69]",
+ "[foo='bar' \\49]",
+ "[foo~='bar' i]",
+ "[foo^='bar' i]",
+ "[foo$='bar' i]",
+ "[foo*='bar' i]",
+ "[foo|='bar' i]",
+ "[|foo='bar' i]",
+ "[*|foo='bar' i]",
+ // Case-sensitive selectors.
+ "[baz='quux' s]",
+ "[baz='quux' S]",
+ "[baz=quux s]",
+ '[baz="quux" s]',
+ "[baz='quux's]",
+ "[baz='quux's ]",
+ "[baz='quux' s ]",
+ "[baz='quux' /**/ s]",
+ "[baz='quux' s /**/ ]",
+ "[baz='quux'/**/s/**/]",
+ "[baz=quux/**/s]",
+ "[baz='quux'\ts\t] /* \\t */",
+ "[baz='quux'\ns\n] /* \\n */",
+ "[baz='quux'\rs\r] /* \\r */",
+ "[baz='quux' \\s]",
+ "[baz='quux' \\73]",
+ "[baz='quux' \\53]",
+ "[baz~='quux' s]",
+ "[baz^='quux' s]",
+ "[baz$='quux' s]",
+ "[baz*='quux' s]",
+ "[baz|='quux' s]",
+ "[|baz='quux' s]",
+ "[*|baz='quux' s]",
+];
+var invalid = [
+ "[foo[ /* sanity check (invalid) */",
+ "[foo='bar' i i]",
+ "[foo i ='bar']",
+ "[foo= i 'bar']",
+ "[i foo='bar']",
+ "[foo='bar' i\u0000] /* \\0 */",
+ "[foo='bar' \u0130]",
+ "[foo='bar' \u0131]",
+ "[foo='bar' ii]",
+ "[foo='bar' ij]",
+ "[foo='bar' j]",
+ "[foo='bar' \\\\i]",
+ "[foo='bar' \\\\69]",
+ "[foo='bar' i()]",
+ "[foo='bar' i ()]",
+ "[foo='bar' () i]",
+ "[foo='bar' (i)]",
+ "[foo='bar' i []]",
+ "[foo='bar' [] i]",
+ "[foo='bar' [i]]",
+ "[foo='bar' i {}]",
+ "[foo='bar' {} i]",
+ "[foo='bar' {i}]",
+ "[foo='bar' 1i]",
+ "[foo='bar' 1]",
+ "[foo='bar' 'i']",
+ "[foo='bar' url(i)]",
+ "[foo='bar' ,i]",
+ "[foo='bar' i,]",
+ "[foo='bar']i",
+ "[foo='bar' |i]",
+ "[foo='bar' \\|i]",
+ "[foo='bar' *|i]",
+ "[foo='bar' \\*|i]",
+ "[foo='bar' *]",
+ "[foo='bar' \\*]",
+ "[foo i]",
+ "[foo/**/i]",
+];
+var mode = "standards mode";
+onload = function() {
+ var quirks = document.getElementById('quirks').contentWindow;
+ var xml = document.getElementById('xml').contentWindow;
+ [window, quirks, xml].forEach(function(global) {
+ var style = global.document.getElementsByTagName('style')[0];
+ var elm = global.document.getElementById('test');
+ function clean_slate() {
+ style.textContent = '';
+ assert_equals(style.sheet.cssRules.length, 0, 'CSSOM was not empty for empty stylesheet');
+ assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'computed style for empty stylesheet');
+ }
+ valid.forEach(function(s) {
+ test(function() {
+ clean_slate();
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, 1, 'valid rule didn\'t parse into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'hidden', 'valid selector didn\'t match');
+ }, s + ' in ' + global.mode);
+ test(function() {
+ assert_equals(global.document.querySelector(s), elm, 'valid selector');
+ }, s + ' with querySelector in ' + global.mode);
+ });
+ invalid.forEach(function(s) {
+ test(function() {
+ clean_slate();
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, 0, 'invalid rule parsed into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'invalid selector matched');
+ }, s + ' in ' + global.mode);
+ test(function() {
+ assert_throws_dom("SyntaxError", global.DOMException, function() {
+ global.document.querySelector(s);
+ }, 'invalid selector');
+ }, s + ' with querySelector in ' + global.mode);
+ });
+ });
+ done();
+};
+</script>
diff --git a/testing/web-platform/tests/css/selectors/attribute-selectors/style-attribute-selector.html b/testing/web-platform/tests/css/selectors/attribute-selectors/style-attribute-selector.html
new file mode 100644
index 0000000000..83e8102c01
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/attribute-selectors/style-attribute-selector.html
@@ -0,0 +1,130 @@
+<!doctype html>
+<title>CSS Selectors Test: Tests the style attribute used in an attribute selector</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#attribute-selectors">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #container { font-size: 16px; color: black; }
+ .test[style] { color: green }
+ .test[style=""] { font-size: 100px }
+ .test[style*="text-decoration"] { background-color: lime }
+ .test[style] + #sibling { color: green; }
+ .test[style*="text-decoration"] + #sibling { background-color: lime; }
+</style>
+<div id="container">
+ <div id="t1" class="test" style></div>
+ <div id="t2" class="test" style=""></div>
+ <div id="t3" class="test" style="text-decoration:underline"></div>
+ <div id="t4" class="test"></div>
+ <div id="sibling"></div>
+</div>
+<script>
+ const no_match_bgcolor = "rgba(0, 0, 0, 0)";
+ const no_match_color = "rgb(0, 0, 0)";
+ const no_match_font_size = "16px";
+ const match_bgcolor = "rgb(0, 255, 0)";
+ const match_color = "rgb(0, 128, 0)";
+ const match_font_size = "100px";
+
+ test(() => {
+ assert_equals(getComputedStyle(t1).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t1).color, match_color);
+ assert_equals(getComputedStyle(t1).fontSize, match_font_size);
+ }, "Match style attribute with no value");
+
+ test(() => {
+ assert_equals(getComputedStyle(t2).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t2).color, match_color);
+ assert_equals(getComputedStyle(t2).fontSize, match_font_size);
+ }, "Match style attribute with empty value");
+
+ test(() => {
+ assert_equals(getComputedStyle(t3).backgroundColor, match_bgcolor);
+ assert_equals(getComputedStyle(t3).color, match_color);
+ assert_equals(getComputedStyle(t3).fontSize, no_match_font_size);
+ }, "Match style attribute with background value");
+
+ test(() => {
+ assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, no_match_color);
+ assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
+ assert_equals(getComputedStyle(sibling).color, no_match_color);
+ }, "Initially no style attribute to match");
+
+ function reset_style(element) {
+ element.removeAttribute("style");
+ element.offsetTop;
+ }
+
+ function set_style(element) {
+ element.setAttribute("style", "text-decoration: underline");
+ element.offsetTop;
+ }
+
+ test(() => {
+ reset_style(t4);
+ t4.setAttribute("style", "text-decoration: underline");
+ assert_equals(getComputedStyle(t4).backgroundColor, match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, match_color);
+ assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
+ assert_equals(getComputedStyle(sibling).color, match_color);
+ }, "Dynamically change style with Element.setAttribute");
+
+ test(() => {
+ reset_style(t4);
+ t4.style = "text-decoration: underline";
+ assert_equals(getComputedStyle(t4).backgroundColor, match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, match_color);
+ assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
+ assert_equals(getComputedStyle(sibling).color, match_color);
+ }, "Dynamically change style with Element.style");
+
+ test(() => {
+ reset_style(t4);
+ t4.style.textDecoration = "underline";
+ assert_equals(getComputedStyle(t4).backgroundColor, match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, match_color);
+ assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
+ assert_equals(getComputedStyle(sibling).color, match_color);
+ }, "Dynamically change style with Element.style.property");
+
+ test(() => {
+ set_style(t4);
+ t4.removeAttribute("style");
+ assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, no_match_color);
+ assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
+ assert_equals(getComputedStyle(sibling).color, no_match_color);
+ assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
+ }, "Dynamically remove style with Element.removeAttribute");
+
+ test(() => {
+ set_style(t4);
+ t4.style = "";
+ assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, match_color);
+ assert_equals(getComputedStyle(t4).fontSize, match_font_size);
+ assert_equals(getComputedStyle(sibling).color, match_color);
+ assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
+ }, "Dynamically remove style with Element.style");
+
+ test(() => {
+ set_style(t4);
+ t4.style.textDecoration = "";
+ assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, match_color);
+ assert_equals(getComputedStyle(t4).fontSize, match_font_size);
+ assert_equals(getComputedStyle(sibling).color, match_color);
+ assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
+ }, "Dynamically remove style with Element.style.property");
+
+ test(() => {
+ set_style(t4);
+ t4.style.removeProperty("text-decoration");
+ assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
+ assert_equals(getComputedStyle(t4).color, match_color);
+ assert_equals(getComputedStyle(t4).fontSize, match_font_size);
+ assert_equals(getComputedStyle(sibling).color, match_color);
+ assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
+ }, "Dynamically remove style with Element.style.removeProperty");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/case-insensitive-parent-ref.html b/testing/web-platform/tests/css/selectors/case-insensitive-parent-ref.html
new file mode 100644
index 0000000000..0138b79972
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/case-insensitive-parent-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Case-insensitive parent selector matching</title>
+ </head>
+ <body>
+ <svg width="500" height="100" xmlns="http://www.w3.org/2000/svg">
+ <foreignObject width="500" height="100">
+ <span style="color: green">Test passes if the text is green.</span>
+ </foreignObject>
+ </svg>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/case-insensitive-parent.html b/testing/web-platform/tests/css/selectors/case-insensitive-parent.html
new file mode 100644
index 0000000000..a684bbb97c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/case-insensitive-parent.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Case-insensitive parent selector matching</title>
+ <link rel="help" href="https://crbug.com/1418575">
+ <link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+ <link rel="match" href="case-insensitive-parent-ref.html">
+ <style>FoReIgNobject span { color: green; }</style>
+ </head>
+ <body>
+ <svg width="500" height="100" xmlns="http://www.w3.org/2000/svg">
+ <foreignObject width="500" height="100">
+ <span>Test passes if the text is green.</span>
+ </foreignObject>
+ </svg>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/child-indexed-no-parent-ref.html b/testing/web-platform/tests/css/selectors/child-indexed-no-parent-ref.html
new file mode 100644
index 0000000000..069c86cf08
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/child-indexed-no-parent-ref.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:ecoal95@gmail.com">
+<style>
+ :root {
+ color: green;
+ }
+</style>
+<p>Should be green
+<p>Should be green
+<p>Should be green
+<p>Should be green
+<p>Should be green
+<p>Should be green
+<p>Should be green
+<p>Should be green
+<p>Should be green
diff --git a/testing/web-platform/tests/css/selectors/child-indexed-no-parent.html b/testing/web-platform/tests/css/selectors/child-indexed-no-parent.html
new file mode 100644
index 0000000000..c77564bf55
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/child-indexed-no-parent.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: child-indexed selectors should match without a parent element.</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:ecoal95@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="child-indexed-no-parent-ref.html">
+<style>
+ :root:first-child #a {
+ color: green;
+ }
+ :root:nth-child(n) #b {
+ color: green;
+ }
+ :root:first-of-type #c {
+ color: green;
+ }
+ :root:nth-of-type(1) #d {
+ color: green;
+ }
+ :root:last-of-type #e {
+ color: green;
+ }
+ :root:last-child #f {
+ color: green;
+ }
+ :root:nth-last-child(1) #g {
+ color: green;
+ }
+ :root:nth-last-of-type(n) #h {
+ color: green;
+ }
+
+ #i {
+ color: green;
+ }
+
+ /* NB: not matching intentionally */
+ :root:nth-last-child(2) #i {
+ color: red;
+ }
+</style>
+<p id="a">Should be green
+<p id="b">Should be green
+<p id="c">Should be green
+<p id="d">Should be green
+<p id="e">Should be green
+<p id="f">Should be green
+<p id="g">Should be green
+<p id="h">Should be green
+<p id="i">Should be green
diff --git a/testing/web-platform/tests/css/selectors/child-indexed-pseudo-class.html b/testing/web-platform/tests/css/selectors/child-indexed-pseudo-class.html
new file mode 100644
index 0000000000..2e496d8541
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/child-indexed-pseudo-class.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Matching of child-indexed pseudo-classes</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:ecoal95@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+var check = function(element, selectors, qsRoot) {
+ for (var i = 0; i < selectors.length; ++i) {
+ var selector = selectors[i][0];
+ var expected = selectors[i][1];
+ test(function() {
+ assert_equals(expected, element.matches(selector));
+
+ if (qsRoot) {
+ assert_equals(expected, element === qsRoot.querySelector(selector));
+ var qsa = qsRoot.querySelectorAll(selector);
+ assert_equals(expected, !!qsa.length && element === qsa[0]);
+ }
+ }, "Expected " + element.tagName + " element to " +
+ (expected ? "match " : "not match ") + selector + " with matches" +
+ (qsRoot ? ", querySelector(), and querySelectorAll()" : ""));
+ }
+}
+
+var rootOfSubtreeSelectors = [
+ [ ":first-child", true ],
+ [ ":last-child", true ],
+ [ ":only-child", true ],
+ [ ":first-of-type", true ],
+ [ ":last-of-type", true ],
+ [ ":only-of-type", true ],
+ [ ":nth-child(1)", true ],
+ [ ":nth-child(n)", true ],
+ [ ":nth-last-child(1)", true ],
+ [ ":nth-last-child(n)", true ],
+ [ ":nth-of-type(1)", true ],
+ [ ":nth-of-type(n)", true ],
+ [ ":nth-last-of-type(1)", true ],
+ [ ":nth-last-of-type(n)", true ],
+ [ ":nth-child(2)", false ],
+ [ ":nth-last-child(2)", false],
+ [ ":nth-of-type(2)", false ],
+ [ ":nth-last-of-type(2)", false],
+];
+
+check(document.documentElement, rootOfSubtreeSelectors, document);
+check(document.createElement('div'), rootOfSubtreeSelectors);
+
+var fragment = document.createDocumentFragment();
+var div = document.createElement('div');
+fragment.appendChild(div);
+check(div, rootOfSubtreeSelectors, fragment);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/dir-pseudo-in-has.html b/testing/web-platform/tests/css/selectors/dir-pseudo-in-has.html
new file mode 100644
index 0000000000..3a3a0757a5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-pseudo-in-has.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#relational"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#dir-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <section><div class="ltr"><span></span></div></section>
+ <section><div dir="ltr" class="ltr"><span></span></div></section>
+ <section dir="ltr"><div class="ltr"><span></span></div></section>
+ <section><div dir="rtl" class="rtl"><span></span></div></section>
+ <section dir="rtl"><div class="rtl"><span></span></div></section>
+ <style>
+ div, section { width: 100px; height: 20px; }
+ section { background: red; }
+ .ltr:has(*:dir(ltr)) { background: green; }
+ .ltr:has(*:dir(rtl)) { background: red; }
+ .rtl:has(*:dir(rtl)) { background: green; }
+ .rtl:has(*:dir(ltr)) { background: red; }
+ </style>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-pseudo-on-bdi-element.html b/testing/web-platform/tests/css/selectors/dir-pseudo-on-bdi-element.html
new file mode 100644
index 0000000000..434434461d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-pseudo-on-bdi-element.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#the-directionality">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+test(() => {
+ const bdi = document.createElement('bdi');
+ assert_true(bdi.matches(':dir(ltr)'));
+ assert_false(bdi.matches(':dir(rtl)'));
+
+ bdi.textContent = '\u05EA';
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+}, 'bdi element without dir content attribute');
+
+test(() => {
+ const bdi = document.createElement('bdi');
+ bdi.setAttribute('dir', 'foo');
+ assert_true(bdi.matches(':dir(ltr)'));
+ assert_false(bdi.matches(':dir(rtl)'));
+
+ bdi.textContent = '\u05EA';
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+}, 'bdi element with invalid dir content attribute');
+
+test(() => {
+ const bdi = document.createElement('bdi');
+ bdi.setAttribute('dir', 'auto');
+ assert_true(bdi.matches(':dir(ltr)'));
+ assert_false(bdi.matches(':dir(rtl)'));
+
+ bdi.textContent = '\u05EA';
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+
+ bdi.setAttribute('dir', 'AUTO');
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+}, 'bdi element with dir=auto content attribute');
+
+test(() => {
+ const bdi = document.createElement('bdi');
+ bdi.setAttribute('dir', 'ltr');
+ assert_true(bdi.matches(':dir(ltr)'));
+ assert_false(bdi.matches(':dir(rtl)'));
+
+ bdi.setAttribute('dir', 'LTR');
+ assert_true(bdi.matches(':dir(ltr)'));
+ assert_false(bdi.matches(':dir(rtl)'));
+
+ bdi.textContent = '\u05EA';
+ assert_true(bdi.matches(':dir(ltr)'));
+ assert_false(bdi.matches(':dir(rtl)'));
+}, 'bdi element with dir=ltr content attribute');
+
+test(() => {
+ const bdi = document.createElement('bdi');
+ bdi.setAttribute('dir', 'rtl');
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+
+ bdi.setAttribute('dir', 'RTL');
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+
+ bdi.textContent = '\u05EA';
+ assert_false(bdi.matches(':dir(ltr)'));
+ assert_true(bdi.matches(':dir(rtl)'));
+}, 'bdi element with dir=rtl content attribute');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-pseudo-on-input-element.html b/testing/web-platform/tests/css/selectors/dir-pseudo-on-input-element.html
new file mode 100644
index 0000000000..25f7a080d7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-pseudo-on-input-element.html
@@ -0,0 +1,203 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#the-directionality">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+test(() => {
+ const input = document.createElement('input');
+ input.type = 'tel';
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'foo');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'rtl');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'RTL');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'ltr');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'LTR');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'auto');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.value = '\u05EA';
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'AUTO');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.removeAttribute('dir');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+}, 'input element whose type attribute is in the telephone state');
+
+test(() => {
+ const input = document.createElement('input');
+ input.type = 'tel';
+
+ const container = document.createElement('div');
+ container.setAttribute('dir', 'rtl');
+ container.appendChild(input);
+
+ // Insert the element into the document so that we can also check for
+ // 'direction' in computed style.
+ document.body.appendChild(container);
+
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+ // Per https://html.spec.whatwg.org/multipage/rendering.html#bidi-rendering:
+ assert_equals(getComputedStyle(input).direction, 'ltr');
+
+ // Changing to a different type causes the special type=tel rule to no longer apply.
+ input.type = 'text';
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+ assert_equals(getComputedStyle(input).direction, 'rtl');
+
+ // And restoring type=tel brings back that behavior.
+ input.type = 'tel';
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+ assert_equals(getComputedStyle(input).direction, 'ltr');
+
+ document.body.removeChild(container);
+}, 'input element whose type attribute is in the telephone state in a RTL block');
+
+for (const type of ['password', 'text', 'search', 'url', 'email', 'submit', 'reset', 'button', 'hidden']) {
+ test(() => {
+ const input = document.createElement('input');
+ input.type = type;
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'foo');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'rtl');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'RTL');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'ltr');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'LTR');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'auto');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.value = '\u05EA';
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'AUTO');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'))
+
+ input.removeAttribute('dir');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+ }, `input element whose type attribute is in the ${type} state`);
+}
+
+test(() => {
+ const input = document.createElement('input');
+ input.type = 'text';
+ // bidirectional character type R
+ input.value = '\u05EA';
+ input.setAttribute('dir', 'auto');
+
+ const container = document.createElement('div');
+ container.appendChild(input);
+
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ // Changing to a different type that does't use value causes the bidi rule to no longer apply.
+ input.type = 'radio';
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ // And restoring type=text brings back that behavior.
+ input.type = 'text';
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+}, 'dynamic changes to type of input elements affect whether value is used for dir=auto');
+
+for (const type of ['date', 'time', 'number', 'range', 'color', 'checkbox', 'radio', 'image']) {
+ test(() => {
+ const input = document.createElement('input');
+ input.type = type;
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'foo');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'rtl');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'RTL');
+ assert_false(input.matches(':dir(ltr)'));
+ assert_true(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'ltr');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'LTR');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'auto');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.value = '\u05EA';
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+
+ input.setAttribute('dir', 'AUTO');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'))
+
+ input.removeAttribute('dir');
+ assert_true(input.matches(':dir(ltr)'));
+ assert_false(input.matches(':dir(rtl)'));
+ }, `input element whose type attribute is in the ${type} state`);
+}
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element-ref.html b/testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element-ref.html
new file mode 100644
index 0000000000..9317f1ebc6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+
+div {
+ width: 100px;
+ height: 100px;
+ float: left;
+ background-color: green;
+}
+
+</style>
+</head>
+<body>
+<div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element.html b/testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element.html
new file mode 100644
index 0000000000..92bf1b4d5f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-pseudo-update-document-element.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html dir="ltr">
+<head>
+<link rel="match" href="dir-pseudo-update-document-element-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+<script>
+document.documentElement.setAttribute('dir', 'rtl');
+</script>
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ float: left;
+}
+
+div:dir(rtl) {
+ background-color: green;
+}
+
+div:dir(ltr) {
+ background-color: red;
+}
+</style>
+</head>
+<body>
+<div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-auto-direction-change-001.html b/testing/web-platform/tests/css/selectors/dir-selector-auto-direction-change-001.html
new file mode 100644
index 0000000000..f6c6393b08
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-auto-direction-change-001.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: Check for correctly updating :dir=auto when the the directionality is changed in a display:none subtree </title>
+ <meta charset="utf8">
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+ <style>
+ #target {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+ :dir(ltr) + #target {
+ background-color: green;
+ }
+ </style>
+</head>
+
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div dir="auto" style="display:none">
+ <div>
+ <div id="inner">رسمية</div>
+ </div>
+ </div>
+ <div id="target"></div>
+ <script>
+ inner.offsetTop;
+ inner.firstChild.data = "LTR";
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-auto.html b/testing/web-platform/tests/css/selectors/dir-selector-auto.html
new file mode 100644
index 0000000000..d53e989f69
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-auto.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<head>
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #div4_1 {
+ direction: rtl;
+ }
+ </style>
+</head>
+
+<!-- &#1514; is the Hebrew letter tav, i.e. RTL -->
+<body>
+ <div id=testDivs>
+ <div id=div1 dir=auto>
+ <div id=div1_1>a</div>
+ </div>
+ <div id=div2 dir=auto>
+ <div id=div2_1>&#1514;</div>
+ </div>
+ <div id=div3 dir=auto>
+ <div id=div3_1 dir=rtl>&#1514;</div>
+ <div id=div3_2>a</div>
+ </div>
+ <div id=div4 dir=auto>
+ <div id=div4_1>
+ <div id=div4_1_1>a</div>
+ </div>
+ </div>
+ </div>
+</body>
+
+<script>
+function test_directionality(message, element, expected) {
+ test(() => {
+ var isLTR = document.querySelector("#" + element.id + ":dir(ltr)") == element;
+ var isRTL = document.querySelector("#" + element.id + ":dir(rtl)") == element;
+ if (expected == "ltr") {
+ assert_true(isLTR);
+ assert_false(isRTL);
+ } else {
+ assert_false(isLTR);
+ assert_true(isRTL);
+ }
+ }, message + " directionality of element " + element.id + " is " + expected);
+}
+
+test_directionality("Initial ", div1, "ltr");
+test_directionality("Initial ", div1_1, "ltr");
+test_directionality("Initial ", div2, "rtl");
+test_directionality("Initial ", div2_1, "rtl");
+test_directionality("Initial ", div3, "ltr");
+test_directionality("Initial ", div3_1, "rtl");
+test_directionality("Initial ", div3_2, "ltr");
+test_directionality("Initial ", div4, "ltr");
+test_directionality("Initial ", div4_1, "ltr");
+test_directionality("Initial ", div4_1_1, "ltr");
+
+div1_1.innerText = "\u05EA";
+div1_1.offsetTop;
+test_directionality("Updated ", div1, "rtl");
+test_directionality("Updated ", div1_1, "rtl");
+
+div1_1.dir = "ltr";
+div1_1.offsetTop;
+test_directionality("Updated ", div1, "ltr");
+test_directionality("Updated ", div1_1, "ltr");
+
+div1_1.innerText = "a";
+div1_1.offsetTop;
+test_directionality("Reupdated ", div1, "ltr");
+test_directionality("Reupdated ", div1_1, "ltr");
+
+div2_1.remove();
+div2.offsetTop;
+test_directionality("Updated ", div2, "ltr");
+
+div3_1.dir = "";
+div3_1.offsetTop;
+test_directionality("Updated ", div3, "rtl");
+div3.appendChild(div3_1);
+div3.offsetTop;
+test_directionality("Updated ", div3, "ltr");
+
+div4_1_1.innerText = "\u05EA";
+div4_1_1.offsetTop;
+test_directionality("Updated ", div4, "rtl");
+test_directionality("Updated ", div4_1, "rtl");
+test_directionality("Updated ", div4_1_1, "rtl");
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-001-ref.html b/testing/web-platform/tests/css/selectors/dir-selector-change-001-ref.html
new file mode 100644
index 0000000000..8c79c8328f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-001-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ span { background-color: lime }
+ </style>
+</head>
+<body>
+ <div>
+ <div>
+ <div></div>
+ <span>The background color should be lime</span>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-001.html b/testing/web-platform/tests/css/selectors/dir-selector-change-001.html
new file mode 100644
index 0000000000..41f50b29fc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-001.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: Check for correctly updating :dir matching on dir attribute change from default(ltr) to rtl</title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="dir-selector-change-001-ref.html">
+ <style>
+ #x:dir(rtl) + span { background-color: lime }
+ #outer { direction:ltr }
+ </style>
+</head>
+<body>
+ <div id="outer" style="-webkit-locale: 'en'">
+ <div>
+ <div id="x"></div>
+ <span>The background color should be lime</span>
+ </div>
+ </div>
+ <script>
+ outer.offsetTop;
+ outer.setAttribute("dir", "rtl");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-002.html b/testing/web-platform/tests/css/selectors/dir-selector-change-002.html
new file mode 100644
index 0000000000..777d764744
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-002.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: Check for correctly updating :dir matching on dir attribute change from default(ltr) to rtl</title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+
+ div:dir(rtl) {
+ background-color: green;
+ }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div id="inner"></div>
+ <script>
+ inner.offsetTop;
+ inner.setAttribute("dir", "rtl");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-003-ref.html b/testing/web-platform/tests/css/selectors/dir-selector-change-003-ref.html
new file mode 100644
index 0000000000..8c79c8328f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-003-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ span { background-color: lime }
+ </style>
+</head>
+<body>
+ <div>
+ <div>
+ <div></div>
+ <span>The background color should be lime</span>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-003.html b/testing/web-platform/tests/css/selectors/dir-selector-change-003.html
new file mode 100644
index 0000000000..92fff8009f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-003.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: Check for correctly updating :dir matching on dir attribute change from rtl to auto</title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="dir-selector-change-003-ref.html">
+ <style>
+ #x:dir(ltr) + span { background-color: lime }
+ </style>
+</head>
+<body>
+ <div id="outer" dir="rtl">
+ <div>
+ <div id="x"></div>
+ <span>The background color should be lime</span>
+ </div>
+ </div>
+ <script>
+ outer.offsetTop;
+ outer.setAttribute("dir", "auto");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-004-ref.html b/testing/web-platform/tests/css/selectors/dir-selector-change-004-ref.html
new file mode 100644
index 0000000000..9a130cb2e5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-004-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ span { background-color: lime }
+ </style>
+</head>
+<body>
+ <div>
+ <div dir="rtl">
+ <div></div>
+ <span>מקור השם עברית</span>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-change-004.html b/testing/web-platform/tests/css/selectors/dir-selector-change-004.html
new file mode 100644
index 0000000000..c7890a601a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-change-004.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: Check for correctly updating :dir matching on directionality change from ltr to rtl</title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="dir-selector-change-004-ref.html">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style>
+ #x:dir(rtl) + span { background-color: lime }
+ </style>
+</head>
+<body>
+ <div dir="auto">
+ <div>
+ <div id="x"></div>
+ <span id="inner">The background color should be lime</span>
+ </div>
+ </div>
+ <script>
+ inner.offsetTop;
+ inner.innerHTML = "מקור השם עברית";
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-ltr-001.html b/testing/web-platform/tests/css/selectors/dir-selector-ltr-001.html
new file mode 100644
index 0000000000..9a61e985d4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-ltr-001.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: basic support for dir(ltr)</title>
+ <link rel="author" title="Takeshi Kurosawa" href="mailto:taken.spc@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+ <meta name="assert" content="The :dir(ltr) pseudo-class matches an element that has a directionality of (ltr). Since the div element has dir=ltr, the selector matches.">
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+
+ div:dir(ltr) {
+ background-color: green;
+ }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div dir="ltr"></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-ltr-002.html b/testing/web-platform/tests/css/selectors/dir-selector-ltr-002.html
new file mode 100644
index 0000000000..988ae3ffcb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-ltr-002.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: exception handling for an invalid identifier of dir()</title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+ <meta name="assert" content="The invalid identifier of :dir(ltrr) pseudo-class doesn't match an element that has a directionality of (ltr). Even if the div element has dir=ltr, the selector should not match.">
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ }
+
+ div:dir(ltrr) {
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div dir="ltr"></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-ltr-003.html b/testing/web-platform/tests/css/selectors/dir-selector-ltr-003.html
new file mode 100644
index 0000000000..8f8bd1ca81
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-ltr-003.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: exception handling for multiple identifiers of dir() </title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+ <meta name="assert" content="The multiple identifiers of :dir(ltr, rtl) pseudo-class don't match an element that has a directionality of (ltr). Even if the div element has dir=ltr, the selector should not match.">
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ }
+
+ div:dir(ltr, rtl) {
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div dir="ltr"></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-querySelector.html b/testing/web-platform/tests/css/selectors/dir-selector-querySelector.html
new file mode 100644
index 0000000000..a05e3fea78
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-querySelector.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<head>
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <div id=outer>
+ <div id=div1></div>
+ <div id=div2 dir=ltr>
+ <div id=div2_1></div>
+ <div id=div2_2 dir=ltr></div>
+ <div id=div2_3 dir=rtl></div>
+ </div>
+ <div id=div3 dir=rtl>
+ <div id=div3_1>
+ <div id=div3_1_1></div>
+ </div>
+ <div id=div3_2 dir=ltr></div>
+ <div id=div3_3 dir=rtl></div>
+ </div>
+ <div id=div4 dir=lol></div>
+ <div id=div5 dir=auto></div>
+ </div>
+</body>
+
+<script>
+test(() => {
+ assert_equals(document.querySelector(":dir(lol)"), null);
+ assert_equals(document.querySelector(":dir(lol )"), null);
+ assert_equals(document.querySelector(":dir( auto)"), null);
+ assert_equals(document.querySelector(":dir(\nauto\t)"), null);
+}, ":dir() allows any ident value but strings other than ltr/rtl don't match");
+
+test(() => {
+ assert_throws_dom("SYNTAX_ERR", () => { document.querySelector(":dir()"); });
+ assert_throws_dom("SYNTAX_ERR", () => { document.querySelector(":dir(ltr, rtl)"); });
+ assert_throws_dom("SYNTAX_ERR", () => { document.querySelector(":dir('ltr')"); });
+}, ":dir() requires exactly an ident argument");
+
+test(() => {
+ assert_equals(document.querySelector(":dir(rtl)"), div2_3);
+ assert_equals(document.querySelector("*:dir(rtl)"), div2_3);
+ assert_equals(document.querySelector("div:dir(ltr)"), outer);
+ assert_equals(document.querySelector("div:dir(ltr):dir(ltr)"), outer);
+ assert_equals(document.querySelector(":dir(rtl)#div3_3"), div3_3);
+ assert_equals(document.querySelector(":nth-child(2):dir(rtl)"), null);
+ assert_equals(document.querySelector(":nth-child(3):dir(rtl)"), div2_3);
+ assert_equals(document.querySelector(":nth-child(4):dir(ltr)"), div4);
+ assert_equals(document.querySelector(":nth-last-child(3):dir(rtl)"), div3);
+}, ":dir() works in compound selectors");
+
+test(() => {
+ assert_equals(document.querySelector("#div2 :dir(ltr)"), div2_1);
+ assert_equals(document.querySelector(":dir(rtl) div"), div3_1);
+ assert_equals(document.querySelector("div + :dir(ltr)"), div2);
+ assert_equals(document.querySelector(":dir(ltr) + :dir(rtl)"), div2_3);
+ assert_equals(document.querySelector(":dir(rtl) :dir(rtl)"), div3_1);
+ assert_equals(document.querySelector(":dir(rtl) + :dir(ltr)"), div3_2);
+ assert_equals(document.querySelector(":dir(rtl) ~ :dir(rtl)"), div3_3);
+ assert_equals(document.querySelector(":dir(rtl) :dir(ltr)"), div3_2);
+ assert_equals(document.querySelector("* :dir(rtl) *"), div3_1);
+ assert_equals(document.querySelector("div :dir(rtl) div"), div3_1);
+ assert_equals(document.querySelector(":dir(ltr) :dir(rtl) + :dir(ltr)"), div3_2);
+ assert_equals(document.querySelector(":dir(ltr) + :dir(rtl) + * + *"), div5);
+ assert_equals(document.querySelector(":dir(rtl) > * > :dir(rtl)"), div3_1_1);
+}, ":dir() works in complex selectors");
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-rtl-001.html b/testing/web-platform/tests/css/selectors/dir-selector-rtl-001.html
new file mode 100644
index 0000000000..50bc06633b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-rtl-001.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: basic support for dir(rtl)</title>
+ <link rel="author" title="Takeshi Kurosawa" href="mailto:taken.spc@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+ <meta name="assert" content="The :dir(rtl) pseudo-class matches an elment that has a directionality of right-to-left (rtl). Since the div element has dir=rtl, the selector matches.">
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+
+ div:dir(rtl) {
+ background-color: green;
+ }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div dir="rtl"></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-white-space-001-ref.html b/testing/web-platform/tests/css/selectors/dir-selector-white-space-001-ref.html
new file mode 100644
index 0000000000..955a2dd603
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-white-space-001-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div></div>
+ <div></div>
+ <div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-selector-white-space-001.html b/testing/web-platform/tests/css/selectors/dir-selector-white-space-001.html
new file mode 100644
index 0000000000..762ff45e58
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-selector-white-space-001.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Level 4 Test: Verify for an identifier with leading and tailing whitespace of dir() </title>
+ <link rel="author" title="Miyoung Shin" href="mailto:myid.shin@igalia.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#dir-pseudo">
+ <link rel="match" href="dir-selector-white-space-001-ref.html">
+ <meta name="assert" content="The :dir(ltr) pseudo-class matches an element that has a directionality of (ltr). Since the div element has dir=ltr, the selector matches.">
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+
+ #a:dir( ltr) { background-color: green; }
+ #b:dir(ltr ) { background-color: green; }
+ #c:dir( ltr ) { background-color: green; }
+ </style>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div id="a" dir="ltr"></div>
+ <div id="b" dir="ltr"></div>
+ <div id="c" dir="ltr"></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-01-ref.html b/testing/web-platform/tests/css/selectors/dir-style-01-ref.html
new file mode 100644
index 0000000000..664d6dfa7f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-01-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>dir() selector reference</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <style>
+ div { text-align: left; }
+ .blue { color: blue; direction: ltr; }
+ .lime { color: lime; direction: rtl; }
+ </style>
+ </head>
+ <body>
+ <div class="blue">This element has default direction.</div>
+ <div class="blue">This element is ltr.</div>
+ <div class="lime">This element is rtl.</div>
+ <div class="blue">
+ <div>This element should inherit ltr.</div>
+ <div class="blue">This element is ltr.</div>
+ <div class="lime">This element is rtl.</div>
+ <div class="blue">Every word in this element should inherit ltr.</div>
+ </div>
+ <div class="lime">
+ <div>This element should inherit rtl.</div>
+ <div class="blue">This element is ltr.</div>
+ <div class="lime">This element is rtl.</div>
+ <div class="lime">Every word in this element should inherit rtl.</div>
+ </div>
+ <div class="blue">This element has an invalid dir attribute and
+ should have default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-01a.html b/testing/web-platform/tests/css/selectors/dir-style-01a.html
new file mode 100644
index 0000000000..f379d14e18
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-01a.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks :dir() basic functions with valid and invalid values.">
+ <link rel="match" href="dir-style-01-ref.html">
+ <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-30">
+ <style>
+ div { text-align: left; }
+ :dir(ltr) { color: blue }
+ :dir(rtl) { color: lime }
+ :dir(foopy) { color: red }
+ </style>
+ </head>
+ <body>
+ <div>This element has default direction.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ <div dir="ltr">
+ <div>This element should inherit ltr.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ <div><span>Every <span>word <span>in <span>this <span>element <span>should <span>inherit <span>ltr</span></span></span></span></span></span></span></span>.</div>
+ </div>
+ <div dir="rtl">
+ <div>This element should inherit rtl.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ <div><span>Every <span>word <span>in <span>this <span>element <span>should <span>inherit <span>rtl</span></span></span></span></span></span></span></span>.</div>
+ </div>
+ <div dir="foopy">This element has an invalid dir attribute and
+ should have default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-01b.html b/testing/web-platform/tests/css/selectors/dir-style-01b.html
new file mode 100644
index 0000000000..37ad9406cf
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-01b.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <meta charset="UTF-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks :dir() basic functions after dynamic directionality change on elements.">
+ <link rel="match" href="dir-style-01-ref.html">
+ <meta name="fuzzy" content="maxDifference=0-255; totalPixels=0-30">
+ <style>
+ div { text-align: left; }
+ :dir(ltr) { color: blue }
+ :dir(rtl) { color: lime }
+ :dir(foopy) { color: red }
+ </style>
+ <script>
+ function switchDir()
+ {
+ divs = document.getElementsByTagName("div");
+ divs[0].offsetWidth; // ensure it's a dynamic change
+ for (var i = 0; i < divs.length; ++i) {
+ theDiv = divs[i];
+ if (theDiv.dir == "ltr") {
+ theDiv.dir = "rtl";
+ } else if (theDiv.dir == "rtl") {
+ theDiv.dir = "ltr";
+ }
+ }
+
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="switchDir()">
+ <div>This element has default direction.</div>
+ <div dir="rtl">This element is ltr.</div>
+ <div dir="ltr">This element is rtl.</div>
+ <div dir="rtl">
+ <div>This element should inherit ltr.</div>
+ <div dir="rtl">This element is ltr.</div>
+ <div dir="ltr">This element is rtl.</div>
+ <div><span>Every <span>word <span>in <span>this <span>element <span>should <span>inherit <span>ltr</span></span></span></span></span></span></span></span>.</div>
+ </div>
+ <div dir="ltr">
+ <div>This element should inherit rtl.</div>
+ <div dir="rtl">This element is ltr.</div>
+ <div dir="ltr">This element is rtl.</div>
+ <div><span>Every <span>word <span>in <span>this <span>element <span>should <span>inherit <span>rtl</span></span></span></span></span></span></span></span>.</div>
+ </div>
+ <div dir="foopy">This element has an invalid dir attribute and
+ should have default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-02-ref.html b/testing/web-platform/tests/css/selectors/dir-style-02-ref.html
new file mode 100644
index 0000000000..64fb090465
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-02-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>dir() selector reference</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <style>
+ div { text-align: left; }
+ .blue { color: blue; direction: ltr; }
+ .lime { color: lime; direction: rtl; }
+ </style>
+ </head>
+ <body>
+ <div class="lime">This element has default direction.</div>
+ <div class="blue">This element is ltr.</div>
+ <div class="lime">This element is rtl.</div>
+ <div class="blue">
+ <div>This element should inherit ltr.</div>
+ <div class="blue">This element is ltr.</div>
+ <div class="lime">This element is rtl.</div>
+ </div>
+ <div class="lime">
+ <div>This element should inherit rtl.</div>
+ <div class="blue">This element is ltr.</div>
+ <div class="lime">This element is rtl.</div>
+ </div>
+ <div class="lime">This element has an invalid dir attribute and
+ should have default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-02a.html b/testing/web-platform/tests/css/selectors/dir-style-02a.html
new file mode 100644
index 0000000000..69b254dc82
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-02a.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html dir="rtl">
+ <head>
+ <meta charset="UTF-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks :dir() basic functions when default document directionality is rtl.">
+ <link rel="match" href="dir-style-02-ref.html">
+ <style>
+ div { text-align: left; }
+ :dir(ltr) { color: blue }
+ :dir(rtl) { color: lime }
+ :dir(foopy) { color: red }
+ </style>
+ </head>
+ <body>
+ <div>This element has default direction.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ <div dir="ltr">
+ <div>This element should inherit ltr.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ </div>
+ <div dir="rtl">
+ <div>This element should inherit rtl.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ </div>
+ <div dir="foopy">This element has an invalid dir attribute and
+ should have default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-02b.html b/testing/web-platform/tests/css/selectors/dir-style-02b.html
new file mode 100644
index 0000000000..802ca41f11
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-02b.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <meta charset="UTF-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks :dir() basic functions when document directionality is dynamically changed from ltr to rtl.">
+ <link rel="match" href="dir-style-02-ref.html">
+ <style>
+ div { text-align: left; }
+ :dir(ltr) { color: blue }
+ :dir(rtl) { color: lime }
+ :dir(foopy) { color: red }
+ </style>
+ <script>
+ function switchDir()
+ {
+ // ensure it's a dynamic change
+ document.documentElement.getBoundingClientRect();
+
+ document.dir = "rtl";
+
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="switchDir()">
+ <div>This element has default direction.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ <div dir="ltr">
+ <div>This element should inherit ltr.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ </div>
+ <div dir="rtl">
+ <div>This element should inherit rtl.</div>
+ <div dir="ltr">This element is ltr.</div>
+ <div dir="rtl">This element is rtl.</div>
+ </div>
+ <div dir="foopy">This element has an invalid dir attribute and
+ should have default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-03-ref.html b/testing/web-platform/tests/css/selectors/dir-style-03-ref.html
new file mode 100644
index 0000000000..8c2a60745a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-03-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>dir() selector reference</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <style>
+ div { text-align: left; }
+ .ltr { color: blue; direction: ltr }
+ .rtl { color: lime; direction: rtl }
+ </style>
+ </head>
+ <body>
+ <div class="rtl">This element is rtl.</div>
+ <div class="ltr">This element has default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-03a.html b/testing/web-platform/tests/css/selectors/dir-style-03a.html
new file mode 100644
index 0000000000..c57b93eaa6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-03a.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks if :dir() can work with other selectors correctly.">
+ <link rel="match" href="dir-style-03-ref.html">
+ <style>
+ div { color: lime; text-align: left; }
+ :not(:dir(ltr)) + div { color: blue; }
+ </style>
+ </head>
+ <body>
+ <div dir="rtl">This element is rtl.</div>
+ <div>This element has default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-03b.html b/testing/web-platform/tests/css/selectors/dir-style-03b.html
new file mode 100644
index 0000000000..bb93b2fd62
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-03b.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <meta charset="UTF-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks if :dir() can work with other selectors correctly after a dynamic directionality change on specified divs.">
+ <link rel="match" href="dir-style-03-ref.html">
+ <style>
+ div { color: lime; text-align: left; }
+ :not(:dir(ltr)) + div { color: blue }
+ </style>
+ <script>
+ function switchDir()
+ {
+ theDiv = document.getElementById("div");
+ theDiv.offsetWidth; // ensure it's a dynamic change
+ if (theDiv.dir == "ltr") {
+ theDiv.dir = "rtl";
+ } else if (theDiv.dir == "rtl") {
+ theDiv.dir = "ltr";
+ }
+
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="switchDir()">
+ <div id="div" dir="ltr">This element is rtl.</div>
+ <div>This element has default direction.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-04-ref.html b/testing/web-platform/tests/css/selectors/dir-style-04-ref.html
new file mode 100644
index 0000000000..13d394abf6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-04-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>dir() selector reference</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <style>
+ div { text-align: left; }
+ .ltr { direction: ltr; color: blue; }
+ .rtl { direction: rtl; color: lime; }
+ </style>
+ </head>
+ <body>
+ <div class="ltr">This element is ltr. <span>This span should
+ inherit dir from the parent. <span>This span should inherit dir
+ from the grandparent.</span></span>
+ </div>
+ <div class="rtl">This element is rtl. <span>This span should
+ inherit dir from the parent. <span>This span should inherit dir
+ from the grandparent.</span></span>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/dir-style-04.html b/testing/web-platform/tests/css/selectors/dir-style-04.html
new file mode 100644
index 0000000000..cbfe1307d4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/dir-style-04.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <meta charset="UTF-8">
+ <title>CSS Test: :dir() selector</title>
+ <link rel="author" title="Astley Chen" href="mailto:aschen@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-dir-pseudo">
+ <meta name="assert" content="Test checks :dir() basic functions on runtime added elements.">
+ <link rel="match" href="dir-style-04-ref.html">
+ <meta name="fuzzy" content="maxDifference=0-70; totalPixels=0-180">
+ <style>
+ :dir(ltr) { color: blue }
+ :dir(rtl) { color: lime }
+ div { text-align: left; }
+ </style>
+ <script>
+ function appendChildren(e)
+ {
+ // ensure it's a dynamic change
+ document.documentElement.getBoundingClientRect();
+
+ var x = document.createElement("span");
+ x.innerHTML = "This span should inherit dir from the parent. ";
+
+ var y = document.createElement("span");
+ y.innerHTML = "This span should inherit dir from the grandparent.";
+
+ var div = document.getElementById(e);
+
+ x.appendChild(y);
+ div.appendChild(x);
+
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </head>
+ <body onload="appendChildren('d1');appendChildren('d2');">
+ <div id="d1" dir="ltr">This element is ltr. </div>
+ <div id="d2" dir="rtl">This element is rtl. </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/eof-right-after-selector-crash.html b/testing/web-platform/tests/css/selectors/eof-right-after-selector-crash.html
new file mode 100644
index 0000000000..c387c755ab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/eof-right-after-selector-crash.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>EOF immediately after selector</title>
+<link rel="help" href="https://crbug.com/1376067">
+<link rel="stylesheet" href="data:,a{">
diff --git a/testing/web-platform/tests/css/selectors/eof-some-after-selector-crash.html b/testing/web-platform/tests/css/selectors/eof-some-after-selector-crash.html
new file mode 100644
index 0000000000..557fabf668
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/eof-some-after-selector-crash.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>EOF some time after selector</title>
+<link rel="help" href="https://crbug.com/1376067">
+<link rel="stylesheet" href="data:text/css,a{xyz">
diff --git a/testing/web-platform/tests/css/selectors/first-child.html b/testing/web-platform/tests/css/selectors/first-child.html
new file mode 100644
index 0000000000..c06aff3f89
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-child.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :first-child</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-first-child-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ See also:
+ * child-indexed-pseudo-class.html
+ * child-indexed-no-parent.html
+ * invalidation/first-child-last-child.html
+-->
+<body>
+
+<div>
+ <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+ <div id="target2">There is the second child element.</div>
+ <blockquote></blockquote>
+</div>
+
+<div>
+ <!-- -->
+ <div id="target3">A comment node should be ignored.</div>
+</div>
+
+<div>
+ .
+ <div id="target4">Non-whitespace text node should be ignored.</div>
+</div>
+
+<div>
+ <blockquote></blockquote>
+ <div id="target5" data-expected="false">The second child should not be matched.</div>
+</div>
+
+<script>
+for (let i = 1; i <= 5; ++i) {
+ let target = document.querySelector(`#target${i}`);
+ test(() => {
+ if (target.dataset.expected == 'false')
+ assert_false(target.matches(':first-child'));
+ else
+ assert_true(target.matches(':first-child'));
+ }, target.textContent);
+}
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/first-letter-flag-001-ref.html b/testing/web-platform/tests/css/selectors/first-letter-flag-001-ref.html
new file mode 100644
index 0000000000..7643368305
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-letter-flag-001-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>::first-letter with a Regional-Indicator flag symbol - reference</title>
+<style>
+ p {
+ font: 24px/3 serif;
+ }
+ span {
+ font-size: 2em;
+ }
+</style>
+<p><span>&#x1F1EC;&#x1F1E7;</span> UK flag
diff --git a/testing/web-platform/tests/css/selectors/first-letter-flag-001.html b/testing/web-platform/tests/css/selectors/first-letter-flag-001.html
new file mode 100644
index 0000000000..dc23dda174
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-letter-flag-001.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>::first-letter with a Regional-Indicator flag symbol</title>
+<meta name="assert" content="::first-letter should apply to symbol characters">
+<link rel=help href="https://drafts.csswg.org/css-pseudo-4/#first-letter-pseudo">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/5099#issuecomment-759612015">
+<link rel=match href=first-letter-flag-001-ref.html>
+<style>
+ p {
+ font: 24px/3 serif;
+ }
+ p::first-letter {
+ font-size: 2em;
+ }
+</style>
+<p>&#x1F1EC;&#x1F1E7; UK flag
diff --git a/testing/web-platform/tests/css/selectors/first-line-bidi-001-ref.html b/testing/web-platform/tests/css/selectors/first-line-bidi-001-ref.html
new file mode 100644
index 0000000000..beb6caf5c4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-line-bidi-001-ref.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Reference for ::first-line selector with bidi content</title>
+<style>
+body { font: 12px arial, sans-serif; }
+table { font-size: 10px; }
+tr td { margin: 1em 1em; border: 1px solid gray; width: 16em; }
+td:nth-child(1) { text-align: left; }
+td:nth-child(2) { text-align: center; }
+td:nth-child(3) { text-align: right; }
+span.first { color: green; background: pink; }
+th { padding: 1em; }
+td { padding: 2px; }
+td p { margin: 0; }
+xl { float: left; font-size: 2.5em; }
+xr { float: right; font-size: 2.5em; }
+</style>
+<p>In each box, the first-line text should be <span style="color:green; background:pink">green on pink</span>
+and should never project outside the box:</p>
+<table>
+<tr><th><code>text-align:left</code></th><th><code>text-align:center</code></th><th><code>text-align:right</code></th></tr>
+<tr>
+ <!-- no padding/indent -->
+ <td>
+ <p><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-left:1em -->
+ <td>
+ <p style="padding-left:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-left:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-left:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-right:1em -->
+ <td>
+ <p style="padding-right:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-right:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-right:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- text-indent:2em -->
+ <td>
+ <p style="text-indent:2em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="text-indent:2em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="text-indent:2em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:left -->
+ <td>
+ <p><xl>A</xl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xl>A</xl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xl>A</xl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:right -->
+ <td>
+ <p><xr>Z</xr><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xr>Z</xr><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xr>Z</xr><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+</table>
diff --git a/testing/web-platform/tests/css/selectors/first-line-bidi-001.html b/testing/web-platform/tests/css/selectors/first-line-bidi-001.html
new file mode 100644
index 0000000000..608a0cabd5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-line-bidi-001.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>::first-line selector with bidi content</title>
+<meta name="assert" content="The use of ::first-line should not disrupt bidi layout.">
+<link rel=help href=https://drafts.csswg.org/css-pseudo-4/#first-line-styling>
+<link rel=match href=first-line-bidi-001-ref.html>
+<style>
+body { font: 12px arial, sans-serif; }
+table { font-size: 10px; }
+tr td { margin: 1em 1em; border: 1px solid gray; width: 16em; }
+td:nth-child(1) { text-align: left; }
+td:nth-child(2) { text-align: center; }
+td:nth-child(3) { text-align: right; }
+td p::first-line { color: green; background: pink; }
+th { padding: 1em; }
+td { padding: 2px; }
+td p { margin: 0; }
+xl { float: left; font-size: 2.5em; }
+xr { float: right; font-size: 2.5em; }
+</style>
+<p>In each box, the first-line text should be <span style="color:green; background:pink">green on pink</span>
+and should never project outside the box:</p>
+<table>
+<tr><th><code>text-align:left</code></th><th><code>text-align:center</code></th><th><code>text-align:right</code></th></tr>
+<tr>
+ <!-- no padding/indent -->
+ <td>
+ <p><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-left:1em -->
+ <td>
+ <p style="padding-left:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-left:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-left:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-right:1em -->
+ <td>
+ <p style="padding-right:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-right:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="padding-right:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- text-indent:2em -->
+ <td>
+ <p style="text-indent:2em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="text-indent:2em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p style="text-indent:2em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:left -->
+ <td>
+ <p><xl>A</xl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xl>A</xl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xl>A</xl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:right -->
+ <td>
+ <p><xr>Z</xr><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xr>Z</xr><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p><xr>Z</xr><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+</table>
diff --git a/testing/web-platform/tests/css/selectors/first-line-bidi-002-ref.html b/testing/web-platform/tests/css/selectors/first-line-bidi-002-ref.html
new file mode 100644
index 0000000000..737ef1ec21
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-line-bidi-002-ref.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Reference for ::first-line selector with bidi content</title>
+<style>
+body { font: 12px arial, sans-serif; }
+table { font-size: 10px; }
+tr td { margin: 1em 1em; border: 1px solid gray; width: 16em; }
+td:nth-child(1) { text-align: left; }
+td:nth-child(2) { text-align: center; }
+td:nth-child(3) { text-align: right; }
+span.first { color: green; background: pink; }
+th { padding: 1em; }
+td { padding: 2px; }
+td p { margin: 0; }
+xl { float: left; font-size: 2.5em; }
+xr { float: right; font-size: 2.5em; }
+</style>
+<p>In each box, the first-line text should be <span style="color:green; background:pink">green on pink</span>
+and should never project outside the box:</p>
+<table>
+<tr><th><code>text-align:left</code></th><th><code>text-align:center</code></th><th><code>text-align:right</code></th></tr>
+<tr>
+ <!-- no padding/indent -->
+ <td>
+ <p dir=rtl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-left:1em -->
+ <td>
+ <p dir=rtl style="padding-left:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-left:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-left:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-right:1em -->
+ <td>
+ <p dir=rtl style="padding-right:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-right:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-right:1em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- text-indent:2em -->
+ <td>
+ <p dir=rtl style="text-indent:2em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="text-indent:2em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="text-indent:2em"><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:left -->
+ <td>
+ <p dir=rtl><xl>A</xl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xl>A</xl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xl>A</xl><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:right -->
+ <td>
+ <p dir=rtl><xr>Z</xr><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xr>Z</xr><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xr>Z</xr><span class=first><span dir=rtl>الخت العربي</span> one ايك two</span><br> دو three تين four</p>
+ </td>
+</tr>
+</table>
diff --git a/testing/web-platform/tests/css/selectors/first-line-bidi-002.html b/testing/web-platform/tests/css/selectors/first-line-bidi-002.html
new file mode 100644
index 0000000000..3d3f0ead8b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-line-bidi-002.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>::first-line selector with bidi content</title>
+<meta name="assert" content="The use of ::first-line should not disrupt bidi layout.">
+<link rel=help href=https://drafts.csswg.org/css-pseudo-4/#first-line-styling>
+<link rel=match href=first-line-bidi-002-ref.html>
+<style>
+body { font: 12px arial, sans-serif; }
+table { font-size: 10px; }
+tr td { margin: 1em 1em; border: 1px solid gray; width: 16em; }
+td:nth-child(1) { text-align: left; }
+td:nth-child(2) { text-align: center; }
+td:nth-child(3) { text-align: right; }
+td p::first-line { color: green; background: pink; }
+th { padding: 1em; }
+td { padding: 2px; }
+td p { margin: 0; }
+xl { float: left; font-size: 2.5em; }
+xr { float: right; font-size: 2.5em; }
+</style>
+<p>In each box, the first-line text should be <span style="color:green; background:pink">green on pink</span>
+and should never project outside the box:</p>
+<!-- Same as first-line-bidi-001 but with dir=rtl on each <p> element -->
+<table>
+<tr><th><code>text-align:left</code></th><th><code>text-align:center</code></th><th><code>text-align:right</code></th></tr>
+<tr>
+ <!-- no padding/indent -->
+ <td>
+ <p dir=rtl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-left:1em -->
+ <td>
+ <p dir=rtl style="padding-left:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-left:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-left:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- padding-right:1em -->
+ <td>
+ <p dir=rtl style="padding-right:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-right:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="padding-right:1em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- text-indent:2em -->
+ <td>
+ <p dir=rtl style="text-indent:2em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="text-indent:2em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl style="text-indent:2em"><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:left -->
+ <td>
+ <p dir=rtl><xl>A</xl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xl>A</xl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xl>A</xl><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+
+<tr>
+ <!-- initial with float:right -->
+ <td>
+ <p dir=rtl><xr>Z</xr><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xr>Z</xr><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+ <td>
+ <p dir=rtl><xr>Z</xr><span dir=rtl>الخت العربي</span> one ايك two<br> دو three تين four</p>
+ </td>
+</tr>
+</table>
diff --git a/testing/web-platform/tests/css/selectors/first-of-type.html b/testing/web-platform/tests/css/selectors/first-of-type.html
new file mode 100644
index 0000000000..b585ed2951
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/first-of-type.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :first-of-type</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-first-of-type-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ See also:
+ * of-type-selectors.html
+ * child-indexed-pseudo-class.html
+ * child-indexed-no-parent.html
+-->
+<body>
+
+<div>
+ <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+ <div id="target2">Thre is another child element of the same type.</div>
+ <div></div>
+</div>
+
+<div>
+ <blockquote></blockquote>
+ <div id="target3">There is a prior child element of another type.</div>
+</div>
+
+<div>
+ <div></div>
+ <blockquote>
+ <div id="target4">A previous element of the parent should not affect.</div>
+ </blockquote>
+</div>
+
+<div>
+ <div>
+ <div id="target5">The parent element of the same type should not affect.</div>
+ </div>
+</div>
+
+<div>
+ <blockquote>
+ <div></div>
+ </blockquote>
+ <div id="target6">A child of the previous element should not affect.</div>
+</div>
+
+<div>
+ <div></div>
+ <div id="target7" data-expected="false">The second child element of the same
+type should not match.</div>
+</div>
+
+<div>
+ <DIV></DIV>
+ <div id="target8" data-expected="false">The second child element of the same
+type should not match, the first child has case-different tag name.</div>
+</div>
+
+<div>
+ <div id="insertBefore1"></div>
+</div>
+
+<script>
+for (let i = 1; i <= 8; ++i) {
+ let target = document.querySelector(`#target${i}`);
+ test(() => {
+ if (target.dataset.expected == 'false')
+ assert_false(target.matches('div:first-of-type'));
+ else
+ assert_true(target.matches('div:first-of-type'));
+ }, target.textContent.replaceAll('\n', ' '));
+}
+
+test(() => {
+ const ib1 = document.querySelector('#insertBefore1');
+ const target = document.createElement('div');
+ assert_true(ib1.matches('div:first-of-type'));
+ ib1.parentNode.insertBefore(target, ib1);
+ assert_true(target.matches('div:first-of-type'));
+ assert_false(ib1.matches('div:first-of-type'));
+
+ target.remove();
+ assert_true(ib1.matches('div:first-of-type'));
+}, 'Dynamic insertion and removal');
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/floating-first-letter-05d0.html b/testing/web-platform/tests/css/selectors/floating-first-letter-05d0.html
new file mode 100644
index 0000000000..68bc77b40f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/floating-first-letter-05d0.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Drop cap with U+05D0 in the document</title>
+<meta name="assert" content="The text placement within :first-line should not be affected by later presence of a right-to-left character.">
+<link rel=help href=https://drafts.csswg.org/css-pseudo-4/#first-line-styling>
+<link rel=match href=floating-first-letter-ref.html>
+<style>
+ p:first-line {
+ background: lightblue;
+ }
+
+ p::first-letter {
+ float: left;
+ font-size: 4rem;
+ }
+ div {
+ color: transparent;
+ }
+</style>
+<p>Ab</p><div>&#x05D0;</div>
diff --git a/testing/web-platform/tests/css/selectors/floating-first-letter-feff.html b/testing/web-platform/tests/css/selectors/floating-first-letter-feff.html
new file mode 100644
index 0000000000..c5cec97fed
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/floating-first-letter-feff.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Drop cap with U+FEFF in the document</title>
+<meta name="assert" content="The text placement within :first-line should not be affected by later presence of U+FEFF.">
+<link rel=help href=https://drafts.csswg.org/css-pseudo-4/#first-line-styling>
+<link rel=match href=floating-first-letter-ref.html>
+<style>
+ p:first-line {
+ background: lightblue;
+ }
+
+ p::first-letter {
+ float: left;
+ font-size: 4rem;
+ }
+</style>
+<p>Ab</p>&#xFEFF;
diff --git a/testing/web-platform/tests/css/selectors/floating-first-letter-ref.html b/testing/web-platform/tests/css/selectors/floating-first-letter-ref.html
new file mode 100644
index 0000000000..3c3141a862
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/floating-first-letter-ref.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Drop cap with no bidi in the document</title>
+<style>
+ p:first-line {
+ background: lightblue;
+ }
+
+ p::first-letter {
+ float: left;
+ font-size: 4rem;
+ }
+</style>
+<p>Ab</p> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/focus-display-none-001.html b/testing/web-platform/tests/css/selectors/focus-display-none-001.html
new file mode 100644
index 0000000000..63bf4465ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-display-none-001.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors Level 4: focus</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-pseudo">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#focus-fixup-rule">
+<meta name="assert" content="Checks ':focus' pseudo-class after 'display: none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="wrapper">
+ <input id="input">
+</div>
+<script>
+ "use strict";
+
+ const wrapper = document.getElementById("wrapper");
+ const input = document.getElementById("input");
+
+ async_test((t) => {
+ input.focus();
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_true(input.matches(":focus"),
+ "Check input matches ':focus' after being focused"));
+
+ input.style.display = "none";
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_false(input.matches(":focus"),
+ "Check input doesn't match ':focus' after getting 'display: none'"));
+ input.style.display = "inline";
+ t.done();
+ });
+ });
+ }, "Test ':focus' after 'display:none' on input");
+
+ async_test((t) => {
+ input.focus();
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_true(input.matches(":focus"),
+ "Check input matches ':focus' after being focused"));
+
+ wrapper.style.display = "none";
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_false(input.matches(":focus"),
+ "Check input doesn't match ':focus' after parent got 'display: none'"));
+ wrapper.style.display = "block";
+ t.done();
+ });
+ });
+ }, "Test ':focus' after 'display:none' on input's parent");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-in-focus-event-001.html b/testing/web-platform/tests/css/selectors/focus-in-focus-event-001.html
new file mode 100644
index 0000000000..01562733e4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-in-focus-event-001.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors Level 4: :focus, :focus-visible and :focus-within in focus event</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-pseudo">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-visible-pseudo">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="help" href="https://w3c.github.io/uievents/#event-type-focus">
+<link rel="help" href="https://crbug.com/523126">
+<meta name='author' title='Takayoshi Kochi' href='mailto:kochi@chromium.org'>
+<meta name='author' title='Manuel Rego Casasnovas' href='mailto:rego@igalia.com'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<input type="text">
+<script>
+var input = document.querySelector('input');
+input.addEventListener('focus', function(e) {
+ test(() => {
+ try {
+ var focusPseudo = document.querySelector(':focus');
+ assert_equals(e.target, focusPseudo, "':focus' matches event.target");
+ } catch (error) {
+ assert_unreached("':focus' is an invalid selector. SyntaxError: " + error);
+ }
+ }, "Checks that ':focus' pseudo-class matches inside 'focus' event handler");
+ test(() => {
+ try {
+ var focusVisiblePseudo = document.querySelector(':focus-visible');
+ assert_equals(e.target, focusVisiblePseudo, "':focus-visible' matches event.target");
+ } catch (error) {
+ assert_unreached("':focus-visible' is an invalid selector. SyntaxError: " + error);
+ }
+ }, "Checks that ':focus-visible' pseudo-class matches inside 'focus' event handler");
+ test(() => {
+ try {
+ var focusWithinPseudo = document.querySelector(':focus-within');
+ assert_equals(document.documentElement, focusWithinPseudo, "':focus-within' matches document.documentElement");
+ } catch (error) {
+ assert_unreached("':focus-within' is an invalid selector. SyntaxError: " + error);
+ }
+ }, "Checks that ':focus-within' pseudo-class matches inside 'focus' event handler");
+}, false);
+input.focus();
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-in-focusin-event-001.html b/testing/web-platform/tests/css/selectors/focus-in-focusin-event-001.html
new file mode 100644
index 0000000000..633f4df87e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-in-focusin-event-001.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors Level 4: :focus, :focus-visible and :focus-within in focusin event</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-pseudo">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-visible-pseudo">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="help" href="https://w3c.github.io/uievents/#event-type-focusin">
+<meta name='author' title='Manuel Rego Casasnovas' href='mailto:rego@igalia.com'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<input type="text">
+<script>
+var input = document.querySelector('input');
+input.addEventListener('focusin', function(e) {
+ test(() => {
+ try {
+ var focusPseudo = document.querySelector(':focus');
+ assert_equals(e.target, focusPseudo, "':focus' matches event.target");
+ } catch (error) {
+ assert_unreached("':focus' is an invalid selector. SyntaxError: " + error);
+ }
+ }, "Checks that ':focus' pseudo-class matches inside 'focusin' event handler");
+ test(() => {
+ try {
+ var focusVisiblePseudo = document.querySelector(':focus-visible');
+ assert_equals(e.target, focusVisiblePseudo, "':focus-visible' matches event.target");
+ } catch (error) {
+ assert_unreached("':focus-visible' is an invalid selector. SyntaxError: " + error);
+ }
+ }, "Checks that ':focus-visible' pseudo-class matches inside 'focusin' event handler");
+ test(() => {
+ try {
+ var focusWithinPseudo = document.querySelector(':focus-within');
+ assert_equals(document.documentElement, focusWithinPseudo, "':focus-within' matches document.documentElement");
+ } catch (error) {
+ assert_unreached("':focus-within' is an invalid selector. SyntaxError: " + error);
+ }
+ }, "Checks that ':focus-within' pseudo-class matches inside 'focusin' event handler");
+}, false);
+input.focus();
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-001.html b/testing/web-platform/tests/css/selectors/focus-visible-001.html
new file mode 100644
index 0000000000..956c91352a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-001.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Keyboard focus enables :focus-visible</title>
+ <link rel="author" title="Rob Dodson" href="robdodson@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+ This test checks that using the Tab key to navigate focus to an element triggers <code>:focus-visible</code> matching.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Use the TAB key on the keyboard to focus the element below that says "Focus me."</li>
+ <li>If the element has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+ </ol>
+ <br>
+ <div id="el" tabindex="0">Focus me.</div>
+ <script>
+ async_test(function(t) {
+ el.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(el).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${el.tagName}#${el.id} should be green`);
+ assert_not_equals(getComputedStyle(el).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${el.tagName}#${el.id} should NOT be red`);
+
+ let focusVisiblePseudoAll = document.querySelectorAll(':focus-visible');
+ assert_equals(focusVisiblePseudoAll.length, 1, "Only 1 element matches ':focus-visible'");
+ let focusVisiblePseudo = document.querySelector(':focus-visible');
+ assert_equals(el, focusVisiblePseudo, "${el.tagName}#${el.id} matches ':focus-visible'");
+ }));
+ const tab_key = '\ue004';
+ test_driver.send_keys(el, tab_key)
+ .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
+ }, "Keyboard focus should match :focus-visible");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-002.html b/testing/web-platform/tests/css/selectors/focus-visible-002.html
new file mode 100644
index 0000000000..850645efe9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-002.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): :focus-visible always matches on texty input elements</title>
+ <meta name="timeout" content="long">
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+ This test checks that <code>:focus-visible</code> always matches on <code>&lt;input&gt;</code> elements which take text input, regardless of focus mechanism.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li><strong>Click</strong> each form element below to focus it.</li>
+ <li>If the element has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+ </ol>
+ <br>
+ <div>
+ <input class="check" id="input1" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input2" type="text" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input3" type="email" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input4" type="password" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input5" type="search" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input6" type="telephone" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input7" type="url" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="input8" type="number" value="10000"></input>
+ </div>
+ <div>
+ <input class="check" id="input9" type="date"></input>
+ </div>
+ <div>
+ <input class="check" id="input10" type="datetime-local"></input>
+ </div>
+ <div>
+ <input class="check" id="input11" type="month"></input>
+ </div>
+ <div>
+ <input class="check" id="input12" type="time"></input>
+ </div>
+ <div>
+ <input class="check" id="input13" type="week"></input>
+ </div>
+ <div>
+ <textarea class="check" id="input14">Focus me.</textarea>
+ </div>
+ <script>
+ setup({ explicit_done: true });
+
+ const elements = document.querySelectorAll(".check");
+ for (let i = 0; i < elements.length; i++) {
+ const target = elements[i];
+ promise_test(() => {
+ return new Promise(resolve => {
+ target.addEventListener("focus", resolve);
+ test_driver.click(target).then(() => {
+ if (i == (elements.length - 1))
+ done();
+ });
+ }).then(() => {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ });
+ }, `Focus element ${target.tagName}#${target.id} via mouse should match :focus-visible as it supports keyboard input`);
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-003.html b/testing/web-platform/tests/css/selectors/focus-visible-003.html
new file mode 100644
index 0000000000..73f8fac55a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-003.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): :focus-visible does not match on non-texty inputs</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: red solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: lime;
+ }
+ </style>
+</head>
+<body>
+ This test checks that <code>:focus-visible</code> is <em>not</em> triggered by mouse focus on <code>&lt;input&gt;</code> elements which do not take text input.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Click each element element below to focus it.</li>
+ <li>If the element has a red outline, then the test result is FAILURE. If the element has a green background, then the test result is SUCCESS.</li>
+ </ol>
+ <br />
+ <div>
+ <span class="check" id="el-1" tabindex="1">Focus me</span>
+ </div>
+ <div>
+ <span class="check" id="el-2" tabindex="-1">Focus me</span>
+ </div>
+ <div>
+ <span class="check" id="el-3" tabindex="0">Focus me</span>
+ </div>
+ <div>
+ <button class="check" id="el-4">Focus me</span>
+ </div>
+ <div>
+ <input class="check" id="el-5" type="button" value="Focus me"></input>
+ </div>
+ <div>
+ <input class="check" id="el-6" type="image" alt="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="el-7" type="reset" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="el-8" type="submit" value="Focus me."></input>
+ </div>
+ <div>
+ <label><input class="check" id="el-9" type="checkbox"></input> Focus me.</label>
+ </div>
+ <div>
+ <label><input class="check" id="el-10" type="radio"></input> Focus me.</label>
+ </div>
+ <div>
+ <!-- Focusing file input triggers a modal, so only test manually -->
+ <input id="el-11" type="file" value="Focus me."></input>
+ </div>
+ <div>
+ <label><input class="check" id="el-12" type="range"></input> Focus me.</label>
+ </div>
+ <div>
+ <!-- Ensure the color input is last, as it has a pop-up which obscures other elements -->
+ <label><input class="check" id="el-13" type="color"></input> Focus me.</label>
+ </div>
+ <script>
+ setup({ explicit_done: true });
+
+ const elements = document.querySelectorAll(".check");
+ for (let i = 0; i < elements.length; i++) {
+ const target = elements[i];
+ promise_test(() => {
+ return new Promise(resolve => {
+ target.addEventListener("focus", resolve);
+ test_driver.click(target).then(() => {
+ if (i == (elements.length - 1))
+ done();
+ });
+ }).then(() => {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ });
+ }, `Focus element ${target.tagName}#${target.id} via mouse should NOT match :focus-visible as it does NOT support keyboard input`);
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-004.html b/testing/web-platform/tests/css/selectors/focus-visible-004.html
new file mode 100644
index 0000000000..075ee83393
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-004.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): :focus-visible does not match on non-texty inputs with appearance: none</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: red solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: lime;
+ }
+
+ .check {
+ -webkit-appearance: none;
+ appearance: none;
+ }
+ </style>
+</head>
+<body>
+ This test checks that <code>:focus-visible</code> is <em>not</em> triggered by mouse focus on <code>&lt;input&gt;</code> elements which do not take text input, even if <code>appearance: none</code> is used.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Click each element element below to focus it.</li>
+ <li>If the element has a red outline, then the test result is FAILURE. If the element has a green background, then the test result is SUCCESS.</li>
+ </ol>
+ <br />
+ <div>
+ <span class="check" id="el-1" tabindex="1">Focus me</span>
+ </div>
+ <div>
+ <span class="check" id="el-2" tabindex="-1">Focus me</span>
+ </div>
+ <div>
+ <span class="check" id="el-3" tabindex="0">Focus me</span>
+ </div>
+ <div>
+ <button class="check" id="el-4">Focus me</span>
+ </div>
+ <div>
+ <input class="check" id="el-5" type="button" value="Focus me"></input>
+ </div>
+ <div>
+ <input class="check" id="el-6" type="image" alt="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="el-7" type="reset" value="Focus me."></input>
+ </div>
+ <div>
+ <input class="check" id="el-8" type="submit" value="Focus me."></input>
+ </div>
+ <div>
+ <!-- Focusing file input triggers a modal, so only test manually -->
+ <input id="el-9" type="file" value="Focus me."></input>
+ </div>
+ <div>
+ <label><input class="check" id="el-10" type="range"></input> Focus me.</label>
+ </div>
+ <div>
+ <!-- Ensure the color input is last, as it has a pop-up which obscures other elements -->
+ <label><input class="check" id="el-11" type="color"></input> Focus me.</label>
+ </div>
+ <script>
+ setup({ explicit_done: true });
+
+ const elements = document.querySelectorAll(".check");
+ for (let i = 0; i < elements.length; i++) {
+ const target = elements[i];
+ promise_test(() => {
+ return new Promise(resolve => {
+ target.addEventListener("focus", resolve);
+ test_driver.click(target).then(() => {
+ if (i == (elements.length - 1))
+ done();
+ });
+ }).then(() => {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ });
+ }, `Focus element ${target.tagName}#${target.id} via mouse should NOT match :focus-visible as it does NOT support keyboard input - not affected by "appearance: none"`);
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-005.html b/testing/web-platform/tests/css/selectors/focus-visible-005.html
new file mode 100644
index 0000000000..a678261f69
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-005.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Programmatic focus causes :focus-visible to match</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: red solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: lime;
+ }
+ </style>
+</head>
+<body>
+ This test checks that programmatically focusing an element after a click does not cause <code>:focus-visible</code> matching to trigger.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Click the button below that says "Click me."</li>
+ <li>If the element that says "I will be focused programmatically." has a red outline, then the test result is FAILURE. If the element has a green background, then the test result is SUCCESS.</li>
+ </ol>
+ <br />
+ <button id="button">Click me.</button>
+ <div id="el" tabindex="-1">I will be focused programmatically.</div>
+ <script>
+ button.addEventListener("click", () => {
+ el.focus();
+ });
+ async_test(function(t) {
+ el.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(el).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${el.tagName}#${el.id} should be lime`);
+ assert_not_equals(getComputedStyle(el).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${el.tagName}#${el.id} should NOT be red`);
+ t.done();
+ }));
+ test_driver.click(button);
+ }, "Programmatic focus after click should not match :focus-visible");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-006.html b/testing/web-platform/tests/css/selectors/focus-visible-006.html
new file mode 100644
index 0000000000..4008755ce2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-006.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): contenteditable elements always match :focus-visible</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ span[contenteditable] {
+ border: 1px solid black;
+ background-color: white;
+ padding: 2px 5px;
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+ This test checks that <code>:focus-visible</code> always matches on elements with <code>contenteditable=true</code> set.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li><strong>Click</strong> the content editable span below to focus it.</li>
+ <li>If the element has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+ </ol>
+ <br />
+ <div>
+ <span id="el" contenteditable>Focus me</span>
+ </div>
+ <script>
+ var actions_promise;
+
+ async_test(function(t) {
+ el.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(el).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${el.tagName}#${el.id} should be green`);
+ assert_not_equals(getComputedStyle(el).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${el.tagName}#${el.id} should NOT be red`);
+ // Make sure the test finishes after all the input actions are completed.
+ actions_promise.then( () => t.done() );
+ }));
+
+ actions_promise = test_driver.click(el);
+ }, "Focus should always match :focus-visible on content editable divs");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-007.html b/testing/web-platform/tests/css/selectors/focus-visible-007.html
new file mode 100644
index 0000000000..149a6f68fe
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-007.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Keyboard use triggers :focus-visible</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ [data-hadkeydown] :focus-visible {
+ outline: green solid 5px;
+ }
+
+ [data-hadmousedown] :focus-visible {
+ outline: red solid 5px;
+ }
+
+ [data-hadkeydown] :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: red;
+ }
+
+ [data-hadmousedown] :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: lime;
+ }
+
+ </style>
+</head>
+<body>
+ This test checks that using the keyboard in a way that does not move focus still causes <code>:focus-visible</code> matching to trigger.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Use the mouse to focus the element below that says "Click me."</li>
+ <li>If the element has a red outline, then the test result is FAILURE.</li>
+ <li>Press the ENTER key.</li>
+ <li>If the element now has a green outline and not red background, then the test result is SUCCESS.</li>
+ </ol>
+
+ <div id="one" tabindex="0">Click me.</div>
+ <script>
+ setup({ explicit_done: true });
+
+ document.body.addEventListener("keydown", (e) => {
+ delete document.body.dataset.hadmousedown;
+ document.body.dataset.hadkeydown = "";
+ }, true);
+
+ document.body.addEventListener("mousedown", (e) => {
+ delete document.body.dataset.hadkeydown;
+ document.body.dataset.hadmousedown = "";
+ }, true);
+
+ async_test(function(t) {
+ let tested_initial_focus = false;
+
+ const handle_initial_focus = t.step_func(() => {
+ tested_initial_focus = true;
+ assert_equals(getComputedStyle(one).backgroundColor, "rgb(0, 255, 0)");
+ assert_not_equals(getComputedStyle(one).outlineColor, "rgb(255, 0, 0)");
+
+ one.addEventListener("keyup", t.step_func(test_modality_change));
+ one.removeEventListener("focus", handle_initial_focus);
+
+ const enter = "\uE007";
+ test_driver.send_keys(one, enter);
+ });
+
+ const test_modality_change = t.step_func(() => {
+ assert_true(tested_initial_focus);
+ one.removeEventListener("keyup", test_modality_change);
+ assert_equals(getComputedStyle(one).outlineColor, "rgb(0, 128, 0)");
+ assert_not_equals(getComputedStyle(one).backgroundColor, "rgb(255, 0, 0)");
+ t.done();
+ });
+
+ one.addEventListener("focus", handle_initial_focus);
+ test_driver.click(one).then(() => done());
+ }, "Using keyboard while element is focused should trigger :focus-visible; using mouse without moving focus should not cancel it; moving focus using mouse should cancel it.");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-008.html b/testing/web-platform/tests/css/selectors/focus-visible-008.html
new file mode 100644
index 0000000000..6fc5b478a8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-008.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Keyboard focus enables :focus-visible</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ #el:focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ #el:focus:not(:focus-visible) {
+ background-color: red;
+ outline: 0;
+ }
+ </style>
+</head>
+<body>
+ This test checks that programmatically focusing an element after a keypress causes <code>:focus-visible</code> to match.
+ <ol id="instructions">
+ <li>Use the tab key to move focus to the button below that says "Tab to me and press ENTER."</li>
+ <li>Press ENTER.</li>
+ <li>If the element that says "I will be focused programmatically." has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+ </ol>
+ <br />
+ <button id="button">Tab to me and press ENTER.</button>
+ <div id="el" tabindex="-1">I will be focused programmatically.</div>
+ <script>
+ if ("async_test" in window) {
+ async_test(function(t) {
+ button.addEventListener("click", t.step_func(() => {
+ el.focus();
+ }));
+ el.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(el).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${el.tagName}#${el.id} should be green`);
+ assert_not_equals(getComputedStyle(el).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${el.tagName}#${el.id} should NOT be red`);
+ t.done();
+ }));
+ test_driver.send_keys(el, "\ue004\ue007"); // TAB and ENTER
+ }, "Programmatic focus after keypress should match :focus-visible");
+ } else {
+ button.addEventListener("click", () => {
+ el.focus();
+ });
+ }
+
+ const tab_key = '\ue004';
+ const enter_key = '\uE007';
+ test_driver.send_keys(el, tab_key).then(() => {
+ test_driver.send_keys(el, enter_key);
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-009.html b/testing/web-platform/tests/css/selectors/focus-visible-009.html
new file mode 100644
index 0000000000..fcb70f2e35
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-009.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Keyboard focus enables :focus-visible</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/html/interaction/focus/the-autofocus-attribute/resources/utils.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ #button:focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ #button:focus:not(:focus-visible) {
+ background-color: red;
+ outline: 0;
+ }
+ </style>
+</head>
+<body>
+ This test checks that any element focused via an <code>autofocus</code> attribute will have <code>:focus-visible</code> matching enabled.
+ <ul id="instructions">
+ <li>If the button that says "I will be focused automatically" has a red background, then the test result is FAILURE. If it has a green outline, then the test result is SUCCESS.</li>
+ </ul>
+ <br />
+ <button id="button" autofocus tabindex="-1">I will be focused automatically.</button>
+ <script>
+ promise_test(async function() {
+ await waitUntilStableAutofocusState();
+ assert_equals(document.activeElement, button, "Should have correct focused element");
+ assert_equals(getComputedStyle(button).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${button.tagName}#${button.id} should be green`);
+ assert_not_equals(getComputedStyle(button).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${button.tagName}#${button.id} should NOT be red`);
+ }, "Autofocus should match :focus-visible");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-010.html b/testing/web-platform/tests/css/selectors/focus-visible-010.html
new file mode 100644
index 0000000000..ada14d63ee
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-010.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Keyboard focus enables :focus-visible</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ outline: 0;
+ }
+ </style>
+</head>
+<body>
+ This test checks that any element focused programmatically on page load will have <code>:focus-visible</code> matching enabled.
+ <ul id="instructions">
+ <li>If the element that says "I will be focused automatically" has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+ </ul>
+ <br />
+ <div id="el" tabindex="-1">I will be focused automatically.</div>
+ <script>
+ window.addEventListener('load', () => {
+ el.focus();
+ });
+
+ async_test(function(t) {
+ el.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(el).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${el.tagName}#${el.id} should be green`);
+ assert_not_equals(getComputedStyle(el).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${el.tagName}#${el.id} should NOT be red`);
+ t.done();
+ }));
+ }, "Programmatic focus on page load should match :focus-visible");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-011.html b/testing/web-platform/tests/css/selectors/focus-visible-011.html
new file mode 100644
index 0000000000..b9dc10bee7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-011.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): :focus-visible matches even if preventDefault() is called</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ #next:focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ button {
+ border: 0;
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ outline: 0;
+ }
+ </style>
+</head>
+<body>
+ This test checks that <code>:focus-visible</code> matches after a keyboard event,
+ even if the event handler calls preventDefault() on the event.
+ <ul id="instructions">
+ <li>Click "Click here and press right arrow.".</li>
+ <li>Press the right arrow key.</li>
+ <li>If the element has a red background, then the test result is FAILURE.
+ If it has a green outline, then the test result is SUCCESS.</li>
+ </ul>
+ <br />
+ <div id="target" tabindex="0">Click here and press right arrow.</div>
+ <script>
+ target.addEventListener("keydown", (e) => {
+ e.preventDefault();
+ });
+ target.addEventListener("keyup", (e) => {
+ e.preventDefault();
+ });
+ target.addEventListener("keypress", (e) => {
+ e.preventDefault();
+ });
+ async_test(function(t) {
+ target.addEventListener("focus", () => {
+ const arrow_right = "\ue014";
+ test_driver.send_keys(target, arrow_right);
+ });
+
+ target.addEventListener("keyup", t.step_func_done((e) => {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(target);
+ }, ":focus-visible matches even if preventDefault() is called");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-012.html b/testing/web-platform/tests/css/selectors/focus-visible-012.html
new file mode 100644
index 0000000000..fab6cc82b9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-012.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): Keyboard shortcut combinations do not trigger :focus-visible</title>
+ <link rel="author" title="Alice Boxhall" href="aboxhall@chromium.org" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-actions.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ outline: 0;
+ outline-color: red;
+ background-color: red;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: green solid 5px;
+ }
+ </style>
+</head>
+<body>
+ This test checks that using keyboard combinations with [Ctrl], [Alt] or [Cmd]
+ do not trigger <code>:focus-visible</code> matching.
+ <ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Click the element below that says "Click me, then use a keyboard shortcut."</li>
+ <li>Press a keyboard combination including [Ctrl], [Alt] or [Cmd], such as <code>Ctrl</code> + <code>y</code></li>
+ <li>If the element has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+ </ol>
+ <br>
+ <div id="el" tabindex="0">Click me, then use a keyboard shortcut.</div>
+ <script>
+ var t = async_test( "Keyboard focus should match :focus-visible");
+
+ el.addEventListener("click", t.step_func(function(e) {
+ assert_equals(getComputedStyle(el).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${el.tagName}#${el.id} should be green`);
+ assert_not_equals(getComputedStyle(el).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${el.tagName}#${el.id} should NOT be red`);
+ }), true);
+
+ el.addEventListener("keydown", t.step_func(function(e) {
+ if (e.altKey || e.ctrlKey || e.metaKey) {
+ assert_equals(getComputedStyle(el).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${el.tagName}#${el.id} should be green`);
+ assert_not_equals(getComputedStyle(el).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${el.tagName}#${el.id} should NOT be red`);
+ t.done();
+ return;
+ }
+ assert_true(false, "No modifier key");
+ t.done();
+ }));
+
+ const ctrl_key = '\uE009';
+ test_driver.click(el).then(() => {
+ return test_driver.send_keys(el, ctrl_key);
+ });
+
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-013.html b/testing/web-platform/tests/css/selectors/focus-visible-013.html
new file mode 100644
index 0000000000..f79b704d39
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-013.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Test: :focus-visible does not match after mouse focus even if previous focused element was matching :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ }
+ }
+
+ #initial:focus-visible {
+ outline: green solid 5px;
+ }
+
+ #initial:focus:not(:focus-visible) {
+ outline: red solid 5px;
+ }
+
+ #target:focus-visible {
+ outline: red solid 5px;
+ }
+
+ #target:focus:not(:focus-visible) {
+ outline: green solid 5px;
+ }
+</style>
+
+<p>This test checks that if the active element matches ':focus-visible' and a mouse click causes focus to move elsewhere, the newly focused element should not match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>If the user-agent does not claim to support the <code>:focus-visible</code> pseudo-class then SKIP this test.</li>
+ <li>Press the TAB key.</li>
+ <li>If the element that says "Initial" has a red outline, then the test rsult is a FAILURE.</li>
+ <li>Use the mouse to focus the element below that says "Target".</li>
+ <li>If the element that says "Target" has a green outline, then the test result is a SUCCESS.</li>
+</ol>
+
+<div id="initial" tabindex="0">Initial</div>
+<div id="target" tabindex="0">Target</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ async_test(function(t) {
+ initial.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(initial).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${initial.tagName}#${initial.id} should be green`);
+ test_driver.click(target).then(() => done());
+ }));
+
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ }));
+
+ const tab_key = '\ue004';
+ test_driver.send_keys(document.body, tab_key);
+ }, ":focus-visible does not match after mouse click even if previous focused element was matching :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-014.html b/testing/web-platform/tests/css/selectors/focus-visible-014.html
new file mode 100644
index 0000000000..1b80c66694
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-014.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Test: :focus-visible matches after script focus move</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<meta name="assert" content="This test checks that if the active element matches ':focus-visible' and a script causes focus to move elsewhere, the newly focused element should match ':focus-visible'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ background: lime;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<input id="input"></input>
+<div id="target" tabindex="0">Target</div>
+
+<script>
+ async_test(function(t) {
+ input.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(input).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${input.tagName}#${input.id} should be lime`);
+ target.focus();
+ }));
+
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ t.done();
+ }));
+
+ input.focus();
+ }, ":focus-visible matches after script focus move");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-015.html b/testing/web-platform/tests/css/selectors/focus-visible-015.html
new file mode 100644
index 0000000000..323dec3e7a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-015.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Test: :focus-visible does not match after script focus move</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<meta name="assert" content="This test checks that if the active element does not match ':focus-visible' and a script causes focus to move elsewhere, the newly focused element should not match ':focus-visible'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ :focus-visible {
+ background: red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<div id="initial" tabindex="0">Initial</div>
+<div id="target" tabindex="0">Target</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ async_test(function(t) {
+ initial.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(initial).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${initial.tagName}#${initial.id} should be lime`);
+ target.focus();
+ }));
+
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ t.done();
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, ":focus-visible does not match after script focus move");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-016.html b/testing/web-platform/tests/css/selectors/focus-visible-016.html
new file mode 100644
index 0000000000..1b8beaa733
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-016.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Test: :focus-visible always match on text inputs</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<meta name="assert" content="This test checks that even if the active element does not match ':focus-visible' and a script causes focus to move into a text input, the text input should match ':focus-visible'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ @supports not selector(:focus-visible) {
+ :focus {
+ outline: red solid 5px;
+ background-color: red;
+ }
+ }
+
+ div:focus-visible {
+ background: red;
+ }
+
+ div:focus:not(:focus-visible) {
+ background-color: lime;
+ }
+
+ input:focus-visible {
+ background: lime;
+ }
+
+ input:focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<div id="initial" tabindex="0">Initial</div>
+<input id="target" />
+
+<script>
+ setup({ explicit_done: true });
+
+ async_test(function(t) {
+ initial.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(initial).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${initial.tagName}#${initial.id} should be lime`);
+ target.focus();
+ }));
+
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ t.done();
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, ":focus-visible always match on text inputs");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-017-2.html b/testing/web-platform/tests/css/selectors/focus-visible-017-2.html
new file mode 100644
index 0000000000..bf9ac86c50
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-017-2.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): By default programatic focus matches :focus-visible and it shows an auto focus ring</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<link rel="help" href="https://html.spec.whatwg.org/#phrasing-content-3" />
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+</style>
+
+<p>This test checks that by default, if using JavaScript to focus an element triggers <code>:focus-visible</code> matching, then the element should show a focus ring with <code>outline-style: auto</code>.</p>
+<ol id="instructions">
+ <li>Focus the following elements with the keyaboard navigation (pressing TAB), if the elements show a focus ring with <code>outline-style: auto</code>, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<abbr tabindex="0">abbr</abbr>
+<address tabindex="0">address</address>
+<a href="#">a</a>
+<bdi tabindex="0">bdi</bdi>
+<blockquote tabindex="0">blockquote</blockquote>
+<code tabindex="0">code</code>
+<dd tabindex="0">dd</dd>
+<details open><summary tabindex="0">summary</summary></details>
+<details tabindex="0"></details>
+<div tabindex="0">div</div>
+<dl tabindex="0">dl</dl>
+<dt tabindex="0">dt</dt>
+<em tabindex="0">em</em>
+<fieldset><legend tabindex="0">legend</legend></fieldset>
+<figcaption tabindex="0">figcaption</figcaption>
+<figure tabindex="0">figure</figure>
+<form tabindex="0">form</form>
+<hr tabindex="0" />
+<img tabindex="0" src="/images/green.png" />
+<label tabindex="0">label</label>
+<li tabindex="0">li</li>
+<mark tabindex="0">mark</mark>
+<meter tabindex="0"></meter>
+<ol tabindex="0">ol</ol>
+<pre tabindex="0">pre</pre>
+<progress tabindex="0"></progress>
+<p tabindex="0">p</p>
+<small tabindex="0">small</small>
+<s tabindex="0">s</s>
+<strong tabindex="0">strong</strong>
+<sub tabindex="0">sub</sub>
+<sup tabindex="0">sup</sup>
+<table><caption tabindex="0">caption</caption></table>
+<table tabindex="0"><td>table</td></table>
+<table><td tabindex="0">td</td></table>
+<time tabindex="0">time</time>
+<ul tabindex="0">ul</ul>
+<u tabindex="0">u</u>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ const elements = document.querySelectorAll("[tabindex]");
+ for (let i = 0; i < elements.length; i++) {
+ const target = elements[i];
+ promise_test(() => {
+ return new Promise(resolve => {
+ target.addEventListener("focus", resolve);
+ target.focus();
+ if (i == (elements.length - 1))
+ done();
+ }).then(() => {
+ assert_equals(getComputedStyle(target).outlineStyle, "auto", `outline-style for ${target.tagName} should be auto`);
+ });
+ }, `By default initial programatic focus matches ':focus-visible', so the element ${target.tagName} shows a focus ring with 'outline-style: auto'`);
+ }
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-017.html b/testing/web-platform/tests/css/selectors/focus-visible-017.html
new file mode 100644
index 0000000000..4ee00612a3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-017.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): By default initial programatic focus matches :focus-visible and it shows an auto focus ring</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<link rel="help" href="https://html.spec.whatwg.org/#phrasing-content-3" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+</style>
+
+<p>This test checks that by default, if using JavaScript to focus an element triggers <code>:focus-visible</code> matching, then the element should show a focus ring with <code>outline-style: auto</code>.</p>
+<ol id="instructions">
+ <li>If the element below that says "Target" show a focus ring with <code>outline-style: auto</code>, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+<div id="target" tabindex="0">Target</div>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).outlineStyle, "auto", `outline-style for ${target.tagName}#${target.id} should be auto`);
+ t.done();
+ }));
+ target.focus();
+ }, "By default initial programatic focus matches ':focus-visible', so the element shows a focus ring with 'outline-style: auto'");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-018-2.html b/testing/web-platform/tests/css/selectors/focus-visible-018-2.html
new file mode 100644
index 0000000000..5481b56c26
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-018-2.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Mouse focus does not show a focus ring by default</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<link rel="help" href="https://html.spec.whatwg.org/#phrasing-content-3" />
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+</style>
+
+<p>This test checks that by default, using the mouse to focus a generic element does not show a focus ring (because it does not trigger <code>:focus-visible</code> matching).</p>
+<ol id="instructions">
+ <li>Click on the elements below"</li>
+ <li>If the elements do not have a focus ring, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<abbr tabindex="0">abbr</abbr>
+<address tabindex="0">address</address>
+<a href="#">a</a>
+<bdi tabindex="0">bdi</bdi>
+<blockquote tabindex="0">blockquote</blockquote>
+<code tabindex="0">code</code>
+<dd tabindex="0">dd</dd>
+<details open><summary tabindex="0">summary</summary></details>
+<details tabindex="0"></details>
+<div tabindex="0">div</div>
+<dl tabindex="0">dl</dl>
+<dt tabindex="0">dt</dt>
+<em tabindex="0">em</em>
+<fieldset><legend tabindex="0">legend</legend></fieldset>
+<figcaption tabindex="0">figcaption</figcaption>
+<figure tabindex="0">figure</figure>
+<form tabindex="0">form</form>
+<hr tabindex="0" />
+<img tabindex="0" src="/images/green.png" />
+<label tabindex="0">label</label>
+<li tabindex="0">li</li>
+<mark tabindex="0">mark</mark>
+<meter tabindex="0"></meter>
+<ol tabindex="0">ol</ol>
+<pre tabindex="0">pre</pre>
+<progress tabindex="0"></progress>
+<p tabindex="0">p</p>
+<small tabindex="0">small</small>
+<s tabindex="0">s</s>
+<strong tabindex="0">strong</strong>
+<sub tabindex="0">sub</sub>
+<sup tabindex="0">sup</sup>
+<table><caption tabindex="0">caption</caption></table>
+<table tabindex="0"><td>table</td></table>
+<table><td tabindex="0">td</td></table>
+<time tabindex="0">time</time>
+<ul tabindex="0">ul</ul>
+<u tabindex="0">u</u>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ const elements = document.querySelectorAll("[tabindex]");
+ for (let i = 0; i < elements.length; i++) {
+ const target = elements[i];
+ promise_test(() => {
+ return new Promise(resolve => {
+ target.addEventListener("focus", resolve);
+ test_driver.click(target).then(() => {
+ if (i == (elements.length - 1))
+ done();
+ }).catch(resolve);
+ }).then(() => {
+ assert_equals(getComputedStyle(target).outlineStyle, "none", `outline-style for ${target.tagName} should be none`);
+ });
+ }, `Mouse focus does not show a focus ring by default in element ${target.tagName}`);
+ }
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-018.html b/testing/web-platform/tests/css/selectors/focus-visible-018.html
new file mode 100644
index 0000000000..80a38d0048
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-018.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Mouse focus does not show a focus ring by default</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+</style>
+
+<p>This test checks that by default, using the mouse to focus a generic element does not show a focus ring (because it does not trigger <code>:focus-visible</code> matching).</p>
+<ol id="instructions">
+ <li>Click on the element below that says "Click me."</li>
+ <li>If the element does not have a focus ring, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+<div id="target" tabindex="0">Click me.</div>
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).outlineStyle, "none", `outline-style for ${target.tagName}#${target.id} should be none`);
+ t.done();
+ }));
+ test_driver.click(target).then(() => done());
+ }, "Mouse focus does not show a focus ring by default");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-019.html b/testing/web-platform/tests/css/selectors/focus-visible-019.html
new file mode 100644
index 0000000000..a32ff4df54
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-019.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus on keyboard event handler matches :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: green solid 5px;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: 0;
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that changing focus via script on keyboard event handler matches <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Type any letter with the keyboard without having done anything before.</li>
+ <li>If the element that says "Focused" has a red background, then the test result is FAILURE. If the element has a green outline, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+<div id="target" tabindex="0">Focused.</div>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ document.addEventListener("keydown", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ test_driver.send_keys(document.body, "a").then(t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+
+ let focusVisiblePseudoAll = document.querySelectorAll(':focus-visible');
+ assert_equals(focusVisiblePseudoAll.length, 1, "Only 1 element matches ':focus-visible'");
+ let focusVisiblePseudo = document.querySelector(':focus-visible');
+ assert_equals(target, focusVisiblePseudo, "${target.tagName}#${target.id} matches ':focus-visible'");
+ }));
+ }, "Focus via script on keyboard event handler matches ':focus-visible'");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-020.html b/testing/web-platform/tests/css/selectors/focus-visible-020.html
new file mode 100644
index 0000000000..f021938d3b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-020.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): :focus-visible doesn't match on ShadowRoot</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ #host:focus-visible {
+ outline: 0;
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that <code>:focus-visible</code> doesn't math on ShadowRoot.</p>
+<ol id="instructions">
+ <li>The input should be focused on load, if it's not focused, focus it via mouse or keyboard.</li>
+ <li>If you see no red the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="host" style="height: 100px;"></div>
+
+<script>
+ const shadowRoot = host.attachShadow({mode: 'open', delegatesFocus: true});
+ shadowRoot.innerHTML = '<input id="target" autofocus value="Focus me">';
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ async_test((t) => {
+ host.focus();
+ window.requestAnimationFrame(t.step_func_done(() => {
+ assert_not_equals(getComputedStyle(host).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${host.tagName}#${host.id} should NOT be red`);
+
+ let focusVisiblePseudoAll = document.querySelectorAll(':focus-visible');
+ assert_equals(focusVisiblePseudoAll.length, 0, "No element matches ':focus-visible'");
+
+ let focusVisibleShadowDOMPseudoAll = shadowRoot.querySelectorAll(':focus-visible');
+ assert_equals(focusVisibleShadowDOMPseudoAll.length, 1, "Only one element matches ':focus-visible' in the Shadow DOM");
+
+ let target = shadowRoot.getElementById("target");
+ assert_equals(target, focusVisibleShadowDOMPseudoAll[0], "${target.tagName}#${target.id} matches ':focus-visible'");
+ }));
+ }, ":focus-visible doesn't match on ShadowRoot");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-021.html b/testing/web-platform/tests/css/selectors/focus-visible-021.html
new file mode 100644
index 0000000000..aa2df6a350
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-021.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Modifier key doesn't make element to stop matching :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ outline: none;
+ background-color: red;
+ }
+</style>
+
+This test checks that using a modifier key does not make the element to stop matching <code>:focus-visible</code>.
+<ol id="instructions">
+ <li>If the element that says "Focused" has a red background, then the test result is a FAILURE.</li>
+ <li>Press the Ctrl key.</li>
+ <li>If the element keeps the green outline and has not a red background, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func(() => {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+
+ const ctrl_key = '\uE009';
+ test_driver.send_keys(target, ctrl_key);
+ }));
+
+ target.addEventListener("keyup", t.step_func_done(() => {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ }, "Ctrl key doesn't make an element to stop matching :focus-visible");
+
+ target.focus();
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-022.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-022.tentative.html
new file mode 100644
index 0000000000..e2692a6bec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-022.tentative.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1711057">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<div id="one" tabindex="1">One</div>
+<div id="two" tabindex="1">Two</div>
+
+<script>
+let one = document.getElementById("one");
+let two = document.getElementById("two");
+
+document.addEventListener("keydown", function(e) {
+ two.focus();
+});
+
+promise_test(async t => {
+ await test_driver.click(one);
+ assert_equals(document.activeElement, one, "#one should be focused by mouse");
+ assert_true(one.matches(":focus"), "#one should match :focus");
+ assert_true(!one.matches(":focus-visible"), "#one should not match :focus-visible");
+
+ await test_driver.send_keys(document.body, " ");
+
+ assert_equals(document.activeElement, two, "#two should be focused by our event listener");
+ assert_true(two.matches(":focus"), "#two should match :focus");
+ assert_true(two.matches(":focus-visible"), "#two should match :focus-visible");
+});
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-023.html b/testing/web-platform/tests/css/selectors/focus-visible-023.html
new file mode 100644
index 0000000000..a90bb07b72
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-023.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Element doesn't match :focus-visiblel after blur</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ :focus-visible {
+ outline: green solid 5px;
+ }
+</style>
+
+<div id="target" tabindex="0">Target</div>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).outlineStyle, "solid", `outline-style for ${target.tagName}#${target.id} should be solid`);
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ target.blur();
+ }));
+ target.addEventListener("blur", t.step_func(function() {
+ assert_equals(getComputedStyle(target).outlineStyle, "none", `outline-style for ${target.tagName}#${target.id} should be none`);
+ t.done();
+ }));
+ target.focus();
+ }, ":focus-visible stop matching after blur");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-024.html b/testing/web-platform/tests/css/selectors/focus-visible-024.html
new file mode 100644
index 0000000000..e64525a177
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-024.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Element matches :focus-visiblel after accesskey</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<meta name="assert" content="This test checks that :focus-visible matches after focusing an element using accesskey.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/accesskey.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ :focus-visible {
+ outline: green solid 5px;
+ }
+</style>
+
+<div id="targetA" tabindex="0" accesskey="a">Target A</div>
+<button id="targetB" tabindex="0" accesskey="b">Target B</button>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ promise_test(async t => {
+ await pressAccessKey("a");
+ assert_equals(getComputedStyle(targetA).outlineStyle, "solid", `outline-style for ${targetA.tagName}#${targetA.id} should be solid`);
+ assert_equals(getComputedStyle(targetA).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${targetA.tagName}#${targetA.id} should be green`);
+ t.done();
+ }, ":focus-visible matches after accesskey on DIV");
+
+ promise_test(async t => {
+ await pressAccessKey("b");
+ assert_equals(getComputedStyle(targetB).outlineStyle, "solid", `outline-style for ${targetB.tagName}#${targetB.id} should be solid`);
+ assert_equals(getComputedStyle(targetB).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${targetB.tagName}#${targetB.id} should be green`);
+ t.done();
+ }, ":focus-visible matches after accesskey on BUTTON");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-025.html b/testing/web-platform/tests/css/selectors/focus-visible-025.html
new file mode 100644
index 0000000000..6492038685
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-025.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Element matches :focus-visiblel after accesskey after previous mouse focus</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<meta name="assert" content="This test checks that :focus-visible matches after focusing an element using accesskey, even when previously another element has been focused by mouse click.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/accesskey.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ :focus-visible {
+ outline: green solid 5px;
+ }
+</style>
+
+<div id="initial" tabindex="0">Initial</div>
+<div id="targetA" tabindex="0" accesskey="a">Target A</div>
+<button id="targetB" tabindex="0" accesskey="b">Target B</button>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ promise_test(async t => {
+ await test_driver.click(initial);
+ assert_equals(getComputedStyle(initial).outlineStyle, "none", `outline-style for ${initial.tagName}#${initial.id} should be none`);
+
+ await pressAccessKey("a");
+ assert_equals(getComputedStyle(targetA).outlineStyle, "solid", `outline-style for ${targetA.tagName}#${targetA.id} should be solid`);
+ assert_equals(getComputedStyle(targetA).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${targetA.tagName}#${targetA.id} should be green`);
+ t.done();
+ }, ":focus-visible matches after accesskey on DIV after previous mouse focus");
+
+ promise_test(async t => {
+ await test_driver.click(initial);
+ assert_equals(getComputedStyle(initial).outlineStyle, "none", `outline-style for ${initial.tagName}#${initial.id} should be none`);
+
+ await pressAccessKey("b");
+ assert_equals(getComputedStyle(targetB).outlineStyle, "solid", `outline-style for ${targetB.tagName}#${targetB.id} should be solid`);
+ assert_equals(getComputedStyle(targetB).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${targetB.tagName}#${targetB.id} should be green`);
+ t.done();
+ }, ":focus-visible matches after accesskey on BUTTON after previous mouse focus");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-026.html b/testing/web-platform/tests/css/selectors/focus-visible-026.html
new file mode 100644
index 0000000000..718d1c0ecb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-026.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Checkbox doesn't match :focus-visiblel after click on label</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<meta name="assert" content="This test checks that :focus-visible does NOT match when a checkbox is focused because an associated label has been clicked.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/accesskey.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ :focus-visible {
+ outline: red solid 5px;
+ }
+</style>
+<input type="checkbox" id="checkbox">
+<label for="checkbox" id="label">label</label>
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ promise_test(async t => {
+ await test_driver.click(label);
+ assert_equals(getComputedStyle(checkbox).outlineStyle, "none", `outline-style for ${checkbox.tagName}#${checkbox.id} should be none`);
+ t.done();
+ }, ":focus-visible does NOT match when a checkbox is focused via click on the associated label");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-027.html b/testing/web-platform/tests/css/selectors/focus-visible-027.html
new file mode 100644
index 0000000000..b4e7117f06
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-027.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test (Selectors): :focus-visible after click and input type change</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1788698">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<input type="button" value="+">
+<script>
+ let input = document.querySelector("input");
+ input.addEventListener("click", function(e) {
+ if (this.type != "button") {
+ return;
+ }
+ this.value = "";
+ this.type = "text";
+ });
+ promise_test(async function() {
+ await test_driver.click(input);
+ assert_equals(input.type, "text");
+ assert_equals(input.matches(":focus"), input.matches(":focus-visible"), "Type change to text might cause :focus-visible to start matching");
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-001.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-001.html
new file mode 100644
index 0000000000..df6d9158b7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-001.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus without any previous user interaction matches :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus when the user hasn't interacted with the page yet, always matches <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+ }, "Script focus without any previous user interaction matches :focus-visible");
+
+ target.focus();
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-002.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-002.tentative.html
new file mode 100644
index 0000000000..e04dc30d49
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-002.tentative.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click in some part of the page other than the element that says "Focused".</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ document.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(document.body).then(() => done());
+ }, "Script focus after mouse click does match :focus-visible");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-003.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-003.tentative.html
new file mode 100644
index 0000000000..a1f772e83b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-003.tentative.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after mouse click does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a mouse click does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click in some part of the page other than the element that says "Focused".</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ document.addEventListener("click", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(document.body).then(() => done());
+ }, "Script focus after blur after mouse click does match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-004.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-004.html
new file mode 100644
index 0000000000..22e2e1e84f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-004.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after keyboard input does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after a keyboard input does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Type some letter with the keyboard without having done anything before.</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ document.addEventListener("keypress", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.send_keys(document.body, "a");
+ }, "Script focus after keyboard event does match :focus-visible");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-005.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-005.html
new file mode 100644
index 0000000000..cdd50c523b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-005.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after keyboard input does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a keyboard input does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Type some letter with the keyboard without having done anything before.</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ document.addEventListener("keypress", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.send_keys(document.body, "a");
+ }, "Script focus after blur after keyboard event does match :focus-visible");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-006.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-006.tentative.html
new file mode 100644
index 0000000000..e2f2e4bc44
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-006.tentative.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click on a NOT focusable element does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click on a NOT focusable element does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after mouse click on a NOT focusable element does match :focus-visible");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-007.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-007.tentative.html
new file mode 100644
index 0000000000..2b7e7bf0a1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-007.tentative.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after mouse click on a NOT focusable element does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a mouse click on a NOT focusable element does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after blur after mouse click on a NOT focusable element does match :focus-visible");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-008-b.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-008-b.html
new file mode 100644
index 0000000000..4ea414f343
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-008-b.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click on a button that does not match :focus-visible, does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click on a button that does not match <code>:focus visible</code>, does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the button that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<button id="initial">Click me</button>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after mouse click on a button that does not match :focus-visible, does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-008.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-008.html
new file mode 100644
index 0000000000..b0db185d86
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-008.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click on a focusable element that does not match :focus-visible, does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click on a focusable element that does not match <code>:focus visible</code>, does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial" tabindex="0">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after mouse click on a focusable element that does not match :focus-visible, does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-009.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-009.html
new file mode 100644
index 0000000000..d0475eef51
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-009.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after mouse click on a focusable element that does not match :focus-visible, does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a mouse click on a focusable element that does not match <code>:focus visible</code>, does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial" tabindex="0">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after blur after mouse click on a focusable element that does not match :focus-visible, does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-010.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-010.html
new file mode 100644
index 0000000000..594a0c7f69
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-010.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click on a focusable element that matches :focus-visible, does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click on a focusable element that matches <code>:focus visible</code>, does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial" value="Click me">
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after mouse click on a focusable element that matches :focus-visible, does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-011.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-011.html
new file mode 100644
index 0000000000..d93bd6d47d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-011.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after mouse click on a focusable element that matches :focus-visible, does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a mouse click on a focusable element that matches <code>:focus visible</code>, does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial" value="Click me">
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Script focus after blur after mouse click on a focusable element that matches :focus-visible, does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-012.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-012.html
new file mode 100644
index 0000000000..3bd3093968
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-012.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after keyboard focus does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after a keyboard focus does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Type TAB key.</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial" tabindex="0">Focus me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("focus", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ const tab_key = "\ue004";
+ test_driver.send_keys(document.body, tab_key);
+ }, "Script focus after keyboard focus does match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-013.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-013.html
new file mode 100644
index 0000000000..02bd95a3f2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-013.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after keyboard focus does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a keyboard focus does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Type TAB key.</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial" tabindex="0">Focus me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("focus", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ const tab_key = "\ue004";
+ test_driver.send_keys(document.body, tab_key);
+ }, "Script focus after blur after keyboard focus does match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-014.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-014.html
new file mode 100644
index 0000000000..de8b960d85
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-014.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after keyboard input does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after a keyboard input does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the input below and type some letter.</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial">
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("keypress", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ initial.focus();
+ test_driver.send_keys(initial, "a");
+ }, "Script focus after keyboard input does match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-015.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-015.html
new file mode 100644
index 0000000000..71d23790c0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-015.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after keyboard input does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a keyboard input does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the input below and type some letter.</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial">
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("keypress", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ initial.focus();
+ test_driver.send_keys(initial, "a");
+ }, "Script focus after blur after keyboard input does match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-016.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-016.tentative.html
new file mode 100644
index 0000000000..38d857743a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-016.tentative.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click on a NOT focusable element after editing an input does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click on a NOT focusable element after editing an input does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the input below and type some letter.</li>
+ <li>Then click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial">
+<div id="trigger">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ trigger.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ initial.addEventListener("keypress", () => {
+ test_driver.click(trigger).then(() => done());
+ });
+
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ initial.focus();
+ test_driver.send_keys(initial, "a");
+ }, "Script focus after mouse click on a NOT focusable element after editing an input does match :focus-visible");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-017.tentative.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-017.tentative.html
new file mode 100644
index 0000000000..0014ae52be
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-017.tentative.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after mouse click on a NOT focusable element after editing an input does match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick green;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: red;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a mouse click on a NOT focusable element after editing an input does match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the input below and type some letter.</li>
+ <li>Then click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red background then the test result is FAILURE, if it has a green outline then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial">
+<div id="trigger">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ trigger.addEventListener("click", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ initial.addEventListener("keypress", () => {
+ test_driver.click(trigger).then(() => done());
+ });
+
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+ assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ initial.focus();
+ test_driver.send_keys(initial, "a");
+ }, "Script focus after blur after mouse click on a NOT focusable element after editing an input does match :focus-visible");
+</script>
+
+
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-018.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-018.html
new file mode 100644
index 0000000000..3072267179
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-018.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after mouse click on a focusable element after editing an input does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after a mouse click on a focusable element after editing an input does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the input below and type some letter.</li>
+ <li>Then click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial">
+<div id="trigger" tabindex="0">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ trigger.addEventListener("click", () => {
+ target.focus();
+ });
+
+ async_test(function(t) {
+ initial.addEventListener("keypress", () => {
+ test_driver.click(trigger).then(() => done());
+ });
+
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ initial.focus();
+ test_driver.send_keys(initial, "a");
+ }, "Script focus after mouse click on a focusable element after editing an input does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-019.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-019.html
new file mode 100644
index 0000000000..b6c3c907e0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-019.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Script focus after blur after mouse click on a focusable element after editing an input does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a script focus after blur after a mouse click on a focusable element after editing an input does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the input below and type some letter.</li>
+ <li>Then click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<input id="initial">
+<div id="trigger" tabindex="0">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ trigger.addEventListener("click", () => {
+ document.activeElement.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ initial.addEventListener("keypress", () => {
+ test_driver.click(trigger).then(() => done());
+ });
+
+ target.addEventListener("focus", t.step_func_done(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ }));
+
+ initial.focus();
+ test_driver.send_keys(initial, "a");
+ }, "Script focus after blur after mouse click on a focusable element after editing an input does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-visible-script-focus-020.html b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-020.html
new file mode 100644
index 0000000000..eb68efc683
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-visible-script-focus-020.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Double script focus after mouse click on a focusable element that does not match :focus-visible, does NOT match :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<style>
+ #warning {
+ display: none;
+ background: red;
+ }
+
+ @supports not selector(:focus-visible) {
+ #instructions {
+ display: none;
+ }
+
+ #warning {
+ display: block;
+ }
+ }
+
+ :focus-visible {
+ outline: solid thick red;
+ }
+
+ :focus:not(:focus-visible) {
+ background-color: lime;
+ }
+</style>
+
+<p>This test checks that a double script focus after a mouse click on a focusable element that does not match <code>:focus visible</code>, does NOT match <code>:focus-visible</code>.</p>
+<ol id="instructions">
+ <li>Click on the element that says "Click me".</li>
+ <li>If the element that says "Focused" has a red outline then the test result is FAILURE, if it has a green background then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="initial" tabindex="0">Click me</div>
+<div id="target" tabindex="0">Focused</div>
+
+<script>
+ setup({ explicit_done: true });
+
+ // Check that :focus-visible is supported.
+ test_valid_selector(':focus-visible');
+
+ initial.addEventListener("click", () => {
+ target.focus();
+ target.blur();
+ target.focus();
+ });
+
+ async_test(function(t) {
+ let count = 0;
+ target.addEventListener("focus", t.step_func(function() {
+ assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 255, 0)", `backgroundColor for ${target.tagName}#${target.id} should be lime`);
+ assert_not_equals(getComputedStyle(target).outlineColor, "rgb(255, 0, 0)", `outlineColor for ${target.tagName}#${target.id} should NOT be red`);
+ if (count > 0)
+ t.done();
+ count++;
+ }));
+
+ test_driver.click(initial).then(() => done());
+ }, "Double script focus after mouse click on a focusable element that does not match :focus-visible, does NOT match :focus-visible");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-001-ref.html b/testing/web-platform/tests/css/selectors/focus-within-001-ref.html
new file mode 100644
index 0000000000..2913775a22
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-001-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within Reference File</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<style>
+div {
+ border: solid 15px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div>Focus this element</div>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-001.html b/testing/web-platform/tests/css/selectors/focus-within-001.html
new file mode 100644
index 0000000000..fcf8a379c8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-001.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-001-ref.html">
+<meta name="assert" content="Test that :focus-within applies to an element with tabindex when :focus applies.">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+
+/* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+div {
+border: solid 15px blue;
+}
+div:focus {
+border-color: red;
+}
+div:focus-within {
+border-color: green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div id="focusme" tabindex="1">Focus this element</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-002.html b/testing/web-platform/tests/css/selectors/focus-within-002.html
new file mode 100644
index 0000000000..e483833feb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-002.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-001-ref.html">
+<meta name="assert" content="Test that :focus-within applies to the parent of an element with tabindex where :focus applies.">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+
+/* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+#focusme:not(:focus) {
+ border: solid 15px blue;
+}
+
+#target:focus-within {
+ border: solid 15px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div id="target">
+ <div id="focusme" tabindex="1">Focus this element</div>
+</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-003.html b/testing/web-platform/tests/css/selectors/focus-within-003.html
new file mode 100644
index 0000000000..b399c4f0cf
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-003.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-001-ref.html">
+<meta name="assert" content="Test that :focus-within applies to ancestors of an element with tabindex where :focus applies.">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+
+/* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+#focusme:not(:focus) {
+ border: solid 15px blue;
+}
+
+#target:focus-within {
+ border: solid 15px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div id="target">
+ <div>
+ <div>
+ <div>
+ <div id="focusme" tabindex="1">Focus this element</div>
+ </div>
+ </div>
+ </div>
+</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-004.html b/testing/web-platform/tests/css/selectors/focus-within-004.html
new file mode 100644
index 0000000000..169af9e070
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-004.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-001-ref.html">
+<meta name="assert" content="Test that :focus-within works on elements that are focusable due to contenteditable.">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+
+ /* Make the caret invisible
+ since it matches the color of the text, which is transparent,
+ while keeping the text readable thanks to its shadow.
+ Not using the caret-color property as it is too new to be relied on. */
+ color: transparent; text-shadow: black 0px 0px 0px;
+}
+
+/* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+#focusme:not(:focus) {
+ border: solid 15px blue;
+}
+
+:focus {
+ border: solid 5px red;
+}
+div:focus-within, #focusme:focus-within {
+ border: solid 5px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div>
+ <div>
+ <div id="focusme" contentEditable="true">Focus this element</div>
+ </div>
+</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-005.html b/testing/web-platform/tests/css/selectors/focus-within-005.html
new file mode 100644
index 0000000000..03f927d1b4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-005.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-001-ref.html">
+<meta name="assert" content="Test that :focus-within works on links.">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+
+/* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+#focusme:not(:focus) {
+ border: solid 15px blue;
+}
+
+/* Make the link look like the div in the reference file */
+#focusme {
+ display: block;
+ text-decoration: none;
+ color: currentColor;
+}
+
+:focus {
+ border: solid 5px red;
+}
+div:focus-within, #focusme:focus-within {
+ border: solid 5px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div>
+ <div>
+ <a id="focusme" href="">Focus this element</a>
+ </div>
+</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-006-ref.html b/testing/web-platform/tests/css/selectors/focus-within-006-ref.html
new file mode 100644
index 0000000000..b93c156876
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-006-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within Reference File</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<style>
+:focus {
+ outline: none;
+
+ /* Make the caret invisible
+ since it matches the color of the text, which is transparent,
+ while keeping the text readable thanks to its shadow.
+ Not using the caret-color property as it is too new to be relied on. */
+ color: transparent; text-shadow: black 0px 0px 0px;
+}
+
+div {
+ border: solid 15px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div>
+ <input id="focusme" value="Focus this element">
+</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-006.html b/testing/web-platform/tests/css/selectors/focus-within-006.html
new file mode 100644
index 0000000000..ff63cceb6e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-006.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-006-ref.html">
+<meta name="assert" content="Test that :focus-within works on form controls, using an input element.">
+<style>
+:focus {
+ outline: none;
+
+ /* Make the caret invisible
+ since it matches the color of the text, which is transparent,
+ while keeping the text readable thanks to its shadow.
+ Not using the caret-color property as it is too new to be relied on. */
+ color: transparent; text-shadow: black 0px 0px 0px;
+}
+
+/* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+#focusme:not(:focus) {
+ border: solid 15px blue;
+}
+
+#focusme:focus:not(:focus-within) {
+ background: red;
+}
+div:focus-within {
+ border: solid 5px green;
+}
+</style>
+<p>Test passes if, when the element below is focused,
+it is surrounded by a thick green border.
+There must be no red or blue once it is focused.</p>
+<div>
+ <div>
+ <div>
+ <input id="focusme" value="Focus this element">
+ </div>
+ </div>
+</div>
+<script>
+var focusme = document.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-007-ref.html b/testing/web-platform/tests/css/selectors/focus-within-007-ref.html
new file mode 100644
index 0000000000..6ecc21536a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-007-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within Reference File</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<style>
+ html, body, div {
+ border: solid 5px green;
+ }
+</style>
+<p>Test passes if, when the element below is focused, it is surrounded by a green border, and HTML and BODY elements also have a green border. There must be no red or blue once it is focused.</p>
+<div>Focus this element</div>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-007.html b/testing/web-platform/tests/css/selectors/focus-within-007.html
new file mode 100644
index 0000000000..f23fe87643
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-007.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-007-ref.html">
+<meta name="assert" content="Checks that ':focus-within' can be used as universal selector.">
+<style>
+ /* Suppress things that cannot be reproduced in the reference file */
+ :focus {
+ outline: none;
+ }
+ html, body, div {
+ border: solid 5px red;
+ }
+ /* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+ div {
+ border-color: blue;
+ }
+ :focus-within {
+ border-color: green;
+ }
+</style>
+<p>Test passes if, when the element below is focused, it is surrounded by a green border, and HTML and BODY elements also have a green border. There must be no red or blue once it is focused.</p>
+<div id="focusme" tabindex="1">Focus this element</div>
+<script>
+ var focusme = document.getElementById('focusme');
+ focusme.focus();
+ document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-008.html b/testing/web-platform/tests/css/selectors/focus-within-008.html
new file mode 100644
index 0000000000..19deff212a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-008.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-007-ref.html">
+<meta name="assert" content="Checks that ':focus-within' can be used as universal selector (using *).">
+<style>
+ /* Suppress things that cannot be reproduced in the reference file */
+ :focus {
+ outline: none;
+ }
+ html, body, div {
+ border: solid 5px red;
+ }
+ /* Use blue to indicate that the user needs to pay attention.
+ This element needs to be focused for the test to make sense. */
+ div {
+ border-color: blue;
+ }
+ *:focus-within {
+ border-color: green;
+ }
+</style>
+<p>Test passes if, when the element below is focused, it is surrounded by a green border, and HTML and BODY elements also have a green border. There must be no red or blue once it is focused.</p>
+<div id="focusme" tabindex="1">Focus this element</div>
+<script>
+ var focusme = document.getElementById('focusme');
+ focusme.focus();
+ document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-009.html b/testing/web-platform/tests/css/selectors/focus-within-009.html
new file mode 100644
index 0000000000..c8d47d2df0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-009.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html id="html">
+<head>
+ <meta charset="utf-8">
+ <title>Selectors Level 4: focus-within</title>
+ <link rel="author" title="Benjamin Poulain" href="mailto:bpoulain@apple.com">
+ <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+ <meta name="assert" content="Checks the basic features of the ':focus-within' pseudo class.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ * {
+ background-color: white;
+ }
+ :focus-within {
+ background-color: rgb(1, 2, 3);
+ }
+ </style>
+</head>
+<body id="body">
+ <div id="test">
+ <div id="container1">
+ <div id="sibling1"></div>
+ <div id="sibling2">
+ <input id="target1">
+ </div>
+ <div id="sibling3"></div>
+ </div>
+ <div id="container2">
+ <div id="sibling4"></div>
+ <div id="sibling5">
+ <textarea id="target2"></textarea>
+ </div>
+ <div id="sibling6"></div>
+ </div>
+ </div>
+ <div id=log></div>
+
+ <script>
+ "use strict";
+
+ function elementsStyledWithFocusWithinSelector() {
+ let elements = [];
+ for (let element of document.querySelectorAll("*")) {
+ if (getComputedStyle(element).backgroundColor === 'rgb(1, 2, 3)') {
+ elements.push(element.id);
+ }
+ }
+ return elements;
+ }
+
+ function elementsMatchingFocusWithinSelector() {
+ let elements = [];
+ for (let element of document.querySelectorAll(":focus-within")) {
+ elements.push(element.id);
+ }
+ return elements;
+ }
+
+ test(
+ function() {
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), []);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), []);
+ }, "Initial State");
+
+ var container1 = document.getElementById("container1");
+ var container2 = document.getElementById("container2");
+ var target1 = document.getElementById("target1");
+ var target2 = document.getElementById("target2");
+
+ test(
+ function() {
+ target1.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container1", "sibling2", "target1"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container1", "sibling2", "target1"]);
+ }, "Focus 'target1'");
+
+ test(
+ function() {
+ target2.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ }, "Focus 'target2'");
+
+ test(
+ function() {
+ target1.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container1", "sibling2", "target1"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container1", "sibling2", "target1"]);
+ }, "Focus 'target1' again");
+
+ test(
+ function() {
+ target2.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ }, "Focus 'target2' again");
+
+ test(
+ function() {
+ target1.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container1", "sibling2", "target1"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container1", "sibling2", "target1"]);
+ }, "Focus 'target1' once again");
+
+ test(
+ function() {
+ container1.parentElement.removeChild(container1);
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), []);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), []);
+ assert_equals(container1.querySelectorAll(":focus-within").length, 0);
+ assert_false(target1.matches(":focus"));
+ assert_false(target2.matches(":focus"));
+ }, "Detach 'container1' from the document");
+
+ test(
+ function() {
+ target1.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), []);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), []);
+ assert_equals(container1.querySelectorAll(":focus-within").length, 0);
+ assert_false(target1.matches(":focus"));
+ assert_false(target2.matches(":focus"));
+ }, "Try to focus 'target1'");
+
+ test(
+ function() {
+ target2.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ }, "Focus 'target2' once again");
+
+ test(
+ function() {
+ container2.appendChild(container1);
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container2", "sibling5", "target2"]);
+ }, "Attach 'container1' in 'container2'");
+
+ test(
+ function() {
+ target1.focus();
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), ["html", "body", "test", "container2", "container1", "sibling2", "target1"]);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), ["html", "body", "test", "container2", "container1", "sibling2", "target1"]);
+ }, "Focus 'target1' for the last time");
+
+ test(
+ function() {
+ container2.appendChild(target1);
+ assert_array_equals(elementsStyledWithFocusWithinSelector(), []);
+ assert_array_equals(elementsMatchingFocusWithinSelector(), []);
+ assert_false(target1.matches(":focus"));
+ assert_false(target2.matches(":focus"));
+ }, "Move 'target1' in 'container2'");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-010.html b/testing/web-platform/tests/css/selectors/focus-within-010.html
new file mode 100644
index 0000000000..2476e03dba
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-010.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="assert" content="Checks that :focus-within is still applied when focus moves from an element to one of its descendants.">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+
+#target {
+ display: none;
+}
+
+#wrapper:focus-within > #target {
+ display: block;
+}
+
+#target:focus {
+ border: solid 15px green;
+}
+</style>
+<p>Test passes if there is a green rectangle below.</p>
+<div id="wrapper" tabindex="1">
+ <div id="target" tabindex="2"></div>
+</div>
+<script>
+var wrapper = document.getElementById('wrapper');
+wrapper.focus();
+var target = document.getElementById('target');
+target.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-011-ref.html b/testing/web-platform/tests/css/selectors/focus-within-011-ref.html
new file mode 100644
index 0000000000..f5e4edf0f2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-011-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :focus-within selector</title>
+ <link rel="author" title="Ethan Lin" href="mailto:ethlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <style type="text/css">
+ div {
+ border: solid 15px blue;
+ outline: none;
+ border-color: green;
+ }
+ #child1 {
+ border-color: blue;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if, when the upper element is unfocused and the lower element is focused, the upper element is blue and the lower one is green, and they are surrounded by a thick green border.</p>
+ <div id="parent">
+ <div id="child1"></div>
+ <div id="child2"></div>
+ </div>
+ <body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-011.html b/testing/web-platform/tests/css/selectors/focus-within-011.html
new file mode 100644
index 0000000000..8c05321c14
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-011.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html class="reftest-wait test">
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :focus-within selector</title>
+ <link rel="author" title="Ethan Lin" href="mailto:ethlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+ <meta name="assert" content="Test checks :focus-within works after focus change">
+ <link rel="match" href="focus-within-011-ref.html">
+ <style>
+ div {
+ border: solid 15px blue;
+ outline: none;
+ }
+ div:focus-within {
+ border-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if, when the upper element is unfocused and the lower element is focused, the upper element is blue and the lower one is green, and they are surrounded by a thick green border.</p>
+ <div id="parent">
+ <div id="child1" tabindex="1"></div>
+ <div id="child2" tabindex="2"></div>
+ </div>
+ <script>
+ var child1 = document.getElementById('child1');
+ child1.focus();
+ document.body.offsetWidth;
+
+ var child2 = document.getElementById('child2');
+ child2.focus();
+ document.body.offsetWidth;
+ document.documentElement.classList.remove('reftest-wait');
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-012-ref.html b/testing/web-platform/tests/css/selectors/focus-within-012-ref.html
new file mode 100644
index 0000000000..5aeac2441d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-012-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :focus-within selector</title>
+ <link rel="author" title="Ethan Lin" href="mailto:ethlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <style type="text/css">
+ div {
+ border: solid 15px green;
+ outline: none;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if, when the element is focused and then removed, the outer element should change to green.</p>
+ <div id="parent"></div>
+ <body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-012.html b/testing/web-platform/tests/css/selectors/focus-within-012.html
new file mode 100644
index 0000000000..754cebb6d7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-012.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :focus-within selector</title>
+ <link rel="author" title="Ethan Lin" href="mailto:ethlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+ <meta name="assert" content="Test checks :focus-within should not apply after element removed.">
+ <link rel="match" href="focus-within-012-ref.html">
+ <style>
+ div {
+ border: solid 15px green;
+ outline: none;
+ }
+ div:focus-within {
+ border-color: red;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if, when the element is focused and then removed, the outer element should change to green.</p>
+ <div id="parent">
+ <div id="child" tabindex="1"></div>
+ </div>
+ <script>
+ var child = document.getElementById('child');
+ child.focus();
+ document.body.offsetWidth;
+ var parent = document.getElementById("parent");
+ parent.removeChild(child);
+ document.body.offsetWidth;
+ document.documentElement.classList.remove('reftest-wait');
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-013-ref.html b/testing/web-platform/tests/css/selectors/focus-within-013-ref.html
new file mode 100644
index 0000000000..cb0badd2ad
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-013-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :focus-within selector</title>
+ <link rel="author" title="Ethan Lin" href="mailto:ethlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ </head>
+ <body>
+ <p>Test passes if, when the element inside the iframe is focused, there is no red border surrounded.</p>
+ <div>
+ <iframe src="focus-within-1.html" width="300px" height="300px" frameborder="0" tabindex="1"><p>Your browser does not support iframes.</p></iframe>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-013.html b/testing/web-platform/tests/css/selectors/focus-within-013.html
new file mode 100644
index 0000000000..eaa1da1ba6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-013.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Test: :focus-within selector</title>
+ <link rel="author" title="Ethan Lin" href="mailto:ethlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+ <meta name="assert" content="Test checks :focus-within should not work for iframe">
+ <link rel="match" href="focus-within-013-ref.html">
+ <style>
+ div:focus-within {
+ border: solid 15px red;
+ }
+ iframe:focus-within {
+ border: solid 15px red;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if, when the element inside the iframe is focused, there is no red border surrounded.</p>
+ <div>
+ <iframe id="iframe" src="focus-within-1.html" width="300px" height="300px" frameborder="0" tabindex="1"><p>Your browser does not support iframes.</p></iframe>
+ </div>
+ <script>
+ var iframe = document.getElementById("iframe");
+ iframe.addEventListener("load", function() {
+ while (iframe.contentWindow.document.documentElement.classList.contains("reftest-wait")) {}
+ document.documentElement.classList.remove('reftest-wait');
+ });
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-display-none-001.html b/testing/web-platform/tests/css/selectors/focus-within-display-none-001.html
new file mode 100644
index 0000000000..3f96fb267d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-display-none-001.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#focus-fixup-rule">
+<meta name="assert" content="Checks ':focus-within' pseudo-class after 'display: none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="wrapper">
+ <input id="input">
+</div>
+<script>
+ "use strict";
+
+ const wrapper = document.getElementById("wrapper");
+ const input = document.getElementById("input");
+
+ async_test((t) => {
+ input.focus();
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_true(input.matches(":focus-within"),
+ "Check input matches ':focus-within' after being focused"));
+ t.step(() => assert_true(wrapper.matches(":focus-within"),
+ "Check wrapper matches ':focus-within' after child was focused"));
+
+ input.style.display = "none";
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_false(input.matches(":focus-within"),
+ "Check input doesn't match ':focus-within' after getting 'display: none'"));
+ t.step(() => assert_false(wrapper.matches(":focus-within"),
+ "Check wrapper doesn't match ':focus-within' after child got 'display: none'"));
+ input.style.display = "inline";
+ t.done();
+ });
+ });
+ }, "Test ':focus-within' after 'display:none' on input");
+
+ async_test((t) => {
+ input.focus();
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_true(input.matches(":focus-within"),
+ "Check input matches ':focus-within' after being focused"));
+ t.step(() => assert_true(wrapper.matches(":focus-within"),
+ "Check wrapper matches ':focus-within' after child was focused"));
+
+ wrapper.style.display = "none";
+ window.requestAnimationFrame(() => {
+ t.step(() => assert_false(input.matches(":focus-within"),
+ "Check input doesn't match ':focus-within' after parent got 'display: none'"));
+ t.step(() => assert_false(wrapper.matches(":focus-within"),
+ "Check wrapper doesn't match ':focus-within' after getting 'display: none'"));
+ wrapper.style.display = "block";
+ t.done();
+ });
+ });
+ }, "Test ':focus-within' after 'display:none' on input's parent");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-001-ref.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-001-ref.html
new file mode 100644
index 0000000000..6ab3631879
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-001-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within shadow DOM Reference File</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<style>
+div {
+ border: solid 15px green;
+}
+</style>
+<p>Test passes if there is a green rectangle below.</p>
+<div></div>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-001.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-001.html
new file mode 100644
index 0000000000..012a774129
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-001.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within with shadow DOM</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="flags" content="dom">
+<meta name="assert" content="Test that :focus-within applies to a focused element inside the shadow DOM.">
+<body>
+<p>Test passes if there is a green rectangle below.</p>
+<div id="shadow-host"><strong>Skip this test, shadow DOM is not supported.</strong></div>
+
+<template id="shadow-template">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+
+div:focus-within {
+ border: solid 15px green;
+}
+</style>
+<div id="focusme" tabindex="1"></div>
+</template>
+
+<script>
+var shadow = document.getElementById('shadow-host').attachShadow({mode: 'open'});
+var template = document.getElementById('shadow-template');
+var instance = document.importNode(template.content, true);
+shadow.appendChild(instance);
+var focusme = shadow.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-002.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-002.html
new file mode 100644
index 0000000000..50b30df424
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-002.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within with shadow DOM</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="flags" content="dom">
+<meta name="assert" content="Test that :focus-within applies to a shadow host containing a focused element.">
+<style>
+div:focus-within {
+ border: solid 15px green;
+}
+</style>
+<body>
+<p>Test passes if there is a green rectangle below.</p>
+<div id="shadow-host"><strong>Skip this test, shadow DOM is not supported.</strong></div>
+
+<template id="shadow-template">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+</style>
+<div id="focusme" tabindex="1"></div>
+</template>
+
+<script>
+var shadow = document.getElementById('shadow-host').attachShadow({mode: 'open'});
+var template = document.getElementById('shadow-template');
+var instance = document.importNode(template.content, true);
+shadow.appendChild(instance);
+var focusme = shadow.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-003.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-003.html
new file mode 100644
index 0000000000..48901b215b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-003.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within with shadow DOM</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="flags" content="dom">
+<meta name="assert" content="Test that :focus-within applies to the parent of a shadow host containing a focused element.">
+<style>
+#target:focus-within {
+ border: solid 15px green;
+}
+</style>
+<body>
+<p>Test passes if there is a green rectangle below.</p>
+<div id="target">
+ <div id="shadow-host"><strong>Skip this test, shadow DOM is not supported.</strong></div>
+</div>
+
+<template id="shadow-template">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+</style>
+<div id="focusme" tabindex="1"></div>
+</template>
+
+<script>
+var shadow = document.getElementById('shadow-host').attachShadow({mode: 'open'});
+var template = document.getElementById('shadow-template');
+var instance = document.importNode(template.content, true);
+shadow.appendChild(instance);
+var focusme = shadow.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-004.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-004.html
new file mode 100644
index 0000000000..6beed1fc13
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-004.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within with shadow DOM</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="author" title="Florian Rivoal" href="mailto:florian@rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="flags" content="dom">
+<meta name="assert" content="Test that :focus-within applies to an ancestor of a shadow host containing a focused element.">
+<style>
+#target:focus-within {
+ border: solid 15px green;
+}
+</style>
+<body>
+<p>Test passes if there is a green rectangle below.</p>
+<div id="target">
+ <div>
+ <div>
+ <div>
+ <div id="shadow-host"><strong>Skip this test, shadow DOM is not supported.</strong></div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<template id="shadow-template">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+</style>
+<div id="focusme" tabindex="1"></div>
+</template>
+
+<script>
+var shadow = document.getElementById('shadow-host').attachShadow({mode: 'open'});
+var template = document.getElementById('shadow-template');
+var instance = document.importNode(template.content, true);
+shadow.appendChild(instance);
+var focusme = shadow.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-005.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-005.html
new file mode 100644
index 0000000000..c645d62f76
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-005.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang=en class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within with shadow DOM</title>
+<link rel="author" title="Keyong Li" href="mailto:kli79@bloomberg.net">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="flags" content="dom">
+<meta name="assert" content="Test that :focus-within propagates through nested shadow DOMs containing a focused element.">
+<style>
+#target:focus-within {
+ border: solid 15px green;
+}
+</style>
+<body>
+<p>Test passes if there is a green rectangle below.</p>
+<div id="target">
+ <div>
+ <div>
+ <div>
+ <div id="shadow-host"><strong>Skip this test, shadow DOM is not supported.</strong></div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<template id="shadow-template">
+<div id="nested-shadow-host"><strong>Skip this test, nested shadow hosts are not supported.</strong></div>
+</template>
+
+<template id="nested-shadow-template">
+<style>
+/* Suppress things that cannot be reproduced in the reference file */
+:focus {
+ outline: none;
+}
+</style>
+<div id="focusme" tabindex="1"></div>
+</template>
+
+<script>
+var shadow = document.getElementById('shadow-host').attachShadow({mode: 'open'});
+var template = document.getElementById('shadow-template');
+var instance = document.importNode(template.content, true);
+shadow.appendChild(instance);
+
+shadow = shadow.getElementById('nested-shadow-host').attachShadow({mode: 'open'});
+template = document.getElementById('nested-shadow-template');
+instance = document.importNode(template.content, true);
+shadow.appendChild(instance);
+
+var focusme = shadow.getElementById('focusme');
+focusme.focus();
+document.documentElement.classList.remove('reftest-wait');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/focus-within-shadow-006.html b/testing/web-platform/tests/css/selectors/focus-within-shadow-006.html
new file mode 100644
index 0000000000..39a2f70610
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/focus-within-shadow-006.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Selectors Level 4: focus-within with shadow DOM</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#focus-within-pseudo">
+<link rel="help" href="https://dom.spec.whatwg.org/#shadow-trees">
+<link rel="match" href="focus-within-shadow-001-ref.html">
+<meta name="flags" content="dom">
+<meta name="assert" content="Checks that ':focus-within' is propagated to the flat tree ancestors, even if it comes from a slotted element.">
+<style>
+ /* Suppress things that cannot be reproduced in the reference file */
+ :focus {
+ outline: none;
+ }
+ :focus-within {
+ border-color: green;
+ }
+</style>
+<p>Test passes if there is a green rectangle below.</p>
+
+<div id="log"></div>
+<script>
+ if (!document.body.attachShadow)
+ document.getElementById("log").innerHTML = "<strong>Skip this test, shadow DOM is not supported.</strong>";
+</script>
+
+<div id="shadow-host">
+ <div id="focusme" tabindex="1"></div>
+</div>
+
+<script>
+ var shadowHost = document.getElementById("shadow-host");
+ shadowHost.attachShadow({ mode: "open"}).innerHTML =
+ "<style>" +
+ " #shadow-div:focus-within { border: solid 15px green; }" +
+ "</style>" +
+ "<div id='shadow-div'>" +
+ " <slot></slot>" +
+ "</div>";
+ var focusme = document.getElementById("focusme");
+ focusme.focus();
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/has-argument-with-explicit-scope.html b/testing/web-platform/tests/css/selectors/has-argument-with-explicit-scope.html
new file mode 100644
index 0000000000..b5773988cc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-argument-with-explicit-scope.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has pseudo class behavior with explicit ':scope' in its argument</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<main>
+ <div id=d01 class="a">
+ <div id=scope1 class="b">
+ <div id=d02 class="c">
+ <div id=d03 class="c">
+ <div id=d04 class="d"></div>
+ </div>
+ </div>
+ <div id=d05 class="e"></div>
+ </div>
+ </div>
+ <div id=d06>
+ <div id=scope2 class="b">
+ <div id=d07 class="c">
+ <div id=d08 class="c">
+ <div id=d09></div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+ function formatElements(elements) {
+ return elements.map(e => e.id).sort().join();
+ }
+
+ // Test that |selector| returns the given elements in the given scope element
+ function test_selector_all(scope, selector, expected) {
+ test(function() {
+ let actual = Array.from(scope.querySelectorAll(selector));
+ assert_equals(formatElements(actual), formatElements(expected));
+ }, `${selector} matches expected elements on ${scope.id}`);
+ }
+
+ // Test that |selector1| and |selector2| returns same elements in the given scope element
+ function compare_selector_all(scope, selector1, selector2) {
+ test(function() {
+ let result1 = Array.from(scope.querySelectorAll(selector1));
+ let result2 = Array.from(scope.querySelectorAll(selector2));
+ assert_equals(formatElements(result1), formatElements(result2));
+ }, `${selector1} and ${selector2} returns same elements on ${scope.id}`);
+ }
+
+ // descendants of a scope element cannot have the scope element as its descendant
+ test_selector_all(scope1, ':has(:scope)', []);
+ test_selector_all(scope1, ':has(:scope .c)', []);
+ test_selector_all(scope1, ':has(.a :scope)', []);
+
+ // there can be more simple and efficient alternative for a ':scope' in ':has'
+ test_selector_all(scope1, '.a:has(:scope) .c', [d02, d03]);
+ compare_selector_all(scope1, '.a:has(:scope) .c', ':is(.a :scope .c)');
+ test_selector_all(scope2, '.a:has(:scope) .c', []);
+ compare_selector_all(scope2, '.a:has(:scope) .c', ':is(.a :scope .c)');
+ test_selector_all(scope1, '.c:has(:is(:scope .d))', [d02, d03]);
+ compare_selector_all(scope1, '.c:has(:is(:scope .d))', ':scope .c:has(.d)');
+ compare_selector_all(scope1, '.c:has(:is(:scope .d))', '.c:has(.d)');
+ test_selector_all(scope2, '.c:has(:is(:scope .d))', []);
+ compare_selector_all(scope2, '.c:has(:is(:scope .d))', ':scope .c:has(.d)');
+ compare_selector_all(scope2, '.c:has(:is(:scope .d))', '.c:has(.d)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/has-basic.html b/testing/web-platform/tests/css/selectors/has-basic.html
new file mode 100644
index 0000000000..3a73edd184
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-basic.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Basic matching behavior of :has pseudo class</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+
+<main id=main>
+ <div id=a class="ancestor">
+ <div id=b class="parent ancestor">
+ <div id=c class="sibling descendant">
+ <div id=d class="descendant"></div>
+ </div>
+ <div id=e class="target descendant"></div>
+ </div>
+ <div id=f class="parent ancestor">
+ <div id=g class="target descendant"></div>
+ </div>
+ <div id=h class="parent ancestor">
+ <div id=i class="target descendant"></div>
+ <div id=j class="sibling descendant">
+ <div id=k class="descendant"></div>
+ </div>
+ </div>
+ </div>
+</main>
+
+<script>
+ function formatElements(elements) {
+ return elements.map(e => e.id).sort().join();
+ }
+
+ // Test that |selector| returns the given elements in #main.
+ function test_selector_all(selector, expected) {
+ test(function() {
+ let actual = Array.from(main.querySelectorAll(selector));
+ assert_equals(formatElements(actual), formatElements(expected));
+ }, `${selector} matches expected elements`);
+ }
+
+ // Test that |selector| returns the given element in #main.
+ function test_selector(selector, expected) {
+ test(function() {
+ assert_equals(main.querySelector(selector), expected);
+ }, `${selector} matches expected element`);
+ }
+
+ // Test that |selector| returns the given closest element.
+ function test_closest(node, selector, expected) {
+ test(function() {
+ assert_equals(node.closest(selector), expected);
+ }, `closest(${selector}) returns expected element`);
+ }
+
+ // Test that |selector| returns matching status.
+ function test_matches(node, selector, expected) {
+ test(function() {
+ assert_equals(node.matches(selector), expected);
+ }, `${selector} matches expectedly`);
+ }
+
+ test_selector_all(':has(#a)', []);
+ test_selector_all(':has(.ancestor)', [a]);
+ test_selector_all(':has(.target)', [a, b, f, h]);
+ test_selector_all(':has(.descendant)', [a, b, c, f, h, j]);
+ test_selector_all('.parent:has(.target)', [b, f, h]);
+ test_selector_all(':has(.sibling ~ .target)', [a, b]);
+ test_selector_all('.parent:has(.sibling ~ .target)', [b]);
+ test_selector_all(':has(:is(.target ~ .sibling .descendant))', [a, h, j]);
+ test_selector_all('.parent:has(:is(.target ~ .sibling .descendant))', [h]);
+ test_selector_all('.sibling:has(.descendant) ~ .target', [e]);
+ test_selector_all(':has(> .parent)', [a]);
+ test_selector_all(':has(> .target)', [b, f, h]);
+ test_selector_all(':has(> .parent, > .target)', [a, b, f, h]);
+ test_selector_all(':has(+ #h)', [f]);
+ test_selector_all('.parent:has(~ #h)', [b, f]);
+ test_selector('.sibling:has(.descendant)', c);
+ test_closest(k, '.ancestor:has(.descendant)', h);
+ test_matches(h, ':has(.target ~ .sibling .descendant)', true);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/has-display-none-checked-ref.html b/testing/web-platform/tests/css/selectors/has-display-none-checked-ref.html
new file mode 100644
index 0000000000..6e855f52ca
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-display-none-checked-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<div>PASS</div>
diff --git a/testing/web-platform/tests/css/selectors/has-display-none-checked.html b/testing/web-platform/tests/css/selectors/has-display-none-checked.html
new file mode 100644
index 0000000000..96b1f8bd04
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-display-none-checked.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>:has() invalidation inside display: none subtree</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1875137">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="match" href="has-display-none-checked-ref.html">
+<style>
+body:has(input:checked) #fail {
+ display: none;
+}
+body:not(:has(input:checked)) #pass {
+ display: none;
+}
+</style>
+<div style="display: none">
+ <input type="checkbox" id="on">
+</div>
+<div id="fail">FAIL</div>
+<div id="pass">PASS</div>
+<script>
+ document.addEventListener("TestRendered", function() {
+ document.querySelector("input").checked = true;
+ document.documentElement.className = "";
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/has-matches-to-uninserted-elements.html b/testing/web-platform/tests/css/selectors/has-matches-to-uninserted-elements.html
new file mode 100644
index 0000000000..4d6c8cf2e3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-matches-to-uninserted-elements.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Matches :has pseudo class to uninserted elements</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+
+<script>
+ // Test that |selector| returns matching status.
+ function test_matches(node, selector, expected) {
+ test(function() {
+ assert_equals(node.matches(selector), expected);
+ }, `${selector} matches expectedly`);
+ }
+
+ subject = document.createElement('subject');
+
+ subject.innerHTML = '<child></child>';
+ test_matches(subject, ':has(child)', true);
+ test_matches(subject, ':has(> child)', true);
+
+ subject.innerHTML = '<child><descendant></descendant></child>';
+ test_matches(subject, ':has(descendant)', true);
+ test_matches(subject, ':has(> descendant)', false);
+
+ subject.innerHTML = '<child></child><direct_sibling></direct_sibling><indirect_sibling></indirect_sibling>';
+ test_matches(subject.firstChild, ':has(~ direct_sibling)', true);
+ test_matches(subject.firstChild, ':has(+ direct_sibling)', true);
+ test_matches(subject.firstChild, ':has(~ indirect_sibling)', true);
+ test_matches(subject.firstChild, ':has(+ indirect_sibling)', false);
+
+ test_matches(subject, ':has(*)', true);
+ test_matches(subject, ':has(> *)', true);
+ test_matches(subject, ':has(~ *)', false);
+ test_matches(subject, ':has(+ *)', false);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/has-relative-argument.html b/testing/web-platform/tests/css/selectors/has-relative-argument.html
new file mode 100644
index 0000000000..aad7436884
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-relative-argument.html
@@ -0,0 +1,184 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has pseudo class behavior with various relative arguments</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+
+<main id=main>
+ <div id=d01>
+ <div id=d02 class="x">
+ <div id=d03 class="a"></div>
+ <div id=d04></div>
+ <div id=d05 class="b"></div>
+ </div>
+ <div id=d06 class="x">
+ <div id=d07 class="x">
+ <div id=d08 class="a"></div>
+ </div>
+ </div>
+ <div id=d09 class="x">
+ <div id=d10 class="a">
+ <div id=d11 class="b"></div>
+ </div>
+ </div>
+ <div id=d12 class="x">
+ <div id=d13 class="a">
+ <div id=d14>
+ <div id=d15 class="b"></div>
+ </div>
+ </div>
+ <div id=d16 class="b"></div>
+ </div>
+ </div>
+ <div id=d17>
+ <div id=d18 class="x"></div>
+ <div id=d19 class="x"></div>
+ <div id=d20 class="a"></div>
+ <div id=d21 class="x"></div>
+ <div id=d22 class="a">
+ <div id=d23 class="b"></div>
+ </div>
+ <div id=d24 class="x"></div>
+ <div id=d25 class="a">
+ <div id=d26>
+ <div id=d27 class="b"></div>
+ </div>
+ </div>
+ <div id=d28 class="x"></div>
+ <div id=d29 class="a"></div>
+ <div id=d30 class="b">
+ <div id=d31 class="c"></div>
+ </div>
+ <div id=d32 class="x"></div>
+ <div id=d33 class="a"></div>
+ <div id=d34 class="b">
+ <div id=d35>
+ <div id=d36 class="c"></div>
+ </div>
+ </div>
+ <div id=d37 class="x"></div>
+ <div id=d38 class="a"></div>
+ <div id=d39 class="b"></div>
+ <div id=d40 class="x"></div>
+ <div id=d41 class="a"></div>
+ <div id=d42></div>
+ <div id=d43 class="b">
+ <div id=d44 class="x">
+ <div id=d45 class="c"></div>
+ </div>
+ </div>
+ <div id=d46 class="x"></div>
+ <div id=d47 class="a">
+ </div>
+ </div>
+ <div>
+ <div id=d48 class="x">
+ <div id=d49 class="x">
+ <div id=d50 class="x d">
+ <div id=d51 class="x d">
+ <div id=d52 class="x">
+ <div id=d53 class="x e">
+ <div id=d54 class="f"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id=d55 class="x"></div>
+ <div id=d56 class="x d"></div>
+ <div id=d57 class="x d"></div>
+ <div id=d58 class="x"></div>
+ <div id=d59 class="x e"></div>
+ <div id=d60 class="f"></div>
+ </div>
+ <div>
+ <div id=d61 class="x"></div>
+ <div id=d62 class="x y"></div>
+ <div id=d63 class="x y">
+ <div id=d64 class="y g">
+ <div id=d65 class="y">
+ <div id=d66 class="y h">
+ <div id=d67 class="i"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id=d68 class="x y">
+ <div id=d69 class="x"></div>
+ <div id=d70 class="x"></div>
+ <div id=d71 class="x y">
+ <div id=d72 class="y g">
+ <div id=d73 class="y">
+ <div id=d74 class="y h">
+ <div id=d75 class="i"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id=d76 class="x"></div>
+ <div id=d77 class="j"><div id=d78><div id=d79></div></div></div>
+ </div>
+ <div id=d80 class="j"></div>
+ </div>
+</main>
+
+<script>
+ function formatElements(elements) {
+ return elements.map(e => e.id).sort().join();
+ }
+
+ // Test that |selector| returns the given elements in #main.
+ function test_selector_all(selector, expected) {
+ test(function() {
+ let actual = Array.from(main.querySelectorAll(selector));
+ assert_equals(formatElements(actual), formatElements(expected));
+ }, `${selector} matches expected elements`);
+ }
+
+ test_selector_all('.x:has(.a)', [d02, d06, d07, d09, d12]);
+ test_selector_all('.x:has(.a > .b)', [d09]);
+ test_selector_all('.x:has(.a .b)', [d09, d12]);
+ test_selector_all('.x:has(.a + .b)', [d12]);
+ test_selector_all('.x:has(.a ~ .b)', [d02, d12]);
+
+ test_selector_all('.x:has(> .a)', [d02, d07, d09, d12]);
+ test_selector_all('.x:has(> .a > .b)', [d09]);
+ test_selector_all('.x:has(> .a .b)', [d09, d12]);
+ test_selector_all('.x:has(> .a + .b)', [d12]);
+ test_selector_all('.x:has(> .a ~ .b)', [d02, d12]);
+
+ test_selector_all('.x:has(+ .a)', [d19, d21, d24, d28, d32, d37, d40, d46]);
+ test_selector_all('.x:has(+ .a > .b)', [d21]);
+ test_selector_all('.x:has(+ .a .b)', [d21, d24]);
+ test_selector_all('.x:has(+ .a + .b)', [d28, d32, d37]);
+ test_selector_all('.x:has(+ .a ~ .b)', [d19, d21, d24, d28, d32, d37, d40]);
+
+ test_selector_all('.x:has(~ .a)', [d18, d19, d21, d24, d28, d32, d37, d40, d46]);
+ test_selector_all('.x:has(~ .a > .b)', [d18, d19, d21]);
+ test_selector_all('.x:has(~ .a .b)', [d18, d19, d21, d24]);
+ test_selector_all('.x:has(~ .a + .b)', [d18, d19, d21, d24, d28, d32, d37]);
+ test_selector_all('.x:has(~ .a + .b > .c)', [d18, d19, d21, d24, d28]);
+ test_selector_all('.x:has(~ .a + .b .c)', [d18, d19, d21, d24, d28, d32]);
+
+ test_selector_all('.x:has(.d .e)', [d48, d49, d50]);
+ test_selector_all('.x:has(.d .e) .f', [d54]);
+ test_selector_all('.x:has(> .d)', [d49, d50]);
+ test_selector_all('.x:has(> .d) .f', [d54]);
+ test_selector_all('.x:has(~ .d ~ .e)', [d48, d55, d56]);
+ test_selector_all('.x:has(~ .d ~ .e) ~ .f', [d60]);
+ test_selector_all('.x:has(+ .d ~ .e)', [d55, d56]);
+ test_selector_all('.x:has(+ .d ~ .e) ~ .f', [d60]);
+
+ test_selector_all('.y:has(> .g .h)', [d63, d71])
+ test_selector_all('.y:has(.g .h)', [d63, d68, d71])
+ test_selector_all('.y:has(> .g .h) .i', [d67, d75])
+ test_selector_all('.y:has(.g .h) .i', [d67, d75])
+
+ test_selector_all('.d .x:has(.e)', [d51, d52])
+
+ test_selector_all('.d ~ .x:has(~ .e)', [d57, d58])
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/has-sibling-chrome-crash.html b/testing/web-platform/tests/css/selectors/has-sibling-chrome-crash.html
new file mode 100644
index 0000000000..0306e3e392
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-sibling-chrome-crash.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>CSS Selectors Test: Chrome crash issue 1470477</title>
+<link rel="help" href="https://crbug.com/1470477">
+<style>
+ :has(> :where(label:first-child + [a="a"]:only-of-type,
+ [a="a"]:only-of-type + label:last-child)) label:last-child {
+ margin-inline: 1em;
+ }
+</style>
+<p>PASS if this tests does not crash</p>
diff --git a/testing/web-platform/tests/css/selectors/has-specificity.html b/testing/web-platform/tests/css/selectors/has-specificity.html
new file mode 100644
index 0000000000..69fcb5b1fb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-specificity.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Specificity for complex :has selectors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#specificity-rules">
+<style>
+ main :has(#foo) { --t0:PASS; }
+ main :has(.foo) { --t0:FAIL; }
+
+ main :has(span#foo) { --t1:PASS; }
+ main :has(#foo) { --t1:FAIL; }
+
+ main :has(.bar, #foo) { --t2:FAIL; }
+ main :has(#foo, .bar) { --t2:PASS; }
+
+ main :has(.bar, #foo) { --t3:PASS; }
+ main :has(.foo, .bar) { --t3:FAIL; }
+
+ main :has(span + span) { --t4:PASS; }
+ main :has(span) { --t4:FAIL; }
+
+ main :has(span, li, #foo) { --t5:PASS; }
+ main :has(span, li, p) { --t5:FAIL; }
+
+ main div:has(.foo) { --t6:FAIL; }
+ main div.baz { --t6:PASS; }
+
+ main div.baz { --t7:FAIL; }
+ main div:has(.foo) { --t7:PASS; }
+</style>
+<main id=main>
+ <div id=div class=baz><p><span id=foo class=foo></span><span class=bar></span><li></li></p></div>
+</main>
+<script>
+ function test_value(name, description) {
+ test(function() {
+ let actual = getComputedStyle(div).getPropertyValue(name);
+ assert_equals(actual, 'PASS');
+ }, description);
+ }
+
+ test_value('--t0', ':has(#foo) wins over :has(.foo)');
+ test_value('--t1', ':has(span#foo) wins over :has(#foo)');
+ test_value('--t2', ':has(.bar, #foo) has same specificity as :has(#foo, .bar)');
+ test_value('--t3', ':has(.bar, #foo) wins over :has(.foo, .bar)');
+ test_value('--t4', ':has(span + span) wins over :has(span)');
+ test_value('--t5', ':has(span, li, p) wins over :has(span, lo, p)');
+ test_value('--t6', 'latter .baz wins over :has(.foo)');
+ test_value('--t7', 'latter :has(.foo) wins over .baz');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-001-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-001-ref.html
new file mode 100644
index 0000000000..6013cb47d3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-001-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ padding: 1em;
+ margin: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ background-color: pink;
+}
+</style>
+<div style="background: green;"><span></span></div>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-001.html b/testing/web-platform/tests/css/selectors/has-style-sharing-001.html
new file mode 100644
index 0000000000..bf45e98cf2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-001.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<link rel="match" href="has-style-sharing-001-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ padding: 1em;
+ margin: 1em;
+}
+
+:has(> span) {
+ background: green;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ background-color: pink;
+}
+</style>
+<div><span></span></div>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-002-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-002-ref.html
new file mode 100644
index 0000000000..c916ab074f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-002-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ padding: 1em;
+ margin: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ background-color: pink;
+}
+</style>
+<div></div>
+<div style="background: green;"><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-002.html b/testing/web-platform/tests/css/selectors/has-style-sharing-002.html
new file mode 100644
index 0000000000..630a136186
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-002.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<link rel="match" href="has-style-sharing-002-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ padding: 1em;
+ margin: 1em;
+}
+
+:has(> span) {
+ background: green;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ background-color: pink;
+}
+</style>
+<div></div>
+<div><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-003-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-003-ref.html
new file mode 100644
index 0000000000..36aae7a103
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-003-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+.has-b {
+ background: green;
+}
+
+.b {
+ background: purple;
+}
+</style>
+
+<div><span class="has-b"></span><span class="a"></span></div>
+<div><span class="b"></span><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-003.html b/testing/web-platform/tests/css/selectors/has-style-sharing-003.html
new file mode 100644
index 0000000000..480a23e368
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-003.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<link rel="match" href="has-style-sharing-003-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+:has(> .a) .b {
+ background: green;
+}
+
+.b {
+ background: purple;
+}
+</style>
+
+<div><span class="b"></span><span class="a"></span></div>
+<div><span class="b"></span><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-004-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-004-ref.html
new file mode 100644
index 0000000000..f710924e31
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-004-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+.has-b {
+ background: green;
+}
+
+.b {
+ background: purple;
+}
+</style>
+
+<div><span class="b"></span><span></span></div>
+<div><span class="has-b"></span><span class="a"></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-004.html b/testing/web-platform/tests/css/selectors/has-style-sharing-004.html
new file mode 100644
index 0000000000..c0879f70ec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-004.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<link rel="match" href="has-style-sharing-004-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+:has(> .a) .b {
+ background: green;
+}
+
+.b {
+ background: purple;
+}
+</style>
+
+<div><span class="b"></span><span></span></div>
+<div><span class="b"></span><span class="a"></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-005-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-005-ref.html
new file mode 100644
index 0000000000..eb95d47373
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-005-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+.has-c {
+ background: green;
+}
+
+.c {
+ background: purple;
+}
+</style>
+<div><span class="b"><span class="has-c"></span></span><span class="a"></span></div>
+<div><span class="b"><span class="c"></span></span><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-005.html b/testing/web-platform/tests/css/selectors/has-style-sharing-005.html
new file mode 100644
index 0000000000..d6b05fc33d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-005.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<link rel="match" href="has-style-sharing-005-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+:has(> .a) .b .c {
+ background: green;
+}
+
+.c {
+ background: purple;
+}
+</style>
+<div><span class="b"><span class="c"></span></span><span class="a"></span></div>
+<div><span class="b"><span class="c"></span></span><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-006-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-006-ref.html
new file mode 100644
index 0000000000..4c03f2150a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-006-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+.has-c {
+ background: green;
+}
+
+.c {
+ background: purple;
+}
+</style>
+<div><span class="b"><span class="c"></span></span><span></span></div>
+<div><span class="b"><span class="has-c"></span></span><span class="a"></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-006.html b/testing/web-platform/tests/css/selectors/has-style-sharing-006.html
new file mode 100644
index 0000000000..e0d824f359
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-006.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012">
+<link rel="match" href="has-style-sharing-006-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ background: blue;
+ margin: 1em;
+ padding: 1em;
+}
+
+span {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+}
+
+:has(> .a) .b .c {
+ background: green;
+}
+
+.c {
+ background: purple;
+}
+</style>
+<div><span class="b"><span class="c"></span></span><span></span></div>
+<div><span class="b"><span class="c"></span></span><span class="a"></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-007-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-007-ref.html
new file mode 100644
index 0000000000..0f26fb2987
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-007-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1869771">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+.cousin {
+ width: 1em;
+ height: 1em;
+ background: purple;
+}
+.special.cousin.has {
+ background: blue;
+}
+</style>
+<div class="sib">
+ <div class="cousin"></div>
+</div>
+<br>
+<div class="sib">
+ <div class="cousin special"></div>
+ <br>
+ <div class="cousin special has"></div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-007.html b/testing/web-platform/tests/css/selectors/has-style-sharing-007.html
new file mode 100644
index 0000000000..494ff15796
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-007.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1869771">
+<link rel="match" href="has-style-sharing-007-ref.html">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+.cousin {
+ width: 1em;
+ height: 1em;
+ background: purple;
+}
+.special.cousin:not(:has(span)) {
+ background: blue;
+}
+</style>
+<div class="sib">
+ <div class="cousin"></div>
+</div>
+<br>
+<div class="sib">
+ <div class="cousin special">
+ <span></span>
+ </div>
+ <br>
+ <div class="cousin special"></div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001-ref.html
new file mode 100644
index 0000000000..c45db87fa3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.after::after {
+ font: 15px/1 Ahem;
+ content: "x";
+}
+</style>
+<div class="after"></div>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001.html
new file mode 100644
index 0000000000..6edb3da03e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-001.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-001-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+:has(> span)::after {
+ font: 15px/1 Ahem;
+ content: 'x';
+}
+</style>
+<div><span></span></div>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002-ref.html
new file mode 100644
index 0000000000..a8138c2572
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.after::after {
+ font: 15px/1 Ahem;
+ content: "x";
+}
+</style>
+<div></div>
+<div class="after"></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002.html
new file mode 100644
index 0000000000..59dd2a9a1b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-002.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-002-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+:has(> span)::after {
+ font: 15px/1 Ahem;
+ content: 'x';
+}
+</style>
+<div></div>
+<div><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003-ref.html
new file mode 100644
index 0000000000..a9b8e248d6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.after::after {
+ font: 15px/1 Ahem;
+ content: "x";
+}
+</style>
+<div><span class="after"></span><span></span></div>
+<div><span></span><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003.html
new file mode 100644
index 0000000000..f94636f5dc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-003.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-003-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+:has(> .a) .b::after {
+ font: 15px/1 ahem;
+ content: 'x';
+}
+</style>
+<div><span class="b"></span><span class="a"></span><span></span></div>
+<div><span class="b"></span></div>
+
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004-ref.html
new file mode 100644
index 0000000000..0d97e1d1c2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.after::after {
+ font: 15px/1 Ahem;
+ content: "x";
+}
+</style>
+<div><span></span><span></span></div>
+<div><span class="after"></span><span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004.html
new file mode 100644
index 0000000000..82e42005d0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-004.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-004-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+:has(> .a) .b::after {
+ font: 15px/1 ahem;
+ content: 'x';
+}
+</style>
+<div><span class="b"></span></div>
+<div><span class="b"></span><span class="a"></span><span></span></div>
+
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005-ref.html
new file mode 100644
index 0000000000..97c2bf2ade
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.after::after {
+ font: 15px/1 Ahem;
+ content: "x";
+}
+</style>
+<div><div class="after"><span></span></div></div>
+<div><div></div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005.html
new file mode 100644
index 0000000000..9e7cbe96fc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-005.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-005-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.cousin:has(> span)::after {
+ font: 15px/1 Ahem;
+ content: 'x';
+}
+</style>
+<div><div class="cousin"><span></span></div></div>
+<div><div class="cousin"></div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006-ref.html
new file mode 100644
index 0000000000..d052141d8e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.after::after {
+ font: 15px/1 Ahem;
+ content: "x";
+}
+</style>
+<div><div></div></div>
+<div><div class="after"><span></span></div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006.html
new file mode 100644
index 0000000000..d8747abd4a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-006.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-006-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+div {
+ width: 20px;
+ height: 20px;
+}
+
+.cousin:has(> span)::after {
+ font: 15px/1 Ahem;
+ content: 'x';
+}
+</style>
+<div><div class="cousin"></div></div>
+<div><div class="cousin"><span></span></div></div>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007-ref.html
new file mode 100644
index 0000000000..24f4502b78
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+::marker {
+ font: 15px/1 Ahem;
+}
+
+.no-marker::marker {
+ content: '';
+}
+</style>
+<ul>
+ <li class="no-marker"><span></span></li>
+ <li></li>
+</ul>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007.html
new file mode 100644
index 0000000000..0e245f5aaf
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-007.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-007-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+::marker {
+ font: 15px/1 Ahem;
+}
+
+:has(> span)::marker {
+ content: '';
+}
+</style>
+<ul>
+ <li><span></span></li>
+ <li></li>
+</ul>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008-ref.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008-ref.html
new file mode 100644
index 0000000000..ad293bab59
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+::marker {
+ font: 15px/1 Ahem;
+}
+
+.no-marker::marker {
+ content: '';
+}
+</style>
+<ul>
+ <li><span></span></li>
+ <li class="no-marker"></li>
+</ul>
diff --git a/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008.html b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008.html
new file mode 100644
index 0000000000..59844419ff
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-style-sharing-pseudo-008.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1876962">
+<link rel="match" href="has-style-sharing-pseudo-008-ref.html">
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching.">
+<style>
+::marker {
+ font: 15px/1 Ahem;
+}
+
+:has(> span)::marker {
+ content: '';
+}
+</style>
+<ul>
+ <li></li>
+ <li><span></span></li>
+</ul>
diff --git a/testing/web-platform/tests/css/selectors/has-visited-ref.html b/testing/web-platform/tests/css/selectors/has-visited-ref.html
new file mode 100644
index 0000000000..3f54e2e391
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-visited-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has combined with :visited/:link</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+ #parent1 {
+ color: green;
+ }
+ #parent2 {
+ color: black;
+ }
+ #parent3 {
+ color: yellowgreen;
+ }
+</style>
+<main>
+ <div id=parent1>
+ <div>parent color should be green with <a href="">visited link</a>.</div>
+ </div>
+ <div id=parent2>
+ <div>parent color should be black with <a href="unvisited">unvisited link</a>.</div>
+ </div>
+ <div id=parent3>
+ <div>parent color should be yellowgreen with <a href="unvisited">any link</a>.</div>
+ </div>
+</main> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/has-visited.html b/testing/web-platform/tests/css/selectors/has-visited.html
new file mode 100644
index 0000000000..8fe322c8b1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/has-visited.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has combined with :visited/:link</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="match" href="has-visited-ref.html">
+<style>
+ #parent1:has(:link) {
+ color: green;
+ }
+ #parent2:has(:visited) {
+ color: yellow;
+ }
+ #parent3:has(:any-link) {
+ color: yellowgreen;
+ }
+</style>
+<main>
+ <div id=parent1>
+ <div>parent color should be green with <a href="">visited link</a>.</div>
+ </div>
+ <div id=parent2>
+ <div>parent color should be black with <a href="unvisited">unvisited link</a>.</div>
+ </div>
+ <div id=parent3>
+ <div>parent color should be yellowgreen with <a href="unvisited">any link</a>.</div>
+ </div>
+</main> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/hash-collision.html b/testing/web-platform/tests/css/selectors/hash-collision.html
new file mode 100644
index 0000000000..04f15e7588
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/hash-collision.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test string hash collision in bucketing</title>
+ <meta rel="author" href="mailto:sesse@chromium.org" title="Steinar H. Gunderson">
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ /* These strings all collide in Blink's AtomicString hash function. */
+ .abetfx { --a: a; }
+ .adqcne { --b: b; }
+ .anztgy { --c: c; }
+ .jkeyea { --d: d; }
+ .ltjjvc { --e: e; }
+ .osniry { --f: f; }
+ .otgvil { --g: g; }
+ .ppvdzg { --h: h; }
+ .pwkbxn { --i: i; }
+ .rkefup { --j: j; }
+ .wsqwrf { --k: k; }
+ .zzpnvg { --l: l; }
+ </style>
+ </head>
+ <body>
+ <div id="d" class="abetfx adqcne anztgy jkeyea ltjjvc osniry otgvil ppvdzg pwkbxn rkefup wsqwrf zzpnvg">Some text</div>
+ <script>
+test(() => {
+ const cs = getComputedStyle(d);
+ assert_equals('a', cs.getPropertyValue('--a'));
+ assert_equals('b', cs.getPropertyValue('--b'));
+ assert_equals('c', cs.getPropertyValue('--c'));
+ assert_equals('d', cs.getPropertyValue('--d'));
+ assert_equals('e', cs.getPropertyValue('--e'));
+ assert_equals('f', cs.getPropertyValue('--f'));
+ assert_equals('g', cs.getPropertyValue('--g'));
+ assert_equals('h', cs.getPropertyValue('--h'));
+ assert_equals('i', cs.getPropertyValue('--i'));
+ assert_equals('j', cs.getPropertyValue('--j'));
+ assert_equals('k', cs.getPropertyValue('--k'));
+ assert_equals('l', cs.getPropertyValue('--l'));
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/historical-xmlid.xht b/testing/web-platform/tests/css/selectors/historical-xmlid.xht
new file mode 100644
index 0000000000..7916d9c120
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/historical-xmlid.xht
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>No xml:id support</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#id-selectors"/>
+ <link rel="help" href="https://dom.spec.whatwg.org/#concept-id"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css"><![CDATA[
+ div {
+ background: green;
+ height: 100px;
+ width: 100px;
+ }
+ #a {
+ background: red;
+ }
+ ]]></style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div xml:id="a"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/hover-001-manual.html b/testing/web-platform/tests/css/selectors/hover-001-manual.html
new file mode 100644
index 0000000000..87d7af91b6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/hover-001-manual.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>CSS Test (Selectors): hover pseudo-class when scrolling</title>
+ <link rel="author" title="Chris Rebert" href="http://chrisrebert.com" />
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-hover-pseudo" />
+ <link rel="help" href="http://www.w3.org/TR/selectors/#the-user-action-pseudo-classes-hover-act" />
+ <meta name="flags" content="interact scroll" />
+ <meta name="assert" content="Scrolling away from an element that was hovered over should cause the :hover pseudo-class to no longer match said element." />
+ <style>
+button {
+ background-color: white;
+ color: black;
+}
+button:hover {
+ background-color: blue;
+ color: white;
+}
+div {
+ height: 2000px;
+ width: 100px;
+}
+ </style>
+</head>
+<body>
+ <ol>
+ <li>If the user-agent does not claim to support the <code>:hover</code> pseudo-class (e.g. the pointing device cannot detect hovering), then SKIP this test.</li>
+ <li>If the user-agent does not allow scrolling the document while leaving the pointer in the same position relative to the viewport, then SKIP this test.</li>
+ <li>Ensure that this document is scrolled all the way to the top.</li>
+ <li>Hover the pointer device over the button below.</li>
+ <li>If the button is not blue, then the test result is FAILURE.</li>
+ <li>
+ Scroll this document down while not moving the pointer at all, until the pointer no longer touches the button. For example, on a traditional desktop or laptop computer, keep the mouse perfectly still and do one of the following:
+ <ul>
+ <li>Press the "Page Down" key on the keyboard.</li>
+ <li>Press the "↓" key on the keyboard.</li>
+ <li>Roll the mouse's scrollwheel.</li>
+ <li>Perform a "scroll down" gesture on the trackpad</li>
+ </ul>
+ </li>
+ <li>If the button is blue, then the test result is FAILURE. If the button is white, then the test result is SUCCESS.</li>
+ </ol>
+ <br />
+ <button>Hover over me.</button>
+ <div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/hover-002.html b/testing/web-platform/tests/css/selectors/hover-002.html
new file mode 100644
index 0000000000..02cee99bf6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/hover-002.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors: Change class to enable :hover</title>
+<link rel="author" title="Rune Lillesveen" href="futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors/#the-hover-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ .affected:hover { color: green }
+ #hoveredContents { display: contents }
+</style>
+<div id="hovered">Hover me - should become green</div>
+<div id="hoveredContents">
+ <div id="hovered2">Hover me - should become green</div>
+</div>
+<script>
+ function mouseMoveToTarget(selector) {
+ let target = document.querySelector(selector);
+ return new test_driver.Actions().pointerMove(0, 0, {origin: target})
+ .send();
+ }
+
+ function testElementGreen(test, element) {
+ element.addEventListener("mouseover", test.step_func(event => {
+ assert_equals(getComputedStyle(element).color, "rgb(0, 128, 0)");
+ test.done();
+ }));
+ }
+
+ // Setting the affected classes here makes the two elements go from never
+ // reacting to hover to being affected by hover without changing computed
+ // style.
+ hovered.offsetTop;
+ hovered.className = "affected";
+ hoveredContents.className = "affected";
+
+ async_test(t => { testElementGreen(t, hovered); }, "Hover #hovered element should make it go green");
+ async_test(t => { testElementGreen(t, hovered2); }, "Hover #hoveredContents child should make it go green");
+
+ mouseMoveToTarget("#hovered").then(() => {
+ mouseMoveToTarget("#hovered2");
+ });
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/i18n/META.yml b/testing/web-platform/tests/css/selectors/i18n/META.yml
new file mode 100644
index 0000000000..9fa8c3b6c9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/META.yml
@@ -0,0 +1,2 @@
+suggested_reviewers:
+ - r12a
diff --git a/testing/web-platform/tests/css/selectors/i18n/README b/testing/web-platform/tests/css/selectors/i18n/README
new file mode 100644
index 0000000000..df60c5800a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/README
@@ -0,0 +1,2 @@
+See http://www.w3.org/International/tests/
+
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-001.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-001.html
new file mode 100644
index 0000000000..e88f20a024
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-001.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es), lang="es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box:lang(es) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value that matches an identical lang attribute value on the same element will produce styling.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-002.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-002.html
new file mode 100644
index 0000000000..71ae3d46f6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-002.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es), lang="es" on parent</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box:lang(es) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test" lang="es"><div id="box">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value that matches an identical lang attribute value on a parent element will produce styling.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-004.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-004.html
new file mode 100644
index 0000000000..cbf4813e42
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-004.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es), lang="ES"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(es) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="ES">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value will match a lang attribute value regardless of case differences.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-005.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-005.html
new file mode 100644
index 0000000000..1c46c450f2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-005.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es), lang="es-MX"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(es) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es-MX">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value will match a lang attribute value when the latter contains additional subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-006.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-006.html
new file mode 100644
index 0000000000..2eb9dd68ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-006.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es-MX), lang="es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(es-MX) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A :lang value will NOT match a lang attribute value when the former contains more subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-007.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-007.html
new file mode 100644
index 0000000000..491697a385
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-007.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es), lang="mx-es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(es-MX) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="mx-es">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "When the :lang value uses a single subtag, it will NOT match against an attribute value where it appears in a different position.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-008.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-008.html
new file mode 100644
index 0000000000..64724fcb4e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-008.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(en-GB), lang="en-GB"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(en-GB) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-GB">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value with language and region subtags will match a lang attribute value with the same subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-009.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-009.html
new file mode 100644
index 0000000000..3d89b2aacf
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-009.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(en-GB), lang="en-GB-scouse"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(en-GB) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-GB-scouse">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value with a multiple subtags will match a lang attribute value with multiple subtags as long as the first part is the same.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-010.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-010.html
new file mode 100644
index 0000000000..c77bc61aed
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-010.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(en-GB), lang="en-US"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(en-GB) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-US">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A :lang value and a lang attribute value will NOT match if their region subtags differ.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-011.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-011.html
new file mode 100644
index 0000000000..648e937e97
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-011.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(az-Arab-IR), lang="az-Arab-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(az-Arab-IR) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-Arab-IR">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value with language, script and region subtags will match a lang attribute value with the same language, script and region subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-012.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-012.html
new file mode 100644
index 0000000000..36f4aad202
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-012.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(az-Arab-IR), lang="az-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(az-Arab-IR) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-IR">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A :lang value with language, script and region subtags will NOT match a lang attribute value with the script subtag missing.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-014.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-014.html
new file mode 100644
index 0000000000..411d50d35e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-014.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(cs-CZ), lang="cs-Latn-CZ"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(cs-CZ) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="cs-Latn-CZ">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_in_array(document.getElementById('box').offsetWidth, [50, 100]);
+}, "A :lang value with language and region subtags will match a lang attribute value with language, script and region subtags under CSS Selectors 4, but not Selectors 3.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-015.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-015.html
new file mode 100644
index 0000000000..ac91535d87
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-015.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(az-Arab-IR), lang="az-arab-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(az-Arab-IR) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-arab-IR">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A :lang value will match a lang attribute value regardless of case differences in the script tag.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-016.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-016.html
new file mode 100644
index 0000000000..6d1ac01875
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-016.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>:lang(es), xml:lang="es" (html)</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#lang-pseudo'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+#box:lang(es) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" xml:lang="es">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to :lang support. If :lang is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A :lang value that matches an identical xml:lang attribute value will NOT produce styling in pages served as HTML.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-021.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-021.html
new file mode 100644
index 0000000000..04cc4431b8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-021.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es"], lang="es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang|='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value that matches an identical lang attribute value on the same element will produce styling.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-022.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-022.html
new file mode 100644
index 0000000000..b4ed986971
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-022.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es"], lang="es" on parent</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang|='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test" lang="es"><div id="box">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang|= value that matches an identical lang attribute value on the parent element will NOT produce styling.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-024.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-024.html
new file mode 100644
index 0000000000..5b1847dd78
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-024.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es"], lang="ES"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='es'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="ES">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value will match a lang attribute value regardless of case differences.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-025.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-025.html
new file mode 100644
index 0000000000..2e2f0c3e5f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-025.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es"], lang="es-MX"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='es'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es-MX">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value will match a lang attribute value when the latter contains additional subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-026.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-026.html
new file mode 100644
index 0000000000..2deb49a3fc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-026.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es-MX"], lang="es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='es-MX'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang|= value will NOT match a lang attribute value when the former contains more subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-027.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-027.html
new file mode 100644
index 0000000000..b8af60ea23
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-027.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es"], lang="mx-es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='es'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="mx-es">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "When the lang|= value uses a single subtag, it will NOT match against an attribute value where it appears in a different position.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-028.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-028.html
new file mode 100644
index 0000000000..ea6a509d6a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-028.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="en-GB"], lang="en-GB"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='en-GB'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-GB">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value with language and region subtags will match a lang attribute value with the same subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-029.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-029.html
new file mode 100644
index 0000000000..1abf1ad490
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-029.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="en-GB"], lang="en-GB-scouse"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='en-GB'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-GB-scouse">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value with a multiple subtags will match a lang attribute value with multiple subtags as long as the first part is the same.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-030.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-030.html
new file mode 100644
index 0000000000..8bac2befb3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-030.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="en-GB"], lang="en-US"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='es-GB'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-US">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang|= value and a lang attribute value will NOT match if their region subtags differ.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-031.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-031.html
new file mode 100644
index 0000000000..5baedd2846
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-031.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="az-Arab-IR"], lang="az-Arab-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='az-Arab-IR'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-Arab-IR">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value with language, script and region subtags will match a lang attribute value with the same language, script and region subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-032.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-032.html
new file mode 100644
index 0000000000..4d19ef9537
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-032.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="az-Arab-IR"], lang="az-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='az-Arab-IR'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-IR">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang|= value with language, script and region subtags will NOT match a lang attribute value with the script subtag missing.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-034.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-034.html
new file mode 100644
index 0000000000..aa7b582100
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-034.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="cs-CZ"], lang="cs-Latn-CZ"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='cs-CZ'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="cs-Latn-CZ">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang|= value with language and region subtags will NOT match a lang attribute value with language, script and region subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-035.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-035.html
new file mode 100644
index 0000000000..8c00b6a62c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-035.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="az-Arab-IR"], lang="az-arab-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='az-Arab-IR'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-arab-IR">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang|= value will match a lang attribute value regardless of case differences in the script tag.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-036.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-036.html
new file mode 100644
index 0000000000..61ba345383
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-036.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang|="es"], xml:lang="es" (html)</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest[lang|=xx] { display:none; }
+#box[lang|='es'] { width: 100px; }
+#relevance[lang|='yy'] { display:none; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" xml:lang="es">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on [lang|=..] for results, but [lang|=..] is not supported by this browser.
+
+
+<!--Notes:
+This tests a detail related to [lang|=..] support. If [lang|=..] is not supported, a message will appear and the test will fail.
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A [lang|='es'] value that matches an identical xml:lang attribute value will NOT produce styling in pages served as HTML.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-041.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-041.html
new file mode 100644
index 0000000000..1de94e2b92
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-041.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es"], lang="es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang= value that matches an identical lang attribute value on the same element will produce styling.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-042.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-042.html
new file mode 100644
index 0000000000..5f8d799c70
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-042.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es"], lang="es" on parent</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test" lang="es"><div id="box">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang|= value that matches an identical lang attribute value on the parent element will NOT produce styling.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-044.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-044.html
new file mode 100644
index 0000000000..bab7033cec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-044.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es"], lang="ES"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="ES">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang= value will match a lang attribute value regardless of case differences.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-045.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-045.html
new file mode 100644
index 0000000000..96941e91ab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-045.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es"], lang="es-MX"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es-MX">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang= value will NOT match a lang attribute value when the latter contains additional subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-046.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-046.html
new file mode 100644
index 0000000000..07af0a2285
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-046.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es-MX"], lang="es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es-MX'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="es">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang= value will NOT match a lang attribute value when the former contains more subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-047.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-047.html
new file mode 100644
index 0000000000..a56364395c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-047.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es"], lang="mx-es"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="mx-es">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "When the lang= value uses a single subtag, it will NOT match against an attribute value where it appears in a different position.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-048.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-048.html
new file mode 100644
index 0000000000..4c8f297f7f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-048.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="en-GB"], lang="en-GB"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='en-GB'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-GB">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang= value with language and region subtags will match a lang attribute value with the same subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-049.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-049.html
new file mode 100644
index 0000000000..b7d1a7ebf6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-049.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="en-GB"], lang="en-GB-scouse"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='en-GB'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-GB-scouse">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang= value with multiple subtags will NOT match a lang attribute value with multiple subtags if the latter has more subtags, even if the first two subtags are the same.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-050.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-050.html
new file mode 100644
index 0000000000..52d7bf1c17
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-050.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="en-GB"], lang="en-US"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='en-GB'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="en-US">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang= value and a lang attribute value will NOT match if their region subtags differ.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-051.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-051.html
new file mode 100644
index 0000000000..7881d53256
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-051.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="az-Arab-IR"], lang="az-Arab-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='az-Arab-IR'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-Arab-IR">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang= value with language, script and region subtags will match a lang attribute value with the same language, script and region subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-052.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-052.html
new file mode 100644
index 0000000000..386a717cb3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-052.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="az-Arab-IR"], lang="az-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='az-Arab-IR'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-IR">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang= value with language, script and region subtags will NOT match a lang attribute value with the script subtag missing.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-054.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-054.html
new file mode 100644
index 0000000000..8732daf05e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-054.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="cs-CZ"], lang="cs-Latn-CZ"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='cs-CZ'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="cs-Latn-CZ">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A lang= value with language and region subtags will NOT match a lang attribute value with language, script and region subtags.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-055.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-055.html
new file mode 100644
index 0000000000..388a287ae9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-055.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="az-Arab-IR"], lang="az-arab-IR"</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='az-Arab-IR'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" lang="az-arab-IR">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A lang= value will match a lang attribute value regardless of case differences in the script tag.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-056.html b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-056.html
new file mode 100644
index 0000000000..8bec0fab08
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/css3-selectors-lang-056.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>[lang="es"], xml:lang="es" (html)</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='http://www.w3.org/TR/css3-selectors/#attribute-selectors'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='HTMLonly'>
+<style type='text/css'>
+.test div { width: 50px; }
+#box[lang='es'] { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" xml:lang="es">&#xA0;</div></div>
+
+
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "A [lang='es'] value that matches an identical xml:lang attribute value will NOT produce styling in pages served as HTML.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries-ref.html b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries-ref.html
new file mode 100644
index 0000000000..eda713a7ed
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <p>Test passes if you see a single 100px by 100px green box below.</p>
+ <div style="width: 100px; height: 100px; background: green;"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries.html b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries.html
new file mode 100644
index 0000000000..ec1e156498
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-across-shadow-boundaries.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo">
+<link rel="match" href="lang-pseudo-class-across-shadow-boundaries-ref.html">
+</head>
+<body>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<style>
+#testCases div { width: 100px; height: 25px; }
+#host1:lang(zh) { background: green; }
+#host3 > :lang(ja) { background: green; }
+#host4 > div { background: red; }
+</style>
+<div id="testCases">
+<div id="host1" lang="zh"><div></div></div>
+<div id="host2" lang="de"><div></div></div>
+<div id="host3" lang="ja"><div></div></div>
+<div id="host4"><div></div></div>
+</div>
+<script>
+host1.attachShadow({mode: 'closed'}).innerHTML = '<slot></slot>';
+host2.attachShadow({mode: 'closed'}).innerHTML = '<style> div { width: 100px; height: 25px; background: red; } div:lang(de) { background: green; } </style><div></div>';
+host3.attachShadow({mode: 'closed'}).innerHTML = '<slot lang="en"></slot>';
+host4.attachShadow({mode: 'closed'}).innerHTML = '<style> :lang(ja)::slotted(*) { background: green !important; } </style><slot lang="ja"></slot>';
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-disconnected.html b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-disconnected.html
new file mode 100644
index 0000000000..30bb773a31
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-disconnected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo"/>
+<body>
+<div id="container" lang="zh"><span></span></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+ let target = container.querySelector('span');
+ assert_true(target.matches(":lang(zh)"));
+ target.parentNode.remove();
+ assert_true(target.matches(":lang(zh)"));
+
+ const anotherContainer = document.createElement('div');
+ anotherContainer.innerHTML = '<div lang="fr"><span></span></div>';
+ target = anotherContainer.querySelector('span');
+ assert_true(target.matches(":lang(fr)"));
+ document.body.append(target.parentNode);
+ assert_true(target.matches(":lang(fr)"));
+}, ":lang pseudo class should work in a disconnected subtree");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-empty-attribute.xhtml b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-empty-attribute.xhtml
new file mode 100644
index 0000000000..5765e0bae1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/i18n/lang-pseudo-class-empty-attribute.xhtml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo"/>
+ <style type="text/css">
+ span {background: white;display:none}
+ span:lang(de) {background: red}
+ </style>
+ </head>
+ <body>
+ <p>Tests if empty language declarations are supported</p>
+ <p xml:lang="de">
+ <span lang="" id="emptyLang"/>
+ <span xml:lang="" id="emptyXmlLang"/>
+ <span id="noLang"/>
+ </p>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ test(() => {
+ assert_equals(getComputedStyle(document.getElementById("emptyLang")).backgroundColor, "rgb(255, 255, 255)");
+ assert_equals(getComputedStyle(document.getElementById("emptyXmlLang")).backgroundColor, "rgb(255, 255, 255)");
+ assert_equals(getComputedStyle(document.getElementById("noLang")).backgroundColor, "rgb(255, 0, 0)");
+ }, "Test if empty language attributes are supported");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal-ref.html b/testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal-ref.html
new file mode 100644
index 0000000000..b5407429be
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS test reference</title>
+<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu">
+<style>
+ span { color: green; }
+</style>
+<body>
+ <a></a><span>This should be green</span>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal.html b/testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal.html
new file mode 100644
index 0000000000..9da6b2edeb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/any-link-attribute-removal.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS test: Handling of dynamic changes to :any-link selectors</title>
+<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu">
+<link rel="match" href="any-link-attribute-removal-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-any-link-pseudo">
+<style>
+ span { color: green; }
+ :any-link + span { color: red; }
+</style>
+<body onload="window.oldColor = getComputedStyle(document.querySelector('span')).color;
+ document.querySelector('a').removeAttribute('href');">
+ <a href=""></a><span>This should be green</span>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/any-link-pseudo.html b/testing/web-platform/tests/css/selectors/invalidation/any-link-pseudo.html
new file mode 100644
index 0000000000..9792fd0ebe
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/any-link-pseudo.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: :any-link</title>
+ <link rel="author" title="Victoria Su" href="mailto:victoriaytsu@google.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-any-link-pseudo">
+ <meta name="assert" content="This tests that the :any-link selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #link { background-color: red }
+ #link:any-link { background-color: green }
+ #link + div { color: pink }
+ </style>
+ <a id="link">This link should have a green background.</a>
+ <div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ </div>
+ <script>
+ test(function() {
+ var red = "rgb(255, 0, 0)";
+ var green = "rgb(0, 128, 0)";
+
+ assert_equals(getComputedStyle(link).backgroundColor, red);
+
+ link.href = "not-visited.html";
+
+ assert_equals(getComputedStyle(link).backgroundColor, green);
+ }, "Style was recalculated for the :any-link pseudo class.");
+
+ </script>
+ </head>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html
new file mode 100644
index 0000000000..d0edb1e5e4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/attribute-or-elemental-selectors-in-has.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :has() invalidation basic</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+.subject:has(> .child) { color: red }
+.subject:has(.descendant) { color: green }
+.subject:has([attrname=descendant]) { color: blue }
+.subject:has(#div_descendant) { color: yellow }
+.subject:has(descendant) { color: yellowgreen }
+</style>
+<main id=main>
+ <div id=div_subject class="subject">
+ <div id=div_child>
+ <div id=div_grandchild></div>
+ </div>
+ </div>
+</main>
+<script>
+ let grey = 'rgb(128, 128, 128)';
+ let red = 'rgb(255, 0, 0)';
+ let green = 'rgb(0, 128, 0)';
+ let blue = 'rgb(0, 0, 255)';
+ let yellow = 'rgb(255, 255, 0)';
+ let yellowgreen = 'rgb(154, 205, 50)';
+
+ function test_div(test_name, el, color) {
+ test(function() {
+ assert_equals(getComputedStyle(el).color, color);
+ }, test_name + ': div#' + el.id + '.color');
+ }
+
+ test_div('initial_color', div_subject, grey);
+ test_div('initial_color', div_child, grey);
+ test_div('initial_color', div_grandchild, grey);
+
+ div_child.classList.add('child');
+ test_div('add .child to #div_child', div_subject, red);
+ div_child.classList.remove('child');
+ test_div('remove .child from #div_child', div_subject, grey);
+
+ div_grandchild.classList.add('child');
+ test_div('add .child to #div_grandchild', div_subject, grey);
+ div_grandchild.classList.remove('child');
+ test_div('remove .child from #div_grandchild', div_subject, grey);
+
+ div_child.classList.add('descendant');
+ test_div('add .descendant to #div_child', div_subject, green);
+ div_child.classList.remove('descendant');
+ test_div('remove .descendant from #div_child', div_subject, grey);
+
+ div_grandchild.classList.add('descendant');
+ test_div('add .descendant to #div_grandchild', div_subject, green);
+ div_grandchild.classList.remove('descendant');
+ test_div('remove .descendant from #div_grandchild', div_subject, grey);
+
+ div_grandchild.setAttribute('attrname', 'descendant');
+ test_div('set descendant to #div_grandchild[attrname]', div_subject, blue);
+ div_grandchild.setAttribute('attrname', '');
+ test_div('clear #div_grandchild[attrname]', div_subject, grey);
+
+ div_grandchild.id = 'div_descendant';
+ test_div('change #div_grandchild to #div_descendant', div_subject, yellow);
+ div_descendant.id = 'div_grandchild';
+ test_div('change #div_descendant to #div_grandchild', div_subject, grey);
+
+ {
+ const descendant = document.createElement('descendant');
+ div_subject.appendChild(descendant);
+ test_div('add descendant to #div_subject', div_subject, yellowgreen);
+ div_subject.removeChild(descendant);
+ test_div('remove descendant from #div_subject', div_subject, grey);
+ }
+
+ {
+ const div = document.createElement('div');
+ const descendant = document.createElement('descendant');
+ div.appendChild(descendant);
+ div_subject.appendChild(div);
+ test_div('add "div > descendant" to #div_subject', div_subject, yellowgreen);
+ div_subject.removeChild(div);
+ test_div('remove "div > descendant" from #div_subject', div_subject, grey);
+ }
+
+ {
+ const child = document.createElement('div');
+ child.classList.add('child');
+ div_subject.appendChild(child);
+ test_div('add div.child to #div_subject', div_subject, red);
+ div_subject.removeChild(child);
+ test_div('remove div.child from #div_subject', div_subject, grey);
+ }
+
+ {
+ const descendant = document.createElement('div');
+ descendant.classList.add('descendant');
+ const div = document.createElement('div');
+ div.appendChild(descendant);
+ div_subject.appendChild(div);
+ test_div('add "div > div.descendant" to #div_subject', div_subject, green);
+ div_subject.removeChild(div);
+ test_div('remove "div > div.descendant" from #div_subject', div_subject, grey);
+ }
+
+ {
+ const child = document.createElement('div');
+ child.id = 'div_descendant';
+ div_subject.appendChild(child);
+ test_div('add div#div_descendant to #div_subject', div_subject, yellow);
+ div_subject.removeChild(child);
+ test_div('remove div#div_descendant from #div_subject', div_subject, grey);
+ }
+
+ {
+ const descendant = document.createElement('div');
+ descendant.id = 'div_descendant';
+ const div = document.createElement('div');
+ div.appendChild(descendant);
+ div_subject.appendChild(div);
+ test_div('add "div#div_descendant" to #div_subject', div_subject, yellow);
+ div_subject.removeChild(div);
+ test_div('remove "div#div_descendant" from #div_subject', div_subject, grey);
+ }
+
+ {
+ const child = document.createElement('div');
+ child.setAttribute('attrname', 'descendant');
+ div_subject.appendChild(child);
+ test_div('add div[attrname] to #div_subject', div_subject, blue);
+ div_subject.removeChild(child);
+ test_div('remove div[attrname] from #div_subject', div_subject, grey);
+ }
+
+ {
+ const descendant = document.createElement('div');
+ descendant.setAttribute('attrname', 'descendant');
+ const div = document.createElement('div');
+ div.appendChild(descendant);
+ div_subject.appendChild(div);
+ test_div('add "div > div[attrname]" to #div_subject', div_subject, blue);
+ div_subject.removeChild(div);
+ test_div('remove "div > div[attrname]" from #div_subject', div_subject, grey);
+ }
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/attribute.html b/testing/web-platform/tests/css/selectors/invalidation/attribute.html
new file mode 100644
index 0000000000..3bda52c91d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/attribute.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: attribute</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#attribute-selectors">
+ <meta name="assert" content="This tests that the attribute selectors are effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ div {
+ color: gray;
+ }
+
+ #a1[style] {
+ color: blue;
+ }
+ #a1[style] > #b1 {
+ color: green;
+ }
+ #a1[style] #c1 {
+ color: red;
+ }
+ #a1[style] + #d1 {
+ color: yellow;
+ }
+
+ [id=a2] {
+ color: blue;
+ }
+ [id=a2] > #b2 {
+ color: green;
+ }
+ [id=a2] #c2 {
+ color: red;
+ }
+ [id=a2] + #d2 {
+ color: yellow;
+ }
+
+ #a3[class~=q] {
+ color: blue;
+ }
+ #a3[class~=q] > #b3 {
+ color: green;
+ }
+ #a3[class~=q] #c3 {
+ color: red;
+ }
+ #a3[class~=q] + #d3 {
+ color: yellow;
+ }
+
+ #a4[run|=one] {
+ color: blue;
+ }
+ #a4[run|=one] > #b4 {
+ color: green;
+ }
+ #a4[run|=one] #c4 {
+ color: red;
+ }
+ #a4[run|=one] + #d4 {
+ color: yellow;
+ }
+
+ #a5 {
+ color: blue;
+ }
+ #a5 > #b5 {
+ color: green;
+ }
+ #a5 #c5 {
+ color: red;
+ }
+ #a5 + #d5 {
+ color: yellow;
+ }
+
+ #a6.q {
+ color: blue;
+ }
+ #a6.q > #b6 {
+ color: green;
+ }
+ #a6.q #c6 {
+ color: red;
+ }
+ #a6.q + #d6 {
+ color: yellow;
+ }
+
+ </style>
+ </head>
+ <body>
+
+ <div id="a1">
+ <div id="b1">
+ <div id="c1">
+ </div>
+ </div>
+ </div>
+ <div id="d1">
+ </div>
+
+ <div>
+ <div id="b2">
+ <div id="c2">
+ </div>
+ </div>
+ </div>
+ <div id="d2">
+ </div>
+
+ <div id="a3">
+ <div id="b3">
+ <div id="c3">
+ </div>
+ </div>
+ </div>
+ <div id="d3">
+ </div>
+
+ <div id="a4">
+ <div id="b4">
+ <div id="c4">
+ </div>
+ </div>
+ </div>
+ <div id="d4">
+ </div>
+
+ <div>
+ <div id="b5">
+ <div id="c5">
+ </div>
+ </div>
+ </div>
+ <div id="d5">
+ </div>
+
+ <div id="a6">
+ <div id="b6">
+ <div id="c6">
+ </div>
+ </div>
+ </div>
+ <div id="d6">
+ </div>
+
+ <script>
+ const gray = "rgb(128, 128, 128)";
+ const blue = "rgb(0, 0, 255)";
+ const green = "rgb(0, 128, 0)";
+ const red = "rgb(255, 0, 0)";
+ const yellow = "rgb(255, 255, 0)";
+
+ function assertGray(a, b, c, d) {
+ assert_equals(getComputedStyle(a).color, gray);
+ assert_equals(getComputedStyle(b).color, gray);
+ assert_equals(getComputedStyle(c).color, gray);
+ assert_equals(getComputedStyle(d).color, gray);
+ }
+
+ function assertColorful(a, b, c, d) {
+ assert_equals(getComputedStyle(a).color, blue);
+ assert_equals(getComputedStyle(b).color, green);
+ assert_equals(getComputedStyle(c).color, red);
+ assert_equals(getComputedStyle(d).color, yellow);
+ }
+
+ test(() => {
+ assertGray(a1, b1, c1, d1);
+ a1.style.visibility = "visible";
+ assertColorful(a1, b1, c1, d1);
+ a1.removeAttribute('style');
+ assertGray(a1, b1, c1, d1);
+ }, "[att] selector is effective");
+
+ test(() => {
+ const a2 = b2.parentElement;
+ assertGray(a2, b2, c2, d2);
+ a2.id = 'x-a2';
+ assertGray(a2, b2, c2, d2);
+ a2.id = 'a2';
+ assertColorful(a2, b2, c2, d2);
+ a2.id = 'a2-y';
+ assertGray(a2, b2, c2, d2);
+ }, "[att=val] selector is effective");
+
+ test(() => {
+ assertGray(a3, b3, c3, d3);
+ a3.setAttribute('class', 'p q r');
+ assertColorful(a3, b3, c3, d3);
+ a3.setAttribute('class', 'q-r');
+ assertGray(a3, b3, c3, d3);
+ }, "[att~=val] selector is effective");
+
+ test(() => {
+ assertGray(a4, b4, c4, d4);
+ a4.setAttribute('run', 'one');
+ assertColorful(a4, b4, c4, d4);
+ a4.setAttribute('run', 'one two three');
+ assertGray(a4, b4, c4, d4);
+ a4.setAttribute('run', 'one-two-three');
+ assertColorful(a4, b4, c4, d4);
+ a4.setAttribute('run', 'zero-one');
+ assertGray(a4, b4, c4, d4);
+ }, "[att|=val] selector is effective");
+
+ test(() => {
+ const a5 = b5.parentElement;
+ assertGray(a5, b5, c5, d5);
+ a5.setAttribute('id', 'x-a5');
+ assertGray(a5, b5, c5, d5);
+ a5.setAttribute('id', 'a5');
+ assertColorful(a5, b5, c5, d5);
+ a5.setAttribute('id', 'a5-y');
+ assertGray(a5, b5, c5, d5);
+ }, "#id selector is effective");
+
+ test(() => {
+ assertGray(a6, b6, c6, d6);
+ a6.classList.add('p');
+ a6.classList.add('q');
+ a6.classList.add('r');
+ assertColorful(a6, b6, c6, d6);
+ a6.classList.remove('q');
+ a6.classList.add('q-r');
+ assertGray(a6, b6, c6, d6);
+ }, ".class selector is effective");
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/child-indexed-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/child-indexed-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..5c689e2333
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/child-indexed-pseudo-classes-in-has.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: child-indexed pseudo classes in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #container ~ div { color: grey }
+ #container:has(:only-child) ~ #only_child { color: red }
+ #container:has(.orange:first-child) ~ #first_child { color: orange }
+ #container:has(.yellow:first-child) ~ #first_child { color: yellow }
+ #container:has(.green:first-child) ~ #first_child { color: green }
+ #container:has(.orange:last-child) ~ #last_child { color: orange }
+ #container:has(.yellow:last-child) ~ #last_child { color: yellow }
+ #container:has(.green:last-child) ~ #last_child { color: green }
+ #container:has(.orange:nth-child(3n)) ~ #nth_child_3n { color: orange }
+ #container:has(.yellow:nth-child(3n)) ~ #nth_child_3n { color: yellow }
+ #container:has(.green:nth-child(3n)) ~ #nth_child_3n { color: green }
+ #container:has(.orange:nth-child(3n+1)) ~ #nth_child_3n_1 { color: orange }
+ #container:has(.yellow:nth-child(3n+1)) ~ #nth_child_3n_1 { color: yellow }
+ #container:has(.green:nth-child(3n+1)) ~ #nth_child_3n_1 { color: green }
+ #container:has(.orange:nth-child(3n+2)) ~ #nth_child_3n_2 { color: orange }
+ #container:has(.yellow:nth-child(3n+2)) ~ #nth_child_3n_2 { color: yellow }
+ #container:has(.green:nth-child(3n+2)) ~ #nth_child_3n_2 { color: green }
+ #container:has(.orange:nth-child(3n)) ~ #nth_child_3n { color: orange }
+ #container:has(.yellow:nth-child(3n)) ~ #nth_child_3n { color: yellow }
+ #container:has(.green:nth-child(3n)) ~ #nth_child_3n { color: green }
+</style>
+<div id="container">
+</div>
+<div id="only_child"></div>
+<div id="first_child"></div>
+<div id="last_child"></div>
+<div id="nth_child_3n_1"></div>
+<div id="nth_child_3n_2"></div>
+<div id="nth_child_3n"></div>
+<script>
+const grey = "rgb(128, 128, 128)";
+const red = "rgb(255, 0, 0)";
+const orange = "rgb(255, 165, 0)";
+const yellow = "rgb(255, 255, 0)";
+const green = "rgb(0, 128, 0)";
+
+function testColors(test_name,
+ only_child_color,
+ first_child_color,
+ last_child_color,
+ nth_child_3n_1_color,
+ nth_child_3n_2_color,
+ nth_child_3n_color) {
+ test(function() {
+ assert_equals(getComputedStyle(only_child).color, only_child_color);
+ }, test_name + ": #only_child");
+ test(function() {
+ assert_equals(getComputedStyle(first_child).color, first_child_color);
+ }, test_name + ": #first_child");
+ test(function() {
+ assert_equals(getComputedStyle(last_child).color, last_child_color);
+ }, test_name + ": #last_child");
+ test(function() {
+ assert_equals(getComputedStyle(nth_child_3n_1).color, nth_child_3n_1_color);
+ }, test_name + ": #nth_child_3n_1");
+ test(function() {
+ assert_equals(getComputedStyle(nth_child_3n_2).color, nth_child_3n_2_color);
+ }, test_name + ": #nth_child_3n_2");
+ test(function() {
+ assert_equals(getComputedStyle(nth_child_3n).color, nth_child_3n_color);
+ }, test_name + ": #nth_child_3n");
+}
+
+testColors("Initial colors", grey, grey, grey, grey, grey, grey);
+
+let div1 = document.createElement("div");
+div1.id = "div1";
+div1.classList.add("green");
+container.insertBefore(div1, container.firstChild);
+testColors("Prepend #div1.green", red, green, green, green, grey, grey);
+
+let div2 = document.createElement("div");
+div2.id = "div2";
+div2.classList.add("yellow");
+container.insertBefore(div2, container.firstChild);
+testColors("Prepend #div2.yellow", grey, yellow, green, yellow, green, grey);
+
+let div3 = document.createElement("div");
+div3.id = "div3";
+div3.classList.add("orange");
+container.insertBefore(div3, container.firstChild);
+testColors("Prepend #div3.orange", grey, orange, green, orange, yellow, green);
+
+let div4 = document.createElement("div");
+div4.id = "div4";
+container.insertBefore(div4, container.firstChild);
+testColors("Prepend #div4", grey, grey, green, green, orange, yellow);
+
+let div5 = document.createElement("div");
+div5.id = "div5";
+container.insertBefore(div5, container.firstChild);
+testColors("Prepend #div5", grey, grey, green, yellow, green, orange);
+
+div1.remove();
+testColors("Remove #div1", grey, grey, yellow, yellow, grey, orange);
+
+div2.remove();
+testColors("Remove #div2", grey, grey, orange, grey, grey, orange);
+
+div3.remove();
+testColors("Remove #div3", grey, grey, grey, grey, grey, grey);
+
+div4.remove();
+testColors("Remove #div4", red, grey, grey, grey, grey, grey);
+
+div5.remove();
+testColors("Remove #div5", grey, grey, grey, grey, grey, grey);
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/class-id-attr-ref.html b/testing/web-platform/tests/css/selectors/invalidation/class-id-attr-ref.html
new file mode 100644
index 0000000000..a3cc6d3d8f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/class-id-attr-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS test reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+div { color: green; }
+</style>
+<div>This should be green</div>
+<div>And this too</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/class-id-attr.html b/testing/web-platform/tests/css/selectors/invalidation/class-id-attr.html
new file mode 100644
index 0000000000..91a6f1a3a5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/class-id-attr.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: [id] and [class] attribute selectors are invalidated correctly.</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#attribute-selectors">
+<link rel="match" href="class-id-attr-ref.html">
+<style>
+[class="foo"] {
+ color: green;
+}
+[id="baz"] {
+ color: green;
+}
+</style>
+<div id="foo">This should be green</div>
+<div id="bar">And this too</div>
+<script>
+onload = function() {
+ document.documentElement.offsetTop;
+ foo.classList.add("foo");
+ bar.setAttribute("id", "baz");
+ document.documentElement.offsetTop;
+}
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/crashtests/nth-child-of-attribute-crash.html b/testing/web-platform/tests/css/selectors/invalidation/crashtests/nth-child-of-attribute-crash.html
new file mode 100644
index 0000000000..8f30fbb5e7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/crashtests/nth-child-of-attribute-crash.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset="utf-8">
+<style>
+#elements [blue] {
+ color: blue;
+}
+#elements :nth-child(1 of :not([blue])) {
+ color: revert;
+}
+</style>
+<div id="elements">
+ <div blue>Child 1</div>
+ <div>Child 2</div>
+</div>
+<script>
+requestAnimationFrame(() =>
+ requestAnimationFrame(() => {
+ elements.children[1].setAttribute("blue", "");
+ elements.children[1].removeAttribute("blue");
+ elements.children[0].removeAttribute("blue");
+ }));
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/defined-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/defined-in-has.html
new file mode 100644
index 0000000000..d691c4a53f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/defined-in-has.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>:has() invalidation with :defined pseudo-class</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/semantics-other.html#selector-defined">
+<style>
+ #subject {
+ background-color: red;
+ width: 100px;
+ height: 100px;
+ }
+ #subject:has(:defined) {
+ background-color: green;
+ }
+</style>
+<body>
+ Test :defined pseudo-class invalidation with :has()
+ <div id="subject">
+ <my-element></my-element>
+ </div>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ const GREEN = "rgb(0, 128, 0)";
+ const RED = "rgb(255, 0, 0)";
+
+ function assert_matches_defined(defined) {
+ assert_equals(getComputedStyle(subject).backgroundColor, defined ? GREEN : RED);
+ }
+
+ test(() => {
+ assert_matches_defined(false);
+ customElements.define("my-element", class MyElement extends HTMLElement { });
+ assert_matches_defined(true);
+ }, "Test :has() invalidation with :defined pseudo-class");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/defined.html b/testing/web-platform/tests/css/selectors/invalidation/defined.html
new file mode 100644
index 0000000000..565ed552e1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/defined.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: :defined</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-defined-pseudo">
+ <meta name="assert" content="This tests that the :defined selector is effective">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/semantics-other.html#selector-defined">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #container {
+ color: gray;
+ }
+
+ #a1:defined {
+ color: blue;
+ }
+ :defined + #b1 {
+ color: green;
+ }
+ :defined > #c1 {
+ color: red;
+ }
+ div + :defined + * #d1 {
+ color: yellow;
+ }
+ </style>
+ </head>
+ <body>
+ <section id="container">
+ <elucidate-late id="a1"></elucidate-late>
+ <div id="b1"></div>
+ <elucidate-late>
+ <div id="c1"></div>
+ </elucidate-late>
+ <div>
+ <div id="d1"></div>
+ </div>
+ </section>
+
+ <script>
+ const gray = "rgb(128, 128, 128)";
+ const blue = "rgb(0, 0, 255)";
+ const green = "rgb(0, 128, 0)";
+ const red = "rgb(255, 0, 0)";
+ const yellow = "rgb(255, 255, 0)";
+
+ function assertGray(a, b, c, d) {
+ assert_equals(getComputedStyle(a).color, gray);
+ assert_equals(getComputedStyle(b).color, gray);
+ assert_equals(getComputedStyle(c).color, gray);
+ assert_equals(getComputedStyle(d).color, gray);
+ }
+
+ function assertColorful(a, b, c, d) {
+ assert_equals(getComputedStyle(a).color, blue);
+ assert_equals(getComputedStyle(b).color, green);
+ assert_equals(getComputedStyle(c).color, red);
+ assert_equals(getComputedStyle(d).color, yellow);
+ }
+
+ class ElucidateLate extends HTMLElement {
+ constructor() {
+ super();
+ }
+ }
+
+ test(() => {
+ assertGray(a1, b1, c1, d1);
+ customElements.define('elucidate-late', ElucidateLate);
+ assertColorful(a1, b1, c1, d1);
+ }, ":defined selector is effective");
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/dir-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/dir-pseudo-class-in-has.html
new file mode 100644
index 0000000000..0f5d072656
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/dir-pseudo-class-in-has.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#relational"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#dir-pseudo"/>
+ <link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <section><div id="ltr1" class="ltr"></div></section>
+ <section id="ltr2" dir="rtl"><div class="ltr"><span></span></div></section>
+ <section dir="ltr"><div class="ltr"><span></span></div></section>
+ <section><div id="rtl1" class="rtl"><span></span></div></section>
+ <section id="rtl2"><div class="rtl"><span></span></div></section>
+ <style>
+ div, section { width: 100px; height: 20px; }
+ section { background: red; }
+ .ltr:has(*:dir(ltr)) { background: green; }
+ .ltr:has(*:dir(rtl)) { background: red; }
+ .rtl:has(*:dir(rtl)) { background: green; }
+ .rtl:has(*:dir(ltr)) { background: red; }
+ </style>
+ <script>
+ requestAnimationFrame(() => {
+ setTimeout(() => {
+ ltr1.appendChild(document.createElement('span'));
+ ltr2.dir = 'ltr';
+ rtl1.dir = 'rtl';
+ rtl2.dir = 'rtl';
+ document.documentElement.className = '';
+ }, 0);
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/empty-pseudo-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/empty-pseudo-in-has.html
new file mode 100644
index 0000000000..4e9f6f2737
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/empty-pseudo-in-has.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :empty in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #subject { color: red }
+ #subject:has(:empty) { color: green }
+ #subject:has(:not(:empty)) { color: blue }
+</style>
+<div id="subject"></div>
+<script>
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+testColor("Empty #subject", red);
+
+let child = document.createElement("div");
+child.id = "child";
+subject.appendChild(child);
+
+testColor("Insert div#child to #subject", green);
+
+child.appendChild(document.createElement("div"));
+
+testColor("Insert div to div.#child", blue);
+
+child.replaceChildren();
+testColor("Remove div from div.#child", green);
+
+child.textContent = "Test";
+testColor("Insert text into div.#child", blue);
+
+child.textContent = "";
+testColor("Remove text from div.#child", green);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/enabled-disabled.html b/testing/web-platform/tests/css/selectors/invalidation/enabled-disabled.html
new file mode 100644
index 0000000000..bac3067d00
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/enabled-disabled.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Selectors Invalidation: :enabled and :disabled</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#enableddisabled">
+ <link rel="help" href="https://html.spec.whatwg.org/#enabling-and-disabling-form-controls:-the-disabled-attribute">
+ <meta name="assert" content="This tests that the :enabled and :disabled selectors are effective, and that the enabled/disabled status of an element is changed when updating its 'disabled' attribute by script.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ input {
+ position: absolute;
+ left: 200px;
+ top: 300px;
+ }
+
+ :enabled {
+ left: 100px;
+ }
+
+ :disabled {
+ top: 400px;
+ }
+ </style>
+ </head>
+ <body>
+ <input id="first" type="button" value="First"></input>
+ <input id="second" type="button" value="Second" disabled></input>
+
+ <script>
+ test(() => {
+ assert_equals(getComputedStyle(first).left, '100px');
+ assert_equals(getComputedStyle(first).top, '300px');
+
+ first.disabled = true;
+ assert_equals(getComputedStyle(first).left, '200px');
+ assert_equals(getComputedStyle(first).top, '400px');
+ }, "Element updates when disabled");
+
+ test(() => {
+ assert_equals(getComputedStyle(second).left, '200px');
+ assert_equals(getComputedStyle(second).top, '400px');
+
+ second.disabled = false;
+ assert_equals(getComputedStyle(second).left, '100px');
+ assert_equals(getComputedStyle(second).top, '300px');
+ }, "Element updates when enabled");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/first-child-last-child.html b/testing/web-platform/tests/css/selectors/invalidation/first-child-last-child.html
new file mode 100644
index 0000000000..4a2ed4570e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/first-child-last-child.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>CSS Selectors Invalidation: :first-child :last-child</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-first-child-pseudo">
+ <meta name="assert" content="This tests that the :first-child and :last-child selectors are effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ div {
+ color: black;
+ }
+ span:first-child {
+ color: blue;
+ }
+ span:last-child {
+ color: red;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="target"><span>first-initially</span><span>last-initially</span></div>
+ <script>
+
+'use strict';
+const black = 'rgb(0, 0, 0)';
+const blue = 'rgb(0, 0, 255)';
+const red = 'rgb(255, 0, 0)';
+
+test(() => {
+ const target = document.querySelector('#target');
+ const first = target.firstChild;
+ assert_equals(getComputedStyle(first).color, blue);
+ target.insertAdjacentHTML('afterbegin', '\n<span>foo</span><span>bar</span>');
+ assert_equals(getComputedStyle(target.firstElementChild).color, blue);
+ assert_equals(getComputedStyle(first).color, black);
+ while (target.firstElementChild !== first)
+ target.removeChild(target.firstElementChild);
+ assert_equals(getComputedStyle(first).color, blue);
+}, 'Adding multiple nodes at once should invalidate :first-child correctly.');
+
+test(() => {
+ const target = document.querySelector('#target');
+ const last = target.lastChild;
+ assert_equals(getComputedStyle(last).color, red);
+ target.insertAdjacentHTML('beforeend', '\n<span>foo</span><span>bar</span>');
+ assert_equals(getComputedStyle(target.lastChild).color, red);
+ assert_equals(getComputedStyle(last).color, black);
+ while (target.lastChild !== last)
+ target.removeChild(target.lastChild);
+ assert_equals(getComputedStyle(last).color, red);
+}, 'Adding multiple nodes at once should invalidate :last-child correctly.');
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/fullscreen-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/fullscreen-pseudo-class-in-has.html
new file mode 100644
index 0000000000..dbbcea2502
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/fullscreen-pseudo-class-in-has.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :fullscreen pseudo class in :has()</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+ #subject:has(#target:fullscreen) { color: green; }
+</style>
+
+<div id="subject">
+ This is some text.
+ <div id="target">This is going to be fullscreened</div>
+</div>
+
+<script>
+let waitForFullscreenChange = () => {
+ return new Promise((resolve) => {
+ document.addEventListener("fullscreenchange", resolve, { once: true });
+ });
+};
+
+promise_test(async function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ test_driver.bless("fullscreen", () => target.requestFullscreen());
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green since target is fullscreen");
+ document.exitFullscreen();
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since target is no longer fullscreen");
+}, ":fullscreen pseudo-class invalidation with requestFullscreen + exitFullscreen");
+
+promise_test(async function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ test_driver.bless("fullscreen", () => target.requestFullscreen());
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green since target is fullscreen");
+ target.remove();
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since target is removed");
+}, ":fullscreen pseudo-class invalidation with requestFullscreen + remove");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-append-first-node.html b/testing/web-platform/tests/css/selectors/invalidation/has-append-first-node.html
new file mode 100644
index 0000000000..82060cc99f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-append-first-node.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1874705">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<style>
+#dut {
+ width: 100px;
+ height: 100px;
+ background: red;
+}
+#dut:has(span) {
+ background: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="dut"></div>
+<script>
+function raf() {
+ return new Promise(resolve => {
+ requestAnimationFrame(resolve);
+ });
+}
+
+async function go() {
+ await raf();
+ await raf();
+ const df = document.createDocumentFragment();
+ const t = document.createTextNode('\n');
+ df.appendChild(t);
+ const s = document.createElement("span");
+ df.appendChild(s);
+ dut.appendChild(df);
+ document.documentElement.className = '';
+}
+
+go();
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-complexity.html b/testing/web-platform/tests/css/selectors/invalidation/has-complexity.html
new file mode 100644
index 0000000000..0bdcdec13b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-complexity.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() invalidation should not be O(n^2)</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+main:has(span) .subject { color: red }
+main:has(span + span) .subject { color: green }
+main:has(span + final) .subject { color: blue }
+main:has(nonexistent + span) .subject { color: black }
+main:has(span) span { color: black }
+main:has(nonexistent) span { color: black }
+main:has(div div span) .subject { color: purple }
+</style>
+<main>
+ <div id=container>
+ <span></span>
+ </div>
+ <div id=subject class=subject></div>
+</main>
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+const purple = 'rgb(128, 0, 128)';
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+const count = 25000;
+
+testColor(`Before appending ${count} elements`, red);
+
+for (let i = 0; i < count; ++i) {
+ const span = document.createElement("span");
+ container.appendChild(span);
+}
+
+testColor(`After appending ${count} elements. This should not time out.`, green);
+
+for (let i = 0; i < count - 1; ++i) {
+ const span = document.createElement("span");
+ container.appendChild(span);
+}
+
+const final = document.createElement("final");
+container.appendChild(final);
+
+testColor(`After appending another ${count} elements. This should not time out.`, blue);
+
+const div = document.createElement("div");
+for (let i = 0; i < count; ++i) {
+ const span = document.createElement("span");
+ div.appendChild(span);
+}
+container.appendChild(div);
+
+testColor(`After appending div with ${count} elements. This should not time out.`, purple);
+
+div.remove();
+
+testColor(`After removing div with ${count} elements. This should not time out.`, blue);
+
+for (let i = 0; i < count; ++i)
+ container.lastChild.remove();
+
+testColor(`After removing ${count} elements one-by-one. This should not time out.`, green);
+
+container.replaceChildren();
+
+testColor(`After removing the remaining elements. This should not time out.`, grey);
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-css-nesting-shared.html b/testing/web-platform/tests/css/selectors/invalidation/has-css-nesting-shared.html
new file mode 100644
index 0000000000..7ce0ac3b04
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-css-nesting-shared.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has() invalidation with nesting where the selector is shared</title>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+#outer1:has(.test) {
+ & #subject1_1 {
+ color: red;
+ }
+ & + #subject1_2 {
+ color: orangered;
+ }
+}
+
+#outer2:has(.test) {
+ & .ancestor {
+ & #subject2_1 {
+ color: green;
+ }
+ & + #subject2_2 {
+ color: lightgreen;
+ }
+ }
+}
+
+#outer3:is(:has(.test) .outer) {
+ & #subject3_1 {
+ color: blue;
+ }
+ & + #subject3_2 {
+ color: skyblue;
+ }
+}
+</style>
+<main id="main">
+ <div>
+ <div id="outer1">
+ <div id="trigger1"></div>
+ <div id="subject1_1"></div>
+ </div>
+ <div id="subject1_2"></div>
+ </div>
+ <div id="outer2">
+ <div id="trigger2"></div>
+ <div class="ancestor">
+ <div id="subject2_1"></div>
+ </div>
+ <div id="subject2_2"></div>
+ </div>
+ <div id="trigger3">
+ <div id="outer3" class="outer">
+ <div id="subject3_1"></div>
+ </div>
+ <div id="subject3_2"></div>
+ </div>
+</main>
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const orangered = 'rgb(255, 69, 0)';
+const green = 'rgb(0, 128, 0)';
+const lightgreen = 'rgb(144, 238, 144)';
+const blue = 'rgb(0, 0, 255)';
+const skyblue = 'rgb(135, 206, 235)';
+
+const colors = {
+ red: {
+ descendant: red,
+ sibling: orangered,
+ },
+ green: {
+ descendant: green,
+ sibling: lightgreen,
+ },
+ blue: {
+ descendant: blue,
+ sibling: skyblue,
+ },
+};
+
+function testColor(testName, element, color) {
+ test(function() {
+ assert_equals(getComputedStyle(element).color, color);
+ }, testName);
+}
+
+function testClassChange(trigger, targetDescendant, targetSibling, expected)
+{
+ trigger.classList.add('test');
+ testColor(`add .test to ${trigger.id} - check ${targetDescendant.id}`, targetDescendant, colors[expected].descendant);
+ testColor(`add .test to ${trigger.id} - check ${targetSibling.id}`, targetSibling, colors[expected].sibling);
+ trigger.classList.remove('test');
+ testColor(`remove .test from ${trigger.id} - check ${targetDescendant.id}`, targetDescendant, grey);
+ testColor(`remove .test from ${trigger.id} - check ${targetSibling.id}`, targetSibling, grey);
+}
+
+testClassChange(trigger1, subject1_1, subject1_2, 'red');
+testClassChange(trigger2, subject2_1, subject2_2, 'green');
+testClassChange(trigger3, subject3_1, subject3_2, 'blue');
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-in-adjacent-position.html b/testing/web-platform/tests/css/selectors/invalidation/has-in-adjacent-position.html
new file mode 100644
index 0000000000..5c1a1ecf78
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-in-adjacent-position.html
@@ -0,0 +1,312 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() in adjacent position</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+div:has(.test) + #subject { color: red }
+div:has([test_attr]) + #subject { color: orangered }
+div:has(> .test) + #subject { color: green }
+div:has(> [test_attr]) + #subject { color: lightgreen }
+div:has(~ .test) + #subject { color: yellow }
+div:has(~ [test_attr]) + #subject { color: ivory }
+div:has(+ .test) + #subject { color: blue }
+div:has(+ [test_attr]) + #subject { color: skyblue }
+div:has(~ div .test) + #subject { color: purple }
+div:has(~ div [test_attr]) + #subject { color: violet }
+div:has(+ div .test) + #subject { color: pink }
+div:has(+ div [test_attr]) + #subject { color: lightpink }
+</style>
+
+<main id=main>
+ <div id=previous_sibling>
+ <div id=previous_sibling_child>
+ <div id=previous_sibling_descendant></div>
+ </div>
+ </div>
+ <div id=subject></div>
+ <div id=next_sibling>
+ <div id=next_sibling_child>
+ <div id=next_sibling_descendant></div>
+ </div>
+ </div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const orangered = 'rgb(255, 69, 0)';
+const green = 'rgb(0, 128, 0)';
+const lightgreen = 'rgb(144, 238, 144)';
+const blue = 'rgb(0, 0, 255)';
+const skyblue = 'rgb(135, 206, 235)';
+const yellow = 'rgb(255, 255, 0)';
+const ivory = 'rgb(255, 255, 240)';
+const purple = 'rgb(128, 0, 128)';
+const violet = 'rgb(238, 130, 238)';
+const pink = 'rgb(255, 192, 203)';
+const lightpink = 'rgb(255, 182, 193)';
+const colors = {
+ grey: {
+ classTest: grey,
+ attributeTest: grey,
+ },
+ red: {
+ classTest: red,
+ attributeTest: orangered,
+ },
+ green: {
+ classTest: green,
+ attributeTest: lightgreen,
+ },
+ blue: {
+ classTest: blue,
+ attributeTest: skyblue,
+ },
+ yellow: {
+ classTest: yellow,
+ attributeTest: ivory,
+ },
+ purple: {
+ classTest: purple,
+ attributeTest: violet,
+ },
+ pink: {
+ classTest: pink,
+ attributeTest: lightpink,
+ },
+};
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ element.classList.add('test');
+ testColor(`add .test to ${element.id}`, expectedColorForClassTest);
+ element.classList.remove('test');
+ testColor(`remove .test from ${element.id}`, grey);
+}
+
+function testElementInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ beforeElement.before(newElement);
+ testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test before ${beforeElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div before ${beforeElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testElementInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ afterElement.after(newElement);
+ testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test after ${afterElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert element div after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div after ${afterElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
+}
+
+function testTreeInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testTreeInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div after ${afterElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
+}
+
+testColor('Initial color', grey);
+
+testClassChange(previous_sibling, "grey");
+testClassChange(previous_sibling_child, "green");
+testClassChange(previous_sibling_descendant, "red");
+testClassChange(subject, "blue");
+testClassChange(next_sibling, "yellow");
+testClassChange(next_sibling_child, "purple");
+testClassChange(next_sibling_descendant, "purple");
+
+testElementInsertionBefore(previous_sibling, "grey");
+testElementInsertionBefore(previous_sibling_child, "green");
+testElementInsertionBefore(previous_sibling_descendant, "red");
+testElementInsertionBefore(subject, "grey");
+testElementInsertionBefore(next_sibling, "yellow");
+testElementInsertionBefore(next_sibling_child, "purple");
+testElementInsertionBefore(next_sibling_descendant, "purple");
+
+testElementInsertionAfter(previous_sibling, "grey");
+testElementInsertionAfter(previous_sibling_child, "green");
+testElementInsertionAfter(previous_sibling_descendant, "red");
+testElementInsertionAfter(subject, "yellow");
+testElementInsertionAfter(next_sibling, "yellow");
+testElementInsertionAfter(next_sibling_child, "purple");
+testElementInsertionAfter(next_sibling_descendant, "purple");
+
+testTreeInsertionBefore(previous_sibling, "grey");
+testTreeInsertionBefore(previous_sibling_child, "red");
+testTreeInsertionBefore(previous_sibling_descendant, "red");
+testTreeInsertionBefore(subject, "green");
+testTreeInsertionBefore(next_sibling, "purple");
+testTreeInsertionBefore(next_sibling_child, "purple");
+testTreeInsertionBefore(next_sibling_descendant, "purple");
+
+testTreeInsertionAfter(previous_sibling, "green");
+testTreeInsertionAfter(previous_sibling_child, "red");
+testTreeInsertionAfter(previous_sibling_descendant, "red");
+testTreeInsertionAfter(subject, "purple");
+testTreeInsertionAfter(next_sibling, "purple");
+testTreeInsertionAfter(next_sibling_child, "purple");
+testTreeInsertionAfter(next_sibling_descendant, "purple");
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-in-ancestor-position.html b/testing/web-platform/tests/css/selectors/invalidation/has-in-ancestor-position.html
new file mode 100644
index 0000000000..7662fbde69
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-in-ancestor-position.html
@@ -0,0 +1,320 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() in ancestor position</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+div:has(.test) #subject { color: red }
+div:has([test_attr]) #subject { color: orangered }
+div:has(> .test) #subject { color: green }
+div:has(> [test_attr]) #subject { color: lightgreen }
+div:has(~ .test) #subject { color: yellow }
+div:has(~ [test_attr]) #subject { color: ivory }
+div:has(+ .test) #subject { color: blue }
+div:has(+ [test_attr]) #subject { color: skyblue }
+div:has(~ div .test) #subject { color: purple }
+div:has(~ div [test_attr]) #subject { color: violet }
+div:has(+ div .test) #subject { color: pink }
+div:has(+ div [test_attr]) #subject { color: lightpink }
+</style>
+
+<main id=main>
+ <div id=subject_ancestor>
+ <div id=subject_parent>
+ <div id=subject>
+ <div id=subject_child>
+ <div id=subject_descendant></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id=next_sibling>
+ <div id=next_sibling_child>
+ <div id=next_sibling_descendant></div>
+ </div>
+ </div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const orangered = 'rgb(255, 69, 0)';
+const green = 'rgb(0, 128, 0)';
+const lightgreen = 'rgb(144, 238, 144)';
+const blue = 'rgb(0, 0, 255)';
+const skyblue = 'rgb(135, 206, 235)';
+const yellow = 'rgb(255, 255, 0)';
+const ivory = 'rgb(255, 255, 240)';
+const purple = 'rgb(128, 0, 128)';
+const violet = 'rgb(238, 130, 238)';
+const pink = 'rgb(255, 192, 203)';
+const lightpink = 'rgb(255, 182, 193)';
+const colors = {
+ grey: {
+ classTest: grey,
+ attributeTest: grey,
+ },
+ red: {
+ classTest: red,
+ attributeTest: orangered,
+ },
+ green: {
+ classTest: green,
+ attributeTest: lightgreen,
+ },
+ blue: {
+ classTest: blue,
+ attributeTest: skyblue,
+ },
+ yellow: {
+ classTest: yellow,
+ attributeTest: ivory,
+ },
+ purple: {
+ classTest: purple,
+ attributeTest: violet,
+ },
+ pink: {
+ classTest: pink,
+ attributeTest: lightpink,
+ },
+};
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ element.classList.add('test');
+ testColor(`add .test to ${element.id}`, expectedColorForClassTest);
+ element.classList.remove('test');
+ testColor(`remove .test from ${element.id}`, grey);
+}
+
+function testElementInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ beforeElement.before(newElement);
+ testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test before ${beforeElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div before ${beforeElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testElementInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ afterElement.after(newElement);
+ testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test after ${afterElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert element div after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div after ${afterElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
+}
+
+function testTreeInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testTreeInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div after ${afterElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
+}
+
+testColor('Initial color', grey);
+
+testClassChange(subject_ancestor, "grey");
+testClassChange(subject_parent, "green");
+testClassChange(subject, "green");
+testClassChange(subject_child, "red");
+testClassChange(subject_descendant, "red");
+testClassChange(next_sibling, "blue");
+testClassChange(next_sibling_child, "pink");
+testClassChange(next_sibling_descendant, "pink");
+
+testElementInsertionBefore(subject_ancestor, "grey");
+testElementInsertionBefore(subject_parent, "green");
+testElementInsertionBefore(subject, "green");
+testElementInsertionBefore(subject_child, "red");
+testElementInsertionBefore(subject_descendant, "red");
+testElementInsertionBefore(next_sibling, "blue");
+testElementInsertionBefore(next_sibling_child, "pink");
+testElementInsertionBefore(next_sibling_descendant, "pink");
+
+testElementInsertionAfter(subject_ancestor, "blue");
+testElementInsertionAfter(subject_parent, "blue");
+testElementInsertionAfter(subject, "green");
+testElementInsertionAfter(subject_child, "red");
+testElementInsertionAfter(subject_descendant, "red");
+testElementInsertionAfter(next_sibling, "yellow");
+testElementInsertionAfter(next_sibling_child, "pink");
+testElementInsertionAfter(next_sibling_descendant, "pink");
+
+testTreeInsertionBefore(subject_ancestor, "grey");
+testTreeInsertionBefore(subject_parent, "red");
+testTreeInsertionBefore(subject, "red");
+testTreeInsertionBefore(subject_child, "red");
+testTreeInsertionBefore(subject_descendant, "red");
+testTreeInsertionBefore(next_sibling, "pink");
+testTreeInsertionBefore(next_sibling_child, "pink");
+testTreeInsertionBefore(next_sibling_descendant, "pink");
+
+testTreeInsertionAfter(subject_ancestor, "pink");
+testTreeInsertionAfter(subject_parent, "pink");
+testTreeInsertionAfter(subject, "red");
+testTreeInsertionAfter(subject_child, "red");
+testTreeInsertionAfter(subject_descendant, "red");
+testTreeInsertionAfter(next_sibling, "purple");
+testTreeInsertionAfter(next_sibling_child, "pink");
+testTreeInsertionAfter(next_sibling_descendant, "pink");
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-in-parent-position.html b/testing/web-platform/tests/css/selectors/invalidation/has-in-parent-position.html
new file mode 100644
index 0000000000..4690e6929f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-in-parent-position.html
@@ -0,0 +1,300 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() in parent position</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+div:has(.test) > #subject { color: red }
+div:has([test_attr]) > #subject { color: orangered }
+div:has(> .test) > #subject { color: green }
+div:has(> [test_attr]) > #subject { color: lightgreen }
+div:has(~ .test) > #subject { color: yellow }
+div:has(~ [test_attr]) > #subject { color: ivory }
+div:has(+ .test) > #subject { color: blue }
+div:has(+ [test_attr]) > #subject { color: skyblue }
+div:has(~ div .test) > #subject { color: purple }
+div:has(~ div [test_attr]) > #subject { color: violet }
+div:has(+ div .test) > #subject { color: pink }
+div:has(+ div [test_attr]) > #subject { color: lightpink }
+</style>
+
+<main id=main>
+ <div id=subject_ancestor>
+ <div id=subject_parent>
+ <div id=subject>
+ <div id=subject_child>
+ <div id=subject_descendant></div>
+ </div>
+ </div>
+ </div>
+ </div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const orangered = 'rgb(255, 69, 0)';
+const green = 'rgb(0, 128, 0)';
+const lightgreen = 'rgb(144, 238, 144)';
+const blue = 'rgb(0, 0, 255)';
+const skyblue = 'rgb(135, 206, 235)';
+const yellow = 'rgb(255, 255, 0)';
+const ivory = 'rgb(255, 255, 240)';
+const purple = 'rgb(128, 0, 128)';
+const violet = 'rgb(238, 130, 238)';
+const pink = 'rgb(255, 192, 203)';
+const lightpink = 'rgb(255, 182, 193)';
+const colors = {
+ grey: {
+ classTest: grey,
+ attributeTest: grey,
+ },
+ red: {
+ classTest: red,
+ attributeTest: orangered,
+ },
+ green: {
+ classTest: green,
+ attributeTest: lightgreen,
+ },
+ blue: {
+ classTest: blue,
+ attributeTest: skyblue,
+ },
+ yellow: {
+ classTest: yellow,
+ attributeTest: ivory,
+ },
+ purple: {
+ classTest: purple,
+ attributeTest: violet,
+ },
+ pink: {
+ classTest: pink,
+ attributeTest: lightpink,
+ },
+};
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ element.classList.add('test');
+ testColor(`add .test to ${element.id}`, expectedColorForClassTest);
+ element.classList.remove('test');
+ testColor(`remove .test from ${element.id}`, grey);
+}
+
+function testElementInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test before ${beforeElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div before ${beforeElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testElementInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test');
+
+ afterElement.after(newElement);
+ testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test after ${afterElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert element div after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div after ${afterElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
+}
+
+function testTreeInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testTreeInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div after ${afterElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
+}
+
+testColor('Initial color', grey);
+
+testClassChange(subject_ancestor, "grey");
+testClassChange(subject_parent, "grey");
+testClassChange(subject, "green");
+testClassChange(subject_child, "red");
+testClassChange(subject_descendant, "red");
+
+testElementInsertionBefore(subject_ancestor, "grey");
+testElementInsertionBefore(subject_parent, "grey");
+testElementInsertionBefore(subject, "green");
+testElementInsertionBefore(subject_child, "red");
+testElementInsertionBefore(subject_descendant, "red");
+
+testElementInsertionAfter(subject_ancestor, "grey");
+testElementInsertionAfter(subject_parent, "blue");
+testElementInsertionAfter(subject, "green");
+testElementInsertionAfter(subject_child, "red");
+testElementInsertionAfter(subject_descendant, "red");
+
+testTreeInsertionBefore(subject_ancestor, "grey");
+testTreeInsertionBefore(subject_parent, "grey");
+testTreeInsertionBefore(subject, "red");
+testTreeInsertionBefore(subject_child, "red");
+testTreeInsertionBefore(subject_descendant, "red");
+
+testTreeInsertionAfter(subject_ancestor, "grey");
+testTreeInsertionAfter(subject_parent, "pink");
+testTreeInsertionAfter(subject, "red");
+testTreeInsertionAfter(subject_child, "red");
+testTreeInsertionAfter(subject_descendant, "red");
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-in-sibling-position.html b/testing/web-platform/tests/css/selectors/invalidation/has-in-sibling-position.html
new file mode 100644
index 0000000000..8b35940f87
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-in-sibling-position.html
@@ -0,0 +1,312 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() in sibling position</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+div:has(.test) ~ #subject { color: red }
+div:has([test_attr]) ~ #subject { color: orangered }
+div:has(> .test) ~ #subject { color: green }
+div:has(> [test_attr]) ~ #subject { color: lightgreen }
+div:has(~ .test) ~ #subject { color: yellow }
+div:has(~ [test_attr]) ~ #subject { color: ivory }
+div:has(+ .test) ~ #subject { color: blue }
+div:has(+ [test_attr]) ~ #subject { color: skyblue }
+div:has(~ div .test) ~ #subject { color: purple }
+div:has(~ div [test_attr]) ~ #subject { color: violet }
+div:has(+ div .test) ~ #subject { color: pink }
+div:has(+ div [test_attr]) ~ #subject { color: lightpink }
+</style>
+
+<main id=main>
+ <div id=previous_sibling>
+ <div id=previous_sibling_child>
+ <div id=previous_sibling_descendant></div>
+ </div>
+ </div>
+ <div id=subject></div>
+ <div id=next_sibling>
+ <div id=next_sibling_child>
+ <div id=next_sibling_descendant></div>
+ </div>
+ </div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const orangered = 'rgb(255, 69, 0)';
+const green = 'rgb(0, 128, 0)';
+const lightgreen = 'rgb(144, 238, 144)';
+const blue = 'rgb(0, 0, 255)';
+const skyblue = 'rgb(135, 206, 235)';
+const yellow = 'rgb(255, 255, 0)';
+const ivory = 'rgb(255, 255, 240)';
+const purple = 'rgb(128, 0, 128)';
+const violet = 'rgb(238, 130, 238)';
+const pink = 'rgb(255, 192, 203)';
+const lightpink = 'rgb(255, 182, 193)';
+const colors = {
+ grey: {
+ classTest: grey,
+ attributeTest: grey,
+ },
+ red: {
+ classTest: red,
+ attributeTest: orangered,
+ },
+ green: {
+ classTest: green,
+ attributeTest: lightgreen,
+ },
+ blue: {
+ classTest: blue,
+ attributeTest: skyblue,
+ },
+ yellow: {
+ classTest: yellow,
+ attributeTest: ivory,
+ },
+ purple: {
+ classTest: purple,
+ attributeTest: violet,
+ },
+ pink: {
+ classTest: pink,
+ attributeTest: lightpink,
+ },
+};
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ element.classList.add('test');
+ testColor(`add .test to ${element.id}`, expectedColorForClassTest);
+ element.classList.remove('test');
+ testColor(`remove .test from ${element.id}`, grey);
+}
+
+function testElementInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ beforeElement.before(newElement);
+ testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test before ${beforeElement.id}`, grey);
+
+ newElement.classList.remove('test')
+
+ beforeElement.before(newElement);
+ testColor(`insert element div before ${beforeElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div before ${beforeElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testElementInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ afterElement.after(newElement);
+ testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove element div.test after ${afterElement.id}`, grey);
+
+ newElement.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert element div after ${afterElement.id}`, grey);
+
+ newElement.classList.add('test');
+ testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.classList.remove('test');
+ testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove element div after ${afterElement.id}`, grey);
+
+ newElement.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
+}
+
+function testTreeInsertionBefore(beforeElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div before ${beforeElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
+}
+
+function testTreeInsertionAfter(afterElement, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
+
+ newChild.classList.remove('test');
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div after ${afterElement.id}`, grey);
+
+ newChild.classList.add('test');
+ testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
+
+ newChild.classList.remove('test');
+ testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
+
+ newElement.remove();
+ testColor(`remove tree div>div after ${afterElement.id}`, grey);
+
+ newChild.setAttribute('test_attr', '');
+
+ afterElement.after(newElement);
+ testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
+
+ newElement.remove();
+ testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
+}
+
+testColor('Initial color', grey);
+
+testClassChange(previous_sibling, "grey");
+testClassChange(previous_sibling_child, "green");
+testClassChange(previous_sibling_descendant, "red");
+testClassChange(subject, "blue");
+testClassChange(next_sibling, "yellow");
+testClassChange(next_sibling_child, "purple");
+testClassChange(next_sibling_descendant, "purple");
+
+testElementInsertionBefore(previous_sibling, "grey");
+testElementInsertionBefore(previous_sibling_child, "green");
+testElementInsertionBefore(previous_sibling_descendant, "red");
+testElementInsertionBefore(subject, "blue");
+testElementInsertionBefore(next_sibling, "yellow");
+testElementInsertionBefore(next_sibling_child, "purple");
+testElementInsertionBefore(next_sibling_descendant, "purple");
+
+testElementInsertionAfter(previous_sibling, "blue");
+testElementInsertionAfter(previous_sibling_child, "green");
+testElementInsertionAfter(previous_sibling_descendant, "red");
+testElementInsertionAfter(subject, "yellow");
+testElementInsertionAfter(next_sibling, "yellow");
+testElementInsertionAfter(next_sibling_child, "purple");
+testElementInsertionAfter(next_sibling_descendant, "purple");
+
+testTreeInsertionBefore(previous_sibling, "green");
+testTreeInsertionBefore(previous_sibling_child, "red");
+testTreeInsertionBefore(previous_sibling_descendant, "red");
+testTreeInsertionBefore(subject, "pink");
+testTreeInsertionBefore(next_sibling, "purple");
+testTreeInsertionBefore(next_sibling_child, "purple");
+testTreeInsertionBefore(next_sibling_descendant, "purple");
+
+testTreeInsertionAfter(previous_sibling, "pink");
+testTreeInsertionAfter(previous_sibling_child, "red");
+testTreeInsertionAfter(previous_sibling_descendant, "red");
+testTreeInsertionAfter(subject, "purple");
+testTreeInsertionAfter(next_sibling, "purple");
+testTreeInsertionAfter(next_sibling_child, "purple");
+testTreeInsertionAfter(next_sibling_descendant, "purple");
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-invalidation-after-removing-non-first-element.html b/testing/web-platform/tests/css/selectors/invalidation/has-invalidation-after-removing-non-first-element.html
new file mode 100644
index 0000000000..482f07b8af
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-invalidation-after-removing-non-first-element.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has() invalidation after removing non-first element</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+#subject:has(descendant) { color: red }
+</style>
+<main id="main">
+ <div id="subject">
+ <div></div>
+ <descendant id="descendant"></descendant>
+ </div>
+</main>
+<script>
+ let grey = 'rgb(128, 128, 128)';
+ let red = 'rgb(255, 0, 0)';
+
+ function test_div(test_name, el, color) {
+ test(function() {
+ assert_equals(getComputedStyle(el).color, color);
+ }, test_name + ': div#' + el.id + '.color');
+ }
+
+ test_div('initial_color', subject, red);
+ subject.removeChild(descendant);
+ test_div('remove descendant', subject, grey);
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-invalidation-for-wiping-an-element.html b/testing/web-platform/tests/css/selectors/invalidation/has-invalidation-for-wiping-an-element.html
new file mode 100644
index 0000000000..03fa9a5554
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-invalidation-for-wiping-an-element.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has() invalidation for wiping an element by means of innerHTML</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+.subject:has(.descendant) { color: green}
+</style>
+<main id=main>
+ <div id="subject" class="subject"></div>
+</main>
+<script>
+ let grey = 'rgb(128, 128, 128)';
+ let green = 'rgb(0, 128, 0)';
+
+ function test_div(test_name, el, color) {
+ test(function() {
+ assert_equals(getComputedStyle(el).color, color);
+ }, test_name + ': div#' + el.id + '.color');
+ }
+
+ test_div('initial color', subject, grey);
+
+ subject.innerHTML = "This is a text <div><div class='descendant'></div></div>";
+
+ test_div('color after inserting text and div > .descendant', subject, green);
+
+ subject.innerHTML = "This is a text";
+
+ test_div('color after wiping #child to remove div > .descendant', subject, grey);
+
+ subject.innerHTML = "<div id='child'> This is a text <div class='descendant'></div></div>";
+
+ test_div('color after inserting text and #child > .descendant', subject, green);
+
+ child.innerHTML = "This is a text";
+
+ test_div('color after wiping #child to remove .descendant', subject, grey);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-pseudo-element.html b/testing/web-platform/tests/css/selectors/invalidation/has-pseudo-element.html
new file mode 100644
index 0000000000..0dfd602e51
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-pseudo-element.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>CSS Selector Invalidation: :has() besides a pseudoelement</title>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<style>
+.anchor:has(.foo)::before {
+ content: "";
+ display: block;
+ width: 100px;
+ height: 100px;
+ background: green;
+ position: absolute;
+}
+</style>
+<script>
+function go() {
+ dut.classList.add("foo");
+ document.documentElement.classList.remove("reftest-wait");
+}
+</script>
+<body onload="go()">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div class="anchor">
+<div id="dut"></div>
+<div style="width: 100px; height: 100px; background: red;"></div>
+</div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-sibling-insertion-removal.html b/testing/web-platform/tests/css/selectors/invalidation/has-sibling-insertion-removal.html
new file mode 100644
index 0000000000..0655b23052
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-sibling-insertion-removal.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>:has() invalidation for sibling insertion and removal</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+#subject1:has(+ #sibling1_1 + #sibling1_2) { color: red }
+#subject2:has(+ #sibling2_2) { color: green }
+#subject3:has(+ #sibling3_1 + #sibling3_2 > #siblingchild3_2_1) { color: blue }
+#subject4:has(+ #sibling4_2 > #siblingchild4_2_1) { color: yellow }
+#subject5:has(+ #sibling5_1 + #sibling5_2) { color: red }
+#subject6:has(+ #sibling6_2) { color: green }
+#subject7:has(+ #sibling7_1 + #sibling7_2 > #siblingchild7_2_1) { color: blue }
+#subject8:has(+ #sibling8_2 > #siblingchild8_2_1) { color: yellow }
+#subject9:has(+ #sibling9_1 + #sibling9_2 ~ #sibling9_3) { color: red }
+#subject10:has(+ #sibling10_2 ~ #sibling10_3) { color: green }
+#subject11:has(+ #sibling11_1 + #sibling11_2 ~ #sibling11_3 > #siblingchild11_3_1) { color: blue }
+#subject12:has(+ #sibling12_2 ~ #sibling12_3 > #siblingchild12_3_1) { color: yellow }
+.sibling13:has(~ .sibling13) { color: green }
+#subject14:has(~ #sibling14_1 ~ #sibling14_2 ~ #sibling14_3) { color: green }
+</style>
+
+<main id="main">
+ <div id="parent1">
+ <div id="subject1"></div>
+ <div id="sibling1_2"></div>
+ <div id="sibling1_3"></div>
+ </div>
+ <div id="parent2">
+ <div id="subject2"></div>
+ <div id="sibling2_1"></div>
+ <div id="sibling2_2"></div>
+ <div id="sibling2_3""></div>
+ </div>
+ <div id="parent3">
+ <div id="subject3"></div>
+ <div id="sibling3_2">
+ <div id="siblingchild3_2_1"></div>
+ </div>
+ <div id="sibling3_3"></div>
+ </div>
+ <div id="parent4">
+ <div id="subject4"></div>
+ <div id="sibling4_1"></div>
+ <div id="sibling4_2">
+ <div id="siblingchild4_2_1"></div>
+ </div>
+ <div id="sibling4_3"></div>
+ </div>
+ <div id="parent5">
+ <div id="subject5"></div>
+ <div id="sibling5_1"></div>
+ <div id="sibling5_2"></div>
+ <div id="sibling5_3""></div>
+ </div>
+ <div id="parent6">
+ <div id="subject6"></div>
+ <div id="sibling6_2"></div>
+ <div id="sibling6_3"></div>
+ </div>
+ <div id="parent7">
+ <div id="subject7"></div>
+ <div id="sibling7_1"></div>
+ <div id="sibling7_2">
+ <div id="siblingchild7_2_1"></div>
+ </div>
+ <div id="sibling7_3"></div>
+ <div id="parent8">
+ <div id="subject8"></div>
+ <div id="sibling8_2">
+ <div id="siblingchild8_2_1"></div>
+ </div>
+ <div id="sibling8_3"></div>
+ </div>
+ <div id="parent9">
+ <div id="subject9"></div>
+ <div id="sibling9_2"></div>
+ <div id="sibling9_3"></div>
+ <div id="sibling9_4"></div>
+ </div>
+ <div id="parent10">
+ <div id="subject10"></div>
+ <div id="sibling10_1"></div>
+ <div id="sibling10_2"></div>
+ <div id="sibling10_3""></div>
+ <div id="sibling10_4""></div>
+ </div>
+ <div id="parent11">
+ <div id="subject11"></div>
+ <div id="sibling11_2"></div>
+ <div id="sibling11_3">
+ <div id="siblingchild11_3_1"></div>
+ </div>
+ <div id="sibling11_4"></div>
+ </div>
+ <div id="parent12">
+ <div id="subject12"></div>
+ <div id="sibling12_1"></div>
+ <div id="sibling12_2"></div>
+ <div id="sibling12_3">
+ <div id="siblingchild12_3_1"></div>
+ </div>
+ <div id="sibling12_4"></div>
+ </div>
+ <div id="parent13">
+ <div class="sibling13"></div>
+ <div id="subject13" class="sibling13"></div>
+ </div>
+ <div id="parent14">
+ <div id="subject14"></div>
+ <div id="sibling14_1"></div>
+ <div id="sibling14_2"></div>
+ <div id="sibling14_3"></div>
+ </div>
+</main>
+<script>
+
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+const yellow = 'rgb(255, 255, 0)';
+
+function testColor(test_name, element, color) {
+ test(function() {
+ assert_equals(getComputedStyle(element).color, color);
+ }, test_name);
+}
+
+function insertBefore(parent, reference, child_id) {
+ var child = document.createElement("div");
+ child.id = child_id;
+ parent.insertBefore(child, reference);
+}
+
+testColor(`subject1: initial color should be ${grey}`, subject1, grey);
+insertBefore(parent1, sibling1_2, "sibling1_1");
+testColor(`subject1: color after #sibling1_1 inserted should be ${red}`,
+ subject1, red);
+
+testColor(`subject2: initial color should be ${grey}`, subject2, grey);
+sibling2_1.remove();
+testColor(`subject2: color after #sibling2_1 removed should be ${green}`,
+ subject2, green);
+
+testColor(`subject3: initial color should be ${grey}`, subject3, grey);
+insertBefore(parent3, sibling3_2, "sibling3_1");
+testColor(`subject3: color after #sibling3_1 inserted should be ${blue}`,
+ subject3, blue);
+
+testColor(`subject4: initial color should be ${grey}`, subject4, grey);
+sibling4_1.remove();
+testColor(`subject4: color after #sibling4_1 removed should be ${yellow}`,
+ subject4, yellow);
+
+testColor(`subject5: initial color should be ${red}`, subject5, red);
+sibling5_1.remove();
+testColor(`subject5: color after #sibling5_1 removed should be ${grey}`,
+ subject5, grey);
+
+testColor(`subject6: initial color should be ${green}`, subject6, green);
+insertBefore(parent6, sibling6_2, "sibling6_1");
+testColor(`subject6: color after #sibling6_1 inserted should be ${grey}`,
+ subject6, grey);
+
+testColor(`subject7: initial color should be ${blue}`, subject7, blue);
+sibling7_1.remove();
+testColor(`subject7: color after #sibling7_1 removed should be ${grey}`,
+ subject7, grey);
+
+testColor(`subject8: initial color should be ${yellow}`, subject8, yellow);
+insertBefore(parent8, sibling8_2, "sibling8_1");
+testColor(`subject8: color after #sibling8_1 inserted should be ${grey}`,
+ subject8, grey);
+
+testColor(`subject9: initial color should be ${grey}`, subject9, grey);
+insertBefore(parent9, sibling9_2, "sibling9_1");
+testColor(`subject9: color after #sibling9_1 inserted should be ${red}`,
+ subject1, red);
+
+testColor(`subject10: initial color should be ${grey}`, subject10, grey);
+sibling10_1.remove();
+testColor(`subject10: color after #sibling10_1 removed should be ${green}`,
+ subject10, green);
+
+testColor(`subject11: initial color should be ${grey}`, subject11, grey);
+insertBefore(parent11, sibling11_2, "sibling11_1");
+testColor(`subject11: color after #sibling11_1 inserted should be ${blue}`,
+ subject11, blue);
+
+testColor(`subject12: initial color should be ${grey}`, subject12, grey);
+sibling12_1.remove();
+testColor(`subject12: color after #sibling12_1 removed should be ${yellow}`,
+ subject12, yellow);
+
+testColor(`subject13: initial color should be ${grey}`, subject13, grey);
+const d = document.createElement("div");
+d.classList.add("sibling13");
+parent13.appendChild(d);
+testColor(`subject13: color after #sibling12_1 removed should be ${green}`,
+ subject13, green);
+
+testColor(`subject14: initial color should be ${green}`, subject14, green);
+sibling14_2.remove();
+testColor(`subject14: color after #sibling14_2 removed should be ${grey}`, subject14, grey);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-sibling.html b/testing/web-platform/tests/css/selectors/invalidation/has-sibling.html
new file mode 100644
index 0000000000..7c56b2e7b3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-sibling.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() with sibling combinator argument</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+#subject:has(~ .test) { color: red }
+#subject:has(+ .test) { color: green }
+#subject:has(~ div .test) { color: blue }
+#subject:has(~ div > .test) { color: purple }
+#subject:has(+ div .test) { color: yellow }
+#subject:has(+ div > .test) { color: pink }
+</style>
+
+<main id=main>
+ <div id=subject></div>
+ <div id=first_sibling>
+ <div id=first_sibling_child>
+ <div id=first_sibling_descendant></div>
+ </div>
+ </div>
+ <div id=second_sibling></div>
+ <div id=third_sibling>
+ <div id=third_sibling_child>
+ <div id=third_sibling_descendant></div>
+ </div>
+ </div>
+</main>
+<script>
+
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+const yellow = 'rgb(255, 255, 0)';
+const purple = 'rgb(128, 0, 128)';
+const pink = 'rgb(255, 192, 203)';
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, expectedColor)
+{
+ element.classList.add('test');
+ testColor(`add .test to ${element.id}`, expectedColor);
+ element.classList.remove('test');
+ testColor(`remove .test from ${element.id}`, grey);
+}
+
+function testElementInsertionBefore(beforeElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ beforeElement.before(newElement);
+ testColor(`insert element div.test before ${beforeElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove element div.test before ${beforeElement.id}`, grey);
+}
+
+function testElementInsertionAfter(afterElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+ newElement.classList.add('test')
+
+ afterElement.after(newElement);
+ testColor(`insert element div.test after ${afterElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove element div.test after ${afterElement.id}`, grey);
+}
+
+function testTreeInsertionBefore(beforeElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
+}
+
+function testTreeInsertionAfter(afterElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newChild.classList.add('test');
+ newElement.appendChild(newChild);
+
+ afterElement.after(newElement);
+ testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
+}
+
+testColor('initial_color', grey);
+
+testClassChange(first_sibling, green);
+testClassChange(second_sibling, red);
+testClassChange(third_sibling, red);
+testClassChange(first_sibling_child, pink);
+testClassChange(first_sibling_descendant, yellow);
+testClassChange(third_sibling_child, purple);
+testClassChange(third_sibling_descendant, blue);
+
+testElementInsertionBefore(first_sibling, green);
+testElementInsertionBefore(second_sibling, red);
+testElementInsertionBefore(third_sibling, red);
+testElementInsertionBefore(first_sibling_child, pink);
+testElementInsertionBefore(first_sibling_descendant, yellow);
+testElementInsertionBefore(third_sibling_child, purple);
+testElementInsertionBefore(third_sibling_descendant, blue);
+
+testElementInsertionAfter(first_sibling, red);
+testElementInsertionAfter(second_sibling, red);
+testElementInsertionAfter(third_sibling, red);
+testElementInsertionAfter(first_sibling_child, pink);
+testElementInsertionAfter(first_sibling_descendant, yellow);
+testElementInsertionAfter(third_sibling_child, purple);
+testElementInsertionAfter(third_sibling_descendant, blue);
+
+testTreeInsertionBefore(first_sibling, pink);
+testTreeInsertionBefore(second_sibling, purple);
+testTreeInsertionBefore(third_sibling, purple);
+testTreeInsertionBefore(first_sibling_child, yellow);
+testTreeInsertionBefore(first_sibling_descendant, yellow);
+testTreeInsertionBefore(third_sibling_child, blue);
+testTreeInsertionBefore(third_sibling_descendant, blue);
+
+testTreeInsertionAfter(first_sibling, purple);
+testTreeInsertionAfter(second_sibling, purple);
+testTreeInsertionAfter(third_sibling, purple);
+testTreeInsertionAfter(first_sibling_child, yellow);
+testTreeInsertionAfter(first_sibling_descendant, yellow);
+testTreeInsertionAfter(third_sibling_child, blue);
+testTreeInsertionAfter(third_sibling_descendant, blue);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-side-effect.html b/testing/web-platform/tests/css/selectors/invalidation/has-side-effect.html
new file mode 100644
index 0000000000..0ea0dee993
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-side-effect.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: Invalidate :has() as result of insertion/removal</title>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+#subject:has(+ #next_sibling) { color: red; }
+#prev_sibling:has(+ #subject + #next_sibling) { color: green; }
+</style>
+
+<main id=main>
+ <div id=prev_sibling></div>
+ <div id=subject></div>
+ <div id=blocks_match></div>
+ <div id=next_sibling></div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+
+function testColors(test_name, subject_color, prev_sibling_color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, subject_color);
+ assert_equals(getComputedStyle(prev_sibling).color, prev_sibling_color);
+ }, test_name);
+}
+
+testColors('Initial colors', grey, grey);
+
+const d = blocks_match;
+d.remove();
+
+testColors('Matches after #blocks_match removed', red, green);
+subject.after(d);
+
+testColors('Does not match after #blocks_match added', grey, grey);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-unstyled.html b/testing/web-platform/tests/css/selectors/invalidation/has-unstyled.html
new file mode 100644
index 0000000000..6a64e49358
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-unstyled.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() affected by unstyled elements</title>
+<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+.none { display: none; }
+#subject:has(.test) { color: red; }
+#subject:has(~ #sibling .test) { color: green; }
+#subject:has(:is(.test_inner #subject_descendant)) { color: blue; }
+#subject:has(~ #sibling :is(.test_inner #sibling_descendant)) { color: yellow; }
+</style>
+
+<main id=main>
+ <div id=subject>
+ <div id=subject_child class="none">
+ <div id=subject_descendant></div>
+ </div>
+ </div>
+ <div id=sibling class="none">
+ <div id=sibling_child>
+ <div id=sibling_descendant></div>
+ </div>
+ </div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+const yellow = "rgb(255, 255, 0)";
+const colors = {
+ grey: {
+ classTest: grey,
+ },
+ red: {
+ classTest: red,
+ },
+ green: {
+ classTest: green,
+ },
+ blue: {
+ classTest: blue,
+ },
+ yellow: {
+ classTest: yellow,
+ },
+};
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, cls, expectedColorName)
+{
+ const expectedColorForClassTest = colors[expectedColorName].classTest;
+ element.classList.add(cls);
+ testColor(`add ${cls} to ${element.id}`, expectedColorForClassTest);
+ element.classList.remove(cls);
+ testColor(`remove ${cls} from ${element.id}`, grey);
+}
+
+testColor('Initial color', grey);
+
+testClassChange(subject_descendant, 'test', 'red');
+testClassChange(sibling_descendant, 'test', 'green');
+testClassChange(subject_child, 'test_inner', 'blue');
+testClassChange(sibling_child, 'test_inner', 'yellow');
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-with-nesting-parent-containing-hover.html b/testing/web-platform/tests/css/selectors/invalidation/has-with-nesting-parent-containing-hover.html
new file mode 100644
index 0000000000..8082980e62
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-with-nesting-parent-containing-hover.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() with nesting parent containing :hover</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ dd, dt { background: white; }
+ dd:hover {
+ dt:has(~ &) { background: lime; }
+ }
+</style>
+<dt id=dt1>#dt1</dt>
+<dd id=dd1>#dd1, Hover me, the DT above should go lime</dd>
+<dt id=dt2>#dt2</dt>
+<dd id=dd2>#dd2, Hover me, both DTs above should go lime</dd>
+<script>
+ const white = 'rgb(255, 255, 255)';
+ const lime = 'rgb(0, 255, 0)';
+
+ function bg_color(element, color, message) {
+ assert_equals(getComputedStyle(element)['background-color'], color, message);
+ }
+
+ promise_test(async () => {
+ bg_color(dt1, white, "#dt1 initially white");
+ bg_color(dd1, white, "#dd1 initially white");
+ bg_color(dt2, white, "#dt2 initially white");
+ bg_color(dd2, white, "#dd2 initially white");
+
+ await new test_driver.Actions().pointerMove(0, 0, {origin: dd1}).send();
+
+ bg_color(dt1, lime, "#dt1 should go lime when hover #dd1");
+ bg_color(dd1, white, "#dd1 doesn't change when hover #dd1");
+ bg_color(dt2, white, "#dt2 doesn't change when hover #dd1");
+ bg_color(dd2, white, "#dd2 doesn't change when hover #dd1");
+
+ await new test_driver.Actions().pointerMove(0, 0, {origin: dt1}).send();
+
+ bg_color(dt1, white, "#dt1 should go white when hover #dt2");
+ bg_color(dd1, white, "#dd1 doesn't change when hover #dt2");
+ bg_color(dt2, white, "#dt2 doesn't change when hover #dt2");
+ bg_color(dd2, white, "#dd2 doesn't change when hover #dt2");
+
+ await new test_driver.Actions().pointerMove(0, 0, {origin: dd2}).send();
+
+ bg_color(dt1, lime, "#dt1 should go lime when hover #dd2");
+ bg_color(dd1, white, "#dd1 doesn't change when hover #dd2");
+ bg_color(dt2, lime, "#dt2 should go lime when hover #dd2");
+ bg_color(dd2, white, "#dd2 doesn't change when hover #dd2");
+ });
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-with-not.html b/testing/web-platform/tests/css/selectors/invalidation/has-with-not.html
new file mode 100644
index 0000000000..b67ec5e3b7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-with-not.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() with :not()</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+div, main { color: grey }
+#subject:has(:not(.test)) { color: green }
+#subject:has(.test :not(.test)) { color: red }
+</style>
+
+<main id=main>
+ <div id=subject>
+ <div id=subject_child class=test>
+ <div id=subject_descendant class=test></div>
+ </div>
+ </div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+
+function testColor(test_name, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, color);
+ }, test_name);
+}
+
+function testClassChange(element, expectedColor)
+{
+ element.classList.remove('test');
+ testColor(`remove .test to ${element.id}`, expectedColor);
+ element.classList.add('test');
+ testColor(`add .test from ${element.id}`, grey);
+}
+
+function testElementInsertionBefore(beforeElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+
+ beforeElement.before(newElement);
+ testColor(`insert element div before ${beforeElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove element div before ${beforeElement.id}`, grey);
+}
+
+function testElementInsertionAfter(afterElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+
+ afterElement.after(newElement);
+ testColor(`insert element div after ${afterElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove element div after ${afterElement.id}`, grey);
+}
+
+function testTreeInsertionBefore(beforeElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newElement.appendChild(newChild);
+
+ beforeElement.before(newElement);
+ testColor(`insert tree div>div before ${beforeElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove tree div>div before ${beforeElement.id}`, grey);
+}
+
+function testTreeInsertionAfter(afterElement, expectedColor)
+{
+ const newElement = document.createElement('div');
+ const newChild = document.createElement('div');
+ newElement.appendChild(newChild);
+
+ afterElement.after(newElement);
+ testColor(`insert tree div.test after ${afterElement.id}`, expectedColor);
+
+ newElement.remove();
+ testColor(`remove tree div.test after ${afterElement.id}`, grey);
+}
+
+testColor('Initial color', grey);
+
+testClassChange(subject_child, green);
+testClassChange(subject_descendant, red);
+
+testElementInsertionBefore(subject_child, green);
+testElementInsertionBefore(subject_descendant, red);
+
+testElementInsertionAfter(subject_child, green);
+testElementInsertionAfter(subject_descendant, red);
+
+testTreeInsertionBefore(subject_child, green);
+testTreeInsertionBefore(subject_descendant, red);
+
+testTreeInsertionAfter(subject_child, green);
+testTreeInsertionAfter(subject_descendant, red);
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-with-nth-child.html b/testing/web-platform/tests/css/selectors/invalidation/has-with-nth-child.html
new file mode 100644
index 0000000000..e8d7d06230
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-with-nth-child.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors Test: :has(:nth-child()) invalidation for sibling change</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+ #test-container > div { background-color: green; }
+ #target1:has(.item:nth-child(3)) { background-color: red; }
+ #target2:has(.item:nth-last-child(3)) { background-color: red; }
+ #target3:has(.item:nth-child(3) > .child) { background-color: red; }
+ #target4:has(.item:nth-last-child(3) > .child) { background-color: red; }
+</style>
+<div id="test-container">
+ <div id="target1">
+ <div class="item" id="item1">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">This text should have a green background</div>
+ </div>
+ <div id="target2">
+ <div class="item">This text should have a green background</div>
+ <div class="item"></div>
+ <div class="item" id="item2">FAIL if you see this text</div>
+ </div>
+ <div id="target3">
+ <div class="item" id="item3">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child">This text should have a green background<span>
+ </div>
+ </div>
+ <div id="target4">
+ <div class="item">
+ <span class="child">This text should have a green background<span>
+ </div>
+ <div class="item"></div>
+ <div class="item" id="item4">FAIL if you see this text</div>
+ </div>
+</div>
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(target1).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target2).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target3).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target4).backgroundColor, "rgb(255, 0, 0)");
+ }, "Initially red");
+
+ test(() => {
+ item1.remove();
+ assert_equals(getComputedStyle(target1).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() no longer matching after removal");
+
+ test(() => {
+ item2.remove();
+ assert_equals(getComputedStyle(target2).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() no longer matching after removal");
+
+ test(() => {
+ item3.remove();
+ assert_equals(getComputedStyle(target3).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() in non-subject no longer matching after removal");
+
+ test(() => {
+ item4.remove();
+ assert_equals(getComputedStyle(target4).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() in non-subject no longer matching after removal");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/has-with-pseudo-class.html b/testing/web-platform/tests/css/selectors/invalidation/has-with-pseudo-class.html
new file mode 100644
index 0000000000..4dc4c1a6a2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/has-with-pseudo-class.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selector Invalidation: :has() with pseudo-classes</title>
+<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+main:has(input) div { color: grey }
+main:has(#checkbox:checked) > #subject { color: red }
+main:has(#option:checked) > #subject { color: red }
+main:has(#checkbox:disabled) > #subject { color: green }
+main:has(#option:disabled) > :is(#subject, #subject2) { color: green }
+main:has(#optgroup:disabled) > #subject { color: blue }
+main:not(:has(#checkbox:enabled)) > #subject3 { color: green }
+main:not(:has(#option:enabled)) :is(#subject3, #subject4) { color: green }
+main:not(:has(#optgroup:enabled)) > #subject3 { color: blue }
+main:has(#text_input:valid) > #subject { color: yellow }
+main:not(:has(#text_input:invalid)) > #subject2 { color: yellow }
+main:has(#form:valid) > #subject3 { color: yellow }
+main:not(:has(#form:invalid)) > #subject4 { color: yellow }
+</style>
+
+<main id=main>
+ <form id=form>
+ <input type=checkbox id=checkbox></input>
+ <select id=select><optgroup id=optgroup><option>a</option><option id=option>b</option></optgroup></select>
+ <input id=text_input type=text required></input>
+ </form>
+ <div id=subject></div>
+ <div id=subject2></div>
+ <div id=subject3></div>
+ <div id=subject4></div>
+</main>
+
+<script>
+const grey = 'rgb(128, 128, 128)';
+const red = 'rgb(255, 0, 0)';
+const green = 'rgb(0, 128, 0)';
+const blue = 'rgb(0, 0, 255)';
+const yellow = 'rgb(255, 255, 0)';
+const purple = 'rgb(128, 0, 128)';
+const pink = 'rgb(255, 192, 203)';
+
+function testColor(test_name, subject_element, color) {
+ test(function() {
+ assert_equals(getComputedStyle(subject_element).color, color);
+ }, test_name);
+}
+
+function testPseudoClassChange(element, property, subject_element, expectedColor)
+{
+ testColor(`Before set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
+
+ element[property] = true;
+ testColor(`Set ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, expectedColor);
+
+ element[property] = false;
+ testColor(`Unset ${property} on ${element.id}, testing ${subject_element.id}`, subject_element, grey);
+}
+
+function testSelectedChange(option, subject_element, expectedColor)
+{
+ const oldOption = select.selectedOptions[0];
+ option.selected = true;
+ testColor(`Set select on ${option.id}`, subject_element, expectedColor);
+ oldOption.selected = true;
+ testColor(`Reset select`, subject, grey);
+}
+
+function testValueChange(input, subject_element, expectedColor)
+{
+ testColor(`Before setting value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
+
+ input.value = "value";
+ testColor(`Set value of ${input.id}, testing ${subject_element.id}`, subject_element, expectedColor);
+
+ input.value = "";
+ testColor(`Clear value of ${input.id}, testing ${subject_element.id}`, subject_element, grey);
+}
+
+testPseudoClassChange(checkbox, "checked", subject, red);
+testSelectedChange(option, subject, red);
+
+testPseudoClassChange(checkbox, "disabled", subject, green);
+testPseudoClassChange(checkbox, "disabled", subject3, green);
+testPseudoClassChange(option, "disabled", subject, green);
+testPseudoClassChange(option, "disabled", subject3, green);
+
+testPseudoClassChange(optgroup, "disabled", subject, blue);
+testPseudoClassChange(optgroup, "disabled", subject2, green);
+testPseudoClassChange(optgroup, "disabled", subject3, blue);
+testPseudoClassChange(optgroup, "disabled", subject4, green);
+
+testValueChange(text_input, subject, yellow);
+testValueChange(text_input, subject2, yellow);
+testValueChange(text_input, subject3, yellow);
+testValueChange(text_input, subject4, yellow);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/host-context-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/host-context-pseudo-class-in-has.html
new file mode 100644
index 0000000000..ca140af6b3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/host-context-pseudo-class-in-has.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: Invalidation for :host-context() inside :has()</title>
+<link rel="author" title="Byungwoo" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="host_parent"><div id="host"></div></div>
+<script>
+ var shadow = host.attachShadow({ mode: 'open' });
+ shadow.innerHTML = `
+ <style>
+ .subject {
+ color: red;
+ }
+ .subject:has(:is(:host-context(.a) > .foo .bar)) { color: green }
+ .subject:has(:is(:host-context(.a) .bar)) { color: blue }
+ </style>
+ <div class="foo">
+ <div id="subject1" class="subject">
+ <div class="bar"></div>
+ </div>
+ </div>
+ <div>
+ <div class="foo">
+ <div id="subject2" class="subject">
+ <div class="bar"></div>
+ </div>
+ </div>
+ </div>
+ `;
+
+ const red = "rgb(255, 0, 0)";
+ const green = "rgb(0, 128, 0)";
+ const blue = "rgb(0, 0, 255)";
+
+ function checkColor(test_name, subject_id, subject_color) {
+ test(function() {
+ let subject = shadow.querySelector("#" + subject_id);
+ assert_equals(getComputedStyle(subject).color, subject_color);
+ }, test_name + ": Check #" + subject_id + " color");
+ }
+
+ checkColor("Before adding 'a' to #host_parent", "subject1", red);
+ checkColor("Before adding 'a' to #host_parent", "subject2", red);
+
+ host_parent.classList.add('a');
+
+ checkColor("After adding 'a' to #host_parent", "subject1", green);
+ checkColor("After adding 'a' to #host_parent", "subject2", blue);
+
+ host_parent.classList.remove('a');
+
+ checkColor("After removing 'a' from #host_parent", "subject1", red);
+ checkColor("After removing 'a' from #host_parent", "subject2", red);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/host-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/host-pseudo-class-in-has.html
new file mode 100644
index 0000000000..4d300befa7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/host-pseudo-class-in-has.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: Invalidation for :host() inside :has()</title>
+<link rel="author" title="Byungwoo" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="host_parent"><div id="host"></div></div>
+<script>
+ var shadow = host.attachShadow({ mode: 'open' });
+ shadow.innerHTML = `
+ <style>
+ .subject {
+ color: red;
+ }
+ .subject:has(:is(:host(.a) > .foo .bar)) { color: green }
+ .subject:has(:is(:host(.a) .bar)) { color: blue }
+ </style>
+ <div class="foo">
+ <div id="subject1" class="subject">
+ <div class="bar"></div>
+ </div>
+ </div>
+ <div>
+ <div class="foo">
+ <div id="subject2" class="subject">
+ <div class="bar"></div>
+ </div>
+ </div>
+ </div>
+ `;
+
+ const red = "rgb(255, 0, 0)";
+ const green = "rgb(0, 128, 0)";
+ const blue = "rgb(0, 0, 255)";
+
+ function checkColor(test_name, subject_id, subject_color) {
+ test(function() {
+ let subject = shadow.querySelector("#" + subject_id);
+ assert_equals(getComputedStyle(subject).color, subject_color);
+ }, test_name + ": Check #" + subject_id + " color");
+ }
+
+ checkColor("Before adding 'a' to #host", "subject1", red);
+ checkColor("Before adding 'a' to #host", "subject2", red);
+
+ host.classList.add('a');
+
+ checkColor("After adding 'a' to #host", "subject1", green);
+ checkColor("After adding 'a' to #host", "subject2", blue);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/input-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/input-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..a9a1d9f5ee
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/input-pseudo-classes-in-has.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: input pseudo classes in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ .ancestor:has(#checkme:checked) { color: green }
+ .ancestor:has(#checkme:indeterminate) { color: yellowgreen }
+ .ancestor:has(#checkme:disabled) { color: blue }
+ .ancestor:has(#textinput:read-only) { color: skyblue }
+ .ancestor:has(#textinput:placeholder-shown) { color: navy }
+ .ancestor:has(#radioinput:default) { color: lightblue }
+ .ancestor:has(#textinput:valid) { color: lightgreen }
+ .ancestor:has(#numberinput:out-of-range) { color: darkgreen }
+ .ancestor:has(#numberinput:required) { color: pink }
+ .ancestor:has(#progress:indeterminate) { color: orange }
+ .ancestor:has(#checkboxinput:default) { color: purple; }
+</style>
+<div id=subject class=ancestor>
+ <input type="checkbox" name="my-checkbox" id="checkme">
+ <label for="checkme">Check me!</label>
+ <input type="text" id="textinput" required>
+ <input id="radioinput" checked>
+ <input id="numberinput" type="number" min="1" max="10" value="5">
+ <progress id="progress" value="50" max="100"></progress>
+ <input id="checkboxinput" type="checkbox">
+</div>
+<script>
+ test(function() {
+ let input = null;
+ this.add_cleanup(() => {
+ if (input) {
+ // Need to put the input back for the rest of the tests.
+ subject.prepend(input);
+ }
+ checkme.checked = false;
+ });
+ checkme.checked = false;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ checkme.checked = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green");
+ checkme.indeterminate = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(154, 205, 50)",
+ "ancestor should be yellowgreen");
+ input = checkme;
+ checkme.remove();
+ input.indeterminate = false;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+
+ subject.prepend(input);
+ input = null;
+ checkme.checked = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green");
+ }, ":checked & :indeterminate invalidation on <input>");
+
+ test(function() {
+ this.add_cleanup(() => {
+ progress.setAttribute("value", "50");
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ progress.removeAttribute("value");
+ assert_equals(getComputedStyle(subject).color, "rgb(255, 165, 0)",
+ "ancestor should be orange");
+ }, ":indeterminate invalidation on <progress>");
+
+ test(function() {
+ this.add_cleanup(() => {
+ checkme.disabled = false;
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ checkme.disabled = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 255)",
+ "ancestor should be blue");
+ }, ":disabled invalidation");
+
+ test(function() {
+ this.add_cleanup(() => {
+ textinput.readOnly = false;
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ textinput.readOnly = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(135, 206, 235)",
+ "ancestor should be skyblue");
+ }, ":read-only invalidation");
+
+ test(function() {
+ this.add_cleanup(() => {
+ textinput.value = "";
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ textinput.value = "text input";
+ assert_equals(getComputedStyle(subject).color, "rgb(144, 238, 144)",
+ "ancestor should be lightgreen");
+ }, ":valid invalidation");
+
+ test(function() {
+ this.add_cleanup(() => {
+ radioinput.removeAttribute("type");
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ radioinput.type = 'radio';
+ assert_equals(getComputedStyle(subject).color, "rgb(173, 216, 230)",
+ "ancestor should be lightblue");
+ }, ":default invalidation with input[type=radio]");
+
+ test(function() {
+ this.add_cleanup(() => {
+ numberinput.required = false;
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ numberinput.required = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(255, 192, 203)",
+ "ancestor should be pink");
+ }, ":required invalidation");
+
+ test(function() {
+ this.add_cleanup(() => {
+ numberinput.value = 5;
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ numberinput.value = 12;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 100, 0)",
+ "ancestor should be darkgreen");
+ }, ":out-of-range invalidation");
+
+ test(function() {
+ this.add_cleanup(() => {
+ textinput.removeAttribute("placeholder");
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ textinput.placeholder = 'placeholder text';
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 128)",
+ "ancestor should be navy");
+ }, ":placeholder-shown invalidation");
+
+ test(function() {
+ this.add_cleanup(() => {
+ checkboxinput.checked = false;
+ checkboxinput.removeAttribute("checked");
+ });
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ checkboxinput.checked = true;
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should still be black");
+ checkboxinput.setAttribute("checked", "");
+ assert_equals(getComputedStyle(subject).color, "rgb(128, 0, 128)",
+ "ancestor should be purple");
+ checkboxinput.checked = false;
+ assert_equals(getComputedStyle(subject).color, "rgb(128, 0, 128)",
+ "ancestor should still be purple");
+ checkboxinput.removeAttribute("checked");
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ }, ":default invalidation with input[type=checkbox] and assignment to .checked");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-001.html b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-001.html
new file mode 100644
index 0000000000..fa966d3f25
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-001.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Invalidation: insert sibling</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#adjacent-sibling-combinators">
+ <meta name="assert" content="This tests that the + next-sibling selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ .c { background-color: blue; }
+ .a + * + .c { background-color: green; }
+ </style>
+</head>
+<body>
+ <div>
+ <div id="first" class="a"></div>
+ <div></div>
+ <div id="target" class="c"></div>
+ </div>
+ <script>
+ 'use strict';
+ const green = 'rgb(0, 128, 0)';
+ const blue = 'rgb(0, 0, 255)';
+
+ test(function() {
+ const first = document.getElementById('first');
+ const target = document.getElementById('target');
+ const parent = first.parentElement;
+ assert_equals(getComputedStyle(target).backgroundColor, green, "initial color");
+
+ parent.removeChild(first);
+ assert_equals(getComputedStyle(target).backgroundColor, blue, "color after removal");
+
+ parent.insertBefore(first, parent.firstChild);
+ assert_equals(getComputedStyle(target).backgroundColor, green, "color after insert")
+ }, "Remove/Insert earlier sibling");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-002.html b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-002.html
new file mode 100644
index 0000000000..7e1eac37ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-002.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Invalidation: insert adjacent sibling of parent</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#adjacent-sibling-combinators">
+ <meta name="assert" content="This tests that the + next-sibling selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ .d { background-color: blue; }
+
+ .a + .c > .d { background-color: green; }
+ </style>
+</head>
+<body>
+ <div>
+ <div id="first" class="a"></div>
+ <div class="c">
+ <div id="target" class="d"></div>
+ </div>
+ </div>
+ <script>
+ 'use strict';
+ const green = 'rgb(0, 128, 0)';
+ const blue = 'rgb(0, 0, 255)';
+
+ test(function() {
+ const first = document.getElementById('first');
+ const target = document.getElementById('target');
+ const parent = first.parentElement;
+ assert_equals(getComputedStyle(target).backgroundColor, green, "initial color");
+
+ parent.removeChild(first);
+ assert_equals(getComputedStyle(target).backgroundColor, blue, "color after removal");
+
+ parent.insertBefore(first, parent.firstChild);
+ assert_equals(getComputedStyle(target).backgroundColor, green, "color after insert")
+ }, "Remove/Insert adjacent sibling of parent");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-003.html b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-003.html
new file mode 100644
index 0000000000..c7c51eaf6a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-003.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Invalidation: insert sibling of ancestor</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#adjacent-sibling-combinators">
+ <meta name="assert" content="This tests that the + next-sibling selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ .c * { background-color: blue; }
+
+ .a + * + .c * { background-color: green; }
+ </style>
+</head>
+<body>
+ <div>
+ <div id="first" class="a"></div>
+ <div></div>
+ <div class="c">
+ <div>
+ <div id="target"></div>
+ </div>
+ </div>
+ </div>
+ <script>
+ 'use strict';
+ const green = 'rgb(0, 128, 0)';
+ const blue = 'rgb(0, 0, 255)';
+
+ test(function() {
+ const first = document.getElementById('first');
+ const target = document.getElementById('target');
+ const parent = first.parentElement;
+ assert_equals(getComputedStyle(target).backgroundColor, green, "initial color");
+
+ parent.removeChild(first);
+ assert_equals(getComputedStyle(target).backgroundColor, blue, "color after removal");
+
+ parent.insertBefore(first, parent.firstChild);
+ assert_equals(getComputedStyle(target).backgroundColor, green, "color after insert")
+ }, "Remove/Insert earlier sibling of ancestor");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-004.html b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-004.html
new file mode 100644
index 0000000000..aa3fb1c9fc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/insert-sibling-004.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CSS Selectors Invalidation: insert sibling of parent</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#general-sibling-combinators">
+ <meta name="assert" content="This tests that the ~ subsequent-sibling selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ span { background-color: blue; }
+
+ .a ~ .c > span { background-color: green; }
+ </style>
+</head>
+<body>
+ <div>
+ <div id="first" class="a"></div>
+ <div></div>
+ <div></div>
+ <div class="c">
+ <span id="target"></span>
+ </div>
+ </div>
+ <script>
+ 'use strict';
+ const green = 'rgb(0, 128, 0)';
+ const blue = 'rgb(0, 0, 255)';
+
+ test(function() {
+ const first = document.getElementById('first');
+ const target = document.getElementById('target');
+ const parent = first.parentElement;
+ assert_equals(getComputedStyle(target).backgroundColor, green, "initial color");
+
+ parent.removeChild(first);
+ assert_equals(getComputedStyle(target).backgroundColor, blue, "color after removal");
+
+ parent.insertBefore(first, parent.firstChild);
+ assert_equals(getComputedStyle(target).backgroundColor, green, "color after insert")
+ }, "Remove/Insert earlier sibling of parent");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-complex-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-complex-in-has.html
new file mode 100644
index 0000000000..c189b0f4be
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-complex-in-has.html
@@ -0,0 +1,379 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :is() in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+div { color: grey }
+.red:has(#descendant:is(.a_has_scope .b)) { color: red }
+.orangered:has(#descendant:is(.a_descendant .b)) #descendant { color: orangered }
+.darkred:has(#descendant:is(.a_indirect_next .b)) ~ #indirect_next { color: darkred }
+.pink:has(#descendant:is(.a_indirect_next_child .b)) ~ #indirect_next #indirect_next_child { color: pink }
+.green:has(#descendant:is(.p + .c_has_scope ~ .d .e)) { color: green }
+.lightgreen:has(#descendant:is(.p + .c_descendant ~ .d .e)) #descendant { color: lightgreen }
+.darkgreen:has(#descendant:is(.p + .c_indirect_next ~ .d .e)) ~ #indirect_next { color: darkgreen }
+.yellowgreen:has(#descendant:is(.p + .c_indirect_next_child ~ .d .e)) ~ #indirect_next #indirect_next_child { color: yellowgreen }
+.blue:has(~ #indirect_next:is(.p + .f_has_scope ~ .g)) { color: blue }
+.skyblue:has(~ #indirect_next:is(.p + .f_descendant ~ .g)) #descendant { color: skyblue }
+.lightblue:has(~ #indirect_next:is(.p + .f_indirect_next ~ .g)) ~ #indirect_next { color: lightblue }
+.darkblue:has(~ #indirect_next:is(.p + .f_indirect_next_child ~ .g)) ~ #indirect_next #indirect_next_child { color: darkblue }
+.yellow:has(~ #indirect_next:is(.h_has_scope .i)) { color: yellow }
+.ivory:has(~ #indirect_next:is(.h_descendant .i)) #descendant { color: ivory }
+.greenyellow:has(~ #indirect_next:is(.h_indirect_next .i)) ~ #indirect_next { color: greenyellow }
+.khaki:has(~ #indirect_next:is(.h_indirect_next_child .i)) ~ #indirect_next #indirect_next_child { color: khaki }
+.purple:has(~ #indirect_next:is(.p + .j_has_scope ~ .k .l)) { color: purple }
+.violet:has(~ #indirect_next:is(.p + .j_descendant ~ .k .l)) #descendant { color: violet }
+.orchid:has(~ #indirect_next:is(.p + .j_indirect_next ~ .k .l)) ~ #indirect_next { color: orchid }
+.plum:has(~ #indirect_next:is(.p + .j_indirect_next_child ~ .k .l)) ~ #indirect_next #indirect_next_child { color: plum }
+.orange:has(#descendant:is(:is(.m, .n) .o)) { color: orange }
+</style>
+<div>
+ <div class="p"></div>
+ <div id="parent_previous"></div>
+ <div id="parent" class="d k">
+ <div class="p"></div>
+ <div id="previous"></div>
+ <div class="p"></div>
+ <div id="has_scope" class="d">
+ <div class="p"></div>
+ <div id="child_previous"></div>
+ <div id="child" class="d">
+ <div id="descendant" class="b e o"></div>
+ </div>
+ </div>
+ <div class="p"></div>
+ <div id="direct_next"></div>
+ <div id="indirect_next" class="g i l">
+ <div id="indirect_next_child"></div>
+ </div>
+ </div>
+</div>
+<script>
+const grey = "rgb(128, 128, 128)";
+const red = "rgb(255, 0, 0)";
+const orangered = "rgb(255, 69, 0)";
+const darkred = "rgb(139, 0, 0)";
+const pink = "rgb(255, 192, 203)";
+const green = "rgb(0, 128, 0)";
+const lightgreen = "rgb(144, 238, 144)";
+const darkgreen = "rgb(0, 100, 0)";
+const yellowgreen = "rgb(154, 205, 50)";
+const blue = "rgb(0, 0, 255)";
+const skyblue = "rgb(135, 206, 235)";
+const lightblue = "rgb(173, 216, 230)";
+const darkblue = "rgb(0, 0, 139)";
+const yellow = "rgb(255, 255, 0)";
+const ivory = "rgb(255, 255, 240)";
+const greenyellow = "rgb(173, 255, 47)";
+const khaki = "rgb(240, 230, 140)";
+const purple = "rgb(128, 0, 128)";
+const violet = "rgb(238, 130, 238)";
+const orchid = "rgb(218, 112, 214)";
+const plum = "rgb(221, 160, 221)";
+const orange = "rgb(255, 165, 0)";
+
+function addClass(element, class_name) {
+ element.classList.add(class_name);
+}
+
+function removeClass(element, class_name) {
+ element.classList.remove(class_name);
+}
+
+function testClassChange(operation, class_name, element_id,
+ selector, matches_result,
+ subject_id, subject_color) {
+ let element = document.getElementById(element_id);
+ assert_equals(element ? element.id : "", element_id);
+ let subject = document.getElementById(subject_id);
+ assert_equals(subject ? subject.id : "", subject_id);
+ let message_prefix = [
+ "[", selector, "]",
+ ["#", element.id, ".classList.",
+ (operation == addClass ? "add" : "remove"),
+ "('", class_name, "')"].join(""),
+ ": "].join(" ");
+ operation(element, class_name);
+ test(function() {
+ assert_equals(subject.matches(selector), matches_result);
+ }, message_prefix + "check matches (" + matches_result + ")");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, subject_color);
+ }, message_prefix + "check #" + subject_id + " color");
+}
+
+function testSiblingInsertionRemoval(class_name, insert_before_id, selector,
+ subject_id,
+ insertion_matches_result,
+ insertion_subject_color,
+ removal_matches_result,
+ removal_subject_color) {
+ let insert_before = document.getElementById(insert_before_id);
+ assert_equals(insert_before ? insert_before.id : "", insert_before_id);
+ let parent = insert_before.parentElement;
+ let subject = document.getElementById(subject_id);
+ assert_equals(subject ? subject.id : "", subject_id);
+ let message_prefix = [
+ "[", selector, "]",
+ ["insert/remove .",
+ class_name, " before #", insert_before.id, ")"].join(""),
+ ": "].join(" ");
+
+ let div = document.createElement("div");
+ div.classList.add(class_name);
+
+ parent.insertBefore(div, insert_before);
+ test(function() {
+ assert_equals(subject.matches(selector), insertion_matches_result);
+ }, message_prefix + "(insertion) check matches (" +
+ insertion_matches_result + ")");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, insertion_subject_color);
+ }, message_prefix + "(insertion) check #" + subject_id + " color");
+
+ div.remove();
+ test(function() {
+ assert_equals(subject.matches(selector), removal_matches_result);
+ }, message_prefix + "(removal) check matches (" +
+ removal_matches_result + ")");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, removal_subject_color);
+ }, message_prefix + "(removal) check #" + subject_id + " color");
+}
+
+assert_equals(getComputedStyle(has_scope).color, grey);
+
+let selector = ".red:has(#descendant:is(.a_has_scope .b))";
+testClassChange(addClass, "red", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "a_has_scope", "parent", selector, true, "has_scope", red);
+testClassChange(removeClass, "a_has_scope", "parent", selector, false, "has_scope", grey);
+testClassChange(addClass, "a_has_scope", "has_scope", selector, true, "has_scope", red);
+testClassChange(removeClass, "a_has_scope", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "a_has_scope", "child", selector, true, "has_scope", red);
+testClassChange(removeClass, "a_has_scope", "child", selector, false, "has_scope", grey);
+testClassChange(removeClass, "red", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".orangered:has(#descendant:is(.a_descendant .b)) #descendant";
+testClassChange(addClass, "orangered", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "a_descendant", "parent", selector, true, "descendant", orangered);
+testClassChange(removeClass, "a_descendant", "parent", selector, false, "descendant", grey);
+testClassChange(addClass, "a_descendant", "has_scope", selector, true, "descendant", orangered);
+testClassChange(removeClass, "a_descendant", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "a_descendant", "child", selector, true, "descendant", orangered);
+testClassChange(removeClass, "a_descendant", "child", selector, false, "descendant", grey);
+testClassChange(removeClass, "orangered", "has_scope", selector, false, "descendant", grey);
+
+selector = ".darkred:has(#descendant:is(.a_indirect_next .b)) ~ #indirect_next";
+testClassChange(addClass, "darkred", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "a_indirect_next", "parent", selector, true, "indirect_next", darkred);
+testClassChange(removeClass, "a_indirect_next", "parent", selector, false, "indirect_next", grey);
+testClassChange(addClass, "a_indirect_next", "has_scope", selector, true, "indirect_next", darkred);
+testClassChange(removeClass, "a_indirect_next", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "a_indirect_next", "child", selector, true, "indirect_next", darkred);
+testClassChange(removeClass, "a_indirect_next", "child", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "darkred", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".pink:has(#descendant:is(.a_indirect_next_child .b)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "pink", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "a_indirect_next_child", "parent", selector, true, "indirect_next_child", pink);
+testClassChange(removeClass, "a_indirect_next_child", "parent", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "a_indirect_next_child", "has_scope", selector, true, "indirect_next_child", pink);
+testClassChange(removeClass, "a_indirect_next_child", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "a_indirect_next_child", "child", selector, true, "indirect_next_child", pink);
+testClassChange(removeClass, "a_indirect_next_child", "child", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "pink", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".green:has(#descendant:is(.p + .c_has_scope ~ .d .e))";
+testClassChange(addClass, "green", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "c_has_scope", "parent_previous", selector, true, "has_scope", green);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "has_scope", false, grey, true, green);
+testClassChange(removeClass, "c_has_scope", "parent_previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("c_has_scope", "parent_previous", selector, "has_scope", true, green, false, grey);
+testClassChange(addClass, "c_has_scope", "previous", selector, true, "has_scope", green);
+testSiblingInsertionRemoval("invalid", "previous", selector, "has_scope", false, grey, true, green);
+testClassChange(removeClass, "c_has_scope", "previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("c_has_scope", "previous", selector, "has_scope", true, green, false, grey);
+testClassChange(addClass, "c_has_scope", "child_previous", selector, true, "has_scope", green);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "has_scope", false, grey, true, green);
+testClassChange(removeClass, "c_has_scope", "child_previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("c_has_scope", "child_previous", selector, "has_scope", true, green, false, grey);
+testClassChange(removeClass, "green", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".lightgreen:has(#descendant:is(.p + .c_descendant ~ .d .e)) #descendant";
+testClassChange(addClass, "lightgreen", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "c_descendant", "parent_previous", selector, true, "descendant", lightgreen);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "descendant", false, grey, true, lightgreen);
+testClassChange(removeClass, "c_descendant", "parent_previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("c_descendant", "parent_previous", selector, "descendant", true, lightgreen, false, grey);
+testClassChange(addClass, "c_descendant", "previous", selector, true, "descendant", lightgreen);
+testSiblingInsertionRemoval("invalid", "previous", selector, "descendant", false, grey, true, lightgreen);
+testClassChange(removeClass, "c_descendant", "previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("c_descendant", "previous", selector, "descendant", true, lightgreen, false, grey);
+testClassChange(addClass, "c_descendant", "child_previous", selector, true, "descendant", lightgreen);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "descendant", false, grey, true, lightgreen);
+testClassChange(removeClass, "c_descendant", "child_previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("c_descendant", "child_previous", selector, "descendant", true, lightgreen, false, grey);
+testClassChange(removeClass, "lightgreen", "has_scope", selector, false, "descendant", grey);
+
+selector = ".darkgreen:has(#descendant:is(.p + .c_indirect_next ~ .d .e)) ~ #indirect_next";
+testClassChange(addClass, "darkgreen", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "c_indirect_next", "parent_previous", selector, true, "indirect_next", darkgreen);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next", false, grey, true, darkgreen);
+testClassChange(removeClass, "c_indirect_next", "parent_previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("c_indirect_next", "parent_previous", selector, "indirect_next", true, darkgreen, false, grey);
+testClassChange(addClass, "c_indirect_next", "previous", selector, true, "indirect_next", darkgreen);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next", false, grey, true, darkgreen);
+testClassChange(removeClass, "c_indirect_next", "previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("c_indirect_next", "previous", selector, "indirect_next", true, darkgreen, false, grey);
+testClassChange(addClass, "c_indirect_next", "child_previous", selector, true, "indirect_next", darkgreen);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "indirect_next", false, grey, true, darkgreen);
+testClassChange(removeClass, "c_indirect_next", "child_previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("c_indirect_next", "child_previous", selector, "indirect_next", true, darkgreen, false, grey);
+testClassChange(removeClass, "darkgreen", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".yellowgreen:has(#descendant:is(.p + .c_indirect_next_child ~ .d .e)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "yellowgreen", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "c_indirect_next_child", "parent_previous", selector, true, "indirect_next_child", yellowgreen);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next_child", false, grey, true, yellowgreen);
+testClassChange(removeClass, "c_indirect_next_child", "parent_previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("c_indirect_next_child", "parent_previous", selector, "indirect_next_child", true, yellowgreen, false, grey);
+testClassChange(addClass, "c_indirect_next_child", "previous", selector, true, "indirect_next_child", yellowgreen);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next_child", false, grey, true, yellowgreen);
+testClassChange(removeClass, "c_indirect_next_child", "previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("c_indirect_next_child", "previous", selector, "indirect_next_child", true, yellowgreen, false, grey);
+testClassChange(addClass, "c_indirect_next_child", "child_previous", selector, true, "indirect_next_child", yellowgreen);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "indirect_next_child", false, grey, true, yellowgreen);
+testClassChange(removeClass, "c_indirect_next_child", "child_previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("c_indirect_next_child", "child_previous", selector, "indirect_next_child", true, yellowgreen, false, grey);
+testClassChange(removeClass, "yellowgreen", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".blue:has(~ #indirect_next:is(.p + .f_has_scope ~ .g))";
+testClassChange(addClass, "blue", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "f_has_scope", "previous", selector, true, "has_scope", blue);
+testSiblingInsertionRemoval("invalid", "previous", selector, "has_scope", false, grey, true, blue);
+testClassChange(removeClass, "f_has_scope", "previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("f_has_scope", "previous", selector, "has_scope", true, blue, false, grey);
+testClassChange(addClass, "f_has_scope", "has_scope", selector, true, "has_scope", blue);
+testClassChange(removeClass, "f_has_scope", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "f_has_scope", "direct_next", selector, true, "has_scope", blue);
+testSiblingInsertionRemoval("invalid", "direct_next", selector, "has_scope", false, grey, true, blue);
+testClassChange(removeClass, "f_has_scope", "direct_next", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("f_has_scope", "direct_next", selector, "has_scope", true, blue, false, grey);
+testClassChange(removeClass, "blue", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".skyblue:has(~ #indirect_next:is(.p + .f_descendant ~ .g)) #descendant";
+testClassChange(addClass, "skyblue", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "f_descendant", "previous", selector, true, "descendant", skyblue);
+testSiblingInsertionRemoval("invalid", "previous", selector, "descendant", false, grey, true, skyblue);
+testClassChange(removeClass, "f_descendant", "previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("f_descendant", "previous", selector, "descendant", true, skyblue, false, grey);
+testClassChange(addClass, "f_descendant", "has_scope", selector, true, "descendant", skyblue);
+testClassChange(removeClass, "f_descendant", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "f_descendant", "direct_next", selector, true, "descendant", skyblue);
+testSiblingInsertionRemoval("invalid", "direct_next", selector, "descendant", false, grey, true, skyblue);
+testClassChange(removeClass, "f_descendant", "direct_next", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("f_descendant", "direct_next", selector, "descendant", true, skyblue, false, grey);
+testClassChange(removeClass, "skyblue", "has_scope", selector, false, "descendant", grey);
+
+selector = ".lightblue:has(~ #indirect_next:is(.p + .f_indirect_next ~ .g)) ~ #indirect_next";
+testClassChange(addClass, "lightblue", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "f_indirect_next", "previous", selector, true, "indirect_next", lightblue);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next", false, grey, true, lightblue);
+testClassChange(removeClass, "f_indirect_next", "previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("f_indirect_next", "previous", selector, "indirect_next", true, lightblue, false, grey);
+testClassChange(addClass, "f_indirect_next", "has_scope", selector, true, "indirect_next", lightblue);
+testClassChange(removeClass, "f_indirect_next", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "f_indirect_next", "direct_next", selector, true, "indirect_next", lightblue);
+testSiblingInsertionRemoval("invalid", "direct_next", selector, "indirect_next", false, grey, true, lightblue);
+testClassChange(removeClass, "f_indirect_next", "direct_next", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("f_indirect_next", "direct_next", selector, "indirect_next", true, lightblue, false, grey);
+testClassChange(removeClass, "lightblue", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".darkblue:has(~ #indirect_next:is(.p + .f_indirect_next_child ~ .g)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "darkblue", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "f_indirect_next_child", "previous", selector, true, "indirect_next_child", darkblue);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next_child", false, grey, true, darkblue);
+testClassChange(removeClass, "f_indirect_next_child", "previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("f_indirect_next_child", "previous", selector, "indirect_next_child", true, darkblue, false, grey);
+testClassChange(addClass, "f_indirect_next_child", "has_scope", selector, true, "indirect_next_child", darkblue);
+testClassChange(removeClass, "f_indirect_next_child", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "f_indirect_next_child", "direct_next", selector, true, "indirect_next_child", darkblue);
+testSiblingInsertionRemoval("invalid", "direct_next", selector, "indirect_next_child", false, grey, true, darkblue);
+testClassChange(removeClass, "f_indirect_next_child", "direct_next", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("f_indirect_next_child", "direct_next", selector, "indirect_next_child", true, darkblue, false, grey);
+testClassChange(removeClass, "darkblue", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".yellow:has(~ #indirect_next:is(.h_has_scope .i))"
+testClassChange(addClass, "yellow", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "h_has_scope", "parent", selector, true, "has_scope", yellow);
+testClassChange(removeClass, "h_has_scope", "parent", selector, false, "has_scope", grey);
+testClassChange(removeClass, "yellow", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".ivory:has(~ #indirect_next:is(.h_descendant .i)) #descendant";
+testClassChange(addClass, "ivory", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "h_descendant", "parent", selector, true, "descendant", ivory);
+testClassChange(removeClass, "h_descendant", "parent", selector, false, "descendant", grey);
+testClassChange(removeClass, "ivory", "has_scope", selector, false, "descendant", grey);
+
+selector = ".greenyellow:has(~ #indirect_next:is(.h_indirect_next .i)) ~ #indirect_next";
+testClassChange(addClass, "greenyellow", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "h_indirect_next", "parent", selector, true, "indirect_next", greenyellow);
+testClassChange(removeClass, "h_indirect_next", "parent", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "greenyellow", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".khaki:has(~ #indirect_next:is(.h_indirect_next_child .i)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "khaki", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "h_indirect_next_child", "parent", selector, true, "indirect_next_child", khaki);
+testClassChange(removeClass, "h_indirect_next_child", "parent", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "khaki", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".purple:has(~ #indirect_next:is(.p + .j_has_scope ~ .k .l))"
+testClassChange(addClass, "purple", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "j_has_scope", "parent_previous", selector, true, "has_scope", purple);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "has_scope", false, grey, true, purple);
+testClassChange(removeClass, "j_has_scope", "parent_previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("j_has_scope", "parent_previous", selector, "has_scope", true, purple, false, grey);
+testClassChange(removeClass, "purple", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".violet:has(~ #indirect_next:is(.p + .j_descendant ~ .k .l)) #descendant";
+testClassChange(addClass, "violet", "has_scope", selector, false, "descendant", grey);
+testClassChange(addClass, "j_descendant", "parent_previous", selector, true, "descendant", violet);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "descendant", false, grey, true, violet);
+testClassChange(removeClass, "j_descendant", "parent_previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("j_descendant", "parent_previous", selector, "descendant", true, violet, false, grey);
+testClassChange(removeClass, "violet", "has_scope", selector, false, "descendant", grey);
+
+selector = ".orchid:has(~ #indirect_next:is(.p + .j_indirect_next ~ .k .l)) ~ #indirect_next";
+testClassChange(addClass, "orchid", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(addClass, "j_indirect_next", "parent_previous", selector, true, "indirect_next", orchid);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next", false, grey, true, orchid);
+testClassChange(removeClass, "j_indirect_next", "parent_previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("j_indirect_next", "parent_previous", selector, "indirect_next", true, orchid, false, grey);
+testClassChange(removeClass, "orchid", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".plum:has(~ #indirect_next:is(.p + .j_indirect_next_child ~ .k .l)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "plum", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(addClass, "j_indirect_next_child", "parent_previous", selector, true, "indirect_next_child", plum);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next_child", false, grey, true, plum);
+testClassChange(removeClass, "j_indirect_next_child", "parent_previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("j_indirect_next_child", "parent_previous", selector, "indirect_next_child", true, plum, false, grey);
+testClassChange(removeClass, "plum", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".orange:has(#descendant:is(:is(.m, .n) .o))";
+testClassChange(addClass, "orange", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "m", "parent", selector, true, "has_scope", orange);
+testClassChange(removeClass, "m", "parent", selector, false, "has_scope", grey);
+testClassChange(addClass, "n", "parent", selector, true, "has_scope", orange);
+testClassChange(removeClass, "n", "parent", selector, false, "has_scope", grey);
+testClassChange(addClass, "m", "has_scope", selector, true, "has_scope", orange);
+testClassChange(removeClass, "m", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "n", "has_scope", selector, true, "has_scope", orange);
+testClassChange(removeClass, "n", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "m", "child", selector, true, "has_scope", orange);
+testClassChange(removeClass, "m", "child", selector, false, "has_scope", grey);
+testClassChange(addClass, "n", "child", selector, true, "has_scope", orange);
+testClassChange(removeClass, "n", "child", selector, false, "has_scope", grey);
+testClassChange(removeClass, "orange", "has_scope", selector, false, "has_scope", grey);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-sibling-relationship-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-sibling-relationship-in-has.html
new file mode 100644
index 0000000000..bd5f96a3e2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/is-pseudo-containing-sibling-relationship-in-has.html
@@ -0,0 +1,311 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors Test: :has(:is()) invalidation for sibling change</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+ #test-container > div { background-color: green; }
+ #target1:has(:is(.item + .item + .item)) { background-color: red; }
+ #target2:has(:is(.invalid .item, .item + .item + .item)) { background-color: red; }
+ #target3:has(:is(.item + .item + .item > .child + .child + .child)) { background-color: red; }
+ #target4:has(:is(.item + .item + .item > .child):is(.child + .child + .child)) { background-color: red; }
+ #target5:has(:is(.item + .item + .item > .child)) { background-color: red; }
+ #target6:has(:is(.invalid .item, .item + .item + .item > .child)) { background-color: red; }
+ #target7:has(:is(.item + .item + .item > .child + .child + .child)) { background-color: red; }
+ #target8:has(:is(.child + .child + .child):is(.item + .item + .item > .child)) { background-color: red; }
+ #target9:has(:is(:where(:is(.item + .item + .item) > .child) + .child + .child)) { background-color: red; }
+ #target10:has(:is(.item:nth-child(3))) { background-color: red; }
+ #target11:has(:is(.item:nth-child(3) > .child:nth-child(3))) { background-color: red; }
+ #target12:has(:is(.item:nth-last-child(3))) { background-color: red; }
+ #target13:has(:is(.item:nth-last-child(3) > .child:nth-last-child(3))) { background-color: red; }
+ #target14:has(:is(.item:nth-child(3) > .child)) { background-color: red; }
+ #target15:has(:is(.item:nth-child(3) > .child:nth-child(3))) { background-color: red; }
+ #target16:has(:is(.item:nth-last-child(3) > .child)) { background-color: red; }
+ #target17:has(:is(.item:nth-last-child(3) > .child:nth-last-child(3))) { background-color: red; }
+ .item + .item + .item {
+ #target18:has(&) { background-color: red; }
+ #target19:has(:is(& > .child + .child + .child)) { background-color: red; }
+ }
+ .item + .item + .item > .child {
+ #target20:has(:is(& + .child + .child)) { background-color: red; }
+ }
+</style>
+<div id="test-container">
+ <div id="target1">
+ <div class="item" id="item1">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">This text should have a green background</div>
+ </div>
+ <div id="target2">
+ <div class="item" id="item2">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">This text should have a green background</div>
+ </div>
+ <div id="target3">
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child" id="item3">(FAIL if you see this text)</span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target4">
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child" id="item4">(FAIL if you see this text)</span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target5">
+ <div class="item" id="item5">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target6">
+ <div class="item" id="item6">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target7">
+ <div class="item"></div>
+ <div class="item" id="item7">FAIL if you see this text</div>
+ <div class="item">
+ <span class="child"></span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target8">
+ <div class="item"></div>
+ <div class="item" id="item8">FAIL if you see this text</div>
+ <div class="item">
+ <span class="child"></span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target9">
+ <div class="item"></div>
+ <div class="item" id="item9">FAIL if you see this text</div>
+ <div class="item">
+ <span class="child"></span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target10">
+ <div class="item" id="item10">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">This text should have a green background</div>
+ </div>
+ <div id="target11">
+ <div class="item"></div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child" id="item11">(FAIL if you see this text)</span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target12">
+ <div class="item">This text should have a green background</div>
+ <div class="item"></div>
+ <div class="item" id="item12">FAIL if you see this text</div>
+ </div>
+ <div id="target13">
+ <div class="item">
+ <span class="child">This text should have a green background</span>
+ <span class="child"></span>
+ <span class="child" id="item13">(FAIL if you see this text)</span>
+ </div>
+ <div class="item"></div>
+ <div class="item"></div>
+ </div>
+ <div id="target14">
+ <div class="item" id="item14">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target15">
+ <div class="item" id="item15">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">
+ <span class="child"></span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target16">
+ <div class="item">
+ <span class="child">This text should have a green background</span>
+ </div>
+ <div class="item"></div>
+ <div class="item" id="item16">FAIL if you see this text</div>
+ </div>
+ <div id="target17">
+ <div class="item">
+ <span class="child">This text should have a green background</span>
+ <span class="child"></span>
+ <span class="child"></span>
+ </div>
+ <div class="item"></div>
+ <div class="item" id="item17">FAIL if you see this text</div>
+ </div>
+ <div id="target18">
+ <div class="item" id="item18">FAIL if you see this text</div>
+ <div class="item"></div>
+ <div class="item">This text should have a green background</div>
+ </div>
+ <div id="target19">
+ <div class="item"></div>
+ <div class="item" id="item19">FAIL if you see this text</div>
+ <div class="item">
+ <span class="child"></span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+ <div id="target20">
+ <div class="item"></div>
+ <div class="item" id="item20">FAIL if you see this text</div>
+ <div class="item">
+ <span class="child"></span>
+ <span class="child"></span>
+ <span class="child">This text should have a green background</span>
+ </div>
+ </div>
+</div>
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(target1).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target2).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target3).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target4).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target5).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target6).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target7).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target8).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target9).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target10).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target11).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target12).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target13).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target14).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target15).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target16).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target17).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target18).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target19).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target20).backgroundColor, "rgb(255, 0, 0)");
+ }, "Initially red");
+
+ test(() => {
+ item1.remove();
+ assert_equals(getComputedStyle(target1).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item2.remove();
+ assert_equals(getComputedStyle(target2).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector enclosed by :is() no longer matching after removal (2)");
+
+ test(() => {
+ item3.remove();
+ assert_equals(getComputedStyle(target3).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector enclosed by :is() no longer matching after removal (3)");
+
+ test(() => {
+ item4.remove();
+ assert_equals(getComputedStyle(target4).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector enclosed by :is() no longer matching after removal (4)");
+
+ test(() => {
+ item5.remove();
+ assert_equals(getComputedStyle(target5).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in non-subject enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item6.remove();
+ assert_equals(getComputedStyle(target6).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in non-subject enclosed by :is() no longer matching after removal (2)");
+
+ test(() => {
+ item7.remove();
+ assert_equals(getComputedStyle(target7).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in non-subject enclosed by :is() no longer matching after removal (3)");
+
+ test(() => {
+ item8.remove();
+ assert_equals(getComputedStyle(target8).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in non-subject enclosed by :is() no longer matching after removal (4)");
+
+ test(() => {
+ item9.remove();
+ assert_equals(getComputedStyle(target9).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in non-subject enclosed by :is() no longer matching after removal (5)");
+
+ test(() => {
+ item10.remove();
+ assert_equals(getComputedStyle(target10).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item11.remove();
+ assert_equals(getComputedStyle(target11).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() enclosed by :is() no longer matching after removal (2)");
+
+ test(() => {
+ item12.remove();
+ assert_equals(getComputedStyle(target12).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item13.remove();
+ assert_equals(getComputedStyle(target13).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() enclosed by :is() no longer matching after removal (2)");
+
+ test(() => {
+ item14.remove();
+ assert_equals(getComputedStyle(target14).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() in non-subject enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item15.remove();
+ assert_equals(getComputedStyle(target15).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() in non-subject enclosed by :is() no longer matching after removal (2)");
+
+ test(() => {
+ item16.remove();
+ assert_equals(getComputedStyle(target16).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() in non-subject enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item17.remove();
+ assert_equals(getComputedStyle(target17).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() in non-subject enclosed by :is() no longer matching after removal (2)");
+
+ test(() => {
+ item18.remove();
+ assert_equals(getComputedStyle(target18).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in parent selector enclosed by :is() no longer matching after removal");
+
+ test(() => {
+ item19.remove();
+ assert_equals(getComputedStyle(target19).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in parent selector non-subject position enclosed by :is() no longer matching after removal (1)");
+
+ test(() => {
+ item20.remove();
+ assert_equals(getComputedStyle(target20).backgroundColor, "rgb(0, 128, 0)");
+ }, "sibling selector in parent selector non-subject position enclosed by :is() no longer matching after removal (2)");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/is.html b/testing/web-platform/tests/css/selectors/invalidation/is.html
new file mode 100644
index 0000000000..8490f09697
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/is.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: :is()</title>
+ <link rel="author" title="Victoria Su" href="mailto:victoriaytsu@google.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+ <meta name="assert" content="This tests that the :is() selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ .b {
+ color: yellow;
+ }
+ /*Simple selector arguments */
+ .a :is(.b, .c) {
+ color: red;
+ }
+ /*Compound selector arguments */
+ .a :is(.c#d, .e) {
+ color: green;
+ }
+ /* Complex selector arguments */
+ .a .g>.b {
+ color: black;
+ }
+ .a :is(.e+.f, .g>.b, .h) {
+ color: blue;
+ }
+ .g>.b {
+ color: black;
+ }
+ .a .h {
+ color: black;
+ }
+ /* Nested */
+ .a+.c>.e {
+ color: black;
+ }
+ .c>.a+.e {
+ color: black;
+ }
+ .a+:is(.b+.f, :is(.c>.e, .g)) {
+ color: red;
+ }
+ .c>.e {
+ color: black;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="a1">
+ <div class="b" id="b1">
+ Red
+ </div>
+ <div class="c" id="c1">
+ Red
+ </div>
+ <div class="c" id="d">
+ Green
+ </div>
+ <div class="e" id="e1">
+ Green
+ </div>
+ <div class="f" id="f1">
+ Blue
+ </div>
+ <div class="g">
+ <div class="b" id="b2">
+ Blue
+ <div class="b" id="b3">
+ Red
+ </div>
+ </div>
+ </div>
+ <div class="h" id="h1">
+ Blue
+ </div>
+ </div>
+ <div class="c" id="c2">
+ <div id="a2"></div>
+ <div class="e" id="e2">
+ Red
+ </div>
+ </div>
+ <script>
+ document.body.offsetTop;
+
+ var black = "rgb(0, 0, 0)";
+ var blue = "rgb(0, 0, 255)";
+ var green = "rgb(0, 128, 0)";
+ var red = "rgb(255, 0, 0)";
+ var yellow = "rgb(255, 255, 0)";
+
+ test(() => {
+ assert_equals(getComputedStyle(b1).color, yellow);
+ assert_equals(getComputedStyle(b2).color, black);
+ assert_equals(getComputedStyle(b3).color, yellow);
+ assert_equals(getComputedStyle(c1).color, black);
+ assert_equals(getComputedStyle(d).color, black);
+ assert_equals(getComputedStyle(e1).color, black);
+ assert_equals(getComputedStyle(e2).color, black);
+ assert_equals(getComputedStyle(f1).color, black);
+ assert_equals(getComputedStyle(h1).color, black);
+ }, "Preconditions.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b1).color, red);
+ assert_equals(getComputedStyle(b3).color, red);
+ assert_equals(getComputedStyle(c1).color, red);
+ }, "Invalidate :is() for simple selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(d).color, green);
+ }, "Invalidate :is() for compound selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b2).color, blue);
+ assert_equals(getComputedStyle(b3).color, red);
+ assert_equals(getComputedStyle(f1).color, blue);
+ }, "Invalidate :is() for complex selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(e2).color, black);
+ a2.className = "a";
+ assert_equals(getComputedStyle(e2).color, red);
+ }, "Invalidate nested :is().");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b2).color, blue);
+ assert_equals(getComputedStyle(h1).color, blue);
+ }, "Test specificity of :is().");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-document-element.html b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-document-element.html
new file mode 100644
index 0000000000..93ece465dd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-document-element.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+ <link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo">
+ <link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+ <meta http-equiv="content-language" content="fr">
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div><span></span></div>
+ <style>
+ div { width: 100px; height: 100px; }
+ div:has(*:lang(fr)) { background: red; }
+ div:has(*:lang(en)) { background: green; }
+ </style>
+ <script>
+ requestAnimationFrame(() => {
+ setTimeout(() => {
+ document.documentElement.lang = 'en';
+ document.documentElement.className = '';
+ }, 0);
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-multiple-document-elements.html b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-multiple-document-elements.html
new file mode 100644
index 0000000000..5dbe9c711a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-multiple-document-elements.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="fr" class="reftest-wait">
+<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<body>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div><span></span></div>
+<script>
+const test = document.querySelector('div').matches('*:has(:lang(fr))') ? 'PASS' : 'FAIL';
+
+const newDocumentElement = document.createElement('html');
+newDocumentElement.lang = 'en';
+document.replaceChild(newDocumentElement, document.documentElement);
+document.documentElement.innerHTML = `
+<head>
+<style>
+ div { width: 100px; height: 100px; }
+ div:has(*:lang(fr)) { background: red; }
+ div:has(*:lang(en)) { background: green; }
+ span.pass { color: green; }
+ span.fail { color: red; }
+</style>
+</head>
+<body>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div><span class="${test.toLowerCase()}">${test}</span></div>
+</body>`;
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-xhtml.xhtml b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-xhtml.xhtml
new file mode 100644
index 0000000000..3a421c2e12
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has-xhtml.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html class="reftest-wait" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#relational"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo"/>
+ <link rel="match" href="../../reference/ref-filled-green-100px-square.xht"/>
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <section class="lang"><div xml:lang="zh" lang="ja"></div></section>
+ <section class="lang"><div id="ja" xml:lang="ja" lang="ja"></div></section>
+ <div><section class="lang" id="fr" lang="fr" style="-webkit-locale: 'en'"><div></div></section></div>
+ <div><section class="lang" id="es" xml:lang="es"><div></div></section></div>
+ <section class="lang"><div id="kr" xml:lang="kr" lang="en"></div></section>
+ <style>
+ body > *:not(p) { background: red; }
+ section, div { width: 100px; height: 20px; }
+ .lang:has(:lang(zh)) { background: green; }
+ .lang:has(:lang(ja)) { background: red; }
+ div:has(.lang:lang(fr)) { background: red; }
+ div:has(.lang:lang(en)) { background: green; }
+ div:has(#es:lang(es)) { background: red; }
+ div:has(#es:lang(en)) { background: green; }
+ .lang:has(#kr:lang(kr)) { background: red; }
+ .lang:has(#kr:lang(kr)) { background: green; }
+ div:has(.lang > :lang(pt)) { background: red; }
+ </style>
+ <script>
+ requestAnimationFrame(() => {
+ setTimeout(() => {
+ document.getElementById('ja').setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:lang', 'zh');
+ document.getElementById('fr').setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:lang', 'en');
+ document.getElementById('es').setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:lang', 'en');
+ document.getElementById('kr').removeAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:lang');
+ document.documentElement.className = '';
+ }, 0);
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has.html
new file mode 100644
index 0000000000..83404fcbc7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/lang-pseudo-class-in-has.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+ <link rel="help" href="https://drafts.csswg.org/selectors/#lang-pseudo">
+ <link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+</head>
+<body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <section class="lang"><div lang="en"></div></section>
+ <section class="lang" id="fr" lang="fr"><div></div></section>
+ <section class="lang" id="ja" lang="ja" style="-webkit-locale: 'en'"><div></div></section>
+ <div><section class="lang" id="zh" lang="zh" style="-webkit-locale: 'en'"><span></span></section></div>
+ <div id="kr" class="lang" lang="kr"></div>
+ <style>
+ div { width: 100px; height: 20px; }
+ .lang div:lang(en) { background: green; }
+ .lang div:lang(fr) { background: red; }
+ .lang div:lang(ja) { background: red; }
+ div:has(.lang :lang(zh)) { background: red; }
+ div:has(.lang :lang(en)) { background: green; }
+ .lang:lang(kr) { background: red; }
+ .lang div:lang(kr) { background: green; }
+ </style>
+ <script>
+ requestAnimationFrame(() => {
+ setTimeout(() => {
+ fr.lang = 'en';
+ ja.lang = 'en';
+ zh.lang = 'en';
+ kr.appendChild(document.createElement('div'));
+ document.documentElement.className = '';
+ }, 0);
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/link-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/link-pseudo-class-in-has.html
new file mode 100644
index 0000000000..d0c617a176
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/link-pseudo-class-in-has.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :any-link and :link pseudo class in :has()</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+ /* :any-link and :link should match similarly */
+ #subject:has(#target:link:any-link) { color: green; }
+ #subject:has(#svgTarget:link:any-link) { color: blue; }
+</style>
+
+<div id="subject">
+ This is some text.
+ <a id="target">This is an anchor element</a>
+ <svg xmlns="http://www.w3.org/2000/svg">
+ <a id="svgTarget"><text>This is an SVG anchor element</text></a>
+ </svg>
+</div>
+
+<script>
+test(function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ target.setAttribute("href", "/");
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green since target is a link");
+ target.removeAttribute("href");
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since target is no longer a link");
+}, ":any-link & :link pseudo-class invalidation with an HTML link");
+
+test(function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ svgTarget.setAttribute("href", "/")
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 255)",
+ "ancestor should be blue since target is a link");
+ svgTarget.removeAttribute("href");
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since target is no longer a link");
+}, ":any-link & :link pseudo-class invalidation with an SVG link");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/link-pseudo-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/link-pseudo-in-has.html
new file mode 100644
index 0000000000..0ff879768b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/link-pseudo-in-has.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :link, :visited :any-link, pseudo-class in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #parent { color: blue; }
+ #grandparent { color: blue; }
+ #parent:has(> :not(:link)) { color: grey; }
+ #parent:has(> :link) { color: green; }
+ #parent:has(> :visited) { color: red; }
+ #grandparent:has(:not(:any-link)) { color: grey; }
+ #grandparent:has(:any-link) { color: green; }
+</style>
+<div id="grandparent"></div>
+<script>
+ const BLUE = "rgb(0, 0, 255)";
+ const GREY = "rgb(128, 128, 128)";
+ const GREEN = "rgb(0, 128, 0)";
+ const RED = "rgb(255, 0, 0)";
+
+ function checkColor(id, color, target_matches) {
+ let element = document.getElementById(id);
+ let message = ["location.hash ==", location.hash, ": #" + id, "should be",
+ color, (target_matches ? "with" : "without"),
+ ":target"].join(" ");
+ assert_equals(getComputedStyle(element).color, color, message);
+ }
+
+ promise_test(async () => {
+ assert_equals(getComputedStyle(grandparent).color, BLUE,
+ "grandparent should be blue without any element");
+
+ let parent = document.createElement("div");
+ parent.id = "parent";
+ grandparent.appendChild(parent);
+
+ assert_equals(getComputedStyle(grandparent).color, GREY,
+ "grandparent should be grey after parent added");
+ assert_equals(getComputedStyle(parent).color, BLUE,
+ "parent should be blue without any link");
+
+ let div = document.createElement("div");
+ parent.appendChild(div);
+
+ assert_equals(getComputedStyle(grandparent).color, GREY,
+ "grandparent should be grey after div added");
+ assert_equals(getComputedStyle(parent).color, GREY,
+ "parent should be grey after div added");
+
+ let visited = document.createElement("a");
+ visited.href = "";
+ parent.appendChild(visited);
+
+ assert_equals(getComputedStyle(grandparent).color, GREEN,
+ "grandparent should be green after visited link added");
+ assert_equals(getComputedStyle(parent).color, GREEN,
+ "parent should be green after visited link added");
+
+ let unvisited = document.createElement("a");
+ unvisited.href = "unvisited";
+ parent.appendChild(unvisited);
+
+ assert_equals(getComputedStyle(grandparent).color, GREEN,
+ "grandparent should be green after unvisited link added");
+ assert_equals(getComputedStyle(parent).color, GREEN,
+ "parent should be green after unvisited link added");
+
+ unvisited.remove();
+
+ assert_equals(getComputedStyle(grandparent).color, GREEN,
+ "grandparent should be green after unvisited link removed");
+ assert_equals(getComputedStyle(parent).color, GREEN,
+ "parent should be blue after unvisited link removed");
+
+ visited.remove();
+
+ assert_equals(getComputedStyle(grandparent).color, GREY,
+ "grandparent should be grey after visited link removed");
+ assert_equals(getComputedStyle(parent).color, GREY,
+ "parent should be grey after visited link removed");
+
+ div.remove();
+
+ assert_equals(getComputedStyle(grandparent).color, GREY,
+ "grandparent should be grey after div removed");
+ assert_equals(getComputedStyle(parent).color, BLUE,
+ "parent should be blue after div removed");
+
+ parent.remove();
+
+ assert_equals(getComputedStyle(grandparent).color, BLUE,
+ "grandparent should be blue after parent removed");
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/location-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/location-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..697fc70ae6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/location-pseudo-classes-in-has.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: location pseudo classes in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #parent1:has(:link) { color: green }
+ #parent1:has(:visited) { color: yellowgreen }
+</style>
+<div id=parent1>
+ <div>parent color must be blue with
+ <a id=link1 href="#unvisited">visited link</a>
+ </div>
+</div>
+<script>
+ test(() => {
+ history.replaceState({}, "", "#visited");
+
+ assert_equals(getComputedStyle(parent1).color, "rgb(0, 128, 0)",
+ "parent should be green");
+
+ link1.href = "#visited";
+
+ assert_equals(getComputedStyle(parent1).color, "rgb(0, 128, 0)",
+ "parent should be still green");
+ });
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..07ab6083e0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long" />
+<title>:has() invalidation with :buffering & :stalled pseudo-classes</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="help" href="https://drafts.csswg.org/selectors/#media-loading-state">
+
+<style>
+#subject:has(video:buffering) {
+ background-color: blue;
+}
+#subject:has(video:stalled) {
+ border-color: green;
+}
+</style>
+
+<div id="subject">
+ <video width="300" height="300" muted loop controls></video>
+</div>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const BLUE = "rgb(0, 0, 255)";
+const GREEN = "rgb(0, 128, 0)";
+
+function assert_buffering_state(buffering) {
+ if (buffering)
+ assert_equals(getComputedStyle(subject).backgroundColor, BLUE);
+ else
+ assert_not_equals(getComputedStyle(subject).backgroundColor, BLUE);
+}
+
+function assert_stalled_state(stalled) {
+ if (stalled)
+ assert_equals(getComputedStyle(subject).borderColor, GREEN);
+ else
+ assert_not_equals(getComputedStyle(subject).borderColor, GREEN);
+}
+
+promise_test(async (t) => {
+ const video = document.querySelector("video");
+ assert_stalled_state(false);
+ await new Promise((r) => {
+ video.addEventListener("stalled", r, { once: true });
+ video.src = `/media/counting.mp4?pipe=trickle(100:d1:r2)&random=${Math.random()}`;
+ });
+ assert_stalled_state(false);
+ const promise = video.play();
+ assert_stalled_state(true);
+ video.src = "";
+ // Wait for the video to abort trying to play
+ try {
+ await promise;
+ } catch (err) {}
+ await video.pause();
+ assert_stalled_state(false);
+}, "Test :has(:stalled) invalidation");
+
+promise_test(async (t) => {
+ const video = document.querySelector("video");
+ assert_buffering_state(false);
+ await new Promise((r) => {
+ video.addEventListener("stalled", r, { once: true });
+ video.src = `/media/counting.mp4?pipe=trickle(100:d1:r2)&random=${Math.random()}`;
+ });
+ video.currentTime = 10;
+ assert_buffering_state(false);
+ const promise = video.play();
+ assert_buffering_state(true);
+ video.src = "";
+ // Wait for the video to abort trying to play
+ try {
+ await promise;
+ } catch (err) {}
+ await video.pause();
+ assert_buffering_state(false);
+}, "Test :has(:buffering) invalidation");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/media-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/media-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..881ba8f30e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/media-pseudo-classes-in-has.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<title>:has() invalidation with :playing, :paused, :seeking and :muted pseudo-classes</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="help" href="https://drafts.csswg.org/selectors/#video-state">
+<style>
+ #subject {
+ background-color: black;
+ accent-color: black;
+ color: black;
+ border: 2px solid black;
+ }
+ #subject:has(:muted) {
+ background-color: red;
+ }
+ #subject:has(:playing) {
+ border-color: green;
+ }
+ #subject:has(:paused) {
+ color: orange;
+ }
+ #subject:has(:seeking) {
+ accent-color: blue;
+ }
+</style>
+<body>
+ <div id="subject">
+ Test media pseudo-classes invalidation with :has()
+ <input type="checkbox">
+ <video width="300" height="300" loop></video>
+ </div>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ const GREEN = "rgb(0, 128, 0)";
+ const ORANGE = "rgb(255, 165, 0)";
+ const BLUE = "rgb(0, 0, 255)";
+ const RED = "rgb(255, 0, 0)";
+ const BLACK = "rgb(0, 0, 0)";
+
+ function assert_matches_muted(muted) {
+ assert_equals(getComputedStyle(subject).backgroundColor, muted ? RED : BLACK);
+ }
+
+ function assert_matches_playing(playing) {
+ assert_equals(getComputedStyle(subject).borderColor, playing ? GREEN : BLACK);
+ assert_equals(getComputedStyle(subject).color, !playing ? ORANGE : BLACK);
+ }
+
+ function assert_matches_seeking(seeking) {
+ assert_equals(getComputedStyle(subject).accentColor, seeking ? BLUE : BLACK);
+ }
+
+ promise_test(async (t) => {
+ t.add_cleanup(() => {
+ video.muted = false;
+ video.pause();
+ video.removeAttribute("src");
+ });
+ const video = document.querySelector("video");
+ assert_matches_muted(false);
+ assert_matches_playing(false);
+ assert_matches_seeking(false);
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+ video.muted = true; // allows us to play the video
+ assert_matches_muted(true);
+ await new Promise((r) => {
+ video.addEventListener("playing", r, { once: true });
+ video.play();
+ });
+ assert_matches_playing(true);
+ }, "Test :playing pseudo-classes");
+
+ promise_test(async (t) => {
+ t.add_cleanup(() => {
+ video.removeAttribute("src");
+ });
+ const video = document.querySelector("video");
+ assert_matches_muted(false);
+ assert_matches_playing(false);
+ assert_matches_seeking(false);
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+
+ assert_matches_seeking(false);
+ await new Promise((r) => {
+ video.addEventListener("seeking", r, { once: true });
+ video.currentTime = 10;
+ });
+ assert_matches_seeking(true);
+ }, "Test :seeking pseudo-class");
+
+ promise_test(async (t) => {
+ t.add_cleanup(() => {
+ video.removeAttribute("src");
+ });
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+ assert_matches_muted(false);
+ video.muted = true;
+ assert_matches_muted(true);
+ video.muted = false;
+ assert_matches_muted(false);
+ }, "Test :muted pseudo-class");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/modal-pseudo-class-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/modal-pseudo-class-in-has.html
new file mode 100644
index 0000000000..140f7cc4f8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/modal-pseudo-class-in-has.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :modal pseudo class in :has()</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<link rel="help" href="https://drafts.csswg.org/selectors/#modal-state">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ #subject:has(#dialog:modal) { color: green; }
+ #subject:has(#fullscreenTarget:modal) { color: blue; }
+</style>
+<div id="subject">
+ This is some text.
+ <dialog id="dialog">This is a dialog</dialog>
+ <div id="fullscreenTarget">This is going to be fullscreened</div>
+</div>
+<script>
+ // Dialog tests
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since dialog is not modal");
+ dialog.show();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since dialog is not modal");
+ dialog.close();
+ }, ":modal pseudo-class is not active with dialog.show()");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ dialog.showModal();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green since dialog is shown modally");
+ dialog.close();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since dialog is closed");
+ }, ":modal pseudo-class invalidation with showModal + close");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ dialog.showModal();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
+ "ancestor should be green since dialog is shown modally");
+ dialog.remove();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since dialog is removed");
+ }, ":modal pseudo-class invalidation with showModal + remove");
+
+ // Fullscreen tests
+ let waitForFullscreenChange = () => {
+ return new Promise((resolve) => {
+ document.addEventListener("fullscreenchange", resolve, { once: true });
+ });
+ };
+ promise_test(async function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ test_driver.bless("fullscreen", () => fullscreenTarget.requestFullscreen());
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 255)",
+ "ancestor should be blue since target is fullscreen");
+ document.exitFullscreen();
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since target is no longer fullscreen");
+ }, ":modal pseudo-class invalidation with requestFullscreen + exitFullscreen");
+ promise_test(async function() {
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black");
+ test_driver.bless("fullscreen", () => fullscreenTarget.requestFullscreen());
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 255)",
+ "ancestor should be blue since target is fullscreen");
+ fullscreenTarget.remove();
+ await waitForFullscreenChange();
+ assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
+ "ancestor should be black since target is removed");
+ }, ":modal pseudo-class invalidation with requestFullscreen + remove");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes-ref.html b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes-ref.html
new file mode 100644
index 0000000000..bfa9d00e1b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset="utf-8" />
+<div>
+ <p style="color: green">Negated</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Negated</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes.html b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes.html
new file mode 100644
index 0000000000..0d76146f19
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-child-when-ancestor-changes.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :not(:nth-child(... of class)) when ancestor changes</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="negated-nth-child-when-ancestor-changes-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+.ancestor :not(:nth-child(even of .c)) {
+ color: green;
+}
+</style>
+<div id="toggler">
+ <p>Negated</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Negated</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("ancestor");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes-ref.html b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes-ref.html
new file mode 100644
index 0000000000..27f51e6da2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset="utf-8" />
+<div>
+ <p style="color: green">Negated</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p style="color: green">Negated</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes.html b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes.html
new file mode 100644
index 0000000000..27f66ee324
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/negated-nth-last-child-when-ancestor-changes.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :not(:nth-last-child(... of class)) when ancestor changes</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="negated-nth-last-child-when-ancestor-changes-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+.ancestor :not(:nth-last-child(even of .c)) {
+ color: green;
+}
+</style>
+<div id="toggler">
+ <p>Negated</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Negated</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("ancestor");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/not-001.html b/testing/web-platform/tests/css/selectors/invalidation/not-001.html
new file mode 100644
index 0000000000..db1cf291c7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/not-001.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>CSS Selectors Invalidation: complex :not()</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#negation">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ * {
+ color: yellow;
+ }
+ :not(.b ~ *) {
+ color: green;
+ }
+</style>
+<div id="b">
+</div>
+<div class="c">
+</div>
+<div class="d">
+</div>
+<script>
+ var black = "rgb(0, 0, 0)";
+ var blue = "rgb(0, 0, 255)";
+ var green = "rgb(0, 128, 0)";
+ var red = "rgb(255, 0, 0)";
+ var yellow = "rgb(255, 255, 0)";
+
+ test(() => {
+ assert_equals(getComputedStyle(document.querySelector("#b")).color, green);
+ assert_equals(getComputedStyle(document.querySelector(".c")).color, green);
+ assert_equals(getComputedStyle(document.querySelector(".d")).color, green);
+ }, "precondition");
+
+ test(() => {
+ document.getElementById("b").className = "b";
+ assert_equals(getComputedStyle(document.querySelector("#b")).color, green);
+ assert_equals(getComputedStyle(document.querySelector(".c")).color, yellow);
+ assert_equals(getComputedStyle(document.querySelector(".d")).color, yellow);
+ }, "Invalidation of sibling combinators in :not()");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/not-002.html b/testing/web-platform/tests/css/selectors/invalidation/not-002.html
new file mode 100644
index 0000000000..811b125f8c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/not-002.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<title>CSS Selectors Invalidation: complex :not()</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#negation">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ .b {
+ color: yellow;
+ }
+ /*Simple selector arguments */
+ .a :not(:not(.b, .c)) {
+ color: red;
+ }
+ /*Compound selector arguments */
+ .a :not(:not(.c#d, .e)) {
+ color: green;
+ }
+ /* Complex selector arguments */
+ .a .g>.b {
+ color: black;
+ }
+ .a :not(:not(.e+.f, .g>.b, .h)) {
+ color: blue;
+ }
+ .g>.b {
+ color: black;
+ }
+ .a .h {
+ color: black;
+ }
+ /* Nested */
+ .a+.c>.e {
+ color: black;
+ }
+ .c>.a+.e {
+ color: black;
+ }
+ .a+:not(:not(.b+.f, :is(.c>.e, .g))) {
+ color: red;
+ }
+ .c>.e {
+ color: black;
+ }
+</style>
+<div id="a1">
+ <div class="b" id="b1">
+ Red
+ </div>
+ <div class="c" id="c1">
+ Red
+ </div>
+ <div class="c" id="d">
+ Green
+ </div>
+ <div class="e" id="e1">
+ Green
+ </div>
+ <div class="f" id="f1">
+ Blue
+ </div>
+ <div class="g">
+ <div class="b" id="b2">
+ Blue
+ <div class="b" id="b3">
+ Red
+ </div>
+ </div>
+ </div>
+ <div class="h" id="h1">
+ Blue
+ </div>
+</div>
+<div class="c" id="c2">
+ <div id="a2"></div>
+ <div class="e" id="e2">
+ Red
+ </div>
+</div>
+<script>
+ document.body.offsetTop;
+
+ var black = "rgb(0, 0, 0)";
+ var blue = "rgb(0, 0, 255)";
+ var green = "rgb(0, 128, 0)";
+ var red = "rgb(255, 0, 0)";
+ var yellow = "rgb(255, 255, 0)";
+
+ test(() => {
+ assert_equals(getComputedStyle(b1).color, yellow);
+ assert_equals(getComputedStyle(b2).color, black);
+ assert_equals(getComputedStyle(b3).color, yellow);
+ assert_equals(getComputedStyle(c1).color, black);
+ assert_equals(getComputedStyle(d).color, black);
+ assert_equals(getComputedStyle(e1).color, black);
+ assert_equals(getComputedStyle(e2).color, black);
+ assert_equals(getComputedStyle(f1).color, black);
+ assert_equals(getComputedStyle(h1).color, black);
+ }, "Preconditions.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b1).color, red);
+ assert_equals(getComputedStyle(b3).color, red);
+ assert_equals(getComputedStyle(c1).color, red);
+ }, "Invalidate :not() for simple selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(d).color, green);
+ }, "Invalidate :not() for compound selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b2).color, blue);
+ assert_equals(getComputedStyle(b3).color, red);
+ assert_equals(getComputedStyle(f1).color, blue);
+ }, "Invalidate :not() for complex selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(e2).color, black);
+ a2.className = "a";
+ assert_equals(getComputedStyle(e2).color, red);
+ }, "Invalidate nested :is() inside :not().");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b2).color, blue);
+ assert_equals(getComputedStyle(h1).color, blue);
+ }, "Test specificity of :not().");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-complex-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-complex-in-has.html
new file mode 100644
index 0000000000..d24abf69f7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-complex-in-has.html
@@ -0,0 +1,375 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :not(&lt;complex-selector&gt;) in :has() argument (complex selector)</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+div { color: grey }
+.red:has(#descendant:not(.a_has_scope .b)) { color: red }
+.orangered:has(#descendant:not(.a_descendant .b)) #descendant { color: orangered }
+.darkred:has(#descendant:not(.a_indirect_next .b)) ~ #indirect_next { color: darkred }
+.pink:has(#descendant:not(.a_indirect_next_child .b)) ~ #indirect_next #indirect_next_child { color: pink }
+.green:has(#descendant:not(.p + .c_has_scope ~ .d .e)) { color: green }
+.lightgreen:has(#descendant:not(.p + .c_descendant ~ .d .e)) #descendant { color: lightgreen }
+.darkgreen:has(#descendant:not(.p + .c_indirect_next ~ .d .e)) ~ #indirect_next { color: darkgreen }
+.yellowgreen:has(#descendant:not(.p + .c_indirect_next_child ~ .d .e)) ~ #indirect_next #indirect_next_child { color: yellowgreen }
+.blue:has(~ #indirect_next:not(.p + .f_has_scope ~ .g)) { color: blue }
+.skyblue:has(~ #indirect_next:not(.p + .f_descendant ~ .g)) #descendant { color: skyblue }
+.lightblue:has(~ #indirect_next:not(.p + .f_indirect_next ~ .g)) ~ #indirect_next { color: lightblue }
+.darkblue:has(~ #indirect_next:not(.p + .f_indirect_next_child ~ .g)) ~ #indirect_next #indirect_next_child { color: darkblue }
+.yellow:has(~ #indirect_next:not(.h_has_scope .i)) { color: yellow }
+.ivory:has(~ #indirect_next:not(.h_descendant .i)) #descendant { color: ivory }
+.greenyellow:has(~ #indirect_next:not(.h_indirect_next .i)) ~ #indirect_next { color: greenyellow }
+.khaki:has(~ #indirect_next:not(.h_indirect_next_child .i)) ~ #indirect_next #indirect_next_child { color: khaki }
+.purple:has(~ #indirect_next:not(.p + .j_has_scope ~ .k .l)) { color: purple }
+.violet:has(~ #indirect_next:not(.p + .j_descendant ~ .k .l)) #descendant { color: violet }
+.orchid:has(~ #indirect_next:not(.p + .j_indirect_next ~ .k .l)) ~ #indirect_next { color: orchid }
+.plum:has(~ #indirect_next:not(.p + .j_indirect_next_child ~ .k .l)) ~ #indirect_next #indirect_next_child { color: plum }
+.orange:has(#descendant:not(.m:not(.n) .o)) { color: orange }
+</style>
+<div>
+ <div class="p"></div>
+ <div id="parent_previous"></div>
+ <div id="parent" class="d k">
+ <div class="p"></div>
+ <div id="previous"></div>
+ <div class="p"></div>
+ <div id="has_scope" class="d">
+ <div class="p"></div>
+ <div id="child_previous"></div>
+ <div id="child" class="d">
+ <div id="descendant" class="b e o"></div>
+ </div>
+ </div>
+ <div class="p"></div>
+ <div id="direct_next"></div>
+ <div id="indirect_next" class="g i l">
+ <div id="indirect_next_child"></div>
+ </div>
+ </div>
+</div>
+<script>
+const grey = "rgb(128, 128, 128)";
+const red = "rgb(255, 0, 0)";
+const orangered = "rgb(255, 69, 0)";
+const darkred = "rgb(139, 0, 0)";
+const pink = "rgb(255, 192, 203)";
+const green = "rgb(0, 128, 0)";
+const lightgreen = "rgb(144, 238, 144)";
+const darkgreen = "rgb(0, 100, 0)";
+const yellowgreen = "rgb(154, 205, 50)";
+const blue = "rgb(0, 0, 255)";
+const skyblue = "rgb(135, 206, 235)";
+const lightblue = "rgb(173, 216, 230)";
+const darkblue = "rgb(0, 0, 139)";
+const yellow = "rgb(255, 255, 0)";
+const ivory = "rgb(255, 255, 240)";
+const greenyellow = "rgb(173, 255, 47)";
+const khaki = "rgb(240, 230, 140)";
+const purple = "rgb(128, 0, 128)";
+const violet = "rgb(238, 130, 238)";
+const orchid = "rgb(218, 112, 214)";
+const plum = "rgb(221, 160, 221)";
+const orange = "rgb(255, 165, 0)";
+
+function addClass(element, class_name) {
+ element.classList.add(class_name);
+}
+
+function removeClass(element, class_name) {
+ element.classList.remove(class_name);
+}
+
+function testClassChange(operation, class_name, element_id,
+ selector, matches_result,
+ subject_id, subject_color) {
+ let element = document.getElementById(element_id);
+ assert_equals(element ? element.id : "", element_id);
+ let subject = document.getElementById(subject_id);
+ assert_equals(subject ? subject.id : "", subject_id);
+ let message_prefix = [
+ "[", selector, "]",
+ ["#", element.id, ".classList.",
+ (operation == addClass ? "add" : "remove"),
+ "('", class_name, "')"].join(""),
+ ": "].join(" ");
+ operation(element, class_name);
+ test(function() {
+ assert_equals(subject.matches(selector), matches_result);
+ }, message_prefix + "check matches (" + matches_result + ")");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, subject_color);
+ }, message_prefix + "check #" + subject_id + " color");
+}
+
+function testSiblingInsertionRemoval(class_name, insert_before_id, selector,
+ subject_id,
+ insertion_matches_result,
+ insertion_subject_color,
+ removal_matches_result,
+ removal_subject_color) {
+ let insert_before = document.getElementById(insert_before_id);
+ assert_equals(insert_before ? insert_before.id : "", insert_before_id);
+ let parent = insert_before.parentElement;
+ let subject = document.getElementById(subject_id);
+ assert_equals(subject ? subject.id : "", subject_id);
+ let message_prefix = [
+ "[", selector, "]",
+ ["insert/remove .",
+ class_name, " before #", insert_before.id, ")"].join(""),
+ ": "].join(" ");
+
+ let div = document.createElement("div");
+ div.classList.add(class_name);
+
+ parent.insertBefore(div, insert_before);
+ test(function() {
+ assert_equals(subject.matches(selector), insertion_matches_result);
+ }, message_prefix + "(insertion) check matches (" +
+ insertion_matches_result + ")");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, insertion_subject_color);
+ }, message_prefix + "(insertion) check #" + subject_id + " color");
+
+ div.remove();
+ test(function() {
+ assert_equals(subject.matches(selector), removal_matches_result);
+ }, message_prefix + "(removal) check matches (" +
+ removal_matches_result + ")");
+ test(function() {
+ assert_equals(getComputedStyle(subject).color, removal_subject_color);
+ }, message_prefix + "(removal) check #" + subject_id + " color");
+}
+
+assert_equals(getComputedStyle(has_scope).color, grey);
+
+let selector = ".red:has(#descendant:not(.a_has_scope .b))";
+testClassChange(addClass, "red", "has_scope", selector, true, "has_scope", red);
+testClassChange(addClass, "a_has_scope", "parent", selector, false, "has_scope", grey);
+testClassChange(removeClass, "a_has_scope", "parent", selector, true, "has_scope", red);
+testClassChange(addClass, "a_has_scope", "has_scope", selector, false, "has_scope", grey);
+testClassChange(removeClass, "a_has_scope", "has_scope", selector, true, "has_scope", red);
+testClassChange(addClass, "a_has_scope", "child", selector, false, "has_scope", grey);
+testClassChange(removeClass, "a_has_scope", "child", selector, true, "has_scope", red);
+testClassChange(removeClass, "red", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".orangered:has(#descendant:not(.a_descendant .b)) #descendant";
+testClassChange(addClass, "orangered", "has_scope", selector, true, "descendant", orangered);
+testClassChange(addClass, "a_descendant", "parent", selector, false, "descendant", grey);
+testClassChange(removeClass, "a_descendant", "parent", selector, true, "descendant", orangered);
+testClassChange(addClass, "a_descendant", "has_scope", selector, false, "descendant", grey);
+testClassChange(removeClass, "a_descendant", "has_scope", selector, true, "descendant", orangered);
+testClassChange(addClass, "a_descendant", "child", selector, false, "descendant", grey);
+testClassChange(removeClass, "a_descendant", "child", selector, true, "descendant", orangered);
+testClassChange(removeClass, "orangered", "has_scope", selector, false, "descendant", grey);
+
+selector = ".darkred:has(#descendant:not(.a_indirect_next .b)) ~ #indirect_next";
+testClassChange(addClass, "darkred", "has_scope", selector, true, "indirect_next", darkred);
+testClassChange(addClass, "a_indirect_next", "parent", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "a_indirect_next", "parent", selector, true, "indirect_next", darkred);
+testClassChange(addClass, "a_indirect_next", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "a_indirect_next", "has_scope", selector, true, "indirect_next", darkred);
+testClassChange(addClass, "a_indirect_next", "child", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "a_indirect_next", "child", selector, true, "indirect_next", darkred);
+testClassChange(removeClass, "darkred", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".pink:has(#descendant:not(.a_indirect_next_child .b)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "pink", "has_scope", selector, true, "indirect_next_child", pink);
+testClassChange(addClass, "a_indirect_next_child", "parent", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "a_indirect_next_child", "parent", selector, true, "indirect_next_child", pink);
+testClassChange(addClass, "a_indirect_next_child", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "a_indirect_next_child", "has_scope", selector, true, "indirect_next_child", pink);
+testClassChange(addClass, "a_indirect_next_child", "child", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "a_indirect_next_child", "child", selector, true, "indirect_next_child", pink);
+testClassChange(removeClass, "pink", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".green:has(#descendant:not(.p + .c_has_scope ~ .d .e))";
+testClassChange(addClass, "green", "has_scope", selector, true, "has_scope", green);
+testClassChange(addClass, "c_has_scope", "parent_previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "has_scope", true, green, false, grey);
+testClassChange(removeClass, "c_has_scope", "parent_previous", selector, true, "has_scope", green);
+testSiblingInsertionRemoval("c_has_scope", "parent_previous", selector, "has_scope", false, grey, true, green);
+testClassChange(addClass, "c_has_scope", "previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("invalid", "previous", selector, "has_scope", true, green, false, grey);
+testClassChange(removeClass, "c_has_scope", "previous", selector, true, "has_scope", green);
+testSiblingInsertionRemoval("c_has_scope", "previous", selector, "has_scope", false, grey, true, green);
+testClassChange(addClass, "c_has_scope", "child_previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "has_scope", true, green, false, grey);
+testClassChange(removeClass, "c_has_scope", "child_previous", selector, true, "has_scope", green);
+testSiblingInsertionRemoval("c_has_scope", "child_previous", selector, "has_scope", false, grey, true, green);
+testClassChange(removeClass, "green", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".lightgreen:has(#descendant:not(.p + .c_descendant ~ .d .e)) #descendant";
+testClassChange(addClass, "lightgreen", "has_scope", selector, true, "descendant", lightgreen);
+testClassChange(addClass, "c_descendant", "parent_previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "descendant", true, lightgreen, false, grey);
+testClassChange(removeClass, "c_descendant", "parent_previous", selector, true, "descendant", lightgreen);
+testSiblingInsertionRemoval("c_descendant", "parent_previous", selector, "descendant", false, grey, true, lightgreen);
+testClassChange(addClass, "c_descendant", "previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("invalid", "previous", selector, "descendant", true, lightgreen, false, grey);
+testClassChange(removeClass, "c_descendant", "previous", selector, true, "descendant", lightgreen);
+testSiblingInsertionRemoval("c_descendant", "previous", selector, "descendant", false, grey, true, lightgreen);
+testClassChange(addClass, "c_descendant", "child_previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "descendant", true, lightgreen, false, grey);
+testClassChange(removeClass, "c_descendant", "child_previous", selector, true, "descendant", lightgreen);
+testSiblingInsertionRemoval("c_descendant", "child_previous", selector, "descendant", false, grey, true, lightgreen);
+testClassChange(removeClass, "lightgreen", "has_scope", selector, false, "descendant", grey);
+
+selector = ".darkgreen:has(#descendant:not(.p + .c_indirect_next ~ .d .e)) ~ #indirect_next";
+testClassChange(addClass, "darkgreen", "has_scope", selector, true, "indirect_next", darkgreen);
+testClassChange(addClass, "c_indirect_next", "parent_previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next", true, darkgreen, false, grey);
+testClassChange(removeClass, "c_indirect_next", "parent_previous", selector, true, "indirect_next", darkgreen);
+testSiblingInsertionRemoval("c_indirect_next", "parent_previous", selector, "indirect_next", false, grey, true, darkgreen);
+testClassChange(addClass, "c_indirect_next", "previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next", true, darkgreen, false, grey);
+testClassChange(removeClass, "c_indirect_next", "previous", selector, true, "indirect_next", darkgreen);
+testSiblingInsertionRemoval("c_indirect_next", "previous", selector, "indirect_next", false, grey, true, darkgreen);
+testClassChange(addClass, "c_indirect_next", "child_previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "indirect_next", true, darkgreen, false, grey);
+testClassChange(removeClass, "c_indirect_next", "child_previous", selector, true, "indirect_next", darkgreen);
+testSiblingInsertionRemoval("c_indirect_next", "child_previous", selector, "indirect_next", false, grey, true, darkgreen);
+testClassChange(removeClass, "darkgreen", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".yellowgreen:has(#descendant:not(.p + .c_indirect_next_child ~ .d .e)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "yellowgreen", "has_scope", selector, true, "indirect_next_child", yellowgreen);
+testClassChange(addClass, "c_indirect_next_child", "parent_previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next_child", true, yellowgreen, false, grey);
+testClassChange(removeClass, "c_indirect_next_child", "parent_previous", selector, true, "indirect_next_child", yellowgreen);
+testSiblingInsertionRemoval("c_indirect_next_child", "parent_previous", selector, "indirect_next_child", false, grey, true, yellowgreen);
+testClassChange(addClass, "c_indirect_next_child", "previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next_child", true, yellowgreen, false, grey);
+testClassChange(removeClass, "c_indirect_next_child", "previous", selector, true, "indirect_next_child", yellowgreen);
+testSiblingInsertionRemoval("c_indirect_next_child", "previous", selector, "indirect_next_child", false, grey, true, yellowgreen);
+testClassChange(addClass, "c_indirect_next_child", "child_previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("invalid", "child_previous", selector, "indirect_next_child", true, yellowgreen, false, grey);
+testClassChange(removeClass, "c_indirect_next_child", "child_previous", selector, true, "indirect_next_child", yellowgreen);
+testSiblingInsertionRemoval("c_indirect_next_child", "child_previous", selector, "indirect_next_child", false, grey, true, yellowgreen);
+testClassChange(removeClass, "yellowgreen", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".blue:has(~ #indirect_next:not(.p + .f_has_scope ~ .g))";
+testClassChange(addClass, "blue", "has_scope", selector, true, "has_scope", blue);
+testClassChange(addClass, "f_has_scope", "previous", selector, false, "has_scope", grey);
+testClassChange(removeClass, "f_has_scope", "previous", selector, true, "has_scope", blue);
+testSiblingInsertionRemoval("f_has_scope", "previous", selector, "has_scope", false, grey, true, blue);
+testClassChange(addClass, "f_has_scope", "has_scope", selector, false, "has_scope", grey);
+testClassChange(removeClass, "f_has_scope", "has_scope", selector, true, "has_scope", blue);
+testClassChange(addClass, "f_has_scope", "direct_next", selector, false, "has_scope", grey);
+testClassChange(removeClass, "f_has_scope", "direct_next", selector, true, "has_scope", blue);
+testSiblingInsertionRemoval("f_has_scope", "direct_next", selector, "has_scope", false, grey, true, blue);
+testClassChange(removeClass, "blue", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".skyblue:has(~ #indirect_next:not(.p + .f_descendant ~ .g)) #descendant";
+testClassChange(addClass, "skyblue", "has_scope", selector, true, "descendant", skyblue);
+testClassChange(addClass, "f_descendant", "previous", selector, false, "descendant", grey);
+testClassChange(removeClass, "f_descendant", "previous", selector, true, "descendant", skyblue);
+testSiblingInsertionRemoval("f_descendant", "previous", selector, "descendant", false, grey, true, skyblue);
+testClassChange(addClass, "f_descendant", "has_scope", selector, false, "descendant", grey);
+testClassChange(removeClass, "f_descendant", "has_scope", selector, true, "descendant", skyblue);
+testClassChange(addClass, "f_descendant", "direct_next", selector, false, "descendant", grey);
+testClassChange(removeClass, "f_descendant", "direct_next", selector, true, "descendant", skyblue);
+testSiblingInsertionRemoval("f_descendant", "direct_next", selector, "descendant", false, grey, true, skyblue);
+testClassChange(removeClass, "skyblue", "has_scope", selector, false, "descendant", grey);
+
+selector = ".lightblue:has(~ #indirect_next:not(.p + .f_indirect_next ~ .g)) ~ #indirect_next";
+testClassChange(addClass, "lightblue", "has_scope", selector, true, "indirect_next", lightblue);
+testClassChange(addClass, "f_indirect_next", "previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next", true, lightblue, false, grey);
+testClassChange(removeClass, "f_indirect_next", "previous", selector, true, "indirect_next", lightblue);
+testSiblingInsertionRemoval("f_indirect_next", "previous", selector, "indirect_next", false, grey, true, lightblue);
+testClassChange(addClass, "f_indirect_next", "has_scope", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "f_indirect_next", "has_scope", selector, true, "indirect_next", lightblue);
+testClassChange(addClass, "f_indirect_next", "direct_next", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("invalid", "direct_next", selector, "indirect_next", true, lightblue, false, grey);
+testClassChange(removeClass, "f_indirect_next", "direct_next", selector, true, "indirect_next", lightblue);
+testSiblingInsertionRemoval("f_indirect_next", "direct_next", selector, "indirect_next", false, grey, true, lightblue);
+testClassChange(removeClass, "lightblue", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".darkblue:has(~ #indirect_next:not(.p + .f_indirect_next_child ~ .g)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "darkblue", "has_scope", selector, true, "indirect_next_child", darkblue);
+testClassChange(addClass, "f_indirect_next_child", "previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next_child", true, darkblue, false, grey);
+testClassChange(removeClass, "f_indirect_next_child", "previous", selector, true, "indirect_next_child", darkblue);
+testSiblingInsertionRemoval("f_indirect_next_child", "previous", selector, "indirect_next_child", false, grey, true, darkblue);
+testClassChange(addClass, "f_indirect_next_child", "has_scope", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "f_indirect_next_child", "has_scope", selector, true, "indirect_next_child", darkblue);
+testClassChange(addClass, "f_indirect_next_child", "direct_next", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("invalid", "direct_next", selector, "indirect_next_child", true, darkblue, false, grey);
+testClassChange(removeClass, "f_indirect_next_child", "direct_next", selector, true, "indirect_next_child", darkblue);
+testSiblingInsertionRemoval("f_indirect_next_child", "direct_next", selector, "indirect_next_child", false, grey, true, darkblue);
+testClassChange(removeClass, "darkblue", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".yellow:has(~ #indirect_next:not(.h_has_scope .i))"
+testClassChange(addClass, "yellow", "has_scope", selector, true, "has_scope", yellow);
+testClassChange(addClass, "h_has_scope", "parent", selector, false, "has_scope", grey);
+testClassChange(removeClass, "h_has_scope", "parent", selector, true, "has_scope", yellow);
+testClassChange(removeClass, "yellow", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".ivory:has(~ #indirect_next:not(.h_descendant .i)) #descendant";
+testClassChange(addClass, "ivory", "has_scope", selector, true, "descendant", ivory);
+testClassChange(addClass, "h_descendant", "parent", selector, false, "descendant", grey);
+testClassChange(removeClass, "h_descendant", "parent", selector, true, "descendant", ivory);
+testClassChange(removeClass, "ivory", "has_scope", selector, false, "descendant", grey);
+
+selector = ".greenyellow:has(~ #indirect_next:not(.h_indirect_next .i)) ~ #indirect_next";
+testClassChange(addClass, "greenyellow", "has_scope", selector, true, "indirect_next", greenyellow);
+testClassChange(addClass, "h_indirect_next", "parent", selector, false, "indirect_next", grey);
+testClassChange(removeClass, "h_indirect_next", "parent", selector, true, "indirect_next", greenyellow);
+testClassChange(removeClass, "greenyellow", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".khaki:has(~ #indirect_next:not(.h_indirect_next_child .i)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "khaki", "has_scope", selector, true, "indirect_next_child", khaki);
+testClassChange(addClass, "h_indirect_next_child", "parent", selector, false, "indirect_next_child", grey);
+testClassChange(removeClass, "h_indirect_next_child", "parent", selector, true, "indirect_next_child", khaki);
+testClassChange(removeClass, "khaki", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".purple:has(~ #indirect_next:not(.p + .j_has_scope ~ .k .l))"
+testClassChange(addClass, "purple", "has_scope", selector, true, "has_scope", purple);
+testClassChange(addClass, "j_has_scope", "parent_previous", selector, false, "has_scope", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "has_scope", true, purple, false, grey);
+testClassChange(removeClass, "j_has_scope", "parent_previous", selector, true, "has_scope", purple);
+testSiblingInsertionRemoval("j_has_scope", "parent_previous", selector, "has_scope", false, grey, true, purple);
+testClassChange(removeClass, "purple", "has_scope", selector, false, "has_scope", grey);
+
+selector = ".violet:has(~ #indirect_next:not(.p + .j_descendant ~ .k .l)) #descendant";
+testClassChange(addClass, "violet", "has_scope", selector, true, "descendant", violet);
+testClassChange(addClass, "j_descendant", "parent_previous", selector, false, "descendant", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "descendant", true, violet, false, grey);
+testClassChange(removeClass, "j_descendant", "parent_previous", selector, true, "descendant", violet);
+testSiblingInsertionRemoval("j_descendant", "parent_previous", selector, "descendant", false, grey, true, violet);
+testClassChange(removeClass, "violet", "has_scope", selector, false, "descendant", grey);
+
+selector = ".orchid:has(~ #indirect_next:not(.p + .j_indirect_next ~ .k .l)) ~ #indirect_next";
+testClassChange(addClass, "orchid", "has_scope", selector, true, "indirect_next", orchid);
+testClassChange(addClass, "j_indirect_next", "parent_previous", selector, false, "indirect_next", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next", true, orchid, false, grey);
+testClassChange(removeClass, "j_indirect_next", "parent_previous", selector, true, "indirect_next", orchid);
+testSiblingInsertionRemoval("j_indirect_next", "parent_previous", selector, "indirect_next", false, grey, true, orchid);
+testClassChange(removeClass, "orchid", "has_scope", selector, false, "indirect_next", grey);
+
+selector = ".plum:has(~ #indirect_next:not(.p + .j_indirect_next_child ~ .k .l)) ~ #indirect_next #indirect_next_child";
+testClassChange(addClass, "plum", "has_scope", selector, true, "indirect_next_child", plum);
+testClassChange(addClass, "j_indirect_next_child", "parent_previous", selector, false, "indirect_next_child", grey);
+testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next_child", true, plum, false, grey);
+testClassChange(removeClass, "j_indirect_next_child", "parent_previous", selector, true, "indirect_next_child", plum);
+testSiblingInsertionRemoval("j_indirect_next_child", "parent_previous", selector, "indirect_next_child", false, grey, true, plum);
+testClassChange(removeClass, "plum", "has_scope", selector, false, "indirect_next_child", grey);
+
+selector = ".orange:has(#descendant:not(.m:not(.n) .o))";
+testClassChange(addClass, "orange", "has_scope", selector, true, "has_scope", orange);
+testClassChange(addClass, "m", "parent", selector, false, "has_scope", grey);
+testClassChange(addClass, "n", "parent", selector, true, "has_scope", orange);
+testClassChange(removeClass, "n", "parent", selector, false, "has_scope", grey);
+testClassChange(removeClass, "m", "parent", selector, true, "has_scope", orange);
+testClassChange(addClass, "m", "has_scope", selector, false, "has_scope", grey);
+testClassChange(addClass, "n", "has_scope", selector, true, "has_scope", orange);
+testClassChange(removeClass, "n", "has_scope", selector, false, "has_scope", grey);
+testClassChange(removeClass, "m", "has_scope", selector, true, "has_scope", orange);
+testClassChange(addClass, "m", "child", selector, false, "has_scope", grey);
+testClassChange(addClass, "n", "child", selector, true, "has_scope", orange);
+testClassChange(removeClass, "n", "child", selector, false, "has_scope", grey);
+testClassChange(removeClass, "m", "child", selector, true, "has_scope", orange);
+testClassChange(removeClass, "orange", "has_scope", selector, false, "has_scope", grey);
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-sibling-relationship-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-sibling-relationship-in-has.html
new file mode 100644
index 0000000000..ec6d86198b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/not-pseudo-containing-sibling-relationship-in-has.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors Test: :has(:not()) invalidation for sibling change</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<style>
+ #test-container > div { background-color: green; }
+ #target1:has(:not(.item, :nth-child(3))) { background-color: red; }
+ #target2:has(:not(.item, :nth-last-child(3))) { background-color: red; }
+</style>
+<div id="test-container">
+ <div id="target1">
+ <div class="item"></div>
+ <div id="item1">This text should have a green background</div>
+ </div>
+ <div id="target2">
+ <div id="item2">This text should have a green background</div>
+ <div class="item"></div>
+ </div>
+</div>
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(target1).backgroundColor, "rgb(255, 0, 0)");
+ assert_equals(getComputedStyle(target2).backgroundColor, "rgb(255, 0, 0)");
+ }, "Initially red");
+
+ function insertDivItemBefore(item) {
+ let div = document.createElement("div");
+ div.classList.add("item");
+ item.parentElement.insertBefore(div, item);
+ }
+
+ function insertDivItemAfter(item) {
+ let div = document.createElement("div");
+ div.classList.add("item");
+ item.parentElement.append(div, item.nextSibling);
+ }
+
+ test(() => {
+ insertDivItemBefore(item1);
+ assert_equals(getComputedStyle(target1).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-child() enclosed by :not() matching after insertion");
+
+ test(() => {
+ insertDivItemAfter(item2);
+ assert_equals(getComputedStyle(target2).backgroundColor, "rgb(0, 128, 0)");
+ }, ":nth-last-child() enclosed by :not() matching after insertion");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor-ref.html
new file mode 100644
index 0000000000..6e6680d8c3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of S) with ancestor in S</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <div>
+ <div>
+ <div style="color: green">Should be green</div>
+ </div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor.html
new file mode 100644
index 0000000000..a7f246328c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-containing-ancestor.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of S) with ancestor in S</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-containing-ancestor-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ div:nth-child(odd of .a .b) {
+ color: green;
+ }
+</style>
+<div id="toggler">
+ <div>
+ <div>
+ <div class="b">Should be green</div>
+ </div>
+ </div>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("a");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root-ref.html
new file mode 100644
index 0000000000..5e9600ad0e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <div style="color: green">Should be green</div>
+ <div style="color: red">Should be red</div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root.html
new file mode 100644
index 0000000000..1618033c95
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-in-shadow-root.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>CSS Selectors Invalidation: :nth-child(An+B) within shadow root</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#nth-child-pseudo">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1480746">
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-in-shadow-root-ref.html">
+<div id="host">
+ <template shadowrootmode="open">
+ <div id="firstChild">Should be red</div>
+ <style>
+ :nth-child(odd) {
+ color: green;
+ }
+ :nth-child(even) {
+ color: red;
+ }
+ </style>
+ </template>
+</div>
+<script>
+host.offsetTop;
+let div = document.createElement("div");
+div.appendChild(document.createTextNode("Should be green"));
+requestAnimationFrame(() =>
+ requestAnimationFrame(() => {
+ host.shadowRoot.insertBefore(div, host.shadowRoot.firstElementChild);
+ takeScreenshot();
+ }));
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html
new file mode 100644
index 0000000000..07617c53ad
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html
@@ -0,0 +1,452 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of attribute) with a large DOM</title>
+<link rel="author" title="Bramus" href="https://www.bram.us/">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<table border="1">
+ <thead>
+ <tr>
+ <th>#</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr hidden="hidden">
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>3</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>5</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>6</td>
+ </tr>
+ <tr>
+ <td>7</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>8</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>9</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>10</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>11</td>
+ </tr>
+ <tr>
+ <td>12</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>13</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>14</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>15</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>16</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>17</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>18</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>19</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>20</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>21</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>22</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>23</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>24</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>25</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>26</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>27</td>
+ </tr>
+ <tr>
+ <td>28</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>29</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>30</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>31</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>32</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>33</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>34</td>
+ </tr>
+ <tr>
+ <td>35</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>36</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>37</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>38</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>39</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>40</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>41</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>42</td>
+ </tr>
+ <tr>
+ <td>43</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>44</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>45</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>46</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>47</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>48</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>49</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>50</td>
+ </tr>
+ <tr>
+ <td>51</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>52</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>53</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>54</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>55</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>56</td>
+ </tr>
+ <tr>
+ <td>57</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>58</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>59</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>60</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>61</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>62</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>63</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>64</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>65</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>66</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>67</td>
+ </tr>
+ <tr>
+ <td>68</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>69</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>70</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>71</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>72</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>73</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>74</td>
+ </tr>
+ <tr>
+ <td>75</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>76</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>77</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>78</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>79</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>80</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>81</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>82</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>83</td>
+ </tr>
+ <tr>
+ <td>84</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>85</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>86</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>87</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>88</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>89</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>90</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>91</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>92</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>93</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>94</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>95</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>96</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>97</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>98</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>99</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>100</td>
+ </tr>
+ <tr>
+ <td>101</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>102</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>103</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>104</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>105</td>
+ </tr>
+ <tr>
+ <td>106</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>107</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>108</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>109</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>110</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>111</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>112</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>113</td>
+ </tr>
+ <tr>
+ <td>114</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>115</td>
+ </tr>
+ <tr>
+ <td>116</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>117</td>
+ </tr>
+ <tr>
+ <td>118</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>119</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>120</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>121</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>122</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>123</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>124</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>125</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>126</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>127</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>128</td>
+ </tr>
+ <tr>
+ <td>129</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>130</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>131</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>132</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>133</td>
+ </tr>
+ <tr>
+ <td>134</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>135</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>136</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>137</td>
+ </tr>
+ <tr>
+ <td>138</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>139</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>140</td>
+ </tr>
+ <tr style="background: lightgrey;">
+ <td>141</td>
+ </tr>
+ <tr>
+ <td>142</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>143</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>144</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>145</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>146</td>
+ </tr>
+ </tbody>
+</table> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom.html
new file mode 100644
index 0000000000..07d87d2d4b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-largedom.html
@@ -0,0 +1,462 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of attribute) with a large DOM</title>
+<link rel="author" title="Bramus" href="https://www.bram.us/">
+<link rel="match" href="nth-child-of-attr-largedom-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ tr:nth-child(even of :not([hidden])){
+ background: lightgrey;
+ }
+</style>
+<table border="1">
+ <thead>
+ <tr>
+ <th>#</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr hidden="hidden">
+ <td>1</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ </tr>
+ <tr>
+ <td>3</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ </tr>
+ <tr>
+ <td>5</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>6</td>
+ </tr>
+ <tr>
+ <td>7</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>8</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>9</td>
+ </tr>
+ <tr>
+ <td>10</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>11</td>
+ </tr>
+ <tr>
+ <td>12</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>13</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>14</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>15</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>16</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>17</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>18</td>
+ </tr>
+ <tr>
+ <td>19</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>20</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>21</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>22</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>23</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>24</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>25</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>26</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>27</td>
+ </tr>
+ <tr>
+ <td>28</td>
+ </tr>
+ <tr>
+ <td>29</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>30</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>31</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>32</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>33</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>34</td>
+ </tr>
+ <tr>
+ <td>35</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>36</td>
+ </tr>
+ <tr>
+ <td>37</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>38</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>39</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>40</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>41</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>42</td>
+ </tr>
+ <tr>
+ <td>43</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>44</td>
+ </tr>
+ <tr>
+ <td>45</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>46</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>47</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>48</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>49</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>50</td>
+ </tr>
+ <tr>
+ <td>51</td>
+ </tr>
+ <tr>
+ <td>52</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>53</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>54</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>55</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>56</td>
+ </tr>
+ <tr>
+ <td>57</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>58</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>59</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>60</td>
+ </tr>
+ <tr>
+ <td>61</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>62</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>63</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>64</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>65</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>66</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>67</td>
+ </tr>
+ <tr>
+ <td>68</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>69</td>
+ </tr>
+ <tr>
+ <td>70</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>71</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>72</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>73</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>74</td>
+ </tr>
+ <tr>
+ <td>75</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>76</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>77</td>
+ </tr>
+ <tr>
+ <td>78</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>79</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>80</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>81</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>82</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>83</td>
+ </tr>
+ <tr>
+ <td>84</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>85</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>86</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>87</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>88</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>89</td>
+ </tr>
+ <tr>
+ <td>90</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>91</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>92</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>93</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>94</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>95</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>96</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>97</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>98</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>99</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>100</td>
+ </tr>
+ <tr>
+ <td>101</td>
+ </tr>
+ <tr>
+ <td>102</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>103</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>104</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>105</td>
+ </tr>
+ <tr>
+ <td>106</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>107</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>108</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>109</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>110</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>111</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>112</td>
+ </tr>
+ <tr>
+ <td>113</td>
+ </tr>
+ <tr>
+ <td>114</td>
+ </tr>
+ <tr>
+ <td>115</td>
+ </tr>
+ <tr>
+ <td>116</td>
+ </tr>
+ <tr>
+ <td>117</td>
+ </tr>
+ <tr>
+ <td>118</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>119</td>
+ </tr>
+ <tr>
+ <td>120</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>121</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>122</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>123</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>124</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>125</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>126</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>127</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>128</td>
+ </tr>
+ <tr>
+ <td>129</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>130</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>131</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>132</td>
+ </tr>
+ <tr>
+ <td>133</td>
+ </tr>
+ <tr>
+ <td>134</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>135</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>136</td>
+ </tr>
+ <tr>
+ <td>137</td>
+ </tr>
+ <tr>
+ <td>138</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>139</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>140</td>
+ </tr>
+ <tr>
+ <td>141</td>
+ </tr>
+ <tr>
+ <td>142</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>143</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>144</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>145</td>
+ </tr>
+ <tr hidden="hidden">
+ <td>146</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+ document.documentElement.offsetTop;
+ document.querySelectorAll(`tbody tr:not([data-affiliation=google-llc"])`).forEach($tr => $tr.setAttribute('hidden', 'hidden'));
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-ref.html
new file mode 100644
index 0000000000..5207cc987d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of attribute)</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p>Not ignored</p>
+ <p>Selectively ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr.html
new file mode 100644
index 0000000000..d4e82ff78c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-attr.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of attribute)</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-of-attr-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of [attr="yes"]) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p attr="no">Ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="yes" id="toggler">Selectively ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.setAttribute("attr", "no");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-prefix.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-prefix.html
new file mode 100644
index 0000000000..2ea57c099f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-prefix.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class prefix)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of [class^=t]) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p class="t1">Not ignored</p>
+ <p id="toggler" class="t2">Selectively ignored</p>
+ <p class="t3">Not ignored</p>
+ <p class="t4">Not ignored</p>
+ <p class="t5">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.setAttribute("class", "new-class");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-ref.html
new file mode 100644
index 0000000000..d4e2dfb71d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class)</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p>Not ignored</p>
+ <p>Selectively ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class.html
new file mode 100644
index 0000000000..1171f25c0a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-class.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class)</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of .c) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c" id="toggler">Selectively ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has-ref.html
new file mode 100644
index 0000000000..39f0501b82
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of :has(...))</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p>Not ignored</p>
+ <p>Selectively ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has.html
new file mode 100644
index 0000000000..8473828973
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-has.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of :has(...))</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-of-has-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of :has(.c)) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Selectively <span><span><span class="c" id="toggler"></span></span></span>ignored</p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-id-prefix.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-id-prefix.html
new file mode 100644
index 0000000000..b07b1cfc41
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-id-prefix.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of ID prefix)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of [id^=t]) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p id="t1">Not ignored</p>
+ <p id="t2">Selectively ignored</p>
+ <p id="t3">Not ignored</p>
+ <p id="t4">Not ignored</p>
+ <p id="t5">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ t2.id = "new-id";
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-ids.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-ids.html
new file mode 100644
index 0000000000..8e94aa3e22
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-ids.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of IDs)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of #t1, #t2, #t3, #t4, #t5) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p id="t1">Not ignored</p>
+ <p id="t2">Selectively ignored</p>
+ <p id="t3">Not ignored</p>
+ <p id="t4">Not ignored</p>
+ <p id="t5">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ t2.id = "new-id";
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html
new file mode 100644
index 0000000000..bc7ecb9ff7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class) as ancestor</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <p>Not <span style="color: green">ignored</span></p>
+ <p>Selectively <span>ignored<span></p>
+ <p>Not <span>ignored</span></p>
+ <p>Not <span style="color: green">ignored</span></p>
+ <p>Not <span>ignored</span></p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor.html
new file mode 100644
index 0000000000..2ae80061b0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-ancestor.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class) as ancestor</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-of-in-ancestor-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(odd of .c) span {
+ color: green;
+ }
+</style>
+<div>
+ <p class="c">Not <span>ignored</span></p>
+ <p class="c" id="toggler">Selectively <span>ignored<span></p>
+ <p class="c">Not <span>ignored</span></p>
+ <p class="c">Not <span>ignored</span></p>
+ <p class="c">Not <span>ignored</span></p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-is.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-is.html
new file mode 100644
index 0000000000..f004195c83
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-is.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :is(:nth-child(... of class))</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:is(:nth-child(even of .c)) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c" id="toggler">Selectively ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html
new file mode 100644
index 0000000000..060c07deca
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>CSS Selectors Invalidation: :nth-child(... of class) within shadow root</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <div>No green</div>
+ <div>No green</div>
+ <div style="color: green">Should be green</div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root.html
new file mode 100644
index 0000000000..519885ea78
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-in-shadow-root.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>CSS Selectors Invalidation: :nth-child(... of class) within shadow root</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-of-in-shadow-root-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div id="host">
+ <template shadowrootmode="open">
+ <style>
+ div:nth-child(even of .foo) {
+ color: green;
+ }
+ </style>
+ <div class="foo" id="toggler">No green</div>
+ <div class="foo">No green</div>
+ <div class="foo">Should be green</div>
+ </template>
+</div>
+<script>
+ host.offsetTop;
+ host.shadowRoot.getElementById('toggler').classList.toggle('foo');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-is.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-is.html
new file mode 100644
index 0000000000..4473845a7a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-is.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-child(... of :is)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of :is(.c)) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c" id="toggler">Selectively ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class-ref.html
new file mode 100644
index 0000000000..b06f47aafa
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Selectively ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class.html
new file mode 100644
index 0000000000..2a0b071b93
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-pseudo-class.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-child(... of pseudo-class)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-child-of-pseudo-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(odd of :defined) {
+ color: green;
+ }
+
+ not-defined, my-element {
+ display: block;
+ margin-block: 1em;
+ margin-inline: 0;
+ }
+</style>
+<div>
+ <not-defined>Ignored</not-defined>
+ <not-defined>Ignored</not-defined>
+ <p>Not ignored</p>
+ <my-element>Selectively ignored</my-element>
+ <p>Not ignored</p>
+ <p>Not ignored</p>
+ <p>Not ignored</p>
+ <not-defined>Ignored</not-defined>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ customElements.define("my-element", class MyElement extends HTMLElement{});
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling-ref.html
new file mode 100644
index 0000000000..ed7fefc59f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of sibling)</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <p>Ignored</p>
+ <p>Ignored</p>
+ <p>Selectively ignored</p>
+ <p>Ignored</p>
+ <p>Not ignored</p>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling.html
new file mode 100644
index 0000000000..68e46518ec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-of-sibling.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of sibling)</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-of-sibling-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-child(even of .a + .b) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p class="a" id="toggler">Ignored</p>
+ <p class="b">Selectively ignored</p>
+ <p class="a">Ignored</p>
+ <p class="b">Not ignored</p>
+ <p class="a">Ignored</p>
+ <p class="b">Not ignored</p>
+ <p class="a">Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("a");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html
new file mode 100644
index 0000000000..7e3f7f0c98
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class) when ancestor changes</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div id="toggler">
+ <p>Ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes.html
new file mode 100644
index 0000000000..c4a97ee7e8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-ancestor-changes.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class) when ancestor changes</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-when-ancestor-changes-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ .ancestor :nth-child(even of .c) {
+ color: green;
+ }
+</style>
+<div id="toggler">
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("ancestor");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html
new file mode 100644
index 0000000000..f30a853cae
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class) when sibling changes</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div>
+ <p>Ignored</p>
+ <p>Odd; used to be green, should not be since no sibling</p>
+ <p>Even, so should not be green</p>
+ <p>Odd, but no sibling, so should not be green</p>
+ <p>Even, so should not be green</p>
+ <p>Ignored</p>
+ <p style="color: green">Odd, should be green</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes.html b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes.html
new file mode 100644
index 0000000000..43374df917
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-child-when-sibling-changes.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-child(... of class) when sibling changes</title>
+<link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
+<link rel="match" href="nth-child-when-sibling-changes-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ .sibling + :nth-child(odd of .c) {
+ color: green;
+ }
+</style>
+<div>
+ <p class="sibling" id="toggler">Ignored</p>
+ <p class="c">Odd; used to be green, should not be since no sibling</p>
+ <p class="c">Even, so should not be green</p>
+ <p class="c" class="sibling">Odd, but no sibling, so should not be green</p>
+ <p class="c">Even, so should not be green</p>
+ <p class="sibling">Ignored</p>
+ <p class="c">Odd, should be green</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("sibling");
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-containing-ancestor.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-containing-ancestor.html
new file mode 100644
index 0000000000..f3a63bdb2e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-containing-ancestor.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of S) with ancestor in S</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-child-containing-ancestor-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ div:nth-last-child(odd of .a .b) {
+ color: green;
+ }
+</style>
+<div id="toggler">
+ <div>
+ <div>
+ <div class="b">Should be green</div>
+ </div>
+ </div>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("a");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root-ref.html
new file mode 100644
index 0000000000..c7adfe3557
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <div style="color: red">Should be red</div>
+ <div style="color: green">Should be green</div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root.html
new file mode 100644
index 0000000000..4145bf7498
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-in-shadow-root.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>CSS Selectors Invalidation: :nth-last-child(An+B) within shadow root</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#nth-last-child-pseudo">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1480746">
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-in-shadow-root-ref.html">
+<div id="host">
+ <template shadowrootmode="open">
+ <div id="firstChild">Should be red</div>
+ <style>
+ :nth-last-child(odd) {
+ color: red;
+ }
+ :nth-last-child(even) {
+ color: green;
+ }
+ </style>
+ </template>
+</div>
+<script>
+host.offsetTop;
+let div = document.createElement("div");
+div.appendChild(document.createTextNode("Should be green"));
+requestAnimationFrame(() =>
+ requestAnimationFrame(() => {
+ host.shadowRoot.insertBefore(div, host.shadowRoot.firstElementChild.nextSibling);
+ takeScreenshot();
+ }));
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr-ref.html
new file mode 100644
index 0000000000..6d0eb88a81
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Selectively ignored</p>
+ <p>Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr.html
new file mode 100644
index 0000000000..9381796bf1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-attr.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of attribute)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-of-attr-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of [attr="yes"]) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="yes" id="toggler">Selectively ignored</p>
+ <p attr="yes">Not ignored</p>
+ <p attr="no">Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.setAttribute("attr", "no");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-prefix.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-prefix.html
new file mode 100644
index 0000000000..da12246926
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-prefix.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-last-child(... of class prefix)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of [class^=t]) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p class="t5">Not ignored</p>
+ <p class="t4">Not ignored</p>
+ <p class="t3">Not ignored</p>
+ <p id="toggler" class="t2">Selectively ignored</p>
+ <p class="t1">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.setAttribute("class", "new-class");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-ref.html
new file mode 100644
index 0000000000..6d0eb88a81
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Selectively ignored</p>
+ <p>Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class.html
new file mode 100644
index 0000000000..2026796bb9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-class.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of class)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of .c) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c" id="toggler">Selectively ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has-ref.html
new file mode 100644
index 0000000000..6d0eb88a81
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Selectively ignored</p>
+ <p>Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has.html
new file mode 100644
index 0000000000..0c80925f87
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-has.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of :has(...))</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-of-has-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of :has(.c)) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Selectively <span><span><span class="c" id="toggler"></span></span></span>ignored</p>
+ <p>Not <span class="c">ignored</span></p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-id-prefix.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-id-prefix.html
new file mode 100644
index 0000000000..747236aca0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-id-prefix.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-last-child(... of ID prefix)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of [id^=t]) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p id="t5">Not ignored</p>
+ <p id="t4">Not ignored</p>
+ <p id="t3">Not ignored</p>
+ <p id="t2">Selectively ignored</p>
+ <p id="t1">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ t2.id = "new-id";
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-ids.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-ids.html
new file mode 100644
index 0000000000..def336119a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-ids.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :nth-last-child(... of IDs)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of #t1, #t2, #t3, #t4, #t5) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p id="t5">Not ignored</p>
+ <p id="t4">Not ignored</p>
+ <p id="t3">Not ignored</p>
+ <p id="t2">Selectively ignored</p>
+ <p id="t1">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ t2.id = "new-id";
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor-ref.html
new file mode 100644
index 0000000000..21e6ae0f6f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor-ref.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p>Not <span>ignored</span></p>
+ <p>Not <span style="color: green">ignored</span></p>
+ <p>Not <span>ignored</span></p>
+ <p>Selectively <span>ignored</span></p>
+ <p>Not <span style="color: green">ignored</span></p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor.html
new file mode 100644
index 0000000000..b4e0e6f4f6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-ancestor.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of class) as ancestor</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-of-in-ancestor-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(odd of .c) span {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p class="c">Not <span>ignored</span></p>
+ <p class="c">Not <span>ignored</span></p>
+ <p class="c">Not <span>ignored</span></p>
+ <p class="c" id="toggler">Selectively <span>ignored</span></p>
+ <p class="c">Not <span>ignored</span></p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-is.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-is.html
new file mode 100644
index 0000000000..370883ecf1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-is.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :is(:nth-last-child(... of class))</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:is(:nth-last-child(even of .c)) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c" id="toggler">Selectively ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root-ref.html
new file mode 100644
index 0000000000..3eb330f58c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <div style="color: green">Should be green</div>
+ <div>No green</div>
+ <div>No green</div>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root.html
new file mode 100644
index 0000000000..7ae04f302c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-in-shadow-root.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of class) within shadow root</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-of-in-shadow-root-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<div id="host">
+ <template shadowrootmode="open">
+ <style>
+ div:nth-last-child(even of .foo) {
+ color: green;
+ }
+ </style>
+ <div class="foo">Should be green</div>
+ <div class="foo">No green</div>
+ <div class="foo" id="toggler">No green</div>
+ </template>
+</div>
+<script>
+ host.offsetTop;
+ host.shadowRoot.getElementById("toggler").classList.toggle("foo");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-is.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-is.html
new file mode 100644
index 0000000000..0db7347698
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-is.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of :is)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-of-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of :is(.c)) {
+ color: green;
+ }
+</style>
+<div>
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c" id="toggler">Selectively ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("c");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class-ref.html
new file mode 100644
index 0000000000..370e8887c5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Selectively ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class.html
new file mode 100644
index 0000000000..1907532065
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-pseudo-class.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of pseudo-class)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="match" href="nth-last-child-of-pseudo-class-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(odd of :defined) {
+ color: green;
+ }
+
+ not-defined, my-element {
+ display: block;
+ margin-block: 1em;
+ margin-inline: 0;
+ }
+</style>
+<div>
+ <not-defined>Ignored</not-defined>
+ <p>Not ignored</p>
+ <p>Not ignored</p>
+ <p>Not ignored</p>
+ <my-element>Selectively ignored</my-element>
+ <p>Not ignored</p>
+ <not-defined>Ignored</not-defined>
+ <not-defined>Ignored</not-defined>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ customElements.define("my-element", class MyElement extends HTMLElement{});
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling-ref.html
new file mode 100644
index 0000000000..349a7b66fb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Ignored</p>
+ <p>Not ignored</p>
+ <p>Ignored</p>
+ <p>Selectively ignored</p>
+ <p>Ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling.html
new file mode 100644
index 0000000000..b7b9bd70ab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-of-sibling.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of sibling)</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-of-sibling-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ p:nth-last-child(even of .a + .b) {
+ color: green;
+ }
+</style>
+<div>
+ <p class="a">Ignored</p>
+ <p class="b">Not ignored</p>
+ <p class="a">Ignored</p>
+ <p class="b">Not ignored</p>
+ <p class="a">Ignored</p>
+ <p class="b" id="toggler">Selectively ignored</p>
+ <p class="a">Ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("b");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes-ref.html
new file mode 100644
index 0000000000..48eeb7b3c6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes-ref.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div id="toggler">
+ <p>Ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p style="color: green">Not ignored</p>
+ <p>Not ignored</p>
+ <p>Ignored</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes.html
new file mode 100644
index 0000000000..1cc7020e5b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-ancestor-changes.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of class) when ancestor changes</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-when-ancestor-changes-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ .ancestor :nth-last-child(even of .c) {
+ color: green;
+ }
+</style>
+<div id="toggler">
+ <p>Ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p class="c">Not ignored</p>
+ <p>Ignored</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("ancestor");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes-ref.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes-ref.html
new file mode 100644
index 0000000000..627ebc074b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test Reference</title>
+<div>
+ <p>Ignored</p>
+ <p>Odd; used to be green, should not be since no sibling</p>
+ <p>Even, so should not be green</p>
+ <p>Odd, but no sibling, so should not be green</p>
+ <p>Even, so should not be green</p>
+ <p>Ignored</p>
+ <p style="color: green">Odd, should be green</p>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes.html b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes.html
new file mode 100644
index 0000000000..a8c2156483
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/nth-last-child-when-sibling-changes.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Selectors Invalidation: :nth-last-child(... of class) when sibling changes</title>
+<link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="nth-last-child-when-sibling-changes-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<style>
+ .sibling + :nth-last-child(odd of .c) {
+ color: green;
+ }
+</style>
+<div>
+ <p class="sibling" id="toggler">Ignored</p>
+ <p class="c">Odd; used to be green, should not be since no sibling</p>
+ <p class="c">Even, so should not be green</p>
+ <p class="c" class="sibling">Odd, but no sibling, so should not be green</p>
+ <p class="c">Even, so should not be green</p>
+ <p class="sibling">Ignored</p>
+ <p class="c">Odd, should be green</p>
+</div>
+<script>
+ document.documentElement.offsetTop;
+ toggler.classList.toggle("sibling");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/part-dir.html b/testing/web-platform/tests/css/selectors/invalidation/part-dir.html
new file mode 100644
index 0000000000..6672d267be
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/part-dir.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<title>::part():dir() invalidation</title>
+<link rel="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<link rel="help" href="https://drafts.csswg.org/css-shadow-parts/#part" />
+<link rel="help" href="https://github.com/whatwg/html/pull/8467" />
+<style>
+ my-element::part(inner) {
+ background-color: #ff0000;
+ }
+ my-element::part(inner):dir(ltr) {
+ background-color: #00ff00;
+ }
+ my-element::part(inner):dir(rtl) {
+ background-color: #0000ff;
+ }
+</style>
+<body>
+ <my-element id="subject"></my-element>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ const RED = "rgb(255, 0, 0)";
+ const GREEN = "rgb(0, 255, 0)";
+ const BLUE = "rgb(0, 0, 255)";
+ customElements.define(
+ "my-element",
+ class MyElement extends HTMLElement {
+ connectedCallback() {
+ this.attachShadow({
+ mode: "open",
+ }).innerHTML = `<div part="inner">Test</div>`;
+ this.elementInternals = this.attachInternals();
+ }
+
+ get inner() {
+ return this.shadowRoot.querySelector("[part=inner]");
+ }
+ },
+ );
+
+ test((t) => {
+ t.add_cleanup(() => {
+ subject.inner.lang = null;
+ });
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, GREEN);
+ subject.inner.dir = "rtl";
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, BLUE);
+ subject.inner.dir = "ltr";
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, GREEN);
+ }, "::part():dir() invalidation");
+
+ test((t) => {
+ t.add_cleanup(() => {
+ subject.removeAttribute("dir");
+ });
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, GREEN);
+ subject.inner.setAttribute("dir", "rtl");
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, BLUE);
+ subject.inner.removeAttribute("dir");
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, GREEN);
+ }, "::part():dir() invalidation from setAttribute");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/part-lang.html b/testing/web-platform/tests/css/selectors/invalidation/part-lang.html
new file mode 100644
index 0000000000..438098b8ef
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/part-lang.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<title>::part():lang() invalidation</title>
+<link rel="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<link rel="help" href="https://drafts.csswg.org/css-shadow-parts/#part" />
+<link rel="help" href="https://github.com/whatwg/html/pull/8467" />
+<style>
+ my-element::part(inner) {
+ background-color: #ff0000;
+ }
+ my-element::part(inner):lang(en) {
+ background-color: #00ffff;
+ }
+ my-element::part(inner):lang(en-GB) {
+ background-color: #00ff00;
+ }
+ my-element::part(inner):lang(fr) {
+ background-color: #0000ff;
+ }
+</style>
+<body>
+ <my-element id="subject" lang="en"></my-element>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ const RED = "rgb(255, 0, 0)";
+ const GREEN = "rgb(0, 255, 0)";
+ const BLUE = "rgb(0, 0, 255)";
+ const AQUA = "rgb(0, 255, 255)";
+ customElements.define(
+ "my-element",
+ class MyElement extends HTMLElement {
+ connectedCallback() {
+ this.attachShadow({
+ mode: "open",
+ }).innerHTML = `<div part="inner">Test</div>`;
+ this.elementInternals = this.attachInternals();
+ }
+
+ get inner() {
+ return this.shadowRoot.querySelector("[part=inner]");
+ }
+ },
+ );
+
+ test((t) => {
+ t.add_cleanup(() => {
+ subject.inner.removeAttribute("lang");
+ });
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, AQUA);
+ subject.inner.lang = "en-GB";
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, GREEN);
+ subject.inner.lang = "fr";
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, BLUE);
+ subject.inner.lang = "en";
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, AQUA);
+ }, "::part():lang() invalidation");
+
+ test((t) => {
+ t.add_cleanup(() => {
+ subject.inner.removeAttribute("lang");
+ });
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, AQUA);
+ subject.inner.setAttribute("lang", "en-GB");
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, GREEN);
+ subject.inner.setAttribute("lang", "en");
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, AQUA);
+ subject.inner.setAttribute("lang", "fr");
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, BLUE);
+ subject.inner.removeAttribute("lang");
+ assert_equals(getComputedStyle(subject.inner).backgroundColor, AQUA);
+ }, "::part():lang() invalidation from setAttribute");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/part-pseudo-ref.html b/testing/web-platform/tests/css/selectors/invalidation/part-pseudo-ref.html
new file mode 100644
index 0000000000..aeb724778a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/part-pseudo-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test Reference</title>
+ <style id="sheet">div { color: green; }</style>
+</head>
+<body>
+ <div>
+ <div>
+ <div>Should be green</div>
+ </div>
+ </div>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/part-pseudo.html b/testing/web-platform/tests/css/selectors/invalidation/part-pseudo.html
new file mode 100644
index 0000000000..eee8bf5522
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/part-pseudo.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>CSS Selectors Invalidation: ::part()</title>
+ <link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+ <link rel="help" href="https://drafts.csswg.org/css-shadow-parts/">
+ <link rel="match" href="part-pseudo-ref.html">
+ <style id="sheet">#host::part(green) { color: red; }</style>
+ </head>
+<body>
+ <div id="host">
+ <template shadowrootmode="open">
+ <div>
+ <div part="green">Should be green</div>
+ </div>
+ </template>
+ </div>
+ <script>
+ document.body.offsetTop;
+ sheet.innerText = "#host::part(green) { color: green; }";
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/placeholder-shown.html b/testing/web-platform/tests/css/selectors/invalidation/placeholder-shown.html
new file mode 100644
index 0000000000..71233ed2a2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/placeholder-shown.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>CSS Selectors Test: :placeholder-shown invalidation</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#placeholder">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #target { color: red; }
+ input:placeholder-shown + #target { color: green; }
+</style>
+<input id="input" type="text">
+<span id="target"></span>
+<script>
+ const red = "rgb(255, 0, 0)";
+ const green = "rgb(0, 128, 0)";
+
+ test(() => {
+ assert_equals(getComputedStyle(target).color, red);
+ }, "Initially no placeholder text");
+
+ test(() => {
+ input.setAttribute("placeholder", "PLACEHOLDER");
+ assert_equals(getComputedStyle(target).color, green);
+ }, "Added placeholder text");
+
+ test(() => {
+ input.setAttribute("placeholder", "");
+ assert_equals(getComputedStyle(target).color, green);
+ }, "Set placeholder text to empty string");
+
+ test(() => {
+ input.removeAttribute("placeholder");
+ assert_equals(getComputedStyle(target).color, red);
+ }, "Removed placeholder attribute");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/quirks-mode-stylesheet-dynamic-add-001.html b/testing/web-platform/tests/css/selectors/invalidation/quirks-mode-stylesheet-dynamic-add-001.html
new file mode 100644
index 0000000000..3d7be98237
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/quirks-mode-stylesheet-dynamic-add-001.html
@@ -0,0 +1,27 @@
+<!-- Quirks mode -->
+<meta charset="utf-8">
+<title>Invalidation of style due to a dynamic stylesheet change in quirks mode</title>
+<link rel="help" href="https://html.spec.whatwg.org/#case-sensitivity-of-selectors">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1433589">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #foo {
+ width: 100px;
+ height: 100px;
+ background: red;
+ }
+</style>
+Should see a green square below.
+<div id="foo"></div>
+<script>
+test(function() {
+ let foo = document.getElementById('foo');
+ assert_equals(getComputedStyle(foo).backgroundColor, "rgb(255, 0, 0)");
+ let style = document.createElement('style');
+ style.textContent = "#FoO { background: green; }";
+ document.body.appendChild(style);
+ assert_equals(getComputedStyle(foo).backgroundColor, "rgb(0, 128, 0)");
+}, "Style should've changed to a green background");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/selectorText-dynamic-001.html b/testing/web-platform/tests/css/selectors/invalidation/selectorText-dynamic-001.html
new file mode 100644
index 0000000000..ac33eca826
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/selectorText-dynamic-001.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: invalidation of class changes when the selector in a rule has changed</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#invalid">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432850">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ body { background: green; }
+ .red { background: red; }
+</style>
+<body class="red">
+Should have a green background.
+<script>
+test(() => {
+ document.body.offsetTop;
+ assert_equals(getComputedStyle(document.body).backgroundColor, "rgb(255, 0, 0)");
+ document.body.className = "";
+ document.styleSheets[0].cssRules[1].selectorText = ".bar";
+ assert_equals(getComputedStyle(document.body).backgroundColor, "rgb(0, 128, 0)");
+}, "Style should be recomputed correctly when the selector it depends on changes");
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-001.html b/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-001.html
new file mode 100644
index 0000000000..44e38ad81e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-001.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: invalidation of class changes when the sheet the style depends on goes away</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#invalid">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432850">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ body { background: green; }
+</style>
+<style id="style">
+ .red { background: red; }
+</style>
+<body class="red">
+Should have a green background.
+<script>
+test(() => {
+ document.body.offsetTop;
+ assert_equals(getComputedStyle(document.body).backgroundColor, "rgb(255, 0, 0)");
+ document.body.className = "";
+ style.remove();
+ assert_equals(getComputedStyle(document.body).backgroundColor, "rgb(0, 128, 0)");
+}, "Style should be recomputed correctly when the stylesheet it depends on goes away");
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002-ref.html b/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002-ref.html
new file mode 100644
index 0000000000..6784161773
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<p style="color: green">
+ Should be green.
+</p>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002.html b/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002.html
new file mode 100644
index 0000000000..189abbe080
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/sheet-going-away-002.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: invalidation of class changes when the sheet the style depends on goes away</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#invalid">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432850">
+<link rel="match" href="sheet-going-away-002-ref.html">
+<style>
+ p { color: green; }
+</style>
+<style id="style">
+ .red p { color: red; }
+</style>
+<body class="red">
+<p>
+ Should be green.
+</p>
+<script>
+document.body.offsetTop;
+document.body.className = "";
+style.remove();
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/sibling.html b/testing/web-platform/tests/css/selectors/invalidation/sibling.html
new file mode 100644
index 0000000000..c0e04fb8b3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/sibling.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: sibling</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#adjacent-sibling-combinators">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#general-sibling-combinators">
+ <meta name="assert" content="This tests that the + next-sibling selector is effective">
+ <meta name="assert" content="This tests that the ~ subsequent-sibling selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+
+* { background-color: inherit; }
+
+body { background-color: rgba(0, 0, 0, 0); }
+
+.t1 .sibling + *,
+.t2 .sibling ~ *,
+.t3 + .sibling + *,
+.t4 + .sibling,
+.t5 + *,
+.t6 ~ .sibling,
+.t7 + * + * .child { background-color: rgb(0, 128, 0); }
+
+ </style>
+ </head>
+ <body>
+
+<div>
+ <div id="t1">
+ <div class="sibling"></div>
+ <div id="r1"></div>
+ <div id="u1"></div>
+ </div>
+</div>
+<div>
+ <div id="t2">
+ <div class="sibling"></div>
+ <div></div>
+ <div id="r2"></div>
+ </div>
+</div>
+<div>
+ <div id="t3"></div>
+ <div class="sibling"></div>
+ <div id="r3"></div>
+</div>
+<div>
+ <div id="t4"></div>
+ <div id="r4" class="sibling"></div>
+ <div id="u4" class="sibling"></div>
+</div>
+<div>
+ <div id="t5"></div>
+ <div id="r5"></div>
+ <div id="u5"></div>
+</div>
+<div>
+ <div id="t6"></div>
+ <div></div>
+ <div id="r6" class="sibling">
+ <div id="r6b"></div>
+ </div>
+ <div id="u6"></div>
+</div>
+<div>
+ <div id="t7">
+ <div class="child"></div>
+ </div>
+ <div></div>
+ <div>
+ <div id="r7" class="child"></div>
+ </div>
+ <div>
+ <div id="u7" class="child"></div>
+ </div>
+</div>
+
+ <script>
+
+test(function() {
+ assert_equals(getComputedStyle(r1).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+
+ t1.className = "t1";
+ assert_equals(getComputedStyle(r1).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+ assert_equals(getComputedStyle(u1).backgroundColor, "rgba(0, 0, 0, 0)", "Background color remains transparent");
+}, "Adjacent with universal selector");
+
+test(function() {
+ assert_equals(getComputedStyle(r2).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+
+ t2.className = "t2";
+ assert_equals(getComputedStyle(r2).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+}, "Indirect adjacent with universal selector");
+
+test(function() {
+ assert_equals(getComputedStyle(r3).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+
+ t3.className = "t3";
+ assert_equals(getComputedStyle(r3).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+}, "Indirect adjacent with two adjacent selectors");
+
+test(function() {
+ assert_equals(getComputedStyle(r4).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+
+ t4.className = "t4";
+ assert_equals(getComputedStyle(r4).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+ assert_equals(getComputedStyle(u4).backgroundColor, "rgba(0, 0, 0, 0)", "Background color remains transparent");
+}, "Adjacent class");
+
+test(function() {
+ assert_equals(getComputedStyle(r5).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+
+ t5.className = "t5";
+ assert_equals(getComputedStyle(r5).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+ assert_equals(getComputedStyle(u5).backgroundColor, "rgba(0, 0, 0, 0)", "Background color remains transparent");
+}, "Adjacent universal");
+
+test(function() {
+ assert_equals(getComputedStyle(r6).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+ assert_equals(getComputedStyle(r6b).backgroundColor, "rgba(0, 0, 0, 0)", "Child's background color should initially be transparent");
+
+ t6.className = "t6";
+ assert_equals(getComputedStyle(r6).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+ assert_equals(getComputedStyle(r6b).backgroundColor, "rgb(0, 128, 0)", "Child's background color is green after class change");
+ assert_equals(getComputedStyle(u6).backgroundColor, "rgba(0, 0, 0, 0)", "Background color remains transparent");
+}, "Sibling subtree through an indirect adjacent combinator");
+
+test(function() {
+ assert_equals(getComputedStyle(r7).backgroundColor, "rgba(0, 0, 0, 0)", "Background color should initially be transparent");
+
+ t7.className = "t7";
+ assert_equals(getComputedStyle(r7).backgroundColor, "rgb(0, 128, 0)", "Background color is green after class change");
+ assert_equals(getComputedStyle(u7).backgroundColor, "rgba(0, 0, 0, 0)", "Background color remains transparent");
+}, "Sibling descendant through a universal selector");
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/state-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/state-in-has.html
new file mode 100644
index 0000000000..15dec18feb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/state-in-has.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<title>:has() invalidation with :state() pseudo-class</title>
+<link rel="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational" />
+<link rel="help" href="https://github.com/whatwg/html/pull/8467" />
+<style>
+ #subject {
+ background-color: #f00;
+ }
+ #subject:has(:state(--green)) {
+ background-color: #0f0;
+ }
+ #subject:has(:state(--blue)) {
+ background-color: #00f;
+ }
+</style>
+<body>
+ Test :state() pseudo-class invalidation with :has()
+ <div id="subject">
+ <my-element id="child"></my-element>
+ </div>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ const RED = "rgb(255, 0, 0)";
+ const GREEN = "rgb(0, 255, 0)";
+ const BLUE = "rgb(0, 0, 255)";
+
+ test(() => {
+ customElements.define(
+ "my-element",
+ class MyElement extends HTMLElement {
+ connectedCallback() {
+ this.elementInternals = this.attachInternals();
+ }
+ },
+ );
+ assert_equals(getComputedStyle(subject).backgroundColor, RED);
+ child.elementInternals.states.add("--green");
+ assert_equals(getComputedStyle(subject).backgroundColor, GREEN);
+ child.elementInternals.states.clear();
+ assert_equals(getComputedStyle(subject).backgroundColor, RED);
+
+ child.elementInternals.states.add("--blue");
+ assert_equals(getComputedStyle(subject).backgroundColor, BLUE);
+ child.elementInternals.states.clear();
+ assert_equals(getComputedStyle(subject).backgroundColor, RED);
+
+ child.elementInternals.states.add("--green");
+ child.elementInternals.states.add("--blue");
+ assert_equals(getComputedStyle(subject).backgroundColor, BLUE);
+ child.elementInternals.states.delete("--blue");
+ assert_equals(getComputedStyle(subject).backgroundColor, GREEN);
+ child.elementInternals.states.delete("--green");
+ assert_equals(getComputedStyle(subject).backgroundColor, RED);
+ }, "Test :has() invalidation with :state() pseudo-classes");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/subject-has-invalidation-with-display-none-anchor-element.html b/testing/web-platform/tests/css/selectors/invalidation/subject-has-invalidation-with-display-none-anchor-element.html
new file mode 100644
index 0000000000..6c87560c69
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/subject-has-invalidation-with-display-none-anchor-element.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: subject :has() invalidation with display: none anchor element</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #target:has(~ input:checked) { display: none; }
+</style>
+<p>Click checkbox</p>
+<div id="target">PASS</div>
+<input type="checkbox" id="checkme">
+<label for="checkme">Check me!</label>
+<script>
+ test(function() {
+ checkme.checked = false;
+ assert_equals(getComputedStyle(target).display, "block",
+ "target display should be empty");
+
+ checkme.checked = true;
+ assert_equals(getComputedStyle(target).display, "none",
+ "target display should be none");
+
+ checkme.checked = false;
+ assert_equals(getComputedStyle(target).display, "block",
+ "target display should be empty again");
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/target-pseudo-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/target-pseudo-in-has.html
new file mode 100644
index 0000000000..a0bcc39b7f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/target-pseudo-in-has.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: :target pseudo-class in :has() argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #parent1 { color: grey; }
+ #parent1:has(:target) { color: green; }
+
+ #parent2 { color: blue; }
+ #parent2:has(:not(:target)) { color: grey; }
+ #parent2:has(:target) { color: green; }
+
+ #parent3 { color: green; }
+ #parent3:not(:has(:target)) { color: grey; }
+</style>
+<a href="#fragment">link to #fragment</a>
+<a href="#fragment2">link to #fragment2</a>
+<a href="#fragment3">link to #fragment3</a>
+<a href="#">link to #</a>
+<div id="parent1">
+ 1:
+ <span id="fragment">Must be green when containing :target</span>
+</div>
+<div id="parent2">
+ 2:
+ <span id="fragment2">Must be green when containing :target</span>
+</div>
+<div id="parent3">
+ 3:
+ <span id="fragment3">Must be green when containing :target</span>
+</div>
+<script>
+ const GREEN = "rgb(0, 128, 0)";
+ const GREY = "rgb(128, 128, 128)";
+ const BLUE = "rgb(0, 0, 255)";
+
+ async function navigateFragment(fragment) {
+ return new Promise(resolve => {
+ let hashChanged = (e) => {
+ if (location.hash.substring(1) === fragment) {
+ resolve();
+ window.removeEventListener("hashchange", hashChanged);
+ }
+ };
+ window.addEventListener("hashchange", hashChanged);
+ fragmentLink(fragment).click();
+ });
+ }
+
+ function fragmentLink(fragment) {
+ return document.querySelector(`a[href="#${fragment}"]`);
+ }
+
+ promise_test(async () => {
+ const fragment = document.querySelector("#fragment");
+ const fragment2 = document.querySelector("#fragment2");
+ const fragment3 = document.querySelector("#fragment3");
+
+ location.hash = "";
+
+ assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target");
+ assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target");
+ assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target");
+
+ await navigateFragment("fragment");
+
+ assert_true(fragment.matches(":target"));
+ assert_equals(getComputedStyle(parent1).color, GREEN, "parent1 should be green on fragment click");
+ assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target");
+ assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target");
+
+ await navigateFragment("fragment2");
+
+ assert_true(fragment2.matches(":target"));
+ assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target");
+ assert_equals(getComputedStyle(parent2).color, GREEN, "parent2 should be green on fragment click");
+ assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target");
+
+ fragment2.remove();
+ assert_equals(getComputedStyle(parent2).color, BLUE, "parent2 should be blue after removing only child");
+
+ parent2.append(fragment2);
+
+ // Skip to check parent2 color since there is nothing in the spec mentioning DOM mutations affecting the target element.
+ // - https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-fragid
+
+ await navigateFragment("fragment3");
+
+ assert_true(fragment3.matches(":target"));
+ assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target");
+ assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target");
+ assert_equals(getComputedStyle(parent3).color, GREEN, "parent3 should be green on fragment click");
+
+ await navigateFragment("");
+
+ assert_equals(location.hash, "");
+ assert_equals(getComputedStyle(parent1).color, GREY, "parent1 should be grey without :target");
+ assert_equals(getComputedStyle(parent2).color, GREY, "parent2 should be grey without :target");
+ assert_equals(getComputedStyle(parent3).color, GREY, "parent3 should be grey without :target");
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/typed-child-indexed-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/typed-child-indexed-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..b3a91d67cb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/typed-child-indexed-pseudo-classes-in-has.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: typed child-indexed pseudo classes in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #container ~ div { color: grey }
+ #container:has(div:only-of-type) ~ #only_of_type { color: red }
+ #container:has(div.orange:first-of-type) ~ #first_of_type { color: orange }
+ #container:has(div.yellow:first-of-type) ~ #first_of_type { color: yellow }
+ #container:has(div.green:first-of-type) ~ #first_of_type { color: green }
+ #container:has(div.orange:last-of-type) ~ #last_of_type { color: orange }
+ #container:has(div.yellow:last-of-type) ~ #last_of_type { color: yellow }
+ #container:has(div.green:last-of-type) ~ #last_of_type { color: green }
+ #container:has(div.orange:nth-of-type(3n+1)) ~ #nth_of_type_3n_1 { color: orange }
+ #container:has(div.yellow:nth-of-type(3n+1)) ~ #nth_of_type_3n_1 { color: yellow }
+ #container:has(div.green:nth-of-type(3n+1)) ~ #nth_of_type_3n_1 { color: green }
+ #container:has(div.orange:nth-of-type(3n+2)) ~ #nth_of_type_3n_2 { color: orange }
+ #container:has(div.yellow:nth-of-type(3n+2)) ~ #nth_of_type_3n_2 { color: yellow }
+ #container:has(div.green:nth-of-type(3n+2)) ~ #nth_of_type_3n_2 { color: green }
+ #container:has(div.orange:nth-of-type(3n)) ~ #nth_of_type_3n { color: orange }
+ #container:has(div.yellow:nth-of-type(3n)) ~ #nth_of_type_3n { color: yellow }
+ #container:has(div.green:nth-of-type(3n)) ~ #nth_of_type_3n { color: green }
+</style>
+<div id="container">
+</div>
+<div id="only_of_type"></div>
+<div id="first_of_type"></div>
+<div id="last_of_type"></div>
+<div id="nth_of_type_3n_1"></div>
+<div id="nth_of_type_3n_2"></div>
+<div id="nth_of_type_3n"></div>
+<script>
+const grey = "rgb(128, 128, 128)";
+const red = "rgb(255, 0, 0)";
+const orange = "rgb(255, 165, 0)";
+const yellow = "rgb(255, 255, 0)";
+const green = "rgb(0, 128, 0)";
+
+function testColors(test_name,
+ only_of_type_color,
+ first_of_type_color,
+ last_of_type_color,
+ nth_of_type_3n_1_color,
+ nth_of_type_3n_2_color,
+ nth_of_type_3n_color) {
+ test(function() {
+ assert_equals(getComputedStyle(only_of_type).color, only_of_type_color);
+ }, test_name + ": #only_of_type");
+ test(function() {
+ assert_equals(getComputedStyle(first_of_type).color, first_of_type_color);
+ }, test_name + ": #first_of_type");
+ test(function() {
+ assert_equals(getComputedStyle(last_of_type).color, last_of_type_color);
+ }, test_name + ": #last_of_type");
+ test(function() {
+ assert_equals(getComputedStyle(nth_of_type_3n_1).color, nth_of_type_3n_1_color);
+ }, test_name + ": #nth_of_type_3n_1");
+ test(function() {
+ assert_equals(getComputedStyle(nth_of_type_3n_2).color, nth_of_type_3n_2_color);
+ }, test_name + ": #nth_of_type_3n_2");
+ test(function() {
+ assert_equals(getComputedStyle(nth_of_type_3n).color, nth_of_type_3n_color);
+ }, test_name + ": #nth_of_type_3n");
+}
+
+testColors("Initial colors", grey, grey, grey, grey, grey, grey);
+
+container.insertBefore(document.createElement("span"), container.firstChild);
+testColors("Prepend span (1)", grey, grey, grey, grey, grey, grey);
+
+let div1 = document.createElement("div");
+div1.id = "div1";
+div1.classList.add("green");
+container.insertBefore(div1, container.firstChild);
+testColors("Prepend #div1.green", red, green, green, green, grey, grey);
+
+container.insertBefore(document.createElement("span"), container.firstChild);
+testColors("Prepend span (2)", red, green, green, green, grey, grey);
+
+let div2 = document.createElement("div");
+div2.id = "div2";
+div2.classList.add("yellow");
+container.insertBefore(div2, container.firstChild);
+testColors("Prepend #div2.yellow", grey, yellow, green, yellow, green, grey);
+
+container.insertBefore(document.createElement("span"), container.firstChild);
+testColors("Prepend span (3)", grey, yellow, green, yellow, green, grey);
+
+let div3 = document.createElement("div");
+div3.id = "div3";
+div3.classList.add("orange");
+container.insertBefore(div3, container.firstChild);
+testColors("Prepend #div3.orange", grey, orange, green, orange, yellow, green);
+
+container.insertBefore(document.createElement("span"), container.firstChild);
+testColors("Prepend span (4)", grey, orange, green, orange, yellow, green);
+
+let div4 = document.createElement("div");
+div4.id = "div4";
+container.insertBefore(div4, container.firstChild);
+testColors("Prepend #div4", grey, grey, green, green, orange, yellow);
+
+container.insertBefore(document.createElement("span"), container.firstChild);
+testColors("Prepend span (5)", grey, grey, green, green, orange, yellow);
+
+let div5 = document.createElement("div");
+div5.id = "div5";
+container.insertBefore(div5, container.firstChild);
+testColors("Prepend #div5", grey, grey, green, yellow, green, orange);
+
+container.insertBefore(document.createElement("span"), container.firstChild);
+testColors("Prepend span (6)", grey, grey, green, yellow, green, orange);
+
+div1.remove();
+testColors("Remove #div1", grey, grey, yellow, yellow, grey, orange);
+
+div2.remove();
+testColors("Remove #div2", grey, grey, orange, grey, grey, orange);
+
+div3.remove();
+testColors("Remove #div3", grey, grey, grey, grey, grey, grey);
+
+div4.remove();
+testColors("Remove #div4", red, grey, grey, grey, grey, grey);
+
+div5.remove();
+testColors("Remove #div5", grey, grey, grey, grey, grey, grey);
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/invalidation/user-action-pseudo-classes-in-has.html b/testing/web-platform/tests/css/selectors/invalidation/user-action-pseudo-classes-in-has.html
new file mode 100644
index 0000000000..01b3df961a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/user-action-pseudo-classes-in-has.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Selectors Invalidation: user-action pseudo classes in :has() argument</title>
+<link rel="author" title="Byungwoo Lee" href="blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ .ancestor:has(.descendant1:hover) { color: blue }
+ .ancestor:has(.descendant1:hover) .other-descendant { color: navy }
+ .ancestor:has(.descendant1:hover:active) { color: skyblue }
+ .ancestor:has(.descendant1:hover:active) .other-descendant { color: lightblue }
+ .ancestor:has(:focus) { color: green }
+ .ancestor:has(:focus) .other-descendant { color: darkgreen }
+ .ancestor:has(.descendant2:focus-visible) { color: yellowgreen }
+ .ancestor:has(.descendant2:focus-visible) .other-descendant { color: greenyellow }
+ .ancestor:has(.descendant3:focus-within) { color: lightgreen }
+ .ancestor:has(.descendant3:focus-within) .other-descendant { color: violet }
+</style>
+<div id=subject1 class=ancestor>
+ <div>
+ <div id=unhoverme>No :hover</div>
+ <div id=hoverme class=descendant1>Hover and click me</div>
+ <div id=focusme1 tabindex=1>Focus me</div>
+ <div id=focusme2 class=descendant2 tabindex=2>Focus me</div>
+ <div class=descendant3>
+ <div><div id=focusme3 tabindex=3>Focus me</div></div>
+ </div>
+ </div>
+ <div><div id=subject3 class=other-descendant>subject</div></div>
+</div>
+<div id=subject2 class=ancestor>
+ <div id=focusme4 tabindex=4>Focus me</div>
+ <div><div id=subject4 class=other-descendant>subject</div></div>
+</div>
+<script>
+ const tab_key = '\ue004';
+
+ promise_test(async () => {
+ assert_equals(getComputedStyle(subject1).color, "rgb(0, 0, 0)", "subject1 initially black");
+ assert_equals(getComputedStyle(subject2).color, "rgb(0, 0, 0)", "subject3 initially black");
+
+ await new test_driver
+ .Actions()
+ .pointerMove(0, 0, {origin: hoverme})
+ .send();
+ assert_equals(getComputedStyle(subject1).color, "rgb(0, 0, 255)",
+ "subject1 should be blue");
+ assert_equals(getComputedStyle(subject3).color, "rgb(0, 0, 128)",
+ "subject3 should be navy");
+
+ await new test_driver
+ .Actions()
+ .pointerMove(0, 0, {origin: unhoverme})
+ .send();
+ assert_equals(getComputedStyle(subject1).color, "rgb(0, 0, 0)",
+ "subject1 should be back to black");
+ assert_equals(getComputedStyle(subject3).color, "rgb(0, 0, 0)",
+ "subject3 should be back to black");
+
+ await new test_driver
+ .Actions()
+ .pointerMove(0, 0, {origin: hoverme})
+ .pointerDown()
+ .send();
+ assert_equals(getComputedStyle(subject1).color, "rgb(135, 206, 235)",
+ "subject1 should be skyblue");
+ assert_equals(getComputedStyle(subject3).color, "rgb(173, 216, 230)",
+ "subject3 should be lightblue");
+
+ // Clean up `pointerDown` from above. We want to test invalidation from
+ // `:hover:active` to `:hover`, but there's no guarantee that pointer
+ // state will stay the same between actions.
+ await new test_driver
+ .Actions()
+ .pointerUp()
+ .pointerMove(0, 0, {origin: unhoverme})
+ .send();
+
+ // Perform the entire activation chain again, then perform `pointerUp`.
+ await new test_driver
+ .Actions()
+ .pointerMove(0, 0, {origin: hoverme})
+ .pointerDown()
+ .pointerUp()
+ .send();
+ assert_equals(getComputedStyle(subject1).color, "rgb(0, 0, 255)",
+ "subject1 should be blue");
+ assert_equals(getComputedStyle(subject3).color, "rgb(0, 0, 128)",
+ "subject3 should be navy");
+
+ await new test_driver
+ .Actions()
+ .pointerMove(0, 0, {origin: focusme1})
+ .pointerDown()
+ .pointerUp()
+ .send();
+ assert_equals(getComputedStyle(subject1).color, "rgb(0, 128, 0)",
+ "subject1 should be green");
+ assert_equals(getComputedStyle(subject3).color, "rgb(0, 100, 0)",
+ "subject3 should be darkgreen");
+
+ await test_driver.send_keys(document.body, tab_key);
+ assert_equals(getComputedStyle(subject1).color, "rgb(154, 205, 50)",
+ "subject1 should be yellowgreen");
+ assert_equals(getComputedStyle(subject3).color, "rgb(173, 255, 47)",
+ "subject3 should be greenyellow");
+
+ await test_driver.send_keys(document.body, tab_key);
+ assert_equals(getComputedStyle(subject1).color, "rgb(144, 238, 144)",
+ "subject1 should be lightgreen");
+ assert_equals(getComputedStyle(subject3).color, "rgb(238, 130, 238)",
+ "subject3 should be violet");
+
+ focusme3.remove();
+ assert_equals(getComputedStyle(subject1).color, "rgb(0, 0, 0)",
+ "subject1 should be black");
+ assert_equals(getComputedStyle(subject3).color, "rgb(0, 0, 0)",
+ "subject3 should be black");
+
+ await test_driver.send_keys(document.body, tab_key);
+ assert_equals(getComputedStyle(subject2).color, "rgb(0, 128, 0)",
+ "subject2 should be green");
+ assert_equals(getComputedStyle(subject4).color, "rgb(0, 100, 0)",
+ "subject4 should be darkgreen");
+
+ focusme4.remove();
+ assert_equals(getComputedStyle(subject2).color, "rgb(0, 0, 0)",
+ "subject2 should be black");
+ assert_equals(getComputedStyle(subject4).color, "rgb(0, 0, 0)",
+ "subject4 should be black");
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/user-valid-user-invalid.html b/testing/web-platform/tests/css/selectors/invalidation/user-valid-user-invalid.html
new file mode 100644
index 0000000000..bca20fc99c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/user-valid-user-invalid.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1477396">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1477392">
+<link rel=help href="https://drafts.csswg.org/selectors/#user-pseudos">
+<link rel=help href="https://html.spec.whatwg.org/#selector-user-valid">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<form>
+ <input type=email>
+ <input type=submit>
+</form>
+
+<style>
+input:user-valid {
+ color: rgb(0, 255, 0);
+}
+input:user-invalid {
+ background-color: rgb(255, 0, 0);
+}
+</style>
+
+<script>
+const green = 'rgb(0, 255, 0)';
+const red = 'rgb(255, 0, 0)';
+
+promise_test(async () => {
+ const emailInput = document.querySelector('input[type=email]');
+ assert_not_equals(getComputedStyle(emailInput).color, green,
+ 'Input should not initially match :user-valid.');
+ assert_not_equals(getComputedStyle(emailInput).backgroundColor, red,
+ 'Input should not initially match :user-invalid.');
+
+ emailInput.focus();
+ await test_driver.send_keys(emailInput, 'user');
+ assert_not_equals(getComputedStyle(emailInput).color, green,
+ ':user-valid should not match until after blurring.');
+ assert_not_equals(getComputedStyle(emailInput).backgroundColor, red,
+ ':user-invalid should not match until after blurring.');
+
+ emailInput.blur();
+ assert_not_equals(getComputedStyle(emailInput).color, green,
+ 'Invalid input should not match :user-valid.');
+ assert_equals(getComputedStyle(emailInput).backgroundColor, red,
+ 'Invalid input should match :user-invalid.');
+
+ emailInput.focus();
+ await test_driver.send_keys(emailInput, '@example.com');
+ assert_equals(getComputedStyle(emailInput).color, green,
+ 'Valid input should match :user-valid.');
+ assert_not_equals(getComputedStyle(emailInput).backgroundColor, red,
+ 'Valid input should not match :user-invalid.');
+}, ':user-valid and :user-invalid should invalidate after user input.');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/invalidation/where.html b/testing/web-platform/tests/css/selectors/invalidation/where.html
new file mode 100644
index 0000000000..170398300f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/invalidation/where.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: :where()</title>
+ <link rel="author" title="Victoria Su" href="mailto:victoriaytsu@google.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#zero-matches">
+ <meta name="assert" content="This tests that the :where() selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ * {
+ color: black;
+ }
+ .b {
+ color: yellow;
+ }
+ /*Simple selector arguments */
+ :where(.b, .c) {
+ color: red;
+ }
+ /*Compound selector arguments */
+ .a~:where(.c#d, .e) {
+ color: green;
+ }
+ /* Complex selector arguments */
+ .h {
+ color: red;
+ }
+ :where(.a~.h, .a~.h+.f) {
+ color: yellow;
+ }
+ /* Nested */
+ :where(.a>:where(.g+.h, .b)~.i) {
+ color: blue;
+ }
+ :where(:is(.a~.h)) {
+ color: yellow;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="a1">
+ <div class="g">
+ </div>
+ <div class="h">
+ </div>
+ <div class="i" id="i1">
+ Blue
+ </div>
+ </div>
+ <div class="b" id="b1">
+ Yellow
+ </div>
+ <div class="c" id="c1">
+ Red
+ </div>
+ <div class="c" id="d">
+ Green
+ </div>
+ <div class="h" id="h1">
+ Red
+ </div>
+ <div class="f" id="f1">
+ Yellow
+ </div>
+ <script>
+ document.body.offsetTop;
+
+ var black = "rgb(0, 0, 0)";
+ var green = "rgb(0, 128, 0)";
+ var red = "rgb(255, 0, 0)";
+ var yellow = "rgb(255, 255, 0)";
+ var blue = "rgb(0, 0, 255)";
+
+ test(() => {
+ assert_equals(getComputedStyle(b1).color, yellow);
+ assert_equals(getComputedStyle(c1).color, red);
+ assert_equals(getComputedStyle(d).color, red);
+ assert_equals(getComputedStyle(h1).color, red);
+ assert_equals(getComputedStyle(f1).color, black);
+ assert_equals(getComputedStyle(i1).color, black);
+ }, "Preconditions.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(b1).color, yellow);
+ assert_equals(getComputedStyle(c1).color, red);
+ }, "Invalidate :where() for simple selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(d).color, green);
+ }, "Invalidate :where() for compound selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(h1).color, red);
+ assert_equals(getComputedStyle(f1).color, yellow);
+ }, "Invalidate :where() for complex selector arguments.");
+
+ test(() => {
+ a1.className = "a";
+ assert_equals(getComputedStyle(i1).color, blue);
+ }, "Invalidate nested :where().");
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/is-default-ns-001.html b/testing/web-platform/tests/css/selectors/is-default-ns-001.html
new file mode 100644
index 0000000000..1c9a5a29e5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-default-ns-001.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Default namespace gets ignored inside non-type selectors for :is() / :not() / :where().</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<!--
+ Default namespace declarations do not affect the compound selector
+ representing the subject of any selector within a :is() pseudo-class, unless
+ that compound selector contains an explicit universal selector or type
+ selector.
+-->
+<link rel="match" href="/css/reference/blank.html">
+<style>
+@namespace url("http://www.w3.org/2000/svg");
+
+/* Type selector, so ns should apply and this should not match */
+*|*:is(div) {
+ width: 100px;
+ height: 100px;
+ background: red;
+}
+</style>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/is-default-ns-002.html b/testing/web-platform/tests/css/selectors/is-default-ns-002.html
new file mode 100644
index 0000000000..b86337f167
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-default-ns-002.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>Default namespace gets ignored inside non-type selectors for :is() / :not() / :where().</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<!--
+ Default namespace declarations do not affect the compound selector
+ representing the subject of any selector within a :is() pseudo-class, unless
+ that compound selector contains an explicit universal selector or type
+ selector.
+-->
+<link rel="match" href="/css/reference/blank.html">
+<style>
+@namespace url("http://www.w3.org/2000/svg");
+
+/* No type selector, so selector should match and hide the <input> */
+*|*:is(:disabled) {
+ display: none;
+}
+</style>
+<input disabled>
diff --git a/testing/web-platform/tests/css/selectors/is-default-ns-003.html b/testing/web-platform/tests/css/selectors/is-default-ns-003.html
new file mode 100644
index 0000000000..410d1221ec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-default-ns-003.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Default namespace respected inside :is() for non-subject compounds</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="match" href="/css/reference/blank.html">
+<!--
+ Default namespace declarations do not affect the compound selector
+ representing the *subject* of any selector within a :is() pseudo-class, unless
+ that compound selector contains an explicit universal selector or type
+ selector.
+-->
+<style>
+@namespace "http://www.w3.org/1999/xhtml";
+
+*|*.a {
+ display:none;
+}
+
+/* This should not apply, since the '.container' compound is affected by the
+ default namespace (even though the '.a' compound is not). */
+*|*:is(.container .a) {
+ display:initial;
+}
+
+</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
+ <g class=container>
+ <text class="a" y="1em">FAIL if this text is visible</text>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/css/selectors/is-nested.html b/testing/web-platform/tests/css/selectors/is-nested.html
new file mode 100644
index 0000000000..0658f9030d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-nested.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors: :is()</title>
+ <link rel="author" title="Victoria Su" href="mailto:victoriaytsu@google.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+ <meta name="assert" content="This tests that the :is() selector is effective when nested">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ /* Testing that highest specificity is chosen for class outside of :is() */
+ .a+.b+.c>.e+.d {
+ color: black;
+ font-size: 10px;
+ width: 10px;
+ }
+ .e:is(.b+.f, .e:is(*, .c>.e, .g, *))+.d {
+ color: red;
+ font-size: 20px;
+ }
+ .a+.b+.c>.e+.d {
+ color: yellow;
+ }
+ /* Testing specificty of a class within :is() */
+ .a+.c>.e {
+ color: black;
+ }
+ .e:is(.b+.f, :is(.c>.e, .g)) {
+ color: red;
+ }
+ .c>.e {
+ color: black;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="a">
+ </div>
+ <div class="b" id="b2">
+ </div>
+ <div class="c" id="c2">
+ <div class="e">
+ </div>
+ <div class="d" id="d1">
+ Yellow
+ </div>
+ </div>
+ <div class="a">
+ </div>
+ <div class="c" id="c2">
+ <div class="e" id="e1">
+ Red
+ </div>
+ </div>
+ <script>
+
+ var red = "rgb(255, 0, 0)";
+ var yellow = "rgb(255, 255, 0)";
+
+ test(() => {
+ assert_equals(getComputedStyle(d1).color, yellow);
+ assert_equals(getComputedStyle(d1).fontSize, "20px");
+ assert_equals(getComputedStyle(d1).width, "10px");
+ }, "Test nested :is() chooses highest specificity for class outside :is().");
+
+ test(() => {
+ assert_equals(getComputedStyle(e1).color, red);
+ }, "Test nested :is() specificity for class within arguments.");
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/is-specificity-shadow.html b/testing/web-platform/tests/css/selectors/is-specificity-shadow.html
new file mode 100644
index 0000000000..af039955eb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-specificity-shadow.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Specificity of :host() inside :is()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#host-selector">
+<style>
+ main :not(:is(:host(#a))) { color: green; }
+ main :not(:is(:host(.a))) { color: red; }
+</style>
+<main>
+ <div id=element>Green</div>
+</main>
+<script>
+ test(function() {
+ assert_equals(getComputedStyle(element).color, 'rgb(0, 128, 0)');
+ }, 'Specificity of :host() inside :is()');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/is-specificity.html b/testing/web-platform/tests/css/selectors/is-specificity.html
new file mode 100644
index 0000000000..541b0406d3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-specificity.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors: :is()</title>
+ <link rel="author" title="Victoria Su" href="mailto:victoriaytsu@google.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+ <meta name="assert" content="This tests that the :is() selector chooses the correct specificity">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ .b.c + .d + .q.r + .s + #target {
+ font-size: 10px;
+ height: 10px;
+ width: 10px;
+ }
+ :is(.a, .b.c + .d, .q) + :is(* + .p, .q.r + .s, * + .t) + #target {
+ height: 20px;
+ width: 20px;
+ }
+ .b.c + .d + .q.r + .s + #target {
+ width: 30px;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="b c"></div>
+ <div class="a d e"></div>
+ <div class="q r"></div>
+ <div class="p s t"></div>
+ <div id="target"></div>
+ <script>
+
+ test(() => {
+ assert_equals(getComputedStyle(target).width, "30px");
+ assert_equals(getComputedStyle(target).height, "20px");
+ assert_equals(getComputedStyle(target).fontSize, "10px");
+ }, "Test :is() uses highest possible specificity");
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/is-where-basic.html b/testing/web-platform/tests/css/selectors/is-where-basic.html
new file mode 100644
index 0000000000..8623c8b7d6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-basic.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>Basic :is/:where matching behavior</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+
+<main id=main>
+ <div id=a><div id=d></div></div>
+ <div id=b><div id=e></div></div>
+ <div id=c><div id=f></div></div>
+</main>
+
+<script>
+ function formatElements(elements) {
+ return elements.map(e => e.id).sort().join();
+ }
+
+ // Test that |selector| returns the given elements in #main.
+ function test_selector(selector, expected) {
+ test(function() {
+ let actual = Array.from(main.querySelectorAll(selector));
+ assert_equals(formatElements(actual), formatElements(expected));
+ }, `${selector} matches expected elements`);
+ }
+
+ test_selector(':is()', []);
+ test_selector(':is(#a)', [a]);
+ test_selector(':is(#a, #f)', [a, f]);
+ test_selector(':is(#a, #c) :where(#a #d, #c #f)', [d, f]);
+ test_selector('#c > :is(#c > #f)', [f]);
+ test_selector('#c > :is(#b > #f)', []);
+ test_selector('#a div:is(#d)', [d]);
+ test_selector(':is(div) > div', [d, e, f]);
+ test_selector(':is(*) > div', [a, b, c, d, e, f]);
+ test_selector(':is(*) div', [a, b, c, d, e, f]);
+ test_selector('div > :where(#e, #f)', [e, f]);
+ test_selector('div > :where(*)', [d, e, f]);
+ test_selector(':is(*) > :where(*)', [a, b, c, d, e, f]);
+ test_selector(':is(#a + #b) + :is(#c)', [c]);
+ test_selector(':is(#a, #b) + div', [b, c]);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/is-where-error-recovery.html b/testing/web-platform/tests/css/selectors/is-where-error-recovery.html
new file mode 100644
index 0000000000..f7e6f6ff6e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-error-recovery.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>CSS Selectors: :is() and :where() error recovery</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/3676">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#zero-matches">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#typedef-forgiving-selector-list">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style id="test-sheet">
+ random-selector { color: blue; }
+</style>
+<div id="test-div"></div>
+<script>
+ let rule = document.getElementById("test-sheet").sheet.cssRules[0];
+ test(function() {
+ for (let pseudo of ["is", "where"]) {
+ rule.selectorText = "random-selector";
+ let invalidSelector = `:${pseudo}(:total-nonsense)`;
+ rule.selectorText = invalidSelector;
+ assert_not_equals(
+ rule.selectorText,
+ "random-selector",
+ "Should've parsed",
+ );
+ assert_equals(
+ rule.selectorText,
+ invalidSelector,
+ "Should be parsed as-is (but not be considered valid)",
+ );
+ assert_equals(document.querySelector(rule.selectorText), null, "Should never match, but should parse");
+ for (let mixedList of [
+ `:${pseudo}(:total-nonsense, #test-div)`,
+ `:${pseudo}(:total-nonsense and-more-stuff, #test-div)`,
+ `:${pseudo}(weird-token || and-more-stuff, #test-div)`,
+ ]) {
+ rule.selectorText = mixedList;
+ assert_equals(
+ rule.selectorText,
+ mixedList,
+ `${mixedList}: Should parse invalid selectors`,
+ );
+ let testDiv = document.getElementById("test-div");
+ assert_equals(document.querySelector(mixedList), testDiv, "Should correctly match");
+ assert_equals(getComputedStyle(testDiv).color, "rgb(0, 0, 255)", "test element should be blue");
+ }
+ }
+ });
+</script>
diff --git a/testing/web-platform/tests/css/selectors/is-where-not.html b/testing/web-platform/tests/css/selectors/is-where-not.html
new file mode 100644
index 0000000000..f3d27db317
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-not.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>:is() inside :not()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="help" href="https://drafts.csswg.org/selectors/#negation">
+
+<main id=main>
+ <div id=a><div id=d></div></div>
+ <div id=b><div id=e></div></div>
+ <div id=c><div id=f></div></div>
+</main>
+
+<script>
+ function formatElements(elements) {
+ return elements.map(e => e.id).sort().join();
+ }
+
+ // Test that |selector| returns the given elements in #main.
+ function test_selector(selector, expected) {
+ test(function() {
+ let actual = Array.from(main.querySelectorAll(selector));
+ assert_equals(formatElements(actual), formatElements(expected));
+ }, `${selector} matches expected elements`);
+ }
+
+ test_selector(':not(:is(#a))', [b, c, d, e, f]);
+ test_selector(':not(:where(#b))', [a, c, d, e, f]);
+ test_selector(':not(:where(:root #c))', [a, b, d, e, f]);
+ test_selector(':not(:is(#a, #b))', [c, d, e, f]);
+ test_selector(':not(:is(#b div))', [a, b, c, d, f]);
+ test_selector(':not(:is(#a div, div + div))', [a, e, f]);
+ test_selector(':not(:is(span))', [a, b, c, d, e, f]);
+ test_selector(':not(:is(div))', []);
+ test_selector(':not(:is(*|div))', []);
+ test_selector(':not(:is(*|*))', []);
+ test_selector(':not(:is(*))', []);
+ test_selector(':not(:is(svg|div))', [a, b, c, d, e, f]);
+ test_selector(':not(:is(:not(div)))', [a, b, c, d, e, f]);
+ test_selector(':not(:is(span, b, i))', [a, b, c, d, e, f]);
+ test_selector(':not(:is(span, b, i, div))', []);
+ test_selector(':not(:is(#b ~ div div, * + #c))', [a, b, d, e]);
+ test_selector(':not(:is(div > :not(#e)))', [a, b, c, e]);
+ test_selector(':not(:is(div > :not(:where(#e, #f))))', [a, b, c, e, f]);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/is-where-pseudo-classes.html b/testing/web-platform/tests/css/selectors/is-where-pseudo-classes.html
new file mode 100644
index 0000000000..c3f1cfa818
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-pseudo-classes.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>:is() combined with pseudo-classes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="help" href="https://drafts.csswg.org/selectors/#useraction-pseudos">
+<style>
+ button {
+ color: black;
+ }
+ /* Selects #a, #c */
+ :is(main :where(main #a), #c:nth-child(odd), #d):is(:enabled) {
+ color: green;
+ }
+ /* Selects #b, #d, #f */
+ button:is(:nth-child(even), span #e):is(:enabled, :where(:disabled)) {
+ color: blue;
+ }
+</style>
+<main>
+ <button id=a>A</button>
+ <button id=b>B</button>
+ <button id=c>C</button>
+ <button id=d disabled>D</button>
+ <button id=e disabled>E</button>
+ <button id=f disabled>F</button>
+</main>
+<script>
+ test(function() {
+ assert_equals(getComputedStyle(a).color, 'rgb(0, 128, 0)');
+ assert_equals(getComputedStyle(b).color, 'rgb(0, 0, 255)');
+ assert_equals(getComputedStyle(c).color, 'rgb(0, 128, 0)');
+ assert_equals(getComputedStyle(d).color, 'rgb(0, 0, 255)');
+ assert_equals(getComputedStyle(e).color, 'rgb(0, 0, 0)');
+ assert_equals(getComputedStyle(f).color, 'rgb(0, 0, 255)');
+ }, ':is() combined with pseudo-classes');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/is-where-pseudo-elements-ref.html b/testing/web-platform/tests/css/selectors/is-where-pseudo-elements-ref.html
new file mode 100644
index 0000000000..3a17efedfb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-pseudo-elements-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>:is() combined with pseudo elements</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<style>
+ #b::before, #d::before {
+ content: "before ";
+ color: green;
+ }
+ #e::after, #h::after {
+ content: " after";
+ color: green;
+ }
+ #a::first-letter, #b::first-letter {
+ color: blue;
+ }
+ #g::first-line, #l::first-line {
+ color: magenta;
+ }
+</style>
+<main id=main>
+ <div id=a>a</div>
+ <div id=b>b</div>
+ <div id=c>c</div>
+ <div id=d>d</div>
+ <div id=e>e</div>
+ <div id=f>f</div>
+ <div id=g>g</div>
+ <div id=h>h</div>
+ <div id=j>j</div>
+ <div id=k>k</div>
+ <div id=l>l<br>l2</div>
+</main>
diff --git a/testing/web-platform/tests/css/selectors/is-where-pseudo-elements.html b/testing/web-platform/tests/css/selectors/is-where-pseudo-elements.html
new file mode 100644
index 0000000000..428b3b9a2d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-pseudo-elements.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>:is() combined with pseudo elements</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="match" href="is-where-pseudo-elements-ref.html">
+<style>
+ :is(#a, #c) + :is(main :is(#b, #d))::before {
+ content: "before ";
+ color: green;
+ }
+ :is(#d + div, #d ~ #h)::after {
+ content: " after";
+ color: green;
+ }
+ :is(main > #a, #b)::first-letter {
+ color: blue;
+ }
+ :is(:where(main > div + #g, #k + #l))::first-line {
+ color: magenta;
+ }
+</style>
+<main id=main>
+ <div id=a>a</div>
+ <div id=b>b</div>
+ <div id=c>c</div>
+ <div id=d>d</div>
+ <div id=e>e</div>
+ <div id=f>f</div>
+ <div id=g>g</div>
+ <div id=h>h</div>
+ <div id=j>j</div>
+ <div id=k>k</div>
+ <div id=l>l<br>l2</div>
+</main>
diff --git a/testing/web-platform/tests/css/selectors/is-where-shadow.html b/testing/web-platform/tests/css/selectors/is-where-shadow.html
new file mode 100644
index 0000000000..1b25bb63f1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-shadow.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<title>:is() inside shadow pseudos</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#host-selector">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#slotted-pseudo">
+<div class="parent1"><div id="host1" class=a><p class=e>::slotted</p></div></div>
+<div class="parent2"><div id="host2" class=b><p class=d>::slotted</p></div></div>
+<div class="parent3"><div id="host3" class=c><p class=f>::slotted</p></div></div>
+</div>
+<script>
+ let shadow1 = host1.attachShadow({ mode: 'open' });
+ let shadow2 = host2.attachShadow({ mode: 'open' });
+ let shadow3 = host3.attachShadow({ mode: 'open' });
+
+ const html = `
+ <style>
+ * { color: blue; }
+ :host(:is(.a, .b)) b { color: green; }
+ :host-context(:is(.parent1, .parent2)) i { color: green; }
+ ::slotted(:is(.e, .f)) { color: green; }
+
+ /* The following should not match: */
+ :host(:is(.z)) b { color: red; }
+ :host(:is(.a + .b)) b { color: red; }
+ :host-context(:is(.z)) i { color: red; }
+ :host-context(:is(.parent1 .parent2)) i { color: red; }
+ ::slotted(:is(.z)) { color: red; }
+ ::slotted(:is(.a > .b)) { color: red; }
+ </style>
+ <b>:host</b>
+ <i>:host-context</i>
+ <slot></slot>
+ `;
+
+ shadow1.innerHTML = html;
+ shadow2.innerHTML = html;
+ shadow3.innerHTML = html;
+
+ const getComputedColor = e => getComputedStyle(e).color;
+ const green = 'rgb(0, 128, 0)';
+ const blue = 'rgb(0, 0, 255)';
+
+ test(function() {
+ assert_equals(getComputedColor(shadow1.querySelector('b')), green);
+ assert_equals(getComputedColor(shadow2.querySelector('b')), green);
+ assert_equals(getComputedColor(shadow3.querySelector('b')), blue);
+ }, ':is() inside :host()');
+
+ test(function() {
+ assert_equals(getComputedColor(shadow1.querySelector('i')), green);
+ assert_equals(getComputedColor(shadow2.querySelector('i')), green);
+ assert_equals(getComputedColor(shadow3.querySelector('i')), blue);
+ }, ':is() inside :host-context()');
+
+ test(function() {
+ assert_equals(getComputedColor(document.querySelector('.e')), green);
+ assert_equals(getComputedColor(document.querySelector('.d')), blue);
+ assert_equals(getComputedColor(document.querySelector('.f')), green);
+ }, ':is() inside ::slotted()');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/is-where-visited-ref.html b/testing/web-platform/tests/css/selectors/is-where-visited-ref.html
new file mode 100644
index 0000000000..c8243ac731
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-visited-ref.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>:is/:where combined with :visited/:link</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<style>
+ :visited, :link {
+ color: black;
+ }
+
+ #parent1 .a, #parent1 .b, #parent1 .c {
+ color: green;
+ }
+ #parent1 .d, #parent1 .f {
+ color: magenta;
+ }
+
+ #parent2 .b, #parent2 .e {
+ color: tomato;
+ }
+
+ #parent3 .c, #parent3 .f {
+ color: skyblue;
+ }
+
+ #parent4 .c, #parent4 .f {
+ color: blue;
+ }
+
+ #parent3 .b, #parent3 .e, #parent4 .b, #parent4 .e {
+ color: maroon;
+ }
+</style>
+<main>
+ <div id=parent1>
+ <a class=a href="">a</a>
+ <a class=b href="">b</a>
+ <a class=c href="">c</a>
+ <a class=d href="unvisited">d</a>
+ <a class=e href="unvisited">e</a>
+ <a class=f href="unvisited">f</a>
+ </div>
+ <div id=parent2>
+ <a class=a href="">a</a>
+ <a class=b href="">b</a>
+ <a class=c href="">c</a>
+ <a class=d href="unvisited">d</a>
+ <a class=e href="unvisited">e</a>
+ <a class=f href="unvisited">f</a>
+ </div>
+ <a id=parent3 href="">
+ <span class=a>a</span>
+ <span class=b>b</span>
+ <span class=c>c</span>
+ <span class=d>d</span>
+ <span class=e>e</span>
+ <span class=f>f</span>
+ </a>
+ <br>
+ <a id=parent4 href="unvisited">
+ <span class=a>a</span>
+ <span class=b>b</span>
+ <span class=c>c</span>
+ <span class=d>d</span>
+ <span class=e>e</span>
+ <span class=f>f</span>
+ </a>
+</main>
diff --git a/testing/web-platform/tests/css/selectors/is-where-visited.html b/testing/web-platform/tests/css/selectors/is-where-visited.html
new file mode 100644
index 0000000000..5025b0a10a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/is-where-visited.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>:is/:where combined with :visited/:link</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="match" href="is-where-visited-ref.html">
+<style>
+ :visited, :link {
+ color: black;
+ }
+
+ #parent1 :is(:visited) {
+ color: green;
+ }
+ #parent1 :is(:link):nth-child(even) {
+ color: magenta;
+ }
+
+ :is(#parent2 .a + :visited, #parent2 .e:link) {
+ color: tomato;
+ }
+
+ main :is(a:visited > :where(.a + span + span, .f)) {
+ color: skyblue;
+ }
+
+ main :is(a:link > :where(.a + span + span, .f)) {
+ color: blue;
+ }
+
+ main :is(a:is(:link, :visited) > :where(.b, .e)) {
+ color: maroon;
+ }
+</style>
+<main>
+ <div id=parent1>
+ <a class=a href="">a</a>
+ <a class=b href="">b</a>
+ <a class=c href="">c</a>
+ <a class=d href="unvisited">d</a>
+ <a class=e href="unvisited">e</a>
+ <a class=f href="unvisited">f</a>
+ </div>
+ <div id=parent2>
+ <a class=a href="">a</a>
+ <a class=b href="">b</a>
+ <a class=c href="">c</a>
+ <a class=d href="unvisited">d</a>
+ <a class=e href="unvisited">e</a>
+ <a class=f href="unvisited">f</a>
+ </div>
+ <a id=parent3 href="">
+ <span class=a>a</span>
+ <span class=b>b</span>
+ <span class=c>c</span>
+ <span class=d>d</span>
+ <span class=e>e</span>
+ <span class=f>f</span>
+ </a>
+ <br>
+ <a id=parent4 href="unvisited">
+ <span class=a>a</span>
+ <span class=b>b</span>
+ <span class=c>c</span>
+ <span class=d>d</span>
+ <span class=e>e</span>
+ <span class=f>f</span>
+ </a>
+</main>
diff --git a/testing/web-platform/tests/css/selectors/last-child.html b/testing/web-platform/tests/css/selectors/last-child.html
new file mode 100644
index 0000000000..423ccf84f4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/last-child.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :last-child</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-last-child-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ See also:
+ * child-indexed-pseudo-class.html
+ * child-indexed-no-parent.html
+ * invalidation/first-child-last-child.html
+-->
+<body>
+
+<div>
+ <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+ <blockquote></blockquote>
+ <div id="target2">There is a prior child element.</div>
+</div>
+
+<div>
+ <div id="target3">A comment node should be ignored.</div>
+ <!-- -->
+</div>
+
+<div>
+ <div id="target4">Non-whitespace text node should be ignored.</div>
+ .
+</div>
+
+<div>
+ <div id="target5" data-expected="false">The first child should not be matched.</div>
+ <blockquote></blockquote>
+</div>
+
+<script>
+for (let i = 1; i <= 5; ++i) {
+ let target = document.querySelector(`#target${i}`);
+ test(() => {
+ if (target.dataset.expected == 'false')
+ assert_false(target.matches(':last-child'));
+ else
+ assert_true(target.matches(':last-child'));
+ }, target.textContent);
+}
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/last-of-type.html b/testing/web-platform/tests/css/selectors/last-of-type.html
new file mode 100644
index 0000000000..35328313e6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/last-of-type.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :last-of-type</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-last-of-type-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ See also:
+ * child-indexed-pseudo-class.html
+ * child-indexed-no-parent.html
+-->
+<body>
+
+<div>
+ <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+ <div></div>
+ <div id="target2">Thre is another child element of the same type.</div>
+</div>
+
+<div>
+ <div id="target3">There is a posterior child element of another type.</div>
+ <blockquote></blockquote>
+</div>
+
+<div>
+ <blockquote>
+ <div id="target4">A next element of the parent should not affect.</div>
+ </blockquote>
+ <div></div>
+</div>
+
+<div>
+ <div>
+ <div id="target5">The parent element of the same type should not affect.</div>
+ </div>
+</div>
+
+<div>
+ <div id="target6">A child of the next element should not affect.</div>
+ <blockquote>
+ <div></div>
+ </blockquote>
+</div>
+
+<div>
+ <div id="target7" data-expected="false">The first child element of the same
+type should not match.</div>
+ <div></div>
+</div>
+
+<div>
+ <div id="target8" data-expected="false">The first child element of the same
+type should not match, the last child has a case-different tag name.</div>
+ <DIV></DIV>
+</div>
+
+<div>
+ <div id="insertAfter1"></div>
+</div>
+
+<script>
+for (let i = 1; i <= 8; ++i) {
+ let target = document.querySelector(`#target${i}`);
+ test(() => {
+ if (target.dataset.expected == 'false')
+ assert_false(target.matches('div:last-of-type'));
+ else
+ assert_true(target.matches('div:last-of-type'));
+ }, target.textContent.replaceAll('\n', ' '));
+}
+
+test(() => {
+ const ia1 = document.querySelector('#insertAfter1');
+ const target = document.createElement('div');
+ assert_true(ia1.matches('div:last-of-type'));
+ ia1.parentNode.insertBefore(target, ia1.nextSibling);
+ assert_true(target.matches('div:last-of-type'));
+ assert_false(ia1.matches('div:last-of-type'));
+
+ target.remove();
+ assert_true(ia1.matches('div:last-of-type'));
+}, 'Dynamic insertion and removal');
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/media/media-loading-state.html b/testing/web-platform/tests/css/selectors/media/media-loading-state.html
new file mode 100644
index 0000000000..6bead20a98
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/media/media-loading-state.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long" />
+<title>Media Loading State: the :buffering and :stalled pseudo-classes</title>
+<link
+ rel="help"
+ href="https://drafts.csswg.org/selectors/#media-loading-state"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <video width="300" height="300" muted loop controls></video>
+ <script type="module">
+ test((t) => {
+ for (const pseudo of [":buffering", ":stalled"]) {
+ try {
+ document.querySelector(`.not-a-thing${pseudo}`);
+ } catch (e) {
+ assert_unreached(`${pseudo} is not supported`);
+ }
+ }
+ }, "Test :pseudo-class syntax is supported without throwing a SyntaxError");
+
+ promise_test(async (t) => {
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("stalled", r, { once: true });
+ video.src = `/media/counting.mp4?pipe=trickle(100:d1:r2)&random=${Math.random()}`;
+ });
+ const promise = video.play();
+ assert_equals(
+ document.querySelector("video:stalled"),
+ video,
+ "video is stalled"
+ );
+ video.src = "";
+ // Wait for the video to abort trying to play
+ try {
+ await promise;
+ } catch (err) {}
+ }, "Test :stalled pseudo-class");
+
+ promise_test(async (t) => {
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("stalled", r, { once: true });
+ video.src = `/media/counting.mp4?pipe=trickle(100:d1:r2)&random=${Math.random()}`;
+ });
+ video.currentTime = 10;
+ const promise = video.play();
+ assert_equals(
+ document.querySelector("video:buffering"),
+ video,
+ "video is buffering"
+ );
+ video.src = "";
+ // Wait for the video to abort trying to play
+ try {
+ await promise;
+ } catch (err) {}
+ }, "Test :buffering pseudo-class");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/media/media-playback-state.html b/testing/web-platform/tests/css/selectors/media/media-playback-state.html
new file mode 100644
index 0000000000..c034dbbdc0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/media/media-playback-state.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>
+ Media Playback State: the :playing, :paused, and :seeking pseudo-classes
+</title>
+<link
+ rel="help"
+ href="https://drafts.csswg.org/selectors/#video-state"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <video width="300" height="300" muted loop></video>
+ <script>
+ test((t) => {
+ for (const pseudo of [":playing", ":paused", ":seeking"]) {
+ try {
+ document.querySelector(`.not-a-thing${pseudo}`);
+ } catch (e) {
+ assert_unreached(`${pseudo} is not supported`);
+ }
+ }
+ }, "Test :pseudo-class syntax is supported without throwing a SyntaxError");
+
+ promise_test(async (t) => {
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+ video.muted = true; // allows us to play the video
+ assert_true(video.muted, "video is muted");
+ assert_true(video.paused, "video is paused");
+ await new Promise((r) => {
+ video.addEventListener("playing", r, { once: true });
+ video.play();
+ });
+ assert_false(video.paused, "video is playing");
+ assert_equals(document.querySelector("video:playing"), video);
+ assert_equals(document.querySelector("video:not(:playing)"), null);
+ assert_equals(document.querySelector("video:paused"), null);
+ assert_equals(document.querySelector("video:not(:paused)"), video);
+ }, "Test :playing pseudo-classes");
+
+ promise_test(async (t) => {
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+ assert_equals(video.paused, true);
+ assert_equals(document.querySelector("video:playing"), null);
+ assert_equals(document.querySelector("video:not(:playing)"), video);
+ assert_equals(document.querySelector("video:paused"), video);
+ assert_equals(document.querySelector("video:not(:paused)"), null);
+ }, "Test :paused pseudo-classes");
+
+ promise_test(async (t) => {
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+ assert_equals(document.querySelector("video:seeking"), null);
+ assert_equals(document.querySelector("video:not(:seeking)"), video);
+ await new Promise((r) => {
+ video.addEventListener("seeking", r, { once: true });
+ video.currentTime = 10;
+ });
+ assert_equals(document.querySelector("video:seeking"), video);
+ assert_equals(document.querySelector("video:not(:seeking)"), null);
+ }, "Test :seeking pseudo-class");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/media/sound-state.html b/testing/web-platform/tests/css/selectors/media/sound-state.html
new file mode 100644
index 0000000000..527bb30b97
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/media/sound-state.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>Sound State: the :muted and :volume-locked pseudo-classes</title>
+<link
+ rel="help"
+ href="https://drafts.csswg.org/selectors/#sound-state"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <video width="300" height="300" loop></video>
+ <script type="module">
+ // Unfortunately, we can't test the volume-locked state because it's not
+ // possible to lock the volume of a video element with JS.
+
+ test((t) => {
+ for (const pseudo of [":muted", ":volume-locked"]) {
+ try {
+ document.querySelector(`.not-a-thing${pseudo}`);
+ } catch (e) {
+ assert_unreached(`${pseudo} is not supported`);
+ }
+ }
+ }, "Test :pseudo-class syntax is supported without throwing a SyntaxError");
+
+ promise_test(async (t) => {
+ assert_equals(
+ document.querySelector("video:muted"),
+ null,
+ "must know :muted"
+ );
+ const video = document.querySelector("video");
+ await new Promise((r) => {
+ video.addEventListener("canplay", r, { once: true });
+ video.src = "/media/counting.mp4";
+ });
+ video.muted = false;
+ assert_false(video.muted, "video is unmuted");
+ assert_equals(document.querySelector("video:muted"), null);
+ assert_equals(document.querySelector("video:not(:muted)"), video);
+ video.muted = true;
+ assert_equals(document.querySelector("video:muted"), video);
+ assert_equals(document.querySelector("video:not(:muted)"), null);
+ }, "Test :muted pseudo-class");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/missing-right-token.html b/testing/web-platform/tests/css/selectors/missing-right-token.html
new file mode 100644
index 0000000000..8fe33a9579
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/missing-right-token.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta id="expected" charset="utf-8">
+ <title>Selectors: attribute selectors with missing right token</title>
+ <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#attribute-selectors">
+ <link rel="help" href="https://drafts.csswg.org/css-syntax/#rule-defs">
+ <meta name="assert" content="Checks attribute selectors with missing right token are matched.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+
+
+ <div id="container">
+ <span></span>
+ <span class="cls"></span>
+ </div>
+
+ <script>
+ test(() => {
+ assert_equals(document.querySelector('meta[charset="utf-8"'), expected);
+ assert_equals(document.querySelector('meta[charset="utf-8'), expected);
+
+ assert_equals(container.querySelectorAll('span:not([class]').length, 1);
+ assert_equals(container.querySelectorAll('span:not([class').length, 1);
+ }, "attribute selectors with missing right tokens succeed");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/modal-pseudo-class.html b/testing/web-platform/tests/css/selectors/modal-pseudo-class.html
new file mode 100644
index 0000000000..f11de65eff
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/modal-pseudo-class.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title>:modal pseudo-class</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="author" title="Jihwan Marc Kim" href="mailto:bluewhale.marc@gmail.com" />
+<link rel="help" href="https://drafts.csswg.org/selectors/#modal-state">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<dialog id="dialog">Just another dialog.</dialog>
+<div id="container">
+ <button id="btn"></button>
+</div>
+
+<script>
+ test(() => {
+ const dialog = document.getElementById("dialog");
+ assert_false(dialog.matches(":modal"), "dialog is initially closed (does not match :modal)");
+
+ dialog.showModal();
+ assert_true(dialog.matches(":modal"), "dialog should match :modal after showModal() call");
+
+ dialog.close();
+ assert_false(dialog.matches(":modal"), "dialog should no longer match :modal after close() call");
+
+ dialog.show();
+ assert_false(dialog.matches(":modal"), "dialog shouldn't match :modal after show() call");
+
+ dialog.close();
+ dialog.showModal();
+ assert_true(dialog.matches(":modal"), "dialog should match :modal after showModal() call");
+
+ dialog.remove();
+ assert_false(dialog.matches(":modal"), "dialog shouldn't match :modal after being removed from document");
+ document.body.append(dialog);
+ assert_false(dialog.matches(":modal"), "dialog shouldn't match :modal after being re-appended to document");
+
+ dialog.close();
+ }, "Test that :modal matches modal <dialog>");
+
+ promise_test(async () => {
+ const container = document.getElementById("container");
+ const btn = document.getElementById("btn");
+
+ assert_false(container.matches(":modal"), "before requestFullscreen (does not match :modal)");
+
+ await test_driver.click(btn);
+
+ await container.requestFullscreen();
+
+ assert_true(container.matches(":modal"), ":fullscreen should match :modal");
+
+ await document.exitFullscreen();
+
+ assert_false(container.matches(":modal"), "after exitFullscreen (does not match :modal)");
+ }, "Test that :modal matches the fullscreen element");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/not-complex.html b/testing/web-platform/tests/css/selectors/not-complex.html
new file mode 100644
index 0000000000..8e092a4ec6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-complex.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Matching behavior for :not with complex selector list</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#negation">
+
+<main id=main>
+ <div id=a><div id=d></div></div>
+ <div id=b><div id=e></div></div>
+ <div id=c><div id=f></div></div>
+</main>
+
+<script>
+ function formatElements(elements) {
+ return elements.map(e => e.id).sort().join();
+ }
+
+ // Test that |selector| returns the given elements in #main.
+ function test_selector(selector, expected) {
+ test(function() {
+ let actual = Array.from(main.querySelectorAll(selector));
+ assert_equals(formatElements(actual), formatElements(expected));
+ }, `${selector} matches expected elements`);
+ }
+
+ test_selector(':not(#a)', [b, c, d, e, f]);
+ test_selector(':not(#a #d)', [a, b, c, e, f]);
+ test_selector(':not(#b div)', [a, b, c, d, f]);
+ test_selector(':not(div div)', [a, b, c]);
+ test_selector(':not(div + div)', [a, d, e, f]);
+ test_selector(':not(main > div)', [d, e, f]);
+ test_selector(':not(#a, #b)', [c, d, e, f]);
+ test_selector(':not(#f, main > div)', [d, e]);
+ test_selector(':not(div + div + div, div + div > div)', [a, b, d]);
+ test_selector(':not(div:nth-child(1))', [b, c]);
+ test_selector(':not(:not(div))', [a, b, c, d, e, f]);
+ test_selector(':not(:not(:not(div)))', []);
+ test_selector(':not(div, span)', []);
+ test_selector(':not(span, p)', [a, b, c, d, e, f]);
+ test_selector(':not(#unknown, .unknown)', [a, b, c, d, e, f]);
+ test_selector(':not(#unknown > div, span)', [a, b, c, d, e, f]);
+ test_selector(':not(#unknown ~ div, span)', [a, b, c, d, e, f]);
+ test_selector(':not(:hover div)', [a, b, c, d, e, f]);
+ test_selector(':not(:link div)', [a, b, c, d, e, f]);
+ test_selector(':not(:visited div)', [a, b, c, d, e, f]);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/not-default-ns-001.html b/testing/web-platform/tests/css/selectors/not-default-ns-001.html
new file mode 100644
index 0000000000..ff8f540bc3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-default-ns-001.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<title>Default namespace gets ignored inside non-type selectors for :is() / :not() / :where().</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#negation">
+<!--
+ Default namespace declarations do not affect the compound selector
+ representing the subject of any selector within a :not() pseudo-class, unless
+ that compound selector contains an explicit universal selector or type
+ selector.
+-->
+<link rel="match" href="/css/reference/blank.html">
+<style>
+@namespace url("http://www.w3.org/2000/svg");
+
+*|div {
+ width: 100px;
+ height: 100px;
+ background: red;
+}
+
+/* Type selector, so ns should apply and this should match */
+*|*:not(div) {
+ display: none;
+}
+</style>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/not-default-ns-002.html b/testing/web-platform/tests/css/selectors/not-default-ns-002.html
new file mode 100644
index 0000000000..3d70ed0a87
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-default-ns-002.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>Default namespace gets ignored inside non-type selectors for :is() / :not() / :where().</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#negation">
+<!--
+ Default namespace declarations do not affect the compound selector
+ representing the subject of any selector within a :not() pseudo-class, unless
+ that compound selector contains an explicit universal selector or type
+ selector.
+-->
+<link rel="match" href="/css/reference/blank.html">
+<style>
+@namespace url("http://www.w3.org/2000/svg");
+
+*|input {
+ display: none;
+}
+
+/* No type selector, so selector should _not_ match and keep the input hidden */
+*|input:not(:disabled) {
+ display: initial;
+}
+</style>
+<input disabled>
diff --git a/testing/web-platform/tests/css/selectors/not-default-ns-003.html b/testing/web-platform/tests/css/selectors/not-default-ns-003.html
new file mode 100644
index 0000000000..f5aab27fab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-default-ns-003.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Default namespace respected inside :is() for non-subject compounds</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#negation">
+<link rel="match" href="/css/reference/blank.html">
+<!--
+ As with :is(), default namespace declarations do not affect the compound
+ selector representing the *subject* of any selector within a :not()
+ pseudo-class, unless that compound selector contains an explicit universal
+ selector or type selector.
+-->
+<style>
+@namespace "http://www.w3.org/1999/xhtml";
+
+*|*.a {
+ display:initial;
+}
+
+/* This should apply, since the '.container' compound is affected by the
+ default namespace (even though the '.a' compound is not). */
+*|g *|*:not(.container .a) {
+ display:none;
+}
+
+</style>
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
+ <g class=container>
+ <text class="a" y="1em">FAIL if this text is visible</text>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/css/selectors/not-links-ref.html b/testing/web-platform/tests/css/selectors/not-links-ref.html
new file mode 100644
index 0000000000..1b2515a5cd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-links-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Test that *:not(:link):not(:visited) does not match links</title>
+<style>
+ span {
+ background-color: green;
+ }
+</style>
+<body>
+ <div>
+ <a href="#">Unvisited (<span>Green</span>)</a>
+ <a href="#">Visited (<span>Green</span>)</a>
+ <span>Green</span>
+ </div>
+ <p>
+ Only "Green" should have green backgrounds.
+ </p>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/not-links.html b/testing/web-platform/tests/css/selectors/not-links.html
new file mode 100644
index 0000000000..58cef1a282
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-links.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Test that *:not(:link):not(:visited) does not match links</title>
+<link rel="match" href="not-links-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#negation">
+<style>
+ * {
+ /* Browsers typically ignore the :visited alpha and use the unvisited
+ alpha instead, which by default is 0, in which case a failure would
+ not be detected. */
+ background-color: white;
+ }
+ div *:not(:link):not(:visited) {
+ background-color: green;
+ }
+</style>
+<body>
+ <div>
+ <a href="#">Unvisited (<span>Green</span>)</a>
+ <a href="#">Visited (<span>Green</span>)</a>
+ <span>Green</span>
+ </div>
+ <p>
+ Only "Green" should have green backgrounds.
+ </p>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/not-specificity.html b/testing/web-platform/tests/css/selectors/not-specificity.html
new file mode 100644
index 0000000000..d9a2a4ddff
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/not-specificity.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Specificity for complex :not selectors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#negation">
+<style>
+ main :not(#foo) { --t0:PASS; }
+ main :not(.foo) { --t0:FAIL; }
+
+ main :not(div#foo) { --t1:PASS; }
+ main :not(#foo) { --t1:FAIL; }
+
+ main :not(.bar, #foo) { --t2:FAIL; }
+ main :not(#foo, .bar) { --t2:PASS; }
+
+ main :not(.bar, #foo) { --t3:PASS; }
+ main :not(.foo, .bar) { --t3:FAIL; }
+
+ main :not(span + span) { --t4:PASS; }
+ main :not(span) { --t4:FAIL; }
+
+ main :not(span, li, #foo) { --t5:PASS; }
+ main :not(span, li, p) { --t5:FAIL; }
+
+ main :not(span, :not(:not(.a#foo)), p) { --t6:PASS; }
+ main :not(span, #foo, p) { --t6:FAIL; }
+
+ main :not(span, #foo, p) { --t7:PASS; }
+ main :not(span, :where(.a#foo), p) { --t7:FAIL; }
+</style>
+<main id=main>
+ <div id=div></div>
+</main>
+<script>
+ function test_value(name, description) {
+ test(function() {
+ let actual = getComputedStyle(div).getPropertyValue(name);
+ assert_equals(actual, 'PASS');
+ }, description);
+ }
+
+ test_value('--t0', ':not(#foo) wins over :not(.foo)');
+ test_value('--t1', ':not(div#foo) wins over :not(#foo)');
+ test_value('--t2', ':not(.bar, #foo) has same specificity as :not(#foo, .bar)');
+ test_value('--t3', ':not(.bar, #foo) wins over :not(.foo, .bar)');
+ test_value('--t4', ':not(span + span) wins over :not(span)');
+ test_value('--t5', ':not(span, li, p) wins over :not(span, lo, p)');
+ test_value('--t6', ':not(span, :not(:not(.a#foo)), p) wins over :not(span, #foo, p)');
+ test_value('--t7', ':not(span, #foo, p) wins over :not(span, :where(.a#foo), p)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child-ref.html b/testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child-ref.html
new file mode 100644
index 0000000000..447426a3e3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child-ref.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+ target {
+ background-color: red;
+ }
+
+ #success1, #success2, #success3 {
+ background-color: green;
+ }
+</style>
+</head>
+<body>
+ <p>Test the matching of an element only if it is the only child matching the selector list. If the test succeed, every instance of the text "Success" should be on green background.</p>
+ <div>
+ <div></div>
+ <target>Foo</target>
+ <div></div>
+ <target>Bar</target>
+ <div></div>
+ </div>
+ <div>
+ <div></div>
+ <div></div>
+ <target id="success1">Success</target>
+ <div></div>
+ </div>
+ <div>
+ <div></div>
+ <target>Foo</target>
+ <div></div>
+ <target>Bar</target>
+ <div></div>
+ </div>
+ <div>
+ <div></div>
+ <div></div>
+ <target id="success2">Success</target>
+ <div></div>
+ </div>
+ <div>
+ <div></div>
+ <target>Foo</target>
+ <div></div>
+ <target>Bar</target>
+ <div></div>
+ </div>
+ <div>
+ <div></div>
+ <div></div>
+ <target id="success3">Success</target>
+ <div></div>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child.html b/testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child.html
new file mode 100644
index 0000000000..1379b4c706
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-and-nth-last-child.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>:nth-child and :nth-last-child with selector list argument chained together</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-and-nth-last-child-ref.html">
+<style>
+ target1 {
+ background-color: red;
+ }
+
+ :nth-child(1 of target1):nth-last-child(1 of target1) {
+ background-color: green;
+ }
+
+ .target {
+ background-color: red;
+ }
+
+ :nth-child(1 of .target):nth-last-child(1 of .target) {
+ background-color: green;
+ }
+
+ [data-target] {
+ background-color: red;
+ }
+
+ :nth-child(1 of [data-target]):nth-last-child(1 of [data-target]) {
+ background-color: green;
+ }
+</style>
+</head>
+<body>
+ <p>Test the matching of an element only if it is the only child matching the selector list. If the test succeed, every instance of the text "Success" should be on green background.</p>
+ <div>
+ <div></div>
+ <target1>Foo</target1>
+ <div></div>
+ <target1>Bar</target1>
+ <div></div>
+ </div>
+ <div>
+ <div></div>
+ <div></div>
+ <target1>Success</target1>
+ <div></div>
+ </div>
+ <div>
+ <div class="nottarget"></div>
+ <target class="target">Foo</target>
+ <div class="nottarget"></div>
+ <target class="target">Bar</target>
+ <div class="nottarget"></div>
+ </div>
+ <div>
+ <div class="nottarget"></div>
+ <div class="nottarget"></div>
+ <target class="target">Success</target>
+ <div class="nottarget"></div>
+ </div>
+ <div>
+ <div data-not-target></div>
+ <target data-target>Foo</target>
+ <div data-not-target></div>
+ <target data-target>Bar</target>
+ <div data-not-target></div>
+ </div>
+ <div>
+ <div data-not-target></div>
+ <div data-not-target></div>
+ <target data-target>Success</target>
+ <div data-not-target></div>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-attribute.html b/testing/web-platform/tests/css/selectors/nth-child-of-attribute.html
new file mode 100644
index 0000000000..0afd46893a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-attribute.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Chris Burdess" href="mailto:chris@bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 10px;
+ background-color: red;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference {
+ background-color: green;
+ }
+ div:nth-child(3n-1 of [align]) { /* selects 2,5,8 of divs that have an align attribute */
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="reference"></div>
+ <div class="reference" align="left"></div>
+ <div class="test" align="left"></div>
+ <div class="reference" align="left"></div>
+ <div class="reference" align="left"></div>
+ <div class="reference"></div>
+ <div class="test" align="left"></div>
+ <div class="reference" align="left"></div>
+ <div class="reference" align="left"></div>
+ <div class="test" align="left"></div>
+ </div>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-classname-002.html b/testing/web-platform/tests/css/selectors/nth-child-of-classname-002.html
new file mode 100644
index 0000000000..8aea79193c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-classname-002.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Chris Burdess" href="mailto:chris@bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 10px;
+ background-color: red;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference {
+ background-color: green;
+ }
+ div:nth-child(-n+3 of .test) { /* selects the first 3 with class test */
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-classname-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-classname-ref.html
new file mode 100644
index 0000000000..b424e73b45
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-classname-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p class="webkit">White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green!</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green!</p>
+ <p>White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-classname.html b/testing/web-platform/tests/css/selectors/nth-child-of-classname.html
new file mode 100644
index 0000000000..1cfb01056c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-classname.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with .className selector list argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-of-classname-ref.html">
+<style>
+p:nth-child(even of .webkit, .fast) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p class="webkit">White</p>
+ <p>White</p>
+ <p>White</p>
+ <p class="fast">Green!</p>
+ <p>White</p>
+ <p>White</p>
+ <p class="webkit">White</p>
+ <p>White</p>
+ <p class="webkit">Green!</p>
+ <p>White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2-ref.html
new file mode 100644
index 0000000000..60bf0446e6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>nth-child(...of S) with many children, where only some match</title>
+ </head>
+ <body>
+ <p>Test passes if there is no red.</p>
+ <div>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p>1</p>
+ <p>2</p>
+ <p></p>
+ <p></p>
+ <p>3</p>
+ <p>4</p>
+ <p></p>
+ <p></p>
+ <p>5</p>
+ <p></p>
+ <p></p>
+ <p>6</p>
+ <p></p>
+ <p>7</p>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p>8</p>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p>9</p>
+ <p>10</p>
+ <p></p>
+ <p></p>
+ <p>11</p>
+ <p>12</p>
+ <p></p>
+ <p></p>
+ <p>13</p>
+ <p>14</p>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2.html b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2.html
new file mode 100644
index 0000000000..1f4fcf2418
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-2.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>nth-child(...of S) with many children, where only some match</title>
+ <link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org" />
+ <link rel="help" href="https://crbug.com/1412421" />
+ <link rel="match" href="nth-child-of-complex-selector-many-children-2-ref.html" />
+ <style>
+ p:nth-child(16 of .c) { background-color: red; }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is no red.</p>
+ <div>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p class="c">1</p>
+ <p class="c">2</p>
+ <p></p>
+ <p></p>
+ <p class="c">3</p>
+ <p class="c">4</p>
+ <p></p>
+ <p></p>
+ <p class="c">5</p>
+ <p></p>
+ <p></p>
+ <p class="c">6</p>
+ <p></p>
+ <p class="c">7</p>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p class="c">8</p>
+ <p></p>
+ <p></p>
+ <p></p>
+ <p class="c">9</p>
+ <p class="c">10</p>
+ <p></p>
+ <p></p>
+ <p class="c">11</p>
+ <p class="c">12</p>
+ <p></p>
+ <p></p>
+ <p class="c">13</p>
+ <p class="c">14</p>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-ref.html
new file mode 100644
index 0000000000..031f3f1785
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children-ref.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children.html b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children.html
new file mode 100644
index 0000000000..ab958c9d88
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-many-children.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with complex selector list argument and more than 32 elements</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-of-complex-selector-many-children-ref.html">
+<style>
+/* At least 4 pair of <p> above, can be overlapping. The other selectors of the list are useless. */
+p:nth-child(4n of html:root>body>p+p:not(empty), :not(*), p:not(p), span, .notthere) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-ref.html
new file mode 100644
index 0000000000..ba38f685c6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector-ref.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector.html b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector.html
new file mode 100644
index 0000000000..f06680a57f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-complex-selector.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with complex selector list argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-of-complex-selector-ref.html">
+<style>
+/* At least 4 pair of <p> above, can be overlapping. The other selectors of the list are useless. */
+p:nth-child(4n of html:root>body>p+p:not(empty), :not(*), p:not(p), span, .notthere) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-compound-selector-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-compound-selector-ref.html
new file mode 100644
index 0000000000..3acec23e61
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-compound-selector-ref.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+<body>
+ <p></p>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p style="background-color: lime">Green</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-compound-selector.html b/testing/web-platform/tests/css/selectors/nth-child-of-compound-selector.html
new file mode 100644
index 0000000000..50bdba0b83
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-compound-selector.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with compound selector argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-of-compound-selector-ref.html">
+<style>
+/* 3n of paragraph with the class foobar but for which foobar is not the only class. */
+p:nth-child(3n+1 of p.foobar:not([class=foobar])) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p class="foobar foo"></p>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p class="foobar">White!</p>
+ <p class="foobar foo">White!</p>
+ <p>White!</p>
+ <p class="foo foobar">White!</p>
+ <p>White!</p>
+ <p class="foobar foo">Green</p>
+ <p class="foobar">White!</p>
+ <p class="foo foobar">White!</p>
+ <p class="foobar">White!</p>
+ <p class="foo foobar baz">White!</p>
+ <p>White!</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-has.html b/testing/web-platform/tests/css/selectors/nth-child-of-has.html
new file mode 100644
index 0000000000..efead020ab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-has.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Chris Burdess" href="mailto:chris@bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 10px;
+ background-color: red;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference {
+ background-color: green;
+ }
+ div:nth-child(even of :has(span)) {
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="reference"></div>
+ <div class="reference"><span></span></div>
+ <div class="reference"></div>
+ <div class="test"><span></span></div>
+ <div class="reference"></div>
+ <div class="reference"><span></span></div>
+ <div class="reference"></div>
+ <div class="test"><span></span></div>
+ <div class="reference"></div>
+ <div class="reference"><span></span></div>
+ </div>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-nesting-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-nesting-ref.html
new file mode 100644
index 0000000000..cdd66ed302
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-nesting-ref.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html>
+<body>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-nesting.html b/testing/web-platform/tests/css/selectors/nth-child-of-nesting.html
new file mode 100644
index 0000000000..78c5cde1cc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-nesting.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child nesting</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="match" href="nth-child-of-nesting-ref.html">
+<style>
+:nth-child(2n + 1 of :nth-child(n of .target)) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>White</p>
+ <p class="target">Green</p>
+ <p>White</p>
+ <p class="target">White</p>
+ <p>White</p>
+ <p class="target">Green</p>
+ <p>White</p>
+ <p class="target">White</p>
+ <p>White</p>
+ <p class="target">Green</p>
+ <p>White</p>
+ <p class="target">White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of-ref.html
new file mode 100644
index 0000000000..94dbc67a85
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of-ref.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<style>
+ div {
+ color: red;
+ }
+
+ .target {
+ color: green;
+ }
+</style>
+<p>Testing no space between "of" and the selector list. If the test succeeded, every instance of the text "Success" should be green.</p>
+<div></div>
+<div>Foo</div>
+<div></div>
+<div>Bar</div>
+<div></div>
+<div class=target>Success</div>
+<div></div>
+<div>Foo</div>
+<div></div>
+<div>Bar</div>
+<div></div>
+<div class=target>Success</div>
+<div></div>
+<div>Foo</div>
+<div></div>
+<div>Bar</div>
+<div></div>
+<div class=target>Success</div>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of.html b/testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of.html
new file mode 100644
index 0000000000..997b07c27d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-no-space-after-of.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>:nth-child with no space between "of" and the selector list</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="match" href="nth-child-of-no-space-after-of-ref.html">
+<style>
+ target {
+ color: red;
+ }
+
+ :nth-child(3 of/* my comment */target) {
+ color: green;
+ }
+
+ .target {
+ color: red;
+ }
+
+ :nth-child(3 of.target) {
+ color: green;
+ }
+
+ [target] {
+ color: red;
+ }
+
+ :nth-child(3 of[target]) {
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <p>Testing no space between "of" and the selector list. If the test succeeded, every instance of the text "Success" should be green.</p>
+ <div></div>
+ <target>Foo</target>
+ <div></div>
+ <target>Bar</target>
+ <div></div>
+ <target>Success</target>
+ <div></div>
+ <div class=target>Foo</div>
+ <div></div>
+ <div class=target>Bar</div>
+ <div></div>
+ <div class=target>Success</div>
+ <div></div>
+ <div target>Foo</div>
+ <div></div>
+ <div target>Bar</div>
+ <div></div>
+ <div target>Success</div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-not.html b/testing/web-platform/tests/css/selectors/nth-child-of-not.html
new file mode 100644
index 0000000000..863274fc8b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-not.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Chris Burdess" href="mailto:chris@bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 10px;
+ background-color: red;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference, .fallback {
+ background-color: green;
+ }
+ div:nth-child(even of :not(.reference)) { /* selects even divs with class test */
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="reference"></div>
+ <div class="test fallback"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="test fallback"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="test fallback"></div>
+ <div class="reference"></div>
+ </div>
+ </body>
+</html>
+
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-nth-child.html b/testing/web-platform/tests/css/selectors/nth-child-of-nth-child.html
new file mode 100644
index 0000000000..bb212a57f7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-nth-child.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Chris Burdess" href="mailto:chris@bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 10px;
+ background-color: red;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference {
+ background-color: green;
+ }
+ div:nth-child(even of :nth-child(even)) { /* selects every other of every other */
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="reference"></div>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-pseudo-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-pseudo-ref.html
new file mode 100644
index 0000000000..7e816b5f18
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-pseudo-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<div class="a">a</div>
+<div class="b">xb</div>
+<div class="a">a</div>
+<div class="b">b</div>
+<div class="a">a</div>
+<div class="b">xb</div>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-pseudo.html b/testing/web-platform/tests/css/selectors/nth-child-of-pseudo.html
new file mode 100644
index 0000000000..7113af9010
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-pseudo.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: :nth-child(of) with pseudo-elements</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1834717">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="nth-child-of-pseudo-ref.html">
+<style>
+div:nth-child(odd of .b)::before {
+ content: "x";
+}
+</style>
+<div class="a">a</div>
+<div class="b">b</div>
+<div class="a">a</div>
+<div class="b">b</div>
+<div class="a">a</div>
+<div class="b">b</div>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-tagname-ref.html b/testing/web-platform/tests/css/selectors/nth-child-of-tagname-ref.html
new file mode 100644
index 0000000000..99c8262b4f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-tagname-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+<body>
+ <webkit></webkit>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White!</p>
+ <p>White!</p>
+ <fast>White!</fast>
+ <p>White!</p>
+ <p>White!</p>
+ <webkit style="background-color: lime">Green</webkit>
+ <p>White!</p>
+ <webkit>White!</webkit>
+ <p>White!</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-tagname.html b/testing/web-platform/tests/css/selectors/nth-child-of-tagname.html
new file mode 100644
index 0000000000..cc92ad6df9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-tagname.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with tagname selector list argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-of-tagname-ref.html">
+<style>
+:nth-child(odd of webkit, fast) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <webkit></webkit>
+ <p>This test the styling of paragraphs with :nth-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White!</p>
+ <p>White!</p>
+ <fast>White!</fast>
+ <p>White!</p>
+ <p>White!</p>
+ <webkit>Green</webkit>
+ <p>White!</p>
+ <webkit>White!</webkit>
+ <p>White!</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-of-universal-selector.html b/testing/web-platform/tests/css/selectors/nth-child-of-universal-selector.html
new file mode 100644
index 0000000000..1f77cba0bc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-of-universal-selector.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Chris Burdess" href="mailto:chris@bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 10px;
+ background-color: red;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference {
+ background-color: green;
+ }
+ div:nth-child(even of *|*) { /* selects every other as S defaults to *|* */
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ <div class="reference"></div>
+ <div class="test"></div>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-1-ref.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-1-ref.html
new file mode 100644
index 0000000000..df70316c8d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-1-ref.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the specificity of :nth-child() with static specificity. The test passes if the text "target" is displayed white on green background. There should be 2 red rects on each side.</p>
+ <div>
+ <foo style="color: red; background-color: red;">Not target</foo>
+ <padding></padding>
+ <bar style="color: red; background-color: red;">Not target</bar>
+ <more-padding></more-padding>
+ <target style="color: white; background-color: green;">Target</target>
+ <more-padding></more-padding>
+ <foo style="color: red; background-color: red;">Not target</foo>
+ <padding></padding>
+ <bar style="color: red; background-color: red;">Not target</bar>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-1.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-1.html
new file mode 100644
index 0000000000..64d9eb27c0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-1.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-specificity-1-ref.html">
+<style>
+ /* The following 3 rules should all have the same specificity when matching <target>. They should be be applied in order. */
+ foo:nth-child(n), bar:nth-child(n), target:nth-child(n) {
+ background-color: red;
+ color: red;
+ }
+ :nth-child(3n of foo, bar, target) {
+ background-color: green;
+ color: blue;
+ }
+ foo.target, bar.target, target.target {
+ color: white;
+ }
+ * {
+ background-color: white;
+ color: black;
+ }
+</style>
+</head>
+<body>
+ <p>This test the specificity of :nth-child() with static specificity. The test passes if the text "target" is displayed white on green background. There should be 2 red rects on each side.</p>
+ <div>
+ <foo>Not target</foo>
+ <padding></padding>
+ <bar>Not target</bar>
+ <more-padding></more-padding>
+ <target class="target">Target</target>
+ <more-padding></more-padding>
+ <foo>Not target</foo>
+ <padding></padding>
+ <bar>Not target</bar>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-2-ref.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-2-ref.html
new file mode 100644
index 0000000000..1f7d376593
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-2-ref.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<style>
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target style="background-color: white; color: black; border: none;">Black text on white background.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: green; color: red; border: none;">Red text on green background.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: white; color: black; border: 5px solid blue;">Black text on white background with a blue border.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: green; color: red; border: 5px solid blue;">Red text on green background with a blue border.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-2.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-2.html
new file mode 100644
index 0000000000..10467e7408
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-2.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-specificity-2-ref.html">
+<style>
+ /* (1, 1, 0) */
+ :nth-child(even of .foo, #bar, target) {
+ background-color: red;
+ color: white;
+ border: 5px solid purple;
+ }
+
+ /* (0, 1, 1) */
+ target.foo {
+ color: red;
+ }
+
+ /* (0, 2, 0) */
+ .foo.foo {
+ background-color: green;
+ }
+ /* (1, 0, 1) */
+ target#bar {
+ border: 5px solid blue;
+ }
+
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text on white background.</target>
+ <target>White text on red background with a purple border.</target>
+ <target class="foo">Red text on green background.</target>
+ <target class="foo">White text on red background with a purple border.</target>
+ <target id="bar">Black text on white background with a blue border.</target>
+ <target id="bar">White text on red background with a purple border.</target>
+ <target class="foo" id="bar">Red text on green background with a blue border.</target>
+ <target class="foo" id="bar">White text on red background with a purple border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-3-ref.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-3-ref.html
new file mode 100644
index 0000000000..b13bc50f41
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-3-ref.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<style>
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target style="color:red; border: 5px solid black;">Red text with black border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="border: 5px solid blue;">Black text with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-3.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-3.html
new file mode 100644
index 0000000000..8649f4fc4a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-3.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-specificity-3-ref.html">
+<style>
+ /* (1, 2, 1) */
+ :nth-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
+ background-color: red;
+ color: white;
+ border: 5px solid purple;
+ }
+
+ /* (0, 1, 1) */
+ target.foo {
+ color: red;
+ }
+ /* (0, 2, 1) */
+ target.foo.foo {
+ border: 5px solid black;
+ }
+
+ /* (1, 1, 0) */
+ .foo#bar {
+ background-color: green;
+ }
+ /* (1, 0, 1) */
+ target#bar {
+ border: 5px solid blue;
+ }
+
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target class="foo">Red text with black border.</target>
+ <target class="foo">White text on red background with purple border.</target>
+ <target id="bar">Black text with blue border.</target>
+ <target id="bar">White text on red background with purple border.</target>
+ <target class="foo" id="bar">Red text on green background with blue border.</target>
+ <target class="foo" id="bar">White text on red background with purple border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-4-ref.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-4-ref.html
new file mode 100644
index 0000000000..b6f26c9cf4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-4-ref.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<style>
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target style="border: 5px solid blue;">Black text with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; border: 5px solid black;">Red text with black border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-child-specificity-4.html b/testing/web-platform/tests/css/selectors/nth-child-specificity-4.html
new file mode 100644
index 0000000000..de856c2824
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-child-specificity-4.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-child-specificity-4-ref.html">
+<style>
+ /* (1, 2, 1) */
+ :nth-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
+ background-color: red;
+ color: white;
+ border: 5px solid purple;
+ }
+
+ /* (0, 1, 1) */
+ target.foo {
+ color: red;
+ }
+ /* (0, 2, 1) */
+ target.foo.foo {
+ border: 5px solid black;
+ }
+
+ /* (1, 1, 0) */
+ .foo#bar {
+ background-color: green;
+ }
+ /* (1, 0, 1) */
+ target#bar {
+ border: 5px solid blue;
+ }
+
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target id="bar">Black text with blue border.</target>
+ <target class="foo">White text on red background with purple border.</target>
+ <target class="foo" id="bar">Red text on green background with blue border.</target>
+ <target id="bar">White text on red background with purple border.</target>
+ <target class="foo">Red text with black border.</target>
+ <target class="foo" id="bar">White text on red background with purple border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-classname-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-classname-ref.html
new file mode 100644
index 0000000000..7df68b2aee
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-classname-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green!</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green!</p>
+ <p>White</p>
+ <p>White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-classname.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-classname.html
new file mode 100644
index 0000000000..80770b08a6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-classname.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with .className selector list argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-of-classname-ref.html">
+<style>
+p:nth-last-child(even of .webkit, .fast) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White</p>
+ <p>White</p>
+ <p class="webkit">Green!</p>
+ <p>White</p>
+ <p>White</p>
+ <p class="webkit">White</p>
+ <p>White</p>
+ <p class="fast">Green!</p>
+ <p>White</p>
+ <p class="webkit">White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector-ref.html
new file mode 100644
index 0000000000..cda1902d1a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector-ref.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p style="background-color: lime">Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector.html
new file mode 100644
index 0000000000..ae8fc6ebfa
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-complex-selector.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with complex selector list argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-of-complex-selector-ref.html">
+<style>
+p:nth-last-child(4n of html:root>body>p+p:not(empty), :not(*), p:not(p), span, .notthere) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+ <p>Green</p>
+ <p>White</p>
+ <p>White</p>
+ <p>White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector-ref.html
new file mode 100644
index 0000000000..bc5c3ddbd5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector-ref.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p style="background-color: lime">Green</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p>White!</p>
+ <p></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector.html
new file mode 100644
index 0000000000..df1d58347b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-compound-selector.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with compound selector argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-of-compound-selector-ref.html">
+<style>
+p:nth-last-child(3n+1 of p.foobar:not([class=foobar])) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+
+ <p>White!</p>
+ <p class="foo foobar baz">White!</p>
+ <p class="foobar">White!</p>
+ <p class="foo foobar">White!</p>
+ <p class="foobar">White!</p>
+ <p class="foobar foo">Green</p>
+ <p>White!</p>
+ <p class="foo foobar">White!</p>
+ <p>White!</p>
+ <p class="foobar foo">White!</p>
+ <p class="foobar">White!</p>
+ <p class="foobar foo"></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-nesting.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-nesting.html
new file mode 100644
index 0000000000..e1ce3ce203
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-nesting.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child nesting</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="match" href="nth-child-of-nesting-ref.html">
+<style>
+:nth-last-child(2n - 2 of :nth-last-child(n of .target)) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>White</p>
+ <p class="target">Green</p>
+ <p>White</p>
+ <p class="target">White</p>
+ <p>White</p>
+ <p class="target">Green</p>
+ <p>White</p>
+ <p class="target">White</p>
+ <p>White</p>
+ <p class="target">Green</p>
+ <p>White</p>
+ <p class="target">White</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-no-space-after-of.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-no-space-after-of.html
new file mode 100644
index 0000000000..5ce99119b9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-no-space-after-of.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>:nth-last-child with no space between "of" and the selector list</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
+<link rel="match" href="nth-child-of-no-space-after-of-ref.html">
+<style>
+ target {
+ color: red;
+ }
+
+ :nth-last-child(1 of/* my comment */target) {
+ color: green;
+ }
+
+ .target {
+ color: red;
+ }
+
+ :nth-last-child(1 of.target) {
+ color: green;
+ }
+
+ [target] {
+ color: red;
+ }
+
+ :nth-last-child(1 of[target]) {
+ color: green;
+ }
+</style>
+</head>
+<body>
+ <p>Testing no space between "of" and the selector list. If the test succeeded, every instance of the text "Success" should be green.</p>
+ <div></div>
+ <target>Foo</target>
+ <div></div>
+ <target>Bar</target>
+ <div></div>
+ <target>Success</target>
+ <div></div>
+ <div class=target>Foo</div>
+ <div></div>
+ <div class=target>Bar</div>
+ <div></div>
+ <div class=target>Success</div>
+ <div></div>
+ <div target>Foo</div>
+ <div></div>
+ <div target>Bar</div>
+ <div></div>
+ <div target>Success</div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1-ref.html
new file mode 100644
index 0000000000..14ca8e42c7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+<body>
+ <p>Test that style-sharing does not ignore cases matching :nth-last-child(An+B of selector list).</p>
+ <p style="background-color: lime">Target</p>
+ <p>Target</p>
+ <p>Target</p>
+ <p style="background-color: lime">Target</p>
+ <p>Target</p>
+ <p>Target</p>
+ <p style="background-color: lime">Target</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1.html
new file mode 100644
index 0000000000..17ea008b2d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-1.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child correct style-sharing</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-of-style-sharing-1-ref.html">
+<style>
+:nth-last-child(3n+1 of .target) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>Test that style-sharing does not ignore cases matching :nth-last-child(An+B of selector list).</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2-ref.html
new file mode 100644
index 0000000000..1ef071d56b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2-ref.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+<body>
+ <p>Test that style-sharing does not ignore cases matching :nth-last-child(An+B of selector list).</p>
+ <p>Target</p>
+ <p>Target</p>
+ <p style="background-color: lime">Target</p>
+ <p>Target</p>
+ <p>Target</p>
+ <p style="background-color: lime">Target</p>
+ <p>Target</p>
+ <p>Target</p>
+ <p style="background-color: lime">Target</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2.html
new file mode 100644
index 0000000000..2c586956b4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-style-sharing-2.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child correct style-sharing</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-of-style-sharing-2-ref.html">
+<style>
+:nth-last-child(3n+1 of .target) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>Test that style-sharing does not ignore cases matching :nth-last-child(An+B of selector list).</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+ <p class="target">Target</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-tagname-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-tagname-ref.html
new file mode 100644
index 0000000000..e0dcc6b036
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-tagname-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White!</p>
+ <webkit>White!</webkit>
+ <p>White!</p>
+ <webkit style="background-color: lime">Green</webkit>
+ <webkit>White!</webkit>
+ <p>White!</p>
+ <p>White!</p>
+ <fast style="background-color: lime">Green</fast>
+ <p>White!</p>
+ <p>White!</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-of-tagname.html b/testing/web-platform/tests/css/selectors/nth-last-child-of-tagname.html
new file mode 100644
index 0000000000..385d12948c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-of-tagname.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with tagname selector list argument</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-of-tagname-ref.html">
+<style>
+:nth-last-child(odd of webkit, fast) {
+ background-color: lime;
+}
+</style>
+</head>
+<body>
+ <p>This test the styling of paragraphs with :nth-last-child(An+B of selector). If the test succeed, paragraphs that say "green" should have a green background.</p>
+ <p>White!</p>
+ <webkit>White!</webkit>
+ <p>White!</p>
+ <webkit>Green</webkit>
+ <webkit>White!</webkit>
+ <p>White!</p>
+ <p>White!</p>
+ <fast>Green</fast>
+ <p>White!</p>
+ <p>White!</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-1-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-1-ref.html
new file mode 100644
index 0000000000..609279fdc5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-1-ref.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html>
+<body>
+ <p>This test the specificity of :nth-last-child() with static specificity. The test passes if the text "target" is displayed white on green background. There should be 2 red rects on each side.</p>
+ <div>
+ <foo style="color: red; background-color: red;">Not target</foo>
+ <padding></padding>
+ <bar style="color: red; background-color: red;">Not target</bar>
+ <more-padding></more-padding>
+ <target style="color: white; background-color: green;">Target</target>
+ <more-padding></more-padding>
+ <foo style="color: red; background-color: red;">Not target</foo>
+ <padding></padding>
+ <bar style="color: red; background-color: red;">Not target</bar>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-1.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-1.html
new file mode 100644
index 0000000000..18e00f1ca5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-1.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-specificity-1-ref.html">
+<style>
+ /* The following 3 rules should all have the same specificity when matching <target>. They should be be applied in order. */
+ foo:nth-last-child(n), bar:nth-last-child(n), target:nth-last-child(n) {
+ background-color: red;
+ color: red;
+ }
+ :nth-last-child(3n of foo, bar, target) {
+ background-color: green;
+ color: blue;
+ }
+ foo.target, bar.target, target.target {
+ color: white;
+ }
+ * {
+ background-color: white;
+ color: black;
+ }
+</style>
+</head>
+<body>
+ <p>This test the specificity of :nth-last-child() with static specificity. The test passes if the text "target" is displayed white on green background. There should be 2 red rects on each side.</p>
+ <div>
+ <foo>Not target</foo>
+ <padding></padding>
+ <bar>Not target</bar>
+ <more-padding></more-padding>
+ <target class="target">Target</target>
+ <more-padding></more-padding>
+ <foo>Not target</foo>
+ <padding></padding>
+ <bar>Not target</bar>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-2-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-2-ref.html
new file mode 100644
index 0000000000..70c44b8fac
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-2-ref.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<style>
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: white; color: black; border: none;">Black text on white background.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: green; color: red; border: none;">Red text on green background.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: white; color: black; border: 5px solid blue;">Black text on white background with a blue border.</target>
+ <target style="background-color: red; color: white; border: 5px solid purple;">White text on red background with a purple border.</target>
+ <target style="background-color: green; color: red; border: 5px solid blue;">Red text on green background with a blue border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-2.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-2.html
new file mode 100644
index 0000000000..3c3c8739f3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-2.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-specificity-2-ref.html">
+<style>
+ /* (1, 1, 0) */
+ :nth-last-child(even of .foo, #bar, target) {
+ background-color: red;
+ color: white;
+ border: 5px solid purple;
+ }
+
+ /* (0, 1, 1) */
+ target.foo {
+ color: red;
+ }
+
+ /* (0, 2, 0) */
+ .foo.foo {
+ background-color: green;
+ }
+ /* (1, 0, 1) */
+ target#bar {
+ border: 5px solid blue;
+ }
+
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>White text on red background with a purple border.</target>
+ <target>Black text on white background.</target>
+ <target class="foo">White text on red background with a purple border.</target>
+ <target class="foo">Red text on green background.</target>
+ <target id="bar">White text on red background with a purple border.</target>
+ <target id="bar">Black text on white background with a blue border.</target>
+ <target class="foo" id="bar">White text on red background with a purple border.</target>
+ <target class="foo" id="bar">Red text on green background with a blue border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-3-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-3-ref.html
new file mode 100644
index 0000000000..8adc397d38
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-3-ref.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<style>
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; border: 5px solid black;">Red text with black border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="border: 5px solid blue;">Black text with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-3.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-3.html
new file mode 100644
index 0000000000..93a7007a48
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-3.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-specificity-3-ref.html">
+<style>
+ /* (1, 2, 1) */
+ :nth-last-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
+ background-color: red;
+ color: white;
+ border: 5px solid purple;
+ }
+
+ /* (0, 1, 1) */
+ target.foo {
+ color: red;
+ }
+ /* (0, 2, 1) */
+ target.foo.foo {
+ border: 5px solid black;
+ }
+
+ /* (1, 1, 0) */
+ .foo#bar {
+ background-color: green;
+ }
+ /* (1, 0, 1) */
+ target#bar {
+ border: 5px solid blue;
+ }
+
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target class="foo">White text on red background with purple border.</target>
+ <target class="foo">Red text with black border.</target>
+ <target id="bar">White text on red background with purple border.</target>
+ <target id="bar">Black text with blue border.</target>
+ <target class="foo" id="bar">White text on red background with purple border.</target>
+ <target class="foo" id="bar">Red text on green background with blue border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-4-ref.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-4-ref.html
new file mode 100644
index 0000000000..f0042d1114
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-4-ref.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+<style>
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="border: 5px solid blue;">Black text with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; background-color:green; border: 5px solid blue;">Red text on green background with blue border.</target>
+ <target style="color:white; background-color:red; border: 5px solid purple;">White text on red background with purple border.</target>
+ <target style="color:red; border: 5px solid black;">Red text with black border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-last-child-specificity-4.html b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-4.html
new file mode 100644
index 0000000000..f556b994b0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-last-child-specificity-4.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<title>:nth-last-child with selector list specificity</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="match" href="nth-last-child-specificity-4-ref.html">
+<style>
+ /* (1, 2, 1) */
+ :nth-last-child(even of target.foo, .foo#bar, target.foo#bar, target#bar) {
+ background-color: red;
+ color: white;
+ border: 5px solid purple;
+ }
+
+ /* (0, 1, 1) */
+ target.foo {
+ color: red;
+ }
+ /* (0, 2, 1) */
+ target.foo.foo {
+ border: 5px solid black;
+ }
+
+ /* (1, 1, 0) */
+ .foo#bar {
+ background-color: green;
+ }
+ /* (1, 0, 1) */
+ target#bar {
+ border: 5px solid blue;
+ }
+
+ target {
+ display: block;
+ margin: 2px;
+ }
+</style>
+</head>
+<body>
+ <div>
+ <target>Black text.</target>
+ <target>Black text.</target>
+ <target class="foo">White text on red background with purple border.</target>
+ <target id="bar">Black text with blue border.</target>
+ <target id="bar">White text on red background with purple border.</target>
+ <target class="foo" id="bar">Red text on green background with blue border.</target>
+ <target class="foo" id="bar">White text on red background with purple border.</target>
+ <target class="foo">Red text with black border.</target>
+ </div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-of-invalid.html b/testing/web-platform/tests/css/selectors/nth-of-invalid.html
new file mode 100644
index 0000000000..89c3026d71
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-of-invalid.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test nth-child selector argument</title>
+ <link rel="author" title="Mike Bremford" href="https://bfo.com"/>
+ <link rel="help" href="https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo"/>
+ <link rel="match" href="../reference/ref-filled-green-100px-square.xht"/>
+ <style type="text/css">
+ div {
+ display: block;
+ width: 100px;
+ height: 20px;
+ background-color: green;
+ }
+ .container {
+ height: 100px;
+ }
+ .reference {
+ background-color: green;
+ }
+ div:nth-child(1 of) { background-color: red; }
+ div:nth-last-child(n of) { background-color: red; }
+ div:nth-child(even of) { background-color: red; }
+ div:nth-last-child(even of even) { background-color: red; } /* valid just not matching */
+ div:nth-child(even .test) { background-color: red; }
+ div:nth-last-child(of) { background-color: red; }
+ div:nth-child(of ) { background-color: red; }
+ div:nth-last-child(of .) { background-color: red; }
+ div:nth-child(of .test) { background-color: red; }
+ div:nth-last-child(n + of ) { background-color: red; }
+ div:nth-child(n - of ) { background-color: red; }
+ div:nth-last-child(n + 1of) { background-color: red; }
+ div:nth-child(+ of .test) { background-color: red; }
+ div:nth-last-child(1 + of .test) { background-color: red; }
+ div:nth-child(1 - of .test) { background-color: red; }
+ div:nth-last-child(1 n) { background-color: red }
+ div:nth-child("1" of div) { background-color: red }
+ div:nth-last-child(1 "of" div) { background-color: red }
+ div:nth-child(1 of "" div) { background-color: red }
+ div:nth-last-child(n-1of div) { background-color: red }
+ div:nth-of-type(n of div) { background-color: red } /* gotcha */
+ div:nth-last-of-type(n of div) { background-color: red }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="container">
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+ </div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/nth-of-type-namespace.html b/testing/web-platform/tests/css/selectors/nth-of-type-namespace.html
new file mode 100644
index 0000000000..f5d81a5df3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/nth-of-type-namespace.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>CSS Selectors Test: :*-of-type with namespace</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#typed-child-index">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ [test-span]:nth-of-type(100) {
+ color: green;
+ }
+</style>
+<div id="container"></div>
+<script>
+
+ setup(() => {
+ function appendSpans(parent) {
+ for (let i = 0; i < 99; i++) {
+ parent.appendChild(document.createElement("span"));
+ }
+ const test_span = document.createElement("span");
+ test_span.setAttribute("test-span", "");
+ parent.appendChild(test_span);
+ }
+
+ function appendSpansNS(parent, namespace) {
+ for (let i = 0; i < 99; i++) {
+ parent.appendChild(document.createElementNS(namespace, "span"));
+ }
+ const test_span = document.createElementNS(namespace, "span");
+ test_span.setAttribute("test-span", "");
+ parent.appendChild(test_span);
+ }
+
+ appendSpans(container);
+ appendSpansNS(container, "http://dummy1/");
+ appendSpansNS(container, "http://dummy2/");
+ });
+
+ const green = "rgb(0, 128, 0)";
+
+ for (let span of container.querySelectorAll("[test-span]")) {
+ test(() => {
+ assert_equals(getComputedStyle(span).color, green,
+ "span with namespace: " + span.namespaceURI
+ + " should have a green color");
+ }, ":nth-of-type selectors matching takes element namespace into account ("
+ + span.namespaceURI + ")");
+ }
+</script>
diff --git a/testing/web-platform/tests/css/selectors/of-type-selectors-ref.xhtml b/testing/web-platform/tests/css/selectors/of-type-selectors-ref.xhtml
new file mode 100644
index 0000000000..ae866213df
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/of-type-selectors-ref.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selectors Level 4: :first-of-type</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
+<style type="text/css">
+div > *|* {
+ display: block;
+ color: black;
+ border: thin solid;
+ margin: 1em;
+}
+.yellow {
+ background: yellow;
+}
+.green {
+ background: lime;
+}
+</style>
+</head>
+<body>
+<div>
+<p class="green">This line should have a green background.</p>
+<p class="yellow">This line should have a yellow background.</p>
+<p class="yellow">This line should have a yellow background.</p>
+<p class="green">This line should have a green background.</p>
+<p class="green">This line should have a green background.</p>
+</div>
+<div>
+<p class="green">This line should have a green background.</p>
+<p class="yellow">This line should have a yellow background.</p>
+<p class="yellow">This line should have a yellow background.</p>
+<p class="green">This line should have a green background.</p>
+<p class="green">This line should have a green background.</p>
+</div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/of-type-selectors.xhtml b/testing/web-platform/tests/css/selectors/of-type-selectors.xhtml
new file mode 100644
index 0000000000..73ec208b8f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/of-type-selectors.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selectors Level 4: :first-of-type</title>
+<meta name="flags" content="namespace nonHTML"/>
+<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-first-of-type-pseudo"/>
+<link rel="match" href="of-type-selectors-ref.xhtml"/>
+<style type="text/css">
+div > *|* {
+ display: block;
+ color: black;
+ background: yellow;
+ border: thin solid;
+ margin: 1em;
+}
+.first-of-type > *|*:first-of-type {
+ background: lime;
+}
+.nth-of-type > *|*:nth-of-type(1) {
+ background: lime;
+}
+</style>
+</head>
+<body>
+<div class="first-of-type">
+<p>This line should have a green background.</p>
+<p>This line should have a yellow background.</p>
+<html:p>This line should have a yellow background.</html:p>
+<p xmlns="http://www.example.com/ns">This line should have a green background.</p>
+<p xmlns="">This line should have a green background.</p>
+</div>
+<div class="nth-of-type">
+<p>This line should have a green background.</p>
+<p>This line should have a yellow background.</p>
+<html:p>This line should have a yellow background.</html:p>
+<p xmlns="http://www.example.com/ns">This line should have a green background.</p>
+<p xmlns="">This line should have a green background.</p>
+</div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-1.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-1.xml
new file mode 100644
index 0000000000..0fb46f0fd1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-1.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Groups of selectors</title>
+ <style type="text/css"><![CDATA[li,p { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li>The background of this list item should be green</li>
+ <li>The background of this second list item should be also green</li>
+</ul>
+<p>The background of this paragraph should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-10.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-10.xml
new file mode 100644
index 0000000000..404fa65f28
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-10.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector (end)</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p[title$="bar"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p title="foobar">This paragraph should have a green background because
+its title attribute ends with &quot;bar&quot;</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100.xml
new file mode 100644
index 0000000000..57658b7013
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute dash-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[a|foo|="bar"], *|*[html|lang|="en"] { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b" xmlns:html="http://www.w3.org/1999/xhtml">
+<p html:lang="en-us">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:foo="bargain-trash">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:foo="bar-drink-glass">This paragraph should have a green background</r>
+<s xmlns="http://www.example.org/b" b:foo="bar-drink-glass">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100b.xml
new file mode 100644
index 0000000000..8519170f15
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-100b.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute dash-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[a|foo|="bar"], *|*[html|lang|="en"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b" xmlns:html="http://www.w3.org/1999/xhtml">
+<p html:lang="en-us">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:foo="bargain-trash">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:foo="bar-drink-glass">This paragraph should have a green background</r>
+<s xmlns="http://www.example.org/b" b:foo="bar-drink-glass">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101.xml
new file mode 100644
index 0000000000..4d17096f43
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute value selector on beginning with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[a|title^="si on"], *|*[title^="si on"] { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="et si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101b.xml
new file mode 100644
index 0000000000..23fc37b86a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-101b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute value selector on beginning with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[a|title^="si on"], *|*[title^="si on"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="et si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102.xml
new file mode 100644
index 0000000000..de59781851
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute value selector on end with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[a|title$="tait"], p[|title$="tait"] { background-color : lime }
+*|*[|title$="tait"], *|*[html|title$="tait"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" xmlns:a="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" xmlns:a="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" xmlns:b="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102b.xml
new file mode 100644
index 0000000000..cfd121ab71
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-102b.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute value selector on end with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[a|title$="tait"], *|*[html|title$="tait"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<p title="si on chantait">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" xmlns:a="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" xmlns:a="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" xmlns:b="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103.xml
new file mode 100644
index 0000000000..191533a5d3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute value selector on middle with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[a|title*="hanta"], p[|title*="hanta"] { background-color : lime }
+*|*[|title*="hanta"], *|*[html|title*="hanta"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103b.xml
new file mode 100644
index 0000000000..4cdd208fa4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-103b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute value selector on middle with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[a|title*="hanta"], *|*[html|title*="hanta"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104.xml
new file mode 100644
index 0000000000..beed75ddaa
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+*|*[*|title] { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104b.xml
new file mode 100644
index 0000000000..9a87d41fa3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-104b.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+*|*[*|title] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105.xml
new file mode 100644
index 0000000000..51d511ee98
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+*|*[*|title="si on chantait"] { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should be unstyled.</q>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105b.xml
new file mode 100644
index 0000000000..3c3cd2ce4c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-105b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+*|*[*|title="si on chantait"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should be unstyled.</q>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106.xml
new file mode 100644
index 0000000000..c806d6bf56
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute space-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+*|*[*|class~="deux"], *|*[*|foo~="deux"] { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p class="un deux trois">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:bar="un deux trois">This paragraph should be unstyled.</q>
+<q xmlns="http://www.example.org/a" a:foo="un second deuxieme trois">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:foo="un deux trois">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:foo="un deux trois">This paragraph should have a green background.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106b.xml
new file mode 100644
index 0000000000..a76ec5a05f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-106b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute space-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+*|*[*|class~="deux"], *|*[*|foo~="deux"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p class="un deux trois">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:bar="un deux trois">This paragraph should be unstyled.</q>
+<q xmlns="http://www.example.org/a" a:foo="un second deuxieme trois">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:foo="un deux trois">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:foo="un deux trois">This paragraph should have a green background.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107.xml
new file mode 100644
index 0000000000..260bdd40c6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute dash-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[*|lang|="en"], *|*[a|foo|="un-d"] { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p lang="en-us">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" a:foo="un-deux-trois">This paragraph should be unstyled.</q>
+<q xmlns="http://www.example.org/a" a:foo="un-second-deuxieme-trois">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:foo="un-d-trois">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:foo="un-d-trois">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107b.xml
new file mode 100644
index 0000000000..ebdd2e009b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-107b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute dash-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[*|lang|="en"], *|*[a|foo|="un-d"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p lang="en-us">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" a:foo="un-deux-trois">This paragraph should be unstyled.</q>
+<q xmlns="http://www.example.org/a" a:foo="un-second-deuxieme-trois">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:foo="un-d-trois">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:foo="un-d-trois">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108.xml
new file mode 100644
index 0000000000..30e354522d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on beginning with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+*|*[*|title^="si on"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108b.xml
new file mode 100644
index 0000000000..933aee9c14
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-108b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on beginning with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+*|*[*|title^="si on"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109.xml
new file mode 100644
index 0000000000..9f8cee6a73
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on end with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+*|*[*|title$="tait"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109b.xml
new file mode 100644
index 0000000000..5e242f5d73
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-109b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on end with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+*|*[*|title$="tait"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-11.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-11.xml
new file mode 100644
index 0000000000..b1c8539739
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-11.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector (contains)</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p[title*="bar"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p title="foobarufoo">This paragraph should have a green background because
+its title attribute contains &quot;bar&quot;</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110.xml
new file mode 100644
index 0000000000..8760fac79a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on middle with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+*|*[*|title*="on ch"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110b.xml
new file mode 100644
index 0000000000..a20984ac41
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-110b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on middle with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+*|*[*|title*="on ch"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111.xml
new file mode 100644
index 0000000000..f834da5485
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111.xml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[|title] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a">
+<p title="si on chantait">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111b.xml
new file mode 100644
index 0000000000..8d55801a24
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-111b.xml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[|title] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a">
+<p title="si on chantait">This paragraph should have a green background</p>
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112.xml
new file mode 100644
index 0000000000..f335eff311
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[|title="si on chantait"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112b.xml
new file mode 100644
index 0000000000..0b5b174b3a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-112b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[|title="si on chantait"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113.xml
new file mode 100644
index 0000000000..c779e14650
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute space-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|p, *|q { background-color : red }
+*|*[|class~="foo"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<p class="bar foo toto">This paragraph should have a green background.</p>
+<address class="bar foofoo toto">This address should be unstyled.</address>
+<q xmlns="http://www.example.org/a" class="bar foo toto">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/b" b:class="bar foo toto">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113b.xml
new file mode 100644
index 0000000000..4cbfc6dfee
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-113b.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute space-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|p, *|q { background-color : lime ! important }
+*|*[|class~="foo"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<p class="bar foo toto">This paragraph should have a green background.</p>
+<address class="bar foofoo toto">This address should be unstyled.</address>
+<q xmlns="http://www.example.org/a" class="bar foo toto">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/b" b:class="bar foo toto">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114.xml
new file mode 100644
index 0000000000..9a7f451ee8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute dash-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|p, *|q { background-color : red }
+*|*[|lang|="foo-bar"], *|*[|myattr|="tat-tut"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<p lang="foo-bar">This paragraph should have a green background.</p>
+<address lang="foo-b">This address should be unstyled.</address>
+<address lang="foo-barbar-toto">This address should be unstyled.</address>
+<q xmlns="http://www.example.org/a" myattr="tat-tut-tot">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/b" b:myattr="tat-tut-tot">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114b.xml
new file mode 100644
index 0000000000..b5aab0d17d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-114b.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute dash-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|p, *|q { background-color : lime ! important }
+*|*[|lang|="foo-bar"], *|*[|myattr|="tat-tut"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<p lang="foo-bar">This paragraph should have a green background.</p>
+<address lang="foo-b">This address should be unstyled.</address>
+<address lang="foo-barbar-toto">This address should be unstyled.</address>
+<q xmlns="http://www.example.org/a" myattr="tat-tut-tot">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/b" b:myattr="tat-tut-tot">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115.xml
new file mode 100644
index 0000000000..4c2492bd1b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on beginning without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[|title^="si on"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115b.xml
new file mode 100644
index 0000000000..9b37ed1ab8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-115b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on beginning without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[|title^="si on"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116.xml
new file mode 100644
index 0000000000..e73d83db14
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on end without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[|title$="tait"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116b.xml
new file mode 100644
index 0000000000..59a46a6362
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-116b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on end without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[|title$="tait"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117.xml
new file mode 100644
index 0000000000..5381cec147
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on middle without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[|title*="on ch"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117b.xml
new file mode 100644
index 0000000000..b88ac99a65
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-117b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector on middle without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[|title*="on ch"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<p title="si on chantait">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should have a green background.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should be unstyled.</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-118.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-118.xml
new file mode 100644
index 0000000000..823c577031
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-118.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED type element selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|l { display : block ; margin-bottom : 1em }
+div.test * { background-color : red }
+div.test *:not(a|p) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="test">
+ <p xmlns="http://www.w3.org/1999/xhtml">This paragraph should have a green background.</p>
+ <p xmlns="http://www.example.org/b">This paragraph should have a green background.</p>
+ <p xmlns="">This paragraph should have a green background.</p>
+ <p xmlns="http://www.example.org/a">
+ <l>This paragraph should have a green background.</l>
+ </p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-119.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-119.xml
new file mode 100644
index 0000000000..8a4eda34b4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-119.xml
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED type element selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.test *:not(*|div) { display : block ; margin-bottom : 1em ;
+ background-color : red }
+div.test > *:not(*|p):not(*|div) { background-color : lime }
+div.stub > *:not(*|div) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="test">
+<div class="stub">
+<p>This paragraph should have a green background.</p>
+<p xmlns="http://www.example.org/b">This paragraph should have a green background.</p>
+<p xmlns="">This paragraph should have a green background.</p>
+<p xmlns="http://www.example.org/a">This paragraph should have a green background.</p>
+</div>
+<address>This address should have a green background.</address>
+<s xmlns="http://www.example.org/b">This paragraph should have a green background.</s>
+<t xmlns="">This paragraph should have a green background.</t>
+<u xmlns="http://www.example.org/a">This paragraph should have a green background.</u>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-120.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-120.xml
new file mode 100644
index 0000000000..4f233426b2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-120.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED type element selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > * { display : block ; margin-bottom : 1em ;
+ background-color : red }
+div.stub > *:not(|p) { background-color : lime }
+div.stub > *|l > *:not(|p) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<p>This paragraph should have a green background</p>
+<p xmlns="http://www.example.org/b">This paragraph should have a green background</p>
+<l xmlns="http://www.example.org/b">
+<p xmlns="">This paragraph should have a
+ green background</p>
+</l>
+<p xmlns="http://www.example.org/a">This paragraph should have a green background</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-121.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-121.xml
new file mode 100644
index 0000000000..4d666876cc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-121.xml
@@ -0,0 +1,28 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED universal selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > *|* { color : red ; display : block ;
+ margin-bottom : 1em }
+div.stub > *|*:not(a|*) { color : green }
+div.stub v { color : green }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<address>This address should be in green characters.</address>
+<s xmlns="http://www.example.org/b">This paragraph should be in green characters.</s>
+<t xmlns="">This paragraph should be in green characters.</t>
+<u xmlns="http://www.example.org/a">
+<v>This paragraph should be in green characters.</v>
+</u>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-122.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-122.xml
new file mode 100644
index 0000000000..2353831305
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-122.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED universal selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > *|* { background-color : lime ; display : block ;
+ margin-bottom : 1em }
+div.stub > *|*:not(*|*) { background-color : red }
+/* yes, the rule just above selects nothing... That's the point */
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-address-p-p-p-lime-background.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<address>This address should have a green background</address>
+<s xmlns="http://www.example.org/b">This paragraph should have a green background</s>
+<t xmlns="">This paragraph should have a green background</t>
+<u xmlns="http://www.example.org/a">This paragraph should have a green background</u>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123.xml
new file mode 100644
index 0000000000..b9e577a059
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED universal selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > *|* { color : red ; display : block ;
+ margin-bottom : 1em }
+div.stub > *|*:not(|*) { color : green }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<address>This address should be in green characters.</address>
+<s xmlns="http://www.example.org/b">This paragraph should be in green characters.</s>
+<u xmlns="http://www.example.org/a">This paragraph should be in green characters.</u>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123b.xml
new file mode 100644
index 0000000000..b6dcd3a97e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-123b.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED universal selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > *|* { color : green ; display : block ;
+ margin-bottom : 1em }
+div.stub > *|*:not(|*) { color : red ! important }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<t xmlns="">This paragraph should be in green characters.</t>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124.xml
new file mode 100644
index 0000000000..6c487f8af8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : red }
+div.stub *:not([a|title="foo"]) {background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="foo">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="foo">This paragraph should be unstyled.</q>
+<s xmlns="http://www.example.org/a" a:title="foobar">This paragraph should have a green background.</s>
+<r xmlns="http://www.example.org/b" b:title="foo">This paragraph should have a green background.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124b.xml
new file mode 100644
index 0000000000..a6fba323d2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-124b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r, *|s { background-color : lime ! important }
+div.stub *:not([a|title="foo"]) {background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="foo">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="foo">This paragraph should be unstyled.</q>
+<s xmlns="http://www.example.org/a" a:title="foobar">This paragraph should have a green background.</s>
+<r xmlns="http://www.example.org/b" b:title="foo">This paragraph should have a green background.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125.xml
new file mode 100644
index 0000000000..10e3ec1d84
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute space-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : red }
+div.stub *|*:not([a|foo~="bar"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="hgt bardot f">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="hgt bar f">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="hgt bar f">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125b.xml
new file mode 100644
index 0000000000..032a0eab06
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-125b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute space-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : lime ! important }
+div.stub *|*:not([a|foo~="bar"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="hgt bardot f">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="hgt bar f">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="hgt bar f">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126.xml
new file mode 100644
index 0000000000..dca13bdbf7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute dash-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : red }
+div.stub *|*:not([a|foo|="bar"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="bargain-trash">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="bar-drink-glass">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="bar-drink-glass">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126b.xml
new file mode 100644
index 0000000000..9dba3b1c72
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-126b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute dash-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : lime ! important }
+div.stub *|*:not([a|foo|="bar"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="bargain-trash">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="bar-drink-glass">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="bar-drink-glass">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127.xml
new file mode 100644
index 0000000000..9ef8cd77a7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute value selector on beginning with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : red }
+div.stub *|*:not([a|title^="si on"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="et si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127b.xml
new file mode 100644
index 0000000000..41e88ecf65
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-127b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute value selector on beginning with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : lime ! important }
+div.stub *|*:not([a|title^="si on"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="et si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128.xml
new file mode 100644
index 0000000000..cb192739de
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute value selector on end with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : red }
+div.stub *|*:not([a|title$="tait"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128b.xml
new file mode 100644
index 0000000000..26dbce728c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-128b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute value selector on end with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : lime ! important }
+div.stub *|*:not([a|title$="tait"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129.xml
new file mode 100644
index 0000000000..c3dbdbaf6d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute value selector on middle with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : red }
+div.stub *|*:not([a|title*="hanta"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129b.xml
new file mode 100644
index 0000000000..407d6a91c5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-129b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute value selector on middle with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|s { background-color : lime ! important }
+div.stub *|*:not([a|title*="hanta"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-p-lime-background-except-middle.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-13.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-13.xml
new file mode 100644
index 0000000000..600426e8b9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-13.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Class selectors</title>
+ <style type="text/css"><![CDATA[li { background-color : red }
+.t1 { background-color : lime }
+li.t2 { background-color : lime }
+.t3 { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li class="t1">This list item should have green background because its class is &quot;t1&quot;</li>
+ <li class="t2">This list item should have green background because its class is &quot;t2&quot;</li>
+ <li class="t2">
+<span class="t33">This list item should have green background because
+ the inner SPAN does not match SPAN.t3</span>
+</li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130.xml
new file mode 100644
index 0000000000..e9a7672c53
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute existence selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q { background-color : red }
+div.stub *|*:not([*|title]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130b.xml
new file mode 100644
index 0000000000..54c6c6a9c2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-130b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute existence selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q { background-color : lime ! important }
+div.stub *|*:not([*|title]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131.xml
new file mode 100644
index 0000000000..f937a8094a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q { background-color : red }
+div.stub *|*:not([*|title="si on chantait"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should have a green background.</q>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131b.xml
new file mode 100644
index 0000000000..05a7753eac
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-131b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q { background-color : lime ! important }
+div.stub *|*:not([*|title="si on chantait"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:foo="si on chantait">This paragraph should have a green background.</q>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132.xml
new file mode 100644
index 0000000000..f7080850ff
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132.xml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute space-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p.deu, *|q { background-color : red }
+div.stub html|*:not([*|class~="deux"]),
+ div.stub *|*:not(html|*):not([*|foo~="deux"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p class="un deux trois">This paragraph should be unstyled</p>
+<p class="un deu trois">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:bar="un deux trois">This paragraph should have a green background.</q>
+<q xmlns="http://www.example.org/a" a:foo="un second deuxieme trois">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="un deux trois">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="un deux trois">This paragraph should be unstyled.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132b.xml
new file mode 100644
index 0000000000..8270be88de
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-132b.xml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute space-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p.deu, *|q { background-color : lime ! important }
+div.stub html|*:not([*|class~="deux"]),
+ div.stub *|*:not(html|*):not([*|foo~="deux"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p class="un deux trois">This paragraph should be unstyled</p>
+<p class="un deu trois">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:bar="un deux trois">This paragraph should have a green background.</q>
+<q xmlns="http://www.example.org/a" a:foo="un second deuxieme trois">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="un deux trois">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="un deux trois">This paragraph should be unstyled.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133.xml
new file mode 100644
index 0000000000..1c1b5baf57
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133.xml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute dash-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p.foo, *|q, *|s { background-color : red }
+div.stub html|*:not([*|lang|="en"]),
+ div.stub *|*:not(html|*):not([a|foo|="un-d"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p lang="en-us">This paragraph should be unstyled.</p>
+<p lang="fr" class="foo">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:foo="un-deux-trois">This paragraph should have a green background.</q>
+<q xmlns="http://www.example.org/a" a:foo="un-second-deuxieme-trois">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="un-d-trois">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="un-d-trois">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133b.xml
new file mode 100644
index 0000000000..6f67b88a17
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-133b.xml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute dash-separated value selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p.foo, *|q, *|s { background-color : lime ! important }
+div.stub html|*:not([*|lang|="en"]),
+ div.stub *|*:not(html|*):not([a|foo|="un-d"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p lang="en-us">This paragraph should be unstyled.</p>
+<p lang="fr" class="foo">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:foo="un-deux-trois">This paragraph should have a green background.</q>
+<q xmlns="http://www.example.org/a" a:foo="un-second-deuxieme-trois">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:foo="un-d-trois">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:foo="un-d-trois">This paragraph should have a green background.</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134.xml
new file mode 100644
index 0000000000..20f42fda60
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on beginning with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p.red, *|q, *|t { background-color : red }
+div.stub *|*:not([*|title^="si on"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-g-u-u-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<p title="si il chantait" class="red">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134b.xml
new file mode 100644
index 0000000000..5a14b8f733
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-134b.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on beginning with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p.red, *|q, *|t { background-color : lime ! important }
+div.stub *|*:not([*|title^="si on"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-g-u-u-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<p title="si il chantait" class="red">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135.xml
new file mode 100644
index 0000000000..842ff6573a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on end with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p.red, *|q, *|t { background-color : red }
+div.stub *|*:not([*|title$="tait"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-g-u-u-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<p title="si tu chantais" class="red">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135b.xml
new file mode 100644
index 0000000000..9658c29253
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-135b.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on end with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p.red, *|q, *|t { background-color : lime ! important }
+div.stub *|*:not([*|title$="tait"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-g-u-u-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<p title="si tu chantais" class="red">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136.xml
new file mode 100644
index 0000000000..ca2a6ca22d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136.xml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on middle with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p.red, *|q, *|t { background-color : red }
+div.stub *|*:not([*|title*="on ch"]) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-g-u-u-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<p title="si il chantait" class="red">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136b.xml
new file mode 100644
index 0000000000..94e8cb03d2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-136b.xml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on middle with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|p.red, *|q, *|t { background-color : lime ! important }
+div.stub *|*:not([*|title*="on ch"]) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-g-u-u-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<p title="si il chantait" class="red">This paragraph should have a green background.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should be unstyled.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137.xml
new file mode 100644
index 0000000000..fd17088d38
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute existence selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|q, *|r { display : block ; margin-bottom : 1em }
+*|q { background-color : red }
+div.stub *|*:not([|title]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137b.xml
new file mode 100644
index 0000000000..47d5dc7b20
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-137b.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute existence selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|q, *|r { display : block ; margin-bottom : 1em }
+*|q { background-color : lime ! important }
+div.stub *|*:not([|title]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138.xml
new file mode 100644
index 0000000000..9e8f8c0e2e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : red }
+div.stub *|*:not([|title="si on chantait"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138b.xml
new file mode 100644
index 0000000000..7cc16fd3c3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-138b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : lime ! important }
+div.stub *|*:not([|title="si on chantait"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<q xmlns="http://www.example.org/a" a:title="si on chantait">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139.xml
new file mode 100644
index 0000000000..ceebe6640b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute space-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|address, *|r { background-color : red }
+div.stub *|*:not([|class~="foo"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p class="bar foo toto">This paragraph should be unstyled.</p>
+<address class="bar foofoo toto">This address should have a green background.</address>
+<q xmlns="http://www.example.org/a" class="bar foo toto">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/b" b:class="bar foo toto">This paragraph should have a green background.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139b.xml
new file mode 100644
index 0000000000..4e727ea9c9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-139b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute space-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|address, *|r { background-color : lime ! important }
+div.stub *|*:not([|class~="foo"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p class="bar foo toto">This paragraph should be unstyled.</p>
+<address class="bar foofoo toto">This address should have a green background.</address>
+<q xmlns="http://www.example.org/a" class="bar foo toto">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/b" b:class="bar foo toto">This paragraph should have a green background.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14.xml
new file mode 100644
index 0000000000..29a6f20d8e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14.xml
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>More than one class selector</title>
+ <style type="text/css"><![CDATA[p { background-color : red ; border : thick solid red ; padding : 1em }
+p.t1 { background-color : lime }
+p.t2 { border : thick solid green }
+
+div { background: green; color: white; }
+div.teST { background: red; color: yellow; }
+div.te { background: red; color: yellow; }
+div.st { background: red; color: yellow; }
+div.te.st { background: red; color: yellow; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+
+<p class="t1 t2">This paragraph
+should have a green background and a green thick solid border because
+it carries both classes t1 and t2.</p>
+
+<div class="test">This line
+should be green.</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140.xml
new file mode 100644
index 0000000000..49c9e4bf74
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute dash-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|address, *|r { background-color : red }
+div.stub *|*:not([|lang|="foo-bar"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p lang="foo-bar">This paragraph should be unstyled.</p>
+<address lang="foo-b">This address should have a green background.</address>
+<address lang="foo-barbar-toto">This address should have a green background.</address>
+<q xmlns="http://www.example.org/a" lang="foo-bar">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/b" b:lang="foo-bar">This paragraph should have a green background.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140b.xml
new file mode 100644
index 0000000000..a39bd7d773
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-140b.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute dash-separated value selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|address, *|q, *|r { display : block ; margin-bottom : 1em }
+*|address, *|r { background-color : lime ! important }
+div.stub *|*:not([|lang|="foo-bar"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p lang="foo-bar">This paragraph should be unstyled.</p>
+<address lang="foo-b">This address should have a green background.</address>
+<address lang="foo-barbar-toto">This address should have a green background.</address>
+<q xmlns="http://www.example.org/a" lang="foo-bar">This paragraph should be unstyled.</q>
+<r xmlns="http://www.example.org/b" b:lang="foo-bar">This paragraph should have a green background.</r>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141.xml
new file mode 100644
index 0000000000..d69a2722fc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on beginning without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : red }
+div.stub *|*:not([|title^="si on"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141b.xml
new file mode 100644
index 0000000000..184cb4e9da
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-141b.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on beginning without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : lime ! important }
+div.stub *|*:not([|title^="si on"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" b:ti="si on chantait">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142.xml
new file mode 100644
index 0000000000..230f49032d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on end without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : red }
+div.stub *|*:not([|title$="tait"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142b.xml
new file mode 100644
index 0000000000..a107e2a4ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-142b.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on end without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : lime ! important }
+div.stub *|*:not([|title$="tait"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143.xml
new file mode 100644
index 0000000000..3bcd4f23c7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on middle without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : red }
+div.stub *|*:not([|title*="on ch"]) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143b.xml
new file mode 100644
index 0000000000..3c86729656
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-143b.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Substring matching attribute selector on middle without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s, *|t{ display : block ; margin-bottom : 1em }
+*|q, *|s, *|t { background-color : lime ! important }
+div.stub *|*:not([|title*="on ch"]) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-u-g-u-g-g.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+<div class="stub">
+<p title="si on chantait">This paragraph should be unstyled.</p>
+<q xmlns="http://www.example.org/a" a:title="si nous chantions">This paragraph should have a green background.</q>
+<r xmlns="http://www.example.org/a" title="si on chantait">This paragraph should be unstyled.</r>
+<s xmlns="http://www.example.org/b" b:title="si on chantait">This paragraph should have a green background.</s>
+<t xmlns="http://www.example.org/b" title="si nous chantions">This paragraph should have a green background.</t>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-144.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-144.xml
new file mode 100644
index 0000000000..cbc7d4c16c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-144.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :enabled:disabled pseudo-classes</title>
+ <style type="text/css"><![CDATA[div :not(:enabled):not(:disabled) { background: lime; }
+p { background : red;}]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <p>This paragraph should have a green background.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145a.xml
new file mode 100644
index 0000000000..ff15de6779
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145a.xml
@@ -0,0 +1,33 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-of-type() pseudo-class with hidden elements</title>
+ <style type="text/css"><![CDATA[
+ line { display: block; }
+ [type~=odd] { background: red; }
+ line:nth-of-type(odd) { background: lime; }
+ [hidden] { display: none; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <test xmlns="http://www.example.org/">
+ <line type="odd">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd" hidden="hidden">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even" hidden="hidden">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even" hidden="hidden">This line should be unstyled.</line>
+ <line type="odd" hidden="hidden">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ </test>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145b.xml
new file mode 100644
index 0000000000..fb57366b69
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-145b.xml
@@ -0,0 +1,33 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-of-type() pseudo-class with hidden elements</title>
+ <style type="text/css"><![CDATA[
+ line { display: block; }
+ [type~=odd] { background: lime ! important; }
+ line:nth-of-type(odd) { background: red; }
+ [hidden] { display: none; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <test xmlns="http://www.example.org/">
+ <line type="odd">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd" hidden="hidden">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even" hidden="hidden">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ <line type="even" hidden="hidden">This line should be unstyled.</line>
+ <line type="odd" hidden="hidden">This line should be green.</line>
+ <line type="even">This line should be unstyled.</line>
+ <line type="odd">This line should be green.</line>
+ </test>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146a.xml
new file mode 100644
index 0000000000..8704f09e6d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146a.xml
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-child() pseudo-class with hidden elements</title>
+ <style type="text/css"><![CDATA[
+ line { display: block; }
+ [type~=match] { background: red; }
+ line:nth-child(3n-1) { background: lime; }
+ [hidden] { display: none; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <test xmlns="http://www.example.org/">
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="match" hidden="hidden">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ </test>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146b.xml
new file mode 100644
index 0000000000..a7b28b4e5c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-146b.xml
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-child() pseudo-class with hidden elements</title>
+ <style type="text/css"><![CDATA[
+ line { display: block; }
+ [type~=match] { background: lime ! important; }
+ line:nth-child(3n-1) { background: red; }
+ [hidden] { display: none; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <test xmlns="http://www.example.org/">
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="match" hidden="hidden">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ </test>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147a.xml
new file mode 100644
index 0000000000..dcf600bf80
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147a.xml
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-last-of-type() pseudo-class with collapsed elements</title>
+ <style type="text/css"><![CDATA[
+ line { display: block; }
+ [type~=match] { background: red; }
+ line:nth-last-of-type(3n-1) { background: lime; }
+ [hidden] { visibility: collapse; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <test xmlns="http://www.example.org/">
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match" hidden="hidden">This line should be green.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ </test>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147b.xml
new file mode 100644
index 0000000000..fdea6da425
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-147b.xml
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-last-of-type() pseudo-class with collapsed elements</title>
+ <style type="text/css"><![CDATA[
+ line { display: block; }
+ [type~=match] { background: lime ! important; }
+ line:nth-last-of-type(3n-1) { background: red; }
+ [hidden] { visibility: collapse; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <test xmlns="http://www.example.org/">
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match" hidden="hidden">This line should be green.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="" hidden="hidden">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="">This line should be unstyled.</line>
+ <line type="match">This line should be green.</line>
+ <line type="">This line should be unstyled.</line>
+ </test>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-148.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-148.xml
new file mode 100644
index 0000000000..51f9858ad8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-148.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and text</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ p:empty { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149.xml
new file mode 100644
index 0000000000..7b10e6296c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and empty elements</title>
+ <style type="text/css"><![CDATA[
+ address:empty { background: lime; }
+ address { background: red; margin: 0; height: 1em; }
+ .text { margin: -1em 0 0 0; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background-offset.xht"/>
+ </head>
+ <body>
+ <address></address>
+ <div class="text">This line should have a green background.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149b.xml
new file mode 100644
index 0000000000..7b10e6296c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-149b.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and empty elements</title>
+ <style type="text/css"><![CDATA[
+ address:empty { background: lime; }
+ address { background: red; margin: 0; height: 1em; }
+ .text { margin: -1em 0 0 0; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background-offset.xht"/>
+ </head>
+ <body>
+ <address></address>
+ <div class="text">This line should have a green background.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14b.xml
new file mode 100644
index 0000000000..816a13b448
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14b.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>More than one class selector</title>
+ <style type="text/css"><![CDATA[
+p { background: green; color: white; }
+.t1.fail { background: red; color: yellow; }
+.fail.t1 { background: red; color: yellow; }
+.t2.fail { background: red; color: yellow; }
+.fail.t2 { background: red; color: yellow; }
+/* Note: This is a valid test even per CSS1, since in CSS1 those rules
+ are invalid and should be dropped. */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-background.xht"/>
+ </head>
+ <body>
+ <p class="t1">This line should be green.</p>
+ <p class="t1 t2">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14c.xml
new file mode 100644
index 0000000000..9f92f7912d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14c.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>More than one class selector</title>
+ <style type="text/css"><![CDATA[
+p { background: red; color: yellow; }
+p.t1.t2 { background: green; color: white; }
+div { background: green; color: white; }
+div.t1 { background: red; color: yellow; }
+address { background: red; color: yellow; }
+address.t5.t5 { background: green; color: white; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p class="t1 t2">This line should be green.</p>
+ <div class="t3">This line should be green.</div>
+ <address class="t4 t5 t6">This line should be green.</address>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14d.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14d.xml
new file mode 100644
index 0000000000..411e3cc2b6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14d.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED More than one class selector</title>
+ <style type="text/css"><![CDATA[
+p { background: green; color: white; }
+.t1:not(.t2) { background: red; color: yellow; }
+:not(.t2).t1 { background: red; color: yellow; }
+.t2:not(.t1) { background: red; color: yellow; }
+:not(.t1).t2 { background: red; color: yellow; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p class="t1 t2">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14e.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14e.xml
new file mode 100644
index 0000000000..4538de38e4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-14e.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED More than one class selector</title>
+ <style type="text/css"><![CDATA[
+p { background: green; color: white; }
+p:not(.t1):not(.t2) { background: red; color: yellow; }
+div { background: red; color: yellow; }
+div:not(.t1) { background: green; color: white; }
+address { background: green; color: white; }
+address:not(.t5):not(.t5) { background: red; color: yellow; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p class="t1 t2">This line should be green.</p>
+ <div class="t3">This line should be green.</div>
+ <address class="t4 t5 t6">This line should be green.</address>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15.xml
new file mode 100644
index 0000000000..73b340e27b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>ID selectors</title>
+ <style type="text/css"><![CDATA[li { background-color : red }
+#t1 { background-color : lime }
+li#t2 { background-color : lime }
+li#t3 { background-color : lime }
+#t4 { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li id="t1">This list item should have a green background. because its ID is &quot;t1&quot;</li>
+ <li id="t2">This list item should have a green background. because its ID is &quot;t2&quot;</li>
+ <li id="t3"><span id="t44">This list item should have a green background. because the inner SPAN does not match &quot;#t4&quot;</span></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-150.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-150.xml
new file mode 100644
index 0000000000..49a7807b10
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-150.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and XML/SGML constructs</title>
+ <style type="text/css"><![CDATA[
+ address:empty { background: lime; }
+ address { background: red; margin: 0; height: 1em; }
+ .text { margin: -1em 0 0 0; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <address><!-- --><?test random PI?></address>
+ <div class="text">This line should have a green background.</div>
+ <p>(Note: This test is based on unpublished errata.)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-151.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-151.xml
new file mode 100644
index 0000000000..46c25dc0a8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-151.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and whitespace</title>
+ <style type="text/css"><![CDATA[
+ address { background: lime; margin: 0; height: 1em; }
+ address:empty { background: red; }
+ .text { margin: -1em 0 0 0; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background-offset.xht"/>
+ </head>
+ <body>
+ <address> </address>
+ <div class="text">This line should have a green background.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-152.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-152.xml
new file mode 100644
index 0000000000..680a0a9aef
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-152.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and elements</title>
+ <style type="text/css"><![CDATA[
+ address { background: lime; margin: 0; height: 1em; }
+ address:empty { background: red; }
+ .text { margin: -1em 0 0 0; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background-offset.xht"/>
+ </head>
+ <body>
+ <address><span></span></address>
+ <div class="text">This line should have a green background.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-153.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-153.xml
new file mode 100644
index 0000000000..45f65fb598
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-153.xml
@@ -0,0 +1,18 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:empty pseudo-class and CDATA</title>
+ <style type="text/css"><![CDATA[
+ address { background: red; margin: 0; height: 1em; display: block; }
+ address:empty { background: lime; }
+ .text { margin: -1em 0 0 0; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <address xmlns="http://tests.example.org/xml-only/"><![CDATA[]]></address>
+ <div class="text">This line should have a green background.</div>
+ <p>(Note: This test is based on unpublished errata.)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-154.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-154.xml
new file mode 100644
index 0000000000..951f107929
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-154.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ p, { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155.xml
new file mode 100644
index 0000000000..b79e92a52c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ .5cm { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="5cm">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155a.xml
new file mode 100644
index 0000000000..3b3d43c809
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155a.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ .\5cm { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="5cm">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155b.xml
new file mode 100644
index 0000000000..d0f663ccfb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155b.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ .two\ words { background: red; }
+
+ /* the "." and "~=" forms match on a space separated list of words.
+ In such a list, a word containing a space can never match, since it
+ would by definition be two words. */
+
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="two words">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155c.xml
new file mode 100644
index 0000000000..85973ec96b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ .one.word { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="one.word">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155d.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155d.xml
new file mode 100644
index 0000000000..ca6ba51c7e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-155d.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ .one\.word { background: lime; }
+ p { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="one.word">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156.xml
new file mode 100644
index 0000000000..4717fb8a39
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ foo % address, p { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156b.xml
new file mode 100644
index 0000000000..28a6c985bb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156b.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ foo % address, p { background: red; }
+ p { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156c.xml
new file mode 100644
index 0000000000..cb888e1eb0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-156c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ foo % address, p { background: red ! important; }
+ p { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-157.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-157.xml
new file mode 100644
index 0000000000..037682791a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-157.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ [*=test] { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="test">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-158.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-158.xml
new file mode 100644
index 0000000000..5bb541dba2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-158.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ [*|*=test] { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p class="test">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-159.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-159.xml
new file mode 100644
index 0000000000..3504398dbc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-159.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing of new pseudo-elements</title>
+ <style type="text/css"><![CDATA[
+ ::selection { background: lime; }
+ :selection { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <p>Try selecting some text in this document. It should be have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15b.xml
new file mode 100644
index 0000000000..b22397ef54
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-15b.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Multiple ID selectors</title>
+ <style type="text/css"><![CDATA[
+p { background: green; color: white; }
+#test#fail { background: red; color: yellow; }
+#fail#test { background: red; color: yellow; }
+#fail { background: red; color: yellow; }
+div { background: red; color: yellow; }
+#pass#pass { background: green; color: white; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-background.xht"/>
+ </head>
+ <body>
+ <p id="test">This line should be green.</p>
+ <div id="pass">This line should be green.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-16.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-16.xml
new file mode 100644
index 0000000000..48122c26d8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-16.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:link pseudo-class</title>
+ <style type="text/css"><![CDATA[p.test a { background-color : red }
+p.test *:link { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" history" />
+ </head>
+ <body>
+<p class="test">
+<a href="http://unvisited.example.org/css3-modsel-16/">This link should have green background.</a>
+(Don&#39;t follow this link.)
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-160.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-160.xml
new file mode 100644
index 0000000000..f73a0ddd03
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-160.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing of unknown pseudo-classes</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ p:subject { background: red; } /* this is not valid CSS, and if UAs
+ implemented the experimental :subject pseudo-class they should have
+ used the :-vnd-ident syntax. */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-161.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-161.xml
new file mode 100644
index 0000000000..888c6f436b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-161.xml
@@ -0,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing of unknown pseudo-classes and pseudo-elements</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+ p * { background: lime; }
+ p > * { background: lime; }
+ p + * { background: lime; }
+ p ~ * { background: lime; }
+
+ /* let's try some pseudos that are not valid CSS but are likely to
+ be implemented as extensions in some UAs. These should not be
+ recognised, as UAs implementing such extensions should use the
+ :-vnd-ident syntax. */
+
+ :canvas { background: red; }
+ :viewport { background: red; }
+ :window { background: red; }
+ :menu { background: red; }
+ :table { background: red; }
+ :select { background: red; }
+ ::canvas { background: red; }
+ ::viewport { background: red; }
+ ::window { background: red; }
+ ::menu { background: red; }
+ ::table { background: red; }
+ ::select { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+ <p>
+ UAs may render the following element as a pop up menu. If so, please ensure the menu is unstyled (or green).
+ <select size="1">
+ <option>This should</option>
+ <option>have a green</option>
+ <option>background.</option>
+ </select>
+ </p>
+ <table><tr><td>This line should have a green background (or it might be unstyled).</td></tr></table>
+ <!-- only allowed to be unstyled if + and ~ are not supported -->
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166.xml
new file mode 100644
index 0000000000..f1d258dc37
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:first-letter with ::first-letter</title>
+ <style type="text/css"><![CDATA[
+ p:first-letter { background-color: red; }
+ p::first-letter { background-color: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p>The first letter of this paragraph should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166a.xml
new file mode 100644
index 0000000000..3ab4942e0d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-166a.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:first-letter with ::first-letter</title>
+ <style type="text/css"><![CDATA[
+ p::first-letter { background-color: red; }
+ p:first-letter { background-color: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p>The first letter of this paragraph should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167.xml
new file mode 100644
index 0000000000..2d86aafaa9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:first-line with ::first-line</title>
+ <style type="text/css"><![CDATA[
+ p:first-line { background-color: red; }
+ p::first-line { background-color: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p>The first line of this paragraph should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167a.xml
new file mode 100644
index 0000000000..d312fc2573
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-167a.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:first-line with ::first-line</title>
+ <style type="text/css"><![CDATA[
+ p::first-line { background-color: red; }
+ p:first-line { background-color: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p>The first line of this paragraph should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168.xml
new file mode 100644
index 0000000000..a0291aba94
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:before with ::before</title>
+ <style type="text/css"><![CDATA[
+ span:before { background-color: red; content: 'FAILED'; }
+ span::before { background-color: lime; content: 'PASSED'; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-test-has-passed-desc.xht"/>
+ </head>
+ <body>
+ <p>This test has <span></span>.</p>
+ <p>(If the previous line just reads &quot;This test has .&quot; then this test has failed.)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168a.xml
new file mode 100644
index 0000000000..7c008b02ce
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-168a.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:before with ::before</title>
+ <style type="text/css"><![CDATA[
+ span::before { background-color: red; content: 'FAILED'; }
+ span:before { background-color: lime; content: 'PASSED'; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-test-has-passed-desc.xht"/>
+ </head>
+ <body>
+ <p>This test has <span></span>.</p>
+ <p>(If the previous line just reads &quot;This test has .&quot; then this test has failed.)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169.xml
new file mode 100644
index 0000000000..ae6433cc04
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:after with ::after</title>
+ <style type="text/css"><![CDATA[
+ span:after { background-color: red; content: 'FAILED'; }
+ span::after { background-color: lime; content: 'PASSED'; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-test-has-passed-desc.xht"/>
+ </head>
+ <body>
+ <p>This test has <span></span>.</p>
+ <p>(If the previous line just reads &quot;This test has .&quot; then this test has failed.)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169a.xml
new file mode 100644
index 0000000000..1e2721ce0a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-169a.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:after with ::after</title>
+ <style type="text/css"><![CDATA[
+ span::after { background-color: red; content: 'FAILED'; }
+ span:after { background-color: lime; content: 'PASSED'; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-test-has-passed-desc.xht"/>
+ </head>
+ <body>
+ <p>This test has <span></span>.</p>
+ <p>(If the previous line just reads &quot;This test has .&quot; then this test has failed.)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-17.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-17.xml
new file mode 100644
index 0000000000..e06fb70d58
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-17.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:visited pseudo-class</title>
+ <style type="text/css"><![CDATA[p.test a { background-color : red }
+p.test *:visited { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" history" />
+ </head>
+ <body>
+<p class="test">
+<a href="http://www.w3.org/">You should see a green background assigned by the anchor.</a>
+(Note: You must have visited http://www.w3.org/ for this test to be valid.)
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170.xml
new file mode 100644
index 0000000000..94eab69ece
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Long chains of selectors</title>
+ <style type="text/css"><![CDATA[
+ span { color: red; }
+ span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span, span { color: green } /* 2049 */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p><span>This line should be green.</span></p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170a.xml
new file mode 100644
index 0000000000..f6a3b84c21
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170a.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Long chains of selectors</title>
+ <style type="text/css"><![CDATA[
+ .span { color: red; }
+ .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span, .span { color: green } /* 2049 */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p class="span">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170b.xml
new file mode 100644
index 0000000000..49915dc8f2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170b.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Long chains of selectors</title>
+ <style type="text/css"><![CDATA[
+ .span { color: red; }
+ .span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span.span { color: green } /* 2049 */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p class="span">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170c.xml
new file mode 100644
index 0000000000..4c9e105e92
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Long chains of selectors</title>
+ <style type="text/css"><![CDATA[
+ p.span { color: red; }
+ p:not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span):not(.span) { color: green } /* 2049 */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p>This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170d.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170d.xml
new file mode 100644
index 0000000000..12c6a2221e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-170d.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Long chains of selectors</title>
+ <style type="text/css"><![CDATA[
+ p { color: red; }
+ p:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child:first-child { color: green } /* 2049 */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p>This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-171.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-171.xml
new file mode 100644
index 0000000000..aa3b86e82f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-171.xml
@@ -0,0 +1,17 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Classes: XHTML global class attribute</title>
+ <style type="text/css"><![CDATA[
+ p { color: green; }
+ .fail { color: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <p xmlns:xhtml="http://www.w3.org/1999/xhtml">
+ <span xhtml:class="fail">This should be green.</span>
+ </p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172a.xml
new file mode 100644
index 0000000000..fca9c6d4b7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172a.xml
@@ -0,0 +1,30 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Namespaced attribute selectors</title>
+ <style type="text/css"><![CDATA[
+ tests, tests * { display: block; color: green; }
+ testA[|attribute] { color: red; }
+ testB[|attribute="fail"] { color: red; }
+ testC[|attribute~="fail"] { color: red; }
+ testD[|attribute^="fail"] { color: red; }
+ testE[|attribute*="fail"] { color: red; }
+ testF[|attribute$="fail"] { color: red; }
+ testG[|attribute|="fail"] { color: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/seven-green-divs.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <tests xmlns="http://css.example.net/" xmlns:test="http://css.example.net/">
+ <testA test:attribute="fail">This should be green.</testA>
+ <testB test:attribute="fail">This should be green.</testB>
+ <testC test:attribute="fail">This should be green.</testC>
+ <testD test:attribute="fail">This should be green.</testD>
+ <testE test:attribute="fail">This should be green.</testE>
+ <testF test:attribute="fail">This should be green.</testF>
+ <testG test:attribute="fail">This should be green.</testG>
+ </tests>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172b.xml
new file mode 100644
index 0000000000..ec93920fbb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-172b.xml
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Namespaced attribute selectors</title>
+ <style type="text/css"><![CDATA[
+ @namespace url(http://css.example.net/);
+ tests, tests * { display: block; color: green; }
+ testA[|attribute] { color: red; }
+ testB[|attribute="fail"] { color: red; }
+ testC[|attribute~="fail"] { color: red; }
+ testD[|attribute^="fail"] { color: red; }
+ testE[|attribute*="fail"] { color: red; }
+ testF[|attribute$="fail"] { color: red; }
+ testG[|attribute|="fail"] { color: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/seven-green-divs.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <tests xmlns="http://css.example.net/" xmlns:test="http://css.example.net/">
+ <testA test:attribute="fail">This should be green.</testA>
+ <testB test:attribute="fail">This should be green.</testB>
+ <testC test:attribute="fail">This should be green.</testC>
+ <testD test:attribute="fail">This should be green.</testD>
+ <testE test:attribute="fail">This should be green.</testE>
+ <testF test:attribute="fail">This should be green.</testF>
+ <testG test:attribute="fail">This should be green.</testG>
+ </tests>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173a.xml
new file mode 100644
index 0000000000..b75f8309c7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173a.xml
@@ -0,0 +1,30 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Namespaced attribute selectors</title>
+ <style type="text/css"><![CDATA[
+ tests, tests * { display: block; color: red; }
+ testA[*|attribute] { color: green; }
+ testB[*|attribute="pass"] { color: green; }
+ testC[*|attribute~="pass"] { color: green; }
+ testD[*|attribute^="pass"] { color: green; }
+ testE[*|attribute*="pass"] { color: green; }
+ testF[*|attribute$="pass"] { color: green; }
+ testG[*|attribute|="pass"] { color: green; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/seven-green-divs.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <tests xmlns="http://css.example.net/" xmlns:test="http://css.example.net/">
+ <testA test:attribute="pass">This should be green.</testA>
+ <testB test:attribute="pass">This should be green.</testB>
+ <testC test:attribute="pass">This should be green.</testC>
+ <testD test:attribute="pass">This should be green.</testD>
+ <testE test:attribute="pass">This should be green.</testE>
+ <testF test:attribute="pass">This should be green.</testF>
+ <testG test:attribute="pass">This should be green.</testG>
+ </tests>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173b.xml
new file mode 100644
index 0000000000..7769701a9b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-173b.xml
@@ -0,0 +1,30 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Namespaced attribute selectors</title>
+ <style type="text/css"><![CDATA[
+ tests, tests * { display: block; color: red; }
+ testA[*|attribute] { color: green; }
+ testB[*|attribute="pass"] { color: green; }
+ testC[*|attribute~="pass"] { color: green; }
+ testD[*|attribute^="pass"] { color: green; }
+ testE[*|attribute*="pass"] { color: green; }
+ testF[*|attribute$="pass"] { color: green; }
+ testG[*|attribute|="pass"] { color: green; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/seven-green-divs.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <tests xmlns="http://css.example.net/" xmlns:test="http://css.example.net/">
+ <testA attribute="pass">This should be green.</testA>
+ <testB attribute="pass">This should be green.</testB>
+ <testC attribute="pass">This should be green.</testC>
+ <testD attribute="pass">This should be green.</testD>
+ <testE attribute="pass">This should be green.</testE>
+ <testF attribute="pass">This should be green.</testF>
+ <testG attribute="pass">This should be green.</testG>
+ </tests>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174a.xml
new file mode 100644
index 0000000000..25e23c5272
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174a.xml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute selectors with multiple attributes</title>
+ <style type="text/css"><![CDATA[
+ tests, tests * { display: block; color: red; }
+ testA[*|attribute="pass"] { color: green; }
+ testB[*|attribute="pass"] { color: green; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <tests xmlns="http://css.example.net/" xmlns:test="http://css.example.net/">
+ <testA attribute="pass" test:attribute="fail">This should be green.</testA>
+ <testB attribute="fail" test:attribute="pass">This should be green.</testB>
+ </tests>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174b.xml
new file mode 100644
index 0000000000..3a4d0a5e3a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-174b.xml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute selectors with multiple attributes</title>
+ <style type="text/css"><![CDATA[
+ tests, tests * { display: block; color: green }
+ testA:not([*|attribute="pass"]) { color: red; }
+ testB:not([*|attribute="pass"]) { color: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <tests xmlns="http://css.example.net/" xmlns:test="http://css.example.net/">
+ <testA attribute="pass" test:attribute="fail">This should be green.</testA>
+ <testB attribute="fail" test:attribute="pass">This should be green.</testB>
+ </tests>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175a.xml
new file mode 100644
index 0000000000..ea4009e820
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175a.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Parsing: Numbers in classes</title>
+ <style type="text/css"><![CDATA[
+ p { color: green; }
+ .13 { color: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p class="13">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175b.xml
new file mode 100644
index 0000000000..52ff65696b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175b.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Parsing: Numbers in classes</title>
+ <style type="text/css"><![CDATA[
+ p { color: green; }
+ .\13 { color: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p class="13">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175c.xml
new file mode 100644
index 0000000000..9613473209
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-175c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Parsing: Numbers in classes</title>
+ <style type="text/css"><![CDATA[
+ p { color: red; }
+ .\31 \33 { color: green; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p class="13">This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-176.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-176.xml
new file mode 100644
index 0000000000..66c85b40f5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-176.xml
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Combinations: classes and IDs</title>
+ <style type="text/css"><![CDATA[
+p { background: red; color: yellow; }
+p:not(#other).class:not(.fail).test#id#id { background: green; color: white; }
+div { background: green; color: white; }
+div:not(#theid).class:not(.fail).test#theid#theid { background: red; color: yellow; }
+div:not(#other).notclass:not(.fail).test#theid#theid { background: red; color: yellow; }
+div:not(#other).class:not(.test).test#theid#theid { background: red; color: yellow; }
+div:not(#other).class:not(.fail).nottest#theid#theid { background: red; color: yellow; }
+div:not(#other).class:not(.fail).nottest#theid#other { background: red; color: yellow; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-background.xht"/>
+ </head>
+ <body>
+ <p id="id" class="class test">This line should be green.</p>
+ <div id="theid" class="class test">This line should be green.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177a.xml
new file mode 100644
index 0000000000..09ea141d64
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177a.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Parsing : vs ::</title>
+ <style type="text/css"><![CDATA[
+ p:selection { color: yellow; background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <p>When you select this text, it shouldn&#39;t go red.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177b.xml
new file mode 100644
index 0000000000..ecba2cde47
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-177b.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Parsing : vs ::</title>
+ <style type="text/css"><![CDATA[
+ div { color: green; }
+ p::first-child { color: yellow; background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <div>
+ <p>This line should be green.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-178.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-178.xml
new file mode 100644
index 0000000000..b3d59b6e17
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-178.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Parsing: :not and pseudo-elements</title>
+ <style type="text/css"><![CDATA[
+ div { color: green; }
+ p:not(:first-line) { color: yellow; background: red; }
+ p:not(:after) { color: yellow; background: red; content: ' THIS TEST HAS FAILED! '; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <div>
+ <p>This line should be green.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179.xml
new file mode 100644
index 0000000000..d63153c859
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-line on inlines</title>
+ <style type="text/css"><![CDATA[
+ p { color: green; }
+ span:first-line { background: red; color: yellow; font-size: 4em; }
+ span::first-line { background: red; color: yellow; font-size: 4em; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-green-color.xht"/>
+ </head>
+ <body>
+ <p><span>This line should be green.</span></p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179a.xml
new file mode 100644
index 0000000000..a1783fbc4a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-179a.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-line after &lt;br&gt;</title>
+ <style type="text/css"><![CDATA[
+ p { color: green; }
+ p:first-line { background: red; color: yellow; font-size: 4em; }
+ p::first-line { background: red; color: yellow; font-size: 4em; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p><br></br>This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18.xml
new file mode 100644
index 0000000000..97443c66cf
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18.xml
@@ -0,0 +1,61 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:hover pseudo-class</title>
+ <style type="text/css"><![CDATA[p:hover { background-color : lime }
+a:hover { background-color : lime }
+
+tr:hover { background-color : green }
+td:hover { background-color : lime }
+
+table { border-spacing: 5px; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p>The background color of this paragraph should turn to green when
+ the mouse pointer hovers either its text (<strong>here</strong>) or its whitespace background, <strong>here</strong>:</p>
+<address>The background color of <a href="#foo">this anchor (<strong>here</strong>)</a> should turn to green when the pointing device hovers over it.</address>
+<table>
+ <tbody>
+ <tr>
+ <td>The cells in</td>
+ <td>this table</td>
+ <td>should go</td>
+ </tr>
+ <tr>
+ <td>green when</td>
+ <td>you hover</td>
+ <td>the pointing</td>
+ </tr>
+ <tr>
+ <td>device over</td>
+ <td>them (<strong>here</strong>).</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>The rows in</td>
+ <td>this table</td>
+ <td>should go</td>
+ </tr>
+ <tr>
+ <td>dark green</td>
+ <td>when the</td>
+ <td>pointing device</td>
+ </tr>
+ <tr>
+ <td>is over the</td>
+ <td>cells <strong>there</strong>:</td>
+ <td></td> <!-- remove this cell to make an evil test; row should still go green, but cell should not -->
+ </tr>
+ <tr>
+ <td>And <strong>here</strong>:</td>
+ <td></td>
+ <td>(blank cells).</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-180a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-180a.xml
new file mode 100644
index 0000000000..d4bf31c619
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-180a.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-letter after &lt;br&gt;</title>
+ <style type="text/css"><![CDATA[
+ p { color: green; }
+ p:first-letter { background: red; color: yellow; font-size: 4em; }
+ p::first-letter { background: red; color: yellow; font-size: 4em; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p><br></br>This line should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-181.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-181.xml
new file mode 100644
index 0000000000..97fde125ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-181.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Case sensitivity</title>
+ <style type="text/css"><![CDATA[
+ .cs { color: green; }
+ .cs P { background: red; color: yellow; }
+ .cs .a { background: red; color: yellow; }
+ .cs .span1 span { background: red; color: yellow; }
+ .cs .span2 { color: red; }
+ .cs .span2 SPAN { color: green; }
+ .cs .span2 span { background: red; color: yellow; }
+ .ci { color: red; }
+ .ci P { background: green; color: white; }
+ .ci .a { background: green; color: white; }
+ .ci .span1 span { background: green; color: white; }
+ .ci .span2 SPAN { background: green; color: white; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>
+
+ <div class="cs">
+ <p>This line should be green.</p>
+ <p class="A">This line should be green.</p>
+ <p class="span1"><SPAN>This line should be green.</SPAN></p>
+ <p class="span2"><SPAN>This line should be green.</SPAN></p>
+ </div>
+
+
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-182.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-182.xml
new file mode 100644
index 0000000000..293c11b780
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-182.xml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Namespaces and \: in selectors</title>
+ <style type="text/css"><![CDATA[
+p { color: green; }
+foo\:bar { background: red; color: yellow; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<p>
+<foo:bar xmlns:foo="http://www.example.org/">
+This text should be green.
+</foo:bar>
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-183.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-183.xml
new file mode 100644
index 0000000000..022df8f118
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-183.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Syntax and parsing of class selectors</title>
+ <style type="text/css"><![CDATA[
+p { color: green; }
+..test { background: red; color: yellow; }
+.foo..quux { background: red; color: yellow; }
+.bar. { background: red; color: yellow; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p class="test">This text should be green.</p>
+<p class=".test">This text should be green.</p>
+<p class="foo">This text should be green.</p>
+<p class="foo quux">This text should be green.</p>
+<p class="foo quux">This text should be green.</p>
+<p class=" bar ">This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184-ref.xht b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184-ref.xht
new file mode 100644
index 0000000000..8ffc002f9b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184-ref.xht
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Ref: Two lime lines</title>
+ <style type="text/css">
+ p { color: lime; }
+ </style>
+ </head>
+ <body>
+ <p>This text should be green.</p>
+ <p>This text should be green.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184a.xml
new file mode 100644
index 0000000000..427fca4ec7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184a.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Ends-with attribute selector with empty value</title>
+ <style type="text/css"><![CDATA[
+p { color: lime; }
+p[class$=""] { color: red; }
+]]></style>
+ <link rel="author" title="Lachlan Hunt" href="http://lachy.id.au/about/contact"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="css3-modsel-184-ref.xht"/>
+ </head>
+ <body>
+<p class="">This text should be green.</p>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184b.xml
new file mode 100644
index 0000000000..eafd50fabc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184b.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Starts-with attribute selector with empty value</title>
+ <style type="text/css"><![CDATA[
+p { color: lime; }
+p[class^=""] { color: red; }
+]]></style>
+ <link rel="author" title="Lachlan Hunt" href="http://lachy.id.au/about/contact"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="css3-modsel-184-ref.xht"/>
+ </head>
+ <body>
+<p class="">This text should be green.</p>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184c.xml
new file mode 100644
index 0000000000..75ce2fd2b5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184c.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Contains attribute selector with empty value</title>
+ <style type="text/css"><![CDATA[
+p { color: lime; }
+p[class*=""] { color: red; }
+]]></style>
+ <link rel="author" title="Lachlan Hunt" href="http://lachy.id.au/about/contact"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="css3-modsel-184-ref.xht"/>
+ </head>
+ <body>
+<p class="">This text should be green.</p>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184d.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184d.xml
new file mode 100644
index 0000000000..5115ddf03a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184d.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED ends-with attribute selector with empty value</title>
+ <style type="text/css"><![CDATA[
+p { color: red; }
+p:not([class$=""]) { color: lime; }
+]]></style>
+ <link rel="author" title="Lachlan Hunt" href="http://lachy.id.au/about/contact"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="css3-modsel-184-ref.xht"/>
+ </head>
+ <body>
+<p class="">This text should be green.</p>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184e.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184e.xml
new file mode 100644
index 0000000000..bb455da782
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184e.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED starts-with attribute selector with empty value</title>
+ <style type="text/css"><![CDATA[
+p { color: red; }
+p:not([class^=""]) { color: lime; }
+]]></style>
+ <link rel="author" title="Lachlan Hunt" href="http://lachy.id.au/about/contact"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="css3-modsel-184-ref.xht"/>
+ </head>
+ <body>
+<p class="">This text should be green.</p>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184f.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184f.xml
new file mode 100644
index 0000000000..7c939c31f5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-184f.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED contains attribute selector with empty value</title>
+ <style type="text/css"><![CDATA[
+p { color: red; }
+p:not([class*=""]) { color: lime; }
+]]></style>
+ <link rel="author" title="Lachlan Hunt" href="http://lachy.id.au/about/contact"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="css3-modsel-184-ref.xht"/>
+ </head>
+ <body>
+<p class="">This text should be green.</p>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18a.xml
new file mode 100644
index 0000000000..da5d12dc88
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18a.xml
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:hover pseudo-class on links</title>
+ <style type="text/css"><![CDATA[
+p { color: navy; }
+
+.a a:hover { background: green; color: white; }
+
+.b a:hover { background: red; color: yellow; }
+.b a:link { background: green; color: white; }
+
+.c :link { background: green; color: white; }
+.c :visited:hover { background: red; color: yellow; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p class="a">The background color of <a href="#foo">this anchor (<strong>here</strong>)</a> should turn to green when the pointing device hovers over it.</p>
+<p class="b">The background color of <a href="#foo">this anchor (<strong>here</strong>)</a> should <strong>remain green when you hover it</strong>.</p>
+<p class="c">The background color of <a href="http://link.example.com/">this anchor (<strong>here</strong>)</a> should <strong>remain green when the pointing device hovers over it</strong> (do not follow that link).</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18b.xml
new file mode 100644
index 0000000000..b8dc445f98
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18b.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:hover pseudo-class</title>
+ <style type="text/css"><![CDATA[div:hover > p:first-child { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <div>
+ <p>The background color of this paragraph should turn to green when the mouse pointer hovers over any of the following:<br></br><strong>This text.</strong></p>
+ <p>This text.</p>
+ <table><tr><td><table><tr><td><dl><dt>This text.</dt><dd>This text.</dd></dl></td></tr></table></td></tr><tr><td>This text.</td></tr></table>
+ <p><sub>This text.</sub></p>
+ <p>...and anything else between the top of the first paragraph and the bottom of this paragraph.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18c.xml
new file mode 100644
index 0000000000..77fba265b9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-18c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:hover pseudo-class on links</title>
+ <style type="text/css"><![CDATA[
+:link, :visited { color: navy; text-decoration: none; }
+:link:hover span { background-color : lime }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <p><a href="#foo">Hover <strong>here</strong> and the background of <span>this text should go green</span>.</a></p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19.xml
new file mode 100644
index 0000000000..79f23a5084
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:active pseudo-class</title>
+ <style type="text/css"><![CDATA[a:active { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p>The background color of <a href="#foo">the anchor</a>
+ should turn to green when it is activated and come back to
+ normal when it is released.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19b.xml
new file mode 100644
index 0000000000..48ae456ca3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-19b.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:active pseudo-class on controls</title>
+ <style type="text/css"><![CDATA[button:active { background: green; color: white; }]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p><button>Activating (e.g. holding the mouse button down on) this button should make it go green.</button></p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-2.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-2.xml
new file mode 100644
index 0000000000..895fea32c9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-2.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Type element selectors</title>
+ <style type="text/css"><![CDATA[address { background-color: lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<address>This address element should have a green background.</address>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-20.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-20.xml
new file mode 100644
index 0000000000..7d1288c9f2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-20.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:focus pseudo-class</title>
+ <style type="text/css"><![CDATA[a:focus { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p>The background color of <a href="#foo">anchors</a>
+ in this page should turn <a href="#foo">to green</a> when they have the
+ <a href="#foo">focus</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21.xml
new file mode 100644
index 0000000000..5c53092247
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21.xml
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:target pseudo-class</title>
+ <style type="text/css"><![CDATA[p:target { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p id="first">This paragraph should be unstyled.
+ The background of the following paragraph should become green when
+ you follow <a href="#second">this link</a>.</p>
+<p id="second">This paragraph should initially be unstyled.
+ It should become green when you select the link above. When you select
+ <a href="#third">this link</a>, it should return to being unstyled and the
+ background of the paragraph below should become green.</p>
+<p id="third">This paragraph should initially be unstyled.
+ It should become green when you select the link above. When you follow
+ <a href="#missing">this link</a>, the three paragraphs
+ should all return to being unstyled.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21b.xml
new file mode 100644
index 0000000000..3274ade1d3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21b.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:target pseudo-class</title>
+ <style type="text/css"><![CDATA[p { background-color: lime; }
+p:target { background-color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p>This paragraph should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21c.xml
new file mode 100644
index 0000000000..18b5cf1900
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-21c.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:target pseudo-class</title>
+ <style type="text/css"><![CDATA[:root { background-color: green; }
+:target { background-color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p>This page should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-22.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-22.xml
new file mode 100644
index 0000000000..bc813519d4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-22.xml
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:lang() pseudo-class</title>
+ <style type="text/css"><![CDATA[ul > li { background-color : red }
+li:lang(en-GB) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li lang="en-GB">This list item should be green because its language is
+ British English</li>
+ <li lang="en-GB-wa">This list item should be green because its language
+ is British English (Wales)</li>
+</ul>
+<ol>
+ <li lang="en-US">This list item should NOT be green because its language
+ is US English</li>
+ <li lang="fr">This list item should NOT be green because its language is
+ French</li>
+</ol>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-25.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-25.xml
new file mode 100644
index 0000000000..450e4bd30b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-25.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:checked pseudo-class</title>
+ <style type="text/css"><![CDATA[input, span { background-color : red }
+input:checked, input:checked + span { background-color : lime}
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>
+<input type="checkbox" checked="checked"></input> <span>Everything in this paragraph should have a green background</span></p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27.xml
new file mode 100644
index 0000000000..38813e16c7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:root pseudo-class</title>
+ <style type="text/css"><![CDATA[html { background-color : red }
+*:root { background-color: lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>The background of the document should be green</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27a.xml
new file mode 100644
index 0000000000..ac5655bff4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27a.xml
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Impossible rules (:root:first-child, etc)</title>
+ <style type="text/css"><![CDATA[
+:root:first-child { background-color: red; }
+:root:last-child { background-color: red; }
+:root:only-child { background-color: red; }
+:root:nth-child(1) { background-color: red; }
+:root:nth-child(n) { background-color: red; }
+:root:nth-last-child(1) { background-color: red; }
+:root:nth-last-child(n) { background-color: red; }
+:root:first-of-type { background-color: red; }
+:root:last-of-type { background-color: red; }
+:root:only-of-type { background-color: red; }
+:root:nth-of-type(1) { background-color: red; }
+:root:nth-of-type(n) { background-color: red; }
+:root:nth-last-of-type(1) { background-color: red; }
+:root:nth-last-of-type(n) { background-color: red; }
+p { color: green; }]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This line should be green (there should be no red on this page).</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27b.xml
new file mode 100644
index 0000000000..1f40e3ccab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-27b.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Impossible rules (* html, * :root)</title>
+ <style type="text/css"><![CDATA[* html { background-color: red; }
+* :root { background-color: red; }
+p { color: green; }]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This line should be green (there should be no red on this page).</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28.xml
new file mode 100644
index 0000000000..c98caaa791
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28.xml
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+ul > li:nth-child(odd) { background-color : lime }
+ol > li:nth-child(even) { background-color : lime }
+table.t1 tr:nth-child(-n+4) { background-color : lime }
+table.t2 td:nth-child(3n+1) { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li class="red">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="red">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="red">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ul>
+<ol>
+ <li>First list item</li>
+ <li class="red">This second list item should have a green background</li>
+ <li>Third list item</li>
+ <li class="red">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="red">This sixth list item should have a green background</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr class="red">
+<td>Green row : 1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr>
+<td>5.1</td>
+<td>5.2</td>
+<td>5.3</td>
+</tr>
+ <tr>
+<td>6.1</td>
+<td>6.2</td>
+<td>6.3</td>
+</tr>
+</table>
+
+<table class="t2" border="1">
+ <tr>
+<td class="red">green cell</td>
+<td>1.2</td>
+<td>1.3</td>
+ <td class="red">green cell</td>
+<td>1.5</td>
+<td>1.6</td>
+ <td class="red">green cell</td>
+<td>1.8</td>
+</tr>
+ <tr>
+<td class="red">green cell</td>
+<td>2.2</td>
+<td>2.3</td>
+ <td class="red">green cell</td>
+<td>2.5</td>
+<td>2.6</td>
+ <td class="red">green cell</td>
+<td>2.8</td>
+</tr>
+ <tr>
+<td class="red">green cell</td>
+<td>3.2</td>
+<td>3.3</td>
+ <td class="red">green cell</td>
+<td>3.5</td>
+<td>3.6</td>
+ <td class="red">green cell</td>
+<td>3.8</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28b.xml
new file mode 100644
index 0000000000..f1af5fd150
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-28b.xml
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+ul > li:nth-child(odd) { background-color : red }
+ol > li:nth-child(even) { background-color : red }
+table.t1 tr:nth-child(-n+4) { background-color : red }
+table.t2 td:nth-child(3n+1) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li class="green">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="green">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="green">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ul>
+<ol>
+ <li>First list item</li>
+ <li class="green">This second list item should have a green background</li>
+ <li>Third list item</li>
+ <li class="green">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="green">This sixth list item should have a green background</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr class="green">
+<td>Green row : 1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr>
+<td>5.1</td>
+<td>5.2</td>
+<td>5.3</td>
+</tr>
+ <tr>
+<td>6.1</td>
+<td>6.2</td>
+<td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td class="green">green cell</td>
+<td>1.2</td>
+<td>1.3</td>
+ <td class="green">green cell</td>
+<td>1.5</td>
+<td>1.6</td>
+ <td class="green">green cell</td>
+<td>1.8</td>
+</tr>
+ <tr>
+<td class="green">green cell</td>
+<td>2.2</td>
+<td>2.3</td>
+ <td class="green">green cell</td>
+<td>2.5</td>
+<td>2.6</td>
+ <td class="green">green cell</td>
+<td>2.8</td>
+</tr>
+ <tr>
+<td class="green">green cell</td>
+<td>3.2</td>
+<td>3.3</td>
+ <td class="green">green cell</td>
+<td>3.5</td>
+<td>3.6</td>
+ <td class="green">green cell</td>
+<td>3.8</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29.xml
new file mode 100644
index 0000000000..372dbfa5db
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29.xml
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-last-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+ul > li:nth-last-child(odd) { background-color : green }
+ol > li:nth-last-child(even) { background-color : green }
+table.t1 tr:nth-last-child(-n+4) { background-color : green }
+table.t2 td:nth-last-child(3n+1) { background-color : green }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li>First list item</li>
+ <li class="red">This second list item should have a green background</li>
+ <li>Third list item</li>
+ <li class="red">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="red">This sixth list item should have a green background</li>
+</ul>
+<ol>
+ <li class="red">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="red">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="red">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr>
+<td>1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 5.1</td>
+<td>5.2</td>
+ <td>5.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 6.1</td>
+<td>6.2</td>
+ <td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td>1.1</td>
+<td class="red">green cell</td>
+<td>1.3</td>
+ <td>1.4</td>
+<td class="red">green cell</td>
+<td>1.6</td>
+ <td>1.7</td>
+<td class="red">green cell</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td class="red">green cell</td>
+<td>2.3</td>
+ <td>2.4</td>
+<td class="red">green cell</td>
+<td>2.6</td>
+ <td>2.7</td>
+<td class="red">green cell</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td class="red">green cell</td>
+<td>3.3</td>
+ <td>3.4</td>
+<td class="red">green cell</td>
+<td>3.6</td>
+ <td>3.7</td>
+<td class="red">green cell</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29b.xml
new file mode 100644
index 0000000000..0d88b4cc08
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-29b.xml
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-last-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+ul > li:nth-last-child(odd) { background-color : red }
+ol > li:nth-last-child(even) { background-color : red }
+table.t1 tr:nth-last-child(-n+4) { background-color : red }
+table.t2 td:nth-last-child(3n+1) { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li>First list item</li>
+ <li class="green">This second list item should have a green background</li>
+ <li>Third list item</li>
+ <li class="green">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="green">This sixth list item should have a green background</li>
+</ul>
+<ol>
+ <li class="green">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="green">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="green">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr>
+<td>1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 5.1</td>
+<td>5.2</td>
+ <td>5.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 6.1</td>
+<td>6.2</td>
+ <td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td>1.1</td>
+<td class="green">green cell</td>
+<td>1.3</td>
+ <td>1.4</td>
+<td class="green">green cell</td>
+<td>1.6</td>
+ <td>1.7</td>
+<td class="green">green cell</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td class="green">green cell</td>
+<td>2.3</td>
+ <td>2.4</td>
+<td class="green">green cell</td>
+<td>2.6</td>
+ <td>2.7</td>
+<td class="green">green cell</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td class="green">green cell</td>
+<td>3.3</td>
+ <td>3.4</td>
+<td class="green">green cell</td>
+<td>3.6</td>
+ <td>3.7</td>
+<td class="green">green cell</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3.xml
new file mode 100644
index 0000000000..7bcc09b947
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector</title>
+ <style type="text/css"><![CDATA[* { color : lime }
+ul, p { color : red }
+*.t1 { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<p>
+<span class="t1">This paragraph, and all textual contents in the document,
+ should be green.</span>
+</p>
+<ul>
+ <li class="t1">This item should be green.</li>
+</ul>
+<foo xmlns="http://www.example.org/a">And this element, part of a non-HTML namespace,
+ should be green too</foo>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-30.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-30.xml
new file mode 100644
index 0000000000..61194a07df
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-30.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-of-type() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+p:nth-of-type(3) { background-color : lime }
+dl > :nth-of-type(3n+1) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This paragraph is here only to fill space in the DOM</p>
+<address>And this address too..</address>
+<p>So does this paragraph !</p>
+<p class="red">But this one should have green background</p>
+<dl>
+ <dt class="red">First definition term that should have green background</dt>
+ <dd class="red">First definition that should have green background</dd>
+ <dt>Second definition term</dt>
+ <dd>Second definition</dd>
+ <dt>Third definition term</dt>
+ <dd>Third definition</dd>
+ <dt class="red">Fourth definition term that should have green background</dt>
+ <dd class="red">Fourth definition that should have green background</dd>
+ <dt>Fifth definition term</dt>
+ <dd>Fifth definition</dd>
+ <dt>Sixth definition term</dt>
+ <dd>Sixth definition</dd>
+</dl>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-31.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-31.xml
new file mode 100644
index 0000000000..da51455b1f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-31.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:nth-last-of-type() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+p:nth-last-of-type(3) { background-color : lime }
+dl > :nth-last-of-type(3n+1) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p class="red">This paragraph should have green background</p>
+<address>But this address is here only to fill space in the dom..</address>
+<p>So does this paragraph !</p>
+<p>And so does this one too.</p>
+<dl>
+ <dt>First definition term</dt>
+ <dd>First definition</dd>
+ <dt>Second definition term</dt>
+ <dd>Second definition</dd>
+ <dt class="red">Third definition term that should have green background</dt>
+ <dd class="red">Third definition that should have green background</dd>
+ <dt>Fourth definition term</dt>
+ <dd>Fourth definition</dd>
+ <dt>Fifth definition term</dt>
+ <dd>Fifth definition</dd>
+ <dt class="red">Sixth definition term that should have green background</dt>
+ <dd class="red">Sixth definition that should have green background</dd>
+</dl>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-32.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-32.xml
new file mode 100644
index 0000000000..3ccffc6747
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-32.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:first-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+.t1 td:first-child { background-color : lime }
+p > *:first-child { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>
+<table class="t1" border="1">
+ <tr>
+ <td class="red">green cell</td>
+ <td>1.2</td>
+ <td>1.3</td>
+ </tr>
+ <tr>
+ <td class="red">green cell</td>
+ <td>2.2</td>
+ <td>2.3</td>
+ </tr>
+ <tr>
+ <td class="red">green cell</td>
+ <td>3.2</td>
+ <td>3.3</td>
+ </tr>
+</table>
+</div>
+<p>This paragraph contains some text
+ <span>and a span that should have a green background</span>
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-33.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-33.xml
new file mode 100644
index 0000000000..f93992be2e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-33.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:last-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+.t1 td:last-child { background-color : lime }
+p > *:last-child { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>
+<table class="t1" border="1">
+ <tr>
+ <td>1.1</td>
+ <td>1.2</td>
+ <td class="red">green cell</td>
+ </tr>
+ <tr>
+ <td>2.1</td>
+ <td>2.2</td>
+ <td class="red">green cell</td>
+ </tr>
+ <tr>
+ <td>3.1</td>
+ <td>3.2</td>
+ <td class="red">green cell</td>
+ </tr>
+</table>
+</div>
+<p>
+<span>This paragraph contains a span that should
+ have a green background</span> and some text after it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-34.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-34.xml
new file mode 100644
index 0000000000..1323ec7b48
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-34.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:first-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+address { margin-bottom : 1em ; margin-left : 1em }
+address:first-of-type { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>This div contains 3 addresses:
+<address class="red">A first address that should have a green background</address>
+<address>A second address with normal background</address>
+<address>A third address with normal background</address>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-35.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-35.xml
new file mode 100644
index 0000000000..7d0437d8ef
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-35.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:last-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+address { margin-bottom : 1em ; margin-left : 1em }
+address:last-of-type { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>
+<address>A first address with normal background</address>
+<address>A second address with normal background</address>
+<address class="red">A third address that should have a green background</address>
+This div contains 3 addresses above this sentence.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-36.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-36.xml
new file mode 100644
index 0000000000..7790d0a5a7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-36.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:only-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+p:only-child { background-color : lime }
+div.testText > div > p { margin-left : 1em }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This paragraph should have normal background</p>
+<div>This div contains only one paragraph
+ <p class="red">This paragraph should have green background</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-37.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-37.xml
new file mode 100644
index 0000000000..5684926083
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-37.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:only-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+.t1 :only-of-type { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div class="t1">
+<p>This paragraph should have normal background</p>
+<address class="red">But this address should have green background</address>
+<p>This paragraph should have normal background</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-38.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-38.xml
new file mode 100644
index 0000000000..f44abe1584
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-38.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-line pseudo-element</title>
+ <style type="text/css"><![CDATA[p:first-line { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This very long paragraph should have a
+ first line with green background. This very long paragraph should have a first
+ line with green background. This very long paragraph should have a first line
+ with green background. This very long paragraph should have a first line with
+ green background. This very long paragraph should have a first line with green
+ background. This very long paragraph should have a first line with green background.
+ This very long paragraph should have a first line with green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39.xml
new file mode 100644
index 0000000000..20cbcfd361
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-letter pseudo-element</title>
+ <style type="text/css"><![CDATA[p:first-letter { font-size : xx-large ; background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+
+<p>This very long paragraph
+should have a big first letter T with a green background. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39a.xml
new file mode 100644
index 0000000000..13a7386313
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39a.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-letter pseudo-element with ::before pseudo-element</title>
+ <style type="text/css"><![CDATA[p:first-letter { color: lime; font-size: xx-large; }
+p:before { color: red; content: 'T'; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+
+<p>his very long paragraph should
+have a big green first letter T. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39b.xml
new file mode 100644
index 0000000000..30fce57ea5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39b.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-letter pseudo-element</title>
+ <style type="text/css"><![CDATA[p::first-letter { font-size : xx-large ; background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+
+<p>This very long paragraph
+should have a big first letter T with a green background. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39c.xml
new file mode 100644
index 0000000000..8f61f5cb8b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-39c.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::first-letter pseudo-element with ::before pseudo-element</title>
+ <style type="text/css"><![CDATA[p::first-letter { color: lime; font-size: xx-large; }
+ p::before { color: red; content: 'T'; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+
+<p>his very long paragraph should
+have a big green first letter T. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text. Dummy text. Dummy
+text. Dummy text. Dummy text. Dummy text.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3a.xml
new file mode 100644
index 0000000000..7c2acd2f9f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-3a.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector (no namespaces)</title>
+ <style type="text/css"><![CDATA[* { color : lime }
+ul, p { color : red }
+*.t1 { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>
+<span class="t1">This paragraph, and all textual contents in the document,
+ should be green.</span>
+</p>
+<ul>
+ <li class="t1">This item should be green.</li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-4.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-4.xml
new file mode 100644
index 0000000000..1e096db55a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-4.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Omitted universal selector</title>
+ <style type="text/css"><![CDATA[#foo { background-color : lime }
+p { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p id="foo">This paragraph should have a green background</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41.xml
new file mode 100644
index 0000000000..b8e031f902
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::before pseudo-element</title>
+ <style type="text/css"><![CDATA[p::before { background-color : lime ; content : "GENERATED CONTENT "}
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>You should see before this paragraph the words GENERATED CONTENT over green background</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41a.xml
new file mode 100644
index 0000000000..653cfc82ba
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-41a.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:before pseudo-element</title>
+ <style type="text/css"><![CDATA[p:before { background-color : lime ; content : "GENERATED CONTENT "}
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>You should see before this paragraph the words GENERATED CONTENT over green background</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42.xml
new file mode 100644
index 0000000000..4221b1a04a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>::after pseudo-element</title>
+ <style type="text/css"><![CDATA[p::after { background-color : lime ; content : "GENERATED CONTENT "}
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>You should see after this paragraph the words GENERATED CONTENT over green background</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42a.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42a.xml
new file mode 100644
index 0000000000..5499b3f2ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-42a.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>:after pseudo-element</title>
+ <style type="text/css"><![CDATA[p:after { background-color : lime ; content : "GENERATED CONTENT "}
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>You should see after this paragraph the words GENERATED CONTENT over green background</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43.xml
new file mode 100644
index 0000000000..62075b35d7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Descendant combinator</title>
+ <style type="text/css"><![CDATA[.white { background-color: transparent ! important; }
+.red { background-color: red; }
+div.t1 p { background-color: lime; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div class="t1">
+ <p class="red">This paragraph should have a green background</p>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <p class="red">This paragraph should have a green background</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <p class="white">This paragraph should be unstyled.</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43b.xml
new file mode 100644
index 0000000000..e47f816397
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-43b.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Descendant combinator</title>
+ <style type="text/css"><![CDATA[.white { background-color: transparent ! important; }
+.green { background-color: lime; }
+div.t1 p { background-color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div class="t1">
+ <p class="white">This paragraph should be unstyled</p>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <p class="white">This paragraph should be unstyled</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <p class="green">This paragraph should have a green background</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44.xml
new file mode 100644
index 0000000000..2706b95604
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Child combinator</title>
+ <style type="text/css"><![CDATA[.white { background-color: transparent ! important; }
+.red { background-color: red; }
+div > p.test { background-color: lime; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <p class="red test">This paragraph should have a green background</p>
+ <div>
+ <p class="red test">This paragraph should have a green background</p>
+ </div>
+ </div>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <p class="white test">This paragraph should be unstyled.</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44b.xml
new file mode 100644
index 0000000000..fa4549b9b4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44b.xml
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Child combinator</title>
+ <style type="text/css"><![CDATA[.white { background-color: transparent ! important; }
+.green { background-color: lime; }
+div > p.test { background-color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <p class="white test">This paragraph should be unstyled.</p>
+ <div>
+ <p class="white test">This paragraph should be unstyled.</p>
+ </div>
+ </div>
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <p class="green test">This paragraph should have a green background.</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44c.xml
new file mode 100644
index 0000000000..b147a74e35
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Child combinator and classes</title>
+ <style type="text/css"><![CDATA[
+ .fail > div { background: red; color: yellow; }
+ .control { background: green; color: white; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div> This should be unstyled. </div>
+ <div class="control"> This should have a green background. </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44d.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44d.xml
new file mode 100644
index 0000000000..9f0fa3ab0f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-44d.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Child combinatior and IDs</title>
+ <style type="text/css"><![CDATA[
+ #fail > div { background: red; }
+ p { background: green; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div> This should be unstyled. </div>
+ <p> This should have a green background. </p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45.xml
new file mode 100644
index 0000000000..e5f97e6582
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Direct adjacent combinator</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+div.stub > p + p { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div class="stub">
+ <p>This paragraph should be unstyled.</p>
+ <p class="red">But this one should have a green background.</p>
+ <p class="red">And this one should also have a green background.</p>
+ <address>This address is only here to fill some space between two paragraphs.</address>
+ <p>This paragraph should be unstyled.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45b.xml
new file mode 100644
index 0000000000..ac7f81d08e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45b.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Direct adjacent combinator</title>
+ <style type="text/css"><![CDATA[.green { background-color: lime; }
+.white { background-color: transparent ! important; }
+div.stub > p + p { background-color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div class="stub">
+ <p class="green">This paragraph should have a green background.</p>
+ <p class="white">But this one should be unstyled.</p>
+ <p class="white">And this one should also be unstyled.</p>
+ <address class="green">This address is only here to fill some space between two paragraphs and should have a green background.</address>
+ <p class="green">This paragraph should have a green background too.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45c.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45c.xml
new file mode 100644
index 0000000000..cd1aa714b0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-45c.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Direct adjacent combinator and classes</title>
+ <style type="text/css"><![CDATA[
+ .fail + div { background: red; }
+ .control { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div> This should be unstyled. </div>
+ <div class="control"> This should have a green background. </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46.xml
new file mode 100644
index 0000000000..08919fdc67
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Indirect adjacent combinator</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+div.stub > p ~ p { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div class="stub">
+ <p>This paragraph should be unstyled.</p>
+ <p class="red">But this one should have a green background</p>
+ <p class="red">And this one should also have a green background</p>
+ <address>This address is only here to fill some space between two paragraphs</address>
+ <p class="red">This paragraph should have a green background</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46b.xml
new file mode 100644
index 0000000000..c22a74e704
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-46b.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Indirect adjacent combinator</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+div.stub > p ~ p { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div class="stub">
+ <p>This paragraph should be unstyled.</p>
+ <p class="green">But this one should have a green background</p>
+ <p class="green">And this one should also have a green background</p>
+ <address>This address is only here to fill some space between two paragraphs</address>
+ <p class="green">This paragraph should have a green background</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-47.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-47.xml
new file mode 100644
index 0000000000..320490f211
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-47.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED type element selector</title>
+ <style type="text/css"><![CDATA[div.stub span, div.stub address, div.stub *|q, div.stub *|r { background-color: red; }
+address, *|q, *|r { display: block; margin: 1em; }
+div.stub *:not(p) { background-color: lime; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <div class="stub">
+ <p>
+ <span>The text in this paragraph should have a green background</span>
+ </p>
+ <address>This address should have a green background</address>
+ <q xmlns="http://www.example.org/a">This element in another namespace should have a green background.</q>
+ <r xmlns="">This element without a namespace should have a green background.</r>
+ <p>This paragraph should be unstyled.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-48.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-48.xml
new file mode 100644
index 0000000000..51484c8eac
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-48.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED universal selector</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > *|* { background-color : lime ; display : block ;
+ margin-bottom : 1em }
+div.stub > *|*:not(*) { background-color : red }
+/* yes, the rule just above selects nothing... That's the point */
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-address-p-p-p-lime-background.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<address>This address should have a green background</address>
+<s xmlns="http://www.example.org/b">This paragraph should have a green background</s>
+<t xmlns="">This paragraph should have a green background</t>
+<u xmlns="http://www.example.org/a">This paragraph should have a green background</u>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-49.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-49.xml
new file mode 100644
index 0000000000..40aa8315ce
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-49.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED omitted universal selector is forbidden</title>
+ <style type="text/css"><![CDATA[@namespace html url(http://www.w3.org/1999/xhtml);
+@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub > *|* { background-color : lime ; display : block ;
+ margin-bottom : 1em }
+div.stub > *|*:not() { background-color : red }
+/* yes, the rule just above selects nothing... That's the point */
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-address-p-p-p-lime-background.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<address>This address should have a green background</address>
+<s xmlns="http://www.example.org/b">This paragraph should have a green background</s>
+<t xmlns="">This paragraph should have a green background</t>
+<u xmlns="http://www.example.org/a">This paragraph should have a green background</u>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-5.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-5.xml
new file mode 100644
index 0000000000..5ef9f9980e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-5.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p[title] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p title="title">This paragraph should have a green background because its TITLE
+ attribute is set.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-50.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-50.xml
new file mode 100644
index 0000000000..7b81eaec82
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-50.xml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED attribute existence selector</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+a|* { color : red ; display : block ; margin-bottom : 1em }
+div.stub *|*:not([test]) { color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<q xmlns="http://www.example.org/a" test="1">
+ <r>This text should be in green characters</r>
+</q>
+<s xmlns="http://www.example.org/a">This text should be in green characters</s>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-51.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-51.xml
new file mode 100644
index 0000000000..327bdca14d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-51.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED attribute value selector</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+div.stub > p {color : red }
+div.stub > a|* { color : red ; display : block ; margin-bottom : 1em }
+div.stub *|*:not([test="1"]) { color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<q xmlns="http://www.example.org/a" test="1">
+ <r test="11">This text should be</r>
+ <r>in green characters</r>
+</q>
+<s xmlns="http://www.example.org/a">This text should be in green characters</s>
+<p>This text should be in green characters</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-52.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-52.xml
new file mode 100644
index 0000000000..3320e3d2c0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-52.xml
@@ -0,0 +1,28 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED attribute space-separated value selector</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub p { color : red }
+div.stub > a|*, div.stub > b|* { color : red ; display : block ; margin-bottom : 1em }
+div.stub *|*:not([test~="foo"]) { color : lime }
+div.stub *|p:not([class~="foo"]) { color : lime }
+div.stub b|*[test~="foo2"] { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<q xmlns="http://www.example.org/a" test="bar foo tut">
+ <r test="tut foofoo bar">This text should be</r>
+ <r>in green characters</r>
+</q>
+<s xmlns="http://www.example.org/a" test="bar tut">This text should be in green characters</s>
+<t xmlns="http://www.example.org/a">This text should be in green characters</t>
+<p class="tit foo1 tut">This text should be in green characters</p>
+<u xmlns="http://www.example.org/b" test="tit foo2 tut">This text should be in green characters</u>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-53.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-53.xml
new file mode 100644
index 0000000000..bb9118688b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-53.xml
@@ -0,0 +1,28 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED attribute dash-separated value selector</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.stub p { color : red }
+div.stub > a|*, div.stub > b|* { color : red ; display : block ; margin-bottom : 1em }
+div.stub *|*:not([test|="foo-bar"]) { color : lime }
+div.stub *|p:not([lang|="en-us"]) { color : lime }
+div.stub b|*[test|="foo2-bar"] { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="stub">
+<q xmlns="http://www.example.org/a" test="foo-bar">
+ <r test="foo-bartut">This text should be</r>
+ <r>in green characters</r>
+</q>
+<s xmlns="http://www.example.org/a" test="bar tut">This text should be in green characters</s>
+<t xmlns="http://www.example.org/a">This text should be in green characters</t>
+<p class="en-uk">This text should be in green characters</p>
+<u xmlns="http://www.example.org/b" test="foo2-bar-lol">This text should be in green characters</u>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-54.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-54.xml
new file mode 100644
index 0000000000..5ab7c84179
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-54.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED substring matching attribute selector on beginning</title>
+ <style type="text/css"><![CDATA[div.stub > * { color : red }
+div.stub *:not([title^="si on"]) { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-paragraph-lime-characters.xht"/>
+ </head>
+ <body>
+<div class="stub">
+<p>This paragraph should be in green characters.</p>
+<p title="on chante?">This paragraph should be in green characters.</p>
+<p title="si on chantait">
+ <span title="si il chantait">This paragraph should be in green characters.</span>
+</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-55.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-55.xml
new file mode 100644
index 0000000000..c4d5a130fb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-55.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED substring matching attribute selector on end</title>
+ <style type="text/css"><![CDATA[div.stub > * { color : red }
+div.stub *:not([title$="tait"]) { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-paragraph-lime-characters.xht"/>
+ </head>
+ <body>
+<div class="stub">
+<p>This paragraph should be in green characters.</p>
+<p title="on chante?">This paragraph should be in green characters.</p>
+<p title="si on chantait">
+ <span title="si il chante">This paragraph should be in green characters.</span>
+</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-56.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-56.xml
new file mode 100644
index 0000000000..cdcc923397
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-56.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED substring matching attribute selector on middle</title>
+ <style type="text/css"><![CDATA[div.stub > * { color : red }
+div.stub *:not([title*=" on"]) { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-paragraph-lime-characters.xht"/>
+ </head>
+ <body>
+<div class="stub">
+<p>This paragraph should be in green characters.</p>
+<p title="on chante?">This paragraph should be in green characters.</p>
+<p title="si on chantait">
+ <span title="si il chante">This paragraph should be in green characters.</span>
+</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57.xml
new file mode 100644
index 0000000000..4539b0a9ec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute existence selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+div.stub *:not([a|title]) {background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <div class="stub">
+ <q xmlns="http://www.example.org/a" a:title="a paragraph">This a:q element should be unstyled.</q>
+ <p title="a paragraph">This paragraph should have a green background.</p>
+ <r xmlns="http://www.example.org/b" b:title="a paragraph">This b:r element should have a green background.</r>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57b.xml
new file mode 100644
index 0000000000..baf4a38b2e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-57b.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Attribute existence selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+div.stub *:not([a|title]) {background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <div class="stub">
+ <q xmlns="http://www.example.org/a" a:title="a paragraph">This a:q element should be unstyled.</q>
+ <p title="a paragraph">This paragraph should have a green background.</p>
+ <r xmlns="http://www.example.org/b" b:title="a paragraph">This b:r element should have a green background.</r>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-59.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-59.xml
new file mode 100644
index 0000000000..e394adbc79
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-59.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED class selector</title>
+ <style type="text/css"><![CDATA[div.stub > * { color : red }
+div.stub *:not(.foo) { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-paragraph-lime-characters.xht"/>
+ </head>
+ <body>
+<div class="stub">
+<p>This paragraph should be in green characters.</p>
+<p class="bar foofoo tut">This paragraph should be in green characters.</p>
+<p class="bar foo tut">
+ <span class="tut foo2">This paragraph should be in green characters.</span>
+</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-6.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-6.xml
new file mode 100644
index 0000000000..7533d3f023
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-6.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector</title>
+ <style type="text/css"><![CDATA[address { background-color : red }
+address[title="foo"] { background-color : lime }
+span[title="a"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<address title="foo">
+<span title="b">This line should </span>
+ <span title="aa">have a green background.
+</span>
+</address>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-60.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-60.xml
new file mode 100644
index 0000000000..de4a23d35b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-60.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED ID selector</title>
+ <style type="text/css"><![CDATA[div.stub > * { color : red }
+div.stub *:not(#foo) { color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/three-paragraph-lime-characters.xht"/>
+ </head>
+ <body>
+<div class="stub">
+<p>This paragraph should be in green characters.</p>
+<p id="foo2">This paragraph should be in green characters.</p>
+<p id="foo">
+ <span>This paragraph should be in green characters.</span>
+</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-61.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-61.xml
new file mode 100644
index 0000000000..cb3c2df6fc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-61.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :link pseudo-class</title>
+ <style type="text/css"><![CDATA[div.stub > * { background-color : red }
+div.stub *:not(:link) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" history" />
+ </head>
+ <body>
+<div class="stub">
+<a href="http://www.w3.org/">This anchor should have a green background</a>
+(Note: You must have visited http://www.w3.org/ for this test to be valid.)
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-62.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-62.xml
new file mode 100644
index 0000000000..ffaea5d44a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-62.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :visited pseudo-class</title>
+ <style type="text/css"><![CDATA[div.stub > * { background-color : red }
+div.stub *:not(:visited) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" history" />
+ </head>
+ <body>
+<div class="stub">
+<a href="http://unvisited.example.org/css3-modsel-62/">This anchor should have a green background</a>
+(Don&#39;t follow this link.)
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-63.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-63.xml
new file mode 100644
index 0000000000..7c4a34a9b2
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-63.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :hover pseudo-class</title>
+ <style type="text/css"><![CDATA[div.stub * { color: lime; text-decoration: none; }
+div.stub > * > *:not(:hover) { color: black }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <div class="stub">
+ <p> <span>The color of this text should be green when the pointing device hovers over it.</span> </p>
+ <p> <a href="http://dummy.example.org/dummy">The color of this text should be green when the pointing device hovers over it.</a> </p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-64.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-64.xml
new file mode 100644
index 0000000000..b1f00e4909
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-64.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :active pseudo-class</title>
+ <style type="text/css"><![CDATA[div.stub * { color : lime }
+div.stub > * > *:not(:active) { color : black }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+ <div class="stub">
+ <p> <a href="http://dummy.example.org/dummy">This text should turn green while it is active.</a> </p>
+ <p> <button>This text should turn green while it is active.</button> </p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-65.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-65.xml
new file mode 100644
index 0000000000..384c6bcd18
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-65.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :focus pseudo-class</title>
+ <style type="text/css"><![CDATA[a:not(:focus) { background-color: transparent; }
+a { background-color: lime; }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p>The background color of all <a href="#foo">anchors</a>
+ should become <a href="#foo"> green</a> when they have the
+ <a href="#foo">focus</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66.xml
new file mode 100644
index 0000000000..e7b9562ea3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66.xml
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :target pseudo-class</title>
+ <style type="text/css"><![CDATA[p { background-color: navy; color: white; }
+p:not(:target) { background-color: white; color: black; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" interact" />
+ </head>
+ <body>
+<p id="first">This paragraph should be unstyled.
+ The background of the following paragraph should become blue when
+ you follow <a href="#second">this link</a>.</p>
+<p id="second">This paragraph should initially be unstyled.
+ It should become blue when you select the link above. When you select
+ <a href="#third">this link</a>, it should return to being unstyled and the
+ background of the paragraph below should become blue.</p>
+<p id="third">This paragraph should initially be unstyled.
+ It should become blue when you select the link above. When you follow
+ <a href="#missing">this link</a>, the three paragraphs
+ should all return to being unstyled.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66b.xml
new file mode 100644
index 0000000000..d23c74c412
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-66b.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :target pseudo-class</title>
+ <style type="text/css"><![CDATA[p { background-color: red; }
+p:not(:target) { background-color: lime; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This paragraph should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-67.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-67.xml
new file mode 100644
index 0000000000..b341517fec
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-67.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :lang() pseudo-class</title>
+ <style type="text/css"><![CDATA[div.stub * { background-color : red }
+div.stub *:not(:lang(fr)) { background-color : green }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div lang="en" class="stub">
+<p>This paragraph should have a green background because the
+ enclosing div is in english.</p>
+<p lang="en">This paragraph should have a green background because
+ it is in english.</p>
+<div lang="fr">
+ <p lang="en">This paragraph should have a green background
+ because it is in english.</p>
+</div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7.xml
new file mode 100644
index 0000000000..c6ac94f986
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute multivalue selector</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p[class~="b"] { background-color : lime }
+address { background-color : red }
+address[title~="foo"] { background-color : lime }
+span[class~="b"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p class="a b c">This paragraph should have green background because CLASS
+ contains &quot;b&quot;</p>
+<address title="tot foo bar">
+<span class="a c">This address should also</span>
+ <span class="a bb c">have green background because the selector in the last
+ rule does not apply to the inner SPANs.</span>
+</address>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-70.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-70.xml
new file mode 100644
index 0000000000..acfe6662a1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-70.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :checked pseudo-class</title>
+ <style type="text/css"><![CDATA[input, span { background-color : red }
+input:not(:checked), input:not(:checked) + span { background-color : lime}]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>
+<input type="checkbox"></input> <span>Everything in this paragraph should have a green background</span></p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72.xml
new file mode 100644
index 0000000000..d62a2aac01
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :root pseudo-class</title>
+ <style type="text/css"><![CDATA[p:not(:root) { background-color: lime; }
+div * { background-color: red; }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <p>This paragraph should have a green background and there should be no red anywhere.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72b.xml
new file mode 100644
index 0000000000..7e25a21ec3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-72b.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :root pseudo-class</title>
+ <style type="text/css"><![CDATA[html:not(:root), test:not(:root) { background-color: red; }
+p { background-color: lime; }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <p>This paragraph should have a green background and there should be no red anywhere.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73.xml
new file mode 100644
index 0000000000..659b2d69f6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73.xml
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+ul > li:not(:nth-child(odd)) { background-color : lime }
+ol > li:not(:nth-child(even)) { background-color : lime }
+table.t1 tr:not(:nth-child(-n+4)) { background-color : lime }
+table.t2 td:not(:nth-child(3n+1)) { background-color : lime }
+table.t1 td, table.t2 td { border : thin black solid }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li>First list item</li>
+ <li class="red">This second list item should have a green background</li>
+ <li>Third list</li>
+ <li class="red">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="red">This sixth list item should have a green background</li>
+</ul>
+<ol>
+ <li class="red">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="red">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="red">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr>
+<td>1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr>
+<td>4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 5.1</td>
+<td>5.2</td>
+<td>5.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 6.1</td>
+<td>6.2</td>
+<td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td>1.1</td>
+<td class="red">green cell</td>
+<td class="red">green cell</td>
+ <td>1.4</td>
+<td class="red">green cell</td>
+<td class="red">green cell</td>
+ <td>1.7</td>
+<td class="red">green cell</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td class="red">green cell</td>
+<td class="red">green cell</td>
+ <td>2.4</td>
+<td class="red">green cell</td>
+<td class="red">green cell</td>
+ <td>2.7</td>
+<td class="red">green cell</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td class="red">green cell</td>
+<td class="red">green cell</td>
+ <td>3.4</td>
+<td class="red">green cell</td>
+<td class="red">green cell</td>
+ <td>3.7</td>
+<td class="red">green cell</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73b.xml
new file mode 100644
index 0000000000..38f69ee587
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-73b.xml
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important; }
+ul > li:not(:nth-child(odd)) { background-color : red }
+ol > li:not(:nth-child(even)) { background-color : red }
+table.t1 tr:not(:nth-child(-n+4)) { background-color : red }
+table.t2 td:not(:nth-child(3n+1)) { background-color : red }
+table.t1 td, table.t2 td { border : thin black solid }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li>First list item</li>
+ <li class="green">This second list item should have a green background</li>
+ <li>Third list</li>
+ <li class="green">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="green">This sixth list item should have a green background</li>
+</ul>
+<ol>
+ <li class="green">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="green">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="green">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr>
+<td>1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr>
+<td>4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 5.1</td>
+<td>5.2</td>
+<td>5.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 6.1</td>
+<td>6.2</td>
+<td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td>1.1</td>
+<td class="green">green cell</td>
+<td class="green">green cell</td>
+ <td>1.4</td>
+<td class="green">green cell</td>
+<td class="green">green cell</td>
+ <td>1.7</td>
+<td class="green">green cell</td>
+</tr>
+ <tr>
+<td>2.1</td>
+<td class="green">green cell</td>
+<td class="green">green cell</td>
+ <td>2.4</td>
+<td class="green">green cell</td>
+<td class="green">green cell</td>
+ <td>2.7</td>
+<td class="green">green cell</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td class="green">green cell</td>
+<td class="green">green cell</td>
+ <td>3.4</td>
+<td class="green">green cell</td>
+<td class="green">green cell</td>
+ <td>3.7</td>
+<td class="green">green cell</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74.xml
new file mode 100644
index 0000000000..94f61de1c4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74.xml
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-last-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+ul > li:not(:nth-last-child(odd)) { background-color : lime }
+ol > li:not(:nth-last-child(even)) { background-color : lime }
+table.t1 tr:not(:nth-last-child(-n+4)) { background-color : lime }
+table.t2 td:not(:nth-last-child(3n+1)) { background-color : lime }
+table.t1 td, table.t2 td { border : thin black solid }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li class="red">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="red">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="red">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ul>
+<ol>
+ <li>First list item</li>
+ <li class="red">This second list item should have a green background</li>
+ <li>Third list item</li>
+ <li class="red">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="red">This sixth list item should have a green background</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr class="red">
+<td>Green row : 1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr class="red">
+<td>Green row : 2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr>
+<td>4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr>
+<td>5.1</td>
+<td>5.2</td>
+ <td>5.3</td>
+</tr>
+ <tr>
+<td>6.1</td>
+<td>6.2</td>
+ <td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td class="red">green cell</td>
+<td>1.2</td>
+<td class="red">green cell</td>
+ <td class="red">green cell</td>
+<td>1.5</td>
+<td class="red">green cell</td>
+ <td class="red">green cell</td>
+<td>1.8</td>
+</tr>
+ <tr>
+<td class="red">green cell</td>
+<td>2.2</td>
+<td class="red">green cell</td>
+ <td class="red">green cell</td>
+<td>2.5</td>
+<td class="red">green cell</td>
+ <td class="red">green cell</td>
+<td>2.8</td>
+</tr>
+ <tr>
+<td class="red">green cell</td>
+<td>3.2</td>
+<td class="red">green cell</td>
+ <td class="red">green cell</td>
+<td>3.5</td>
+<td class="red">green cell</td>
+ <td class="red">green cell</td>
+<td>3.8</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74b.xml
new file mode 100644
index 0000000000..ddc7c9bf60
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-74b.xml
@@ -0,0 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-last-child() pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important; }
+ul > li:not(:nth-last-child(odd)) { background-color : red }
+ol > li:not(:nth-last-child(even)) { background-color : red }
+table.t1 tr:not(:nth-last-child(-n+4)) { background-color : red }
+table.t2 td:not(:nth-last-child(3n+1)) { background-color : red }
+table.t1 td, table.t2 td { border : thin black solid }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<ul>
+ <li class="green">This first list item should have a green background</li>
+ <li>Second list item</li>
+ <li class="green">This third list item should have a green background</li>
+ <li>Fourth list item</li>
+ <li class="green">This fifth list item should have a green background</li>
+ <li>Sixth list item</li>
+</ul>
+<ol>
+ <li>First list item</li>
+ <li class="green">This second list item should have a green background</li>
+ <li>Third list item</li>
+ <li class="green">This fourth list item should have a green background</li>
+ <li>Fifth list item</li>
+ <li class="green">This sixth list item should have a green background</li>
+</ol>
+<div>
+<table border="1" class="t1">
+ <tr class="green">
+<td>Green row : 1.1</td>
+<td>1.2</td>
+ <td>1.3</td>
+</tr>
+ <tr class="green">
+<td>Green row : 2.1</td>
+<td>2.2</td>
+ <td>2.3</td>
+</tr>
+ <tr>
+<td>3.1</td>
+<td>3.2</td>
+ <td>3.3</td>
+</tr>
+ <tr>
+<td>4.1</td>
+<td>4.2</td>
+ <td>4.3</td>
+</tr>
+ <tr>
+<td>5.1</td>
+<td>5.2</td>
+ <td>5.3</td>
+</tr>
+ <tr>
+<td>6.1</td>
+<td>6.2</td>
+ <td>6.3</td>
+</tr>
+</table>
+<p></p>
+<table class="t2" border="1">
+ <tr>
+<td class="green">green cell</td>
+<td>1.2</td>
+<td class="green">green cell</td>
+ <td class="green">green cell</td>
+<td>1.5</td>
+<td class="green">green cell</td>
+ <td class="green">green cell</td>
+<td>1.8</td>
+</tr>
+ <tr>
+<td class="green">green cell</td>
+<td>2.2</td>
+<td class="green">green cell</td>
+ <td class="green">green cell</td>
+<td>2.5</td>
+<td class="green">green cell</td>
+ <td class="green">green cell</td>
+<td>2.8</td>
+</tr>
+ <tr>
+<td class="green">green cell</td>
+<td>3.2</td>
+<td class="green">green cell</td>
+ <td class="green">green cell</td>
+<td>3.5</td>
+<td class="green">green cell</td>
+ <td class="green">green cell</td>
+<td>3.8</td>
+</tr>
+</table>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75.xml
new file mode 100644
index 0000000000..de6c1c9868
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-of-type() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+p:not(:nth-of-type(3)) { background-color : lime }
+dl > *:not(:nth-of-type(3n+1)) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p class="red">This paragraph should have green background</p>
+<address>And this address should be unstyled.</address>
+<p class="red">This paragraph should also have green background!</p>
+<p>But this one should be unstyled again.</p>
+<dl>
+ <dt>First definition term</dt>
+ <dd>First definition</dd>
+ <dt class="red">Second definition term that should have green background</dt>
+ <dd class="red">Second definition that should have green background</dd>
+ <dt class="red">Third definition term that should have green background</dt>
+ <dd class="red">Third definition that should have green background</dd>
+ <dt>Fourth definition term</dt>
+ <dd>Fourth definition</dd>
+ <dt class="red">Fifth definition term that should have green background</dt>
+ <dd class="red">Fifth definition that should have green background</dd>
+ <dt class="red">Sixth definition term that should have green background</dt>
+ <dd class="red">Sixth definition that should have green background</dd>
+</dl>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75b.xml
new file mode 100644
index 0000000000..35bc2a70fd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-75b.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-of-type() pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+p:not(:nth-of-type(3)) { background-color : red }
+dl > *:not(:nth-of-type(3n+1)) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p class="green">This paragraph should have green background</p>
+<address>And this address should be unstyled.</address>
+<p class="green">This paragraph should also have green background!</p>
+<p>But this one should be unstyled again.</p>
+<dl>
+ <dt>First definition term</dt>
+ <dd>First definition</dd>
+ <dt class="green">Second definition term that should have green background</dt>
+ <dd class="green">Second definition that should have green background</dd>
+ <dt class="green">Third definition term that should have green background</dt>
+ <dd class="green">Third definition that should have green background</dd>
+ <dt>Fourth definition term</dt>
+ <dd>Fourth definition</dd>
+ <dt class="green">Fifth definition term that should have green background</dt>
+ <dd class="green">Fifth definition that should have green background</dd>
+ <dt class="green">Sixth definition term that should have green background</dt>
+ <dd class="green">Sixth definition that should have green background</dd>
+</dl>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76.xml
new file mode 100644
index 0000000000..5937f0ead7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-last-of-type() pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+p:not(:nth-last-of-type(3)) { background-color : lime }
+dl > *:not(:nth-last-of-type(3n+1)) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This paragraph should be unstyled.</p>
+<address>This address should be unstyled.</address>
+<p class="red">This paragraph should have green background.</p>
+<p class="red">This paragraph should have green background.</p>
+<dl>
+ <dt class="red">First definition term that should have green background.</dt>
+ <dd class="red">First definition that should also have a green background.</dd>
+ <dt class="red">Second definition term that should have green background.</dt>
+ <dd class="red">Second definition that should have green background.</dd>
+ <dt>Third definition term.</dt>
+ <dd>Third definition.</dd>
+ <dt class="red">Fourth definition term that should have green background.</dt>
+ <dd class="red">Fourth definition that should have green background.</dd>
+ <dt class="red">Fifth definition term that should have green background.</dt>
+ <dd class="red">Fifth definition that should have green background.</dd>
+ <dt>Sixth definition term.</dt>
+ <dd>Sixth definition.</dd>
+</dl>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76b.xml
new file mode 100644
index 0000000000..3b3048be9b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-76b.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :nth-last-of-type() pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+p:not(:nth-last-of-type(3)) { background-color : red }
+dl > *:not(:nth-last-of-type(3n+1)) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p>This paragraph should be unstyled.</p>
+<address>This address should be unstyled.</address>
+<p class="green">This paragraph should have green background.</p>
+<p class="green">This paragraph should have green background.</p>
+<dl>
+ <dt class="green">First definition term that should have green background.</dt>
+ <dd class="green">First definition that should also have a green background.</dd>
+ <dt class="green">Second definition term that should have green background.</dt>
+ <dd class="green">Second definition that should have green background.</dd>
+ <dt>Third definition term.</dt>
+ <dd>Third definition.</dd>
+ <dt class="green">Fourth definition term that should have green background.</dt>
+ <dd class="green">Fourth definition that should have green background.</dd>
+ <dt class="green">Fifth definition term that should have green background.</dt>
+ <dd class="green">Fifth definition that should have green background.</dd>
+ <dt>Sixth definition term.</dt>
+ <dd>Sixth definition.</dd>
+</dl>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77.xml
new file mode 100644
index 0000000000..e78ddcf1ab
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :first-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+.t1 td:not(:first-child) { background-color : lime }
+p > *:not(:first-child) { background-color : lime }
+table.t1 td { border : thin black solid }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <table class="t1" border="1">
+ <tr>
+ <td>1.1</td>
+ <td class="red">green cell</td>
+ <td class="red">green cell</td>
+ </tr>
+ <tr>
+ <td>2.1</td>
+ <td class="red">green cell</td>
+ <td class="red">green cell</td>
+ </tr>
+ <tr>
+ <td>3.1</td>
+ <td class="red">green cell</td>
+ <td class="red">green cell</td>
+ </tr>
+ </table>
+ </div>
+ <p>This paragraph <span>should be</span> unstyled.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77b.xml
new file mode 100644
index 0000000000..8225cd2601
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-77b.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :first-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+.t1 td:not(:first-child) { background-color : red }
+p > *:not(:first-child) { background-color : red }
+table.t1 td { border : thin black solid }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <table class="t1" border="1">
+ <tr>
+ <td>1.1</td>
+ <td class="green">green cell</td>
+ <td class="green">green cell</td>
+ </tr>
+ <tr>
+ <td>2.1</td>
+ <td class="green">green cell</td>
+ <td class="green">green cell</td>
+ </tr>
+ <tr>
+ <td>3.1</td>
+ <td class="green">green cell</td>
+ <td class="green">green cell</td>
+ </tr>
+ </table>
+ </div>
+ <p>This paragraph <span>should be</span> unstyled.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78.xml
new file mode 100644
index 0000000000..415722bbdd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :last-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+.t1 td:not(:last-child) { background-color : lime }
+p > *:not(:last-child) { background-color : lime }
+table.t1 td { border : thin black solid }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <table class="t1" border="1">
+ <tr>
+ <td class="red">green cell</td>
+ <td class="red">green cell</td>
+ <td>1.3</td>
+ </tr>
+ <tr>
+ <td class="red">green cell</td>
+ <td class="red">green cell</td>
+ <td>2.3</td>
+ </tr>
+ <tr>
+ <td class="red">green cell</td>
+ <td class="red">green cell</td>
+ <td>3.3</td>
+ </tr>
+ </table>
+ </div>
+ <p>This <span>paragraph should</span> be unstyled.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78b.xml
new file mode 100644
index 0000000000..207609b5f0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-78b.xml
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :last-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+.t1 td:not(:last-child) { background-color : red }
+p > *:not(:last-child) { background-color : red }
+table.t1 td { border : thin black solid }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <div>
+ <table class="t1" border="1">
+ <tr>
+ <td class="green">green cell</td>
+ <td class="green">green cell</td>
+ <td>1.3</td>
+ </tr>
+ <tr>
+ <td class="green">green cell</td>
+ <td class="green">green cell</td>
+ <td>2.3</td>
+ </tr>
+ <tr>
+ <td class="green">green cell</td>
+ <td class="green">green cell</td>
+ <td>3.3</td>
+ </tr>
+ </table>
+ </div>
+ <p>This <span>paragraph should</span> be unstyled.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-79.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-79.xml
new file mode 100644
index 0000000000..fef9ea2c54
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-79.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :first-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+address { margin-bottom : 1em ; margin-left : 1em }
+address:not(:first-of-type) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>This div contains 3 addresses :
+<address>A first address with normal background</address>
+<address class="red">A second address that should have a green background</address>
+<address class="red">A third address that should have a green background</address>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7b.xml
new file mode 100644
index 0000000000..a5df860a38
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-7b.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute multivalue selector</title>
+ <style type="text/css"><![CDATA[
+p { background: lime; }
+[title~="hello world"] { background: red; }
+/* Section 6.3.1: Represents the att attribute whose value is a
+space-separated list of words, one of which is exactly "val". If this
+selector is used, the words in the value must not contain spaces
+(since they are separated by spaces). */
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/this-line-lime-background.xht"/>
+ </head>
+ <body>
+ <p title="hello world">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-8.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-8.xml
new file mode 100644
index 0000000000..67daa49273
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-8.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selectors (hyphen-separated attributes)</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p[lang|="en"] { background-color : lime }
+address { background-color : red }
+address[lang="fi"] { background-color : lime }
+span[lang|="fr"] { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p lang="en-gb">This paragraph should have green background because its language is &quot;en-gb&quot;</p>
+<address lang="fi">
+<span lang="en-us">This address should also</span>
+ <span lang="en-fr">have green background because the language of the inner SPANs
+ is not French.</span>
+</address>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-80.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-80.xml
new file mode 100644
index 0000000000..e8731bbe2f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-80.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :last-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+address { margin-bottom : 1em ; margin-left : 1em }
+address:not(:last-of-type) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div>
+<address class="red">A first address that should have a green background</address>
+<address class="red">A second address that should have a green background</address>
+<address>A third address with normal background</address>
+This div should have three addresses above it.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81.xml
new file mode 100644
index 0000000000..73c5779466
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :only-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+p:not(:only-child) { background-color : lime }
+div.testText > div > p { margin-left : 1em }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p class="red">This paragraph should have a green background.</p>
+ <div>This div contains only one paragraph.
+ <p>This paragraph should be unstyled.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81b.xml
new file mode 100644
index 0000000000..6b084f0030
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-81b.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :only-child pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+p:not(:only-child) { background-color : lime }
+div.testText > div > p { margin-left : 1em }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+ <p class="green">This paragraph should have a green background.</p>
+ <div>This div contains only one paragraph.
+ <p>This paragraph should be unstyled.</p>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82.xml
new file mode 100644
index 0000000000..21fe0f88b8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :only-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.red { background-color : red }
+.t1 *:not(:only-of-type) { background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div class="t1">
+<p class="red">This paragraph should have green background.</p>
+<address>But this address should be unstyled.</address>
+<p class="red">This paragraph should have green background.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82b.xml
new file mode 100644
index 0000000000..9f8893f885
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-82b.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED :only-of-type pseudo-class</title>
+ <style type="text/css"><![CDATA[.green { background-color : lime ! important }
+.t1 *:not(:only-of-type) { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<div class="t1">
+<p class="green">This paragraph should have green background.</p>
+<address>But this address should be unstyled.</address>
+<p class="green">This paragraph should have green background.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83-ref.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83-ref.xml
new file mode 100644
index 0000000000..6ab85b3239
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83-ref.xml
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>This paragraph green background red</title>
+ <style type="text/css"><![CDATA[p { background-color : green }]]></style>
+ </head>
+ <body>
+ <p>This paragraph should have a green background</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83.xml
new file mode 100644
index 0000000000..b5f1012262
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-83.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Negation pseudo-class can be an argument of itself</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p:not(:not(p)) { background-color : green }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#negation-pseudo"/>
+ <link rel="match" href="css3-modsel-83-ref.xml"/>
+ </head>
+ <body>
+<p>This paragraph should have a green background</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-86.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-86.xml
new file mode 100644
index 0000000000..96507ad656
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-86.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nondeterministic matching of descendant and child combinators</title>
+ <style type="text/css"><![CDATA[p { color: red; }
+blockquote > div p { color: green; }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<blockquote>
+<div>
+<div>
+<p>This text should be green.</p>
+</div>
+</div>
+</blockquote>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87.xml
new file mode 100644
index 0000000000..29e95de36e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nondeterministic matching of direct and indirect adjacent combinators</title>
+ <style type="text/css"><![CDATA[p { color: red; }
+blockquote + div ~ p { color: green; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/bq-u-u-u-green.xht"/>
+ </head>
+ <body>
+<blockquote><div>This text should be unstyled.</div></blockquote>
+<div>This text should be unstyled.</div>
+<div>This text should be unstyled.</div>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87b.xml
new file mode 100644
index 0000000000..5867fc9da3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-87b.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nondeterministic matching of direct and indirect adjacent combinators</title>
+ <style type="text/css"><![CDATA[p { color: green ! important; }
+blockquote + div ~ p { color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/bq-u-u-u-green.xht"/>
+ </head>
+ <body>
+<blockquote><div>This text should be unstyled.</div></blockquote>
+<div>This text should be unstyled.</div>
+<div>This text should be unstyled.</div>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88.xml
new file mode 100644
index 0000000000..a6dc75ba75
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nondeterministic matching of descendant and direct adjacent combinators</title>
+ <style type="text/css"><![CDATA[p { color: red; }
+blockquote + div p { color: green; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<blockquote><div>This text should be unstyled.</div></blockquote>
+<div>
+<div>
+<p>This text should be green.</p>
+</div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88b.xml
new file mode 100644
index 0000000000..6c038ed5fd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-88b.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nondeterministic matching of descendant and direct adjacent combinators</title>
+ <style type="text/css"><![CDATA[p { color: green ! important; }
+blockquote + div p { color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<blockquote><div>This text should be unstyled.</div></blockquote>
+<div>
+<div>
+<p>This text should be green.</p>
+</div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-89.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-89.xml
new file mode 100644
index 0000000000..c9f3f25f73
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-89.xml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Simple combination of descendant and child combinators</title>
+ <style type="text/css"><![CDATA[p { color: red; }
+blockquote div > p { color: green; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<blockquote>
+<div>
+<div>
+<p>This text should be green.</p>
+</div>
+</div>
+</blockquote>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-9.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-9.xml
new file mode 100644
index 0000000000..3974899ee6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-9.xml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Substring matching attribute selector (beginning)</title>
+ <style type="text/css"><![CDATA[p { background-color : red }
+p[title^="foo"] { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ </head>
+ <body>
+<p title="foobar">This paragraph should have a green background<br></br>
+because its title attribute begins with &quot;foo&quot;</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90.xml
new file mode 100644
index 0000000000..1fc84e7978
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Simple combination of direct and indirect adjacent combinators</title>
+ <style type="text/css"><![CDATA[p { color: red; }
+blockquote ~ div + p { color: green; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/bq-u-u-u-green.xht"/>
+ </head>
+ <body>
+<blockquote><div>This text should be unstyled.</div></blockquote>
+<div>This text should be unstyled.</div>
+<div>This text should be unstyled.</div>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90b.xml
new file mode 100644
index 0000000000..33fd9d711d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-90b.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Simple combination of direct and indirect adjacent combinators</title>
+ <style type="text/css"><![CDATA[p { color: green ! important; }
+blockquote ~ div + p { color: red; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/bq-u-u-u-green.xht"/>
+ </head>
+ <body>
+<blockquote><div>This text should be unstyled.</div></blockquote>
+<div>This text should be unstyled.</div>
+<div>This text should be unstyled.</div>
+<p>This text should be green.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-91.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-91.xml
new file mode 100644
index 0000000000..2fc2ed6d73
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-91.xml
@@ -0,0 +1,14 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Type element selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace test url(http://www.example.org/a);
+testa { background-color : red }
+test|testa { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<testa xmlns="http://www.example.org/a">This paragraph should have a green background</testa>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-92.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-92.xml
new file mode 100644
index 0000000000..16883a4a42
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-92.xml
@@ -0,0 +1,16 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Type element selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace test url(http://www.example.org/b);
+div.myTest * { background-color : red }
+div.myTest *|testA { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="myTest">
+<testA xmlns="http://www.example.org/b">This paragraph should have a green background</testA>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-93.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-93.xml
new file mode 100644
index 0000000000..47f802396c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-93.xml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Type element selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace test url(http://www.example.org/b);
+*|testA { background-color : red }
+|testA {background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<testA xmlns="">This paragraph has no declared namespace and should have a green background.</testA>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94.xml
new file mode 100644
index 0000000000..4bebf5303c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94.xml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+p, q { display : block ; margin-bottom : 1em }
+b|* { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<p>This line should be unstyled.</p>
+<p xmlns="http://www.example.org/b">This line should have a green background.</p>
+<q xmlns="http://www.example.org/b">This line should have a green background.</q>
+<p xmlns="http://www.example.org/a">This line should be unstyleed.</p>
+<p xmlns="http://www.example.org/b">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94b.xml
new file mode 100644
index 0000000000..d2ab44d297
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-94b.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+p, q { display : block ; margin-bottom : 1em }
+b|* { background-color : red }
+[test] { background-color: lime; }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<p>This line should be unstyled.</p>
+<p xmlns="http://www.example.org/b" test="test">This line should have a green background.</p>
+<q xmlns="http://www.example.org/b" test="test">This line should have a green background.</q>
+<p xmlns="http://www.example.org/a">This line should be unstyled.</p>
+<p xmlns="http://www.example.org/b" test="test">This line should have a green background.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-95.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-95.xml
new file mode 100644
index 0000000000..9ba5dd0e8f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-95.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector with universal namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.test * { background-color : red ; display : block ; margin-bottom : 1em }
+div.test *|* { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+ <div class="test">
+ <p>This line should have a green background</p>
+ <p xmlns="http://www.example.org/b">This line should have a green background</p>
+ <q xmlns="http://www.example.org/b">This line should have a green background</q>
+ <p xmlns="http://www.example.org/a">This line should have a green background</p>
+ <foo xmlns="http://www.example.org/b">This line should have a green background</foo>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96.xml
new file mode 100644
index 0000000000..8d62a81ea8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.green * { background-color : red }
+div.test * { display : block ; margin-bottom : 1em }
+div.test |* { background-color : lime }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="test">
+ <p>This line should be unstyled.</p>
+ <elementA xmlns="http://www.example.org/a">This line should be unstyled.</elementA>
+ <elementB xmlns="http://www.example.org/b">This line should be unstyled.</elementB>
+ <div class="green">
+ <p xmlns="">This line should have a green background</p>
+ <elementA xmlns="">This line should have a green background</elementA>
+ <elementB xmlns="">This line should have a green background</elementB>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96b.xml
new file mode 100644
index 0000000000..5c85d67f15
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-96b.xml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Universal selector without declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+div.green * { background-color : lime ! important }
+div.test * { display : block ; margin-bottom : 1em }
+div.test |* { background-color : red }]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body>
+<div class="test">
+ <p>This line should be unstyled.</p>
+ <elementA xmlns="http://www.example.org/a">This line should be unstyled.</elementA>
+ <elementB xmlns="http://www.example.org/b">This line should be unstyled.</elementB>
+ <div class="green">
+ <p xmlns="">This line should have a green background</p>
+ <elementA xmlns="">This line should have a green background</elementA>
+ <elementB xmlns="">This line should have a green background</elementB>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97.xml
new file mode 100644
index 0000000000..a254bafb55
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97.xml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r { display : block ; margin-bottom : 1em }
+*|q { background-color : red }
+*[a|title] {background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <p title="a paragraph">This paragraph should be unstyled.</p>
+ <q xmlns="http://www.example.org/a" a:title="a paragraph">This paragraph should have a green background.</q>
+ <r xmlns="http://www.example.org/b" b:title="a paragraph">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97b.xml
new file mode 100644
index 0000000000..71e3467f27
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-97b.xml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute existence selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r { display : block ; margin-bottom : 1em }
+*|q { background-color : lime ! important }
+*[a|title] {background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <p title="a paragraph">This paragraph should be unstyled.</p>
+ <q xmlns="http://www.example.org/a" a:title="a paragraph">This paragraph should have a green background.</q>
+ <r xmlns="http://www.example.org/b" b:title="a paragraph">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98.xml
new file mode 100644
index 0000000000..9d68a22d6b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q, *|t { background-color : red }
+*[a|title="foo"] {background-color : lime }
+*[a|title=footwo] {background-color : lime }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <p title="foo">This paragraph should be unstyled.</p>
+ <q xmlns="http://www.example.org/a" a:title="foo">This paragraph should have a green background</q>
+ <s xmlns="http://www.example.org/a" a:title="foobar">This paragraph should be unstyled.</s>
+ <r xmlns="http://www.example.org/b" b:title="foo">This paragraph should be unstyled.</r>
+ <t xmlns="http://www.example.org/a" a:title="footwo">This paragraph should have a green background</t>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98b.xml
new file mode 100644
index 0000000000..bf416abf82
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-98b.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|q { background-color : lime ! important }
+*[a|title="foo"] {background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <p title="foo">This paragraph should be unstyled.</p>
+ <q xmlns="http://www.example.org/a" a:title="foo">This paragraph should have a green background</q>
+ <s xmlns="http://www.example.org/a" a:title="foobar">This paragraph should be unstyled.</s>
+ <r xmlns="http://www.example.org/b" b:title="foo">This paragraph should be unstyled.</r>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99.xml
new file mode 100644
index 0000000000..2d385fe6f4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99.xml
@@ -0,0 +1,24 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute space-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : red }
+*|*[a|foo~="bar"], *|*[|class~="bar"] { background-color : lime }
+*|*[html|class~="bar"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <p class="t bar u">This paragraph should have a green background.</p>
+ <q xmlns="http://www.example.org/a" a:foo="hgt bardot f">This paragraph should be unstyled.</q>
+ <r xmlns="http://www.example.org/a" a:foo="hgt bar f">This paragraph should have a green background.</r>
+ <s xmlns="http://www.example.org/b" b:foo="hgt bar f">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99b.xml
new file mode 100644
index 0000000000..f8aff417ef
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-99b.xml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Attribute space-separated value selector with declared namespace</title>
+ <style type="text/css"><![CDATA[@namespace a url(http://www.example.org/a);
+@namespace b url(http://www.example.org/b);
+@namespace html url(http://www.w3.org/1999/xhtml);
+*|p, *|q, *|r, *|s { display : block ; margin-bottom : 1em }
+*|p, *|r { background-color : lime ! important }
+*|*[a|foo~="bar"], *|*[html|class~="bar"] { background-color : red }
+]]></style>
+ <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <link rel="match" href="reference/lime-bg-paras-g-u-g-u.xht"/>
+ <meta name="flags" content=" namespace" />
+ </head>
+ <body xmlns:a="http://www.example.org/a" xmlns:b="http://www.example.org/b">
+ <p class="t bar u">This paragraph should have a green background.</p>
+ <q xmlns="http://www.example.org/a" a:foo="hgt bardot f">This paragraph should be unstyled.</q>
+ <r xmlns="http://www.example.org/a" a:foo="hgt bar f">This paragraph should have a green background.</r>
+ <s xmlns="http://www.example.org/b" b:foo="hgt bar f">This paragraph should be unstyled.</s>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1.xml
new file mode 100644
index 0000000000..144cf0e0fd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>NEGATED Dynamic handling of :empty</title>
+ <style type="text/css"><![CDATA[
+ #test { background: red; display: block; padding: 1em; }
+ #test:not(:empty) { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" dom" />
+ </head>
+ <body>
+
+ <div>
+
+ <script type="text/javascript">
+ <![CDATA[
+
+ function test() {
+ document.getElementById('test').appendChild(document.createTextNode('This line should be green.'));
+ }
+
+ window.setTimeout("test()", 100);
+ ]]>
+ </script>
+
+ <p> The following bar should be green. </p>
+
+ <div id="test"></div>
+
+ </div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1b.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1b.xml
new file mode 100644
index 0000000000..f4583f843c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d1b.xml
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Dynamic handling of :empty</title>
+ <style type="text/css"><![CDATA[
+ #test1 { background: red; display: block; padding: 1em; margin: 1em; }
+ #test1:empty { background: lime; }
+ #test2 { background: lime; display: block; padding: 1em; margin: 1em; }
+ #test2:empty { background: red; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" dom" />
+ </head>
+ <body>
+
+ <div>
+
+ <script type="text/javascript">
+ <![CDATA[
+
+ function test() {
+ document.getElementById('test1').appendChild(document.createTextNode(''));
+ document.getElementById('test2').appendChild(document.createTextNode(' '));
+ }
+
+ window.setTimeout("test()", 100);
+ ]]>
+ </script>
+
+ <p> The following two bars should be green. </p>
+
+ <div id="test1"></div>
+ <div id="test2"></div>
+
+ </div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d2.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d2.xml
new file mode 100644
index 0000000000..aa24e95999
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d2.xml
@@ -0,0 +1,42 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Dynamic handling of combinators</title>
+ <style type="text/css"><![CDATA[
+ #test { background: red; display: block; padding: 1em; }
+ #stub ~ div div + div > div { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" dom" />
+ </head>
+ <body>
+
+ <div>
+
+
+ <script type="text/javascript">
+ <![CDATA[
+
+ function test() {
+ el = document.getElementById('test');
+ el.parentNode.parentNode.insertBefore(document.createElementNS('http://www.w3.org/1999/xhtml', 'div'), el.parentNode);
+ }
+
+ window.setTimeout("test()", 100);
+ ]]>
+ </script>
+
+
+
+
+ <p> The following bar should be green. </p>
+
+ <div id="stub"></div>
+ <div></div>
+ <div><div><!-- <div/> --><div><div id="test"></div></div></div></div>
+
+ </div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d3.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d3.xml
new file mode 100644
index 0000000000..e8b15e9614
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d3.xml
@@ -0,0 +1,44 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Dynamic handling of attribute selectors</title>
+ <style type="text/css"><![CDATA[
+ [test] { background: red; display: block; padding: 1em; }
+ stub ~ [|attribute^=start]:not([|attribute~=mid])[|attribute*=dle][|attribute$=end] ~ t { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" dom namespace" />
+ </head>
+ <body>
+
+ <div>
+
+ <script type="text/javascript">
+ <![CDATA[
+
+ function test() {
+ document.getElementsByTagNameNS('', 't')[1].setAttributeNS('', 'attribute', 'start middle end');
+ }
+
+ window.setTimeout("test()", 100);
+ ]]>
+ </script>
+
+ <p> The following block should be green. </p>
+
+ <!-- root of selector -->
+ <stub xmlns=""></stub>
+
+ <!-- middle part of selector does not match this -->
+ <t xmlns="" attribute="fake"></t>
+
+ <!-- middle part of selector matches this once attribute is fixed -->
+ <t xmlns="" attribute="start mid dle end"></t>
+
+ <!-- subject of selector -->
+ <t xmlns="" test="test"></t>
+
+ </div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d4.xml b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d4.xml
new file mode 100644
index 0000000000..73fe3a7384
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/css3-modsel-d4.xml
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Dynamic updating of :first-child and :last-child</title>
+ <style type="text/css"><![CDATA[
+ #two:first-child { background: red; }
+ #three:last-child { background: lime; }
+]]></style>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
+ <meta name="flags" content=" dom" />
+ </head>
+ <body>
+
+ <div>
+
+ <script type="text/javascript">
+ <![CDATA[
+
+ function test() {
+ el2 = document.getElementById('two');
+ el3 = document.getElementById('three');
+ el2.parentNode.insertBefore(el3.nextSibling, el2);
+ }
+
+ window.setTimeout("test()", 100);
+ ]]>
+ </script>
+
+ <div><p id="two">This line should be unstyled. (2)</p><p id="three">This line should have a green background. (3)</p><p>This line should be unstyled. (4 moving to 1)</p></div>
+
+ </div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/bq-u-u-u-green.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/bq-u-u-u-green.xht
new file mode 100644
index 0000000000..17c893cd49
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/bq-u-u-u-green.xht
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Blockquote then green eventually</title>
+ <style type="text/css">
+ p { color: green; }
+ </style>
+ </head>
+ <body>
+ <blockquote><div>This text should be unstyled.</div></blockquote>
+ <div>This text should be unstyled.</div>
+ <div>This text should be unstyled.</div>
+ <p>This text should be green.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-g-u.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-g-u.xht
new file mode 100644
index 0000000000..aedd173524
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-g-u.xht
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Five paragraphs lime background g u g g u</title>
+ <style type="text/css">
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u-u.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u-u.xht
new file mode 100644
index 0000000000..2782cfc860
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u-u.xht
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Five paragraphs lime background g u g u u</title>
+ <style type="text/css">
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p>This paragraph should be unstyled.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u.xht
new file mode 100644
index 0000000000..ee174e00e6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-g-u.xht
@@ -0,0 +1,14 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Four paragraphs lime background g u g u</title>
+ <style type="text/css">
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-u-g-g.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-u-g-g.xht
new file mode 100644
index 0000000000..8d236dfc60
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-g-u-u-g-g.xht
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Five paragraphs lime background g u u g g</title>
+ <style type="text/css">
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-g-u-u-g.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-g-u-u-g.xht
new file mode 100644
index 0000000000..1768b0ed27
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-g-u-u-g.xht
@@ -0,0 +1,16 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Six paragraphs lime background u g g u u g</title>
+ <style type="text/css">
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-u-g-g.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-u-g-g.xht
new file mode 100644
index 0000000000..d565fc0e22
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/lime-bg-paras-u-g-u-g-g.xht
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Five paragraphs lime background u g u g g</title>
+ <style type="text/css">
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/seven-green-divs.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/seven-green-divs.xht
new file mode 100644
index 0000000000..8daf648750
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/seven-green-divs.xht
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Seven green divs</title>
+ <style type="text/css">
+ div { color: green; }
+ </style>
+ </head>
+ <body>
+ <div>This should be green.</div>
+ <div>This should be green.</div>
+ <div>This should be green.</div>
+ <div>This should be green.</div>
+ <div>This should be green.</div>
+ <div>This should be green.</div>
+ <div>This should be green.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/this-address-p-p-p-lime-background.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/this-address-p-p-p-lime-background.xht
new file mode 100644
index 0000000000..17f9b8c83d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/this-address-p-p-p-lime-background.xht
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>"this line should have a green background" lime margin offset</title>
+ <style type="text/css">
+ div, address {
+ background-color: lime ;
+ display : block ;
+ margin-bottom : 1em }
+ </style>
+ </head>
+ <body>
+ <address>This address should have a green background</address>
+ <div>This paragraph should have a green background</div>
+ <div>This paragraph should have a green background</div>
+ <div>This paragraph should have a green background</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-background.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-background.xht
new file mode 100644
index 0000000000..35c264e149
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-background.xht
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>"This line should be green." green</title>
+ <style type="text/css">
+ p { background: green; color: white; }
+ </style>
+ </head>
+ <body>
+ <p>This line should be green.</p>
+ <p>This line should be green.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-color.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-color.xht
new file mode 100644
index 0000000000..4ae49b1dca
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-green-color.xht
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>"This line" green color</title>
+ <style type="text/css"><![CDATA[
+ p { color: green }
+]]></style>
+ </head>
+ <body>
+ <p>This line should be green.</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background-offset.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background-offset.xht
new file mode 100644
index 0000000000..9fd7a450df
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background-offset.xht
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>"this line should have a green background" lime margin offset</title>
+ <style type="text/css">
+ .a { background: lime; margin: 0; height: 1em; }
+ .b { margin: -1em 0 0 0; }
+ </style>
+ </head>
+ <body>
+ <div class="a"></div>
+ <div class="b">This line should have a green background.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background.xht
new file mode 100644
index 0000000000..72fd9d8827
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/this-line-lime-background.xht
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>"this line should have a green background" lime</title>
+ <style type="text/css"><![CDATA[
+ p { background: lime; }
+]]></style>
+ </head>
+ <body>
+ <p>This line should have a green background.</p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/this-test-has-passed-desc.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/this-test-has-passed-desc.xht
new file mode 100644
index 0000000000..1688ca6237
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/this-test-has-passed-desc.xht
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>This test has PASSED</title>
+ <style type="text/css">
+ span { background-color: lime; }
+ </style>
+ </head>
+ <body>
+ <p>This test has <span>PASSED</span>.</p>
+ <p>(If the previous line just reads &quot;This test has .&quot; then this test has failed.)</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/three-p-lime-background-except-middle.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/three-p-lime-background-except-middle.xht
new file mode 100644
index 0000000000..278fa2b749
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/three-p-lime-background-except-middle.xht
@@ -0,0 +1,14 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Three paragraphs lime background middle unstyled</title>
+ <style type="text/css">
+ p { margin: 0 0 1em 0; }
+ .lime { background-color: lime }
+ </style>
+ </head>
+ <body>
+ <p class="lime">This paragraph should have a green background.</p>
+ <p>This paragraph should be unstyled.</p>
+ <p class="lime">This paragraph should have a green background.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/old-tests/reference/three-paragraph-lime-characters.xht b/testing/web-platform/tests/css/selectors/old-tests/reference/three-paragraph-lime-characters.xht
new file mode 100644
index 0000000000..46bfede1a5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/old-tests/reference/three-paragraph-lime-characters.xht
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Three paragraphs, green</title>
+ <style type="text/css">
+ p { color: lime }
+ </style>
+ </head>
+ <body>
+ <p>This paragraph should be in green characters.</p>
+ <p>This paragraph should be in green characters.</p>
+ <p>This paragraph should be in green characters.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/only-child.html b/testing/web-platform/tests/css/selectors/only-child.html
new file mode 100644
index 0000000000..590c07ba2b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/only-child.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :only-child</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-only-child-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ See also child-indexed-pseudo-class.html.
+-->
+<body>
+
+<div>
+ <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+ <div id="target2">A comment node should be ignored.</div>
+ <!-- -->
+</div>
+
+<div>
+ <div id="target3">Non-whitespace text node should be ignored.</div>
+ .
+</div>
+
+<div>
+ <blockquote></blockquote>
+ <div id="target4" data-expected="false">There is another child element.</div>
+</div>
+
+<div>
+ <div id="target5"></div>
+</div>
+
+<script>
+for (let i = 1; i <= 4; ++i) {
+ let target = document.querySelector(`#target${i}`);
+ test(() => {
+ if (target.dataset.expected == 'false')
+ assert_false(target.matches(':only-child'));
+ else
+ assert_true(target.matches(':only-child'));
+ }, target.textContent);
+}
+
+test(() => {
+ const target = document.querySelector('#target5');
+ assert_true(target.matches(':only-child'));
+
+ const another = target.parentNode.appendChild(document.createElement('div'));
+ assert_false(target.matches(':only-child'));
+ assert_false(another.matches(':only-child'));
+
+ another.remove();
+ assert_true(target.matches(':only-child'));
+}, 'Dynamic addition and removal');
+
+</script>
+
diff --git a/testing/web-platform/tests/css/selectors/only-of-type.html b/testing/web-platform/tests/css/selectors/only-of-type.html
new file mode 100644
index 0000000000..28a0ae7655
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/only-of-type.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Selectors :only-of-type</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-only-of-type-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ See also child-indexed-pseudo-class.html.
+-->
+<body>
+
+<div>
+ <div id="target1">Whitespace nodes should be ignored.</div>
+</div>
+
+<div>
+ <div id="target2">A comment node should be ignored.</div>
+ <!-- -->
+</div>
+
+<div>
+ <div id="target3">Non-whitespace text node should be ignored.</div>
+ .
+</div>
+
+<div>
+ <blockquote></blockquote>
+ <div id="target4" data-expected="false">There is another child element of a different type.</div>
+</div>
+
+<div>
+ <div id="target5"></div>
+</div>
+
+<script>
+for (let i = 1; i <= 4; ++i) {
+ let target = document.querySelector(`#target${i}`);
+ test(() => {
+ if (target.dataset.expected == 'true')
+ assert_false(target.matches(':only-of-type'));
+ else
+ assert_true(target.matches(':only-of-type'));
+ }, target.textContent);
+}
+
+test(() => {
+ const target = document.querySelector('#target5');
+ assert_true(target.matches(':only-of-type'));
+
+ const of_different_type = target.parentNode.appendChild(document.createElement('span'));
+ assert_true(of_different_type.matches(':only-of-type'));
+ assert_true(target.matches(':only-of-type'));
+
+ const another_of_type = target.parentNode.appendChild(document.createElement('div'));
+ assert_false(target.matches(':only-of-type'));
+ assert_false(another_of_type.matches(':only-of-type'));
+
+ another_of_type.remove();
+ assert_true(target.matches(':only-of-type'));
+}, 'Dynamic addition and removal');
+
+</script>
diff --git a/testing/web-platform/tests/css/selectors/open-closed-pseudo.html b/testing/web-platform/tests/css/selectors/open-closed-pseudo.html
new file mode 100644
index 0000000000..9301fd2f41
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/open-closed-pseudo.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://drafts.csswg.org/selectors-4/#open-state">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<dialog>dialog</dialog>
+
+<details>details</details>
+
+<select>
+ <option>one</option>
+</select>
+
+<script>
+test(() => {
+ const dialog = document.querySelector('dialog');
+ assert_true(dialog.matches(':closed'),
+ ':closed should match when the dialog is closed.');
+ assert_false(dialog.matches(':open'),
+ ':open should not match when the dialog is closed.');
+
+ dialog.show();
+ assert_false(dialog.matches(':closed'),
+ ':closed should not match after dialog.open().');
+ assert_true(dialog.matches(':open'),
+ ':open should match after dialog.open().');
+
+ dialog.close();
+ dialog.showModal();
+ assert_false(dialog.matches(':closed'),
+ ':closed should not match after dialog.showModal().');
+ assert_true(dialog.matches(':open'),
+ ':open should match after dialog.showModal().');
+
+ dialog.close();
+}, 'The dialog element should support :open and :closed.');
+
+test(() => {
+ const details = document.querySelector('details');
+ assert_true(details.matches(':closed'),
+ ':closed should match when the details is closed.');
+ assert_false(details.matches(':open'),
+ ':open should not match when the details is closed.');
+
+ details.open = true;
+ assert_false(details.matches(':closed'),
+ ':closed should not match when the details is open.');
+ assert_true(details.matches(':open'),
+ ':open should match when the details is open.');
+}, 'The details element should support :open and :closed.');
+
+promise_test(async () => {
+ const select = document.querySelector('select');
+ assert_true(select.matches(':closed'),
+ ':closed should match when the select is closed.');
+ assert_false(select.matches(':open'),
+ ':open should not match when the select is closed.');
+
+ await test_driver.click(select);
+ await new Promise(requestAnimationFrame);
+ assert_false(select.matches(':closed'),
+ ':closed should not match when the select is open.');
+ assert_true(select.matches(':open'),
+ ':open should match when the select is open.');
+}, 'The select element should support :open and :closed.');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/invalid-pseudos.html b/testing/web-platform/tests/css/selectors/parsing/invalid-pseudos.html
new file mode 100644
index 0000000000..a4be206b25
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/invalid-pseudos.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Selectors: Test that various prefixed pseudos are not web exposed</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../support/parsing-testcommon.js"></script>
+<script>
+// Pseudo-classes
+test_invalid_selector(":-internal-animating-full-screen-transition");
+test_invalid_selector(":-internal-fullscreen-document");
+test_invalid_selector(":-internal-html-document");
+test_invalid_selector(":-internal-media-document");
+test_invalid_selector(":-khtml-drag");
+test_invalid_selector(":-webkit-animating-full-screen-transition");
+test_invalid_selector(":-webkit-full-page-media");
+test_invalid_selector(":-webkit-full-screen-ancestor");
+test_invalid_selector(":-webkit-full-screen-controls-hidden");
+test_invalid_selector(":-webkit-full-screen-document");
+
+// Pseudo-elements
+test_invalid_selector("::-apple-attachment-controls-container");
+test_invalid_selector("::-internal-loading-auto-fill-button");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-anplusb.html b/testing/web-platform/tests/css/selectors/parsing/parse-anplusb.html
new file mode 100644
index 0000000000..b7cfd29351
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-anplusb.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors: Test parsing of an+b selectors</title>
+ <link rel="author" title="Chris Nardi" href="mailto:cnardi@chromium.org">
+ <link rel="help" href="https://drafts.csswg.org/selectors-3/#nth-child-pseudo">
+ <link rel="help" href="https://drafts.csswg.org/selectors-3/#nth-last-child-pseudo">
+ <link rel="help" href="https://drafts.csswg.org/selectors-3/#nth-of-type-pseudo">
+ <link rel="help" href="https://drafts.csswg.org/selectors-3/#nth-last-of-type-pseudo">
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style id="teststyles">
+ </style>
+ </head>
+ <body>
+ <script>
+ function add_selector_style(source) {
+ var style_element = document.getElementById("teststyles");
+ style_element.firstChild.data = source + "{ font-size: 1em; }";
+ return style_element.sheet;
+ }
+
+ function assert_selector_serializes_to(source, expected_result) {
+ test(function() {
+ var sheet = add_selector_style(source);
+ assert_equals(sheet.cssRules[0].selectorText, expected_result);
+ }, source + " should be parsed and serialized correctly");
+ }
+
+ function assert_invalid_selector(source) {
+ test(function() {
+ var sheet = add_selector_style(source);
+ assert_equals(sheet.cssRules[0], undefined);
+ }, source + " should not parse");
+ }
+
+ function run_tests_on_anplusb_selector(source) {
+ assert_selector_serializes_to(source + '(1n+0)', source + '(n)');
+ assert_selector_serializes_to(source + '(n+0)', source + '(n)');
+ assert_selector_serializes_to(source + '(n)', source + '(n)');
+ assert_selector_serializes_to(source + '(-n+0)', source + '(-n)');
+ assert_selector_serializes_to(source + '(-n)', source + '(-n)');
+ assert_selector_serializes_to(source + '(N)', source + '(n)');
+ assert_selector_serializes_to(source + '(+n+3)', source + '(n+3)');
+ assert_selector_serializes_to(source + '( +n + 7 )', source + '(n+7)');
+ assert_selector_serializes_to(source + '( N- 123)', source + '(n-123)');
+ assert_selector_serializes_to(source + '(n- 10)', source + '(n-10)');
+ assert_selector_serializes_to(source + '(-n\n- 1)', source + '(-n-1)');
+ assert_selector_serializes_to(source + '( 23n\n\n+\n\n123 )', source + '(23n+123)');
+
+ assert_invalid_selector(source + '(n- 1 2)');
+ assert_invalid_selector(source + '(n-b1)');
+ assert_invalid_selector(source + '(n-+1)');
+ assert_invalid_selector(source + '(n-1n)');
+ assert_invalid_selector(source + '(-n -b1)');
+ assert_invalid_selector(source + '(-1n- b1)');
+ assert_invalid_selector(source + '(-n-13b1)');
+ assert_invalid_selector(source + '(-n-+1)');
+ assert_invalid_selector(source + '(-n+n)');
+ assert_invalid_selector(source + '(+ 1n)');
+ assert_invalid_selector(source + '( n +12 3)');
+ assert_invalid_selector(source + '( 12 n )');
+ assert_invalid_selector(source + '(+12n-0+1)');
+ assert_invalid_selector(source + '(+12N -- 1)');
+ assert_invalid_selector(source + '(+12 N )');
+ assert_invalid_selector(source + '(+ n + 7)');
+ }
+
+ run_tests_on_anplusb_selector(':nth-child');
+ run_tests_on_anplusb_selector(':nth-last-child');
+ run_tests_on_anplusb_selector(':nth-of-type');
+ run_tests_on_anplusb_selector(':nth-last-of-type');
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-attribute.html b/testing/web-platform/tests/css/selectors/parsing/parse-attribute.html
new file mode 100644
index 0000000000..a8fcfb24f5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-attribute.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: Attribute selectors</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#attribute-selectors">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ // Attribute presence and value selectors
+ test_valid_selector('[att]');
+ test_valid_selector('[att=val]', '[att="val"]');
+ test_valid_selector('[att~=val]', '[att~="val"]');
+ test_valid_selector('[att|=val]', '[att|="val"]');
+ test_valid_selector('h1[title]');
+ test_valid_selector("span[class='example']", 'span[class="example"]');
+ test_valid_selector('a[hreflang=fr]', 'a[hreflang="fr"]');
+ test_valid_selector("a[hreflang|='en']", 'a[hreflang|="en"]');
+
+ // Substring matching attribute selectors
+ test_valid_selector('[att^=val]', '[att^="val"]');
+ test_valid_selector('[att$=val]', '[att$="val"]');
+ test_valid_selector('[att*=val]', '[att*="val"]');
+ test_valid_selector('object[type^="image/"]');
+ test_valid_selector('a[href$=".html"]');
+ test_valid_selector('p[title*="hello"]');
+
+ // From Attribute selectors and namespaces examples in spec:
+ test_valid_selector('[*|att]');
+ test_valid_selector('[|att]', '[att]');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-child.html b/testing/web-platform/tests/css/selectors/parsing/parse-child.html
new file mode 100644
index 0000000000..510c45db86
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-child.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: Child combinators</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#child-combinators">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('body > p');
+ test_valid_selector('div ol>li p', 'div ol > li p');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-class.html b/testing/web-platform/tests/css/selectors/parsing/parse-class.html
new file mode 100644
index 0000000000..00abcf838d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-class.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: Class selectors</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#class-html">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('*.pastoral',
+ ['*.pastoral', '.pastoral']);
+ test_valid_selector('.pastoral',
+ ['*.pastoral', '.pastoral']);
+ test_valid_selector('h1.pastoral');
+ test_valid_selector('p.pastoral.marine');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-descendant.html b/testing/web-platform/tests/css/selectors/parsing/parse-descendant.html
new file mode 100644
index 0000000000..5ff3a7bbfd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-descendant.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: Descendant combinator</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#descendant-combinators">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('h1 em');
+ test_valid_selector('div * p');
+ test_valid_selector('div p *[href]',
+ ['div p *[href]', 'div p [href]']);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-focus-visible.html b/testing/web-platform/tests/css/selectors/parsing/parse-focus-visible.html
new file mode 100644
index 0000000000..52ac963add
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-focus-visible.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: :focus-visible pseudo-class</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector(':focus-visible');
+ test_valid_selector('a:focus-visible');
+ test_valid_selector(':focus:not(:focus-visible)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html b/testing/web-platform/tests/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html
new file mode 100644
index 0000000000..a633c913d1
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The relational pseudo-class (disallow nesting :has() inside :has())</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#has-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_invalid_selector('.a:has(.b:has(.c))');
+ test(() => {
+ // It's not easy to check that these are invalid because :is() and :where()
+ // use forgiving parsing. Check that they never match instead.
+ assert_false(document.documentElement.matches(":has(:is(:has(*)))"));
+ assert_false(document.documentElement.matches(":has(:where(:has(*)))"));
+ assert_true(document.documentElement.matches(":has(:is(:has(*), script))"));
+ assert_true(document.documentElement.matches(":has(:where(:has(*), script))"));
+ })
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-has-forgiving-selector.html b/testing/web-platform/tests/css/selectors/parsing/parse-has-forgiving-selector.html
new file mode 100644
index 0000000000..ef7748326e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-has-forgiving-selector.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The relational pseudo-class (forgiving selector parsing)</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8356">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ // disallow nesting :has() inside :has(), but serialize back unchanged
+ test_valid_forgiving_selector(':has(:is(:has(*)))');
+ test_valid_forgiving_selector(':has(:where(:has(*)))');
+ // serialize :is() back unchanged
+ test_valid_forgiving_selector(':has(:is(.a, 123))');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-has.html b/testing/web-platform/tests/css/selectors/parsing/parse-has.html
new file mode 100644
index 0000000000..1c0f254ba5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-has.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The relational pseudo-class</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#has-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector(':has(a)');
+ test_valid_selector(':has(#a)');
+ test_valid_selector(':has(.a)');
+ test_valid_selector(':has([a])');
+ test_valid_selector(':has([a="b"])');
+ test_valid_selector(':has([a|="b"])');
+ test_valid_selector(':has(:hover)');
+ test_valid_selector('*:has(.a)', ['*:has(.a)', ':has(.a)']);
+ test_valid_selector('.a:has(.b)');
+ test_valid_selector('.a:has(> .b)');
+ test_valid_selector('.a:has(~ .b)');
+ test_valid_selector('.a:has(+ .b)');
+ test_valid_selector('.a:has(.b) .c');
+ test_valid_selector('.a .b:has(.c)');
+ test_valid_selector('.a .b:has(.c .d)');
+ test_valid_selector('.a .b:has(.c .d) .e');
+ test_valid_selector('.a:has(.b:is(.c .d))');
+ test_valid_selector('.a:is(.b:has(.c) .d)');
+ test_valid_selector('.a:not(:has(.b))');
+ test_valid_selector('.a:has(:not(.b))');
+ test_valid_selector('.a:has(.b):has(.c)');
+ test_valid_selector('*|*:has(*)', ':has(*)');
+ test_valid_selector(':has(*|*)', ':has(*)');
+ test_invalid_selector(':has');
+ test_invalid_selector('.a:has');
+ test_invalid_selector('.a:has b');
+ /* :has() is unforgiving, but :is() can still forgive */
+ test_invalid_selector(':has()');
+ test_invalid_selector(':has(123)');
+ test_invalid_selector(':has(.a, 123)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-id.html b/testing/web-platform/tests/css/selectors/parsing/parse-id.html
new file mode 100644
index 0000000000..2441c4217e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-id.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: ID selectors</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#id-selectors">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('h1#chapter1');
+ test_valid_selector('#chapter1');
+ test_valid_selector('*#z98y',
+ ['*#z98y', '#z98y']);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-is-where.html b/testing/web-platform/tests/css/selectors/parsing/parse-is-where.html
new file mode 100644
index 0000000000..ee73fe0f88
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-is-where.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<title>CSS Selectors: :is() and :where() parsing</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#zero-matches">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ function assert_valid(valid, pattern, expected_pattern, description) {
+ for (let pseudo of ["is", "where"]) {
+ let selector = pattern.replace("{}", ":" + pseudo);
+ let expected_selector = selector;
+ if (expected_pattern != null)
+ expected_selector = expected_pattern.replace("{}", ":" + pseudo);
+ if (valid) {
+ test_valid_selector(selector, expected_selector);
+ } else {
+ test_valid_forgiving_selector(selector);
+ }
+ }
+ }
+
+ assert_valid(true, "{}(div )", "{}(div)", "Trailing whitespace");
+ assert_valid(true, "{}(div + bar, div ~ .baz)", null, "Multiple selectors with combinators");
+
+ assert_valid(true, "{}(:is(div))", null, "Nested :is");
+ assert_valid(true, "{}(:where(div))", null, "Nested :where");
+
+ assert_valid(true, ":host({}(div))", null, "Nested inside :host, without combinators");
+ assert_valid(true, ":host({}(div ))", ":host({}(div))", "Nested inside :host, with trailing whitespace");
+ // See https://github.com/w3c/csswg-drafts/issues/5093
+ assert_valid(false, ":host({}(div .foo))", null, "Nested inside :host, with combinators");
+
+ assert_valid(true, "{}(:hover, :active)", null, "Pseudo-classes inside");
+ assert_valid(true, "{}(div):hover", null, "Pseudo-classes after");
+ assert_valid(true, "{}(div)::before", null, "Pseudo-elements after");
+ assert_valid(false, "{}(::before)", null, "Pseudo-elements inside");
+
+ assert_valid(true, "{}(div) + bar", null, "Combinators after");
+ assert_valid(true, "::part(foo){}(:hover)", null, "After part with simple pseudo-class");
+ assert_valid(false, "::part(foo){}([attr='value'])", null, "After part with invalid selector after");
+
+ assert_valid(true, ":not({}(div))", null, "Nested inside :not, without combinators");
+ assert_valid(true, ":not({}(div .foo))", null, "Nested inside :not, with combinators");
+ // This should be invalid even with the forgiving behavior because
+ // `<any-value>` doesn't allow bad tokens:
+ // https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value
+ test_invalid_selector(`:is(# C4єанйтж╕/┘ГЁжЮХєа▓┐ЁЭБМєаСеЁЭЖА%=[ямм0)`);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-is.html b/testing/web-platform/tests/css/selectors/parsing/parse-is.html
new file mode 100644
index 0000000000..68236445c5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-is.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The Matches-Any Pseudo-class: ':is()'</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#matches">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector(':is(ul,ol,.list) > [hidden]',
+ ':is(ul, ol, .list) > [hidden]');
+ test_valid_selector(':is(:hover,:focus)',
+ ':is(:hover, :focus)');
+ test_valid_selector('a:is(:not(:hover))');
+
+ test_valid_selector(':is(#a)');
+ test_valid_selector('.a.b ~ :is(.c.d ~ .e.f)');
+ test_valid_selector('.a.b ~ .c.d:is(span.e + .f, .g.h > .i.j .k)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-not.html b/testing/web-platform/tests/css/selectors/parsing/parse-not.html
new file mode 100644
index 0000000000..f455059251
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-not.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The negation pseudo-class</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#negation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('button:not([disabled])');
+ test_valid_selector('*:not(foo)',
+ ['*:not(foo)', ':not(foo)']);
+ test_valid_selector(':not(:link):not(:visited)');
+ test_valid_selector('*|*:not(*)', ':not(*)');
+ test_valid_selector(':not(:hover)');
+ test_valid_selector(':not(*|*)', ':not(*)');
+ test_valid_selector('foo:not(bar)');
+ test_valid_selector(':not(:not(foo))');
+ test_valid_selector(':not(.a .b)');
+ test_valid_selector(':not(.a + .b)');
+ test_valid_selector(':not(.a .b ~ c)');
+ test_valid_selector(':not(span.a, div.b)');
+ test_valid_selector(':not(.a .b ~ c, .d .e)');
+ test_valid_selector(':not(:host)');
+ test_valid_selector(':not(:host(.a))');
+ test_valid_selector(':host(:not(.a))');
+ test_valid_selector(':not(:host(:not(.a)))');
+ test_valid_selector(':not([disabled][selected])', ':not([disabled][selected])');
+ test_valid_selector(':not([disabled],[selected])', ':not([disabled], [selected])');
+
+ test_invalid_selector(':not()');
+ test_invalid_selector(':not(:not())');
+ test_invalid_selector(':not(::before)');
+ test_invalid_selector(':not(:unknownpseudo)');
+ test_invalid_selector(':not(.a, :unknownpseudo)');
+ test_invalid_selector(':not(:unknownpseudo, .a)');
+ test_invalid_selector(':host(:not(.a .b))');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-part.html b/testing/web-platform/tests/css/selectors/parsing/parse-part.html
new file mode 100644
index 0000000000..c166fd7765
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-part.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>CSS Selectors: part pseudo selectors</title>
+<link rel="help" href="https://drafts.csswg.org/css-shadow-parts/#part" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector("::part(--foo)");
+ test_valid_selector("::part(bar)");
+ test_valid_selector("::part(--)");
+ test_valid_selector("::part(--0)");
+ test_valid_selector("::part(foo bar)");
+ test_valid_selector("::part(-foo bar)");
+ test_valid_selector("::part(foo):focus");
+ test_valid_selector("::part(foo):hover");
+ test_valid_selector("::part(foo):focus-within");
+ test_valid_selector("::part(foo)::before");
+ test_valid_selector("::part(foo)::after");
+ test_valid_selector("::part(foo)::placeholder");
+ test_valid_selector("::part(foo)::first-line");
+ test_valid_selector("::part(foo)::first-letter");
+ test_valid_selector("::part(foo)::file-selector-button");
+ test_valid_selector("::part(foo):is(:focus)");
+ test_valid_selector(":lang(en)::part(foo)");
+ test_valid_selector(":dir(ltr)::part(foo)");
+ test_valid_selector("::part(foo):lang(en)");
+ test_valid_selector("::part(foo):dir(ltr)");
+ test_invalid_selector(":part()");
+ test_invalid_selector(":part(0)");
+ test_invalid_selector(":part('foo')");
+ test_invalid_selector(":part([foo])");
+ test_invalid_selector('::part(foo) + ::part(bar)');
+ test_valid_forgiving_selector("::part(foo):is(ul)");
+ test_valid_forgiving_selector("::part(foo):is(nav ul)");
+ test_valid_forgiving_selector("::part(foo):where(ul)");
+ test_valid_forgiving_selector("::part(foo):where(nav ul)");
+ test_invalid_selector("::part(foo):has(li)");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-sibling.html b/testing/web-platform/tests/css/selectors/parsing/parse-sibling.html
new file mode 100644
index 0000000000..4f7a7a3fbc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-sibling.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: Sibling combinators</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#sibling-combinators">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('math + p');
+ test_valid_selector('h1.opener + h2');
+ test_valid_selector('h1 ~ pre');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-slotted.html b/testing/web-platform/tests/css/selectors/parsing/parse-slotted.html
new file mode 100644
index 0000000000..4b7b4a3b56
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-slotted.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>CSS Selectors: slotted pseudo selectors</title>
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#slotted-pseudo" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector("::slotted(bar)");
+ test_valid_selector('::slotted([attr="foo"])');
+ test_valid_selector("::slotted(*)");
+ test_valid_selector("::slotted(.class)");
+ test_valid_selector("::slotted(:not(foo))");
+ test_valid_selector('::slotted(:not(:nth-last-of-type(2)):not([slot="foo"]))');
+ test_valid_selector("::slotted(:first-child)");
+ test_valid_selector("::slotted(:hover)");
+ test_invalid_selector("::slotted");
+ test_invalid_selector("::slotted()");
+ test_invalid_selector("::slotted(0)");
+ test_invalid_selector(":slotted(foo)");
+ test_invalid_selector("::slotted(foo):first-child");
+ test_invalid_selector("::slotted(foo):hover");
+ test_invalid_selector("::slotted(foo):focus");
+ test_invalid_selector("::slotted(foo):lang(en)");
+ test_invalid_selector("::slotted(foo):dir(ltr)");
+ test_invalid_selector('::slotted(foo) + ::slotted(bar)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-state.html b/testing/web-platform/tests/css/selectors/parsing/parse-state.html
new file mode 100644
index 0000000000..95e3134b2c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-state.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>CSS Selectors: custom state pseudo selectors</title>
+<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/8213" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector(":state(--foo)");
+ test_valid_selector(":state(bar)");
+ test_valid_selector(":state(--)");
+ test_valid_selector(":state(--0)");
+ test_valid_selector(":host(:state(--foo))");
+ test_valid_selector('my-input[type="foo"]:state(checked)');
+ test_valid_selector('my-input[type="foo"]:state(--0)::before');
+ test_valid_selector('my-input[type="foo"]:state(--0)::part(inner)');
+ test_valid_selector(
+ 'my-input[type="foo"]:state(--0)::part(inner):state(bar)',
+ );
+ test_valid_selector('::part(inner):state(bar)::before');
+ test_valid_selector('::part(inner):state(bar)::after');
+ test_invalid_selector(":state");
+ test_invalid_selector(":state(");
+ test_invalid_selector(":state()");
+ test_invalid_selector(":state(0)");
+ test_invalid_selector(":state(0rem)");
+ test_invalid_selector(":state(url())");
+ test_invalid_selector(":state(foo(1))");
+ test_invalid_selector(":state(:host)");
+ test_invalid_selector("my-input::after:state(foo)");
+ test_invalid_selector('::part(inner):state(bar)::before:state(foo)');
+ test_invalid_selector('::part(inner):state(bar)::after:state(foo)');
+ test_invalid_selector("my-input::first-letter:state(foo)");
+ test_invalid_selector('::slotted(foo):state(foo)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-universal.html b/testing/web-platform/tests/css/selectors/parsing/parse-universal.html
new file mode 100644
index 0000000000..e944a93f12
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-universal.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: Universal selector</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#universal-selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector('*');
+ test_valid_selector('div :first-child',
+ ['div *:first-child', 'div :first-child']);
+ test_valid_selector('div *:first-child',
+ ['div *:first-child', 'div :first-child']);
+</script>
diff --git a/testing/web-platform/tests/css/selectors/parsing/parse-where.html b/testing/web-platform/tests/css/selectors/parsing/parse-where.html
new file mode 100644
index 0000000000..3a90969570
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/parsing/parse-where.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The Specificity-adjustment Pseudo-class: ':where()'</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#zero-matches">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+ test_valid_selector(':where(ul,ol,.list) > [hidden]',
+ ':where(ul, ol, .list) > [hidden]');
+ test_valid_selector(':where(:hover,:focus)',
+ ':where(:hover, :focus)');
+ test_valid_selector('a:where(:not(:hover))');
+
+ test_valid_selector(':where(#a)');
+ test_valid_selector('.a.b ~ :where(.c.d ~ .e.f)');
+ test_valid_selector('.a.b ~ .c.d:where(span.e + .f, .g.h > .i.j .k)');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/placeholder-shown.html b/testing/web-platform/tests/css/selectors/placeholder-shown.html
new file mode 100644
index 0000000000..62f6f96a10
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/placeholder-shown.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>CSS Selectors Test: :placeholder-shown matching</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#placeholder">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ :not(:placeholder-shown) + #t1,
+ :placeholder-shown + #t2,
+ :placeholder-shown + #t3,
+ :placeholder-shown + #t4,
+ :not(:placeholder-shown) + #t5,
+ :not(:placeholder-shown) + #t6,
+ :not(:placeholder-shown) + #t7 {
+ color: green;
+ }
+</style>
+<input type="text"><span id="t1">Should be green</span>
+<input type="text" placeholder><span id="t2">Should be green</span>
+<input type="text" placeholder=""><span id="t3">Should be green</span>
+<input type="text" placeholder="placeholder"><span id="t4">Should be green</span>
+<input type="text" placeholder value="value"><span id="t5">Should be green</span>
+<input type="text" placeholder="" value="value"><span id="t6">Should be green</span>
+<input type="text" placeholder="placeholder" value="value"><span id="t7">Should be green</span>
+<script>
+ const green = "rgb(0, 128, 0)";
+
+ test(() => assert_equals(getComputedStyle(t1).color, green,
+ "No placeholder attribute"));
+ test(() => assert_equals(getComputedStyle(t2).color, green,
+ "Placeholder attribute without value"));
+ test(() => assert_equals(getComputedStyle(t3).color, green,
+ "Placeholder attribute - empty string"));
+ test(() => assert_equals(getComputedStyle(t4).color, green,
+ "Placeholder attribute - non-empty string"));
+ test(() => assert_equals(getComputedStyle(t5).color, green,
+ "Placeholder attribute without value - input text"));
+ test(() => assert_equals(getComputedStyle(t6).color, green,
+ "Placeholder attribute - empty string - input text"));
+ test(() => assert_equals(getComputedStyle(t7).color, green,
+ "Placeholder attribute - non-empty string - input text"));
+</script>
diff --git a/testing/web-platform/tests/css/selectors/pseudo-enabled-disabled.html b/testing/web-platform/tests/css/selectors/pseudo-enabled-disabled.html
new file mode 100644
index 0000000000..521767de37
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/pseudo-enabled-disabled.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#enableddisabled">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="container">
+<button id="button_enabled"></button>
+<button id="button_disabled" disabled></button>
+<input id="input_enabled">
+<input id="input_disabled" disabled>
+<select id="select_enabled"></select>
+<select id="select_disabled" disabled></select>
+<textarea id="textarea_enabled"></textarea>
+<textarea id="textarea_disabled" disabled></textarea>
+<span id="incapable"></span>
+</div>
+
+<script>
+test(() => {
+ const container = document.querySelector('#container');
+ const matched = container.querySelectorAll(':enabled');
+ for (let element of matched) {
+ assert_true(element.id.endsWith('_enabled'), element.id);
+ }
+}, ':enabeld should match to enabled controls');
+
+test(() => {
+ const container = document.querySelector('#container');
+ const matched = container.querySelectorAll(':disabled');
+ for (let element of matched) {
+ assert_true(element.id.endsWith('_disabled'), element.id);
+ }
+}, ':disabled should match to enabled controls');
+
+test(() => {
+ const container = document.querySelector('#container');
+ const matched = container.querySelectorAll(':not(:enabled)');
+ for (let element of matched) {
+ assert_true(element.id.endsWith('_disabled') || element.id == 'incapable', element.id);
+ }
+}, ':not(:enabeld) should match to disabled controls and non-controls');
+
+test(() => {
+ const container = document.querySelector('#container');
+ const matched = container.querySelectorAll(':not(:disabled)');
+ for (let element of matched) {
+ assert_true(element.id.endsWith('_enabled') || element.id == 'incapable', element.id);
+ }
+}, ':not(:disabled) should match to enabled controls and non-controls');
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/query/query-is.html b/testing/web-platform/tests/css/selectors/query/query-is.html
new file mode 100644
index 0000000000..918eaee701
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/query/query-is.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Selectors Level 4: query using :is()</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#matches">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/css/support/query-testcommon.js"></script>
+</head>
+<body>
+ <div id="a1" class="a">
+ <div class="b" id="b1"></div>
+ <div class="c" id="c1"></div>
+ <div class="c" id="d"></div>
+ <div class="e" id="e1"></div>
+ <div class="f" id="f1"></div>
+ <div class="g">
+ <div class="b" id="b2">
+ <div class="b" id="b3"></div>
+ </div>
+ </div>
+ <div class="h" id="h1"></div>
+ </div>
+ <div class="c" id="c2">
+ <div id="a2" class="a"></div>
+ <div class="e" id="e2"></div>
+ </div>
+ <script>
+ 'use strict';
+
+ // Simple selector arguments are supported by :is
+ test_query_selector(document, '.a :is(.b, .c)',
+ ['b1', 'c1', 'd', 'b2', 'b3']);
+
+ // Compound selector arguments are supported by :is
+ test_query_selector(document, '.a :is(.c#d, .e)',
+ ['d', 'e1']);
+
+ // Complex selector arguments are supported by :is
+ test_query_selector(document, '.a :is(.e+.f, .g>.b, .h)',
+ ['f1', 'b2', 'h1']);
+
+ // Nested selector arguments are supported by :is
+ test_query_selector(document, '.a+:is(.b+.f, :is(.c>.e, .g))',
+ 'e2');
+
+ // Nested :where selector arguments are supported by :is
+ test_query_selector(document, '.a :is(:where(:where(.b ~ .c)))',
+ ['c1', 'd']);
+
+ // Nested :not selector arguments are supported by :is
+ test_query_selector(document, '.b + :is(.c + .c + .c, .b + .c:not(span), .b + .c + .e) ~ .h',
+ ['h1']);
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/query/query-where.html b/testing/web-platform/tests/css/selectors/query/query-where.html
new file mode 100644
index 0000000000..b7cf5e1b20
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/query/query-where.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Selectors Level 4: query using :where()</title>
+ <link rel="help" href="https://drafts.csswg.org/selectors/#zero-matches">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/css/support/query-testcommon.js"></script>
+</head>
+<body>
+ <div id="a1" class="a">
+ <div class="b" id="b1"></div>
+ <div class="c" id="c1"></div>
+ <div class="c" id="d"></div>
+ <div class="e" id="e1"></div>
+ <div class="f" id="f1"></div>
+ <div class="g">
+ <div class="b" id="b2">
+ <div class="b" id="b3"></div>
+ </div>
+ </div>
+ <div class="h" id="h1"></div>
+ </div>
+ <div class="c" id="c2">
+ <div id="a2" class="a"></div>
+ <div class="e" id="e2"></div>
+ </div>
+ <script>
+ 'use strict';
+
+ // Simple selector arguments are supported by :where
+ test_query_selector(document, '.a :where(.b, .c)',
+ ['b1', 'c1', 'd', 'b2', 'b3']);
+
+ // Compound selector arguments are supported by :where
+ test_query_selector(document, '.a :where(.c#d, .e)',
+ ['d', 'e1']);
+
+ // Complex selector arguments are supported by :where
+ test_query_selector(document, '.a :where(.e+.f, .g>.b, .h)',
+ ['f1', 'b2', 'h1']);
+
+ // Nested selector arguments are supported by :where
+ test_query_selector(document, '.a+:where(.b+.f, :where(.c>.e, .g))',
+ ['e2']);
+
+ // Nested :is selector arguments are supported by :where
+ test_query_selector(document, '.a :where(:is(:is(.b ~ .c)))',
+ ['c1', 'd']);
+
+ // Nested :not selector arguments are supported by :where
+ test_query_selector(document, '.b + :where(.c + .c + .c, .b + .c:not(span), .b + .c + .e) ~ .h',
+ ['h1']);
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/remove-hovered-element-ref.html b/testing/web-platform/tests/css/selectors/remove-hovered-element-ref.html
new file mode 100644
index 0000000000..9527a465ea
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/remove-hovered-element-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<title>CSS Reftest Reference</title>
+<p>Clicking the right square should make the left one go green.</p>
+<div style="width: 100px; height: 100px; background: green;"></div>
diff --git a/testing/web-platform/tests/css/selectors/remove-hovered-element.html b/testing/web-platform/tests/css/selectors/remove-hovered-element.html
new file mode 100644
index 0000000000..ec2eed1d47
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/remove-hovered-element.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Selectors: :hover style cleared on ancestor when hovered element is removed.</title>
+<link rel="help" href="https://drafts.csswg.org/selectors/#the-hover-pseudo">
+<link rel="match" href="remove-hovered-element-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+ div {
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ #outer:hover {
+ background-color: red;
+ }
+ #relative {
+ position: relative;
+ left: 150px;
+ }
+</style>
+<p>Clicking the right square should make the left one go green.</p>
+<div id="outer">
+ <div id="relative"><div id="inner">Click me</div></div>
+</div>
+<script>
+ inner.addEventListener("click", () => {
+ relative.style.display = "none";
+ // force layout box removal
+ document.body.offsetTop;
+ relative.remove();
+ takeScreenshot();
+ });
+
+ // Hover #inner and click.
+ var actions = new test_driver.Actions();
+ actions.pointerMove(0, 0, {origin: inner}).pointerDown().pointerUp().send();
+</script>
diff --git a/testing/web-platform/tests/css/selectors/resources/blue15x15.png b/testing/web-platform/tests/css/selectors/resources/blue15x15.png
new file mode 100644
index 0000000000..89de32fdb8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/resources/blue15x15.png
Binary files differ
diff --git a/testing/web-platform/tests/css/selectors/root-siblings.html b/testing/web-platform/tests/css/selectors/root-siblings.html
new file mode 100644
index 0000000000..c2f897ab28
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/root-siblings.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test: Parsing check for * ~ :root error handling</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#selector-syntax">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="assert" content="* ~ :root should not match anything">
+<style>
+* ~ :root div {
+ background-color: red;
+}
+div {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div></div>
diff --git a/testing/web-platform/tests/css/selectors/scope-selector.html b/testing/web-platform/tests/css/selectors/scope-selector.html
new file mode 100644
index 0000000000..06b6bc1378
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/scope-selector.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<link rel='help' href='https://drafts.csswg.org/selectors-4/#the-scope-pseudo'>
+<meta name='description' content=':scope should match when context object is a ShadowRoot or a DocumentFragment'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<div id='shadowHost'></div>
+<script>
+'use strict'
+const shadowHost = document.getElementById("shadowHost");
+const shadowRoot = shadowHost.attachShadow({mode:'open'})
+shadowRoot.appendChild(document.createElement("div"));
+
+test (() => {
+ assert_equals(shadowRoot.querySelectorAll(':scope > div').length, 0, 'should not match in shadow root');
+});
+
+const documentFragment = document.createDocumentFragment();
+documentFragment.appendChild(document.createElement("div"));
+
+test(() => {
+ assert_equals(documentFragment.querySelectorAll(':scope > div').length, 0, 'should not match in document fragment');
+});
+
+test(() => {
+ assert_equals(shadowRoot.firstChild.querySelector(':scope'), null, 'should return null');
+ assert_equals(shadowRoot.firstChild.querySelectorAll(':scope').length, 0, 'should return 0');
+
+ assert_equals(shadowRoot.querySelector(':scope'), null, 'should return null');
+ assert_equals(shadowRoot.querySelectorAll(':scope').length, 0, 'should return 0');
+
+ assert_equals(documentFragment.querySelector(':scope'), null, 'should return null');
+ assert_equals(documentFragment.querySelectorAll(':scope').length, 0, 'should return 0');
+
+ assert_equals(document.querySelector(':scope'), document.documentElement, 'should return the document element');
+ assert_equals(document.querySelectorAll(':scope').length, 1, 'should return 1');
+}, 'querySelector() with ":scope" should return the document element, if present in the subtree');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/scope-without-scoping.html b/testing/web-platform/tests/css/selectors/scope-without-scoping.html
new file mode 100644
index 0000000000..2ee7619e80
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/scope-without-scoping.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="UTF-8">
+<title>Selectors Level 4: :scope without scoping</title>
+<link rel="author" title="Xidorn Quan" href="mailto:me@upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#scope-pseudo">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<style>
+ div {
+ width: 100px;
+ height: 100px;
+ background: red;
+ }
+ :scope > body > div {
+ background: green;
+ }
+</style>
+<body>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selection-image-001-no-selection-noref.html b/testing/web-platform/tests/css/selectors/selection-image-001-no-selection-noref.html
new file mode 100644
index 0000000000..ad2104bef6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selection-image-001-no-selection-noref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1449010">
+<p>
+ Some text <img src="resources/blue15x15.png"> some more.
+</p>
diff --git a/testing/web-platform/tests/css/selectors/selection-image-001-noref.html b/testing/web-platform/tests/css/selectors/selection-image-001-noref.html
new file mode 100644
index 0000000000..df3d946ecb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selection-image-001-noref.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1449010">
+<p>
+ Some text <img src="resources/blue15x15.png"> some more.
+</p>
+<script>
+onload = () => {
+ getSelection().removeAllRanges();
+ let r = document.createRange();
+ r.selectNode(document.documentElement);
+ getSelection().addRange(r);
+}
+</script>
diff --git a/testing/web-platform/tests/css/selectors/selection-image-001.html b/testing/web-platform/tests/css/selectors/selection-image-001.html
new file mode 100644
index 0000000000..51a1643c4e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selection-image-001.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>::selection is respected on images</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1449010">
+<link rel="mismatch" href="selection-image-001-noref.html">
+<style>
+img::-moz-selection {
+ background: green;
+}
+img::selection {
+ background: green;
+}
+</style>
+<p>
+ Some text <img src="resources/blue15x15.png"> some more.
+</p>
+<script>
+onload = () => {
+ getSelection().removeAllRanges();
+ let r = document.createRange();
+ r.selectNode(document.documentElement);
+ getSelection().addRange(r);
+}
+</script>
diff --git a/testing/web-platform/tests/css/selectors/selection-image-002.html b/testing/web-platform/tests/css/selectors/selection-image-002.html
new file mode 100644
index 0000000000..72958da207
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selection-image-002.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>CSS Test: Image and text selection is painted.</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1449010">
+<link rel="mismatch" href="selection-image-001-no-selection-noref.html">
+<p>
+ Some text <img src="resources/blue15x15.png"> some more.
+</p>
+<script>
+onload = () => {
+ getSelection().removeAllRanges();
+ let r = document.createRange();
+ r.selectNode(document.documentElement);
+ getSelection().addRange(r);
+}
+</script>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-emptify-placeholder.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-emptify-placeholder.html
new file mode 100644
index 0000000000..17316ede26
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-emptify-placeholder.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>When non-empty placeholder becomes empty, :placeholder-shown test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#placeholder">
+<input id="myinput" type="text" placeholder="FAIL">
+<textarea id="mytextarea" placeholder="FAIL"></textarea>
+<script>
+test(() => {
+ const input = document.querySelector("input");
+ input.placeholder = "";
+ input.value = "NO RED";
+ assert_false(input.matches(":placeholder-shown"));
+}, "input:placeholder-shown should not be matched");
+
+test(() => {
+ const textarea = document.querySelector("textarea");
+ textarea.placeholder = "";
+ textarea.value = "No RED";
+ assert_false(textarea.matches(":placeholder-shown"));
+}, "textarea:placeholder-shown should not be matched");
+</script>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001-ref.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001-ref.html
new file mode 100644
index 0000000000..2ac4c10979
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <input placeholder="text"><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001.html
new file mode 100644
index 0000000000..8ce91d7954
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-001.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <title>Check for correctly updating :placeholder-shown matching on type change</title>
+ <link rel="match" href="selector-placeholder-shown-type-change-001-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#placeholder">
+ <style>
+ span { color: red; }
+ :placeholder-shown + span { color: green }
+ </style>
+ <script>
+ onload = function() {
+ // setTimeout because in some browsers apparently a toplevel restyle
+ // happens right after the load event fires?
+ setTimeout(function() {
+ document.querySelector("input").type = "";
+ document.documentElement.className = "";
+ }, 10);
+ }
+ </script>
+ </head>
+ <body>
+ <input type="hidden" placeholder="text"><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002-ref.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002-ref.html
new file mode 100644
index 0000000000..884a70d1fb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002.html
new file mode 100644
index 0000000000..0319e255cd
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-002.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <title>Check for correctly updating :placeholder-shown matching on type change</title>
+ <link rel="match" href="selector-placeholder-shown-type-change-002-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#placeholder">
+ <style>
+ span { color: green; }
+ :placeholder-shown + span { color: red }
+ </style>
+ <script>
+ onload = function() {
+ // setTimeout because in some browsers apparently a toplevel restyle
+ // happens right after the load event fires?
+ setTimeout(function() {
+ document.querySelector("input").type = "hidden";
+ document.documentElement.className = "";
+ }, 10);
+ }
+ </script>
+ </head>
+ <body>
+ <input placeholder="text"><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003-ref.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003-ref.html
new file mode 100644
index 0000000000..884a70d1fb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003.html b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003.html
new file mode 100644
index 0000000000..90485d839a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-placeholder-shown-type-change-003.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <title>Check for correctly updating :placeholder-shown matching on type change</title>
+ <link rel="match" href="selector-placeholder-shown-type-change-003-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#placeholder">
+ <style>
+ span { color: green; }
+ :placeholder-shown + span { color: red }
+ </style>
+ <script>
+ onload = function() {
+ // setTimeout because in some browsers apparently a toplevel restyle
+ // happens right after the load event fires?
+ setTimeout(function() {
+ document.querySelector("input").type = "hidden";
+ document.documentElement.className = "";
+ }, 10);
+ }
+ </script>
+ </head>
+ <body>
+ <input required placeholder="text"><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-read-write-type-change-001-ref.html b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-001-ref.html
new file mode 100644
index 0000000000..6ad6b107b9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <input type="button"><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-read-write-type-change-001.html b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-001.html
new file mode 100644
index 0000000000..0dd083002a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-001.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Check for correctly updating :read-write matching on type change</title>
+ <link rel="match" href="selector-read-write-type-change-001-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#rw-pseudos">
+ <style>
+ span { color: green; }
+ :read-write + span { color: red }
+ </style>
+ <script>
+ onload = function() {
+ document.querySelector("input").type = "button";
+ }
+ </script>
+ </head>
+ <body>
+ <input required><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-read-write-type-change-002-ref.html b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-002-ref.html
new file mode 100644
index 0000000000..d8e9641876
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-002-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <input required><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-read-write-type-change-002.html b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-002.html
new file mode 100644
index 0000000000..491a01ba6c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-read-write-type-change-002.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <title>Check for correctly updating :read-write matching on type change</title>
+ <link rel="match" href="selector-read-write-type-change-002-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#rw-pseudos">
+ <style>
+ span { color: red; }
+ :read-write + span { color: green }
+ </style>
+ <script>
+ onload = function() {
+ // setTimeout because in some browsers apparently a toplevel restyle
+ // happens right after the load event fires?
+ setTimeout(function() {
+ document.querySelector("input").type = "";
+ document.documentElement.className = "";
+ }, 10);
+ }
+ </script>
+ </head>
+ <body>
+ <input type="hidden" required><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-required-ref.html b/testing/web-platform/tests/css/selectors/selector-required-ref.html
new file mode 100644
index 0000000000..038a8a9b6f
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-required-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS level4 Selector :required and :optional</title>
+ <link rel="author" title="LEE YUN HEE" href="mailto:zzirasi@gmail.com">
+
+ <style>
+ input {border:3px solid green;}
+ </style>
+ </head>
+ <body>
+ <p>
+ You should see a green input box.
+ </p>
+ <p>
+ <input>
+ </p>
+ <p>
+ <input>
+ </p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-required-type-change-001-ref.html b/testing/web-platform/tests/css/selectors/selector-required-type-change-001-ref.html
new file mode 100644
index 0000000000..6ad6b107b9
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-required-type-change-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <input type="button"><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-required-type-change-001.html b/testing/web-platform/tests/css/selectors/selector-required-type-change-001.html
new file mode 100644
index 0000000000..1d0a5a10c4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-required-type-change-001.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Check for correctly updating :required matching on type change</title>
+ <link rel="match" href="selector-required-type-change-001-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#opt-pseudos">
+ <style>
+ span { color: green; }
+ :required + span { color: red }
+ </style>
+ <script>
+ onload = function() {
+ document.querySelector("input").type = "button";
+ }
+ </script>
+ </head>
+ <body>
+ <input required><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-required-type-change-002-ref.html b/testing/web-platform/tests/css/selectors/selector-required-type-change-002-ref.html
new file mode 100644
index 0000000000..d8e9641876
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-required-type-change-002-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ span { color: green; }
+ </style>
+ </head>
+ <body>
+ <input required><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-required-type-change-002.html b/testing/web-platform/tests/css/selectors/selector-required-type-change-002.html
new file mode 100644
index 0000000000..739f5f3f71
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-required-type-change-002.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head>
+ <title>Check for correctly updating :required matching on type change</title>
+ <link rel="match" href="selector-required-type-change-002-ref.html">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#opt-pseudos">
+ <style>
+ span { color: red; }
+ :required + span { color: green }
+ </style>
+ <script>
+ onload = function() {
+ // setTimeout because in some browsers apparently a toplevel restyle
+ // happens right after the load event fires?
+ setTimeout(function() {
+ document.querySelector("input").type = "";
+ document.documentElement.className = "";
+ }, 10);
+ }
+ </script>
+ </head>
+ <body>
+ <input type="hidden" required><span>This should be green</span>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-required.html b/testing/web-platform/tests/css/selectors/selector-required.html
new file mode 100644
index 0000000000..9c0899ad2b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-required.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS level4 Selector :required and :optional</title>
+ <link rel="author" title="LEE YUN HEE" href="mailto:zzirasi@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/selectors4/#opt-pseudos">
+ <meta name="assert" content="You should see a green input box.">
+ <link rel="match" href="selector-required-ref.html">
+ <style>
+ input {border:3px solid red;}
+ :required {border-color:green;}
+ :optional {border-color:green;}
+ </style>
+ </head>
+ <body>
+ <p>
+ You should see a green input box.
+ </p>
+ <p>
+ <input required>
+ </p>
+ <p>
+ <input optional>
+ </p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selector-structural-pseudo-root-ref.html b/testing/web-platform/tests/css/selectors/selector-structural-pseudo-root-ref.html
new file mode 100644
index 0000000000..6523fd3b64
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-structural-pseudo-root-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<style>
+html { background: green; }
+</style>
+<body>
+
+</body>
diff --git a/testing/web-platform/tests/css/selectors/selector-structural-pseudo-root.html b/testing/web-platform/tests/css/selectors/selector-structural-pseudo-root.html
new file mode 100644
index 0000000000..2009ec17fb
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selector-structural-pseudo-root.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<style>
+html { background: red; }
+html:nth-child(1):nth-last-child(1):nth-of-type(1):nth-last-of-type(1):first-child:last-child:only-child:first-of-type:last-of-type:only-of-type { background: green; }
+</style>
+<link rel="help" href="https://www.w3.org/TR/css3-selectors/#structural-pseudos">
+<link rel="match" href="selector-structural-pseudo-root-ref.html">
+<meta name="assert" content="Structural pseudo-classes match the root element, sibling pseudos are based on siblings without needing a parent (Selectors 3 erratum)"> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-000-ref.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-000-ref.html
new file mode 100644
index 0000000000..466e9f464b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-000-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching reference</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+
+<style>
+div.test { color: green; }
+</style>
+
+<div class="test">This should be green</div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-000.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-000.html
new file mode 100644
index 0000000000..1d66bebbc6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-000.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+:lang(en-US) { color: green; }
+</style>
+
+<div class="test">This should be green</div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-001.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-001.html
new file mode 100644
index 0000000000..908643fca8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-001.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang(fr) { color: green; }
+</style>
+
+<div class="test"><span lang="fr">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-002.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-002.html
new file mode 100644
index 0000000000..0be426c66e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-002.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("FR") { color: green; }
+</style>
+
+<div class="test"><span lang="fr">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-003.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-003.html
new file mode 100644
index 0000000000..a3e5340b6e
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-003.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("Fr") { color: green; }
+</style>
+
+<div class="test"><span lang="fR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-004.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-004.html
new file mode 100644
index 0000000000..d592997270
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-004.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("fr") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-CH">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-005.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-005.html
new file mode 100644
index 0000000000..816dfc9b50
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-005.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: green; }
+:lang("fr-CH") { color: red; }
+</style>
+
+<div class="test"><span lang="fr">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-006.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-006.html
new file mode 100644
index 0000000000..d249a4c8c0
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-006.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: green; }
+:lang("fr-CH") { color: red; }
+</style>
+
+<div class="test"><span lang="fr-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-007.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-007.html
new file mode 100644
index 0000000000..a21506d94c
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-007.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("*-CH") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-CH">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-008.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-008.html
new file mode 100644
index 0000000000..77f77a884a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-008.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("*-Latn") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-009.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-009.html
new file mode 100644
index 0000000000..bf2e988391
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-009.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("fr-FR") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-010.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-010.html
new file mode 100644
index 0000000000..081c9207ad
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-010.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("*-FR") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-011.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-011.html
new file mode 100644
index 0000000000..5620317a14
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-011.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("fr", "nl", "de") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-012.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-012.html
new file mode 100644
index 0000000000..f299e22eae
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-012.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang(de, nl, fr) { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-013.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-013.html
new file mode 100644
index 0000000000..34303d9780
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-013.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: green; }
+:lang(de, nl, 0, fr) { color: red; }
+</style>
+
+<div class="test"><span lang="fr">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-014.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-014.html
new file mode 100644
index 0000000000..2d064c8d29
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-014.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: green; }
+:lang(0) { color: red; }
+</style>
+
+<div class="test"><span lang="0">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-015.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-015.html
new file mode 100644
index 0000000000..4d90b080f3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-015.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang(\*-FR) { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-016.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-016.html
new file mode 100644
index 0000000000..4923890fe6
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-016.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang(fr) { color: green; }
+</style>
+
+<div class="test"><span lang="fr-FR-x-foobar">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-017.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-017.html
new file mode 100644
index 0000000000..d5c86e5b77
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-017.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("fr-x-foobar") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR-x-foobar">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-018.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-018.html
new file mode 100644
index 0000000000..2f777a2ab4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-018.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("*-x-foobar") { color: green; }
+</style>
+
+<div class="test"><span lang="fr-Latn-FR-x-foobar">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-019.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-019.html
new file mode 100644
index 0000000000..a1e793cdac
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-019.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: green; }
+:lang("fr-x-foobar") { color: red; }
+</style>
+
+<div class="test"><span lang="fr">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-020.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-020.html
new file mode 100644
index 0000000000..9a17af2e41
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-020.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("iw") { color: green; }
+</style>
+
+<div class="test"><span lang="iw-ase-jpan-basiceng">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-021.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-021.html
new file mode 100644
index 0000000000..7320902151
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-021.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+span:lang("en-gb-oed") { color: magenta; }
+span span:lang("*-gb") { color: green; }
+</style>
+
+<div class="test" lang="en-GB-oed"><span><span>This should be green</span></span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-022.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-022.html
new file mode 100644
index 0000000000..5573fa00d3
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-022.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("i-navajo") { color: green; }
+</style>
+
+<div class="test"><span lang="i-navajo">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-023.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-023.html
new file mode 100644
index 0000000000..58e82e7be7
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-023.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("x") { color: green; } /* not a well-formed lang tag, but matches per
+ the Extended Filtering algorithm */
+</style>
+
+<div class="test"><span lang="x-lojban">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-024.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-024.html
new file mode 100644
index 0000000000..fb1926855d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-024.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("art") { color: green; }
+</style>
+
+<div class="test"><span lang="art-lojban">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-4/lang-025.html b/testing/web-platform/tests/css/selectors/selectors-4/lang-025.html
new file mode 100644
index 0000000000..027223299d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-4/lang-025.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<meta charset="utf-8">
+<title>CSS Selectors 4 - :lang matching</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-lang-pseudo">
+<link rel="match" href="lang-000-ref.html">
+
+<style>
+div.test { color: red; }
+:lang("art") { color: green; }
+</style>
+
+<!-- This can match :lang("art"), because "-x-lojban" is a private subtag,
+ so this is *not* the grandfathered "art-lojban" tag. -->
+<div class="test"><span lang="art-x-lojban">This should be green</span></div>
diff --git a/testing/web-platform/tests/css/selectors/selectors-attr-many-ref.html b/testing/web-platform/tests/css/selectors/selectors-attr-many-ref.html
new file mode 100644
index 0000000000..7d8a9f6d89
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-attr-many-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<title>Selectors: Many attribute selectors, and one that is only set</title>
+<p>This text should be black.</p>
+<p style="color: green">This text should be green.</p>
+<p style="color: blue">This text should be blue.</p>
diff --git a/testing/web-platform/tests/css/selectors/selectors-attr-many.html b/testing/web-platform/tests/css/selectors/selectors-attr-many.html
new file mode 100644
index 0000000000..b38b8f52cf
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-attr-many.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>Selectors: Many attribute selectors, and one that is only set</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="help" href="https://crbug.com/1345818"/>
+<link rel="match" href="selectors-attr-many-ref.html"/>
+<style>
+[color-me] { color: green; }
+[color-me='blue'] { color: blue; }
+[color-me='blue1'] { color: blue; }
+[color-me='blue2'] { color: blue; }
+[color-me='blue3'] { color: blue; }
+[color-me='blue4'] { color: blue; }
+[color-me='blue5'] { color: blue; }
+[color-me='blue6'] { color: blue; }
+[color-me='blue7'] { color: blue; }
+[color-me='blue8'] { color: blue; }
+[color-me='blue9'] { color: blue; }
+[color-me='orange'] { color: orange; }
+[color-me='orange1'] { color: orange; }
+[color-me='orange2'] { color: orange; }
+[color-me='orange3'] { color: orange; }
+[color-me='orange4'] { color: orange; }
+[color-me='orange5'] { color: orange; }
+[color-me='orange6'] { color: orange; }
+[color-me='orange7'] { color: orange; }
+[color-me='orange8'] { color: orange; }
+[color-me='orange9'] { color: orange; }
+[color-me='green'] { color: green; }
+[color-me='green1'] { color: green; }
+[color-me='green2'] { color: green; }
+[color-me='green3'] { color: green; }
+[color-me='green4'] { color: green; }
+[color-me='green5'] { color: green; }
+[color-me='green6'] { color: green; }
+[color-me='green7'] { color: green; }
+[color-me='green8'] { color: green; }
+[color-me='green9'] { color: green; }
+[color-me='purple'] { color: purple; }
+[color-me='purple1'] { color: purple; }
+[color-me='purple2'] { color: purple; }
+[color-me='purple3'] { color: purple; }
+[color-me='purple4'] { color: purple; }
+[color-me='purple5'] { color: purple; }
+[color-me='purple6'] { color: purple; }
+[color-me='purple7'] { color: purple; }
+[color-me='purple8'] { color: purple; }
+[color-me='purple9'] { color: purple; }
+[color-me='turquoise'] { color: turquoise; }
+[color-me='turquoise1'] { color: turquoise; }
+[color-me='turquoise2'] { color: turquoise; }
+[color-me='turquoise3'] { color: turquoise; }
+[color-me='turquoise4'] { color: turquoise; }
+[color-me='turquoise5'] { color: turquoise; }
+[color-me='turquoise6'] { color: turquoise; }
+[color-me='turquoise7'] { color: turquoise; }
+[color-me='turquoise8'] { color: turquoise; }
+</style>
+<p>This text should be black.</p>
+<p color-me="unknown">This text should be green.</p>
+<p color-me="blue">This text should be blue.</p>
diff --git a/testing/web-platform/tests/css/selectors/selectors-attr-white-space-001-ref.html b/testing/web-platform/tests/css/selectors/selectors-attr-white-space-001-ref.html
new file mode 100644
index 0000000000..3b768b36a5
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-attr-white-space-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors: White space in attribute selectors (reference)</title>
+<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"/>
+<style>
+body { color: green; }
+</style>
+<p>This text should be green.</p>
+<p>This text should be green.</p>
+<p>This text should be green.</p>
+<p>This text should be green.</p>
diff --git a/testing/web-platform/tests/css/selectors/selectors-attr-white-space-001.html b/testing/web-platform/tests/css/selectors/selectors-attr-white-space-001.html
new file mode 100644
index 0000000000..62df884cf4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-attr-white-space-001.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Selectors: White space in attribute selectors</title>
+<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au"/>
+<link rel="help" href="https://drafts.csswg.org/selectors-3/#w3cselgrammar"/>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#grammar"/>
+<link rel="match" href="selectors-attr-white-space-001-ref.html"/>
+<style>
+body { color: red; }
+[ data-test-1] { color: green; }
+[data-test-2 ] { color: green; }
+[data-test-3 = x] { color: green; }
+[ |data-test-4] { color: green; }
+[ | data-test-4] { color: red; }
+</style>
+<p data-test-1="">This text should be green.</p>
+<p data-test-2="">This text should be green.</p>
+<p data-test-3="x">This text should be green.</p>
+<p data-test-4="">This text should be green.</p>
diff --git a/testing/web-platform/tests/css/selectors/selectors-case-sensitive-001.html b/testing/web-platform/tests/css/selectors/selectors-case-sensitive-001.html
new file mode 100644
index 0000000000..6891554543
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-case-sensitive-001.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>Test element names are case-insensitive only in ASCII range</title>
+<link rel="help" href="https://www.w3.org/TR/selectors-4/#case-sensitive">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<style>
+\212A {
+ display: block;
+ background: lime;
+ width: 200px;
+ height: 100px;
+}
+</style>
+<body>
+ <p>You should see a green square below.</p>
+ <div id="container"></div>
+<script>
+// Insert from JavaScript to avoid parser doing something special.
+let test_element = document.createElement('\u212A');
+container.appendChild(test_element);
+let test_element_with_ns = document.createElementNS('https://dummy.ns', '\u212A');
+container.appendChild(test_element_with_ns);
+
+test(() => {
+ assert_equals(test_element.offsetHeight, 100);
+}, 'CSS selector should match for Unicode uppercase element');
+
+test(() => {
+ // Elements in different namespace cannot compute style or height.
+ // Test the height of the container instead.
+ assert_equals(container.offsetHeight, 200);
+}, 'Elements with namespace should work the same way');
+
+test(() => {
+ let e = document.querySelector('k');
+ assert_equals(e, null);
+}, '`querySelector` should not use Unicode case-folding');
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/selectors-empty-001-ref.xml b/testing/web-platform/tests/css/selectors/selectors-empty-001-ref.xml
new file mode 100644
index 0000000000..3f1b3f42a8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-empty-001-ref.xml
@@ -0,0 +1,40 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>CSS: 15 simple tests of :empty</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
+<style type="text/css">
+tests, tests * {
+ display: block;
+}
+tests > * {
+ border: solid thick lime;
+ height: 1em;
+ padding: 4px;
+ margin: 4px;
+ color: white;
+}
+</style>
+</head>
+<body>
+<p>Below there should be fifteen big green boxes and no red.</p>
+<tests xmlns="http://www.example.org/" type="positive">
+ <test1/>
+ <test2/>
+ <test3/>
+ <test4/>
+ <test5/>
+</tests>
+<tests xmlns="http://www.example.org/" type="negative">
+ <test1/>
+ <test2/>
+ <test3/>
+ <test4/>
+ <test5/>
+ <test6/>
+ <test7/>
+ <test8/>
+ <test9/>
+ <test10/>
+</tests>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selectors-empty-001.xml b/testing/web-platform/tests/css/selectors/selectors-empty-001.xml
new file mode 100644
index 0000000000..3b882debcc
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-empty-001.xml
@@ -0,0 +1,47 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS: 15 simple tests of :empty</title>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors-3/#empty-pseudo"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-empty-pseudo"/>
+ <link rel="match" href="selectors-empty-001-ref.xml"/>
+ <meta name="flags" content="nonHTML"/>
+ <style type="text/css">
+ tests, tests * {
+ display: block;
+ }
+ tests > * {
+ border: solid thick red;
+ height: 1em;
+ padding: 4px;
+ margin: 4px;
+ color: white;
+ }
+ tests[type=positive] > :empty, tests[type=negative] > :not(:empty) {
+ border: solid thick lime;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Below there should be fifteen big green boxes and no red.</p>
+ <tests xmlns="http://www.example.org/" type="positive">
+ <test1/>
+ <test2></test2>
+ <test3><!-- --></test3>
+ <test4><?testfour?></test4>
+ <test5 title="data"></test5>
+ </tests>
+ <tests xmlns="http://www.example.org/" type="negative">
+ <test1><test1> </test1></test1>
+ <test2>green!</test2>
+ <test3>&gt;&lt;</test3>
+ <test4>&#x2211;</test4>
+ <test5><test5/></test5>
+ <test6> </test6>
+ <test7> <!-- --></test7>
+ <test8> <?testfour?></test8>
+ <test9><!-- --> </test9>
+ <test10><?testfour?> </test10>
+ </tests>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selectors-namespace-001-ref.xml b/testing/web-platform/tests/css/selectors/selectors-namespace-001-ref.xml
new file mode 100644
index 0000000000..8c8ee979a8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-namespace-001-ref.xml
@@ -0,0 +1,14 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selectors Reftest Reference</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
+<style type="text/css">
+body {
+ color: green;
+}
+</style>
+</head>
+<body>
+This text should be green.
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/selectors-namespace-001.xml b/testing/web-platform/tests/css/selectors/selectors-namespace-001.xml
new file mode 100644
index 0000000000..d46f134133
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/selectors-namespace-001.xml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS: 1 simple test of namespaces (attributes)</title>
+ <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
+ <link rel="alternate" href="http://www.hixie.ch/tests/adhoc/css/selectors/namespace/001.xml"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors-3/#attrnmsp"/>
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#attrnmsp"/>
+ <link rel="match" href="selectors-namespace-001-ref.xml"/>
+ <style type="text/css">
+ @namespace html url(http://www.w3.org/1999/xhtml);
+ @namespace test url(http://www.example.org/);
+ html|body { color: red; }
+ [test] { color: green; }
+ </style>
+ </head>
+ <body>
+ <test test="test" xmlns="http://www.example.org/">
+ This text should be green.
+ </test>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/sharing-in-svg-use-ref.html b/testing/web-platform/tests/css/selectors/sharing-in-svg-use-ref.html
new file mode 100644
index 0000000000..703cc99bb8
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/sharing-in-svg-use-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>CSS Test reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<svg width="200" height="100">
+ <defs>
+ <g id="p0">
+ <rect width="100" height="100" style="fill: blue" />
+ <rect x="100" y="0" width="100" height="100" style="fill: purple" />
+ </g>
+ </defs>
+ <use href="#p0" x="0" y="0" />
+</svg>
diff --git a/testing/web-platform/tests/css/selectors/sharing-in-svg-use.html b/testing/web-platform/tests/css/selectors/sharing-in-svg-use.html
new file mode 100644
index 0000000000..08a038ca8b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/sharing-in-svg-use.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>CSS Test: nth-of-type should work in an svg use subtree</title>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1540385">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="sharing-in-svg-use-ref.html">
+<style>
+rect:nth-of-type(1) {
+ fill: blue;
+}
+rect:nth-of-type(2) {
+ fill: purple;
+}
+</style>
+<!-- Should see two different colors -->
+<svg width="200" height="100">
+ <defs>
+ <g id="p0">
+ <rect width="100" height="100" />
+ <rect x="100" y="0" width="100" height="100" />
+ </g>
+ </defs>
+ <use href="#p0" x="0" y="0" />
+</svg>
diff --git a/testing/web-platform/tests/css/selectors/spurious-brace-crash.html b/testing/web-platform/tests/css/selectors/spurious-brace-crash.html
new file mode 100644
index 0000000000..b1a462a969
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/spurious-brace-crash.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Spurious left-brace byte when converted to UTF-16</title>
+<link rel="help" href="https://crbug.com/1376485">
+<link rel="stylesheet" href="data:text/css,.a{--x:%22%EF%89%BB%22;}.b{}">
diff --git a/testing/web-platform/tests/css/selectors/user-invalid.html b/testing/web-platform/tests/css/selectors/user-invalid.html
new file mode 100644
index 0000000000..5f8fa5811a
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/user-invalid.html
@@ -0,0 +1,196 @@
+<!doctype html>
+<title>Support for the :user-invalid pseudo-class</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#user-pseudos">
+<link rel="help" href="https://html.spec.whatwg.org/#selector-user-invalid">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+:is(input:not([type=submit], [type=reset]), textarea) {
+ border: 2px solid black;
+}
+
+:is(input:not([type=submit], [type=reset]), textarea):user-valid {
+ border-color: green;
+}
+
+:is(input:not([type=submit], [type=reset]), textarea):user-invalid {
+ border-color: red;
+}
+</style>
+
+<input id="initially-invalid" type="email" value="foo">
+
+<p>Test form interactions (reset / submit):</p>
+<form id="form">
+ <input placeholder="Required field" required id="required-input"><br>
+ <textarea placeholder="Required field" required id="required-textarea"></textarea><br>
+ <input type="checkbox" required id="required-checkbox"><br>
+ <input type="submit" id="submit-button">
+ <input type="reset" id="reset-button">
+</form>
+
+<script>
+promise_test(async () => {
+ const input = document.querySelector("#initially-invalid");
+ assert_false(input.validity.valid, "Should be invalid");
+ // The selector can't match because no interaction has happened.
+ assert_false(input.matches(':user-invalid'));
+
+ assert_false(input.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(input.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ await test_driver.click(input);
+ input.blur();
+
+ assert_false(input.matches(":user-valid"), "No change happened, still does not match :user-valid");
+ assert_false(input.matches(":user-invalid"), "No change happened, still does not match :user-invalid");
+
+ input.value = "not an email";
+
+ assert_false(input.matches(":user-valid"), "Programatically set value, :user-valid should not match");
+ assert_false(input.matches(":user-invalid"), "Programatically set value, :user-invalid should not match");
+
+ input.value = "";
+
+ assert_false(input.matches(":user-valid"), "Programatically cleared value, :user-valid should not match");
+ assert_false(input.matches(":user-invalid"), "Programatically cleared value, :user-invalid should not match");
+
+ await test_driver.click(input);
+ await test_driver.send_keys(input, "not an email");
+ input.blur();
+
+ assert_true(input.matches(":user-invalid"), "Typed an invalid email, :user-invalid now matches");
+ assert_false(input.matches(":user-valid"), "Typed an invalid email, :user-valid does not match");
+
+ input.value = "";
+ await test_driver.click(input);
+ await test_driver.send_keys(input, "test@example.com");
+ input.blur();
+
+ assert_true(input.matches(":user-valid"), "Put a valid email, :user-valid now matches");
+ assert_false(input.matches(":user-invalid"), "Put an valid email, :user-invalid no longer matches");
+}, ':user-invalid selector should respond to user action');
+
+promise_test(async () => {
+ const form = document.querySelector("#form");
+ const requiredInput = document.querySelector("#required-input");
+ const requiredTextarea = document.querySelector("#required-textarea");
+ const requiredCheckbox = document.querySelector("#required-checkbox");
+ const submitButton = document.querySelector("#submit-button");
+ const resetButton = document.querySelector("#reset-button");
+
+ assert_false(requiredInput.validity.valid);
+ assert_false(requiredTextarea.validity.valid);
+ assert_false(requiredCheckbox.validity.valid);
+ // The selector can't match because no interaction has happened.
+ assert_false(requiredInput.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(requiredInput.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ assert_false(requiredTextarea.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(requiredTextarea.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ assert_false(requiredCheckbox.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(requiredCheckbox.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ submitButton.click();
+
+ assert_true(requiredInput.matches(":user-invalid"), "Submitted the form, input is validated");
+ assert_false(requiredInput.matches(":user-valid"), "Submitted the form, input is validated");
+
+ assert_true(requiredTextarea.matches(":user-invalid"), "Submitted the form, textarea is validated");
+ assert_false(requiredTextarea.matches(":user-valid"), "Submitted the form, textarea is validated");
+
+ assert_true(requiredCheckbox.matches(":user-invalid"), "Submitted the form, checkbox is validated");
+ assert_false(requiredCheckbox.matches(":user-valid"), "Submitted the form, checkbox is validated");
+
+ resetButton.click();
+
+ assert_false(requiredInput.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
+ assert_false(requiredInput.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
+
+ assert_false(requiredTextarea.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
+ assert_false(requiredTextarea.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
+
+ assert_false(requiredCheckbox.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
+ assert_false(requiredCheckbox.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
+
+ // Test programmatic form submission with constraint validation.
+ form.requestSubmit();
+
+ assert_true(requiredInput.matches(":user-invalid"), "Called form.requestSubmit(), input is validated");
+ assert_false(requiredInput.matches(":user-valid"), "Called form.requestSubmit(), input is validated");
+
+ assert_true(requiredTextarea.matches(":user-invalid"), "Called form.requestSubmit(), textarea is validated");
+ assert_false(requiredTextarea.matches(":user-valid"), "Called form.requestSubmit(), textarea is validated");
+
+ assert_true(requiredCheckbox.matches(":user-invalid"), "Called form.requestSubmit(), checkbox is validated");
+ assert_false(requiredCheckbox.matches(":user-valid"), "Called form.requestSubmit(), checkbox is validated");
+}, ":user-invalid selector properly interacts with submit & reset buttons");
+
+// historical: https://github.com/w3c/csswg-drafts/issues/1329
+test(() => {
+ const input = document.querySelector('input');
+ // matches() will throw if the selector isn't suppported
+ assert_throws_dom("SyntaxError", () => input.matches(':user-error'));
+}, ':user-error selector should not be supported');
+
+['required-input', 'required-textarea'].forEach(elementId => {
+ promise_test(async () => {
+ const resetButton = document.getElementById('reset-button');
+ const element = document.getElementById(elementId);
+
+ element.value = '';
+ resetButton.click();
+ assert_false(element.matches(':user-invalid'),
+ 'Element should not match :user-invalid at the start of the test.');
+ assert_false(element.matches(':user-valid'),
+ 'Element should not match :user-valid at the start of the test.');
+
+ const backspace = '\uE003';
+ element.focus();
+ await test_driver.send_keys(element, 'a');
+ await test_driver.send_keys(element, backspace);
+ assert_false(element.matches(':user-invalid'),
+ 'Element should not match :user-invalid before blurring.');
+ assert_false(element.matches(':user-valid'),
+ 'Element should not match :user-valid before blurring.');
+
+ element.blur();
+ assert_true(element.matches(':user-invalid'),
+ 'Element should match :user-invalid after typing text and deleting it.');
+ assert_false(element.matches(':user-valid'),
+ 'Element should not match :user-valid after the test.');
+ }, `${elementId}: A required input or textarea should match :user-invalid if a user types into it and then clears it before blurring.`);
+});
+
+promise_test(async () => {
+ const checkbox = document.getElementById('required-checkbox');
+
+ const resetButton = document.getElementById('reset-button');
+ resetButton.click();
+ assert_false(checkbox.matches(':user-invalid'),
+ 'Checkbox should not match :user-invalid at the start of the test.');
+ assert_false(checkbox.checked,
+ 'Checkbox should not be checked at the start of the test.');
+
+ checkbox.checked = true;
+ assert_false(checkbox.matches(':user-invalid'),
+ 'Checkbox should not match :user-invalid after programatically changing value.');
+ checkbox.checked = false;
+ assert_false(checkbox.matches(':user-invalid'),
+ 'Checkbox should not match :user-invalid after programatically changing value.');
+
+ await test_driver.click(checkbox);
+ assert_true(checkbox.checked, 'Checkbox should be checked after clicking once.');
+ assert_false(checkbox.matches(':user-invalid'),
+ 'Checkbox should not match :user-invalid after checking it.');
+ await test_driver.click(checkbox);
+ assert_false(checkbox.checked, 'Checkbox should not be checked after clicking twice.');
+ assert_true(checkbox.matches(':user-invalid'),
+ 'Checkbox should match :user-invalid after clicking twice.');
+}, 'A required checkbox should match :user-invalid if the user unchecks it and blurs.');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/user-valid.html b/testing/web-platform/tests/css/selectors/user-valid.html
new file mode 100644
index 0000000000..7a12eb237d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/user-valid.html
@@ -0,0 +1,154 @@
+<!doctype html>
+<title>Support for the :user-valid pseudo-class</title>
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<link rel="help" href="https://drafts.csswg.org/selectors/#user-pseudos">
+<link rel="help" href="https://html.spec.whatwg.org/#selector-user-valid">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+:is(input:not([type=submit], [type=reset]), textarea) {
+ border: 2px solid black;
+}
+
+:is(input:not([type=submit], [type=reset]), textarea):user-valid {
+ border-color: green;
+}
+
+:is(input:not([type=submit], [type=reset]), textarea):user-invalid {
+ border-color: red;
+}
+</style>
+
+<input id="initially-valid" type="email">
+
+<p>Test form interactions (reset / submit):</p>
+<form id="form">
+ <input placeholder="Optional field" id="optional-input"><br>
+ <textarea placeholder="Optional field" id="optional-textarea"></textarea><br>
+ <input type="checkbox" id="optional-checkbox"><br>
+ <input required placeholder="Required field"> <!-- Prevent the form from navigating with this invalid input -->
+ <input type="submit" id="submit-button">
+ <input type="reset" id="reset-button">
+</form>
+
+<script>
+promise_test(async () => {
+ const input = document.querySelector("#initially-valid");
+ assert_true(input.validity.valid);
+ // The selector can't match because no interaction has happened.
+ assert_false(input.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(input.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ await test_driver.click(input);
+ input.blur();
+
+ assert_false(input.matches(":user-valid"), "No change happened, still does not match :user-valid");
+ assert_false(input.matches(":user-invalid"), "No change happened, still does not match :user-invalid");
+
+ input.value = "test@example.com";
+
+ assert_false(input.matches(":user-valid"), "Programatically set value, :user-valid should not match");
+ assert_false(input.matches(":user-invalid"), "Programatically set value, :user-invalid should not match");
+
+ input.value = "";
+
+ assert_false(input.matches(":user-valid"), "Programatically cleared value, :user-valid should not match");
+ assert_false(input.matches(":user-invalid"), "Programatically cleared value, :user-invalid should not match");
+
+ await test_driver.click(input);
+ await test_driver.send_keys(input, "test@example.com");
+ input.blur();
+
+ assert_true(input.matches(":user-valid"), "Typed a valid email, :user-valid now matches");
+ assert_false(input.matches(":user-invalid"), "Typed a valid email, :user-invalid does not match");
+
+ input.required = true;
+ input.value = "";
+
+ assert_false(input.matches(":user-valid"), "Cleared required input, :user-valid no longer matches");
+ assert_true(input.matches(":user-invalid"), "Cleared required input, :user-invalid now matches");
+}, ":user-valid selector should respond to user action");
+
+promise_test(async () => {
+ const form = document.querySelector("#form");
+ const optionalInput = document.querySelector("#optional-input");
+ const optionalTextarea = document.querySelector("#optional-textarea");
+ const optionalCheckbox = document.querySelector("#optional-checkbox");
+ const submitButton = document.querySelector("#submit-button");
+ const resetButton = document.querySelector("#reset-button");
+
+ assert_true(optionalInput.validity.valid);
+ assert_true(optionalTextarea.validity.valid);
+ assert_true(optionalCheckbox.validity.valid);
+ // The selector can't match because no interaction has happened.
+ assert_false(optionalInput.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(optionalInput.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ assert_false(optionalTextarea.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(optionalTextarea.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ assert_false(optionalCheckbox.matches(":user-valid"), "Initially does not match :user-valid");
+ assert_false(optionalCheckbox.matches(":user-invalid"), "Initially does not match :user-invalid");
+
+ submitButton.click();
+
+ assert_true(optionalInput.matches(":user-valid"), "Submitted the form, input is validated");
+ assert_false(optionalInput.matches(":user-invalid"), "Submitted the form, input is validated");
+
+ assert_true(optionalTextarea.matches(":user-valid"), "Submitted the form, textarea is validated");
+ assert_false(optionalTextarea.matches(":user-invalid"), "Submitted the form, textarea is validated");
+
+ assert_true(optionalCheckbox.matches(":user-valid"), "Submitted the form, checkbox is validated");
+ assert_false(optionalCheckbox.matches(":user-invalid"), "Submitted the form, checkbox is validated");
+
+ resetButton.click();
+
+ assert_false(optionalInput.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
+ assert_false(optionalInput.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
+
+ assert_false(optionalTextarea.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
+ assert_false(optionalTextarea.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
+
+ assert_false(optionalCheckbox.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
+ assert_false(optionalCheckbox.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
+
+ // Test programmatic form submission with constraint validation.
+ form.requestSubmit();
+
+ assert_true(optionalInput.matches(":user-valid"), "Called form.requestSubmit(), input is validated");
+ assert_false(optionalInput.matches(":user-invalid"), "Called form.requestSubmit(), input is validated");
+
+ assert_true(optionalTextarea.matches(":user-valid"), "Called form.requestSubmit(), textarea is validated");
+ assert_false(optionalTextarea.matches(":user-invalid"), "Called form.requestSubmit(), textarea is validated");
+
+ assert_true(optionalCheckbox.matches(":user-valid"), "Called form.requestSubmit(), checkbox is validated");
+ assert_false(optionalCheckbox.matches(":user-invalid"), "Called form.requestSubmit(), checkbox is validated");
+}, ":user-valid selector properly interacts with submit & reset buttons");
+
+promise_test(async () => {
+ const checkbox = document.getElementById('optional-checkbox');
+
+ const resetButton = document.getElementById('reset-button');
+ resetButton.click();
+ assert_false(checkbox.matches(':user-valid'),
+ 'Checkbox should not match :user-valid at the start of the test.');
+ assert_false(checkbox.checked,
+ 'Checkbox should not be checked at the start of the test.');
+
+ checkbox.checked = true;
+ assert_false(checkbox.matches(':user-valid'),
+ 'Checkbox should not match :user-valid after programatically changing value.');
+ checkbox.checked = false;
+ assert_false(checkbox.matches(':user-valid'),
+ 'Checkbox should not match :user-valid after programatically changing value.');
+
+ await test_driver.click(checkbox);
+ assert_true(checkbox.checked, 'Checkbox should be checked after clicking once.');
+
+ assert_true(checkbox.matches(':user-valid'),
+ 'Checkbox should match :user-valid after clicking once.');
+}, 'Checkboxes should match :user-valid after the user clicks on it.');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/valid-invalid-form-fieldset.html b/testing/web-platform/tests/css/selectors/valid-invalid-form-fieldset.html
new file mode 100644
index 0000000000..95bfd9c844
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/valid-invalid-form-fieldset.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/9257">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<form>
+ <fieldset>
+ <input type=email>
+ <input type=submit>
+ </fieldset>
+</form>
+
+<script>
+promise_test(async () => {
+ const form = document.querySelector('form');
+ const fieldset = document.querySelector('fieldset');
+ const input = document.querySelector('input[type=email]');
+
+ assert_false(form.matches(':invalid'), 'form should not initially match :invalid.');
+ assert_true(form.matches(':valid'), 'form should initialy match :valid.');
+ assert_false(form.matches(':user-valid'), 'initial state: form should never match :user-valid.');
+ assert_false(form.matches(':user-invalid'), 'initial state: form should never match :user-invalid.');
+
+ assert_false(fieldset.matches(':invalid'), 'fieldset should not initially match :invalid.');
+ assert_true(fieldset.matches(':valid'), 'fieldset should initialy match :valid.');
+ assert_false(fieldset.matches(':user-valid'), 'initial state: fieldset should never match :user-valid.');
+ assert_false(fieldset.matches(':user-invalid'), 'initial state: fieldset should never match :user-invalid.');
+
+ assert_false(input.matches(':invalid'), 'input should not initially match :invalid.');
+ assert_true(input.matches(':valid'), 'input should initialy match :valid.');
+ assert_false(input.matches(':user-valid'), 'input should not initialy match :user-valid.');
+ assert_false(input.matches(':user-invalid'), 'input should not initialy match :user-invalid.');
+
+ await test_driver.click(input);
+ await test_driver.send_keys(input, 'user');
+ input.blur();
+
+ assert_true(form.matches(':invalid'), 'form should match :invalid after invalid text was entered.');
+ assert_false(form.matches(':valid'), 'form should not match :valid after invalid text was entered.');
+ assert_false(form.matches(':user-valid'), 'after text was entered: form should never match :user-valid.');
+ assert_false(form.matches(':user-invalid'), 'after text was entered: form should never match :user-invalid.');
+
+ assert_true(fieldset.matches(':invalid'), 'fieldset should match :invalid after invalid text was entered.');
+ assert_false(fieldset.matches(':valid'), 'fieldset should not match :valid after invalid text was entered.');
+ assert_false(fieldset.matches(':user-valid'), 'after invalid text was entered: fieldset should never match :user-valid.');
+ assert_false(fieldset.matches(':user-invalid'), 'after ininvalid text was entered: fieldset should never match :user-invalid.');
+
+ assert_true(input.matches(':invalid'), 'input should match :invalid after invalid text was entered.');
+ assert_false(input.matches(':valid'), 'input should not match :valid after invalid text was entered.');
+ assert_false(input.matches(':user-valid'), 'input should not match :user-valid after invalid text was entered.');
+ assert_true(input.matches(':user-invalid'), 'input should match :user-invalid after invalid text was entered.');
+
+ await test_driver.click(input);
+ await test_driver.send_keys(input, '@example.com');
+ await input.blur();
+
+ assert_false(form.matches(':invalid'), 'form should not match :invalid after valid text was entered.');
+ assert_true(form.matches(':valid'), 'form should match :valid after valid text was entered.');
+ assert_false(form.matches(':user-valid'), 'after valid text was entered: form should never match :user-valid.');
+ assert_false(form.matches(':user-invalid'), 'after invalid text was entered: form should never match :user-invalid.');
+
+ assert_false(fieldset.matches(':invalid'), 'fieldset should not match :invalid after valid text was entered.');
+ assert_true(fieldset.matches(':valid'), 'fieldset should match :valid after valid text was entered.');
+ assert_false(fieldset.matches(':user-valid'), 'after valid text was entered: fieldset should never match :user-valid.');
+ assert_false(fieldset.matches(':user-invalid'), 'after invalid text was entered: fieldset should never match :user-invalid.');
+
+ assert_false(input.matches(':invalid'), 'input should not match :invalid after valid text was entered.');
+ assert_true(input.matches(':valid'), 'input should match :valid after valid text was entered.');
+ assert_true(input.matches(':user-valid'), 'input should match :user-valid after valid text was entered.');
+ assert_false(input.matches(':user-invalid'), 'input should not match :user-invalid after invalid text was entered.');
+}, 'form and fieldset elements should match :valid/:invalid but not :user-valid/:user-invalid.');
+</script>
diff --git a/testing/web-platform/tests/css/selectors/visited-inheritance-ref.html b/testing/web-platform/tests/css/selectors/visited-inheritance-ref.html
new file mode 100644
index 0000000000..64300b13f4
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/visited-inheritance-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>inherited link color when modifying parent</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors">
+<style>
+ div { color: green; }
+ a { color: green; }
+</style>
+<main>
+ <div id="parentdiv">
+ <a href="" id="link">Visited link should be green</a>
+ </div>
+</main>
diff --git a/testing/web-platform/tests/css/selectors/visited-inheritance.html b/testing/web-platform/tests/css/selectors/visited-inheritance.html
new file mode 100644
index 0000000000..1442307a92
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/visited-inheritance.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>inherited link color when modifying parent</title>
+<link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+<link rel="match" href="visited-inheritance-ref.html">
+<link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors">
+<style>
+ div { color: red; }
+ a { color: inherit; }
+</style>
+<main>
+ <div id="parentdiv">
+ <a href="" id="link">Visited link should be green</a>
+ </div>
+ <script>
+ link.offsetTop;
+ parentdiv.style.color = 'green';
+ </script>
+</main>
diff --git a/testing/web-platform/tests/css/selectors/visited-part-crash.html b/testing/web-platform/tests/css/selectors/visited-part-crash.html
new file mode 100644
index 0000000000..f4cb28995b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/visited-part-crash.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<link rel="help" href="https://crbug.com/1413904">
+<style>
+ .foo:visited::part(test) {}
+</style>
+<div class=foo>
+ <a class=foo href="">Test</a>
+</div>
diff --git a/testing/web-platform/tests/css/selectors/webkit-pseudo-element.html b/testing/web-platform/tests/css/selectors/webkit-pseudo-element.html
new file mode 100644
index 0000000000..30103fa72b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/webkit-pseudo-element.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>WebKit-prefixed pseudo-elements</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#compat">
+<meta name="assert" content="WebKit-prefixed pseudo-elements should always be valid">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style id="style">
+#test {
+ color: rgb(255, 0, 0);
+}
+span::-webkit-something-invalid, #test, ::-WeBkIt-sOmEtHiNg-NoNeXiSt123, ::-webkit-\ escaped {
+ color: rgb(0, 255, 0);
+}
+::-webkitfoo, #test {
+ color: rgb(255, 0, 0);
+}
+</style>
+<body>
+<div id="test"></div>
+<script>
+ test(() => {
+ let elem = document.getElementById("test");
+ assert_equals(getComputedStyle(elem).color, "rgb(0, 255, 0)");
+ }, "rules include webkit-prefixed pseudo-element should be cascaded");
+
+ test(() => {
+ let sheet = document.getElementById("style").sheet;
+ assert_equals(sheet.cssRules[1].selectorText,
+ "span::-webkit-something-invalid, " +
+ "#test, ::-webkit-something-nonexist123, " +
+ "::-webkit-\\ escaped");
+ }, "webkit-prefixed pseudo-element selectors should be accessible from CSSOM");
+
+ test(() => {
+ document.querySelector("span::-webkit-something-invalid");
+ document.querySelectorAll("span::-webkit-something-invalid");
+ }, "qS and qSA shouldn't throw exception");
+
+ test(() => {
+ let sheet = document.getElementById("style").sheet;
+ assert_equals(sheet.cssRules.length, 2);
+ assert_throws_dom("SyntaxError", () => document.querySelector("span::-webkitfoo"));
+ assert_throws_dom("SyntaxError", () => document.querySelectorAll("span::-webkitfoo"));
+ }, "webkit-prefix without dash is invalid");
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/selectors/x-pseudo-element.html b/testing/web-platform/tests/css/selectors/x-pseudo-element.html
new file mode 100644
index 0000000000..76c66a803b
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/x-pseudo-element.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>CSS Test: 'x-' prefixed pseudo-elements don't parse correctly</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#pseudo-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ p {
+ color: green;
+ }
+ ::x-something-nobody-would-think-of, p {
+ color: red;
+ }
+</style>
+<p>Should be green
+<script>
+ test(function() {
+ let p = document.querySelector('p');
+ assert_equals(getComputedStyle(p).color, "rgb(0, 128, 0)");
+ }, "x-prefixed pseudo-elements should make the whole rule invalid")
+</script>
diff --git a/testing/web-platform/tests/css/selectors/xml-class-selector-ref.xml b/testing/web-platform/tests/css/selectors/xml-class-selector-ref.xml
new file mode 100644
index 0000000000..6b44280737
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/xml-class-selector-ref.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <title>Class selectors in an XML namespace</title>
+ <link rel="author" href="mailto:masonf@chromium.org" />
+ <body>
+ <p>The .class selector should work in any namespace. Both boxes should be green.</p>
+ <Boxes xmlns="http://foo">
+ <box>.classname selector</box>
+ <box>*[class~="classname"] selector</box>
+ </Boxes>
+
+ <style>
+ box {background:green;}
+ </style>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/selectors/xml-class-selector.xml b/testing/web-platform/tests/css/selectors/xml-class-selector.xml
new file mode 100644
index 0000000000..5666c0065d
--- /dev/null
+++ b/testing/web-platform/tests/css/selectors/xml-class-selector.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <title>Class selectors in an XML namespace</title>
+ <link rel="author" href="mailto:masonf@chromium.org" />
+ <link rel="help" href="https://dom.spec.whatwg.org/#dom-element-classname" />
+ <link rel="help" href="https://crbug.com/649444" />
+ <link rel="match" href="xml-class-selector-ref.xml" />
+ <body>
+ <p>The .class selector should work in any namespace. Both boxes should be green.</p>
+ <Boxes xmlns="http://foo">
+ <box class="green">.classname selector</box>
+ <box class="green2">*[class~="classname"] selector</box>
+ </Boxes>
+
+ <style>
+ box {background:red;}
+ .green {background: green;}
+ *[class~="green2"] {background: green;}
+ </style>
+ </body>
+</html>