void ScopedStyleResolver::collectMatchingShadowHostRules(ElementRuleCollector& collector, CascadeOrder cascadeOrder) { for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) { ASSERT(m_authorStyleSheets[i]->ownerNode()); MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), &m_scope->rootNode(), m_authorStyleSheets[i], i); collector.collectMatchingShadowHostRules(matchRequest, cascadeOrder); } }
void ScopedStyleResolver::collectMatchingShadowHostRules(ElementRuleCollector& collector, bool includeEmptyRules, CascadeOrder cascadeOrder) { RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); ASSERT(!collector.scopeContainsLastMatchedElement()); collector.setScopeContainsLastMatchedElement(true); for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) { ASSERT(m_authorStyleSheets[i]->ownerNode()); MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), includeEmptyRules, &m_scope->rootNode(), m_authorStyleSheets[i], i); collector.collectMatchingShadowHostRules(matchRequest, ruleRange, cascadeOrder); } collector.setScopeContainsLastMatchedElement(false); }
void Matcher_impl::execMatchedRules(std::shared_ptr<ParsedRequest> parsedRequest) { std::queue<std::shared_ptr<Rule> > ruleQueue= matchRequest(parsedRequest->getUrl()); while(!ruleQueue.empty()) { std::shared_ptr<Rule> rule = ruleQueue.front(); rule->operateRequest(parsedRequest); if(rule->isFinal()) break; ruleQueue.pop(); } }
void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules) { clearMatchedRules(); m_result.ranges.lastAuthorRule = m_result.matchedProperties.size() - 1; // Match global author rules. MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules); StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); collectMatchingRules(matchRequest, ruleRange); collectMatchingRulesForRegion(matchRequest, ruleRange); sortAndTransferMatchedRules(); }
bool ElementRuleCollector::hasAnyMatchingRules(RuleSet* ruleSet) { clearMatchedRules(); m_mode = SelectorChecker::SharingRules; // To check whether a given RuleSet has any rule matching a given element, // should not see the element's treescope. Because RuleSet has no information // about "scope". MatchRequest matchRequest(ruleSet); collectMatchingRules(matchRequest); collectMatchingShadowHostRules(matchRequest); return !m_matchedRules.isEmpty(); }
void ElementRuleCollector::matchUserRules(bool includeEmptyRules) { if (!m_ruleSets.userStyle()) return; clearMatchedRules(); m_result.ranges.lastUserRule = m_result.matchedProperties.size() - 1; MatchRequest matchRequest(m_ruleSets.userStyle(), includeEmptyRules); StyleResolver::RuleRange ruleRange = m_result.ranges.userRuleRange(); collectMatchingRules(matchRequest, ruleRange); collectMatchingRulesForRegion(matchRequest, ruleRange); sortAndTransferMatchedRules(); }
void ScopedStyleResolver::matchAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles) { if (m_authorStyle) { collector.clearMatchedRules(); collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1; // Match author rules. MatchRequest matchRequest(m_authorStyle.get(), includeEmptyRules, m_scopingNode); StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); collector.setBehaviorAtBoundary(applyAuthorStyles ? SelectorChecker::DoesNotCrossBoundary : static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::DoesNotCrossBoundary | SelectorChecker::ScopeContainsLastMatchedElement)); collector.collectMatchingRules(matchRequest, ruleRange); collector.collectMatchingRulesForRegion(matchRequest, ruleRange); collector.sortAndTransferMatchedRules(); } }
void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules) { #if ENABLE(SHADOW_DOM) if (m_element.shadowRoot()) matchHostPseudoClassRules(includeEmptyRules); #endif clearMatchedRules(); m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1; // Match global author rules. MatchRequest matchRequest(&m_authorStyle, includeEmptyRules); StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); collectMatchingRules(matchRequest, ruleRange); collectMatchingRulesForRegion(matchRequest, ruleRange); sortAndTransferMatchedRules(); }
void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope cascadeScope, CascadeOrder cascadeOrder) { const ContainerNode* scopingNode = &m_scopingNode; unsigned behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary; if (!applyAuthorStyles) behaviorAtBoundary |= SelectorChecker::ScopeContainsLastMatchedElement; if (m_scopingNode.isShadowRoot()) { scopingNode = toShadowRoot(m_scopingNode).host(); behaviorAtBoundary |= SelectorChecker::ScopeIsShadowHost; } for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) { MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), includeEmptyRules, scopingNode, applyAuthorStyles, i, m_authorStyleSheets[i]); collector.collectMatchingRules(matchRequest, collector.matchedResult().ranges.authorRuleRange(), static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder); } }
void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules) { clearMatchedRules(); m_result.ranges.lastAuthorRule = m_result.matchedProperties.size() - 1; if (!m_state.element()) return; // Match global author rules. MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules); StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); collectMatchingRules(matchRequest, ruleRange); collectMatchingRulesForRegion(matchRequest, ruleRange); #if ENABLE(SHADOW_DOM) matchShadowDistributedRules(includeEmptyRules, ruleRange); #endif sortAndTransferMatchedRules(); matchScopedAuthorRules(includeEmptyRules); }
void ElementRuleCollector::matchHostPseudoClassRules(bool includeEmptyRules) { ASSERT(m_element.shadowRoot()); auto& shadowAuthorStyle = *m_element.shadowRoot()->styleResolver().ruleSets().authorStyle(); auto& shadowHostRules = shadowAuthorStyle.hostPseudoClassRules(); if (shadowHostRules.isEmpty()) return; clearMatchedRules(); m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1; auto ruleRange = m_result.ranges.authorRuleRange(); MatchRequest matchRequest(&shadowAuthorStyle, includeEmptyRules); collectMatchingRulesForList(&shadowHostRules, matchRequest, ruleRange); // We just sort the host rules before other author rules. This matches the current vague spec language // but is not necessarily exactly what is needed. // FIXME: Match the spec when it is finalized. sortAndTransferMatchedRules(); }
void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules) { clearMatchedRules(); m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1; StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); // Match global author rules. MatchRequest matchRequest(&m_authorStyle, includeEmptyRules); collectMatchingRules(matchRequest, ruleRange); collectMatchingRulesForRegion(matchRequest, ruleRange); auto* parent = m_element.parentElement(); if (parent && parent->shadowRoot()) matchSlottedPseudoElementRules(matchRequest, ruleRange); if (m_element.shadowRoot()) matchHostPseudoClassRules(matchRequest, ruleRange); sortAndTransferMatchedRules(); }
void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope cascadeScope, CascadeOrder cascadeOrder) { if (!m_authorStyle) return; const ContainerNode* scopingNode = &m_scopingNode; unsigned behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary; if (!applyAuthorStyles) behaviorAtBoundary |= SelectorChecker::ScopeContainsLastMatchedElement; if (m_scopingNode.isShadowRoot()) { scopingNode = toShadowRoot(m_scopingNode).host(); behaviorAtBoundary |= SelectorChecker::ScopeIsShadowHost; } MatchRequest matchRequest(m_authorStyle.get(), includeEmptyRules, scopingNode, applyAuthorStyles); RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); collector.collectMatchingRules(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder); collector.collectMatchingRulesForRegion(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder); }
void ElementRuleCollector::matchScopedAuthorRules(bool includeEmptyRules) { #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) if (!m_scopeResolver) return; // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent). if (m_scopeResolver->hasScopedStyles() && m_scopeResolver->ensureStackConsistency(m_state.element())) { bool applyAuthorStyles = m_state.element()->treeScope()->applyAuthorStyles(); bool documentScope = true; unsigned scopeSize = m_scopeResolver->stackSize(); for (unsigned i = 0; i < scopeSize; ++i) { clearMatchedRules(); m_result.ranges.lastAuthorRule = m_result.matchedProperties.size() - 1; const StyleScopeResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i); documentScope = documentScope && !frame.m_scope->isInShadowTree(); if (documentScope) { if (!applyAuthorStyles) continue; } else { if (!m_scopeResolver->matchesStyleBounds(frame)) continue; } MatchRequest matchRequest(frame.m_ruleSet, includeEmptyRules, frame.m_scope); StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); collectMatchingRules(matchRequest, ruleRange); collectMatchingRulesForRegion(matchRequest, ruleRange); sortAndTransferMatchedRules(); } } matchHostRules(includeEmptyRules); #else UNUSED_PARAM(includeEmptyRules); #endif }
std::unique_ptr<RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules) { ASSERT(is<HTMLSlotElement>(m_element)); clearMatchedRules(); m_mode = SelectorChecker::Mode::CollectingRules; // Match global author rules. MatchRequest matchRequest(&m_authorStyle, includeEmptyRules); StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); collectMatchingRulesForList(&m_authorStyle.slottedPseudoElementRules(), matchRequest, ruleRange); if (m_matchedRules.isEmpty()) return { }; auto ruleDataVector = std::make_unique<RuleSet::RuleDataVector>(); ruleDataVector->reserveInitialCapacity(m_matchedRules.size()); for (auto& matchedRule : m_matchedRules) ruleDataVector->uncheckedAppend(*matchedRule.ruleData); return ruleDataVector; }
int main(int argc, char *argv[]) { lList *queuelist = NULL, *joblist = NULL; enum { MATCH_REQUEST, LOOP_JOBS_QUEUES /* SUBWHERE */ }; int scene, fulfilled, numdiddeldum; lList *erglist = NULL; lListElem *job, *queue; lCondition *where = NULL; lEnumeration *w0, *w1, *nothing, *all; lList *queuecomplexes = NULL, *attributes = NULL; lListElem *attribute, *request; const char *operator; DENTER_MAIN(TOP_LAYER, "example2"); if (argc != 3) usage(); sscanf(argv[1], "%d", &scene); sscanf(argv[2], "%d", &numdiddeldum); /* neccessary for comfortable output */ lInit(nmv); queuelist = buildQueueList(); printf("\n\nQUEUELIST\n\n"); lWriteList(queuelist); COMPLEXLIST = buildComplexList(); printf("\n\nCOMPLEXLIST\n\n"); lWriteList(COMPLEXLIST); joblist = buildJobList(numdiddeldum); printf("\n\nJOBLIST\n\n"); lWriteList(joblist); printf("\n******** BEGIN PROCESSING *********\n\n"); switch (scene) { case MATCH_REQUEST: /* find for each job in the joblist all queues that suffer the request of this job ( implemented with quick list functions ) */ for_each(job, joblist) { printf("\n-------------------------------" "-------------------------------\n"); printf("*** job %s may get started in the following queues ***\n\n", lGetString(job, J_name)); for_each(queue, queuelist) { if (matchRequest(lGetList(queue, Q_complexname), lGetList(job, J_hardrequest))) { if (!erglist) if (!(erglist = lCreateList("erglist", QueueT))) { printf("case MATCH_REQUEST: lCreateList" " failure\n"); exit(-1); } lAppendElem(erglist, lCopyElem(queue)); } } printf("\n\n**** ERGLIST ****\n\n"); if (erglist) { lWriteList(erglist); lFreeList(&erglist); erglist = NULL; } } break; case LOOP_JOBS_QUEUES: /* find for each job in the joblist all queues that suffer the request of this job ( implemented with mighty database-like functions ) */ for_each(job, joblist) { printf("\n--------------------------------------------------------------\n"); printf("*** job %s may get started in the following queues ***\n\n", lGetString(job, J_name)); for_each(queue, queuelist) { /* build a list of the complexes of the queue therefore: build a subset of the complex list with the queues complex name list as a selector join the complex name list of the queue ( join field: N_complexname) with the global complex list ( join field: C_name ) select nothing from the queue's complex name list (w0) and only the attributes of the global complex list (w1) every valid combination is needed, so the where parameter is NULL for both lists */ w0 = lWhat("%T(NONE)", ComplexNameT); /* NIX */ w1 = lWhat("%T(%I)", ComplexT, C_attribute); queuecomplexes = lJoin("queuecomplexes", N_complexname, lGetList(queue, Q_complexname), NULL, w0, C_name, COMPLEXLIST, NULL, w1); lFreeWhat(&w0); lFreeWhat(&w1); /* try to find a hard request of this job that is not fulfilled by the queue's complexes */ fulfilled = 1; for_each(request, lGetList(job, J_hardrequest)) { /* build a flat complex attribute list with only these attributes of the request this produces a attribute list of all complexes */ nothing = lWhat("%T(NONE)", lGetListDescr(queuecomplexes)); all = lWhat("%T(ALL)", ComplexAttributeT); where = lWhere("%T( %I == %s )", ComplexAttributeT, A_name, lGetString(request, R_name)); attributes = lJoinSublist("attributelist", C_attribute, queuecomplexes, NULL, nothing, ComplexAttributeT, where, all); lFreeWhere(&where); lFreeWhat(¬hing); lFreeWhat(&all); /* if we get an empty list then the queue has no complex fulfilling the request of this job */ /* right now the lJoinSublist function returns an empty list (no elements) if there was no sublist */ if (lGetNumberOfElem(attributes) == 0) { fulfilled = 0; break; /* leave request loop */ } /* if there are attributes the values of at least one complex of the queue must fulfill the request */ for_each(attribute, attributes) { operator = lGetString(request, R_operator); if (strcmp(operator, "==") == 0) { fulfilled = (!strcmp( lGetString(attribute, A_value), lGetString(request, R_value))); } else if (strcmp(operator, "!=") == 0) { fulfilled = (strcmp( lGetString(attribute, A_value), lGetString(request, R_value))); } /* else if .. ( for all operators ) */ if (fulfilled) break; /* leave attribute loop */ }