Source/WebCore/ChangeLog

 12015-08-13 Chris Dumez <cdumez@apple.com>
 2
 3 Refactor HTMLCollection to be as fast as CachedLiveNodeList
 4 https://bugs.webkit.org/show_bug.cgi?id=147979
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Refactor HTMLCollection to be as fast as CachedLiveNodeList. This is in
 9 preparation of having getElementsByTagName*() / getElementsByClassName()
 10 return an HTMLCollection instead of a NodeList, as per the
 11 specification. Chrome and Firefox already match the specification in
 12 this case.
 13
 14 Traversing an HTMLCollection was slow because of all the extra
 15 branching it had compared to CachedLiveNodeList. To address the issue,
 16 this patch introduces a new templated CachedHTMLCollection subclass,
 17 which behaves in a similar way as CachedLiveNodeList. The 2 template
 18 parameters are:
 19 1. The type of the subclass of CachedHTMLCollection, so we can call
 20 elementMatches() directly on the subclass, without needed any
 21 virtual function call or switch statement. This is the same approach
 22 as in CachedLiveNodeList.
 23 2. The type of tree traversal used (Descendants, ChildrenOnly,
 24 CustomForwardOnly). Unlike LiveNodeList, HTMLCollection needs to
 25 support these 3 types of tree traversal. These were causing extra
 26 branching for every item() call. We are now able to choose the right
 27 type of traversal for the CachedHTMLCollection at compile time.
 28
 29 * WebCore.xcodeproj/project.pbxproj:
 30 Add new files to the Project.
 31
 32 * dom/ContainerNode.cpp:
 33 (WebCore::ContainerNode::children):
 34 (WebCore::ContainerNode::cachedHTMLCollection): Deleted.
 35 * dom/ContainerNode.h:
 36 Drop ContainerNode::ensureCachedHTMLCollection() and use
 37 NodeListsNodeData::addCachedCollection() directly at call sites
 38 instead. We need access to the CollectionType at build-time so
 39 we can resolve the CollectionTraversalType parameter for the
 40 GenericCachedHTMLCollection using CollectionTypeTraits.
 41
 42 * dom/Document.cpp:
 43 * dom/Document.h:
 44 Update ensureCachedCollection() so the CollectionType is now a template
 45 parameter instead of a method argument. We need to know the
 46 CollectionType at build time to construct the GenericCachedHTMLCollection.
 47
 48 * dom/ElementChildIterator.h:
 49 (WebCore::ElementChildIterator<ElementType>::operator):
 50 (WebCore::ElementChildConstIterator<ElementType>::operator):
 51 Add support for decrementing an ElementChildIterator, for consistency
 52 with ElementDescendantIterator. We need this to support backward
 53 traversal in CachedHTMLCollections that use the 'ChildrenOnly' type
 54 of traversal.
 55
 56 * dom/LiveNodeList.h:
 57 (WebCore::CachedLiveNodeList<NodeListType>::collectionBegin):
 58 (WebCore::CachedLiveNodeList<NodeListType>::collectionLast):
 59 (WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseForward):
 60 (WebCore::CachedLiveNodeList<NodeListType>::collectionTraverseBackward):
 61 Move traversal implementation to CollectionTraversal.h, so it can be
 62 shared with achedHTMLCollection.h.
 63
 64 * html/CachedHTMLCollection.h: Added.
 65 (WebCore::traversalType>::CachedHTMLCollection):
 66 (WebCore::traversalType>::~CachedHTMLCollection):
 67 (WebCore::traversalType>::CachedHTMLCollection::memoryCost):
 68 (WebCore::traversalType>::collectionCanTraverseBackward):
 69 (WebCore::traversalType>::collectionTraverseForward):
 70 (WebCore::traversalType>::collectionTraverseBackward):
 71 (WebCore::traversalType>::willValidateIndexCache):
 72 (WebCore::traversalType>::length):
 73 (WebCore::traversalType>::item):
 74 (WebCore::traversalType>::invalidateCache):
 75 (WebCore::traversalType>::elementMatches):
 76 (WebCore::nameShouldBeVisibleInDocumentAll):
 77 (WebCore::traversalType>::namedItem):
 78
 79 * html/CollectionTraversal.h: Added.
 80 Add new template class that provide the collection traversal code
 81 needed by CollectionIndexCache. It has template specializations for
 82 all 3 types of traversal: Descendants, ChildrenOnly, and
 83 CustomForwardOnly.
 84
 85 * html/CollectionType.h:
 86 Add CollectionTypeTraits traits so we can resolve the
 87 CollectionTraversalType used by a specific CollectionType at
 88 compile-time. This is needed for the second template parameter of
 89 CachedHTMLCollection.
 90
 91 * html/GenericCachedHTMLCollection.cpp: Added.
 92 (WebCore::GenericCachedHTMLCollection<traversalType>::elementMatches):
 93 * html/GenericCachedHTMLCollection.h: Added.
 94 Add CachedHTMLCollection subclass is the generic one used for all
 95 CollectionTypes that do not have their own subclass (e.g. NodeChildren).
 96 This has an elementMatches() method with a switch() statement handling
 97 all these CollectionTypes. Those are not normally not performance
 98 sensitive.
 99
 100 * html/HTMLAllCollection.cpp:
 101 (WebCore::HTMLAllCollection::HTMLAllCollection):
 102 * html/HTMLAllCollection.h:
 103 Subclass CachedHTMLCollection instead of HTMLCollection. Also provide
 104 an elementMatches() method that simply returns true as we want to
 105 match all elements.
 106
 107 * html/HTMLCollection.cpp:
 108 (WebCore::HTMLCollection::HTMLCollection):
 109 Move CollectionIndexCache member to the subclass and drop the 2 other
 110 members as they are replaced with the CollectionTraversalType template
 111 parameter of CachedHTMLCollection.
 112
 113 (WebCore::HTMLCollection::~HTMLCollection):
 114 Move Document::unregisterCollection() call to ~CachedHTMLCollection()
 115 as we needed to check if the CollectionIndexCache was valid first.
 116
 117 (WebCore::HTMLCollection::updateNamedElementCache):
 118 Move part of the implementation to the CachedHTMLCollection subclass
 119 as it needs to know about the type of traversal and it needs to be
 120 able to call elementMatches().
 121
 122 * html/HTMLCollection.h:
 123 (WebCore::HTMLCollection::rootNode):
 124 Inline for performance reasons and consistency with CachedLiveNodeList.
 125
 126 (WebCore::HTMLCollection::memoryCost):
 127 Make virtual and move part of the implementation to the
 128 CachedHTMLCollection subclass to compute the cost of the
 129 CollectionIndexCache.
 130
 131 (WebCore::HTMLCollection::invalidateCache):
 132 Move part of the implementation to the subclass to invalidate the
 133 CollectionIndexCache.
 134
 135 * html/HTMLFieldSetElement.cpp:
 136 (WebCore::HTMLFieldSetElement::elements):
 137
 138 * html/HTMLFormControlsCollection.cpp:
 139 * html/HTMLFormControlsCollection.h:
 140 Subclass CachedHTMLCollection instead of HTMLCollection.
 141 customElementAfter() no longer needs to be virtual as it
 142 is called directly by CachedHTMLCollection on the subclass.
 143
 144 * html/HTMLFormElement.cpp:
 145 (WebCore::HTMLFormElement::elements):
 146 * html/HTMLMapElement.cpp:
 147 (WebCore::HTMLMapElement::areas):
 148 Call NodeListsNodeData::addCachedCollection() directly.
 149
 150 * html/HTMLNameCollection.cpp:
 151 * html/HTMLNameCollection.h:
 152 Subclass CachedHTMLCollection instead of HTMLCollection.
 153
 154 * html/HTMLOptionsCollection.cpp:
 155 * html/HTMLOptionsCollection.h:
 156 Subclass CachedHTMLCollection instead of HTMLCollection.
 157
 158 * html/HTMLSelectElement.cpp:
 159 (WebCore::HTMLSelectElement::selectedOptions):
 160 (WebCore::HTMLSelectElement::options):
 161 * html/HTMLTableElement.cpp:
 162 (WebCore::HTMLTableElement::rows):
 163 (WebCore::HTMLTableElement::tBodies):
 164 * html/HTMLTableRowElement.cpp:
 165 (WebCore::HTMLTableRowElement::cells):
 166 Call NodeListsNodeData::addCachedCollection() directly.
 167
 168 * html/HTMLTableRowsCollection.cpp:
 169 * html/HTMLTableRowsCollection.h:
 170 Subclass CachedHTMLCollection instead of HTMLCollection.
 171 customElementAfter() no longer needs to be virtual as it
 172 is called directly by CachedHTMLCollection on the subclass.
 173
 174 * html/HTMLTableSectionElement.cpp:
 175 (WebCore::HTMLTableSectionElement::rows):
 176 Call NodeListsNodeData::addCachedCollection() directly.
 177
11782015-08-12 Antti Koivisto <antti@apple.com>
2179
3180 CachedResource leak in validation code

Source/WebCore/CMakeLists.txt

@@set(WebCore_SOURCES
16081608 html/FormAssociatedElement.cpp
16091609 html/FormController.cpp
16101610 html/FormDataList.cpp
 1611 html/GenericCachedHTMLCollection.cpp
16111612 html/HTMLAllCollection.cpp
16121613 html/HTMLAnchorElement.cpp
16131614 html/HTMLAppletElement.cpp

Source/WebCore/WebCore.vcxproj/WebCore.vcxproj

1610716107 <ClCompile Include="..\html\FormController.cpp" />
1610816108 <ClCompile Include="..\html\FormDataList.cpp" />
1610916109 <ClCompile Include="..\html\FTPDirectoryDocument.cpp" />
 16110 <ClCompile Include="..\html\GenericCachedHTMLCollection.cpp" />
1611016111 <ClCompile Include="..\html\HiddenInputType.cpp" />
1611116112 <ClCompile Include="..\html\HTMLAllCollection.cpp" />
1611216113 <ClCompile Include="..\html\HTMLAnchorElement.cpp">

Source/WebCore/WebCore.xcodeproj/project.pbxproj

16851685 46C83EFE1A9BBE2900A79A41 /* GeoNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 46C83EFC1A9BBE2900A79A41 /* GeoNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
16861686 46DB7D571B20FE46005651B2 /* VNodeTrackerCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DB7D561B20FE3C005651B2 /* VNodeTrackerCocoa.cpp */; };
16871687 46DBB6501AB8C96F00D9A813 /* PowerObserverMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 46DBB64E1AB8C96F00D9A813 /* PowerObserverMac.h */; };
 1688 46EBEA021B7D4D6500BE4941 /* CollectionTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = 46EBEA011B7D4D5D00BE4941 /* CollectionTraversal.h */; };
16881689 46F3E3F91B2109000087ED13 /* VNodeTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DB7D581B20FE58005651B2 /* VNodeTracker.cpp */; };
16891690 46F3E3FA1B2109100087ED13 /* VNodeTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 46DB7D591B20FE58005651B2 /* VNodeTracker.h */; settings = {ATTRIBUTES = (Private, ); }; };
16901691 46FCB6181A70820E00C5A21E /* DiagnosticLoggingKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = CD37B37515C1A7E1006DC898 /* DiagnosticLoggingKeys.h */; settings = {ATTRIBUTES = (Private, ); }; };

26692670 82AB1776125C826700C5069D /* InspectorResourceAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 82AB1772125C826700C5069D /* InspectorResourceAgent.h */; };
26702671 82E3D8DE122EA0D1003AE5BC /* CSSPropertySourceData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82E3D8DC122EA0D1003AE5BC /* CSSPropertySourceData.cpp */; };
26712672 82E3D8DF122EA0D1003AE5BC /* CSSPropertySourceData.h in Headers */ = {isa = PBXBuildFile; fileRef = 82E3D8DD122EA0D1003AE5BC /* CSSPropertySourceData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2673 830030F51B7D33B500ED3AAC /* GenericCachedHTMLCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 830030F31B7D33A600ED3AAC /* GenericCachedHTMLCollection.cpp */; };
 2674 830030F61B7D33B500ED3AAC /* GenericCachedHTMLCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 830030F41B7D33A600ED3AAC /* GenericCachedHTMLCollection.h */; };
 2675 830030F81B7D3B7800ED3AAC /* CachedHTMLCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 830030F71B7D398800ED3AAC /* CachedHTMLCollection.h */; };
 2676 831D48C01B7D9A52006DE39A /* ClassNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 831D48BE1B7D9A46006DE39A /* ClassNodeList.cpp */; };
 2677 831D48C11B7D9A52006DE39A /* ClassNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = 831D48BF1B7D9A46006DE39A /* ClassNodeList.h */; };
