Changeset 285054 in webkit
- Timestamp:
- Oct 29, 2021 2:42:50 PM (9 months ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
LayoutTests/imported/w3c/ChangeLog (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing-expected.txt (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/css/parser/CSSSelectorParser.cpp (modified) (16 diffs)
-
Source/WebCore/css/parser/CSSSelectorParser.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r285045 r285054 1 2021-10-29 Antti Koivisto <antti@apple.com> 2 3 Allow :is/:where after all pseudo elements 4 https://bugs.webkit.org/show_bug.cgi?id=232434 5 6 Reviewed by Dean Jackson. 7 8 * web-platform-tests/css/css-scoping/slotted-parsing-expected.txt: 9 1 10 2021-10-29 Yusuke Suzuki <ysuzuki@apple.com> 2 11 -
trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/slotted-parsing-expected.txt
r284973 r285054 16 16 PASS "::slotted([attr]:hover)" should be a valid selector 17 17 PASS "::slotted(:not(.a))" should be a valid selector 18 FAIL "::slotted(*):is()" should be a valid selector The string did not match the expected pattern. 19 FAIL "::slotted(*):is(:hover)" should be a valid selector The string did not match the expected pattern. 20 FAIL "::slotted(*):is(#id)" should be a valid selector The string did not match the expected pattern. 21 FAIL "::slotted(*):where()" should be a valid selector The string did not match the expected pattern. 22 FAIL "::slotted(*):where(:hover)" should be a valid selector The string did not match the expected pattern. 23 FAIL "::slotted(*):where(#id)" should be a valid selector The string did not match the expected pattern. 18 PASS "::slotted(*):is()" should be a valid selector 19 PASS "::slotted(*):is(:hover)" should be a valid selector 20 PASS "::slotted(*):is(#id)" should be a valid selector 21 PASS "::slotted(*):where()" should be a valid selector 22 PASS "::slotted(*):where(:hover)" should be a valid selector 23 PASS "::slotted(*):where(#id)" should be a valid selector 24 24 PASS "::slotted(*)::before" should be a valid selector 25 25 PASS "::slotted(*)::after" should be a valid selector -
trunk/Source/WebCore/ChangeLog
r285050 r285054 1 2021-10-29 Antti Koivisto <antti@apple.com> 2 3 Allow :is/:where after all pseudo elements 4 https://bugs.webkit.org/show_bug.cgi?id=232434 5 6 Reviewed by Dean Jackson. 7 8 Any subselectors that are not legal in the context will be removed by the forgiving parsing. 9 This matches the behavior in other engines and the discussion in https://github.com/w3c/csswg-drafts/issues/5093. 10 11 The validity check is moved from the compound selector level to the simple selector level. This way if we are 12 inside forgiving selector list parsing, it can recover and continue. 13 14 * css/parser/CSSSelectorParser.cpp: 15 (WebCore::isLogicalCombinationPseudoClass): 16 (WebCore::isPseudoClassValidAfterPseudoElement): 17 (WebCore::isSimpleSelectorValidAfterPseudoElement): 18 19 :is(), :where(), and so on are always legal but their content is necessarily not. 20 21 (WebCore::CSSSelectorParser::consumeCompoundSelector): 22 23 Set the preceding pseudo-element as parser state. 24 25 (WebCore::CSSSelectorParser::consumeSimpleSelector): 26 27 Check if the pseudo-class or pseudo-element is valid immediately after consuming it. 28 29 (WebCore::CSSSelectorParser::consumePseudo): 30 31 Disallow nesting in all cases. 32 33 (WebCore::CSSSelectorParser::DisallowPseudoElementsScope::DisallowPseudoElementsScope): Deleted. 34 (WebCore::CSSSelectorParser::DisallowPseudoElementsScope::~DisallowPseudoElementsScope): Deleted. 35 36 Just use SetForScope. 37 38 * css/parser/CSSSelectorParser.h: 39 1 40 2021-10-29 Alan Bujtas <zalan@apple.com> 2 41 -
trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp
r285032 r285054 40 40 namespace WebCore { 41 41 42 class CSSSelectorParser::DisallowPseudoElementsScope {43 public:44 explicit DisallowPseudoElementsScope(CSSSelectorParser& parser)45 : m_parser(parser)46 , m_wasDisallowed(std::exchange(m_parser.m_disallowPseudoElements, true))47 {48 }49 50 ~DisallowPseudoElementsScope()51 {52 m_parser.m_disallowPseudoElements = m_wasDisallowed;53 }54 55 private:56 CSSSelectorParser& m_parser;57 bool m_wasDisallowed;58 };59 60 42 static AtomString serializeANPlusB(const std::pair<int, int>&); 61 43 static bool consumeANPlusB(CSSParserTokenRange&, std::pair<int, int>&); … … 339 321 } 340 322 323 static bool isLogicalCombinationPseudoClass(CSSSelector::PseudoClassType pseudo) 324 { 325 switch (pseudo) { 326 case CSSSelector::PseudoClassIs: 327 case CSSSelector::PseudoClassWhere: 328 case CSSSelector::PseudoClassNot: 329 case CSSSelector::PseudoClassAny: 330 case CSSSelector::PseudoClassMatches: 331 case CSSSelector::PseudoClassHas: 332 return true; 333 default: 334 return false; 335 } 336 } 337 341 338 static bool isPseudoClassValidAfterPseudoElement(CSSSelector::PseudoClassType pseudoClass, CSSSelector::PseudoElementType compoundPseudoElement) 342 339 { 340 // Validity of these is determined by their content. 341 if (isLogicalCombinationPseudoClass(pseudoClass)) 342 return true; 343 343 344 switch (compoundPseudoElement) { 344 345 case CSSSelector::PseudoElementPart: 345 346 return !isTreeStructuralPseudoClass(pseudoClass); 346 347 case CSSSelector::PseudoElementSlotted: 347 // FIXME: A WPT indicates :is/:where should be parsed but reduce to nothing as their content is not legal in the context.348 348 return false; 349 349 case CSSSelector::PseudoElementResizer: … … 380 380 static bool isSimpleSelectorValidAfterPseudoElement(const CSSParserSelector& simpleSelector, CSSSelector::PseudoElementType compoundPseudoElement) 381 381 { 382 if (compoundPseudoElement == CSSSelector::PseudoElementUnknown)383 return true;382 ASSERT(compoundPseudoElement != CSSSelector::PseudoElementUnknown); 383 384 384 if (compoundPseudoElement == CSSSelector::PseudoElementPart) { 385 385 if (simpleSelector.match() == CSSSelector::PseudoElement && simpleSelector.pseudoElementType() != CSSSelector::PseudoElementPart) … … 392 392 if (simpleSelector.match() != CSSSelector::PseudoClass) 393 393 return false; 394 CSSSelector::PseudoClassType pseudo = simpleSelector.pseudoClassType(); 395 if (pseudo == CSSSelector::PseudoClassNot) { 396 ASSERT(simpleSelector.selectorList()); 397 ASSERT(simpleSelector.selectorList()->first()); 398 pseudo = simpleSelector.selectorList()->first()->pseudoClassType(); 399 } 400 return isPseudoClassValidAfterPseudoElement(pseudo, compoundPseudoElement); 394 395 return isPseudoClassValidAfterPseudoElement(simpleSelector.pseudoClassType(), compoundPseudoElement); 401 396 } 402 397 … … 409 404 std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSParserTokenRange& range) 410 405 { 406 ASSERT(!m_precedingPseudoElement || m_disallowPseudoElements); 407 411 408 std::unique_ptr<CSSParserSelector> compoundSelector; 412 409 413 410 AtomString namespacePrefix; 414 411 AtomString elementName; 415 CSSSelector::PseudoElementType compoundPseudoElement = CSSSelector::PseudoElementUnknown;416 412 const bool hasName = consumeName(range, elementName, namespacePrefix); 417 413 if (!hasName) { … … 420 416 return nullptr; 421 417 if (compoundSelector->match() == CSSSelector::PseudoElement) 422 compoundPseudoElement = compoundSelector->pseudoElementType();418 m_precedingPseudoElement = compoundSelector->pseudoElementType(); 423 419 } 424 420 425 421 while (auto simpleSelector = consumeSimpleSelector(range)) { 426 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747427 // The UASheetMode check is a work-around to allow this selector in mediaControls(New).css:428 // video::-webkit-media-text-track-region-container.scrolling429 if (m_context.mode != UASheetMode && !isSimpleSelectorValidAfterPseudoElement(*simpleSelector.get(), compoundPseudoElement)) {430 m_failedParsing = true;431 return nullptr;432 }433 422 if (simpleSelector->match() == CSSSelector::PseudoElement) 434 compoundPseudoElement = simpleSelector->pseudoElementType();423 m_precedingPseudoElement = simpleSelector->pseudoElementType(); 435 424 436 425 if (compoundSelector) … … 440 429 } 441 430 431 if (!m_disallowPseudoElements) 432 m_precedingPseudoElement = { }; 442 433 443 434 // While inside a nested selector like :is(), the default namespace shall be ignored when [1]: … … 477 468 else 478 469 return nullptr; 479 if (!selector) 470 471 if (!selector) { 480 472 m_failedParsing = true; 473 return nullptr; 474 } 475 476 if (m_precedingPseudoElement) { 477 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747 478 // The UASheetMode check is a work-around to allow this selector in mediaControls(New).css: 479 // video::-webkit-media-text-track-region-container.scrolling 480 if (m_context.mode != UASheetMode && !isSimpleSelectorValidAfterPseudoElement(*selector, *m_precedingPseudoElement)) 481 m_failedParsing = true; 482 } 483 481 484 return selector; 482 485 } … … 677 680 } 678 681 679 if (!selector || (selector->match() == CSSSelector::PseudoElement && m_disallowPseudoElements)) 680 return nullptr; 682 if (!selector) 683 return nullptr; 684 685 // Pseudo-elements are not allowed inside pseudo-classes or pseudo-elements. 686 if (selector->match() == CSSSelector::PseudoElement && m_disallowPseudoElements) 687 return nullptr; 688 SetForScope disallowPseudoElementsScope(m_disallowPseudoElements, true); 681 689 682 690 if (token.type() == IdentToken) { … … 692 700 if (token.type() != FunctionToken) 693 701 return nullptr; 694 702 695 703 if (selector->match() == CSSSelector::PseudoClass) { 696 704 switch (selector->pseudoClassType()) { 697 705 case CSSSelector::PseudoClassNot: { 698 706 SetForScope<bool> resistDefaultNamespace(m_resistDefaultNamespace, true); 699 DisallowPseudoElementsScope scope(*this);700 707 auto selectorList = makeUnique<CSSSelectorList>(); 701 708 *selectorList = consumeComplexSelectorList(block); … … 723 730 if (block.peek().type() != WhitespaceToken) 724 731 return nullptr; 725 DisallowPseudoElementsScope scope(*this);726 732 block.consumeWhitespace(); 727 733 auto selectorList = makeUnique<CSSSelectorList>(); … … 747 753 case CSSSelector::PseudoClassAny: { 748 754 SetForScope<bool> resistDefaultNamespace(m_resistDefaultNamespace, true); 749 DisallowPseudoElementsScope scope(*this);750 755 auto selectorList = makeUnique<CSSSelectorList>(); 751 756 *selectorList = consumeForgivingComplexSelectorList(block); … … 764 769 } 765 770 case CSSSelector::PseudoClassHas: { 766 DisallowPseudoElementsScope scope(*this);767 771 auto selectorList = makeUnique<CSSSelectorList>(); 768 772 *selectorList = consumeForgivingRelativeSelectorList(block); … … 791 795 #if ENABLE(VIDEO) 792 796 case CSSSelector::PseudoElementCue: { 793 DisallowPseudoElementsScope scope(*this);794 797 auto selectorList = makeUnique<CSSSelectorList>(); 795 798 *selectorList = consumeCompoundSelectorList(block); … … 801 804 #endif 802 805 case CSSSelector::PseudoElementHighlight: { 803 DisallowPseudoElementsScope scope(*this);804 805 806 auto& ident = block.consumeIncludingWhitespace(); 806 807 if (ident.type() != IdentToken || !block.atEnd()) … … 826 827 } 827 828 case CSSSelector::PseudoElementSlotted: { 828 DisallowPseudoElementsScope scope(*this);829 830 829 auto innerSelector = consumeCompoundSelector(block); 831 830 block.consumeWhitespace(); -
trunk/Source/WebCore/css/parser/CSSSelectorParser.h
r281295 r285054 92 92 bool m_resistDefaultNamespace { false }; 93 93 bool m_ignoreDefaultNamespace { false }; 94 std::optional<CSSSelector::PseudoElementType> m_precedingPseudoElement; 94 95 }; 95 96
Note: See TracChangeset
for help on using the changeset viewer.