Source/WebCore/ChangeLog

 12022-05-09 Tim Nguyen <ntim@apple.com>
 2
 3 Implement CSS :modal pseudo class
 4 https://bugs.webkit.org/show_bug.cgi?id=240109
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Test: imported/w3c/web-platform-tests/css/selectors/invalidation/modal-pseudo-class-in-has.html
 9
 10 Renames :-internal-modal-dialog to :modal.
 11
 12 * css/CSSSelector.cpp:
 13 (WebCore::CSSSelector::selectorText const):
 14 * css/CSSSelector.h:
 15 * css/SelectorChecker.cpp:
 16 (WebCore::SelectorChecker::checkOne const):
 17 * css/SelectorCheckerTestFunctions.h:
 18 (WebCore::matchesModalPseudoClass):
 19 (WebCore::matchesModalDialogPseudoClass): Deleted.
 20 * css/SelectorPseudoClassAndCompatibilityElementMap.in:
 21 * css/dialog.css:
 22 (dialog:modal):
 23 (dialog:-internal-modal-dialog): Deleted.
 24 * css/parser/CSSSelectorParser.cpp:
 25 (WebCore::CSSSelectorParser::consumePseudo):
 26 * cssjit/SelectorCompiler.cpp:
 27 (WebCore::SelectorCompiler::JSC_DEFINE_JIT_OPERATION):
 28 (WebCore::SelectorCompiler::addPseudoClassType):
 29 * html/HTMLDialogElement.cpp:
 30 (WebCore::HTMLDialogElement::showModal):
 31 (WebCore::HTMLDialogElement::close):
 32 (WebCore::HTMLDialogElement::removedFromAncestor):
 33 (WebCore::HTMLDialogElement::setIsModal):
 34 * html/HTMLDialogElement.h:
 35
1362022-05-09 Ziran Sun <zsun@igalia.com>
237
338 Make input placeholder line-height declaration !important

Source/WebCore/css/CSSSelector.cpp

@@String CSSSelector::selectorText(const String& rightSide) const
591591 case CSSSelector::PseudoClassLink:
592592 builder.append(":link");
593593 break;
594  case CSSSelector::PseudoClassModalDialog:
595  builder.append(":-internal-modal-dialog");
 594 case CSSSelector::PseudoClassModal:
 595 builder.append(":modal");
596596 break;
597597 case CSSSelector::PseudoClassNoButton:
598598 builder.append(":no-button");

Source/WebCore/css/CSSSelector.h