26722678 832B843419D8E55100B26055 /* SVGAnimateElementBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 832B843319D8E55100B26055 /* SVGAnimateElementBase.h */; };
26732679 832B843619D8E57400B26055 /* SVGAnimateElementBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 832B843519D8E57400B26055 /* SVGAnimateElementBase.cpp */; };
26742680 83520C7E1A71BFCC006BD2AA /* CSSFontFamily.h in Headers */ = {isa = PBXBuildFile; fileRef = 83520C7D1A71BFCC006BD2AA /* CSSFontFamily.h */; };

54105416 BC8BF15A1058141800A40A07 /* UserStyleSheetTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8BF1591058141800A40A07 /* UserStyleSheetTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
54115417 BC8C8FAD0DDCD31B00B592F4 /* RenderStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8C8FAB0DDCD31B00B592F4 /* RenderStyle.cpp */; };
54125418 BC8C8FAE0DDCD31B00B592F4 /* RenderStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = BC8C8FAC0DDCD31B00B592F4 /* RenderStyle.h */; settings = {ATTRIBUTES = (Private, ); }; };
5413  BC904B760D10998F00680D32 /* ClassNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC904B720D10998F00680D32 /* ClassNodeList.cpp */; };
5414  BC904B770D10998F00680D32 /* ClassNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC904B730D10998F00680D32 /* ClassNodeList.h */; };
54155419 BC926F800C0552470082776B /* JSHTMLFrameSetElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC926F7E0C0552470082776B /* JSHTMLFrameSetElement.cpp */; };
54165420 BC926F810C0552470082776B /* JSHTMLFrameSetElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC926F7F0C0552470082776B /* JSHTMLFrameSetElement.h */; };
54175421 BC9439C3116CF4940048C750 /* JSNodeCustom.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9439C2116CF4940048C750 /* JSNodeCustom.h */; settings = {ATTRIBUTES = (Private, ); }; };

89248928 46DB7D581B20FE58005651B2 /* VNodeTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VNodeTracker.cpp; sourceTree = "<group>"; };
89258929 46DB7D591B20FE58005651B2 /* VNodeTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VNodeTracker.h; sourceTree = "<group>"; };
89268930 46DBB64E1AB8C96F00D9A813 /* PowerObserverMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PowerObserverMac.h; sourceTree = "<group>"; };
 8931 46EBEA011B7D4D5D00BE4941 /* CollectionTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionTraversal.h; sourceTree = "<group>"; };
89278932 490707E41219C04300D90E51 /* ANGLEWebKitBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ANGLEWebKitBridge.cpp; sourceTree = "<group>"; };
89288933 490707E51219C04300D90E51 /* ANGLEWebKitBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANGLEWebKitBridge.h; sourceTree = "<group>"; };
89298934 49291E4A134172C800E753DE /* ImageRenderingMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageRenderingMode.h; sourceTree = "<group>"; };

1002410029 82AB1772125C826700C5069D /* InspectorResourceAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorResourceAgent.h; sourceTree = "<group>"; };
1002510030 82E3D8DC122EA0D1003AE5BC /* CSSPropertySourceData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertySourceData.cpp; sourceTree = "<group>"; };
1002610031 82E3D8DD122EA0D1003AE5BC /* CSSPropertySourceData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPropertySourceData.h; sourceTree = "<group>"; };
 10032 830030F31B7D33A600ED3AAC /* GenericCachedHTMLCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericCachedHTMLCollection.cpp; sourceTree = "<group>"; };
 10033 830030F41B7D33A600ED3AAC /* GenericCachedHTMLCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericCachedHTMLCollection.h; sourceTree = "<group>"; };
 10034 830030F71B7D398800ED3AAC /* CachedHTMLCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedHTMLCollection.h; sourceTree = "<group>"; };
 10035 831D48BE1B7D9A46006DE39A /* ClassNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassNodeList.cpp; sourceTree = "<group>"; };
 10036 831D48BF1B7D9A46006DE39A /* ClassNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassNodeList.h; sourceTree = "<group>"; };
1002710037 832B843319D8E55100B26055 /* SVGAnimateElementBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimateElementBase.h; sourceTree = "<group>"; };
1002810038 832B843519D8E57400B26055 /* SVGAnimateElementBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimateElementBase.cpp; sourceTree = "<group>"; };
1002910039 83520C7D1A71BFCC006BD2AA /* CSSFontFamily.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSFontFamily.h; sourceTree = "<group>"; };

1299213002 BC8BF1591058141800A40A07 /* UserStyleSheetTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserStyleSheetTypes.h; sourceTree = "<group>"; };
1299313003 BC8C8FAB0DDCD31B00B592F4 /* RenderStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderStyle.cpp; sourceTree = "<group>"; };
1299413004 BC8C8FAC0DDCD31B00B592F4 /* RenderStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderStyle.h; sourceTree = "<group>"; };
12995  BC904B720D10998F00680D32 /* ClassNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassNodeList.cpp; sourceTree = "<group>"; };
12996  BC904B730D10998F00680D32 /* ClassNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassNodeList.h; sourceTree = "<group>"; };
1299713005 BC926F7E0C0552470082776B /* JSHTMLFrameSetElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLFrameSetElement.cpp; sourceTree = "<group>"; };
1299813006 BC926F7F0C0552470082776B /* JSHTMLFrameSetElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLFrameSetElement.h; sourceTree = "<group>"; };
1299913007 BC9439C2116CF4940048C750 /* JSNodeCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSNodeCustom.h; sourceTree = "<group>"; };

1816218170 F55B3D7A1251F12D003EF269 /* BaseTextInputType.h */,
1816318171 F55B3D7B1251F12D003EF269 /* ButtonInputType.cpp */,
1816418172 F55B3D7C1251F12D003EF269 /* ButtonInputType.h */,
 18173 830030F71B7D398800ED3AAC /* CachedHTMLCollection.h */,
1816518174 F55B3D7D1251F12D003EF269 /* CheckboxInputType.cpp */,
1816618175 F55B3D7E1251F12D003EF269 /* CheckboxInputType.h */,
1816718176 4ACBC0BC12713CBD0094F9B2 /* ClassList.cpp */,
1816818177 4ACBC0BD12713CBD0094F9B2 /* ClassList.h */,
 18178 46EBEA011B7D4D5D00BE4941 /* CollectionTraversal.h */,
1816918179 93C441FF0F813AE100C1A634 /* CollectionType.h */,
1817018180 BC29935C17A1DD5800BCE880 /* ColorInputType.cpp */,
1817118181 F55B3D801251F12D003EF269 /* ColorInputType.h */,

1820018210 9B50B1DC17CD4C0F0087F63C /* FormNamedItem.h */,
1820118211 97205AAD123928CA00B17380 /* FTPDirectoryDocument.cpp */,
1820218212 97205AAE123928CA00B17380 /* FTPDirectoryDocument.h */,
 18213 830030F31B7D33A600ED3AAC /* GenericCachedHTMLCollection.cpp */,
 18214 830030F41B7D33A600ED3AAC /* GenericCachedHTMLCollection.h */,
1820318215 F55B3D8B1251F12D003EF269 /* HiddenInputType.cpp */,
1820418216 F55B3D8C1251F12D003EF269 /* HiddenInputType.h */,
1820518217 BC97E239109144950010D361 /* HTMLAllCollection.cpp */,

2315323165 83D26D3C1AFDCC50001B3873 /* ChildNode.idl */,
2315423166 A818721A0977D3C0005826D9 /* ChildNodeList.cpp */,
2315523167 A81872150977D3C0005826D9 /* ChildNodeList.h */,
23156  BC904B720D10998F00680D32 /* ClassNodeList.cpp */,
23157  BC904B730D10998F00680D32 /* ClassNodeList.h */,
 23168 831D48BE1B7D9A46006DE39A /* ClassNodeList.cpp */,
 23169 831D48BF1B7D9A46006DE39A /* ClassNodeList.h */,
2315823170 BCC065770F3CE1B700CD2D87 /* ClientRect.cpp */,
2315923171 BCC065780F3CE1B700CD2D87 /* ClientRect.h */,
2316023172 BCC065790F3CE1B700CD2D87 /* ClientRect.idl */,

2417024182 14D823520AF92A790004F057 /* Chrome.h in Headers */,
2417124183 14D824080AF93AEB0004F057 /* ChromeClient.h in Headers */,
2417224184 4ACBC0BF12713CBD0094F9B2 /* ClassList.h in Headers */,
24173  BC904B770D10998F00680D32 /* ClassNodeList.h in Headers */,
2417424185 BCC0657E0F3CE1B700CD2D87 /* ClientRect.h in Headers */,
2417524186 BCC065810F3CE1B700CD2D87 /* ClientRectList.h in Headers */,
2417624187 85031B400A44EFC700F992E0 /* ClipboardEvent.h in Headers */,

2444224453 8372DB311A6780A800C697C5 /* DiagnosticLoggingResultType.h in Headers */,
2444324454 CECADFC7153778FF00E37068 /* DictationAlternative.h in Headers */,
2444424455 CECADFC9153778FF00E37068 /* DictationCommand.h in Headers */,
 24456 46EBEA021B7D4D6500BE4941 /* CollectionTraversal.h in Headers */,
2444524457 D0BD4F5D1408850F006839B6 /* DictationCommandIOS.h in Headers */,
2444624458 15145B901B3A1CE000662BF7 /* MediaDeviceInfo.h in Headers */,
2444724459 316023F01532C40C00D50FF4 /* Dictionary.h in Headers */,

2454724559 85E711960AC5D5350053270F /* DOMDocumentTypeInternal.h in Headers */,
2454824560 8518DCE90A9CC80D0091B7A6 /* DOMDOMImplementation.h in Headers */,
2454924561 85E711970AC5D5350053270F /* DOMDOMImplementationInternal.h in Headers */,
 24562 831D48C11B7D9A52006DE39A /* ClassNodeList.h in Headers */,
2455024563 52CCA9E815E3F64C0053C77F /* DOMDOMNamedFlowCollection.h in Headers */,
2455124564 52CCA9EA15E3F64C0053C77F /* DOMDOMNamedFlowCollectionInternal.h in Headers */,
2455224565 2D9A247415B9C2E300D34527 /* DOMDOMSecurityPolicy.h in Headers */,

2562925642 FDA15EB212B03EE1003A583A /* JSPannerNode.h in Headers */,
2563025643 8A9A587511E84C81008ACFD1 /* JSPerformance.h in Headers */,
2563125644 8A9A587111E84C36008ACFD1 /* JSPerformanceNavigation.h in Headers */,
 25645 830030F61B7D33B500ED3AAC /* GenericCachedHTMLCollection.h in Headers */,
2563225646 8A9A588811E84F37008ACFD1 /* JSPerformanceTiming.h in Headers */,
2563325647 FDEA6247152102FC00479DF0 /* JSPeriodicWave.h in Headers */,
2563425648 93B70D6C09EB0C7C009D8468 /* JSPluginElementFunctions.h in Headers */,

2696826982 B2227A510D00BF220071B782 /* SVGNumberList.h in Headers */,
2696926983 B2227A540D00BF220071B782 /* SVGPaint.h in Headers */,
2697026984 B2227A570D00BF220071B782 /* SVGParserUtilities.h in Headers */,
 26985 830030F81B7D3B7800ED3AAC /* CachedHTMLCollection.h in Headers */,
2697126986 2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */,
2697226987 84C6784D1214814700A92902 /* SVGPathBlender.h in Headers */,
2697326988 8476C9EB11DF6A2900555B02 /* SVGPathBuilder.h in Headers */,

2796327978 14D8238B0AF92DF60004F057 /* Chrome.cpp in Sources */,
2796427979 ABAF22080C03B1C700B0BCF0 /* ChromeMac.mm in Sources */,
2796527980 4ACBC0BE12713CBD0094F9B2 /* ClassList.cpp in Sources */,
27966  BC904B760D10998F00680D32 /* ClassNodeList.cpp in Sources */,
2796727981 BCC0657D0F3CE1B700CD2D87 /* ClientRect.cpp in Sources */,
2796827982 BCC065800F3CE1B700CD2D87 /* ClientRectList.cpp in Sources */,
2796927983 85031B3F0A44EFC700F992E0 /* ClipboardEvent.cpp in Sources */,

