Diff
Modified: trunk/Source/WebCore/CMakeLists.txt (94088 => 94089)
--- trunk/Source/WebCore/CMakeLists.txt 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/CMakeLists.txt 2011-08-30 17:43:24 UTC (rev 94089)
@@ -568,7 +568,7 @@
dom/ScriptExecutionContext.cpp
dom/ScriptRunner.cpp
dom/SelectElement.cpp
- dom/SelectorNodeList.cpp
+ dom/SelectorQuery.cpp
dom/ShadowContentElement.cpp
dom/ShadowInclusionSelector.cpp
dom/ShadowRoot.cpp
Modified: trunk/Source/WebCore/ChangeLog (94088 => 94089)
--- trunk/Source/WebCore/ChangeLog 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/ChangeLog 2011-08-30 17:43:24 UTC (rev 94089)
@@ -1,3 +1,55 @@
+2011-08-30 Antti Koivisto <[email protected]>
+
+ querySelector/querySelectorAll should use selector checker fast path
+ https://bugs.webkit.org/show_bug.cgi?id=67161
+
+ Reviewed by Sam Weinig.
+
+ Descendant and child selectors can be matches substantially faster using
+ SelectorChecker::fastCheckSelector() path. Currently it is used for style matching only.
+
+ Add SelectorQuery class that can do both querySelector and querySelectorAll efficiently using
+ fast path. Use inlined loop for DOM traversal.
+
+ The patch is ~25% speedup in the overall native score of http://www.webkit.org/perf/slickspeed/.
+ Some individual subtests (using child or descendant selectors) execute twice as fast.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * WebCore.gypi:
+ * WebCore.pro:
+ * WebCore.vcproj/WebCore.vcproj:
+ * WebCore.xcodeproj/project.pbxproj:
+ * css/CSSStyleSelector.cpp:
+ (WebCore::CSSStyleSelector::SelectorChecker::checkSelector):
+ (WebCore::CSSStyleSelector::SelectorChecker::isFastCheckableSelector):
+ (WebCore::RuleData::RuleData):
+ * css/CSSStyleSelector.h:
+
+ Make fast path checking available outside CSSStyleSelector.
+
+ * dom/DOMAllInOne.cpp:
+ * dom/Node.cpp:
+ (WebCore::Node::querySelector):
+ (WebCore::Node::querySelectorAll):
+
+ Switch to SelectorQuery.
+
+ * dom/SelectorNodeList.cpp: Removed.
+ * dom/SelectorNodeList.h: Removed.
+
+ SelectorQuery makes these obsolete.
+
+ * dom/SelectorQuery.cpp: Added.
+ (WebCore::SelectorQuery::SelectorQuery):
+ (WebCore::SelectorQuery::queryAll):
+ (WebCore::SelectorQuery::queryFirst):
+ (WebCore::SelectorQuery::canUseIdLookup):
+ (WebCore::SelectorQuery::execute):
+ * dom/SelectorQuery.h: Added.
+
+ Class for selector matching in tree.
+
2011-08-30 Dmitry Titov <[email protected]>
REGRESSION (r93913): Failures in fast/replaced/frame-removed-during-resize.html and scrollbars/scrollable-iframe-remove-crash.html
Modified: trunk/Source/WebCore/GNUmakefile.list.am (94088 => 94089)
--- trunk/Source/WebCore/GNUmakefile.list.am 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/GNUmakefile.list.am 2011-08-30 17:43:24 UTC (rev 94089)
@@ -1284,8 +1284,8 @@
Source/WebCore/dom/ScriptRunner.h \
Source/WebCore/dom/SelectElement.cpp \
Source/WebCore/dom/SelectElement.h \
- Source/WebCore/dom/SelectorNodeList.cpp \
- Source/WebCore/dom/SelectorNodeList.h \
+ Source/WebCore/dom/SelectorQuery.cpp \
+ Source/WebCore/dom/SelectorQuery.h \
Source/WebCore/dom/ShadowContentElement.cpp \
Source/WebCore/dom/ShadowContentElement.h \
Source/WebCore/dom/ShadowInclusionSelector.cpp \
Modified: trunk/Source/WebCore/WebCore.gypi (94088 => 94089)
--- trunk/Source/WebCore/WebCore.gypi 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.gypi 2011-08-30 17:43:24 UTC (rev 94089)
@@ -5354,8 +5354,8 @@
'dom/ScriptedAnimationController.h',
'dom/SelectElement.cpp',
'dom/SelectElement.h',
- 'dom/SelectorNodeList.cpp',
- 'dom/SelectorNodeList.h',
+ 'dom/SelectorQuery.cpp',
+ 'dom/SelectorQuery.h',
'dom/ShadowContentElement.cpp',
'dom/ShadowContentElement.h',
'dom/ShadowInclusionSelector.cpp',
Modified: trunk/Source/WebCore/WebCore.pro (94088 => 94089)
--- trunk/Source/WebCore/WebCore.pro 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.pro 2011-08-30 17:43:24 UTC (rev 94089)
@@ -542,7 +542,7 @@
dom/ScriptExecutionContext.cpp \
dom/ScriptRunner.cpp \
dom/SelectElement.cpp \
- dom/SelectorNodeList.cpp \
+ dom/SelectorQuery.cpp \
dom/ShadowContentElement.cpp \
dom/ShadowInclusionSelector.cpp \
dom/ShadowRoot.cpp \
@@ -1536,7 +1536,7 @@
dom/ScriptElement.h \
dom/ScriptExecutionContext.h \
dom/SelectElement.h \
- dom/SelectorNodeList.h \
+ dom/SelectorQuery.h \
dom/ShadowContentElement.h \
dom/ShadowInclusionSelector.h \
dom/ShadowRoot.h \
Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (94088 => 94089)
--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2011-08-30 17:43:24 UTC (rev 94089)
@@ -48330,7 +48330,7 @@
>
</File>
<File
- RelativePath="..\dom\SelectorNodeList.cpp"
+ RelativePath="..\dom\SelectorQuery.cpp"
>
<FileConfiguration
Name="Debug|Win32"
@@ -48382,66 +48382,10 @@
</FileConfiguration>
</File>
<File
- RelativePath="..\dom\SelectorNodeList.cpp"
+ RelativePath="..\dom\SelectorQuery.h"
>
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo_CFLite|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo_CFLite|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Production|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
</File>
<File
- RelativePath="..\dom\SelectorNodeList.h"
- >
- </File>
- <File
- RelativePath="..\dom\SelectorNodeList.h"
- >
- </File>
- <File
RelativePath="..\dom\ShadowContentElement.cpp"
>
<FileConfiguration
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (94088 => 94089)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2011-08-30 17:43:24 UTC (rev 94089)
@@ -5098,8 +5098,6 @@
BC7FA6210D1F0CBD00DB22A9 /* DynamicNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA61F0D1F0CBD00DB22A9 /* DynamicNodeList.h */; };
BC7FA62D0D1F0EFF00DB22A9 /* StaticNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA62B0D1F0EFF00DB22A9 /* StaticNodeList.h */; };
BC7FA62E0D1F0EFF00DB22A9 /* StaticNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7FA62C0D1F0EFF00DB22A9 /* StaticNodeList.cpp */; };
- BC7FA6810D1F167900DB22A9 /* SelectorNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA67F0D1F167900DB22A9 /* SelectorNodeList.h */; };
- BC7FA6820D1F167900DB22A9 /* SelectorNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7FA6800D1F167900DB22A9 /* SelectorNodeList.cpp */; };
BC80C9870CD294EE00A0B7B3 /* CSSTimingFunctionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC80C9850CD294EE00A0B7B3 /* CSSTimingFunctionValue.cpp */; };
BC80C9880CD294EE00A0B7B3 /* CSSTimingFunctionValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC80C9860CD294EE00A0B7B3 /* CSSTimingFunctionValue.h */; };
BC8243290D0CE8A200460C8F /* JSSQLError.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8243250D0CE8A200460C8F /* JSSQLError.h */; };
@@ -5652,6 +5650,8 @@
E446143C0CD689CC00FADA75 /* JSHTMLSourceElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B423720CBFB6E000AF2ECE /* JSHTMLSourceElement.h */; };
E44614510CD68A3500FADA75 /* RenderVideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B41E330CBFB60900AF2ECE /* RenderVideo.cpp */; };
E44614520CD68A3500FADA75 /* RenderVideo.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B41E340CBFB60900AF2ECE /* RenderVideo.h */; };
+ E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E45322A9140CE267005A0F92 /* SelectorQuery.cpp */; };
+ E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E45322AA140CE267005A0F92 /* SelectorQuery.h */; };
E462A4A1113E71BE004A4220 /* IntPointHash.h in Headers */ = {isa = PBXBuildFile; fileRef = E462A4A0113E71BE004A4220 /* IntPointHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4778B7F115A581A00B5D372 /* JSCustomEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4778B7D115A581A00B5D372 /* JSCustomEvent.cpp */; };
E4778B80115A581A00B5D372 /* JSCustomEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = E4778B7E115A581A00B5D372 /* JSCustomEvent.h */; };
@@ -11817,8 +11817,6 @@
BC7FA61F0D1F0CBD00DB22A9 /* DynamicNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicNodeList.h; sourceTree = "<group>"; };
BC7FA62B0D1F0EFF00DB22A9 /* StaticNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticNodeList.h; sourceTree = "<group>"; };
BC7FA62C0D1F0EFF00DB22A9 /* StaticNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticNodeList.cpp; sourceTree = "<group>"; };
- BC7FA67F0D1F167900DB22A9 /* SelectorNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorNodeList.h; sourceTree = "<group>"; };
- BC7FA6800D1F167900DB22A9 /* SelectorNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorNodeList.cpp; sourceTree = "<group>"; };
BC80C9850CD294EE00A0B7B3 /* CSSTimingFunctionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSSTimingFunctionValue.cpp; sourceTree = "<group>"; };
BC80C9860CD294EE00A0B7B3 /* CSSTimingFunctionValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSTimingFunctionValue.h; sourceTree = "<group>"; };
BC8243250D0CE8A200460C8F /* JSSQLError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLError.h; sourceTree = "<group>"; };
@@ -12405,6 +12403,8 @@
E44614110CD6826900FADA75 /* JSMediaError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaError.h; sourceTree = "<group>"; };
E44614120CD6826900FADA75 /* JSTimeRanges.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTimeRanges.cpp; sourceTree = "<group>"; };
E44614130CD6826900FADA75 /* JSTimeRanges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTimeRanges.h; sourceTree = "<group>"; };
+ E45322A9140CE267005A0F92 /* SelectorQuery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorQuery.cpp; sourceTree = "<group>"; };
+ E45322AA140CE267005A0F92 /* SelectorQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorQuery.h; sourceTree = "<group>"; };
E462A4A0113E71BE004A4220 /* IntPointHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntPointHash.h; sourceTree = "<group>"; };
E4778B7D115A581A00B5D372 /* JSCustomEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomEvent.cpp; sourceTree = "<group>"; };
E4778B7E115A581A00B5D372 /* JSCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomEvent.h; sourceTree = "<group>"; };
@@ -20062,8 +20062,8 @@
8A413ADE1207BBA50082016E /* ScriptRunner.h */,
084AEBE20FB505FA0038483E /* SelectElement.cpp */,
084AEBE30FB505FA0038483E /* SelectElement.h */,
- BC7FA6800D1F167900DB22A9 /* SelectorNodeList.cpp */,
- BC7FA67F0D1F167900DB22A9 /* SelectorNodeList.h */,
+ E45322A9140CE267005A0F92 /* SelectorQuery.cpp */,
+ E45322AA140CE267005A0F92 /* SelectorQuery.h */,
A766CF8B13810E0C0011A0B3 /* ShadowContentElement.cpp */,
A74C2D3B13811E0D00F83572 /* ShadowContentElement.h */,
A71C30B61381265E00DBC351 /* ShadowInclusionSelector.cpp */,
@@ -22839,7 +22839,6 @@
371F4FFC0D25E7F300ECE0D5 /* SegmentedFontData.h in Headers */,
B2C3DA2F0D006C1D00EF6F26 /* SegmentedString.h in Headers */,
084AEBE50FB505FA0038483E /* SelectElement.h in Headers */,
- BC7FA6810D1F167900DB22A9 /* SelectorNodeList.h in Headers */,
A75E497610752ACB00C9B896 /* SerializedScriptValue.h in Headers */,
93309E10099E64920056E581 /* SetNodeAttributeCommand.h in Headers */,
B8DBDB4C130B0F8A00F5CDB1 /* SetSelectionCommand.h in Headers */,
@@ -23448,6 +23447,7 @@
93500F3213FDE3BE0099EC24 /* NSScrollerImpDetails.h in Headers */,
D0A3A7311405A39800FB8ED3 /* ResourceLoaderOptions.h in Headers */,
BCE43897140B0051005E437E /* EventConstructors.h in Headers */,
+ E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */,
B10B6980140C174000BC1C26 /* WebVTTToken.h in Headers */,
B10B6982140C174000BC1C26 /* WebVTTTokenizer.h in Headers */,
);
@@ -25781,7 +25781,6 @@
371F4FFD0D25E7F300ECE0D5 /* SegmentedFontData.cpp in Sources */,
B2C3DA2E0D006C1D00EF6F26 /* SegmentedString.cpp in Sources */,
084AEBE40FB505FA0038483E /* SelectElement.cpp in Sources */,
- BC7FA6820D1F167900DB22A9 /* SelectorNodeList.cpp in Sources */,
A75E497710752ACB00C9B896 /* SerializedScriptValue.cpp in Sources */,
93309E0F099E64920056E581 /* SetNodeAttributeCommand.cpp in Sources */,
B8DBDB4B130B0F8A00F5CDB1 /* SetSelectionCommand.cpp in Sources */,
@@ -26259,6 +26258,7 @@
1A1414B513A0F0500019996C /* WebKitFontFamilyNames.cpp in Sources */,
DF9AFD7313FC31D80015FEB7 /* MediaPlayerPrivateAVFoundationObjC.mm in Sources */,
BCE4389A140B0073005E437E /* JSEventConstructors.cpp in Sources */,
+ E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */,
B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (94088 => 94089)
--- trunk/Source/WebCore/css/CSSStyleSelector.cpp 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp 2011-08-30 17:43:24 UTC (rev 94089)
@@ -875,9 +875,20 @@
#endif
}
-bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
+bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element, bool isFastCheckableSelector) const
{
PseudoId dynamicPseudo = NOPSEUDO;
+ if (isFastCheckableSelector && !element->isSVGElement()) {
+ // fastCheckSelector assumes class and id match for the top selector.
+ if (sel->m_match == CSSSelector::Class) {
+ if (!(element->hasClass() && static_cast<StyledElement*>(element)->classNames().contains(sel->value())))
+ return false;
+ } else if (sel->m_match == CSSSelector::Id) {
+ if (!(element->hasID() && element->idForStyleResolution() == sel->value()))
+ return false;
+ }
+ return fastCheckSelector(sel, element);
+ }
return checkSelector(sel, element, dynamicPseudo, false, false) == SelectorMatches;
}
@@ -2012,17 +2023,6 @@
const AtomicString& namespaceURI = selector->tag().namespaceURI();
return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
}
-
-inline bool isFastCheckableSelector(const CSSSelector* selector)
-{
- for (; selector; selector = selector->tagHistory()) {
- if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
- return false;
- if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
- return false;
- }
- return true;
-}
template <bool checkValue(const Element*, AtomicStringImpl*)>
inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
@@ -2116,6 +2116,17 @@
return true;
}
+bool CSSStyleSelector::SelectorChecker::isFastCheckableSelector(const CSSSelector* selector)
+{
+ for (; selector; selector = selector->tagHistory()) {
+ if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
+ return false;
+ if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
+ return false;
+ }
+ return true;
+}
+
// Recursive check of selectors and combinators
// It can return 3 different values:
// * SelectorMatches - the selector matches the element e
@@ -3035,7 +3046,7 @@
, m_selector(selector)
, m_specificity(selector->specificity())
, m_position(position)
- , m_hasFastCheckableSelector(isFastCheckableSelector(selector))
+ , m_hasFastCheckableSelector(CSSStyleSelector::SelectorChecker::isFastCheckableSelector(selector))
, m_hasMultipartSelector(selector->tagHistory())
, m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
{
Modified: trunk/Source/WebCore/css/CSSStyleSelector.h (94088 => 94089)
--- trunk/Source/WebCore/css/CSSStyleSelector.h 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/css/CSSStyleSelector.h 2011-08-30 17:43:24 UTC (rev 94089)
@@ -275,10 +275,11 @@
public:
SelectorChecker(Document*, bool strictParsing);
- bool checkSelector(CSSSelector*, Element*) const;
+ bool checkSelector(CSSSelector*, Element*, bool isFastCheckableSelector = false) const;
SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle*, RenderStyle* elementParentStyle) const;
bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
+ static bool isFastCheckableSelector(const CSSSelector*);
static bool fastCheckSelector(const CSSSelector*, const Element*);
EInsideLink determineLinkState(Element* element) const;
Modified: trunk/Source/WebCore/dom/DOMAllInOne.cpp (94088 => 94089)
--- trunk/Source/WebCore/dom/DOMAllInOne.cpp 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/DOMAllInOne.cpp 2011-08-30 17:43:24 UTC (rev 94089)
@@ -115,7 +115,7 @@
#include "ScriptRunner.cpp"
#include "ScriptableDocumentParser.cpp"
#include "SelectElement.cpp"
-#include "SelectorNodeList.cpp"
+#include "SelectorQuery.cpp"
#include "ShadowContentElement.cpp"
#include "ShadowInclusionSelector.cpp"
#include "ShadowRoot.cpp"
Modified: trunk/Source/WebCore/dom/Node.cpp (94088 => 94089)
--- trunk/Source/WebCore/dom/Node.cpp 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/Node.cpp 2011-08-30 17:43:24 UTC (rev 94089)
@@ -81,7 +81,7 @@
#include "RenderTextControl.h"
#include "RenderView.h"
#include "ScopedEventQueue.h"
-#include "SelectorNodeList.h"
+#include "SelectorQuery.h"
#include "ShadowRoot.h"
#include "StaticNodeList.h"
#include "TagNodeList.h"
@@ -1765,29 +1765,9 @@
ec = NAMESPACE_ERR;
return 0;
}
-
- CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
-
- // FIXME: we could also optimize for the the [id="foo"] case
- if (strictParsing && inDocument() && querySelectorList.hasOneSelector() && querySelectorList.first()->m_match == CSSSelector::Id) {
- Element* element = treeScope()->getElementById(querySelectorList.first()->value());
- if (element && (isDocumentNode() || element->isDescendantOf(this)) && selectorChecker.checkSelector(querySelectorList.first(), element))
- return element;
- return 0;
- }
-
- // FIXME: We can speed this up by implementing caching similar to the one use by getElementById
- for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
- if (n->isElementNode()) {
- Element* element = static_cast<Element*>(n);
- for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
- if (selectorChecker.checkSelector(selector, element))
- return element;
- }
- }
- }
- return 0;
+ SelectorQuery selectorQuery(this, querySelectorList);
+ return selectorQuery.queryFirst();
}
PassRefPtr<NodeList> Node::querySelectorAll(const String& selectors, ExceptionCode& ec)
@@ -1813,7 +1793,8 @@
return 0;
}
- return createSelectorNodeList(this, querySelectorList);
+ SelectorQuery selectorQuery(this, querySelectorList);
+ return selectorQuery.queryAll();
}
Document *Node::ownerDocument() const
Deleted: trunk/Source/WebCore/dom/SelectorNodeList.cpp (94088 => 94089)
--- trunk/Source/WebCore/dom/SelectorNodeList.cpp 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/SelectorNodeList.cpp 2011-08-30 17:43:24 UTC (rev 94089)
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "SelectorNodeList.h"
-
-#include "CSSSelector.h"
-#include "CSSSelectorList.h"
-#include "CSSStyleSelector.h"
-#include "Document.h"
-#include "Element.h"
-#include "HTMLNames.h"
-#include "StaticNodeList.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelectorList& querySelectorList)
-{
- Vector<RefPtr<Node> > nodes;
- Document* document = rootNode->document();
- CSSSelector* _onlySelector_ = querySelectorList.hasOneSelector() ? querySelectorList.first() : 0;
- bool strictParsing = !document->inQuirksMode();
-
- CSSStyleSelector::SelectorChecker selectorChecker(document, strictParsing);
-
- if (strictParsing && rootNode->inDocument() && onlySelector && onlySelector->m_match == CSSSelector::Id && !document->containsMultipleElementsWithId(onlySelector->value())) {
- Element* element = document->getElementById(onlySelector->value());
- if (element && (rootNode->isDocumentNode() || element->isDescendantOf(rootNode)) && selectorChecker.checkSelector(onlySelector, element))
- nodes.append(element);
- } else {
- for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode)) {
- if (n->isElementNode()) {
- Element* element = static_cast<Element*>(n);
- for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
- if (selectorChecker.checkSelector(selector, element)) {
- nodes.append(n);
- break;
- }
- }
- }
- }
- }
-
- return StaticNodeList::adopt(nodes);
-}
-
-} // namespace WebCore
Deleted: trunk/Source/WebCore/dom/SelectorNodeList.h (94088 => 94089)
--- trunk/Source/WebCore/dom/SelectorNodeList.h 2011-08-30 17:35:52 UTC (rev 94088)
+++ trunk/Source/WebCore/dom/SelectorNodeList.h 2011-08-30 17:43:24 UTC (rev 94089)
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SelectorNodeList_h
-#define SelectorNodeList_h
-
-#include <wtf/PassRefPtr.h>
-
-namespace WebCore {
-
- class CSSSelectorList;
- class Node;
- class StaticNodeList;
-
- PassRefPtr<StaticNodeList> createSelectorNodeList(Node* rootNode, const CSSSelectorList&);
-
-} // namespace WebCore
-
-#endif // SelectorNodeList_h
Added: trunk/Source/WebCore/dom/SelectorQuery.cpp (0 => 94089)
--- trunk/Source/WebCore/dom/SelectorQuery.cpp (rev 0)
+++ trunk/Source/WebCore/dom/SelectorQuery.cpp 2011-08-30 17:43:24 UTC (rev 94089)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SelectorQuery.h"
+
+#include "CSSSelectorList.h"
+#include "Document.h"
+#include "StaticNodeList.h"
+#include "StyledElement.h"
+
+namespace WebCore {
+
+SelectorQuery::SelectorQuery(Node* rootNode, const CSSSelectorList& selectorList)
+ : m_rootNode(rootNode)
+ , m_selectorChecker(rootNode->document(), !rootNode->document()->inQuirksMode())
+{
+ for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
+ m_selectors.append(SelectorData(selector, CSSStyleSelector::SelectorChecker::isFastCheckableSelector(selector)));
+}
+
+PassRefPtr<NodeList> SelectorQuery::queryAll() const
+{
+ Vector<RefPtr<Node> > result;
+ execute<false>(result);
+ return StaticNodeList::adopt(result);
+}
+
+PassRefPtr<Element> SelectorQuery::queryFirst() const
+{
+ Vector<RefPtr<Node> > result;
+ execute<true>(result);
+ if (result.isEmpty())
+ return 0;
+ ASSERT(result.size() == 1);
+ ASSERT(result.first()->isElementNode());
+ return static_cast<Element*>(result.first().get());
+}
+
+bool SelectorQuery::canUseIdLookup() const
+{
+ // We need to return the matches in document order. To use id lookup while there is possiblity of multiple matches
+ // we would need to sort the results. For now, just traverse the document in that case.
+ if (m_selectors.size() != 1)
+ return false;
+ if (m_selectors[0].selector->m_match != CSSSelector::Id)
+ return false;
+ if (!m_rootNode->inDocument())
+ return false;
+ if (m_rootNode->document()->inQuirksMode())
+ return false;
+ if (m_rootNode->document()->containsMultipleElementsWithId(m_selectors[0].selector->value()))
+ return false;
+ return true;
+}
+
+template <bool firstMatchOnly>
+void SelectorQuery::execute(Vector<RefPtr<Node> >& matchedElements) const
+{
+ if (canUseIdLookup()) {
+ ASSERT(m_selectors.size() == 1);
+ CSSSelector* selector = m_selectors[0].selector;
+ Element* element = m_rootNode->document()->getElementById(selector->value());
+ if (!element || !(m_rootNode->isDocumentNode() || element->isDescendantOf(m_rootNode)))
+ return;
+ if (m_selectorChecker.checkSelector(selector, element, m_selectors[0].isFastCheckable))
+ matchedElements.append(element);
+ return;
+ }
+
+ unsigned selectorCount = m_selectors.size();
+
+ Node* n = m_rootNode->firstChild();
+ while (n) {
+ if (n->isElementNode()) {
+ Element* element = static_cast<Element*>(n);
+ for (unsigned i = 0; i < selectorCount; ++i) {
+ if (m_selectorChecker.checkSelector(m_selectors[i].selector, element, m_selectors[i].isFastCheckable)) {
+ matchedElements.append(element);
+ if (firstMatchOnly)
+ return;
+ break;
+ }
+ }
+ if (element->firstChild()) {
+ n = element->firstChild();
+ continue;
+ }
+ }
+ while (!n->nextSibling()) {
+ n = n->parentNode();
+ if (n == m_rootNode)
+ return;
+ }
+ n = n->nextSibling();
+ }
+}
+
+}
Added: trunk/Source/WebCore/dom/SelectorQuery.h (0 => 94089)
--- trunk/Source/WebCore/dom/SelectorQuery.h (rev 0)
+++ trunk/Source/WebCore/dom/SelectorQuery.h 2011-08-30 17:43:24 UTC (rev 94089)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SelectorQuery_h
+#define SelectorQuery_h
+
+#include "CSSStyleSelector.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Node;
+class NodeList;
+class Element;
+class CSSSelector;
+class CSSSelectorList;
+
+class SelectorQuery {
+public:
+ SelectorQuery(Node* rootNode, const CSSSelectorList&);
+
+ PassRefPtr<NodeList> queryAll() const;
+ PassRefPtr<Element> queryFirst() const;
+
+private:
+ bool canUseIdLookup() const;
+
+ template <bool firstMatchOnly>
+ void execute(Vector<RefPtr<Node> >&) const;
+
+ struct SelectorData {
+ SelectorData(CSSSelector* selector, bool isFastCheckable) : selector(selector), isFastCheckable(isFastCheckable) { }
+ CSSSelector* selector;
+ bool isFastCheckable;
+ };
+ Node* m_rootNode;
+ Vector<SelectorData> m_selectors;
+ CSSStyleSelector::SelectorChecker m_selectorChecker;
+};
+
+}
+
+#endif