@@namespace WebCore {
185185#if ENABLE(ATTACHMENT_ELEMENT)
186186 PseudoClassHasAttachment,
187187#endif
188  PseudoClassModalDialog,
 188 PseudoClassModal,
189189 };
190190
191191 enum PseudoElementType {

Source/WebCore/css/SelectorChecker.cpp

@@bool SelectorChecker::checkOne(CheckingContext& checkingContext, const LocalCont
11321132 return hasAttachment(element);
11331133#endif
11341134
1135  case CSSSelector::PseudoClassModalDialog:
1136  return matchesModalDialogPseudoClass(element);
 1135 case CSSSelector::PseudoClassModal:
 1136 return matchesModalPseudoClass(element);
11371137
11381138 case CSSSelector::PseudoClassUnknown:
11391139 ASSERT_NOT_REACHED();

Source/WebCore/css/SelectorCheckerTestFunctions.h

@@ALWAYS_INLINE bool matchesFocusWithinPseudoClass(const Element& element)
531531 return element.hasFocusWithin() && isFrameFocused(element);
532532}
533533
534 ALWAYS_INLINE bool matchesModalDialogPseudoClass(const Element& element)
 534ALWAYS_INLINE bool matchesModalPseudoClass(const Element& element)
535535{
536536 if (is<HTMLDialogElement>(element))
537537 return downcast<HTMLDialogElement>(element).isModal();

Source/WebCore/css/SelectorPseudoClassAndCompatibilityElementMap.in

1 -internal-modal-dialog
21-khtml-drag
32-webkit-any
43-webkit-any-link, PseudoClassAnyLinkDeprecated, PseudoElementUnknown

@@last-child
5049last-of-type
5150link
5251matches
 52modal
5353no-button
5454not
5555nth-child

Source/WebCore/css/dialog.css

@@dialog[open] {
1616 display: block;
1717}
1818
19 dialog:-internal-modal-dialog {
 19dialog:modal {
2020 position: fixed;
2121 overflow: auto;
2222 inset-block-start: 0;

Source/WebCore/css/parser/CSSSelectorParser.cpp

@@std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumePseudo(CSSParserTok
644644 if (!selector)
645645 return nullptr;
646646 if (selector->match() == CSSSelector::PseudoClass) {
647  if (m_context.mode != UASheetMode && selector->pseudoClassType() == CSSSelector::PseudoClassModalDialog)
648  return nullptr;
649647 if (!m_context.focusVisibleEnabled && selector->pseudoClassType() == CSSSelector::PseudoClassFocusVisible)
650648 return nullptr;
651649 if (!m_context.hasPseudoClassEnabled && selector->pseudoClassType() == CSSSelector::PseudoClassHas)

Source/WebCore/cssjit/SelectorCompiler.cpp

@@static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(operationMatchesVolumeLock
125125#if ENABLE(ATTACHMENT_ELEMENT)
126126static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(operationHasAttachment, bool, (const Element&));
127127#endif
128 static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(operationMatchesModalDialogPseudoClass, bool, (const Element&));
 128static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(operationMatchesModalPseudoClass, bool, (const Element&));
129129
130130static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(operationAttributeValueBeginsWithCaseSensitive, bool, (const Attribute* attribute, AtomStringImpl* expectedString));
131131static JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(operationAttributeValueBeginsWithCaseInsensitive, bool, (const Attribute* attribute, AtomStringImpl* expectedString));

@@JSC_DEFINE_JIT_OPERATION(operationMatchesLangPseudoClass, bool, (const Element&
804804 return matchesLangPseudoClass(element, argumentList);
805805}
806806
807 JSC_DEFINE_JIT_OPERATION(operationMatchesModalDialogPseudoClass, bool, (const Element& element))
 807JSC_DEFINE_JIT_OPERATION(operationMatchesModalPseudoClass, bool, (const Element& element))
808808{
809  return matchesModalDialogPseudoClass(element);
 809 return matchesModalPseudoClass(element);
810810}
811811
812812static inline FunctionType addPseudoClassType(const CSSSelector& selector, SelectorFragment& fragment, SelectorContext selectorContext, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode& visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)

@@static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec
945945 return FunctionType::SimpleSelectorChecker;
946946#endif
947947
948  case CSSSelector::PseudoClassModalDialog:
949  fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr<JSC::OperationPtrTag>(operationMatchesModalDialogPseudoClass));
 948 case CSSSelector::PseudoClassModal:
 949 fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr<JSC::OperationPtrTag>(operationMatchesModalPseudoClass));
950950 return FunctionType::SimpleSelectorChecker;
951951
952952 // These pseudo-classes only have meaning with scrollbars.

Source/WebCore/html/HTMLDialogElement.cpp

2626#include "config.h"
2727#include "HTMLDialogElement.h"
2828
 29#include "CSSSelector.h"
2930#include "DocumentInlines.h"
3031#include "EventLoop.h"
3132#include "EventNames.h"
3233#include "FocusOptions.h"
3334#include "HTMLNames.h"
 35#include "PseudoClassChangeInvalidation.h"
3436#include "RenderElement.h"
3537#include "ScopedEventQueue.h"
3638#include "TypedElementDescendantIterator.h"

@@ExceptionOr<void> HTMLDialogElement::showModal()
7577 EventQueueScope scope;
7678 setBooleanAttribute(openAttr, true);
7779
78  m_isModal = true;
 80 setIsModal(true);
7981
8082 if (!isInTopLayer())
8183 addToTopLayer();

@@void HTMLDialogElement::close(const String& result)
9496
9597 setBooleanAttribute(openAttr, false);
9698
97  m_isModal = false;
 99 setIsModal(false);
98100
99101 if (!result.isNull())
100102 m_returnValue = result;

@@void HTMLDialogElement::runFocusingSteps()
158160void HTMLDialogElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
159161{
160162 HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
161  m_isModal = false;
 163 setIsModal(false);
 164}
 165
 166void HTMLDialogElement::setIsModal(bool newValue)
 167{
 168 Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassModal, newValue);
 169 m_isModal = newValue;
162170}
163171
164172}

Source/WebCore/html/HTMLDialogElement.h

@@private:
5353 HTMLDialogElement(const QualifiedName&, Document&);
5454
5555 void removedFromAncestor(RemovalType, ContainerNode& oldParentOfRemovedTree) final;
 56 void setIsModal(bool newValue);
5657
5758 String m_returnValue;
5859 bool m_isModal { false };

LayoutTests/ChangeLog

 12022-05-09 Tim Nguyen <ntim@apple.com>
 2
 3 Implement CSS :modal pseudo class
 4 https://bugs.webkit.org/show_bug.cgi?id=240109
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Removes :-internal-modal-dialog from internal pseudo classes.
 9
 10 * fast/css/pseudo-class-internal-expected.txt:
 11 * fast/css/pseudo-class-internal.html:
 12
1132022-05-09 Ziran Sun <zsun@igalia.com>
214
315 Make input placeholder line-height declaration !important

LayoutTests/imported/w3c/ChangeLog

 12022-05-09 Tim Nguyen <ntim@apple.com>
 2
 3 Implement CSS :modal pseudo class
 4 https://bugs.webkit.org/show_bug.cgi?id=240109
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Add and extend tests for :modal pseudo-class.
 9
 10 * web-platform-tests/css/selectors/invalidation/modal-pseudo-class-in-has-expected.txt: Added.
 11 * web-platform-tests/css/selectors/invalidation/modal-pseudo-class-in-has.html: Added.
 12 * web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-show-modal.html:
 13
1142022-05-06 Rob Buis <rbuis@igalia.com>
215
316 Use correct document as root for lazy image observer

LayoutTests/fast/css/pseudo-class-internal-expected.txt

@@On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
44
55
66PASS target.matches(":-internal-direct-focus") threw exception SyntaxError: The string did not match the expected pattern..
7 PASS target.matches(":-internal-modal-dialog") threw exception SyntaxError: The string did not match the expected pattern..
87PASS successfullyParsed is true
98
109TEST COMPLETE

LayoutTests/fast/css/pseudo-class-internal.html

@@description('This tests that -internal- pseudo classes are not exposed');
1010function runTest() {
1111 const internalPseudoClasses = [
1212 ':-internal-direct-focus',
13  ':-internal-modal-dialog',
1413 ];
1514 for (const pseudo of internalPseudoClasses) {
1615 shouldThrowErrorName('target.matches("' + pseudo + '")', 'SyntaxError');

LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/modal-pseudo-class-in-has-expected.txt

 1This is some text.
 2
 3PASS :modal pseudo-class is not active with dialog.show()
 4PASS :modal pseudo-class invalidation with showModal+close
 5PASS :modal pseudo-class invalidation with showModal+remove
 6

LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/modal-pseudo-class-in-has.html

 1<!DOCTYPE html>
 2<meta charset="utf-8" />
 3<title>CSS Selectors Invalidation: :modal pseudo class in :has()</title>
 4<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
 5<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
 6<script src="/resources/testharness.js"></script>
 7<script src="/resources/testharnessreport.js"></script>
 8<style>
 9 #subject:has(#dialog:modal) { color: green }
 10</style>
 11<div id="subject">
 12 This is some text.
 13 <dialog id="dialog">This is a dialog</dialog>
 14</div>
 15<script>
 16 test(function() {
 17 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
 18 "ancestor should be black since dialog is not modal");
 19 dialog.show();
 20 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
 21 "ancestor should be black since dialog is not modal");
 22 dialog.close();
 23 }, ":modal pseudo-class is not active with dialog.show()");
 24 test(function() {
 25 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
 26 "ancestor should be black");
 27 dialog.showModal();
 28 assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
 29 "ancestor should be green since dialog is shown modally");
 30 dialog.close();
 31 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
 32 "ancestor should be black since dialog is closed");
 33 }, ":modal pseudo-class invalidation with showModal+close");
 34 test(function() {
 35 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
 36 "ancestor should be black");
 37 dialog.showModal();
 38 assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)",
 39 "ancestor should be green since dialog is shown modally");
 40 dialog.remove();
 41 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)",
 42 "ancestor should be black since dialog is closed");
 43 }, ":modal pseudo-class invalidation with showModal+remove");
 44</script>