2897028984 A9C6E64C0D7465E7006442E9 /* JSDOMPluginArrayCustom.cpp in Sources */,
2897128985 A9C6E64D0D7465E7006442E9 /* JSDOMPluginCustom.cpp in Sources */,
2897228986 E172AF8F1811BC3700FBADB9 /* JSDOMPromise.cpp in Sources */,
 28987 831D48C01B7D9A52006DE39A /* ClassNodeList.cpp in Sources */,
2897328988 BC5A86B50C3367E800EEA649 /* JSDOMSelection.cpp in Sources */,
2897428989 4ACBC0CA12713D0A0094F9B2 /* JSDOMSettableTokenList.cpp in Sources */,
2897528990 C5137CF211A58378004ADB99 /* JSDOMStringList.cpp in Sources */,

2926229277 07969DBD17D14151007FF842 /* JSRTCSessionDescriptionCallback.cpp in Sources */,
2926329278 07D07B141834158800ABDD3C /* JSRTCSessionDescriptionCustom.cpp in Sources */,
2926429279 07969DBF17D14151007FF842 /* JSRTCStatsCallback.cpp in Sources */,
 29280 830030F51B7D33B500ED3AAC /* GenericCachedHTMLCollection.cpp in Sources */,
2926529281 07969DC117D14151007FF842 /* JSRTCStatsReport.cpp in Sources */,
2926629282 07969DC317D14151007FF842 /* JSRTCStatsResponse.cpp in Sources */,
2926729283 07DC5FD417D3EEE90099F890 /* JSRTCStatsResponseCustom.cpp in Sources */,

Source/WebCore/dom/ContainerNode.cpp

3232#include "Editor.h"
3333#include "FloatRect.h"
3434#include "FrameView.h"
 35#include "GenericCachedHTMLCollection.h"
3536#include "HTMLFormControlsCollection.h"
3637#include "HTMLOptionsCollection.h"
3738#include "HTMLTableRowsCollection.h"

@@RefPtr<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name)
902903
903904Ref<HTMLCollection> ContainerNode::children()
904905{
905  return ensureCachedHTMLCollection(NodeChildren);
 906 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<NodeChildren>::traversalType>>(*this, NodeChildren);
906907}
907908
908909Element* ContainerNode::firstElementChild() const

@@void ContainerNode::prepend(Vector<NodeOrString>&& nodeOrStringVector, Exception
939940 insertBefore(node.release(), firstChild(), ec);
940941}
941942
942 Ref<HTMLCollection> ContainerNode::ensureCachedHTMLCollection(CollectionType type)
943 {
944  if (HTMLCollection* collection = cachedHTMLCollection(type))
945  return *collection;
946 
947  if (type == TableRows)
948  return ensureRareData().ensureNodeLists().addCachedCollection<HTMLTableRowsCollection>(downcast<HTMLTableElement>(*this), type);
949  else if (type == SelectOptions)
950  return ensureRareData().ensureNodeLists().addCachedCollection<HTMLOptionsCollection>(downcast<HTMLSelectElement>(*this), type);
951  else if (type == FormControls) {
952  ASSERT(hasTagName(HTMLNames::formTag) || hasTagName(HTMLNames::fieldsetTag));
953  return ensureRareData().ensureNodeLists().addCachedCollection<HTMLFormControlsCollection>(*this, type);
954  }
955  return ensureRareData().ensureNodeLists().addCachedCollection<HTMLCollection>(*this, type);
956 }
957 
958943HTMLCollection* ContainerNode::cachedHTMLCollection(CollectionType type)
959944{
960945 return hasRareData() && rareData()->nodeLists() ? rareData()->nodeLists()->cachedCollection<HTMLCollection>(type) : nullptr;

Source/WebCore/dom/ContainerNode.h

@@protected:
169169 void setFirstChild(Node* child) { m_firstChild = child; }
170170 void setLastChild(Node* child) { m_lastChild = child; }
171171
172  Ref<HTMLCollection> ensureCachedHTMLCollection(CollectionType);
173172 HTMLCollection* cachedHTMLCollection(CollectionType);
174173
175174private:

Source/WebCore/dom/Document.cpp

6363#include "FrameLoader.h"
6464#include "FrameLoaderClient.h"
6565#include "FrameView.h"
 66#include "GenericCachedHTMLCollection.h"
6667#include "HTMLAllCollection.h"
6768#include "HTMLAnchorElement.h"
6869#include "HTMLBaseElement.h"
6970#include "HTMLBodyElement.h"
7071#include "HTMLCanvasElement.h"
71 #include "HTMLCollection.h"
7272#include "HTMLDocument.h"
7373#include "HTMLElementFactory.h"
7474#include "HTMLFormControlElement.h"

@@bool Document::hasSVGRootNode() const
47724772 return documentElement() && documentElement()->hasTagName(SVGNames::svgTag);
47734773}
47744774
4775 Ref<HTMLCollection> Document::ensureCachedCollection(CollectionType type)
 4775template <CollectionType collectionType>
 4776Ref<HTMLCollection> Document::ensureCachedCollection()
47764777{
4777  return ensureRareData().ensureNodeLists().addCachedCollection<HTMLCollection>(*this, type);
 4778 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<collectionType>::traversalType>>(*this, collectionType);
47784779}
47794780
47804781Ref<HTMLCollection> Document::images()
47814782{
4782  return ensureCachedCollection(DocImages);
 4783 return ensureCachedCollection<DocImages>();
47834784}
47844785
47854786Ref<HTMLCollection> Document::applets()
47864787{
4787  return ensureCachedCollection(DocApplets);
 4788 return ensureCachedCollection<DocApplets>();
47884789}
47894790
47904791Ref<HTMLCollection> Document::embeds()
47914792{
4792  return ensureCachedCollection(DocEmbeds);
 4793 return ensureCachedCollection<DocEmbeds>();
47934794}
47944795
47954796Ref<HTMLCollection> Document::plugins()
47964797{
47974798 // This is an alias for embeds() required for the JS DOM bindings.
4798  return ensureCachedCollection(DocEmbeds);
 4799 return ensureCachedCollection<DocEmbeds>();
47994800}
48004801
48014802Ref<HTMLCollection> Document::scripts()
48024803{
4803  return ensureCachedCollection(DocScripts);
 4804 return ensureCachedCollection<DocScripts>();
48044805}
48054806
48064807Ref<HTMLCollection> Document::links()
48074808{
4808  return ensureCachedCollection(DocLinks);
 4809 return ensureCachedCollection<DocLinks>();
48094810}
48104811
48114812Ref<HTMLCollection> Document::forms()
48124813{
4813  return ensureCachedCollection(DocForms);
 4814 return ensureCachedCollection<DocForms>();
48144815}
48154816
48164817Ref<HTMLCollection> Document::anchors()
48174818{
4818  return ensureCachedCollection(DocAnchors);
 4819 return ensureCachedCollection<DocAnchors>();
48194820}
48204821
48214822Ref<HTMLCollection> Document::all()

Source/WebCore/dom/Document.h

@@class HTMLIFrameElement;
113113class HTMLImageElement;
114114class HTMLMapElement;
115115class HTMLMediaElement;
116 class HTMLNameCollection;
117116class HTMLScriptElement;
118117class HitTestRequest;
119118class HitTestResult;

@@private:
13451344
13461345 Node* nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint = nullptr);
13471346
1348  Ref<HTMLCollection> ensureCachedCollection(CollectionType);
 1347 template <CollectionType collectionType>
 1348 Ref<HTMLCollection> ensureCachedCollection();
13491349
13501350#if ENABLE(FULLSCREEN_API)
13511351 void dispatchFullScreenChangeOrErrorEvent(Deque<RefPtr<Node>>&, const AtomicString& eventName, bool shouldNotifyMediaElement);

Source/WebCore/dom/ElementChildIterator.h

@@public:
4141
4242 ElementChildIterator(const ContainerNode& parent);
4343 ElementChildIterator(const ContainerNode& parent, ElementType* current);
 44 ElementChildIterator& operator--();
4445 ElementChildIterator& operator++();
4546};
4647

@@public:
5556
5657 ElementChildConstIterator(const ContainerNode& parent);
5758 ElementChildConstIterator(const ContainerNode& parent, const ElementType* current);
 59 ElementChildConstIterator& operator--();
5860 ElementChildConstIterator& operator++();
5961};
6062

@@inline ElementChildIterator<ElementType>::ElementChildIterator(const ContainerNo
108110}
109111
110112template <typename ElementType>
 113inline ElementChildIterator<ElementType>& ElementChildIterator<ElementType>::operator--()
 114{
 115 return static_cast<ElementChildIterator<ElementType>&>(ElementIterator<ElementType>::traversePreviousSibling());
 116}
 117
 118template <typename ElementType>
111119inline ElementChildIterator<ElementType>& ElementChildIterator<ElementType>::operator++()
112120{
113121 return static_cast<ElementChildIterator<ElementType>&>(ElementIterator<ElementType>::traverseNextSibling());

@@inline ElementChildConstIterator<ElementType>::ElementChildConstIterator(const C
128136}
129137
130138template <typename ElementType>
 139inline ElementChildConstIterator<ElementType>& ElementChildConstIterator<ElementType>::operator--()
 140{
 141 return static_cast<ElementChildConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traversePreviousSibling());
 142}
 143
 144
 145template <typename ElementType>
131146inline ElementChildConstIterator<ElementType>& ElementChildConstIterator<ElementType>::operator++()
132147{
133148 return static_cast<ElementChildConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traverseNextSibling());

Source/WebCore/dom/LiveNodeList.h

2525#define LiveNodeList_h
2626
2727#include "CollectionIndexCache.h"
 28#include "CollectionTraversal.h"
2829#include "CollectionType.h"
2930#include "Document.h"
3031#include "ElementDescendantIterator.h"

