Changeset 197165 in webkit
- Timestamp:
- Feb 26, 2016, 6:57:01 AM (9 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r197162 r197165 1 2016-02-26 Antti Koivisto <antti@apple.com> 2 3 Implement ::slotted pseudo element 4 https://bugs.webkit.org/show_bug.cgi?id=149441 5 <rdar://problem/22731987> 6 7 Reviewed by Andreas Kling. 8 9 * fast/shadow-dom/css-scoping-shadow-slotted-rule.html: 10 11 Enable the test, fix it and update it to the current spec. 12 13 * fast/shadow-dom/slotted-pseudo-element-css-text-expected.txt: Added. 14 * fast/shadow-dom/slotted-pseudo-element-css-text.html: Added. 15 16 Add parsing/cssText test based on a Blink test. 17 There are a few failures due to * not roundtripping and the parser being too lenient with pseudo elements. 18 19 * platform/mac/TestExpectations: 20 1 21 2016-02-26 Youenn Fablet <youenn.fablet@crf.canon.fr> 2 22 -
trunk/LayoutTests/fast/shadow-dom/css-scoping-shadow-slotted-rule.html
r190098 r197165 2 2 <html> 3 3 <head> 4 <title>CSS Scoping - :slotted p esudo element must allow selecting elements assigned to a slot element</title>4 <title>CSS Scoping - :slotted pseudo element must allow selecting elements assigned to a slot element</title> 5 5 <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/> 6 6 <link rel="help" href="http://www.w3.org/TR/css-scoping-1/#selectors-data-model"> … … 13 13 width: 100px; 14 14 height: 100px; 15 background: red; 15 color: red; 16 background: green; 16 17 } 17 18 my-host > div, nested-host { … … 24 25 <my-host> 25 26 <div class="green">FAIL1</div> 26 < div><span>FAIL2</span></div>27 <myelem><span>FAIL2</span></myelem> 27 28 <nested-host> 28 29 <span>FAIL3</span> … … 37 38 var shadowHost = document.querySelector('my-host'); 38 39 shadowRoot = shadowHost.attachShadow({mode: 'open'}); 39 shadowRoot.innerHTML = '<slot></slot><style> ::slotted > .green, ::slotted span{ color:green; } </style>';40 shadowRoot.innerHTML = '<slot></slot><style> ::slotted(.green), ::slotted(myelem) { color:green; } </style>'; 40 41 41 42 shadowHost = document.querySelector('nested-host'); 42 43 shadowRoot = shadowHost.attachShadow({mode: 'open'}); 43 shadowRoot.innerHTML = '<s lot></slot>';44 shadowRoot.innerHTML = '<style> .mydiv ::slotted(*) { color:green; } </style><div class=mydiv><slot></slot></div>'; 44 45 45 46 shadowHost = document.querySelector('another-host'); 46 47 shadowRoot = shadowHost.attachShadow({mode: 'open'}); 47 shadowRoot.innerHTML = '<style> ::slotted { color:green; } </style><slot></slot>';48 shadowRoot.innerHTML = '<style> ::slotted(*) { color:green; } </style><slot></slot>'; 48 49 } catch (exception) { 49 50 document.body.appendChild(document.createTextNode(exception)); -
trunk/LayoutTests/platform/mac/TestExpectations
r197162 r197165 1250 1250 webkit.org/b/148695 fast/shadow-dom [ Pass ] 1251 1251 webkit.org/b/149440 fast/shadow-dom/css-scoping-shadow-host-functional-rule.html [ ImageOnlyFailure ] 1252 webkit.org/b/149441 fast/shadow-dom/css-scoping-shadow-slotted-rule.html [ ImageOnlyFailure ]1253 1252 webkit.org/b/149441 fast/shadow-dom/css-scoping-shadow-slot-display-override.html [ ImageOnlyFailure ] 1254 1253 -
trunk/Source/WebCore/ChangeLog
r197160 r197165 1 2016-02-25 Antti Koivisto <antti@apple.com> 2 3 Implement ::slotted pseudo element 4 https://bugs.webkit.org/show_bug.cgi?id=149441 5 <rdar://problem/22731987> 6 7 Reviewed by Andreas Kling. 8 9 Based on latest in https://github.com/w3c/webcomponents/issues/331 10 11 * css/CSSGrammar.y.in: 12 13 Parse ::slotted. 14 15 * css/CSSParser.cpp: 16 (WebCore::CSSParser::detectFunctionTypeToken): 17 * css/CSSParserValues.cpp: 18 (WebCore::CSSParserSelector::parsePseudoElementCueFunctionSelector): 19 (WebCore::CSSParserSelector::parsePseudoElementSlottedFunctionSelector): 20 21 Tokenize ::slotted. 22 23 (WebCore::CSSParserSelector::parsePseudoClassAndCompatibilityElementSelector): 24 * css/CSSParserValues.h: 25 * css/CSSSelector.cpp: 26 (WebCore::CSSSelector::pseudoId): 27 * css/CSSSelector.h: 28 * css/ElementRuleCollector.cpp: 29 (WebCore::ElementRuleCollector::matchAuthorRules): 30 (WebCore::ElementRuleCollector::matchHostPseudoClassRules): 31 (WebCore::ElementRuleCollector::matchSlottedPseudoElementRules): 32 33 Match ::slotted selector. 34 35 (WebCore::ElementRuleCollector::collectSlottedPseudoElementRulesForSlot): 36 37 Collect ::slotted rules that may apply to an element in a slot. 38 39 (WebCore::ElementRuleCollector::matchUserRules): 40 (WebCore::ElementRuleCollector::matchUARules): 41 (WebCore::findSlottedPseudoElementSelector): 42 (WebCore::ElementRuleCollector::ruleMatches): 43 * css/ElementRuleCollector.h: 44 * css/RuleSet.cpp: 45 (WebCore::RuleSet::addRule): 46 47 Collect ::slotted rules. 48 49 (WebCore::RuleSet::shrinkToFit): 50 * css/RuleSet.h: 51 (WebCore::RuleSet::hostPseudoClassRules): 52 (WebCore::RuleSet::slottedPseudoElementRules): 53 (WebCore::RuleSet::focusPseudoClassRules): 54 (WebCore::RuleSet::universalRules): 55 * css/SelectorChecker.cpp: 56 (WebCore::SelectorChecker::checkOne): 57 * style/StyleSharingResolver.cpp: 58 (WebCore::Style::SharingResolver::resolve): 59 60 Disable style sharing for children of shadow host. They may be affected by the shadow tree style 61 which is not considered in style sharing checks. 62 1 63 2016-02-25 Myles C. Maxfield <mmaxfield@apple.com> 2 64 -
trunk/Source/WebCore/css/CSSGrammar.y.in
r195951 r197165 366 366 #endif 367 367 368 #if ENABLE_SHADOW_DOM 369 370 %token <string> SLOTTEDFUNCTION 371 372 #endif 373 368 374 %% 369 375 … … 1356 1362 | ':' ':' CUEFUNCTION maybe_space simple_selector_list maybe_space ')' { 1357 1363 $$ = CSSParserSelector::parsePseudoElementCueFunctionSelector($3, $5); 1364 } 1365 #endif 1366 #if ENABLE_SHADOW_DOM 1367 | ':' ':' SLOTTEDFUNCTION maybe_space compound_selector maybe_space ')' { 1368 $$ = CSSParserSelector::parsePseudoElementSlottedFunctionSelector($3, $5); 1358 1369 } 1359 1370 #endif -
trunk/Source/WebCore/css/CSSParser.cpp
r197022 r197165 11895 11895 return true; 11896 11896 } 11897 #if ENABLE(SHADOW_DOM) 11898 if (isEqualToCSSIdentifier(name, "slotted")) { 11899 m_token = SLOTTEDFUNCTION; 11900 return true; 11901 } 11902 #endif 11897 11903 return false; 11898 11904 -
trunk/Source/WebCore/css/CSSParserValues.cpp
r195951 r197165 232 232 #endif 233 233 234 #if ENABLE(SHADOW_DOM) 235 CSSParserSelector* CSSParserSelector::parsePseudoElementSlottedFunctionSelector(const CSSParserString& functionIdentifier, CSSParserSelector* parsedSelector) 236 { 237 ASSERT_UNUSED(functionIdentifier, String(functionIdentifier) == "slotted("); 238 239 if (!parsedSelector) 240 return nullptr; 241 242 std::unique_ptr<CSSParserSelector> ownedParsedSelector(parsedSelector); 243 244 for (auto* component = parsedSelector; component; component = component->tagHistory()) { 245 if (component->matchesPseudoElement()) 246 return nullptr; 247 } 248 249 auto selectorVector = std::make_unique<Vector<std::unique_ptr<CSSParserSelector>>>(); 250 selectorVector->append(WTFMove(ownedParsedSelector)); 251 252 auto selector = std::make_unique<CSSParserSelector>(); 253 selector->m_selector->setMatch(CSSSelector::PseudoElement); 254 selector->m_selector->setPseudoElementType(CSSSelector::PseudoElementSlotted); 255 selector->adoptSelectorVector(*selectorVector); 256 return selector.release(); 257 } 258 #endif 259 234 260 CSSParserSelector* CSSParserSelector::parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString) 235 261 { -
trunk/Source/WebCore/css/CSSParserValues.h
r195951 r197165 204 204 static CSSParserSelector* parsePagePseudoSelector(const CSSParserString& pseudoTypeString); 205 205 static CSSParserSelector* parsePseudoElementSelector(CSSParserString& pseudoTypeString); 206 static CSSParserSelector* parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>* selectorVector); 206 static CSSParserSelector* parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>*); 207 #if ENABLE(SHADOW_DOM) 208 static CSSParserSelector* parsePseudoElementSlottedFunctionSelector(const CSSParserString& functionIdentifier, CSSParserSelector*); 209 #endif 207 210 static CSSParserSelector* parsePseudoClassAndCompatibilityElementSelector(CSSParserString& pseudoTypeString); 208 211 -
trunk/Source/WebCore/css/CSSSelector.cpp
r195951 r197165 300 300 case PseudoElementCue: 301 301 #endif 302 #if ENABLE(SHADOW_DOM) 303 case PseudoElementSlotted: 304 #endif 302 305 case PseudoElementUnknown: 303 306 case PseudoElementUserAgentCustom: … … 645 648 } 646 649 } else if (cs->match() == CSSSelector::PseudoElement) { 647 str.appendLiteral("::"); 648 str.append(cs->value()); 650 switch (cs->pseudoElementType()) { 651 #if ENABLE(SHADOW_DOM) 652 case CSSSelector::PseudoElementSlotted: 653 str.appendLiteral("::slotted("); 654 cs->selectorList()->buildSelectorsText(str); 655 str.append(')'); 656 break; 657 #endif 658 default: 659 str.appendLiteral("::"); 660 str.append(cs->value()); 661 } 649 662 } else if (cs->isAttributeSelector()) { 650 663 str.append('['); -
trunk/Source/WebCore/css/CSSSelector.h
r192758 r197165 182 182 PseudoElementScrollbarTrackPiece, 183 183 PseudoElementSelection, 184 #if ENABLE(SHADOW_DOM) 185 PseudoElementSlotted, 186 #endif 184 187 PseudoElementUserAgentCustom, 185 188 PseudoElementWebKitCustom, -
trunk/Source/WebCore/css/ElementRuleCollector.cpp
r196383 r197165 37 37 #include "CSSValueKeywords.h" 38 38 #include "HTMLElement.h" 39 #include "HTMLSlotElement.h" 39 40 #include "InspectorInstrumentation.h" 40 41 #include "NodeRenderStyle.h" … … 207 208 if (m_element.shadowRoot()) 208 209 matchHostPseudoClassRules(includeEmptyRules); 210 211 auto* parent = m_element.parentNode(); 212 if (parent && parent->shadowRoot()) 213 matchSlottedPseudoElementRules(includeEmptyRules); 209 214 #endif 210 215 … … 241 246 // FIXME: Match the spec when it is finalized. 242 247 sortAndTransferMatchedRules(); 248 } 249 250 void ElementRuleCollector::matchSlottedPseudoElementRules(bool includeEmptyRules) 251 { 252 auto* hostShadowRoot = m_element.parentNode()->shadowRoot(); 253 ASSERT(hostShadowRoot); 254 auto* slot = hostShadowRoot->findAssignedSlot(m_element); 255 if (!slot) 256 return; 257 auto* shadowAuthorStyle = hostShadowRoot->styleResolver().ruleSets().authorStyle(); 258 if (!shadowAuthorStyle) 259 return; 260 // Find out if there are any ::slotted rules in the shadow tree matching the current slot. 261 // FIXME: This is really part of the slot style and could be cached when resolving it. 262 ElementRuleCollector collector(*slot, *shadowAuthorStyle, nullptr); 263 auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot(includeEmptyRules); 264 if (slottedPseudoElementRules.isEmpty()) 265 return; 266 267 clearMatchedRules(); 268 m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1; 269 270 { 271 // Match in the current scope. 272 TemporaryChange<bool> change(m_isMatchingSlottedPseudoElements, true); 273 274 MatchRequest matchRequest(nullptr, includeEmptyRules); 275 auto ruleRange = m_result.ranges.authorRuleRange(); 276 collectMatchingRulesForList(&slottedPseudoElementRules, matchRequest, ruleRange); 277 } 278 279 // FIXME: What is the correct order? 280 sortAndTransferMatchedRules(); 281 } 282 283 RuleSet::RuleDataVector ElementRuleCollector::collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules) 284 { 285 ASSERT(is<HTMLSlotElement>(m_element)); 286 287 clearMatchedRules(); 288 289 m_mode = SelectorChecker::Mode::CollectingRules; 290 291 // Match global author rules. 292 MatchRequest matchRequest(&m_authorStyle, includeEmptyRules); 293 StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); 294 collectMatchingRulesForList(&m_authorStyle.slottedPseudoElementRules(), matchRequest, ruleRange); 295 296 if (m_matchedRules.isEmpty()) 297 return { }; 298 299 RuleSet::RuleDataVector ruleDataVector; 300 ruleDataVector.reserveInitialCapacity(m_matchedRules.size()); 301 for (auto& matchedRule : m_matchedRules) 302 ruleDataVector.uncheckedAppend(*matchedRule.ruleData); 303 return ruleDataVector; 243 304 } 244 305 #endif … … 284 345 sortAndTransferMatchedRules(); 285 346 } 347 348 #if ENABLE(SHADOW_DOM) 349 static const CSSSelector* findSlottedPseudoElementSelector(const CSSSelector* selector) 350 { 351 for (; selector; selector = selector->tagHistory()) { 352 if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementSlotted) { 353 if (auto* list = selector->selectorList()) 354 return list->first(); 355 break; 356 } 357 }; 358 return nullptr; 359 } 360 #endif 286 361 287 362 inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, unsigned& specificity) … … 357 432 #endif // ENABLE(CSS_SELECTOR_JIT) 358 433 { 434 auto* selector = ruleData.selector(); 435 #if ENABLE(SHADOW_DOM) 436 if (m_isMatchingSlottedPseudoElements) { 437 selector = findSlottedPseudoElementSelector(ruleData.selector()); 438 if (!selector) 439 return false; 440 } 441 #endif 359 442 // Slow path. 360 443 SelectorChecker selectorChecker(m_element.document()); 361 selectorMatches = selectorChecker.match(* ruleData.selector(), m_element, context, specificity);444 selectorMatches = selectorChecker.match(*selector, m_element, context, specificity); 362 445 } 363 446 -
trunk/Source/WebCore/css/ElementRuleCollector.h
r196383 r197165 74 74 #if ENABLE(SHADOW_DOM) 75 75 void matchHostPseudoClassRules(bool includeEmptyRules); 76 void matchSlottedPseudoElementRules(bool includeEmptyRules); 77 RuleSet::RuleDataVector collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules); 76 78 #endif 77 79 … … 99 101 bool m_sameOriginOnly { false }; 100 102 SelectorChecker::Mode m_mode { SelectorChecker::Mode::ResolvingStyle }; 103 #if ENABLE(SHADOW_DOM) 104 bool m_isMatchingSlottedPseudoElements { false }; 105 #endif 101 106 102 107 Vector<MatchedRule, 64> m_matchedRules; -
trunk/Source/WebCore/css/RuleSet.cpp
r196383 r197165 267 267 return; 268 268 } 269 if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementSlotted) { 270 // ::slotted pseudo elements work accross shadow boundary making filtering difficult. 271 ruleData.disableSelectorFiltering(); 272 m_slottedPseudoElementRules.append(ruleData); 273 return; 274 } 269 275 #endif 270 276 if (selector->relation() != CSSSelector::SubSelector) … … 423 429 m_cuePseudoRules.shrinkToFit(); 424 430 #endif 431 #if ENABLE(SHADOW_DOM) 432 m_hostPseudoClassRules.shrinkToFit(); 433 m_slottedPseudoElementRules.shrinkToFit(); 434 #endif 425 435 m_focusPseudoClassRules.shrinkToFit(); 426 436 m_universalRules.shrinkToFit(); -
trunk/Source/WebCore/css/RuleSet.h
r196383 r197165 185 185 #if ENABLE(SHADOW_DOM) 186 186 const RuleDataVector& hostPseudoClassRules() const { return m_hostPseudoClassRules; } 187 const RuleDataVector& slottedPseudoElementRules() const { return m_slottedPseudoElementRules; } 187 188 #endif 188 189 const RuleDataVector* focusPseudoClassRules() const { return &m_focusPseudoClassRules; } … … 211 212 #if ENABLE(SHADOW_DOM) 212 213 RuleDataVector m_hostPseudoClassRules; 214 RuleDataVector m_slottedPseudoElementRules; 213 215 #endif 214 216 RuleDataVector m_focusPseudoClassRules; -
trunk/Source/WebCore/css/SelectorChecker.cpp
r196629 r197165 45 45 #include "HTMLParserIdioms.h" 46 46 #include "HTMLProgressElement.h" 47 #include "HTMLSlotElement.h" 47 48 #include "HTMLStyleElement.h" 48 49 #include "InspectorInstrumentation.h" … … 1039 1040 } 1040 1041 #endif 1041 // ### add the rest of the checks... 1042 #if ENABLE(SHADOW_DOM) 1043 if (selector.match() == CSSSelector::PseudoElement && selector.pseudoElementType() == CSSSelector::PseudoElementSlotted) { 1044 // We see ::slotted() pseudo elements when collecting slotted rules from the slot shadow tree only. 1045 ASSERT(checkingContext.resolvingMode == Mode::CollectingRules); 1046 return is<HTMLSlotElement>(element); 1047 } 1048 #endif 1042 1049 return true; 1043 1050 } -
trunk/Source/WebCore/style/StyleSharingResolver.cpp
r196031 r197165 77 77 return nullptr; 78 78 auto& parentElement = *element.parentElement(); 79 if (parentElement.shadowRoot()) 80 return nullptr; 79 81 if (!parentElement.renderStyle()) 80 82 return nullptr;
Note:
See TracChangeset
for help on using the changeset viewer.