Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add the runtime flag and basic implementation of :dir
https://bugs.webkit.org/show_bug.cgi?id=243090

Reviewed by Cameron McCormack.

Added the rudimentary support for :dir under a new runtime flag.

* LayoutTests/TestExpectations: Removed failing expectations from now passing tests.
* LayoutTests/imported/w3c/web-platform-tests/css/selectors/dir-selector-auto-expected.txt: Rebaselined.
* LayoutTests/imported/w3c/web-platform-tests/css/selectors/dir-selector-querySelector-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/dir-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/dir-html-input-dynamic-text-expected.txt: Ditto.
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/dir01-expected.txt: Ditto.

* Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml: Added a runtime flag.
* Source/WebCore/css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne const):
* Source/WebCore/css/SelectorCheckerTestFunctions.h:
(WebCore::matchesDirPseudoClass): Added.
* Source/WebCore/html/HTMLElement.cpp:
(WebCore::HTMLElement::computeDirectionality const): Added.
* Source/WebCore/html/HTMLElement.h:

Canonical link: https://commits.webkit.org/252737@main
  • Loading branch information
rniwa committed Jul 22, 2022
1 parent 22aafa3 commit 143e43d
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 49 deletions.
13 changes: 0 additions & 13 deletions LayoutTests/TestExpectations
Expand Up @@ -478,7 +478,6 @@ fast/history/page-cache-active-fetch-response-blobReadAsBlob.html [ DumpJSConsol
fast/dom/navigator-detached-no-crash.html [ DumpJSConsoleLogInStdErr ]
webaudio/audioworket-out-of-memory.html [ DumpJSConsoleLogInStdErr ]

webkit.org/b/202495 imported/w3c/web-platform-tests/shadow-dom/directionality-002.tentative.html [ ImageOnlyFailure ]
webkit.org/b/242376 imported/w3c/web-platform-tests/shadow-dom/imperative-slot-layout-invalidation-001.html [ ImageOnlyFailure ]

# Newly imported WPT tests that are timing out.
Expand Down Expand Up @@ -1458,17 +1457,9 @@ webkit.org/b/234139 imported/w3c/web-platform-tests/css/selectors/focus-visible-
webkit.org/b/217904 imported/w3c/web-platform-tests/css/selectors/is-where-visited.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-auto-direction-change-001.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-change-001.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-change-002.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-change-003.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-change-004.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-ltr-001.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-rtl-001.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-selector-white-space-001.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-style-01a.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-style-01b.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-style-02a.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-style-02b.html [ ImageOnlyFailure ]
webkit.org/b/64861 imported/w3c/web-platform-tests/css/selectors/dir-style-04.html [ ImageOnlyFailure ]
webkit.org/b/223497 imported/w3c/web-platform-tests/css/selectors/nesting.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/selectors/xml-class-selector.xml [ ImageOnlyFailure ]
webkit.org/b/238822 imported/w3c/web-platform-tests/css/selectors/child-indexed-no-parent.html [ ImageOnlyFailure ]
Expand Down Expand Up @@ -4599,8 +4590,6 @@ webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/host-context
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/host-context-specificity-002.html [ ImageOnlyFailure ]
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/host-context-specificity-003.html [ ImageOnlyFailure ]
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/host-with-default-namespace-001.html [ ImageOnlyFailure ]
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/shadow-directionality-001.tentative.html [ ImageOnlyFailure ]
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/shadow-directionality-002.tentative.html [ ImageOnlyFailure ]
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/slotted-placeholder.html [ ImageOnlyFailure ]

# aspect-ratio (some of these rely on contain-intrinsic-size)
Expand Down Expand Up @@ -5217,8 +5206,6 @@ webkit.org/b/239959 ipc/stream-sync-crash-no-timeout.html [ Skip ]
# The test invokes random messages, potentially produces random results.
ipc/start-message-testing.html [ Skip ]

imported/w3c/web-platform-tests/css/css-shadow-parts/interaction-with-nested-pseudo-class.html [ ImageOnlyFailure ]

webkit.org/b/183994 imported/w3c/web-platform-tests/css/cssom/css-style-attr-decl-block.html [ Failure ]

# Test is crashing in Debug builds since import.
Expand Down
Expand Up @@ -3,26 +3,26 @@ a
ת
ת

FAIL Initial directionality of element div1 is ltr assert_true: expected true got false
FAIL Initial directionality of element div1_1 is ltr assert_true: expected true got false
FAIL Initial directionality of element div2 is rtl assert_true: expected true got false
FAIL Initial directionality of element div2_1 is rtl assert_true: expected true got false
FAIL Initial directionality of element div3 is ltr assert_true: expected true got false
FAIL Initial directionality of element div3_1 is rtl assert_true: expected true got false
FAIL Initial directionality of element div3_2 is ltr assert_true: expected true got false
FAIL Initial directionality of element div4 is ltr assert_true: expected true got false
FAIL Initial directionality of element div4_1 is ltr assert_true: expected true got false
FAIL Initial directionality of element div4_1_1 is ltr assert_true: expected true got false
FAIL Updated directionality of element div1 is rtl assert_true: expected true got false
FAIL Updated directionality of element div1_1 is rtl assert_true: expected true got false
FAIL Updated directionality of element div1 is ltr assert_true: expected true got false
FAIL Updated directionality of element div1_1 is ltr assert_true: expected true got false
FAIL Reupdated directionality of element div1 is ltr assert_true: expected true got false
FAIL Reupdated directionality of element div1_1 is ltr assert_true: expected true got false
FAIL Updated directionality of element div2 is ltr assert_true: expected true got false
FAIL Updated directionality of element div3 is rtl assert_true: expected true got false
FAIL Updated directionality of element div3 is ltr assert_true: expected true got false
FAIL Updated directionality of element div4 is rtl assert_true: expected true got false
FAIL Updated directionality of element div4_1 is rtl assert_true: expected true got false
FAIL Updated directionality of element div4_1_1 is rtl assert_true: expected true got false
PASS Initial directionality of element div1 is ltr
PASS Initial directionality of element div1_1 is ltr
PASS Initial directionality of element div2 is rtl
PASS Initial directionality of element div2_1 is rtl
PASS Initial directionality of element div3 is ltr
PASS Initial directionality of element div3_1 is rtl
PASS Initial directionality of element div3_2 is ltr
PASS Initial directionality of element div4 is ltr
PASS Initial directionality of element div4_1 is ltr
PASS Initial directionality of element div4_1_1 is ltr
PASS Updated directionality of element div1 is rtl
PASS Updated directionality of element div1_1 is rtl
PASS Updated directionality of element div1 is ltr
PASS Updated directionality of element div1_1 is ltr
PASS Reupdated directionality of element div1 is ltr
PASS Reupdated directionality of element div1_1 is ltr
PASS Updated directionality of element div2 is ltr
PASS Updated directionality of element div3 is rtl
PASS Updated directionality of element div3 is ltr
PASS Updated directionality of element div4 is rtl
PASS Updated directionality of element div4_1 is rtl
PASS Updated directionality of element div4_1_1 is rtl

@@ -1,6 +1,6 @@

PASS :dir() allows any ident value but strings other than ltr/rtl don't match
PASS :dir() requires exactly an ident argument
FAIL :dir() works in compound selectors assert_equals: expected Element node <div id="div2_3" dir="rtl"></div> but got null
FAIL :dir() works in complex selectors assert_equals: expected Element node <div id="div2_1"></div> but got null
PASS :dir() works in compound selectors
PASS :dir() works in complex selectors

@@ -1,18 +1,31 @@

FAIL ':dir(rtl)' matches all elements whose directionality is 'rtl'. assert_array_equals: lengths differ, expected array [Element node <bdo dir="rtl" id="bdo1">WERBEH</bdo>, Element node <bdi dir="rtl" id="bdi2">WERBEH</bdi>, Element node <bdi id="bdi4">إيان</bdi>, Element node <span dir="rtl" id="span2">WERBEH</span>, Element node <span dir="rtl" id="span5">WERBEH</span>, Element node <span dir="rtl" id="span7">
<input type="tel" id="in..., Element node <input type="tel" id="input-tel3" dir="rtl"></input>, Element node <bdo dir="auto" id="bdo4">إيان</bdo>] length 8, got [] length 0
<input type="tel" id="in..., Element node <input type="tel" id="input-tel3" dir="rtl"></input>, Element node <bdo dir="auto" id="bdo4">إيان</bdo>] length 8, got [Element node <bdo dir="rtl" id="bdo1">WERBEH</bdo>, Element node <bdi dir="rtl" id="bdi2">WERBEH</bdi>, Element node <bdi id="bdi4">إيان</bdi>, Element node <span dir="rtl" id="span2">WERBEH</span>, Element node <span dir="rtl" id="span5">WERBEH</span>, Element node <span dir="rtl" id="span7">
<input type="tel" id="in..., Element node <input type="tel" id="input-tel1"></input>, Element node <input type="tel" id="input-tel2" dir="invalid"></input>, Element node <input type="tel" id="input-tel3" dir="rtl"></input>, Element node <bdo dir="auto" id="bdo4">إيان</bdo>] length 10
FAIL ':dir(ltr)' matches all elements whose directionality is 'ltr'. assert_array_equals: lengths differ, expected array […, Element node <link rel="author" title="Denis Ah-Kang" href="mailto:den..., Element node <link rel="help" href="https://html.spec.whatwg.org/multi..., Element node <script src="/resources/testharness.js" id="script1"></sc..., Element node <script src="/resources/testharnessreport.js" id="script2..., Element node <script src="utils.js" id="script3"></script>, Element node <style id="style">
#span1 {direction: rtl;}
#..., Element node <body id="body">
<div id="log"></div>
<bdo dir="r..., Element node <div id="log"></div>, Element node <bdo dir="ltr" id="bdo2">HEBREW</bdo>, Element node <bdi id="bdi1">HEBREW</bdi>, Element node <bdi dir="ltr" id="bdi3">HEBREW</bdi>, Element node <span id="span1">WERBEH</span>, Element node <span dir="ltr" id="span3">HEBREW</span>, Element node <span id="span4">WERBEH</span>, Element node <span dir="ltr" id="span6">HEBREW</span>, Element node <input type="tel" id="input-tel1"></input>, Element node <input type="tel" id="input-tel2" dir="invalid"></input>, Element node <bdo dir="auto" id="bdo3">HEBREW</bdo>, Element node <bdo dir="ltr" id="bdo5">עברית</bdo>, Element node <script id="script4">
const rtlElements = [
...] length 24, got [] length 0
...] length 24, got […, Element node <meta charset="utf-8" id="meta"></meta>, Element node <title id="title">Selector: pseudo-classes (:dir(ltr), :d..., Element node <link rel="author" title="Denis Ah-Kang" href="mailto:den..., Element node <link rel="help" href="https://html.spec.whatwg.org/multi..., Element node <script src="/resources/testharness.js" id="script1"></sc..., Element node <script src="/resources/testharnessreport.js" id="script2..., Element node <script src="utils.js" id="script3"></script>, Element node <style id="style">
#span1 {direction: rtl;}
#..., Element node <body id="body">
<div id="log"></div>
<bdo dir="r..., Element node <div id="log"></div>, Element node <bdo dir="ltr" id="bdo2">HEBREW</bdo>, Element node <bdi id="bdi1">HEBREW</bdi>, Element node <bdi dir="ltr" id="bdi3">HEBREW</bdi>, Element node <span id="span1">WERBEH</span>, Element node <span dir="ltr" id="span3">HEBREW</span>, Element node <span id="span4">WERBEH</span>, Element node <span dir="ltr" id="span6">HEBREW</span>, Element node <bdo dir="auto" id="bdo3">HEBREW</bdo>, Element node <bdo dir="ltr" id="bdo5">עברית</bdo>, Element node <script id="script4">
const rtlElements = [
...] length 22
FAIL ':dir(ltr)' doesn't match elements not in the document. assert_array_equals: lengths differ, expected array […, Element node <link rel="author" title="Denis Ah-Kang" href="mailto:den..., Element node <link rel="help" href="https://html.spec.whatwg.org/multi..., Element node <script src="/resources/testharness.js" id="script1"></sc..., Element node <script src="/resources/testharnessreport.js" id="script2..., Element node <script src="utils.js" id="script3"></script>, Element node <style id="style">
#span1 {direction: rtl;}
#..., Element node <body id="body">
<div id="log"></div>
<bdo dir="r..., Element node <div id="log"></div>, Element node <bdo dir="ltr" id="bdo2">HEBREW</bdo>, Element node <bdi id="bdi1">HEBREW</bdi>, Element node <bdi dir="ltr" id="bdi3">HEBREW</bdi>, Element node <span id="span1">WERBEH</span>, Element node <span dir="ltr" id="span3">HEBREW</span>, Element node <span id="span4">WERBEH</span>, Element node <span dir="ltr" id="span6">HEBREW</span>, Element node <input type="tel" id="input-tel1"></input>, Element node <input type="tel" id="input-tel2" dir="invalid"></input>, Element node <bdo dir="auto" id="bdo3">HEBREW</bdo>, Element node <bdo dir="ltr" id="bdo5">עברית</bdo>, Element node <script id="script4">
const rtlElements = [
...] length 24, got [] length 0
...] length 24, got […, Element node <meta charset="utf-8" id="meta"></meta>, Element node <title id="title">Selector: pseudo-classes (:dir(ltr), :d..., Element node <link rel="author" title="Denis Ah-Kang" href="mailto:den..., Element node <link rel="help" href="https://html.spec.whatwg.org/multi..., Element node <script src="/resources/testharness.js" id="script1"></sc..., Element node <script src="/resources/testharnessreport.js" id="script2..., Element node <script src="utils.js" id="script3"></script>, Element node <style id="style">
#span1 {direction: rtl;}
#..., Element node <body id="body">
<div id="log"></div>
<bdo dir="r..., Element node <div id="log"></div>, Element node <bdo dir="ltr" id="bdo2">HEBREW</bdo>, Element node <bdi id="bdi1">HEBREW</bdi>, Element node <bdi dir="ltr" id="bdi3">HEBREW</bdi>, Element node <span id="span1">WERBEH</span>, Element node <span dir="ltr" id="span3">HEBREW</span>, Element node <span id="span4">WERBEH</span>, Element node <span dir="ltr" id="span6">HEBREW</span>, Element node <bdo dir="auto" id="bdo3">HEBREW</bdo>, Element node <bdo dir="ltr" id="bdo5">עברית</bdo>, Element node <script id="script4">
const rtlElements = [
...] length 22
WERBEH HEBREW HEBREW WERBEH HEBREW إيان WERBEH WERBEH HEBREW ‮WERBEH‬ HEBREW إيان עברית
@@ -1,4 +1,4 @@


FAIL :dir on <input> isn't altered by text children assert_true: Input with ltr value should match dir(ltr) expected true got false
PASS :dir on <input> isn't altered by text children

@@ -1,10 +1,5 @@

FAIL direction doesn't affect :dir() assert_array_equals: lengths differ, expected array [Element node <html><head><meta charset="iso-8859-8" id="meta">
<title ..., Element node <head><meta charset="iso-8859-8" id="meta">
<title id="ti..., Element node <meta charset="iso-8859-8" id="meta"></meta>, Element node <title id="title">Selector: pseudo-classes (:dir(ltr), :d..., Element node <link rel="author" title="Denis Ah-Kang" href="mailto:den..., Element node <link rel="help" href="https://html.spec.whatwg.org/multi..., Element node <script src="/resources/testharness.js" id="script1"></sc..., Element node <script src="/resources/testharnessreport.js" id="script2..., Element node <script src="utils.js" id="script3"></script>, Element node <body><div id="log"></div>
<div>This text is left to righ..., Element node <div id="log"></div>, Element node <div>This text is left to right<div id="div1" style="dire..., Element node <div id="div1" style="direction:rtl">this is right to lef..., Element node <div>This text is left to right<span id="div2" style="dir..., Element node <span id="div2" style="direction:rtl">this is left to rig..., Element node <script>
var ltr = new Array(),
all = document.qu...] length 16, got [] length 0
PASS direction doesn't affect :dir()
This text is left to right
this is right to left
This text is left to rightthis is left to right
13 changes: 13 additions & 0 deletions Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml
Expand Up @@ -531,6 +531,19 @@ DialogElementEnabled:
WebCore:
default: true

DirPseudoEnabled:
type: bool
humanReadableName: ":dir pseudo-class"
humanReadableDescription: "Enable the directionality pseudo-class :dir"
condition: ENABLE(CSS_SELECTORS_LEVEL4)
defaultValue:
WebKitLegacy:
default: false
WebKit:
default: false
WebCore:
default: false

# FIXME: Starting the preference name with "Disable" is inconsistent with most other preferences and should be changed.
DisableMediaExperiencePIDInheritance:
type: bool
Expand Down
3 changes: 1 addition & 2 deletions Source/WebCore/css/SelectorChecker.cpp
Expand Up @@ -1118,9 +1118,8 @@ bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont
return false;

#if ENABLE(CSS_SELECTORS_LEVEL4)
// FIXME: Implement :dir() selector.
case CSSSelector::PseudoClassDir:
return false;
return matchesDirPseudoClass(element, selector.argument());

// FIXME: Implement :role() selector.
case CSSSelector::PseudoClassRole:
Expand Down
21 changes: 21 additions & 0 deletions Source/WebCore/css/SelectorCheckerTestFunctions.h
Expand Up @@ -248,6 +248,27 @@ ALWAYS_INLINE bool matchesLangPseudoClass(const Element& element, const Vector<A
return false;
}

#if ENABLE(CSS_SELECTORS_LEVEL4)
ALWAYS_INLINE bool matchesDirPseudoClass(const Element& element, const AtomString& argument)
{
if (!is<HTMLElement>(element))
return false;

if (!element.document().settings().dirPseudoEnabled())
return false;

// FIXME: Add support for non-HTML elements.
switch (downcast<HTMLElement>(element).computeDirectionality()) {
case TextDirection::LTR:
return equalIgnoringASCIICase(argument, "ltr"_s);
case TextDirection::RTL:
return equalIgnoringASCIICase(argument, "rtl"_s);
}

return false;
}
#endif

ALWAYS_INLINE bool matchesReadOnlyPseudoClass(const Element& element)
{
return !element.matchesReadWritePseudoClass();
Expand Down
16 changes: 16 additions & 0 deletions Source/WebCore/html/HTMLElement.cpp
Expand Up @@ -778,6 +778,22 @@ bool HTMLElement::hasDirectionAuto() const
return (hasTagName(bdiTag) && direction.isNull()) || equalLettersIgnoringASCIICase(direction, "auto"_s);
}

// FIXME: Cache directionality.
TextDirection HTMLElement::computeDirectionality() const
{
for (const Element* element = this; element; element = const_cast<Element*>(element)->parentOrShadowHostElement()) {
auto direction = element->attributeWithoutSynchronization(dirAttr);
if ((element->hasTagName(bdiTag) && !direction) || equalLettersIgnoringASCIICase(direction, "auto"_s))
return directionality();

if (equalLettersIgnoringASCIICase(direction, "ltr"_s))
return TextDirection::LTR;
if (equalLettersIgnoringASCIICase(direction, "rtl"_s))
return TextDirection::RTL;
}
return TextDirection::LTR;
}

TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) const
{
if (!(selfOrAncestorHasDirAutoAttribute() && hasDirectionAuto())) {
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/html/HTMLElement.h
Expand Up @@ -88,6 +88,7 @@ class HTMLElement : public StyledElement {
WEBCORE_EXPORT const AtomString& dir() const;
WEBCORE_EXPORT void setDir(const AtomString&);

TextDirection computeDirectionality() const;
bool hasDirectionAuto() const;
TextDirection directionalityIfhasDirAutoAttribute(bool& isAuto) const;

Expand Down

0 comments on commit 143e43d

Please sign in to comment.