@@class CachedLiveNodeList : public LiveNodeList {
8081public:
8182 virtual ~CachedLiveNodeList();
8283
83  virtual unsigned length() const override final;
84  virtual Node* item(unsigned offset) const override final;
 84 unsigned length() const override final { return m_indexCache.nodeCount(nodeList()); }
 85 Node* item(unsigned offset) const override final { return m_indexCache.nodeAt(nodeList(), offset); }
8586
8687 // For CollectionIndexCache
87  ElementDescendantIterator collectionBegin() const;
88  ElementDescendantIterator collectionLast() const;
 88 ElementDescendantIterator collectionBegin() const { return Traversal::begin(nodeList(), rootNode()); }
 89 ElementDescendantIterator collectionLast() const { return Traversal::last(nodeList(), rootNode()); }
8990 ElementDescendantIterator collectionEnd() const { return ElementDescendantIterator(); }
90  void collectionTraverseForward(ElementDescendantIterator&, unsigned count, unsigned& traversedCount) const;
91  void collectionTraverseBackward(ElementDescendantIterator&, unsigned count) const;
 91 void collectionTraverseForward(ElementDescendantIterator& current, unsigned count, unsigned& traversedCount) const { Traversal::traverseForward(nodeList(), current, count, traversedCount); }
 92 void collectionTraverseBackward(ElementDescendantIterator& current, unsigned count) const { Traversal::traverseBackward(nodeList(), current, count); }
9293 bool collectionCanTraverseBackward() const { return true; }
9394 void willValidateIndexCache() const;
9495
9596 virtual void invalidateCache(Document&) const override final;
96  virtual size_t memoryCost() const override final;
 97 virtual size_t memoryCost() const override final { return m_indexCache.memoryCost(); }
9798
9899protected:
99100 CachedLiveNodeList(ContainerNode& rootNode, NodeListInvalidationType);
100101
101102private:
 103 using Traversal = CollectionTraversal<CollectionTraversalType::Descendants>;
 104 NodeListType& nodeList() { return static_cast<NodeListType&>(*this); }
 105 const NodeListType& nodeList() const { return static_cast<const NodeListType&>(*this); }
 106
102107 ContainerNode& rootNode() const;
103108
104109 mutable CollectionIndexCache<NodeListType, ElementDescendantIterator> m_indexCache;

@@ALWAYS_INLINE bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationTyp
131136template <class NodeListType>
132137CachedLiveNodeList<NodeListType>::CachedLiveNodeList(ContainerNode& ownerNode, NodeListInvalidationType invalidationType)
133138 : LiveNodeList(ownerNode, invalidationType)
134  , m_indexCache(static_cast<NodeListType&>(*this))
 139 , m_indexCache(nodeList())
135140{
136141}
137142
138143template <class NodeListType>
139144CachedLiveNodeList<NodeListType>::~CachedLiveNodeList()
140145{
141  auto& nodeList = static_cast<const NodeListType&>(*this);
142  if (m_indexCache.hasValidCache(nodeList))
 146 if (m_indexCache.hasValidCache(nodeList()))
143147 document().unregisterNodeListForInvalidation(*this);
144148}
145149
146150template <class NodeListType>
147151inline ContainerNode& CachedLiveNodeList<NodeListType>::rootNode() const
148152{
149  if (static_cast<const NodeListType&>(*this).isRootedAtDocument() && ownerNode().inDocument())
 153 if (nodeList().isRootedAtDocument() && ownerNode().inDocument())
150154 return ownerNode().document();
151155
152156 return ownerNode();
153157}
154158
155159template <class NodeListType>
156 ElementDescendantIterator CachedLiveNodeList<NodeListType>::collectionBegin() const
157 {
158  auto& nodeList = static_cast<const NodeListType&>(*this);
159  auto descendants = elementDescendants(rootNode());
160  auto end = descendants.end();
161  for (auto it = descendants.begin(); it != end; ++it) {
162  if (nodeList.elementMatches(*it))
163  return it;
164  }
165  return end;
166 }
167 
168 template <class NodeListType>
169 ElementDescendantIterator CachedLiveNodeList<NodeListType>::collectionLast() const
170 {
171  auto& nodeList = static_cast<const NodeListType&>(*this);
172  auto descendants = elementDescendants(rootNode());
173  auto end = descendants.end();
174  for (auto it = descendants.last(); it != end; --it) {
175  if (nodeList.elementMatches(*it))
176  return it;
177  }
178  return end;
179 }
180 
181 template <class NodeListType>
182 void CachedLiveNodeList<NodeListType>::collectionTraverseForward(ElementDescendantIterator& current, unsigned count, unsigned& traversedCount) const
183 {
184  auto& nodeList = static_cast<const NodeListType&>(*this);
185  ASSERT(nodeList.elementMatches(*current));
186  auto end = collectionEnd();
187  for (traversedCount = 0; traversedCount < count; ++traversedCount) {
188  do {
189  ++current;
190  if (current == end)
191  return;
192  } while (!nodeList.elementMatches(*current));
193  }
194 }
195 
196 template <class NodeListType>
197 void CachedLiveNodeList<NodeListType>::collectionTraverseBackward(ElementDescendantIterator& current, unsigned count) const
198 {
199  auto& nodeList = static_cast<const NodeListType&>(*this);
200  ASSERT(nodeList.elementMatches(*current));
201  auto end = collectionEnd();
202  for (; count; --count) {
203  do {
204  --current;
205  if (current == end)
206  return;
207  } while (!nodeList.elementMatches(*current));
208  }
209 }
210 
211 template <class NodeListType>
212160void CachedLiveNodeList<NodeListType>::willValidateIndexCache() const
213161{
214  document().registerNodeListForInvalidation(const_cast<NodeListType&>(static_cast<const NodeListType&>(*this)));
 162 document().registerNodeListForInvalidation(const_cast<CachedLiveNodeList<NodeListType>&>(*this));
215163}
216164
217165template <class NodeListType>
218166void CachedLiveNodeList<NodeListType>::invalidateCache(Document& document) const
219167{
220  auto& nodeList = static_cast<const NodeListType&>(*this);
221  if (!m_indexCache.hasValidCache(nodeList))
 168 if (!m_indexCache.hasValidCache(nodeList()))
222169 return;
223  document.unregisterNodeListForInvalidation(const_cast<NodeListType&>(nodeList));
224  m_indexCache.invalidate(nodeList);
225 }
226 
227 template <class NodeListType>
228 unsigned CachedLiveNodeList<NodeListType>::length() const
229 {
230  return m_indexCache.nodeCount(static_cast<const NodeListType&>(*this));
231 }
232 
233 template <class NodeListType>
234 Node* CachedLiveNodeList<NodeListType>::item(unsigned offset) const
235 {
236  return m_indexCache.nodeAt(static_cast<const NodeListType&>(*this), offset);
237 }
238 
239 template <class NodeListType>
240 size_t CachedLiveNodeList<NodeListType>::memoryCost() const
241 {
242  return m_indexCache.memoryCost();
 170 document.unregisterNodeListForInvalidation(const_cast<NodeListType&>(nodeList()));
 171 m_indexCache.invalidate(nodeList());
243172}
244173
245174} // namespace WebCore

Source/WebCore/html/CachedHTMLCollection.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef CachedHTMLCollection_h
 27#define CachedHTMLCollection_h
 28
 29#include "CollectionTraversal.h"
 30#include "HTMLCollection.h"
 31#include "HTMLElement.h"
 32
 33namespace WebCore {
 34
 35template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 36class CachedHTMLCollection : public HTMLCollection {
 37public:
 38 using Traversal = CollectionTraversal<traversalType>;
 39 using IteratorType = typename Traversal::IteratorType;
 40
 41 CachedHTMLCollection(ContainerNode& base, CollectionType);
 42
 43 virtual ~CachedHTMLCollection();
 44
 45 virtual unsigned length() const override final { return m_indexCache.nodeCount(collection()); }
 46 virtual Element* item(unsigned offset) const override final { return m_indexCache.nodeAt(collection(), offset); }
 47 virtual Element* namedItem(const AtomicString& name) const override;
 48 virtual size_t memoryCost() const override final { return m_indexCache.memoryCost() + HTMLCollection::memoryCost(); }
 49
 50 // For CollectionIndexCache; do not use elsewhere.
 51 IteratorType collectionBegin() const { return Traversal::begin(collection(), rootNode()); }
 52 IteratorType collectionLast() const { return Traversal::last(collection(), rootNode()); }
 53 IteratorType collectionEnd() const { return Traversal::end(rootNode()); }
 54 void collectionTraverseForward(IteratorType& current, unsigned count, unsigned& traversedCount) const { Traversal::traverseForward(collection(), current, count, traversedCount); }
 55 void collectionTraverseBackward(IteratorType& current, unsigned count) const { Traversal::traverseBackward(collection(), current, count); }
 56 bool collectionCanTraverseBackward() const { return traversalType != CollectionTraversalType::CustomForwardOnly; }
 57 void willValidateIndexCache() const;
 58
 59 virtual void invalidateCache(Document&) override;
 60
 61 bool elementMatches(Element&) const;
 62
 63private:
 64 HTMLCollectionClass& collection() { return static_cast<HTMLCollectionClass&>(*this); }
 65 const HTMLCollectionClass& collection() const { return static_cast<const HTMLCollectionClass&>(*this); }
 66
 67 mutable CollectionIndexCache<HTMLCollectionClass, IteratorType> m_indexCache;
 68};
 69
 70template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 71CachedHTMLCollection<HTMLCollectionClass, traversalType>::CachedHTMLCollection(ContainerNode& base, CollectionType collectionType)
 72 : HTMLCollection(base, collectionType)
 73 , m_indexCache(collection())
 74{ }
 75
 76template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 77CachedHTMLCollection<HTMLCollectionClass, traversalType>::~CachedHTMLCollection()
 78{
 79 if (m_indexCache.hasValidCache(collection()))
 80 document().unregisterCollection(*this);
 81}
 82
 83template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 84void CachedHTMLCollection<HTMLCollectionClass, traversalType>::willValidateIndexCache() const
 85{
 86 document().registerCollection(const_cast<CachedHTMLCollection<HTMLCollectionClass, traversalType>&>(*this));
 87}
 88
 89template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 90void CachedHTMLCollection<HTMLCollectionClass, traversalType>::invalidateCache(Document& document)
 91{
 92 HTMLCollection::invalidateCache(document);
 93 if (m_indexCache.hasValidCache(collection())) {
 94 document.unregisterCollection(*this);
 95 m_indexCache.invalidate(collection());
 96 }
 97}
 98
 99template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 100bool CachedHTMLCollection<HTMLCollectionClass, traversalType>::elementMatches(Element&) const
 101{
 102 ASSERT_NOT_REACHED();
 103 return false;
 104}
 105
 106static inline bool nameShouldBeVisibleInDocumentAll(HTMLElement& element)
 107{
 108 // The document.all collection returns only certain types of elements by name,
 109 // although it returns any type of element by id.
 110 return element.hasTagName(HTMLNames::appletTag)
 111 || element.hasTagName(HTMLNames::embedTag)
 112 || element.hasTagName(HTMLNames::formTag)
 113 || element.hasTagName(HTMLNames::imgTag)
 114 || element.hasTagName(HTMLNames::inputTag)
 115 || element.hasTagName(HTMLNames::objectTag)
 116 || element.hasTagName(HTMLNames::selectTag);
 117}
 118
 119static inline bool nameShouldBeVisibleInDocumentAll(Element& element)
 120{
 121 return is<HTMLElement>(element) && nameShouldBeVisibleInDocumentAll(downcast<HTMLElement>(element));
 122}
 123
 124template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 125Element* CachedHTMLCollection<HTMLCollectionClass, traversalType>::namedItem(const AtomicString& name) const
 126{
 127 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp
 128 // This method first searches for an object with a matching id
 129 // attribute. If a match is not found, the method then searches for an
 130 // object with a matching name attribute, but only on those elements
 131 // that are allowed a name attribute.
 132
 133 if (name.isEmpty())
 134 return nullptr;
 135
 136 ContainerNode& root = rootNode();
 137 if (traversalType != CollectionTraversalType::CustomForwardOnly && root.isInTreeScope()) {
 138 Element* candidate = nullptr;
 139
 140 TreeScope& treeScope = root.treeScope();
 141 if (treeScope.hasElementWithId(*name.impl())) {
 142 if (!treeScope.containsMultipleElementsWithId(name))
 143 candidate = treeScope.getElementById(name);
 144 } else if (treeScope.hasElementWithName(*name.impl())) {
 145 if (!treeScope.containsMultipleElementsWithName(name)) {
 146 candidate = treeScope.getElementByName(name);
 147 if (candidate && type() == DocAll && !nameShouldBeVisibleInDocumentAll(*candidate))
 148 candidate = nullptr;
 149 }
 150 } else
 151 return nullptr;
 152
 153 if (candidate && collection().elementMatches(*candidate)) {
 154 if (traversalType == CollectionTraversalType::ChildrenOnly ? candidate->parentNode() == &root : candidate->isDescendantOf(&root))
 155 return candidate;
 156 }
 157 }
 158
 159 return HTMLCollection::namedItem(name);
 160}
 161
 162} // namespace WebCore
 163
 164#endif // CachedHTMLCollection_h
 165

