WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
WIP
bug-101180-20121108183424.patch (text/plain), 46.02 KB, created by
Shinya Kawanaka
on 2012-11-08 01:36:15 PST
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Shinya Kawanaka
Created:
2012-11-08 01:36:15 PST
Size:
46.02 KB
patch
obsolete
>Subversion Revision: 133839 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 78acb0cad9f6fbf19472d27e59a6b09b294d6ea6..1495ddc0e1f1d216c4eceb73a3106414cea4d932 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,110 @@ >+2012-11-08 Shinya Kawanaka <shinyak@chromium.org> >+ >+ [Shadow] ElementShadow should have RuleFeatureSet for select attribute selectors. >+ https://bugs.webkit.org/show_bug.cgi?id=101180 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This is a preparation patch for Bug 100451. >+ >+ We preserve RuleFeatureSet collected from select attributes in ShadowDOM. >+ When an element attribute is changed, we might have to invalidate content distribution, >+ however it's high cost operation. So we would like to check RuleFeatureSet used in >+ select attributes to determine we really need to invalidate distribution. >+ >+ Like StyleResolver, ElementShadow has several rule features. When nested ShadowDOM is used, >+ first we collect features in nested ShadowDOM, and merge it to the parent ShadowDOM. >+ For the performance reason, we have a flag to check whether we need to collect features again. >+ >+ Test: fast/dom/shadow/shadow-select-attribute-featureset.html >+ >+ * WebCore.exp.in: >+ * css/RuleFeature.cpp: >+ (WebCore::RuleFeatureSet::collectFeaturesFromSelector): Moved from RuleSet.cpp, since we would like to reuse this. >+ (WebCore): >+ * css/RuleFeature.h: >+ (WebCore): >+ (RuleFeatureSet): >+ * css/RuleSet.cpp: >+ (WebCore::collectFeaturesFromRuleData): >+ * dom/ElementShadow.cpp: >+ (WebCore::ElementShadow::ElementShadow): >+ (WebCore::ElementShadow::setShouldCollectSelectFeatureSet): Enable a flag to collect feature set of descendant >+ nodes (and their ShadowDOM). >+ (WebCore): >+ (WebCore::ElementShadow::ensureSelectFeatureSetCollected): >+ (WebCore::ElementShadow::collectSelectFeatureSetFrom): Collect RuleFeatureSet from all descendant Nodes and their >+ ShadowDOM. We need to collect id, class, and attribute names. >+ (WebCore::ElementShadow::hasSelectorForId): >+ (WebCore::ElementShadow::hasSelectorForClass): >+ (WebCore::ElementShadow::hasSelectorForAttribute): >+ * dom/ElementShadow.h: >+ (WebCore::ElementShadow::shouldCollectSelectFeatureSet): >+ (ElementShadow): >+ * html/shadow/HTMLContentElement.cpp: >+ (WebCore::HTMLContentElement::parseAttribute): When select attribute is changed, enable a flag to recollect features. >+ (WebCore::HTMLContentElement::insertedInto): We have to recollect features when HTMLContentElement is moved. >+ (WebCore::HTMLContentElement::removedFrom): ditto. >+ * html/shadow/HTMLContentElement.h: >+ (WebCore::toHTMLContentElement): >+ (WebCore): >+ * testing/Internals.cpp: >+ (WebCore::Internals::hasSelectorForIdInShadow): >+ (WebCore): >+ (WebCore::Internals::hasSelectorForClassInShadow): >+ (WebCore::Internals::hasSelectorForAttributeInShadow): >+ * testing/Internals.h: >+ (Internals): >+ * testing/Internals.idl: >+ >+2012-11-07 Shinya Kawanaka <shinyak@chromium.org> >+ >+ HTMLContentElement should preserve parsed CSSSelectorList >+ https://bugs.webkit.org/show_bug.cgi?id=101543 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ We would like to preserve CSSSelectorList for select attribute of HTMLContentElement. >+ >+ Before, we parsed and validated select attribute every time distribution happens. If we preserve the parsed >+ CSSSelectorList, we can reduce distribution time. >+ >+ This is also a prepration patch for Bug 101180. It also needs the parsed CSSSelectorList. We don't want to >+ parse and validate it again. >+ >+ No new tests, covered by exising tests. >+ >+ * html/shadow/ContentSelectorQuery.cpp: >+ (WebCore::ContentSelectorQuery::ContentSelectorQuery): We don't parse select attribute here anymore. >+ if it's already parsed. >+ (WebCore::ContentSelectorQuery::matches): >+ * html/shadow/ContentSelectorQuery.h: >+ (ContentSelectorQuery): >+ * html/shadow/HTMLContentElement.cpp: >+ (WebCore::HTMLContentElement::HTMLContentElement): >+ (WebCore::HTMLContentElement::isSelectValid): >+ (WebCore::HTMLContentElement::ensureSelectParsed): If we don't have parsed the current select attribute, >+ we parse and validate it. >+ (WebCore::HTMLContentElement::parseAttribute): When select attribute is changed, we have to have a flag enabled >+ to parse select attrite again. >+ (WebCore::validateSubSelector): Moved from ContentSelectorQuery. >+ (WebCore): >+ (WebCore::validateSelector): Moved from ContentSelectorQuery. >+ (WebCore::HTMLContentElement::validateSelect): >+ * html/shadow/HTMLContentElement.h: >+ (HTMLContentElement): >+ (WebCore::HTMLContentElement::setSelect): >+ (WebCore): >+ (WebCore::HTMLContentElement::selectorList): >+ * html/shadow/HTMLShadowElement.cpp: >+ (WebCore::HTMLShadowElement::emptySelectorList): >+ (WebCore): >+ * html/shadow/HTMLShadowElement.h: >+ (HTMLShadowElement): >+ (WebCore::HTMLShadowElement::selectorList): >+ * html/shadow/InsertionPoint.h: >+ (InsertionPoint): >+ > 2012-11-07 Adam Barth <abarth@webkit.org> > > [V8] IntrusiveDOMWrapperMap should be usable for more than just Nodes >diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in >index 4b2efc59523415397e47bc0ffa494b313fcdbb7c..022aebfa008e304ca4875db56996f967d34a2eff 100644 >--- a/Source/WebCore/WebCore.exp.in >+++ b/Source/WebCore/WebCore.exp.in >@@ -215,6 +215,7 @@ __ZN7WebCore13AXObjectCache42gAccessibilityEnhancedUserInterfaceEnabledE > __ZN7WebCore13CharacterData7setDataERKN3WTF6StringERi > __ZN7WebCore13ContainerNode11appendChildEN3WTF10PassRefPtrINS_4NodeEEERib > __ZN7WebCore13ContainerNode11removeChildEPNS_4NodeERi >+__ZN7WebCore13ElementShadow31ensureSelectFeatureSetCollectedEv > __ZN7WebCore13HTTPHeaderMapC1Ev > __ZN7WebCore13HTTPHeaderMapD1Ev > __ZN7WebCore13HitTestResultC1ERKS0_ >diff --git a/Source/WebCore/css/RuleFeature.cpp b/Source/WebCore/css/RuleFeature.cpp >index b1f929687927fd7709ff022f55d0eb3d97c2d7dc..1b11c8faed43841b87c1f6196240a5b23e744a99 100644 >--- a/Source/WebCore/css/RuleFeature.cpp >+++ b/Source/WebCore/css/RuleFeature.cpp >@@ -29,6 +29,7 @@ > #include "config.h" > #include "RuleFeature.h" > >+#include "CSSSelector.h" > #include "WebCoreMemoryInstrumentation.h" > #include <wtf/MemoryInstrumentationHashMap.h> > #include <wtf/MemoryInstrumentationHashSet.h> >@@ -36,6 +37,27 @@ > > namespace WebCore { > >+void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector* selector) >+{ >+ if (selector->m_match == CSSSelector::Id) >+ idsInRules.add(selector->value().impl()); >+ else if (selector->m_match == CSSSelector::Class) >+ classesInRules.add(selector->value().impl()); >+ else if (selector->isAttributeSelector()) >+ attrsInRules.add(selector->attribute().localName().impl()); >+ switch (selector->pseudoType()) { >+ case CSSSelector::PseudoFirstLine: >+ usesFirstLineRules = true; >+ break; >+ case CSSSelector::PseudoBefore: >+ case CSSSelector::PseudoAfter: >+ usesBeforeAfterRules = true; >+ break; >+ default: >+ break; >+ } >+} >+ > void RuleFeatureSet::add(const RuleFeatureSet& other) > { > HashSet<AtomicStringImpl*>::const_iterator end = other.idsInRules.end(); >diff --git a/Source/WebCore/css/RuleFeature.h b/Source/WebCore/css/RuleFeature.h >index ce6d04e664e42f4fabfbf25f38ddb2b4e2bba3b7..0ffc6e5ee2172a67b7e7ed9c09f112face78143e 100644 >--- a/Source/WebCore/css/RuleFeature.h >+++ b/Source/WebCore/css/RuleFeature.h >@@ -30,6 +30,7 @@ > namespace WebCore { > > class StyleRule; >+class CSSSelector; > > struct RuleFeature { > RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin) >@@ -51,7 +52,11 @@ struct RuleFeatureSet { > > void add(const RuleFeatureSet&); > void clear(); >+ >+ void collectFeaturesFromSelector(const CSSSelector*); >+ > void reportMemoryUsage(MemoryObjectInfo*) const; >+ > HashSet<AtomicStringImpl*> idsInRules; > HashSet<AtomicStringImpl*> classesInRules; > HashSet<AtomicStringImpl*> attrsInRules; >diff --git a/Source/WebCore/css/RuleSet.cpp b/Source/WebCore/css/RuleSet.cpp >index e92d1768b298d7ae896c07be2887aa741c5a6d38..a5367ee82dbd5931e94b6849d43e7b1efd9c9186 100644 >--- a/Source/WebCore/css/RuleSet.cpp >+++ b/Source/WebCore/css/RuleSet.cpp >@@ -157,38 +157,17 @@ void RuleSet::RuleSetSelectorPair::reportMemoryUsage(MemoryObjectInfo* memoryObj > info.addMember(ruleSet); > } > >-static inline void collectFeaturesFromSelector(RuleFeatureSet& features, const CSSSelector* selector) >-{ >- if (selector->m_match == CSSSelector::Id) >- features.idsInRules.add(selector->value().impl()); >- else if (selector->m_match == CSSSelector::Class) >- features.classesInRules.add(selector->value().impl()); >- else if (selector->isAttributeSelector()) >- features.attrsInRules.add(selector->attribute().localName().impl()); >- switch (selector->pseudoType()) { >- case CSSSelector::PseudoFirstLine: >- features.usesFirstLineRules = true; >- break; >- case CSSSelector::PseudoBefore: >- case CSSSelector::PseudoAfter: >- features.usesBeforeAfterRules = true; >- break; >- default: >- break; >- } >-} >- > static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData& ruleData) > { > bool foundSiblingSelector = false; > for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { >- collectFeaturesFromSelector(features, selector); >+ features.collectFeaturesFromSelector(selector); > > if (CSSSelectorList* selectorList = selector->selectorList()) { > for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { > if (!foundSiblingSelector && selector->isSiblingSelector()) > foundSiblingSelector = true; >- collectFeaturesFromSelector(features, subSelector); >+ features.collectFeaturesFromSelector(subSelector); > } > } else if (!foundSiblingSelector && selector->isSiblingSelector()) > foundSiblingSelector = true; >diff --git a/Source/WebCore/dom/ElementShadow.cpp b/Source/WebCore/dom/ElementShadow.cpp >index 6f87f1644afb94bfbfe5eb78ceb31fee45162f1b..73f6c63043bbeeed5b128fd8938a4029a8854aa8 100644 >--- a/Source/WebCore/dom/ElementShadow.cpp >+++ b/Source/WebCore/dom/ElementShadow.cpp >@@ -27,9 +27,12 @@ > #include "config.h" > #include "ElementShadow.h" > >+#include "CSSParser.h" >+#include "CSSSelectorList.h" > #include "ContainerNodeAlgorithms.h" > #include "Document.h" > #include "Element.h" >+#include "HTMLContentElement.h" > #include "HTMLShadowElement.h" > #include "InspectorInstrumentation.h" > #include "ShadowRoot.h" >@@ -39,6 +42,7 @@ > namespace WebCore { > > ElementShadow::ElementShadow() >+ : m_shouldCollectSelectFeatureSet(false) > { > } > >@@ -203,6 +207,73 @@ void ElementShadow::invalidateDistribution(Element* host) > m_distributor.finishInivalidation(); > } > >+void ElementShadow::setShouldCollectSelectFeatureSet() >+{ >+ if (shouldCollectSelectFeatureSet()) >+ return; >+ >+ m_shouldCollectSelectFeatureSet = true; >+ >+ if (ShadowRoot* parentShadowRoot = host()->shadowRoot()) { >+ if (ElementShadow* parentElementShadow = parentShadowRoot->owner()) >+ parentElementShadow->setShouldCollectSelectFeatureSet(); >+ } >+} >+ >+void ElementShadow::ensureSelectFeatureSetCollected() >+{ >+ if (!m_shouldCollectSelectFeatureSet) >+ return; >+ >+ m_selectFeatures.clear(); >+ for (ShadowRoot* root = oldestShadowRoot(); root; root = root->youngerShadowRoot()) >+ collectSelectFeatureSetFrom(root); >+ m_shouldCollectSelectFeatureSet = false; >+} >+ >+void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot* root) >+{ >+ if (!root->hasContentElement()) >+ return; >+ >+ if (root->hasElementShadow()) { >+ for (Node* node = root->firstChild(); node; node = node->traverseNextNode()) { >+ if (ElementShadow* elementShadow = node->isElementNode() ? toElement(node)->shadow() : 0) { >+ elementShadow->ensureSelectFeatureSetCollected(); >+ m_selectFeatures.add(elementShadow->m_selectFeatures); >+ } >+ } >+ } >+ >+ if (root->hasContentElement()) { >+ for (Node* node = root->firstChild(); node; node = node->traverseNextNode()) { >+ if (isHTMLContentElement(node)) { >+ const CSSSelectorList& list = toHTMLContentElement(node)->selectorList(); >+ for (CSSSelector* selector = list.first(); selector; selector = list.next(selector)) >+ m_selectFeatures.collectFeaturesFromSelector(selector); >+ } >+ } >+ } >+} >+ >+bool ElementShadow::hasSelectorForId(const AtomicString& idValue) const >+{ >+ ASSERT(!idValue.isEmpty()); >+ return m_selectFeatures.idsInRules.contains(idValue.impl()); >+} >+ >+bool ElementShadow::hasSelectorForClass(const AtomicString& classValue) const >+{ >+ ASSERT(!classValue.isEmpty()); >+ return m_selectFeatures.classesInRules.contains(classValue.impl()); >+} >+ >+bool ElementShadow::hasSelectorForAttribute(const AtomicString& attributeName) const >+{ >+ ASSERT(!attributeName.isEmpty()); >+ return m_selectFeatures.attrsInRules.contains(attributeName.impl()); >+} >+ > void ElementShadow::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const > { > MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); >diff --git a/Source/WebCore/dom/ElementShadow.h b/Source/WebCore/dom/ElementShadow.h >index 2f6f56c74f6692cee34486a9a7f9b021c70e9285..f8c30c2cf5ea6c0ed247b9ff886fdc34b9fe7504 100644 >--- a/Source/WebCore/dom/ElementShadow.h >+++ b/Source/WebCore/dom/ElementShadow.h >@@ -29,6 +29,7 @@ > > #include "ContentDistributor.h" > #include "ExceptionCode.h" >+#include "RuleFeature.h" > #include "ShadowRoot.h" > #include <wtf/DoublyLinkedList.h> > #include <wtf/Noncopyable.h> >@@ -69,13 +70,25 @@ public: > ContentDistributor& distributor(); > const ContentDistributor& distributor() const; > >+ bool shouldCollectSelectFeatureSet() const { return m_shouldCollectSelectFeatureSet; } >+ void setShouldCollectSelectFeatureSet(); >+ void ensureSelectFeatureSetCollected(); >+ >+ bool hasSelectorForId(const AtomicString&) const; >+ bool hasSelectorForClass(const AtomicString&) const; >+ bool hasSelectorForAttribute(const AtomicString&) const; >+ > void reportMemoryUsage(MemoryObjectInfo*) const; > > private: > void invalidateDistribution(Element* host); > >+ void collectSelectFeatureSetFrom(ShadowRoot*); >+ > DoublyLinkedList<ShadowRoot> m_shadowRoots; > ContentDistributor m_distributor; >+ RuleFeatureSet m_selectFeatures; >+ bool m_shouldCollectSelectFeatureSet : 1; > }; > > inline ShadowRoot* ElementShadow::youngestShadowRoot() const >diff --git a/Source/WebCore/html/shadow/ContentSelectorQuery.cpp b/Source/WebCore/html/shadow/ContentSelectorQuery.cpp >index 0a6ec32eee5fd00b8e95b433eddf949736b14eea..dbe5a8e9562f68fa6a07f3c33970fa85f3b86bb4 100644 >--- a/Source/WebCore/html/shadow/ContentSelectorQuery.cpp >+++ b/Source/WebCore/html/shadow/ContentSelectorQuery.cpp >@@ -27,7 +27,6 @@ > #include "config.h" > #include "ContentSelectorQuery.h" > >-#include "CSSParser.h" > #include "CSSSelectorList.h" > #include "InsertionPoint.h" > #include "SelectorChecker.h" >@@ -65,26 +64,12 @@ bool ContentSelectorDataList::matches(const ContentSelectorChecker& selectorChec > return false; > } > >-ContentSelectorQuery::ContentSelectorQuery(const InsertionPoint* insertionPoint) >+ContentSelectorQuery::ContentSelectorQuery(InsertionPoint* insertionPoint) > : m_insertionPoint(insertionPoint) > , m_selectorChecker(insertionPoint->document(), !insertionPoint->document()->inQuirksMode()) > { >- if (insertionPoint->select().isNull() || insertionPoint->select().isEmpty()) { >- m_isValidSelector = true; >- return; >- } >- >- CSSParser parser(insertionPoint->document()); >- parser.parseSelector(insertionPoint->select(), m_selectorList); >- >- m_isValidSelector = ContentSelectorQuery::validateSelectorList(); >- if (m_isValidSelector) >- m_selectors.initialize(m_selectorList); >-} >- >-bool ContentSelectorQuery::isValidSelector() const >-{ >- return m_isValidSelector; >+ if (insertionPoint->isSelectValid()) >+ m_selectors.initialize(insertionPoint->selectorList()); > } > > bool ContentSelectorQuery::matches(const Vector<RefPtr<Node> >& siblings, int nth) const >@@ -95,7 +80,7 @@ bool ContentSelectorQuery::matches(const Vector<RefPtr<Node> >& siblings, int nt > if (m_insertionPoint->select().isNull() || m_insertionPoint->select().isEmpty()) > return true; > >- if (!m_isValidSelector) >+ if (!m_insertionPoint->isSelectValid()) > return false; > > if (!node->isElementNode()) >@@ -104,85 +89,4 @@ bool ContentSelectorQuery::matches(const Vector<RefPtr<Node> >& siblings, int nt > return m_selectors.matches(m_selectorChecker, siblings, nth); > } > >-static bool validateSubSelector(CSSSelector* selector) >-{ >- switch (selector->m_match) { >- case CSSSelector::None: >- case CSSSelector::Id: >- case CSSSelector::Class: >- case CSSSelector::Exact: >- case CSSSelector::Set: >- case CSSSelector::List: >- case CSSSelector::Hyphen: >- case CSSSelector::Contain: >- case CSSSelector::Begin: >- case CSSSelector::End: >- return true; >- case CSSSelector::PseudoElement: >- return false; >- case CSSSelector::PagePseudoClass: >- case CSSSelector::PseudoClass: >- break; >- } >- >- switch (selector->pseudoType()) { >- case CSSSelector::PseudoEmpty: >- case CSSSelector::PseudoLink: >- case CSSSelector::PseudoVisited: >- case CSSSelector::PseudoTarget: >- case CSSSelector::PseudoEnabled: >- case CSSSelector::PseudoDisabled: >- case CSSSelector::PseudoChecked: >- case CSSSelector::PseudoIndeterminate: >- case CSSSelector::PseudoNthChild: >- case CSSSelector::PseudoNthLastChild: >- case CSSSelector::PseudoNthOfType: >- case CSSSelector::PseudoNthLastOfType: >- case CSSSelector::PseudoFirstChild: >- case CSSSelector::PseudoLastChild: >- case CSSSelector::PseudoFirstOfType: >- case CSSSelector::PseudoLastOfType: >- case CSSSelector::PseudoOnlyOfType: >- return true; >- default: >- return false; >- } >-} >- >-static bool validateSelector(CSSSelector* selector) >-{ >- ASSERT(selector); >- >- if (!validateSubSelector(selector)) >- return false; >- >- CSSSelector* prevSubSelector = selector; >- CSSSelector* subSelector = selector->tagHistory(); >- >- while (subSelector) { >- if (prevSubSelector->relation() != CSSSelector::SubSelector) >- return false; >- if (!validateSubSelector(subSelector)) >- return false; >- >- prevSubSelector = subSelector; >- subSelector = subSelector->tagHistory(); >- } >- >- return true; >-} >- >-bool ContentSelectorQuery::validateSelectorList() >-{ >- if (!m_selectorList.first()) >- return false; >- >- for (CSSSelector* selector = m_selectorList.first(); selector; selector = m_selectorList.next(selector)) { >- if (!validateSelector(selector)) >- return false; >- } >- >- return true; >-} >- > } >diff --git a/Source/WebCore/html/shadow/ContentSelectorQuery.h b/Source/WebCore/html/shadow/ContentSelectorQuery.h >index 2c710a5852e92d76882c7c20750bfd26da2aa03b..78a082454c9d12f2b0f3c5504a8b90abe9e1ebe6 100644 >--- a/Source/WebCore/html/shadow/ContentSelectorQuery.h >+++ b/Source/WebCore/html/shadow/ContentSelectorQuery.h >@@ -64,18 +64,14 @@ private: > class ContentSelectorQuery { > WTF_MAKE_NONCOPYABLE(ContentSelectorQuery); > public: >- explicit ContentSelectorQuery(const InsertionPoint*); >+ explicit ContentSelectorQuery(InsertionPoint*); > >- bool isValidSelector() const; > bool matches(const Vector<RefPtr<Node> >& siblings, int nthNode) const; > private: >- bool validateSelectorList(); > >- const InsertionPoint* m_insertionPoint; >+ InsertionPoint* m_insertionPoint; > ContentSelectorDataList m_selectors; >- CSSSelectorList m_selectorList; > ContentSelectorChecker m_selectorChecker; >- bool m_isValidSelector; > }; > > } >diff --git a/Source/WebCore/html/shadow/HTMLContentElement.cpp b/Source/WebCore/html/shadow/HTMLContentElement.cpp >index 5040e9eb8d6062756eeaf9be44374d66a5e125e0..8ec04416160fb597cb974c05cd4f533656a68ded 100644 >--- a/Source/WebCore/html/shadow/HTMLContentElement.cpp >+++ b/Source/WebCore/html/shadow/HTMLContentElement.cpp >@@ -27,6 +27,7 @@ > #include "config.h" > #include "HTMLContentElement.h" > >+#include "CSSParser.h" > #include "ContentDistributor.h" > #include "ContentSelectorQuery.h" > #include "ContextFeatures.h" >@@ -65,6 +66,8 @@ PassRefPtr<HTMLContentElement> HTMLContentElement::create(const QualifiedName& t > HTMLContentElement::HTMLContentElement(const QualifiedName& name, Document* document) > : InsertionPoint(name, document) > , m_registeredWithShadowRoot(false) >+ , m_shouldParseSelectorList(false) >+ , m_isValidSelector(true) > { > } > >@@ -77,22 +80,33 @@ const AtomicString& HTMLContentElement::select() const > return getAttribute(selectAttr); > } > >-bool HTMLContentElement::isSelectValid() const >+bool HTMLContentElement::isSelectValid() > { >- ContentSelectorQuery query(this); >- return query.isValidSelector(); >+ ensureSelectParsed(); >+ return m_isValidSelector; > } > >-void HTMLContentElement::setSelect(const AtomicString& selectValue) >+inline void HTMLContentElement::ensureSelectParsed() > { >- setAttribute(selectAttr, selectValue); >+ if (!m_shouldParseSelectorList) >+ return; >+ >+ CSSParser parser(document()); >+ parser.parseSelector(select(), m_selectorList); >+ m_shouldParseSelectorList = false; >+ m_isValidSelector = validateSelect(); >+ if (!m_isValidSelector) >+ m_selectorList = CSSSelectorList(); > } > > void HTMLContentElement::parseAttribute(const Attribute& attribute) > { > if (attribute.name() == selectAttr) { >- if (ShadowRoot* root = shadowRoot()) >+ if (ShadowRoot* root = shadowRoot()) { >+ root->owner()->setShouldCollectSelectFeatureSet(); > root->owner()->invalidateDistribution(); >+ } >+ m_shouldParseSelectorList = true; > } else > InsertionPoint::parseAttribute(attribute); > } >@@ -102,7 +116,9 @@ Node::InsertionNotificationRequest HTMLContentElement::insertedInto(ContainerNod > InsertionPoint::insertedInto(insertionPoint); > > if (insertionPoint->inDocument() && isActive()) { >- shadowRoot()->registerContentElement(); >+ ShadowRoot* root = shadowRoot(); >+ root->registerContentElement(); >+ root->owner()->setShouldCollectSelectFeatureSet(); > m_registeredWithShadowRoot = true; > } > >@@ -118,8 +134,98 @@ void HTMLContentElement::removedFrom(ContainerNode* insertionPoint) > if (root) > root->unregisterContentElement(); > m_registeredWithShadowRoot = false; >+ >+ if (ElementShadow* elementShadow = root ? root->owner() : 0) >+ elementShadow->setShouldCollectSelectFeatureSet(); > } > InsertionPoint::removedFrom(insertionPoint); > } > >+static bool validateSubSelector(CSSSelector* selector) >+{ >+ switch (selector->m_match) { >+ case CSSSelector::None: >+ case CSSSelector::Id: >+ case CSSSelector::Class: >+ case CSSSelector::Exact: >+ case CSSSelector::Set: >+ case CSSSelector::List: >+ case CSSSelector::Hyphen: >+ case CSSSelector::Contain: >+ case CSSSelector::Begin: >+ case CSSSelector::End: >+ return true; >+ case CSSSelector::PseudoElement: >+ return false; >+ case CSSSelector::PagePseudoClass: >+ case CSSSelector::PseudoClass: >+ break; >+ } >+ >+ switch (selector->pseudoType()) { >+ case CSSSelector::PseudoEmpty: >+ case CSSSelector::PseudoLink: >+ case CSSSelector::PseudoVisited: >+ case CSSSelector::PseudoTarget: >+ case CSSSelector::PseudoEnabled: >+ case CSSSelector::PseudoDisabled: >+ case CSSSelector::PseudoChecked: >+ case CSSSelector::PseudoIndeterminate: >+ case CSSSelector::PseudoNthChild: >+ case CSSSelector::PseudoNthLastChild: >+ case CSSSelector::PseudoNthOfType: >+ case CSSSelector::PseudoNthLastOfType: >+ case CSSSelector::PseudoFirstChild: >+ case CSSSelector::PseudoLastChild: >+ case CSSSelector::PseudoFirstOfType: >+ case CSSSelector::PseudoLastOfType: >+ case CSSSelector::PseudoOnlyOfType: >+ return true; >+ default: >+ return false; >+ } >+} >+ >+static bool validateSelector(CSSSelector* selector) >+{ >+ ASSERT(selector); >+ >+ if (!validateSubSelector(selector)) >+ return false; >+ >+ CSSSelector* prevSubSelector = selector; >+ CSSSelector* subSelector = selector->tagHistory(); >+ >+ while (subSelector) { >+ if (prevSubSelector->relation() != CSSSelector::SubSelector) >+ return false; >+ if (!validateSubSelector(subSelector)) >+ return false; >+ >+ prevSubSelector = subSelector; >+ subSelector = subSelector->tagHistory(); >+ } >+ >+ return true; >+} >+ >+bool HTMLContentElement::validateSelect() const >+{ >+ ASSERT(!m_shouldParseSelectorList); >+ >+ if (select().isNull() || select().isEmpty()) >+ return true; >+ >+ if (!m_selectorList.first()) >+ return false; >+ >+ for (CSSSelector* selector = m_selectorList.first(); selector; selector = m_selectorList.next(selector)) { >+ if (!validateSelector(selector)) >+ return false; >+ } >+ >+ return true; >+} >+ >+ > } >diff --git a/Source/WebCore/html/shadow/HTMLContentElement.h b/Source/WebCore/html/shadow/HTMLContentElement.h >index 2a3a32cea55929e87ce71bac73b7864c790f0ff6..ed0b0888432cd3f36e9117fa919929816ea149d4 100644 >--- a/Source/WebCore/html/shadow/HTMLContentElement.h >+++ b/Source/WebCore/html/shadow/HTMLContentElement.h >@@ -31,6 +31,7 @@ > #ifndef HTMLContentElement_h > #define HTMLContentElement_h > >+#include "CSSSelectorList.h" > #include "InsertionPoint.h" > #include <wtf/Forward.h> > >@@ -44,9 +45,10 @@ public: > > virtual ~HTMLContentElement(); > >- const AtomicString& select() const; > void setSelect(const AtomicString&); >- virtual bool isSelectValid() const; >+ virtual const AtomicString& select() const; >+ virtual bool isSelectValid(); >+ virtual const CSSSelectorList& selectorList(); > > protected: > HTMLContentElement(const QualifiedName&, Document*); >@@ -56,16 +58,40 @@ protected: > > private: > virtual void parseAttribute(const Attribute&) OVERRIDE; >+ void ensureSelectParsed(); >+ bool validateSelect() const; > > bool m_registeredWithShadowRoot; >+ >+ bool m_shouldParseSelectorList; >+ bool m_isValidSelector; >+ CSSSelectorList m_selectorList; > }; > >+inline void HTMLContentElement::setSelect(const AtomicString& selectValue) >+{ >+ setAttribute(HTMLNames::selectAttr, selectValue); >+ m_shouldParseSelectorList = true; >+} >+ >+inline const CSSSelectorList& HTMLContentElement::selectorList() >+{ >+ ensureSelectParsed(); >+ return m_selectorList; >+} >+ > inline bool isHTMLContentElement(const Node* node) > { > ASSERT(node); > return node->hasTagName(HTMLContentElement::contentTagName(node->document())); > } > >+inline HTMLContentElement* toHTMLContentElement(Node* node) >+{ >+ ASSERT(!node || isHTMLContentElement(node)); >+ return static_cast<HTMLContentElement*>(node); >+} >+ > } > > #endif >diff --git a/Source/WebCore/html/shadow/HTMLShadowElement.cpp b/Source/WebCore/html/shadow/HTMLShadowElement.cpp >index 7d7e41529fbdf16f130408ee232f198b82835264..da18ba8eae5e4b24fe5afc664979e6b2d5a5964d 100644 >--- a/Source/WebCore/html/shadow/HTMLShadowElement.cpp >+++ b/Source/WebCore/html/shadow/HTMLShadowElement.cpp >@@ -87,4 +87,10 @@ void HTMLShadowElement::removedFrom(ContainerNode* insertionPoint) > InsertionPoint::removedFrom(insertionPoint); > } > >+const CSSSelectorList& HTMLShadowElement::emptySelectorList() >+{ >+ DEFINE_STATIC_LOCAL(CSSSelectorList, selectorList, (CSSSelectorList())); >+ return selectorList; >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/html/shadow/HTMLShadowElement.h b/Source/WebCore/html/shadow/HTMLShadowElement.h >index bac2b92b57961b23dfcc2e32e1f55b2d57e32645..87059896f77d2023c0f2af1c68843733df1713fd 100644 >--- a/Source/WebCore/html/shadow/HTMLShadowElement.h >+++ b/Source/WebCore/html/shadow/HTMLShadowElement.h >@@ -42,8 +42,9 @@ public: > > virtual ~HTMLShadowElement(); > >- const AtomicString& select() const; >- bool isSelectValid() const OVERRIDE { return true; } >+ virtual const AtomicString& select() const; >+ virtual bool isSelectValid() OVERRIDE { return true; } >+ virtual const CSSSelectorList& selectorList() { return emptySelectorList(); } > > protected: > virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; >@@ -52,6 +53,8 @@ protected: > private: > HTMLShadowElement(const QualifiedName&, Document*); > >+ static const CSSSelectorList& emptySelectorList(); >+ > bool m_registeredWithShadowRoot; > }; > >diff --git a/Source/WebCore/html/shadow/InsertionPoint.h b/Source/WebCore/html/shadow/InsertionPoint.h >index 243a08c18a3461030395d9a5ba7d20559b6711a9..23dad8dca7081231821f97d8bf304d77333276f7 100644 >--- a/Source/WebCore/html/shadow/InsertionPoint.h >+++ b/Source/WebCore/html/shadow/InsertionPoint.h >@@ -31,6 +31,7 @@ > #ifndef InsertionPoint_h > #define InsertionPoint_h > >+#include "CSSSelectorList.h" > #include "ContentDistributor.h" > #include "ElementShadow.h" > #include "HTMLElement.h" >@@ -53,7 +54,8 @@ public: > PassRefPtr<NodeList> getDistributedNodes() const; > > virtual const AtomicString& select() const = 0; >- virtual bool isSelectValid() const = 0; >+ virtual bool isSelectValid() = 0; >+ virtual const CSSSelectorList& selectorList() = 0; > > bool resetStyleInheritance() const; > void setResetStyleInheritance(bool); >diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp >index e4d308410a063368fcec60c2dec392bf7e2e9da7..7be18d9be5b755d4caf79aa8e74f8485288066bd 100644 >--- a/Source/WebCore/testing/Internals.cpp >+++ b/Source/WebCore/testing/Internals.cpp >@@ -306,6 +306,39 @@ Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec) > return parentTreeScope ? parentTreeScope->rootNode() : 0; > } > >+bool Internals::hasSelectorForIdInShadow(Element* host, const String& idValue, ExceptionCode& ec) >+{ >+ if (!host || !host->shadow()) { >+ ec = INVALID_ACCESS_ERR; >+ return 0; >+ } >+ >+ host->shadow()->ensureSelectFeatureSetCollected(); >+ return host->shadow()->hasSelectorForId(idValue); >+} >+ >+bool Internals::hasSelectorForClassInShadow(Element* host, const String& className, ExceptionCode& ec) >+{ >+ if (!host || !host->shadow()) { >+ ec = INVALID_ACCESS_ERR; >+ return 0; >+ } >+ >+ host->shadow()->ensureSelectFeatureSetCollected(); >+ return host->shadow()->hasSelectorForClass(className); >+} >+ >+bool Internals::hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionCode& ec) >+{ >+ if (!host || !host->shadow()) { >+ ec = INVALID_ACCESS_ERR; >+ return 0; >+ } >+ >+ host->shadow()->ensureSelectFeatureSetCollected(); >+ return host->shadow()->hasSelectorForAttribute(attributeName); >+} >+ > bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionCode& ec) const > { > if (root && root->isShadowRoot()) >diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h >index 21117397c811c858f3b1f49fc57d16ac25a71121..544d31e889450e551d7c8bd29136c7c712a04ee6 100644 >--- a/Source/WebCore/testing/Internals.h >+++ b/Source/WebCore/testing/Internals.h >@@ -96,6 +96,9 @@ public: > bool isValidContentSelect(Element* insertionPoint, ExceptionCode&); > Node* treeScopeRootNode(Node*, ExceptionCode&); > Node* parentTreeScope(Node*, ExceptionCode&); >+ bool hasSelectorForIdInShadow(Element* host, const String& idValue, ExceptionCode&); >+ bool hasSelectorForClassInShadow(Element* host, const String& className, ExceptionCode&); >+ bool hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionCode&); > > bool attached(Node*, ExceptionCode&); > >diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl >index 7a5ab7b90edb64b650dc3437b43a1d69971b01ad..304e64c8eecd00f5323edc62a0aef8ef8317bed4 100644 >--- a/Source/WebCore/testing/Internals.idl >+++ b/Source/WebCore/testing/Internals.idl >@@ -59,6 +59,9 @@ > boolean isValidContentSelect(in Element contentElement) raises(DOMException); > Node treeScopeRootNode(in Node node) raises (DOMException); > Node parentTreeScope(in Node node) raises (DOMException); >+ boolean hasSelectorForIdInShadow(in Element host, in DOMString id) raises (DOMException); >+ boolean hasSelectorForClassInShadow(in Element host, in DOMString className) raises (DOMException); >+ boolean hasSelectorForAttributeInShadow(in Element host, in DOMString attributeName) raises (DOMException); > > Node nextSiblingByWalker(in Node node) raises(DOMException); > Node firstChildByWalker(in Node node) raises(DOMException); >diff --git a/Source/autotools/symbols.filter b/Source/autotools/symbols.filter >index d82f1798511c26d47bf5454504fc0665fec96be9..94d46cc7879c86c3efbe2ea1f431123d71d3295b 100644 >--- a/Source/autotools/symbols.filter >+++ b/Source/autotools/symbols.filter >@@ -56,6 +56,7 @@ _ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_13ContainerNodeEiib; > _ZN7WebCore12TextIterator29getLocationAndLengthFromRangeEPNS_7ElementEPKNS_5RangeERjS6_; > _ZN7WebCore12TextIterator29getLocationAndLengthFromRangeEPNS_7ElementEPKNS_5RangeERmS6_; > _ZN7WebCore12PrintContext20pageNumberForElementEPNS_7ElementERKNS_9FloatSizeE; >+_ZN7WebCore13ElementShadow31ensureSelectFeatureSetCollectedEv; > _ZN7WebCore13createWrapperEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEPNS_4NodeE; > _ZN7WebCore14ClientRectListC1ERKN3WTF6VectorINS_9FloatQuadELj0EEE; > _ZN7WebCore14ClientRectListC1ERKN3WTF6VectorINS_9FloatQuadELm0EEE; >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index cdf7058316a500b7e2aa905f1585418978faefcf..a9ac64fbae014cdfc80ca415970b45b75d3df6cd 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,13 @@ >+2012-11-08 Shinya Kawanaka <shinyak@chromium.org> >+ >+ [Shadow] ElementShadow should have RuleFeatureSet for select attribute selectors. >+ https://bugs.webkit.org/show_bug.cgi?id=101180 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/dom/shadow/shadow-select-attribute-featureset-expected.txt: Added. >+ * fast/dom/shadow/shadow-select-attribute-featureset.html: Added. >+ > 2012-11-07 Hayato Ito <hayato@chromium.org> > > Unreviewed gardening. >diff --git a/LayoutTests/fast/dom/shadow/shadow-select-attribute-featureset-expected.txt b/LayoutTests/fast/dom/shadow/shadow-select-attribute-featureset-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..ccda44d904d231ef4607065682b6f0f1869bb026 >--- /dev/null >+++ b/LayoutTests/fast/dom/shadow/shadow-select-attribute-featureset-expected.txt >@@ -0,0 +1,75 @@ >+Id should be collected >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForIdInShadow(host, "bar") is false >+PASS internals.hasSelectorForIdInShadow(host, "host") is false >+ >+Class should be collected >+PASS internals.hasSelectorForClassInShadow(host, "foo") is true >+PASS internals.hasSelectorForClassInShadow(host, "host") is false >+ >+Attribute should be collected >+PASS internals.hasSelectorForAttributeInShadow(host, "foo") is true >+PASS internals.hasSelectorForAttributeInShadow(host, "host") is false >+ >+Select attribute might have several selectors >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForIdInShadow(host, "bar") is false >+PASS internals.hasSelectorForIdInShadow(host, "baz") is false >+PASS internals.hasSelectorForClassInShadow(host, "foo") is false >+PASS internals.hasSelectorForClassInShadow(host, "bar") is true >+PASS internals.hasSelectorForClassInShadow(host, "baz") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "foo") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "bar") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "baz") is true >+ >+Don't count shadow element >+PASS internals.hasSelectorForIdInShadow(host, "foo") is false >+PASS internals.hasSelectorForIdInShadow(host, "bar") is false >+PASS internals.hasSelectorForIdInShadow(host, "baz") is false >+PASS internals.hasSelectorForClassInShadow(host, "foo") is false >+PASS internals.hasSelectorForClassInShadow(host, "bar") is false >+PASS internals.hasSelectorForClassInShadow(host, "baz") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "foo") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "bar") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "baz") is false >+ >+Complex case for single ShadowRoot >+PASS internals.hasSelectorForIdInShadow(host, "foo") is false >+PASS internals.hasSelectorForClassInShadow(host, "foo") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "foo") is true >+PASS internals.hasSelectorForAttributeInShadow(host, "piyo") is false >+ >+Another complex case for single ShadowRoot >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForClassInShadow(host, "foo") is true >+PASS internals.hasSelectorForAttributeInShadow(host, "foo") is true >+ >+Multiple ShadowRoot case >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForIdInShadow(host, "bar") is true >+PASS internals.hasSelectorForIdInShadow(host, "baz") is false >+PASS internals.hasSelectorForClassInShadow(host, "foo") is false >+PASS internals.hasSelectorForClassInShadow(host, "bar") is true >+PASS internals.hasSelectorForClassInShadow(host, "baz") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "foo") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "bar") is false >+PASS internals.hasSelectorForAttributeInShadow(host, "baz") is true >+ >+Dynamic select attribute update >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForIdInShadow(host, "bar") is false >+PASS internals.hasSelectorForIdInShadow(host, "foo") is false >+PASS internals.hasSelectorForIdInShadow(host, "bar") is true >+ >+Nested ShadowDOM case >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForIdInShadow(host, "bar") is true >+PASS internals.hasSelectorForIdInShadow(host, "baz") is false >+PASS internals.hasSelectorForIdInShadow(host, "foo") is true >+PASS internals.hasSelectorForIdInShadow(host, "bar") is false >+PASS internals.hasSelectorForIdInShadow(host, "baz") is true >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/fast/dom/shadow/shadow-select-attribute-featureset.html b/LayoutTests/fast/dom/shadow/shadow-select-attribute-featureset.html >new file mode 100644 >index 0000000000000000000000000000000000000000..12a55149566a882c579c9d7a33ebd9daca69f036 >--- /dev/null >+++ b/LayoutTests/fast/dom/shadow/shadow-select-attribute-featureset.html >@@ -0,0 +1,175 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../../js/resources/js-test-pre.js"></script> >+<script src="resources/polyfill.js"></script> >+<script src="resources/shadow-dom.js"></script> >+</head> >+<body> >+ >+<div id="container"></div> >+<pre id="console"></pre> >+ >+<script> >+function testCase(f) >+{ >+ container.innerHTML = ''; >+ container.appendChild(createDOM('div', {'id': 'host'}, >+ createShadowRoot())); >+ shadowRoot = internals.shadowRoot(host); >+ >+ f(); >+ debug(''); >+} >+ >+testCase(function() >+{ >+ debug('Id should be collected'); >+ >+ shadowRoot.innerHTML = '<content select="#foo"></content>'; >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "host")', 'false'); >+}); >+ >+testCase(function() >+{ >+ debug('Class should be collected'); >+ >+ shadowRoot.innerHTML = '<content select=".foo"></content>'; >+ shouldBe('internals.hasSelectorForClassInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "host")', 'false'); >+}); >+ >+testCase(function() >+{ >+ debug('Attribute should be collected'); >+ >+ shadowRoot.innerHTML = '<content select="div[foo]"></content>'; >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "host")', 'false'); >+}); >+ >+testCase(function() >+{ >+ debug('Select attribute might have several selectors'); >+ >+ shadowRoot.innerHTML = '<content select="#foo,.bar,div[baz]"></content>'; >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "baz")', 'false'); >+ >+ shouldBe('internals.hasSelectorForClassInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "bar")', 'true'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "baz")', 'false'); >+ >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "baz")', 'true'); >+}); >+ >+testCase(function() >+{ >+ debug('Don\'t count shadow element'); >+ >+ shadowRoot.innerHTML = '<shadow select="#foo,.bar,div[baz]"></shadow>'; >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "baz")', 'false'); >+ >+ shouldBe('internals.hasSelectorForClassInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "baz")', 'false'); >+ >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "baz")', 'false'); >+}); >+ >+testCase(function() >+{ >+ debug('Complex case for single ShadowRoot'); >+ >+ shadowRoot.innerHTML = '<div><div></div><content select="*"></content><div><content select="div[foo=piyo]"></content></div>'; >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "piyo")', 'false'); >+}); >+ >+testCase(function() >+{ >+ debug('Another complex case for single ShadowRoot'); >+ >+ shadowRoot.innerHTML = '<content select="#foo,.foo,div[foo]"></content>'; >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "foo")', 'true'); >+}); >+ >+testCase(function() >+{ >+ debug('Multiple ShadowRoot case'); >+ >+ var anotherShadowRoot = new WebKitShadowRoot(host); >+ >+ shadowRoot.innerHTML = '<content select="#foo"></content>'; >+ anotherShadowRoot.innerHTML = '<content select="#bar"></content><content select="div[baz],.bar"></content>'; >+ >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "baz")', 'false'); >+ >+ shouldBe('internals.hasSelectorForClassInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "bar")', 'true'); >+ shouldBe('internals.hasSelectorForClassInShadow(host, "baz")', 'false'); >+ >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForAttributeInShadow(host, "baz")', 'true'); >+}); >+ >+testCase(function() >+{ >+ debug('Dynamic select attribute update'); >+ >+ shadowRoot.innerHTML = '<content select="#foo"></content>'; >+ >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'false'); >+ >+ var content = shadowRoot.querySelector('content'); >+ content.select = '#bar'; >+ >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'false'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'true'); >+}); >+ >+testCase(function() >+{ >+ debug('Nested ShadowDOM case'); >+ >+ shadowRoot.innerHTML = '<content select="#foo"></content>'; >+ >+ var div = document.createElement('div'); >+ var nestedShadowRoot = new WebKitShadowRoot(div); >+ nestedShadowRoot.innerHTML = '<content select="#bar"></content>'; >+ shadowRoot.appendChild(div); >+ >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "baz")', 'false'); >+ >+ var content = nestedShadowRoot.querySelector('content'); >+ content.select = '#baz'; >+ >+ shouldBe('internals.hasSelectorForIdInShadow(host, "foo")', 'true'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "bar")', 'false'); >+ shouldBe('internals.hasSelectorForIdInShadow(host, "baz")', 'true'); >+}); >+ >+finishJSTest(); >+</script> >+<script src="../../js/resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/ChangeLog b/ChangeLog >index ea8cf9df5ded11f079632b7d95c1f1e90a33e10f..172341d131f458015f1565a0982c406e7d47400e 100644 >--- a/ChangeLog >+++ b/ChangeLog >@@ -1,3 +1,14 @@ >+2012-11-08 Shinya Kawanaka <shinyak@chromium.org> >+ >+ [Shadow] ElementShadow should have RuleFeatureSet for select attribute selectors. >+ https://bugs.webkit.org/show_bug.cgi?id=101180 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Exposes necessary symbols. >+ >+ * Source/autotools/symbols.filter: >+ > 2012-11-07 Shinya Kawanaka <shinyak@chromium.org> > > [Shadow] Use setPseudo() instead of setShadowPseudoId().
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 101180
:
172753
|
172957
|
172961
|
172967
|
173185
|
173213