LayoutTests/imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-show-modal.html

1010
1111<script>
1212test(() => {
13  const dialog = document.getElementById('mydialog');
 13 const dialog = document.getElementById("mydialog");
1414 const computedStyle = window.getComputedStyle(dialog, null);
15  assert_equals(computedStyle.display, 'none');
 15 assert_equals(computedStyle.display, "none");
 16 assert_false(dialog.matches(":modal"));
1617
1718 dialog.showModal();
18  assert_equals(computedStyle.display, 'block');
 19 assert_equals(computedStyle.display, "block");
 20 assert_true(dialog.matches(":modal"));
1921
2022 // The quoted texts output below are from <http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#dom-dialog-showmodal>.
21  assert_throws_dom('InvalidStateError', () => dialog.showModal());
 23 assert_throws_dom("InvalidStateError", () => dialog.showModal());
2224
2325 dialog.close();
24  assert_equals(computedStyle.display, 'none');
 26 assert_equals(computedStyle.display, "none");
 27 assert_false(dialog.matches(":modal"));
2528
2629 dialog.parentNode.removeChild(dialog);
27  assert_throws_dom('InvalidStateError', () => dialog.showModal());
 30 assert_throws_dom("InvalidStateError", () => dialog.showModal());
2831
2932 const doc = document.implementation.createHTMLDocument();
3033 doc.body.appendChild(dialog);
3134 assert_false(dialog.open);
3235 dialog.showModal();
33  assert_true(dialog.open, 'Although the document is not attached to any pages, showModal() should execute as normal.');
34 }, 'Tests that showModal() performs the steps specified in the HTML spec.');
 36 assert_true(dialog.open, "Although the document is not attached to any pages, showModal() should execute as normal.");
 37}, "Tests that showModal() performs the steps specified in the HTML spec.");
3538</script>