std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector( CSSParserTokenRange& range) { std::unique_ptr<CSSParserSelector> compoundSelector; AtomicString namespacePrefix; AtomicString elementName; CSSSelector::PseudoType compoundPseudoElement = CSSSelector::PseudoUnknown; if (!consumeName(range, elementName, namespacePrefix)) { compoundSelector = consumeSimpleSelector(range); if (!compoundSelector) return nullptr; if (compoundSelector->match() == CSSSelector::PseudoElement) compoundPseudoElement = compoundSelector->pseudoType(); } if (m_context.isHTMLDocument()) elementName = elementName.lower(); while (std::unique_ptr<CSSParserSelector> simpleSelector = consumeSimpleSelector(range)) { // TODO([email protected]): crbug.com/578131 // The UASheetMode check is a work-around to allow this selector in // mediaControls(New).css: // video::-webkit-media-text-track-region-container.scrolling if (m_context.mode() != UASheetMode && !isSimpleSelectorValidAfterPseudoElement(*simpleSelector.get(), compoundPseudoElement)) { m_failedParsing = true; return nullptr; } if (simpleSelector->match() == CSSSelector::PseudoElement) compoundPseudoElement = simpleSelector->pseudoType(); if (compoundSelector) compoundSelector = addSimpleSelectorToCompound( std::move(compoundSelector), std::move(simpleSelector)); else compoundSelector = std::move(simpleSelector); } if (!compoundSelector) { AtomicString namespaceURI = determineNamespace(namespacePrefix); if (namespaceURI.isNull()) { m_failedParsing = true; return nullptr; } if (namespaceURI == defaultNamespace()) namespacePrefix = nullAtom; return CSSParserSelector::create( QualifiedName(namespacePrefix, elementName, namespaceURI)); } prependTypeSelectorIfNeeded(namespacePrefix, elementName, compoundSelector.get()); return splitCompoundAtImplicitShadowCrossingCombinator( std::move(compoundSelector)); }
const AtomicString& CSSSelectorParser::determineNamespace( const AtomicString& prefix) { if (prefix.isNull()) return defaultNamespace(); if (prefix.isEmpty()) return emptyAtom; // No namespace. If an element/attribute has a namespace, // we won't match it. if (prefix == starAtom) return starAtom; // We'll match any namespace. if (!m_styleSheet) return nullAtom; // Cannot resolve prefix to namespace without a // stylesheet, syntax error. return m_styleSheet->namespaceURIFromPrefix(prefix); }
Stmt* Parser::forStatement() { Expr* init=NULL; Expr* lhs=NULL; uint32_t numbindings = 0; bool is_each = false; eat (T_For); if (hd() == T_Identifier && identValue() == compiler->SYM_each) { is_each = true; eat(T_Identifier); } uint32_t pos = position(); eat (T_LeftParen); if (hd() == T_Var) { uint32_t dummy = 0; init = varBindings(&dummy, defaultNamespace(), false, false, EFLAG_NoIn, &numbindings, &lhs); } else if (hd() == T_Semicolon) ; else lhs = init = commaExpression(EFLAG_NoIn); if (match(T_In)) { if (numbindings > 1) compiler->syntaxError(pos, SYNTAXERR_FOR_IN_ONEBINDING); Expr* objexpr = commaExpression(0); eat (T_RightParen); Stmt* body = statement(); AvmAssert( lhs != NULL ); return ALLOC(ForInStmt, (pos, lhs, init, objexpr, body, is_each)); } else { if (is_each) compiler->syntaxError(pos, SYNTAXERR_FOR_EACH_REQS_IN); eat(T_Semicolon); Expr* test = hd() == T_Semicolon ? NULL : commaExpression(0); eat(T_Semicolon); Expr* update = hd() == T_RightParen ? NULL : commaExpression(0); eat(T_RightParen); Stmt* body = statement (); return ALLOC(ForStmt, (pos, init, test, update, body)); } }
void CSSSelectorParser::prependTypeSelectorIfNeeded( const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) { if (elementName.isNull() && defaultNamespace() == starAtom && !compoundSelector->needsImplicitShadowCombinatorForMatching()) return; AtomicString determinedElementName = elementName.isNull() ? starAtom : elementName; AtomicString namespaceURI = determineNamespace(namespacePrefix); if (namespaceURI.isNull()) { m_failedParsing = true; return; } AtomicString determinedPrefix = namespacePrefix; if (namespaceURI == defaultNamespace()) determinedPrefix = nullAtom; QualifiedName tag = QualifiedName(determinedPrefix, determinedElementName, namespaceURI); // *:host/*:host-context never matches, so we can't discard the *, // otherwise we can't tell the difference between *:host and just :host. // // Also, selectors where we use a ShadowPseudo combinator between the // element and the pseudo element for matching (custom pseudo elements, // ::cue, ::shadow), we need a universal selector to set the combinator // (relation) on in the cases where there are no simple selectors preceding // the pseudo element. bool explicitForHost = compoundSelector->isHostPseudoSelector() && !elementName.isNull(); if (tag != anyQName() || explicitForHost || compoundSelector->needsImplicitShadowCombinatorForMatching()) compoundSelector->prependTagSelector( tag, determinedPrefix == nullAtom && determinedElementName == starAtom && !explicitForHost); }