Source/WebCore/html/CollectionTraversal.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef CollectionTraversal_h
 27#define CollectionTraversal_h
 28
 29#include "CollectionType.h"
 30#include "ElementChildIterator.h"
 31#include "ElementDescendantIterator.h"
 32
 33namespace WebCore {
 34
 35template <CollectionTraversalType traversalType>
 36struct CollectionTraversal { };
 37
 38template <>
 39struct CollectionTraversal<CollectionTraversalType::Descendants> {
 40 using IteratorType = ElementDescendantIterator;
 41
 42 static ElementDescendantIterator end(ContainerNode&) { return ElementDescendantIterator(); }
 43
 44 template <typename CollectionClass>
 45 static ElementDescendantIterator begin(const CollectionClass&, ContainerNode& rootNode);
 46
 47 template <typename CollectionClass>
 48 static ElementDescendantIterator last(const CollectionClass&, ContainerNode& rootNode);
 49
 50 template <typename CollectionClass>
 51 static void traverseForward(const CollectionClass&, ElementDescendantIterator& current, unsigned count, unsigned& traversedCount);
 52
 53 template <typename CollectionClass>
 54 static void traverseBackward(const CollectionClass&, ElementDescendantIterator& current, unsigned count);
 55};
 56
 57template <>
 58struct CollectionTraversal<CollectionTraversalType::ChildrenOnly> {
 59 using IteratorType = ElementChildIterator<Element>;
 60
 61 static ElementChildIterator<Element> end(ContainerNode& rootNode) { return ElementChildIterator<Element>(rootNode); }
 62
 63 template <typename CollectionClass>
 64 static ElementChildIterator<Element> begin(const CollectionClass&, ContainerNode& rootNode);
 65
 66 template <typename CollectionClass>
 67 static ElementChildIterator<Element> last(const CollectionClass&, ContainerNode& rootNode);
 68
 69 template <typename CollectionClass>
 70 static void traverseForward(const CollectionClass&, ElementChildIterator<Element>& current, unsigned count, unsigned& traversedCount);
 71
 72 template <typename CollectionClass>
 73 static void traverseBackward(const CollectionClass&, ElementChildIterator<Element>& current, unsigned count);
 74};
 75
 76template <>
 77struct CollectionTraversal<CollectionTraversalType::CustomForwardOnly> {
 78 using IteratorType = Element*;
 79
 80 static Element* end(ContainerNode&) { return nullptr; }
 81
 82 template <typename CollectionClass>
 83 static Element* begin(const CollectionClass&, ContainerNode&);
 84
 85 template <typename CollectionClass>
 86 static Element* last(const CollectionClass&, ContainerNode&);
 87
 88 template <typename CollectionClass>
 89 static void traverseForward(const CollectionClass&, Element*& current, unsigned count, unsigned& traversedCount);
 90
 91 template <typename CollectionClass>
 92 static void traverseBackward(const CollectionClass&, Element*&, unsigned count);
 93};
 94
 95template <typename CollectionClass>
 96inline ElementDescendantIterator CollectionTraversal<CollectionTraversalType::Descendants>::begin(const CollectionClass& collection, ContainerNode& rootNode)
 97{
 98 auto descendants = elementDescendants(rootNode);
 99 auto end = descendants.end();
 100 for (auto it = descendants.begin(); it != end; ++it) {
 101 if (collection.elementMatches(*it))
 102 return it;
 103 }
 104 return end;
 105}
 106
 107template <typename CollectionClass>
 108inline ElementChildIterator<Element> CollectionTraversal<CollectionTraversalType::ChildrenOnly>::begin(const CollectionClass& collection, ContainerNode& rootNode)
 109{
 110 auto children = childrenOfType<Element>(rootNode);
 111 auto end = children.end();
 112 for (auto it = children.begin(); it != end; ++it) {
 113 if (collection.elementMatches(*it))
 114 return it;
 115 }
 116 return end;
 117}
 118
 119template <typename CollectionClass>
 120inline Element* CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::begin(const CollectionClass& collection, ContainerNode&)
 121{
 122 return collection.customElementAfter(nullptr);
 123}
 124
 125template <typename CollectionClass>
 126inline ElementDescendantIterator CollectionTraversal<CollectionTraversalType::Descendants>::last(const CollectionClass& collection, ContainerNode& rootNode)
 127{
 128 auto descendants = elementDescendants(rootNode);
 129 auto end = descendants.end();
 130 for (auto it = descendants.last(); it != end; --it) {
 131 if (collection.elementMatches(*it))
 132 return it;
 133 }
 134 return end;
 135}
 136
 137template <typename CollectionClass>
 138inline ElementChildIterator<Element> CollectionTraversal<CollectionTraversalType::ChildrenOnly>::last(const CollectionClass& collection, ContainerNode& rootNode)
 139{
 140 auto children = childrenOfType<Element>(rootNode);
 141 auto end = children.end();
 142 ElementChildIterator<Element> last(rootNode, children.last());
 143 for (auto it = last; it != end; --it) {
 144 if (collection.elementMatches(*it))
 145 return it;
 146 }
 147 return end;
 148}
 149
 150template <typename CollectionClass>
 151inline Element* CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::last(const CollectionClass&, ContainerNode&)
 152{
 153 ASSERT_NOT_REACHED();
 154 return nullptr;
 155}
 156
 157template <typename CollectionClass>
 158inline void CollectionTraversal<CollectionTraversalType::Descendants>::traverseForward(const CollectionClass& collection, ElementDescendantIterator& current, unsigned count, unsigned& traversedCount)
 159{
 160 ASSERT(collection.elementMatches(*current));
 161 auto end = collection.collectionEnd();
 162 for (traversedCount = 0; traversedCount < count; ++traversedCount) {
 163 do {
 164 ++current;
 165 if (current == end)
 166 return;
 167 } while (!collection.elementMatches(*current));
 168 }
 169}
 170
 171template <typename CollectionClass>
 172inline void CollectionTraversal<CollectionTraversalType::ChildrenOnly>::traverseForward(const CollectionClass& collection, ElementChildIterator<Element>& current, unsigned count, unsigned& traversedCount)
 173{
 174 ASSERT(collection.elementMatches(*current));
 175 auto end = collection.collectionEnd();
 176 for (traversedCount = 0; traversedCount < count; ++traversedCount) {
 177 do {
 178 ++current;
 179 if (current == end)
 180 return;
 181 } while (!collection.elementMatches(*current));
 182 }
 183}
 184
 185template <typename CollectionClass>
 186inline void CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::traverseForward(const CollectionClass& collection, Element*& current, unsigned count, unsigned& traversedCount)
 187{
 188 Element* element = current;
 189 for (traversedCount = 0; traversedCount < count; ++traversedCount) {
 190 element = collection.customElementAfter(element);
 191 if (!element) {
 192 current = nullptr;
 193 return;
 194 }
 195 }
 196 current = element;
 197}
 198
 199template <typename CollectionClass>
 200inline void CollectionTraversal<CollectionTraversalType::Descendants>::traverseBackward(const CollectionClass& collection, ElementDescendantIterator& current, unsigned count)
 201{
 202 ASSERT(collection.elementMatches(*current));
 203 auto end = collection.collectionEnd();
 204 for (; count; --count) {
 205 do {
 206 --current;
 207 if (current == end)
 208 return;
 209 } while (!collection.elementMatches(*current));
 210 }
 211}
 212
 213template <typename CollectionClass>
 214inline void CollectionTraversal<CollectionTraversalType::ChildrenOnly>::traverseBackward(const CollectionClass& collection, ElementChildIterator<Element>& current, unsigned count)
 215{
 216 ASSERT(collection.elementMatches(*current));
 217 auto end = collection.collectionEnd();
 218 for (; count; --count) {
 219 do {
 220 --current;
 221 if (current == end)
 222 return;
 223 } while (!collection.elementMatches(*current));
 224 }
 225}
 226
 227template <typename CollectionClass>
 228inline void CollectionTraversal<CollectionTraversalType::CustomForwardOnly>::traverseBackward(const CollectionClass&, Element*&, unsigned count)
 229{
 230 UNUSED_PARAM(count);
 231 ASSERT_NOT_REACHED();
 232}
 233
 234} // namespace WebCore
 235
 236#endif // CollectionTraversal_h

Source/WebCore/html/CollectionType.h

@@enum CollectionType {
5353 FormControls
5454};
5555
56 } // namespace
 56enum class CollectionTraversalType { Descendants, ChildrenOnly, CustomForwardOnly };
 57template<CollectionType collectionType>
 58struct CollectionTypeTraits {
 59 static const CollectionTraversalType traversalType = CollectionTraversalType::Descendants;
 60};
 61
 62template<>
 63struct CollectionTypeTraits<NodeChildren> {
 64 static const CollectionTraversalType traversalType = CollectionTraversalType::ChildrenOnly;
 65};
 66
 67template<>
 68struct CollectionTypeTraits<TRCells> {
 69 static const CollectionTraversalType traversalType = CollectionTraversalType::ChildrenOnly;
 70};
 71
 72template<>
 73struct CollectionTypeTraits<TSectionRows> {
 74 static const CollectionTraversalType traversalType = CollectionTraversalType::ChildrenOnly;
 75};
 76
 77template<>
 78struct CollectionTypeTraits<TableTBodies> {
 79 static const CollectionTraversalType traversalType = CollectionTraversalType::ChildrenOnly;
 80};
 81
 82template<>
 83struct CollectionTypeTraits<TableRows> {
 84 static const CollectionTraversalType traversalType = CollectionTraversalType::CustomForwardOnly;
 85};
 86
 87template<>
 88struct CollectionTypeTraits<FormControls> {
 89 static const CollectionTraversalType traversalType = CollectionTraversalType::CustomForwardOnly;
 90};
 91
 92} // namespace WebCore
5793
5894#endif

Source/WebCore/html/GenericCachedHTMLCollection.cpp

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "GenericCachedHTMLCollection.h"
 28
 29#include "HTMLNames.h"
 30#include "HTMLObjectElement.h"
 31#include "HTMLOptionElement.h"
 32
 33namespace WebCore {
 34
 35using namespace HTMLNames;
 36
 37template <CollectionTraversalType traversalType>
 38bool GenericCachedHTMLCollection<traversalType>::elementMatches(Element& element) const
 39{
 40 switch (Base::type()) {
 41 case NodeChildren:
 42 return true;
 43 case DocImages:
 44 return element.hasTagName(imgTag);
 45 case DocScripts:
 46 return element.hasTagName(scriptTag);
 47 case DocForms:
 48 return element.hasTagName(formTag);
 49 case TableTBodies:
 50 return element.hasTagName(tbodyTag);
 51 case TRCells:
 52 return element.hasTagName(tdTag) || element.hasTagName(thTag);
 53 case TSectionRows:
 54 return element.hasTagName(trTag);
 55 case SelectedOptions:
 56 return is<HTMLOptionElement>(element) && downcast<HTMLOptionElement>(element).selected();
 57 case DataListOptions:
 58 if (is<HTMLOptionElement>(element)) {
 59 HTMLOptionElement& option = downcast<HTMLOptionElement>(element);
 60 if (!option.isDisabledFormControl() && !option.value().isEmpty())
 61 return true;
 62 }
 63 return false;
 64 case MapAreas:
 65 return element.hasTagName(areaTag);
 66 case DocApplets:
 67 return is<HTMLAppletElement>(element) || (is<HTMLObjectElement>(element) && downcast<HTMLObjectElement>(element).containsJavaApplet());
 68 case DocEmbeds:
 69 return element.hasTagName(embedTag);
 70 case DocLinks:
 71 return (element.hasTagName(aTag) || element.hasTagName(areaTag)) && element.fastHasAttribute(hrefAttr);
 72 case DocAnchors:
 73 return element.hasTagName(aTag) && element.fastHasAttribute(nameAttr);
 74 case DocAll:
 75 case DocumentNamedItems:
 76 case FormControls:
 77 case SelectOptions:
 78 case TableRows:
 79 case WindowNamedItems:
 80 break;
 81 }
 82 ASSERT_NOT_REACHED();
 83 return false;
 84}
 85template bool GenericCachedHTMLCollection<CollectionTraversalType::Descendants>::elementMatches(Element&) const;
 86template bool GenericCachedHTMLCollection<CollectionTraversalType::ChildrenOnly>::elementMatches(Element&) const;
 87template bool GenericCachedHTMLCollection<CollectionTraversalType::CustomForwardOnly>::elementMatches(Element&) const;
 88
 89} // namespace WebCore

Source/WebCore/html/GenericCachedHTMLCollection.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef GenericCachedHTMLCollection_h
 27#define GenericCachedHTMLCollection_h
 28
 29#include "CachedHTMLCollection.h"
 30
 31namespace WebCore {
 32
 33template <CollectionTraversalType traversalType>
 34class GenericCachedHTMLCollection final : public CachedHTMLCollection<GenericCachedHTMLCollection<traversalType>, traversalType> {
 35public:
 36 static Ref<GenericCachedHTMLCollection> create(ContainerNode& base, CollectionType collectionType)
 37 {
 38 return adoptRef(*new GenericCachedHTMLCollection(base, collectionType));
 39 }
 40
 41 bool elementMatches(Element&) const;
 42
 43private:
 44 using Base = CachedHTMLCollection<GenericCachedHTMLCollection<traversalType>, traversalType>;
 45 GenericCachedHTMLCollection(ContainerNode& base, CollectionType collectionType)
 46 : Base(base, collectionType)
 47 { }
 48};
 49
 50} // namespace WebCore
 51
 52#endif // GenericCachedHTMLCollection_h
 53

Source/WebCore/html/HTMLAllCollection.cpp

@@Ref<HTMLAllCollection> HTMLAllCollection::create(Document& document, CollectionT
3636}
3737
3838inline HTMLAllCollection::HTMLAllCollection(Document& document, CollectionType type)
39  : HTMLCollection(document, type)
 39 : CachedHTMLCollection<HTMLAllCollection, CollectionTypeTraits<DocAll>::traversalType>(document, type)
4040{
4141}
4242

Source/WebCore/html/HTMLAllCollection.h

2626#ifndef HTMLAllCollection_h
2727#define HTMLAllCollection_h
2828
29 #include "HTMLCollection.h"
 29#include "CachedHTMLCollection.h"
3030
3131namespace WebCore {
3232
33 class HTMLAllCollection final : public HTMLCollection {
 33class HTMLAllCollection final : public CachedHTMLCollection<HTMLAllCollection, CollectionTypeTraits<DocAll>::traversalType> {
3434public:
3535 static Ref<HTMLAllCollection> create(Document&, CollectionType);
3636
3737 Element* namedItemWithIndex(const AtomicString& name, unsigned index) const;
3838
 39 // For CachedHTMLCollection.
 40 bool elementMatches(Element&) const { return true; }
 41
3942private:
4043 HTMLAllCollection(Document&, CollectionType);
4144};

Source/WebCore/html/HTMLCollection.cpp

2323#include "config.h"
2424#include "HTMLCollection.h"
2525
26 #include "ElementTraversal.h"
27 #include "HTMLDocument.h"
28 #include "HTMLNameCollection.h"
 26#include "CachedHTMLCollection.h"
2927#include "HTMLNames.h"
30 #include "HTMLObjectElement.h"
31 #include "HTMLOptionElement.h"
3228#include "NodeRareData.h"
3329
3430namespace WebCore {
3531
3632using namespace HTMLNames;
3733
38 static bool shouldOnlyIncludeDirectChildren(CollectionType type)
39 {
40  switch (type) {
41  case DocAll:
42  case DocAnchors:
43  case DocApplets:
44  case DocEmbeds:
45  case DocForms:
46  case DocImages:
47  case DocLinks:
48  case DocScripts:
49  case DocumentNamedItems:
50  case MapAreas:
51  case TableRows:
52  case SelectOptions:
53  case SelectedOptions:
54  case DataListOptions:
55  case WindowNamedItems:
56  case FormControls:
57  return false;
58  case NodeChildren:
59  case TRCells:
60  case TSectionRows:
61  case TableTBodies:
62  return true;
63  }
64  ASSERT_NOT_REACHED();
65  return false;
66 }
67 
6834inline auto HTMLCollection::rootTypeFromCollectionType(CollectionType type) -> RootType
6935{
7036 switch (type) {

@@static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col
13197 return DoNotInvalidateOnAttributeChanges;
13298}
13399
134 HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, ElementTraversalType traversalType)
 100HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type)
135101 : m_ownerNode(ownerNode)
136  , m_indexCache(*this)
137102 , m_collectionType(type)
138103 , m_invalidationType(invalidationTypeExcludingIdAndNameAttributes(type))
139104 , m_rootType(rootTypeFromCollectionType(type))
140  , m_shouldOnlyIncludeDirectChildren(shouldOnlyIncludeDirectChildren(type))
141  , m_usesCustomForwardOnlyTraversal(traversalType == CustomForwardOnlyTraversal)
142105{
143106 ASSERT(m_rootType == static_cast<unsigned>(rootTypeFromCollectionType(type)));
144107 ASSERT(m_invalidationType == static_cast<unsigned>(invalidationTypeExcludingIdAndNameAttributes(type)));
145108 ASSERT(m_collectionType == static_cast<unsigned>(type));
146109}
147110
148 Ref<HTMLCollection> HTMLCollection::create(ContainerNode& base, CollectionType type)
149 {
150  return adoptRef(*new HTMLCollection(base, type));
151 }
152 
153111HTMLCollection::~HTMLCollection()
154112{
155  if (m_indexCache.hasValidCache(*this))
156  document().unregisterCollection(*this);
157113 if (hasNamedElementCache())
158114 document().collectionWillClearIdNameMap(*this);
 115
159116 // HTMLNameCollection removes cache by itself.
160117 if (type() != WindowNamedItems && type() != DocumentNamedItems)
161118 ownerNode().nodeLists()->removeCachedCollection(this);
162119}
163120
164 ContainerNode& HTMLCollection::rootNode() const
165 {
166  if (isRootedAtDocument() && ownerNode().inDocument())
167  return ownerNode().document();
168 
169  return ownerNode();
170 }
171 
172 static inline bool isMatchingHTMLElement(const HTMLCollection& collection, HTMLElement& element)
 121void HTMLCollection::invalidateCache(Document& document)
173122{
174  switch (collection.type()) {
175  case DocImages:
176  return element.hasTagName(imgTag);
177  case DocScripts:
178  return element.hasTagName(scriptTag);
179  case DocForms:
180  return element.hasTagName(formTag);
181  case TableTBodies:
182  return element.hasTagName(tbodyTag);
183  case TRCells:
184  return element.hasTagName(tdTag) || element.hasTagName(thTag);
185  case TSectionRows:
186  return element.hasTagName(trTag);
187  case SelectOptions:
188  return element.hasTagName(optionTag);
189  case SelectedOptions:
190  return is<HTMLOptionElement>(element) && downcast<HTMLOptionElement>(element).selected();
191  case DataListOptions:
192  if (is<HTMLOptionElement>(element)) {
193  HTMLOptionElement& option = downcast<HTMLOptionElement>(element);
194  if (!option.isDisabledFormControl() && !option.value().isEmpty())
195  return true;
196  }
197  return false;
198  case MapAreas:
199  return element.hasTagName(areaTag);
200  case DocApplets:
201  return is<HTMLAppletElement>(element) || (is<HTMLObjectElement>(element) && downcast<HTMLObjectElement>(element).containsJavaApplet());
202  case DocEmbeds:
203  return element.hasTagName(embedTag);
204  case DocLinks:
205  return (element.hasTagName(aTag) || element.hasTagName(areaTag)) && element.fastHasAttribute(hrefAttr);
206  case DocAnchors:
207  return element.hasTagName(aTag) && element.fastHasAttribute(nameAttr);
208  case DocumentNamedItems:
209  return downcast<DocumentNameCollection>(collection).elementMatches(element);
210  case DocAll:
211  case NodeChildren:
212  case WindowNamedItems:
213  case FormControls:
214  case TableRows:
215  break;
216  }
217  ASSERT_NOT_REACHED();
218  return false;
219 }
220 
221 static inline bool isMatchingElement(const HTMLCollection& collection, Element& element)
222 {
223  // Collection types that deal with any type of Elements, not just HTMLElements.
224  switch (collection.type()) {
225  case DocAll:
226  case NodeChildren:
227  return true;
228  case WindowNamedItems:
229  return downcast<WindowNameCollection>(collection).elementMatches(element);
230  default:
231  // Collection types that only deal with HTMLElements.
232  return is<HTMLElement>(element) && isMatchingHTMLElement(collection, downcast<HTMLElement>(element));
233  }
234 }
235 
236 static inline Element* previousElement(ContainerNode& base, Element& element, bool onlyIncludeDirectChildren)
237 {
238  return onlyIncludeDirectChildren ? ElementTraversal::previousSibling(element) : ElementTraversal::previous(element, &base);
239 }
240 
241 ALWAYS_INLINE Element* HTMLCollection::iterateForPreviousElement(Element* element) const
242 {
243  bool onlyIncludeDirectChildren = m_shouldOnlyIncludeDirectChildren;
244  ContainerNode& rootNode = this->rootNode();
245  for (; element; element = previousElement(rootNode, *element, onlyIncludeDirectChildren)) {
246  if (isMatchingElement(*this, *element))
247  return element;
248  }
249  return nullptr;
250 }
251 
252 static inline Element* firstMatchingElement(const HTMLCollection& collection, ContainerNode& root)
253 {
254  Element* element = ElementTraversal::firstWithin(root);
255  while (element && !isMatchingElement(collection, *element))
256  element = ElementTraversal::next(*element, &root);
257  return element;
258 }
259 
260 static inline Element* nextMatchingElement(const HTMLCollection& collection, Element& element, ContainerNode& root)
261 {
262  Element* next = &element;
263  do {
264  next = ElementTraversal::next(*next, &root);
265  } while (next && !isMatchingElement(collection, *next));
266  return next;
267 }
268 
269 unsigned HTMLCollection::length() const
270 {
271  return m_indexCache.nodeCount(*this);
272 }
273 
274 Element* HTMLCollection::item(unsigned offset) const
275 {
276  return m_indexCache.nodeAt(*this, offset);
277 }
278 
279 static inline bool nameShouldBeVisibleInDocumentAll(HTMLElement& element)
280 {
281  // The document.all collection returns only certain types of elements by name,
282  // although it returns any type of element by id.
283  return element.hasTagName(appletTag)
284  || element.hasTagName(embedTag)
285  || element.hasTagName(formTag)
286  || element.hasTagName(imgTag)
287  || element.hasTagName(inputTag)
288  || element.hasTagName(objectTag)
289  || element.hasTagName(selectTag);
290 }
291 
292 static inline bool nameShouldBeVisibleInDocumentAll(Element& element)
293 {
294  return is<HTMLElement>(element) && nameShouldBeVisibleInDocumentAll(downcast<HTMLElement>(element));
295 }
296 
297 static inline Element* firstMatchingChildElement(const HTMLCollection& nodeList, ContainerNode& root)
298 {
299  Element* element = ElementTraversal::firstWithin(root);
300  while (element && !isMatchingElement(nodeList, *element))
301  element = ElementTraversal::nextSibling(*element);
302  return element;
303 }
304 
305 static inline Element* nextMatchingSiblingElement(const HTMLCollection& nodeList, Element& element)
306 {
307  Element* next = &element;
308  do {
309  next = ElementTraversal::nextSibling(*next);
310  } while (next && !isMatchingElement(nodeList, *next));
311  return next;
312 }
313 
314 inline bool HTMLCollection::usesCustomForwardOnlyTraversal() const
315 {
316  return m_usesCustomForwardOnlyTraversal;
317 }
318 
319 inline Element* HTMLCollection::firstElement(ContainerNode& root) const
320 {
321  if (usesCustomForwardOnlyTraversal())
322  return customElementAfter(nullptr);
323  if (m_shouldOnlyIncludeDirectChildren)
324  return firstMatchingChildElement(*this, root);
325  return firstMatchingElement(*this, root);
326 }
327 
328 inline Element* HTMLCollection::traverseForward(Element& current, unsigned count, unsigned& traversedCount, ContainerNode& root) const
329 {
330  Element* element = &current;
331  if (usesCustomForwardOnlyTraversal()) {
332  for (traversedCount = 0; traversedCount < count; ++traversedCount) {
333  element = customElementAfter(element);
334  if (!element)
335  return nullptr;
336  }
337  } else if (m_shouldOnlyIncludeDirectChildren) {
338  for (traversedCount = 0; traversedCount < count; ++traversedCount) {
339  element = nextMatchingSiblingElement(*this, *element);
340  if (!element)
341  return nullptr;
342  }
343  } else {
344  for (traversedCount = 0; traversedCount < count; ++traversedCount) {
345  element = nextMatchingElement(*this, *element, root);
346  if (!element)
347  return nullptr;
348  }
349  }
350  return element;
351 }
352 
353 Element* HTMLCollection::collectionBegin() const
354 {
355  return firstElement(rootNode());
356 }
357 
358 Element* HTMLCollection::collectionLast() const
359 {
360  // FIXME: This should be optimized similarly to the forward case.
361  auto& root = rootNode();
362  Element* last = m_shouldOnlyIncludeDirectChildren ? ElementTraversal::lastChild(root) : ElementTraversal::lastWithin(root);
363  return iterateForPreviousElement(last);
364 }
365 
366 void HTMLCollection::collectionTraverseForward(Element*& current, unsigned count, unsigned& traversedCount) const
367 {
368  current = traverseForward(*current, count, traversedCount, rootNode());
369 }
370 
371 void HTMLCollection::collectionTraverseBackward(Element*& current, unsigned count) const
372 {
373  // FIXME: This should be optimized similarly to the forward case.
374  if (m_shouldOnlyIncludeDirectChildren) {
375  for (; count && current; --count)
376  current = iterateForPreviousElement(ElementTraversal::previousSibling(*current));
377  return;
378  }
379  auto& root = rootNode();
380  for (; count && current; --count)
381  current = iterateForPreviousElement(ElementTraversal::previous(*current, &root));
382 }
383 
384 void HTMLCollection::invalidateCache(Document& document) const
385 {
386  if (m_indexCache.hasValidCache(*this)) {
387  document.unregisterCollection(const_cast<HTMLCollection&>(*this));
388  m_indexCache.invalidate(*this);
389  }
390123 if (hasNamedElementCache())
391124 invalidateNamedElementCache(document);
392125}

@@void HTMLCollection::invalidateNamedElementCache(Document& document) const
400133
401134Element* HTMLCollection::namedItem(const AtomicString& name) const
402135{
403  // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp
404  // This method first searches for an object with a matching id
405  // attribute. If a match is not found, the method then searches for an
406  // object with a matching name attribute, but only on those elements
407  // that are allowed a name attribute.
408 
409  if (name.isEmpty())
410  return nullptr;
411 
412  ContainerNode& root = rootNode();
413  if (!usesCustomForwardOnlyTraversal() && root.isInTreeScope()) {
414  Element* candidate = nullptr;
415 
416  TreeScope& treeScope = root.treeScope();
417  if (treeScope.hasElementWithId(*name.impl())) {
418  if (!treeScope.containsMultipleElementsWithId(name))
419  candidate = treeScope.getElementById(name);
420  } else if (treeScope.hasElementWithName(*name.impl())) {
421  if (!treeScope.containsMultipleElementsWithName(name)) {
422  candidate = treeScope.getElementByName(name);
423  if (candidate && type() == DocAll && !nameShouldBeVisibleInDocumentAll(*candidate))
424  candidate = nullptr;
425  }
426  } else
427  return nullptr;
428 
429  if (candidate && isMatchingElement(*this, *candidate)) {
430  if (m_shouldOnlyIncludeDirectChildren ? candidate->parentNode() == &root : candidate->isDescendantOf(&root))
431  return candidate;
432  }
433  }
434 
435136 // The pathological case. We need to walk the entire subtree.
436137 updateNamedElementCache();
437138 ASSERT(m_namedElementCache);

@@void HTMLCollection::updateNamedElementCache() const
456157
457158 auto cache = std::make_unique<CollectionNamedElementCache>();
458159
459  unsigned size = m_indexCache.nodeCount(*this);
 160 unsigned size = length();
460161 for (unsigned i = 0; i < size; ++i) {
461  Element& element = *m_indexCache.nodeAt(*this, i);
 162 Element& element = *item(i);
462163 const AtomicString& id = element.getIdAttribute();
463164 if (!id.isEmpty())
464165 cache->appendToIdCache(id, element);

@@PassRefPtr<NodeList> HTMLCollection::tags(const String& name)
513214 return ownerNode().getElementsByTagName(name);
514215}
515216
516 Element* HTMLCollection::customElementAfter(Element*) const
517 {
518  ASSERT_NOT_REACHED();
519  return nullptr;
520 }
521 
522217} // namespace WebCore

Source/WebCore/html/HTMLCollection.h

@@private:
6060
6161class HTMLCollection : public ScriptWrappable, public RefCounted<HTMLCollection> {
6262public:
63  static Ref<HTMLCollection> create(ContainerNode& base, CollectionType);
6463 virtual ~HTMLCollection();
6564
6665 // DOM API
67  unsigned length() const;
68  Element* item(unsigned offset) const;
 66 virtual unsigned length() const = 0;
 67 virtual Element* item(unsigned offset) const = 0;
6968 virtual Element* namedItem(const AtomicString& name) const;
7069 PassRefPtr<NodeList> tags(const String&);
7170
7271 // Non-DOM API
7372 bool hasNamedItem(const AtomicString& name) const;
7473 Vector<Ref<Element>> namedItems(const AtomicString& name) const;
75  size_t memoryCost() const;
 74 virtual size_t memoryCost() const;
7675
7776 bool isRootedAtDocument() const;
7877 NodeListInvalidationType invalidationType() const;
7978 CollectionType type() const;
8079 ContainerNode& ownerNode() const;
81  void invalidateCache(const QualifiedName* attributeName) const;
82  virtual void invalidateCache(Document&) const;
83 
84  // For CollectionIndexCache; do not use elsewhere.
85  Element* collectionBegin() const;
86  Element* collectionLast() const;
87  Element* collectionEnd() const;
88  void collectionTraverseForward(Element*&, unsigned count, unsigned& traversedCount) const;
89  void collectionTraverseBackward(Element*&, unsigned count) const;
90  bool collectionCanTraverseBackward() const;
91  void willValidateIndexCache() const;
 80 void invalidateCache(const QualifiedName* attributeName);
 81 virtual void invalidateCache(Document&);
9282
9383 bool hasNamedElementCache() const;
9484
9585protected:
96  enum ElementTraversalType { NormalTraversal, CustomForwardOnlyTraversal };
97  HTMLCollection(ContainerNode& base, CollectionType, ElementTraversalType = NormalTraversal);
 86 HTMLCollection(ContainerNode& base, CollectionType);
9887
9988 virtual void updateNamedElementCache() const;
10089
10190 void setNamedItemCache(std::unique_ptr<CollectionNamedElementCache>) const;
10291 const CollectionNamedElementCache& namedItemCaches() const;
10392
104 private:
10593 Document& document() const;
10694 ContainerNode& rootNode() const;
107  bool usesCustomForwardOnlyTraversal() const;
108 
109  Element* iterateForPreviousElement(Element*) const;
110  Element* firstElement(ContainerNode& root) const;
111  Element* traverseForward(Element&, unsigned count, unsigned& traversedCount, ContainerNode& root) const;
112 
113  virtual Element* customElementAfter(Element*) const;
11495
11596 void invalidateNamedElementCache(Document&) const;
11697

@@private:
119100
120101 Ref<ContainerNode> m_ownerNode;
121102
122  mutable CollectionIndexCache<HTMLCollection, Element*> m_indexCache;
123103 mutable std::unique_ptr<CollectionNamedElementCache> m_namedElementCache;
124104
125105 const unsigned m_collectionType : 5;
126106 const unsigned m_invalidationType : 4;
127107 const unsigned m_rootType : 1;
128  const unsigned m_shouldOnlyIncludeDirectChildren : 1;
129  const unsigned m_usesCustomForwardOnlyTraversal : 1;
130108};
131109
 110inline ContainerNode& HTMLCollection::rootNode() const
 111{
 112 if (isRootedAtDocument() && ownerNode().inDocument())
 113 return ownerNode().document();
 114
 115 return ownerNode();
 116}
 117
132118inline const Vector<Element*>* CollectionNamedElementCache::findElementsWithId(const AtomicString& id) const
133119{
134120 return find(m_idMap, id);

@@inline void CollectionNamedElementCache::append(StringToElementsMap& map, const
177163
178164inline size_t HTMLCollection::memoryCost() const
179165{
180  return m_indexCache.memoryCost() + (m_namedElementCache ? m_namedElementCache->memoryCost() : 0);
 166 return m_namedElementCache ? m_namedElementCache->memoryCost() : 0;
181167}
182168
183169inline bool HTMLCollection::isRootedAtDocument() const

@@inline Document& HTMLCollection::document() const
205191 return m_ownerNode->document();
206192}
207193
208 inline void HTMLCollection::invalidateCache(const QualifiedName* attributeName) const
 194inline void HTMLCollection::invalidateCache(const QualifiedName* attributeName)
209195{
210196 if (!attributeName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attributeName))
211197 invalidateCache(document());

@@inline void HTMLCollection::invalidateCache(const QualifiedName* attributeName)
213199 invalidateNamedElementCache(document());
214200}
215201
216 inline Element* HTMLCollection::collectionEnd() const
217 {
218  return nullptr;
219 }
220 
221 inline bool HTMLCollection::collectionCanTraverseBackward() const
222 {
223  return !m_usesCustomForwardOnlyTraversal;
224 }
225 
226 inline void HTMLCollection::willValidateIndexCache() const
227 {
228  document().registerCollection(const_cast<HTMLCollection&>(*this));
229 }
230 
231202inline bool HTMLCollection::hasNamedElementCache() const
232203{
233204 return !!m_namedElementCache;

Source/WebCore/html/HTMLFieldSetElement.cpp

2626#include "HTMLFieldSetElement.h"
2727
2828#include "ElementIterator.h"
29 #include "HTMLCollection.h"
 29#include "HTMLFormControlsCollection.h"
3030#include "HTMLLegendElement.h"
3131#include "HTMLNames.h"
3232#include "HTMLObjectElement.h"
 33#include "NodeRareData.h"
3334#include "RenderFieldset.h"
3435#include <wtf/StdLibExtras.h>
3536

@@HTMLLegendElement* HTMLFieldSetElement::legend() const
161162
162163Ref<HTMLCollection> HTMLFieldSetElement::elements()
163164{
164  return ensureCachedHTMLCollection(FormControls);
 165 return ensureRareData().ensureNodeLists().addCachedCollection<HTMLFormControlsCollection>(*this, FormControls);
165166}
166167
167168void HTMLFieldSetElement::refreshElementsIfNeeded() const

Source/WebCore/html/HTMLFormControlsCollection.cpp

@@using namespace HTMLNames;
3636// calculation every time if anything has changed.
3737
3838HTMLFormControlsCollection::HTMLFormControlsCollection(ContainerNode& ownerNode)
39  : HTMLCollection(ownerNode, FormControls, CustomForwardOnlyTraversal)
 39 : Base(ownerNode, FormControls)
4040 , m_cachedElement(nullptr)
4141 , m_cachedElementOffsetInArray(0)
4242{

@@void HTMLFormControlsCollection::updateNamedElementCache() const
177177 setNamedItemCache(WTF::move(cache));
178178}
179179
180 void HTMLFormControlsCollection::invalidateCache(Document& document) const
 180void HTMLFormControlsCollection::invalidateCache(Document& document)
181181{
182  HTMLCollection::invalidateCache(document);
 182 Base::invalidateCache(document);
183183 m_cachedElement = nullptr;
184184 m_cachedElementOffsetInArray = 0;
185185}

Source/WebCore/html/HTMLFormControlsCollection.h

2323#ifndef HTMLFormControlsCollection_h
2424#define HTMLFormControlsCollection_h
2525
26 #include "HTMLCollection.h"
 26#include "CachedHTMLCollection.h"
2727#include "HTMLElement.h"
2828
2929namespace WebCore {

@@class HTMLImageElement;
3434// This class is just a big hack to find form elements even in malformed HTML elements.
3535// The famous <table><tr><form><td> problem.
3636
37 class HTMLFormControlsCollection final : public HTMLCollection {
 37class HTMLFormControlsCollection final : public CachedHTMLCollection<HTMLFormControlsCollection, CollectionTypeTraits<FormControls>::traversalType> {
3838public:
3939 static Ref<HTMLFormControlsCollection> create(ContainerNode&, CollectionType);
4040 virtual ~HTMLFormControlsCollection();
4141
 42 // For CachedHTMLCollection.
 43 Element* customElementAfter(Element*) const;
 44
4245private:
 46 using Base = CachedHTMLCollection<HTMLFormControlsCollection, CollectionTypeTraits<FormControls>::traversalType>;
4347 explicit HTMLFormControlsCollection(ContainerNode&);
4448
4549 virtual HTMLElement* namedItem(const AtomicString& name) const override;
46  virtual void invalidateCache(Document&) const override;
 50 virtual void invalidateCache(Document&) override;
4751 virtual void updateNamedElementCache() const override;
4852
4953 const Vector<FormAssociatedElement*>& formControlElements() const;
5054 const Vector<HTMLImageElement*>& formImageElements() const;
51  virtual Element* customElementAfter(Element*) const override;
5255
5356 mutable Element* m_cachedElement;
5457 mutable unsigned m_cachedElementOffsetInArray;

Source/WebCore/html/HTMLFormElement.cpp

3737#include "Frame.h"
3838#include "FrameLoader.h"
3939#include "FrameLoaderClient.h"
40 #include "HTMLCollection.h"
 40#include "HTMLFormControlsCollection.h"
4141#include "HTMLImageElement.h"
4242#include "HTMLInputElement.h"
4343#include "HTMLNames.h"
4444#include "HTMLTableElement.h"
 45#include "NodeRareData.h"
4546#include "Page.h"
4647#include "RenderTextControl.h"
4748#include "ScriptController.h"

@@void HTMLFormElement::removeImgElement(HTMLImageElement* e)
638639
639640Ref<HTMLCollection> HTMLFormElement::elements()
640641{
641  return ensureCachedHTMLCollection(FormControls);
 642 return ensureRareData().ensureNodeLists().addCachedCollection<HTMLFormControlsCollection>(*this, FormControls);
642643}
643644
644645String HTMLFormElement::name() const

Source/WebCore/html/HTMLMapElement.cpp

2525#include "Attribute.h"
2626#include "Document.h"
2727#include "ElementIterator.h"
 28#include "GenericCachedHTMLCollection.h"
2829#include "HTMLAreaElement.h"
29 #include "HTMLCollection.h"
3030#include "HTMLImageElement.h"
3131#include "HitTestResult.h"
3232#include "IntSize.h"
 33#include "NodeRareData.h"
3334
3435namespace WebCore {
3536

@@void HTMLMapElement::parseAttribute(const QualifiedName& name, const AtomicStrin
112113
113114Ref<HTMLCollection> HTMLMapElement::areas()
114115{
115  return ensureCachedHTMLCollection(MapAreas);
 116 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<MapAreas>::traversalType>>(*this, MapAreas);
116117}
117118
118119Node::InsertionNotificationRequest HTMLMapElement::insertedInto(ContainerNode& insertionPoint)

Source/WebCore/html/HTMLNameCollection.cpp

@@namespace WebCore {
3636
3737using namespace HTMLNames;
3838
39 HTMLNameCollection::HTMLNameCollection(Document& document, CollectionType type, const AtomicString& name)
40  : HTMLCollection(document, type)
41  , m_name(name)
42 {
43 }
44 
45 HTMLNameCollection::~HTMLNameCollection()
46 {
47  ASSERT(type() == WindowNamedItems || type() == DocumentNamedItems);
48 
49  document().nodeLists()->removeCachedCollection(this, m_name);
50 }
51 
5239bool WindowNameCollection::elementMatchesIfNameAttributeMatch(const Element& element)
5340{
5441 return is<HTMLImageElement>(element) || is<HTMLFormElement>(element) || is<HTMLAppletElement>(element)

Source/WebCore/html/HTMLNameCollection.h

2323#ifndef HTMLNameCollection_h
2424#define HTMLNameCollection_h
2525
26 #include "HTMLCollection.h"
 26#include "CachedHTMLCollection.h"
 27#include "NodeRareData.h"
2728#include <wtf/text/AtomicString.h>
2829
2930namespace WebCore {
3031
3132class Document;
3233
33 class HTMLNameCollection : public HTMLCollection {
 34template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 35class HTMLNameCollection : public CachedHTMLCollection<HTMLCollectionClass, traversalType> {
3436public:
3537 virtual ~HTMLNameCollection();
3638
37  Document& document() { return downcast<Document>(ownerNode()); }
38 
3939protected:
4040 HTMLNameCollection(Document&, CollectionType, const AtomicString& name);
4141
4242 AtomicString m_name;
 43
 44private:
 45 using Base = CachedHTMLCollection<HTMLCollectionClass, traversalType>;
 46 Document& document() { return downcast<Document>(Base::ownerNode()); }
4347};
4448
45 class WindowNameCollection final : public HTMLNameCollection {
 49template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 50HTMLNameCollection<HTMLCollectionClass, traversalType>::HTMLNameCollection(Document& document, CollectionType type, const AtomicString& name)
 51 : CachedHTMLCollection<HTMLCollectionClass, traversalType>(document, type)
 52 , m_name(name)
 53{
 54}
 55
 56template <typename HTMLCollectionClass, CollectionTraversalType traversalType>
 57HTMLNameCollection<HTMLCollectionClass, traversalType>::~HTMLNameCollection()
 58{
 59 ASSERT(Base::type() == WindowNamedItems || Base::type() == DocumentNamedItems);
 60
 61 document().nodeLists()->removeCachedCollection(this, m_name);
 62}
 63
 64class WindowNameCollection final : public HTMLNameCollection<WindowNameCollection, CollectionTraversalType::Descendants> {
4665public:
4766 static Ref<WindowNameCollection> create(Document& document, CollectionType type, const AtomicString& name)
4867 {
4968 return adoptRef(*new WindowNameCollection(document, type, name));
5069 }
5170
 71 // For CachedHTMLCollection.
5272 bool elementMatches(const Element& element) const { return elementMatches(element, m_name.impl()); }
5373
5474 static bool elementMatchesIfIdAttributeMatch(const Element&) { return true; }

@@public:
5777
5878private:
5979 WindowNameCollection(Document& document, CollectionType type, const AtomicString& name)
60  : HTMLNameCollection(document, type, name)
 80 : HTMLNameCollection<WindowNameCollection, CollectionTraversalType::Descendants>(document, type, name)
6181 {
6282 ASSERT(type == WindowNamedItems);
6383 }
6484};
6585
66 class DocumentNameCollection final : public HTMLNameCollection {
 86class DocumentNameCollection final : public HTMLNameCollection<DocumentNameCollection, CollectionTraversalType::Descendants> {
6787public:
6888 static Ref<DocumentNameCollection> create(Document& document, CollectionType type, const AtomicString& name)
6989 {

@@public:
7292
7393 static bool elementMatchesIfIdAttributeMatch(const Element&);
7494 static bool elementMatchesIfNameAttributeMatch(const Element&);
 95
 96 // For CachedHTMLCollection.
7597 bool elementMatches(const Element& element) const { return elementMatches(element, m_name.impl()); }
7698
7799 static bool elementMatches(const Element&, const AtomicStringImpl*);
78100
79101private:
80102 DocumentNameCollection(Document& document, CollectionType type, const AtomicString& name)
81  : HTMLNameCollection(document, type, name)
 103 : HTMLNameCollection<DocumentNameCollection, CollectionTraversalType::Descendants>(document, type, name)
82104 {
83105 ASSERT(type == DocumentNamedItems);
84106 }

Source/WebCore/html/HTMLOptionsCollection.cpp

2727namespace WebCore {
2828
2929HTMLOptionsCollection::HTMLOptionsCollection(HTMLSelectElement& select)
30  : HTMLCollection(select, SelectOptions)
 30 : Base(select, SelectOptions)
3131{
3232}
3333

Source/WebCore/html/HTMLOptionsCollection.h

2424#ifndef HTMLOptionsCollection_h
2525#define HTMLOptionsCollection_h
2626
27 #include "HTMLCollection.h"
 27#include "CachedHTMLCollection.h"
2828#include "HTMLSelectElement.h"
2929
3030namespace WebCore {

@@class HTMLOptionElement;
3333
3434typedef int ExceptionCode;
3535
36 class HTMLOptionsCollection final : public HTMLCollection {
 36class HTMLOptionsCollection final : public CachedHTMLCollection<HTMLOptionsCollection, CollectionTypeTraits<SelectOptions>::traversalType> {
3737public:
3838 static Ref<HTMLOptionsCollection> create(HTMLSelectElement&, CollectionType);
3939

@@public:
5050
5151 void setLength(unsigned, ExceptionCode&);
5252
 53 // For CachedHTMLCollection.
 54 bool elementMatches(Element&) const;
 55
5356private:
 57 using Base = CachedHTMLCollection<HTMLOptionsCollection, CollectionTypeTraits<SelectOptions>::traversalType>;
5458 explicit HTMLOptionsCollection(HTMLSelectElement&);
5559};
5660
 61inline bool HTMLOptionsCollection::elementMatches(Element& element) const
 62{
 63 return element.hasTagName(HTMLNames::optionTag);
 64}
 65
5766} // namespace WebCore
5867
5968SPECIALIZE_TYPE_TRAITS_HTMLCOLLECTION(HTMLOptionsCollection, SelectOptions)

Source/WebCore/html/HTMLSelectElement.cpp

3838#include "FormController.h"
3939#include "FormDataList.h"
4040#include "Frame.h"
 41#include "GenericCachedHTMLCollection.h"
4142#include "HTMLFormElement.h"
4243#include "HTMLNames.h"
4344#include "HTMLOptGroupElement.h"

4647#include "KeyboardEvent.h"
4748#include "LocalizedStrings.h"
4849#include "MouseEvent.h"
 50#include "NodeRareData.h"
4951#include "Page.h"
5052#include "PlatformMouseEvent.h"
5153#include "RenderListBox.h"

@@bool HTMLSelectElement::childShouldCreateRenderer(const Node& child) const
374376
375377Ref<HTMLCollection> HTMLSelectElement::selectedOptions()
376378{
377  return ensureCachedHTMLCollection(SelectedOptions);
 379 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<SelectedOptions>::traversalType>>(*this, SelectedOptions);
378380}
379381
380382Ref<HTMLOptionsCollection> HTMLSelectElement::options()
381383{
382  return downcast<HTMLOptionsCollection>(ensureCachedHTMLCollection(SelectOptions).get());
 384 return ensureRareData().ensureNodeLists().addCachedCollection<HTMLOptionsCollection>(*this, SelectOptions);
383385}
384386
385387void HTMLSelectElement::updateListItemSelectedStates()

Source/WebCore/html/HTMLTableElement.cpp

3131#include "CSSValuePool.h"
3232#include "ExceptionCode.h"
3333#include "ExceptionCodePlaceholder.h"
 34#include "GenericCachedHTMLCollection.h"
3435#include "HTMLNames.h"
3536#include "HTMLParserIdioms.h"
3637#include "HTMLTableCaptionElement.h"
3738#include "HTMLTableRowElement.h"
3839#include "HTMLTableRowsCollection.h"
3940#include "HTMLTableSectionElement.h"
 41#include "NodeRareData.h"
4042#include "RenderTable.h"
4143#include "StyleProperties.h"
4244#include <wtf/Ref.h>

@@bool HTMLTableElement::isURLAttribute(const Attribute& attribute) const
551553
552554Ref<HTMLCollection> HTMLTableElement::rows()
553555{
554  return ensureCachedHTMLCollection(TableRows);
 556 return ensureRareData().ensureNodeLists().addCachedCollection<HTMLTableRowsCollection>(*this, TableRows);
555557}
556558
557559Ref<HTMLCollection> HTMLTableElement::tBodies()
558560{
559  return ensureCachedHTMLCollection(TableTBodies);
 561 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<TableTBodies>::traversalType>>(*this, TableTBodies);
560562}
561563
562564const AtomicString& HTMLTableElement::rules() const

Source/WebCore/html/HTMLTableRowElement.cpp

2626#include "HTMLTableRowElement.h"
2727
2828#include "ExceptionCode.h"
29 #include "HTMLCollection.h"
 29#include "GenericCachedHTMLCollection.h"
3030#include "HTMLNames.h"
3131#include "HTMLTableCellElement.h"
3232#include "HTMLTableElement.h"
3333#include "HTMLTableSectionElement.h"
3434#include "NodeList.h"
 35#include "NodeRareData.h"
3536#include "Text.h"
3637
3738namespace WebCore {

@@void HTMLTableRowElement::deleteCell(int index, ExceptionCode& ec)
156157
157158Ref<HTMLCollection> HTMLTableRowElement::cells()
158159{
159  return ensureCachedHTMLCollection(TRCells);
 160 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<TRCells>::traversalType>>(*this, TRCells);
160161}
161162
162163void HTMLTableRowElement::setCells(HTMLCollection*, ExceptionCode& ec)

Source/WebCore/html/HTMLTableRowsCollection.cpp

@@HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement& table)
149149}
150150
151151HTMLTableRowsCollection::HTMLTableRowsCollection(HTMLTableElement& table)
152  : HTMLCollection(table, TableRows, CustomForwardOnlyTraversal)
 152 : Base(table, TableRows)
153153{
154154}
155155

Source/WebCore/html/HTMLTableRowsCollection.h

2929#ifndef HTMLTableRowsCollection_h
3030#define HTMLTableRowsCollection_h
3131
32 #include "HTMLCollection.h"
 32#include "CachedHTMLCollection.h"
3333#include "HTMLTableElement.h"
3434
3535namespace WebCore {
3636
3737class HTMLTableRowElement;
3838
39 class HTMLTableRowsCollection final : public HTMLCollection {
 39class HTMLTableRowsCollection final : public CachedHTMLCollection<HTMLTableRowsCollection, CollectionTypeTraits<TableRows>::traversalType> {
4040public:
4141 static Ref<HTMLTableRowsCollection> create(HTMLTableElement&, CollectionType);
4242

@@public:
4646 static HTMLTableRowElement* rowAfter(HTMLTableElement&, HTMLTableRowElement*);
4747 static HTMLTableRowElement* lastRow(HTMLTableElement&);
4848
 49 // For CachedHTMLCollection.
 50 Element* customElementAfter(Element*) const;
 51
4952private:
 53 using Base = CachedHTMLCollection<HTMLTableRowsCollection, CollectionTypeTraits<TableRows>::traversalType>;
5054 explicit HTMLTableRowsCollection(HTMLTableElement&);
51 
52  virtual Element* customElementAfter(Element*) const override;
5355};
5456
5557} // namespace WebCore

Source/WebCore/html/HTMLTableSectionElement.cpp

2626#include "HTMLTableSectionElement.h"
2727
2828#include "ExceptionCode.h"
 29#include "GenericCachedHTMLCollection.h"
2930#include "HTMLCollection.h"
3031#include "HTMLNames.h"
3132#include "HTMLTableRowElement.h"
3233#include "HTMLTableElement.h"
3334#include "NodeList.h"
 35#include "NodeRareData.h"
3436#include "Text.h"
3537
3638namespace WebCore {

@@void HTMLTableSectionElement::setVAlign(const AtomicString& value)
147149
148150Ref<HTMLCollection> HTMLTableSectionElement::rows()
149151{
150  return ensureCachedHTMLCollection(TSectionRows);
 152 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<TSectionRows>::traversalType>>(*this, TSectionRows);
151153}
152154
153155}