Source/WebCore/ChangeLog

 12012-03-26 Hayato Ito <hayato@chromium.org>
 2
 3 [Shadow DOM] Add a Walker class which can traverse a reified tree.
 4 https://bugs.webkit.org/show_bug.cgi?id=82009
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 ReifiedTreeWalker is intended to be a successor of current ReifiedTreeTraversal APIs.
 9 ReifiedTreeWalker uses a cursor pattern and takes a starting node in its constructor.
 10 It remembers a position of currently visiting node in reified tree.
 11
 12 The typical usage is:
 13
 14 for (ReifiedTreeWalker walker(node); walker.get(); walker.nextNode()) {
 15 ...
 16 }
 17
 18 I'll update clients of ReifiedTreeTraversal APIs so that it uses this Walker in follow-up patches.
 19 After that, I'll get rid of ReifiedTreeTraversal APIs in favor of the Walker.
 20
 21 Test: fast/dom/shadow/reified-tree-traversal.html
 22
 23 * CMakeLists.txt:
 24 * GNUmakefile.list.am:
 25 * Target.pri:
 26 * WebCore.gypi:
 27 * WebCore.vcproj/WebCore.vcproj:
 28 * WebCore.xcodeproj/project.pbxproj:
 29 * dom/ReifiedTreeWalker.cpp: Added.
 30 (WebCore):
 31 (WebCore::isShadowHost):
 32 (WebCore::shadowTreeFor):
 33 (WebCore::shadowTreeOfParent):
 34 (WebCore::ReifiedTreeWalker::firstChild):
 35 (WebCore::ReifiedTreeWalker::traverseFirstChild):
 36 (WebCore::ReifiedTreeWalker::lastChild):
 37 (WebCore::ReifiedTreeWalker::traverseLastChild):
 38 (WebCore::ReifiedTreeWalker::traverseChild):
 39 (WebCore::ReifiedTreeWalker::traverseLightChildren):
 40 (WebCore::ReifiedTreeWalker::traverseNode):
 41 (WebCore::ReifiedTreeWalker::nextSibling):
 42 (WebCore::ReifiedTreeWalker::previousSibling):
 43 (WebCore::ReifiedTreeWalker::traverseSiblingOrBackToInsertionPoint):
 44 (WebCore::ReifiedTreeWalker::traverseSiblingInCurrentTree):
 45 (WebCore::ReifiedTreeWalker::traverseSiblingOrBackToYoungerShadowRoot):
 46 (WebCore::ReifiedTreeWalker::escapeFallbackContentElement):
 47 (WebCore::ReifiedTreeWalker::traverseNodeEscapingFallbackContents):
 48 (WebCore::ReifiedTreeWalker::parentNode):
 49 (WebCore::ReifiedTreeWalker::traverseParentNode):
 50 (WebCore::ReifiedTreeWalker::traverseParentNodeInCurrentTree):
 51 (WebCore::ReifiedTreeWalker::traverseParentNodeBackToYoungerShadowRootOrHost):
 52 (WebCore::ReifiedTreeWalker::adjustedParentNode):
 53 (WebCore::ReifiedTreeWalker::traverseNextSibling):
 54 (WebCore::ReifiedTreeWalker::traversePreviousSibling):
 55 (WebCore::ReifiedTreeWalker::nextNode):
 56 (WebCore::ReifiedTreeWalker::previousNode):
 57 * dom/ReifiedTreeWalker.h: Added.
 58 (WebCore):
 59 (ReifiedTreeWalker):
 60 (WebCore::ReifiedTreeWalker::get):
 61 (WebCore::ReifiedTreeWalker::canCrossUpperBoundary):
 62 (WebCore::ReifiedTreeWalker::ReifiedTreeWalker):
 63 (WebCore::ReifiedTreeWalker::startedWithFirstChild):
 64 * testing/Internals.cpp:
 65 (WebCore::Internals::nextSiblingByWalker):
 66 (WebCore):
 67 (WebCore::Internals::firstChildByWalker):
 68 (WebCore::Internals::lastChildByWalker):
 69 (WebCore::Internals::nextNodeByWalker):
 70 (WebCore::Internals::previousNodeByWalker):
 71 * testing/Internals.h:
 72 (Internals):
 73 * testing/Internals.idl:
 74
1752012-03-26 Stephen White <senorblanco@chromium.org>
276
377 Make filters and the threaded compositor play well together.

61316205 * rendering/RenderLayerBacking.cpp:
61326206 (WebCore::RenderLayerBacking::RenderLayerBacking):
61336207
 62082012-03-22 Hayato Ito <hayato@chromium.org>
 6209
 6210 Benchmark for Reified Teee Traversal APIs.
 6211 https://bugs.webkit.org/show_bug.cgi?id=81495
 6212
 6213 Reviewed by NOBODY (OOPS!).
 6214
 6215 No intention to commit this patch as of now. Just for benchmarking.
 6216
 6217 Test: fast/dom/shadow/benchmark.html
 6218
 6219 * testing/Internals.cpp:
 6220 (WebCore):
 6221 (WebCore::Internals::doTraverseNextNode):
 6222 (WebCore::Internals::doTraverseNextNodeInReifiedTree):
 6223 * testing/Internals.h:
 6224 (Internals):
 6225 * testing/Internals.idl:
 6226
 62272012-03-23 Hayato Ito <hayato@chromium.org>
 6228
 6229 WIP. Walker version.
 6230 https://bugs.webkit.org/show_bug.cgi?id=82009
 6231
 6232 Reviewed by NOBODY (OOPS!).
 6233
 6234 Test: fast/dom/shadow/reified-tree-walker.html
 6235
 6236 * WebCore.gypi:
 6237 * dom/ReifiedTreeWalker.cpp: Added.
 6238 (WebCore):
 6239 (WebCore::isShadowHost):
 6240 (WebCore::shadowTreeFor):
 6241 (WebCore::shadowTreeOfParent):
 6242 (WebCore::ReifiedTreeWalker::firstChild):
 6243 (WebCore::ReifiedTreeWalker::traverseFirstChild):
 6244 (WebCore::ReifiedTreeWalker::lastChild):
 6245 (WebCore::ReifiedTreeWalker::traverseLastChild):
 6246 (WebCore::ReifiedTreeWalker::traverseChild):
 6247 (WebCore::ReifiedTreeWalker::traverseLightChildren):
 6248 (WebCore::ReifiedTreeWalker::traverseNode):
 6249 (WebCore::ReifiedTreeWalker::nextSibling):
 6250 (WebCore::ReifiedTreeWalker::previousSibling):
 6251 (WebCore::ReifiedTreeWalker::traverseSiblingOrBackToInsertionPoint):
 6252 (WebCore::ReifiedTreeWalker::traverseSiblingInCurrentTree):
 6253 (WebCore::ReifiedTreeWalker::traverseSiblingOrBackToYoungerShadowRoot):
 6254 (WebCore::ReifiedTreeWalker::escapeFallbackContentElement):
 6255 (WebCore::ReifiedTreeWalker::traverseNodeEscapingFallbackContents):
 6256 (WebCore::ReifiedTreeWalker::parentNode):
 6257 (WebCore::ReifiedTreeWalker::traverseParentNode):
 6258 (WebCore::ReifiedTreeWalker::traverseParentNodeInCurrentTree):
 6259 (WebCore::ReifiedTreeWalker::traverseParentNodeBackToYoungerShadowRootOrHost):
 6260 (WebCore::ReifiedTreeWalker::adjustedParentNode):
 6261 (WebCore::ReifiedTreeWalker::traverseNextSibling):
 6262 (WebCore::ReifiedTreeWalker::traversePreviousSibling):
 6263 (WebCore::ReifiedTreeWalker::nextNode):
 6264 (WebCore::ReifiedTreeWalker::previousNode):
 6265 * dom/ReifiedTreeWalker.h: Added.
 6266 (WebCore):
 6267 (ReifiedTreeWalker):
 6268 (WebCore::ReifiedTreeWalker::get):
 6269 (WebCore::ReifiedTreeWalker::allowCrossingUpperBoundary):
 6270 (WebCore::ReifiedTreeWalker::ReifiedTreeWalker):
 6271 (WebCore::ReifiedTreeWalker::startedWithFirstChild):
 6272 * testing/Internals.cpp:
 6273 (WebCore::Internals::nextSiblingByWalker):
 6274 (WebCore):
 6275 (WebCore::Internals::firstChildByWalker):
 6276 (WebCore::Internals::lastChildByWalker):
 6277 (WebCore::Internals::nextNodeByWalker):
 6278 (WebCore::Internals::previousNodeByWalker):
 6279 * testing/Internals.h:
 6280 (Internals):
 6281 * testing/Internals.idl:
 6282
613462832012-03-21 Xingnan Wang <xingnan.wang@intel.com>
61356284
61366285 Web audio layout test failed in debug with an ASSERT error in ReverbConvolverStage.cpp

Source/WebCore/CMakeLists.txt

@@SET(WebCore_SOURCES
616616 dom/RangeException.cpp
617617 dom/RegisteredEventListener.cpp
618618 dom/ReifiedTreeTraversal.cpp
 619 dom/ReifiedTreeWalker.cpp
619620 dom/ScopedEventQueue.cpp
620621 dom/ScriptableDocumentParser.cpp
621622 dom/ScriptElement.cpp

Source/WebCore/GNUmakefile.list.am

@@webcore_sources += \
19231923 Source/WebCore/dom/RegisteredEventListener.h \
19241924 Source/WebCore/dom/ReifiedTreeTraversal.cpp \
19251925 Source/WebCore/dom/ReifiedTreeTraversal.h \
 1926 Source/WebCore/dom/ReifiedTreeWalker.cpp \
 1927 Source/WebCore/dom/ReifiedTreeWalker.h \
19261928 Source/WebCore/dom/RenderedDocumentMarker.h \
19271929 Source/WebCore/dom/ScopedEventQueue.cpp \
19281930 Source/WebCore/dom/ScopedEventQueue.h \

Source/WebCore/Target.pri

@@SOURCES += \
593593 dom/RawDataDocumentParser.h \
594594 dom/RegisteredEventListener.cpp \
595595 dom/ReifiedTreeTraversal.cpp \
 596 dom/ReifiedTreeWalker.cpp \
596597 dom/ScopedEventQueue.cpp \
597598 dom/ScriptedAnimationController.cpp \
598599 dom/ScriptableDocumentParser.cpp \

@@HEADERS += \
17231724 dom/Range.h \
17241725 dom/RegisteredEventListener.h \
17251726 dom/ReifiedTreeTraversal.h \
 1727 dom/ReifiedTreeWalker.h \
17261728 dom/RenderedDocumentMarker.h \
17271729 dom/ScriptedAnimationController.h \
17281730 dom/ScriptElement.h \

Source/WebCore/WebCore.gypi

626626 'dom/RangeBoundaryPoint.h',
627627 'dom/RegisteredEventListener.h',
628628 'dom/ReifiedTreeTraversal.h',
 629 'dom/ReifiedTreeWalker.h',
629630 'dom/RenderedDocumentMarker.h',
630631 'dom/ScriptExecutionContext.h',
631632 'dom/ScriptRunner.h',

52195220 'dom/RegisteredEventListener.cpp',
52205221 'dom/ReifiedTreeTraversal.cpp',
52215222 'dom/ReifiedTreeTraversal.h',
 5223 'dom/ReifiedTreeWalker.cpp',
 5224 'dom/ReifiedTreeWalker.h',
52225225 'dom/RequestAnimationFrameCallback.h',
52235226 'dom/ScopedEventQueue.cpp',
52245227 'dom/ScopedEventQueue.h',

Source/WebCore/WebCore.vcproj/WebCore.vcproj

5191051910 >
5191151911 </File>
5191251912 <File
 51913 RelativePath="..\dom\ReifiedTreeWalker.cpp"
 51914 >
 51915 </File>
 51916 <File
 51917 RelativePath="..\dom\ReifiedTreeWalker.h"
 51918 >
 51919 </File>
 51920 <File
5191351921 RelativePath="..\dom\RegisteredEventListener.cpp"
5191451922 >
5191551923 <FileConfiguration

Source/WebCore/WebCore.xcodeproj/project.pbxproj

13671367 4A1E71A614E106AC00626F9D /* JSShadowRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A1E71A414E106AC00626F9D /* JSShadowRoot.h */; };
13681368 4A38BF5014FE1C0900612512 /* WebSocketDeflateFramer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A38BF4E14FE1C0900612512 /* WebSocketDeflateFramer.cpp */; };
13691369 4A38BF5114FE1C0900612512 /* WebSocketDeflateFramer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A38BF4F14FE1C0900612512 /* WebSocketDeflateFramer.h */; };
 1370 4A6A0C5B15232F2400B09C6E /* ReifiedTreeWalker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6A0C5915232F2400B09C6E /* ReifiedTreeWalker.cpp */; };
 1371 4A6A0C5C15232F2400B09C6E /* ReifiedTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A6A0C5A15232F2400B09C6E /* ReifiedTreeWalker.h */; };
13701372 4A6E9FC313C17D1D0046A7F8 /* FontFeatureValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6E9FC113C17D1D0046A7F8 /* FontFeatureValue.cpp */; };
13711373 4A6E9FC413C17D1D0046A7F8 /* FontFeatureValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A6E9FC213C17D1D0046A7F8 /* FontFeatureValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
13721374 4A6E9FC713C17D570046A7F8 /* FontFeatureSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6E9FC513C17D570046A7F8 /* FontFeatureSettings.cpp */; };

83118313 4A1E71A414E106AC00626F9D /* JSShadowRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSShadowRoot.h; sourceTree = "<group>"; };
83128314 4A38BF4E14FE1C0900612512 /* WebSocketDeflateFramer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebSocketDeflateFramer.cpp; path = Modules/websockets/WebSocketDeflateFramer.cpp; sourceTree = "<group>"; };
83138315 4A38BF4F14FE1C0900612512 /* WebSocketDeflateFramer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebSocketDeflateFramer.h; path = Modules/websockets/WebSocketDeflateFramer.h; sourceTree = "<group>"; };
 8316 4A6A0C5915232F2400B09C6E /* ReifiedTreeWalker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReifiedTreeWalker.cpp; sourceTree = "<group>"; };
 8317 4A6A0C5A15232F2400B09C6E /* ReifiedTreeWalker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReifiedTreeWalker.h; sourceTree = "<group>"; };
83148318 4A6E9FC113C17D1D0046A7F8 /* FontFeatureValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFeatureValue.cpp; sourceTree = "<group>"; };
83158319 4A6E9FC213C17D1D0046A7F8 /* FontFeatureValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontFeatureValue.h; sourceTree = "<group>"; };
83168320 4A6E9FC513C17D570046A7F8 /* FontFeatureSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFeatureSettings.cpp; sourceTree = "<group>"; };

2108821092 85031B360A44EFC700F992E0 /* RegisteredEventListener.h */,
2108921093 4A013D271512FD7700E1E613 /* ReifiedTreeTraversal.cpp */,
2109021094 4A013D281512FD7700E1E613 /* ReifiedTreeTraversal.h */,
 21095 4A6A0C5915232F2400B09C6E /* ReifiedTreeWalker.cpp */,
 21096 4A6A0C5A15232F2400B09C6E /* ReifiedTreeWalker.h */,
2109121097 A76E5F7E135E0DCF00A69837 /* RenderedDocumentMarker.h */,
2109221098 4998AEC413F9D0EA0090B1AA /* RequestAnimationFrameCallback.h */,
2109321099 4998AEC513F9D0EA0090B1AA /* RequestAnimationFrameCallback.idl */,

2379423800 85031B4C0A44EFC700F992E0 /* RegisteredEventListener.h in Headers */,
2379523801 B2C3DA2D0D006C1D00EF6F26 /* RegularExpression.h in Headers */,
2379623802 4A013D2A1512FD7700E1E613 /* ReifiedTreeTraversal.h in Headers */,
 23803 4A6A0C5C15232F2400B09C6E /* ReifiedTreeWalker.h in Headers */,
2379723804 93309E01099E64920056E581 /* RemoveCSSPropertyCommand.h in Headers */,
2379823805 D06C0D8F0CFD11460065F43F /* RemoveFormatCommand.h in Headers */,
2379923806 93309E05099E64920056E581 /* RemoveNodeCommand.h in Headers */,

2694526952 85031B4B0A44EFC700F992E0 /* RegisteredEventListener.cpp in Sources */,
2694626953 B2C3DA2C0D006C1D00EF6F26 /* RegularExpression.cpp in Sources */,
2694726954 4A013D291512FD7700E1E613 /* ReifiedTreeTraversal.cpp in Sources */,
 26955 4A6A0C5B15232F2400B09C6E /* ReifiedTreeWalker.cpp in Sources */,
2694826956 93309E00099E64920056E581 /* RemoveCSSPropertyCommand.cpp in Sources */,
2694926957 D06C0D900CFD11460065F43F /* RemoveFormatCommand.cpp in Sources */,
2695026958 93309E04099E64920056E581 /* RemoveNodeCommand.cpp in Sources */,

Source/WebCore/dom/ReifiedTreeWalker.cpp

 1/*
 2 * Copyright (C) 2012 Google 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 are
 6 * met:
 7 *
 8 * * Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * * Neither the name of Google Inc. nor the names of its
 11 * contributors may be used to endorse or promote products derived from
 12 * this software without specific prior written permission.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25 */
 26
 27#include "config.h"
 28#include "ReifiedTreeWalker.h"
 29
 30#include "Element.h"
 31#include "HTMLContentSelector.h"
 32#include "InsertionPoint.h"
 33#include "ShadowTree.h"
 34
 35namespace WebCore {
 36
 37static inline bool isShadowHost(const Node* node)
 38{
 39 return node && node->isElementNode() && toElement(node)->hasShadowRoot();
 40}
 41
 42static inline ShadowTree* shadowTreeFor(const Node* node)
 43{
 44 if (node && node->isElementNode())
 45 return toElement(node)->shadowTree();
 46 return 0;
 47}
 48
 49static inline ShadowTree* shadowTreeOfParent(const Node* node)
 50{
 51 if (node && node->parentNode())
 52 return shadowTreeFor(node->parentNode());
 53 return 0;
 54}
 55
 56void ReifiedTreeWalker::firstChild()
 57{
 58 ASSERT(m_node);
 59 m_node = traverseChild(m_node, TraversalDirectionForward);
 60 ASSERT(!m_node || !m_node->isShadowRoot());
 61}
 62
 63Node* ReifiedTreeWalker::traverseFirstChild(const Node* node) const
 64{
 65 ASSERT(node);
 66 return traverseChild(node, TraversalDirectionForward);
 67}
 68
 69void ReifiedTreeWalker::lastChild()
 70{
 71 ASSERT(m_node);
 72 m_node = traverseLastChild(m_node);
 73 ASSERT(!m_node || !m_node->isShadowRoot());
 74}
 75
 76Node* ReifiedTreeWalker::traverseLastChild(const Node* node) const
 77{
 78 ASSERT(node);
 79 return traverseChild(node, TraversalDirectionBackward);
 80}
 81
 82Node* ReifiedTreeWalker::traverseChild(const Node* node, TraversalDirection direction) const
 83{
 84 ASSERT(node);
 85 // FIXME: Add an assertion once InsertionPoint have isActive() function.
 86 // https://bugs.webkit.org/show_bug.cgi?id=82010
 87 // ASSERT(!isInsertionPoint(node) || !toInsertionPoint(node)->isActive());
 88 ASSERT(!node->isShadowRoot());
 89 if (canCrossUpperBoundary()) {
 90 ShadowTree* shadowTree = shadowTreeFor(node);
 91 if (shadowTree && shadowTree->hasShadowRoot())
 92 return traverseLightChildren(shadowTree->youngestShadowRoot(), direction);
 93 return traverseLightChildren(node, direction);
 94 }
 95 if (isShadowHost(node))
 96 return 0;
 97 return traverseLightChildren(node, direction);
 98}
 99
 100Node* ReifiedTreeWalker::traverseLightChildren(const Node* node, TraversalDirection direction)
 101{
 102 ASSERT(node);
 103 if (Node* child = (direction == TraversalDirectionForward ? node->firstChild() : node->lastChild()))
 104 return traverseNode(child, direction);
 105 return 0;
 106}
 107
 108Node* ReifiedTreeWalker::traverseNode(const Node* node, TraversalDirection direction)
 109{
 110 ASSERT(node);
 111 if (isInsertionPoint(node)) {
 112 const HTMLContentSelectionList* selectionList = toInsertionPoint(node)->selections();
 113 if (HTMLContentSelection* selection = (direction == TraversalDirectionForward ? selectionList->first() : selectionList->last()))
 114 return traverseNode(selection->node(), direction);
 115 return traverseLightChildren(node, direction);
 116 }
 117 return const_cast<Node*>(node);
 118}
 119
 120void ReifiedTreeWalker::nextSibling()
 121{
 122 ASSERT(m_node);
 123 ASSERT(!m_node->isShadowRoot());
 124 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionForward);
 125 ASSERT(!m_node || !m_nodet->isShadowRoot());
 126}
 127
 128void ReifiedTreeWalker::previousSibling()
 129{
 130 ASSERT(m_node);
 131 ASSERT(!m_node->isShadowRoot());
 132 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionBackward);
 133 ASSERT(!m_node || !m_node->isShadowRoot());
 134}
 135
 136Node* ReifiedTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction)
 137{
 138 ASSERT(node);
 139 ShadowTree* shadowTree = shadowTreeOfParent(node);
 140 if (!shadowTree)
 141 return traverseSiblingInCurrentTree(node, direction);
 142 HTMLContentSelection* selection = shadowTree->selectionFor(node);
 143 if (!selection)
 144 return traverseSiblingInCurrentTree(node, direction);
 145 if (HTMLContentSelection* nextSelection = (direction == TraversalDirectionForward ? selection->next() : selection->previous()))
 146 return traverseNode(nextSelection->node(), direction);
 147 return traverseSiblingOrBackToInsertionPoint(selection->insertionPoint(), direction);
 148}
 149
 150Node* ReifiedTreeWalker::traverseSiblingInCurrentTree(const Node* node, TraversalDirection direction)
 151{
 152 ASSERT(node);
 153 if (Node* next = (direction == TraversalDirectionForward ? node->nextSibling() : node->previousSibling()))
 154 return traverseNode(next, direction);
 155 if (Node* next = traverseSiblingOrBackToYoungerShadowRoot(node, direction))
 156 return next;
 157 return escapeFallbackContentElement(node, direction);
 158}
 159
 160Node* ReifiedTreeWalker::traverseSiblingOrBackToYoungerShadowRoot(const Node* node, TraversalDirection direction)
 161{
 162 ASSERT(node);
 163 if (node->parentNode() && node->parentNode()->isShadowRoot()) {
 164 ShadowRoot* parentShadowRoot = toShadowRoot(node->parentNode());
 165 if (!parentShadowRoot->isYoungest()) {
 166 InsertionPoint* assignedInsertionPoint = parentShadowRoot->assignedTo();
 167 ASSERT(assignedInsertionPoint);
 168 return traverseSiblingInCurrentTree(assignedInsertionPoint, direction);
 169 }
 170 }
 171 return 0;
 172}
 173
 174Node* ReifiedTreeWalker::escapeFallbackContentElement(const Node* node, TraversalDirection direction)
 175{
 176 ASSERT(node);
 177 if (node->parentNode() && isInsertionPoint(node->parentNode()))
 178 return traverseSiblingOrBackToInsertionPoint(node->parentNode(), direction);
 179 return 0;
 180}
 181
 182Node* ReifiedTreeWalker::traverseNodeEscapingFallbackContents(const Node* node) const
 183{
 184 ASSERT(node);
 185 if (isInsertionPoint(node))
 186 return traverseParentNodeOrBackToInsertionPoint(node);
 187 return const_cast<Node*>(node);
 188}
 189
 190void ReifiedTreeWalker::parentNode()
 191{
 192 ASSERT(m_node);
 193 ASSERT(!m_node->isShadowRoot());
 194 // FIXME: Add an assertion once InsertionPoint have isActive() function.
 195 // https://bugs.webkit.org/show_bug.cgi?id=82010
 196 // ASSERT(!isInsertionPoint(node) || !toInsertionPoint(node)->isActive());
 197 m_node = traverseParentNode(m_node);
 198}
 199
 200Node* ReifiedTreeWalker::traverseParentNode(const Node* node) const
 201{
 202 if (ShadowTree* shadowTree = shadowTreeOfParent(node)) {
 203 if (HTMLContentSelection* selection = shadowTree->selectionFor(node))
 204 return traverseParentNode(selection->insertionPoint());
 205 }
 206 return traverseParentNodeInCurrentTree(node);
 207}
 208
 209Node* ReifiedTreeWalker::traverseParentNodeInCurrentTree(const Node* node) const
 210{
 211 if (Node* parent = node->parentNode()) {
 212 if (parent->isShadowRoot())
 213 return traverseParentNodeBackToYoungerShadowRootOrHost(toShadowRoot(parent));
 214 return traverseNodeEscapingFallbackContents(parent);
 215 }
 216 return 0;
 217}
 218
 219Node* ReifiedTreeWalker::traverseParentNodeBackToYoungerShadowRootOrHost(const ShadowRoot* shadowRoot) const
 220{
 221 ASSERT(shadowRoot);
 222 if (shadowRoot->isYoungest()) {
 223 if (canCrossUpperBoundary())
 224 return shadowRoot->host();
 225 return 0;
 226 }
 227 InsertionPoint* assignedInsertionPoint = shadowRoot->assignedTo();
 228 ASSERT(assignedInsertionPoint);
 229 return traverseParentNodeOrBackToInsertionPoint(assignedInsertionPoint);
 230}
 231
 232void ReifiedTreeWalker::adjustedParentNode()
 233{
 234 ASSERT(m_node);
 235 if (ShadowTree* shadowTree = shadowTreeOfParent(m_node)) {
 236 if (HTMLContentSelection* selection = shadowTree->selectionFor(m_node)) {
 237 m_node = selection->insertionPoint();
 238 return;
 239 }
 240 }
 241 if (!m_node->isShadowRoot()) {
 242 m_node = m_node->parentNode();
 243 return;
 244 }
 245 const ShadowRoot* shadowRoot = toShadowRoot(m_node);
 246 if (!shadowRoot->isYoungest()) {
 247 ASSERT(shadowRoot->assignedTo());
 248 m_node = shadowRoot->assignedTo();
 249 return;
 250 }
 251 if (canCrossUpperBoundary())
 252 m_node = shadowRoot->host();
 253 else
 254 m_node = 0;
 255}
 256
 257Node* ReifiedTreeWalker::traverseNextSibling(const Node* node)
 258{
 259 ASSERT(node);
 260 return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionForward);
 261}
 262
 263Node* ReifiedTreeWalker::traversePreviousSibling(const Node* node)
 264{
 265 ASSERT(node);
 266 return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionBackward);
 267}
 268
 269void ReifiedTreeWalker::nextNode()
 270{
 271 if (Node* next = traverseFirstChild(m_node)) {
 272 m_node = next;
 273 return;
 274 }
 275 if (Node* next = traverseNextSibling(m_node)) {
 276 m_node = next;
 277 return;
 278 }
 279 const Node* n = m_node;
 280 while (n && !traverseNextSibling(n))
 281 n = traverseParentNode(n);
 282 if (n) {
 283 m_node = traverseNextSibling(n);
 284 return;
 285 }
 286 m_node = 0;
 287}
 288
 289void ReifiedTreeWalker::previousNode()
 290{
 291 if (Node* n = traversePreviousSibling(m_node)) {
 292 while (Node* child = traverseLastChild(n))
 293 n = child;
 294 m_node = n;
 295 return;
 296 }
 297 parentNode();
 298}
 299
 300} // namespace

Source/WebCore/dom/ReifiedTreeWalker.h

 1/*
 2 * Copyright (C) 2012 Google 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 are
 6 * met:
 7 *
 8 * * Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * * Neither the name of Google Inc. nor the names of its
 11 * contributors may be used to endorse or promote products derived from
 12 * this software without specific prior written permission.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25 */
 26
 27#ifndef ReifiedTreeWalker_h
 28#define ReifiedTreeWalker_h
 29
 30namespace WebCore {
 31
 32class Node;
 33class ShadowRoot;
 34
 35class ReifiedTreeWalker {
 36public:
 37 enum Policy {
 38 CrossUpperBoundary,
 39 DoNotCrossUppdrBoundary,
 40 };
 41
 42 inline ReifiedTreeWalker(const Node*, Policy = CrossUpperBoundary);
 43
 44 // For a common use case such as:
 45 // for (ReifiedTreeWalker walker = ReifiedTreeWalker::startedWithFirstChild(node); walker.get(); walker.nextSibling())
 46 static inline ReifiedTreeWalker startedWithFirstChild(const Node*, Policy = CrossUpperBoundary);
 47
 48 Node* get() const { return const_cast<Node*>(m_node); }
 49
 50 void firstChild();
 51 void lastChild();
 52
 53 void nextSibling();
 54 void previousSibling();
 55
 56 void parentNode();
 57
 58 void nextNode();
 59 void previousNode();
 60
 61 // FIXME: An 'adjusted' is not good name for general use case. Rename this.
 62 // https://bugs.webkit.org/show_bug.cgi?id=82022
 63 // This may return ShadowRoot or InsertionPoint.
 64 void adjustedParentNode();
 65
 66private:
 67 enum TraversalDirection {
 68 TraversalDirectionForward,
 69 TraversalDirectionBackward
 70 };
 71
 72 bool canCrossUpperBoundary() const { return m_policy == CrossUpperBoundary; }
 73
 74 static Node* traverseNode(const Node*, TraversalDirection);
 75 static Node* traverseLightChildren(const Node*, TraversalDirection);
 76
 77 Node* traverseFirstChild(const Node*) const;
 78 Node* traverseLastChild(const Node*) const;
 79 Node* traverseChild(const Node*, TraversalDirection) const;
 80 Node* traverseParentNode(const Node*) const;
 81
 82 static Node* traverseNextSibling(const Node*);
 83 static Node* traversePreviousSibling(const Node*);
 84
 85 static Node* traverseSiblingOrBackToInsertionPoint(const Node*, TraversalDirection);
 86 static Node* traverseSiblingInCurrentTree(const Node*, TraversalDirection);
 87
 88 static Node* traverseSiblingOrBackToYoungerShadowRoot(const Node*, TraversalDirection);
 89 static Node* escapeFallbackContentElement(const Node*, TraversalDirection);
 90
 91 Node* traverseNodeEscapingFallbackContents(const Node*) const;
 92
 93 Node* traverseParentNodeOrBackToInsertionPoint(const Node*) const;
 94 Node* traverseParentNodeInCurrentTree(const Node*) const;
 95 Node* traverseParentNodeBackToYoungerShadowRootOrHost(const ShadowRoot*) const;
 96
 97 const Node* m_node;
 98 Policy m_policy;
 99};
 100
 101ReifiedTreeWalker::ReifiedTreeWalker(const Node* node, Policy policy)
 102 : m_node(node)
 103 , m_policy(policy)
 104{
 105}
 106
 107ReifiedTreeWalker ReifiedTreeWalker::startedWithFirstChild(const Node* node, Policy policy)
 108{
 109 ReifiedTreeWalker walker(node, policy);
 110 walker.firstChild();
 111 return walker;
 112}
 113
 114} // namespace
 115
 116#endif

Source/WebCore/testing/Internals.cpp

5151#include "Page.h"
5252#include "Range.h"
5353#include "ReifiedTreeTraversal.h"
 54#include "ReifiedTreeWalker.h"
5455#include "RenderObject.h"
5556#include "RenderTreeAsText.h"
5657#include "Settings.h"

@@bool Internals::attached(Node* node, ExceptionCode& ec)
182183 return node->attached();
183184}
184185
 186Node* Internals::nextSiblingByWalker(Node* node, ExceptionCode& ec)
 187{
 188 if (!node) {
 189 ec = INVALID_ACCESS_ERR;
 190 return 0;
 191 }
 192 ReifiedTreeWalker walker(node);
 193 walker.nextSibling();
 194 return walker.get();
 195}
 196
 197Node* Internals::firstChildByWalker(Node* node, ExceptionCode& ec)
 198{
 199 if (!node) {
 200 ec = INVALID_ACCESS_ERR;
 201 return 0;
 202 }
 203 ReifiedTreeWalker walker(node);
 204 walker.firstChild();
 205 return walker.get();
 206}
 207
 208Node* Internals::lastChildByWalker(Node* node, ExceptionCode& ec)
 209{
 210 if (!node) {
 211 ec = INVALID_ACCESS_ERR;
 212 return 0;
 213 }
 214 ReifiedTreeWalker walker(node);
 215 walker.lastChild();
 216 return walker.get();
 217}
 218
 219Node* Internals::nextNodeByWalker(Node* node, ExceptionCode& ec)
 220{
 221 if (!node) {
 222 ec = INVALID_ACCESS_ERR;
 223 return 0;
 224 }
 225 ReifiedTreeWalker walker(node);
 226 walker.nextNode();
 227 return walker.get();
 228}
 229
 230Node* Internals::previousNodeByWalker(Node* node, ExceptionCode& ec)
 231{
 232 if (!node) {
 233 ec = INVALID_ACCESS_ERR;
 234 return 0;
 235 }
 236 ReifiedTreeWalker walker(node);
 237 walker.previousNode();
 238 return walker.get();
 239}
 240
185241Node* Internals::nextSiblingInReifiedTree(Node* node, ExceptionCode& ec)
186242{
187243 if (!node) {

Source/WebCore/testing/Internals.h

@@public:
8484
8585 bool attached(Node*, ExceptionCode&);
8686
 87 // FIXME: Rename these functions if walker is prefered.
 88 Node* nextSiblingByWalker(Node*, ExceptionCode&);
 89 Node* firstChildByWalker(Node*, ExceptionCode&);
 90 Node* lastChildByWalker(Node*, ExceptionCode&);
 91 Node* nextNodeByWalker(Node*, ExceptionCode&);
 92 Node* previousNodeByWalker(Node*, ExceptionCode&);
 93
8794 Node* nextSiblingInReifiedTree(Node*, ExceptionCode&);
8895 Node* firstChildInReifiedTree(Node*, ExceptionCode&);
8996 Node* lastChildInReifiedTree(Node*, ExceptionCode&);

Source/WebCore/testing/Internals.idl

@@module window {
5555 Element getElementByIdInShadowRoot(in Node shadowRoot, in DOMString id) raises(DOMException);
5656 boolean isValidContentSelect(in Element contentElement) raises(DOMException);
5757
 58 Node nextSiblingByWalker(in Node node) raises(DOMException);
 59 Node firstChildByWalker(in Node node) raises(DOMException);
 60 Node lastChildByWalker(in Node node) raises(DOMException);
 61 Node nextNodeByWalker(in Node node) raises(DOMException);
 62 Node previousNodeByWalker(in Node node) raises(DOMException);
 63
5864 Node nextSiblingInReifiedTree(in Node node) raises(DOMException);
5965 Node firstChildInReifiedTree(in Node node) raises(DOMException);
6066 Node lastChildInReifiedTree(in Node node) raises(DOMException);

@@module window {
126132
127133#if defined(ENABLE_BATTERY_STATUS) && ENABLE_BATTERY_STATUS
128134 void setBatteryStatus(in Document document, in DOMString eventType, in boolean charging, in double chargingTime, in double dischargingTime, in double level) raises (DOMException);
129 #endif
 135#endif
130136
131137 [Conditional=INSPECTOR] unsigned long numberOfLiveNodes();
132138 [Conditional=INSPECTOR] unsigned long numberOfLiveDocuments();

LayoutTests/ChangeLog

 12012-03-26 Hayato Ito <hayato@chromium.org>
 2
 3 [Shadow DOM] Add a Walker class which can traverse a reified tree.
 4 https://bugs.webkit.org/show_bug.cgi?id=82009
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * fast/dom/shadow/reified-tree-walker-expected.txt: Added.
 9 * fast/dom/shadow/reified-tree-walker.html: Added.
 10
1112012-03-26 Ryosuke Niwa <rniwa@webkit.org>
212
313 Rebaseline after r112177.

49254935
49264936 * platform/gtk/http/tests/security/clipboard/clipboard-file-access-expected.txt:
49274937
 49382012-03-22 Hayato Ito <hayato@chromium.org>
 4939
 4940 Benchmark for Reified Teee Traversal APIs.
 4941 https://bugs.webkit.org/show_bug.cgi?id=81495
 4942
 4943 Reviewed by NOBODY (OOPS!).
 4944
 4945 No intention to commit this patch as of now. Just for benchmarking.
 4946
 4947 * fast/dom/shadow/benchmark.html: Added.
 4948
 49492012-03-23 Hayato Ito <hayato@chromium.org>
 4950
 4951 WIP. Walker version.
 4952 https://bugs.webkit.org/show_bug.cgi?id=82009
 4953
 4954 Reviewed by NOBODY (OOPS!).
 4955
 4956 * fast/dom/shadow/reified-tree-walker-expected.txt: Added.
 4957 * fast/dom/shadow/reified-tree-walker.html: Added.
 4958
492849592012-03-21 Xiaomei Ji <xji@chromium.org>
49294960
49304961 [chromium] Font fallback in cr-win is wrong for string contains zero-width-space.

LayoutTests/fast/dom/shadow/reified-tree-walker-expected.txt

 1Tests for Reified DOM Tree Traversal APIs. Can only run within DRT
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5
 6ShadowRoot should be used.
 7Reified Tree:
 8DIV id=a
 9 DIV id=b
 10
 11Traverse in forward.
 12DIV id=a
 13DIV id=b
 14Traverse in backward.
 15DIV id=b
 16DIV id=a
 17
 18A content element should select light children
 19Reified Tree:
 20DIV id=a
 21 DIV id=b
 22 DIV id=c
 23 DIV id=d
 24
 25Traverse in forward.
 26DIV id=a
 27DIV id=b
 28DIV id=c
 29DIV id=d
 30Traverse in backward.
 31DIV id=d
 32DIV id=c
 33DIV id=b
 34DIV id=a
 35
 36Test for content element selector.
 37Reified Tree:
 38DIV id=a
 39 DIV id=b
 40
 41Traverse in forward.
 42DIV id=a
 43Traverse in backward.
 44DIV id=a
 45
 46Light children should be selected only at once.
 47Reified Tree:
 48DIV id=a
 49 DIV id=b
 50
 51Traverse in forward.
 52DIV id=a
 53DIV id=b
 54Traverse in backward.
 55DIV id=e
 56DIV id=d
 57DIV id=c
 58DIV id=a
 59
 60A content element can have fallback elements.
 61Reified Tree:
 62DIV id=a
 63 DIV id=b
 64 DIV id=f1
 65 DIV id=f2
 66
 67Traverse in forward.
 68DIV id=a
 69DIV id=b
 70DIV id=f1
 71DIV id=f2
 72Traverse in backward.
 73DIV id=f2
 74DIV id=f1
 75DIV id=b
 76DIV id=a
 77
 78Fallback elements should not be used if element selects any elements.
 79Reified Tree:
 80DIV id=a
 81 DIV id=b
 82 DIV id=f1
 83 DIV id=f2
 84
 85Traverse in forward.
 86DIV id=a
 87DIV id=b
 88DIV id=f1
 89DIV id=f2
 90Traverse in backward.
 91DIV id=f2
 92DIV id=f1
 93DIV id=b
 94DIV id=a
 95
 96Test for Nested ShadowRoots.
 97Reified Tree:
 98DIV id=a
 99 DIV id=b
 100 DIV id=c
 101 DIV id=e
 102 DIV id=d
 103 DIV id=f
 104 DIV id=h
 105 DIV id=i
 106 DIV id=g
 107
 108Traverse in forward.
 109DIV id=a
 110DIV id=b
 111DIV id=c
 112DIV id=e
 113DIV id=d
 114DIV id=f
 115DIV id=h
 116DIV id=i
 117DIV id=g
 118Traverse in backward.
 119DIV id=g
 120DIV id=i
 121DIV id=h
 122DIV id=f
 123DIV id=d
 124DIV id=e
 125DIV id=c
 126DIV id=b
 127DIV id=a
 128
 129Test for Multiple ShadowRoots.
 130Reified Tree:
 131DIV id=a
 132 DIV id=d
 133 DIV id=b
 134 DIV id=f
 135 DIV id=c
 136 DIV id=e
 137
 138Traverse in forward.
 139DIV id=a
 140DIV id=d
 141DIV id=b
 142DIV id=f
 143DIV id=c
 144DIV id=e
 145Traverse in backward.
 146DIV id=e
 147DIV id=c
 148DIV id=f
 149DIV id=b
 150DIV id=d
 151DIV id=a
 152
 153PASS successfullyParsed is true
 154
 155TEST COMPLETE
 156

LayoutTests/fast/dom/shadow/reified-tree-walker.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../js/resources/js-test-pre.js"></script>
 5<script src="resources/shadow-dom.js"></script>
 6</head>
 7<body>
 8<div id="console"></div>
 9<script>
 10description("Tests for Reified DOM Tree Traversal APIs. Can only run within DRT");
 11
 12if (window.layoutTestController)
 13 layoutTestController.dumpAsText();
 14
 15function dumpNode(node)
 16{
 17 var output = node.nodeName + "\t";
 18 if (node.id)
 19 output += ' id=' + node.id;
 20 if (node.className)
 21 output += ' class=' + node.className;
 22 return output;
 23}
 24
 25function dumpReifiedTree(node, indent)
 26{
 27 indent = indent || "";
 28 var output = indent + dumpNode(node) + "\n";
 29 var child;
 30 for (child = internals.firstChildByWalker(node); child; child = internals.nextSiblingByWalker(child))
 31 output += dumpReifiedTree(child, indent + "\t");
 32 return output;
 33}
 34
 35function lastNodeByWalker(root)
 36{
 37 var lastNode = root;
 38 while (internals.lastChildByWalker(lastNode))
 39 lastNode = internals.lastChildByWalker(lastNode);
 40 return lastNode;
 41}
 42
 43function showReifiedTreeByTraversingInForward(root)
 44{
 45 var node = root;
 46 var last = lastNodeByWalker(root);
 47 while (node) {
 48 debug(dumpNode(node));
 49 if (node == last)
 50 break;
 51 node = internals.nextNodeByWalker(node);
 52 }
 53}
 54
 55function showReifiedTreeByTraversingInBackward(root)
 56{
 57 var node = lastNodeByWalker(root);
 58 while (node) {
 59 debug(dumpNode(node));
 60 if (node == root)
 61 break;
 62 node = internals.previousNodeByWalker(node);
 63 }
 64}
 65
 66function showReifiedTree(node)
 67{
 68 document.body.appendChild(node);
 69 document.body.offsetLeft;
 70
 71 debug('Reified Tree:');
 72 debug(dumpReifiedTree(node));
 73
 74 debug('Traverse in forward.');
 75 showReifiedTreeByTraversingInForward(node);
 76
 77 debug('Traverse in backward.');
 78 showReifiedTreeByTraversingInBackward(node);
 79
 80 debug('');
 81}
 82
 83debug('ShadowRoot should be used.');
 84showReifiedTree(
 85 createDOM('div', {'id': 'a'},
 86 createShadowRoot(createDOM('div', {'id': 'b'})),
 87 createDOM('div', {'id': 'c'})));
 88
 89debug('A content element should select light children');
 90showReifiedTree(
 91 createDOM('div', {'id': 'a'},
 92 createShadowRoot(createDOM('div', {'id': 'b'}),
 93 createDOM('content')),
 94 createDOM('div', {'id': 'c'}),
 95 createDOM('div', {'id': 'd'})));
 96
 97debug('Test for content element selector.');
 98showReifiedTree(
 99 createDOM('div', {'id': 'a'},
 100 createShadowRoot(createDOM('div', {'id': 'b'}),
 101 createDOM('content', {'select': '.d'})),
 102 createDOM('div', {'id': 'c'}),
 103 createDOM('div', {'id': 'd'}),
 104 createDOM('div', {'id': 'e'})));
 105
 106debug('Light children should be selected only at once.');
 107showReifiedTree(
 108 createDOM('div', {'id': 'a'},
 109 createShadowRoot(createDOM('div', {'id': 'b'}),
 110 createDOM('content', {'select': '.d'}),
 111 createDOM('content')),
 112 createDOM('div', {'id': 'c'}),
 113 createDOM('div', {'id': 'd'}),
 114 createDOM('div', {'id': 'e'})));
 115
 116debug('A content element can have fallback elements.');
 117showReifiedTree(
 118 createDOM('div', {'id': 'a'},
 119 createShadowRoot(createDOM('div', {'id': 'b'}),
 120 createDOM('content', {'select': '.z'},
 121 createDOM('div', {'id': 'f1'}),
 122 createDOM('div', {'id': 'f2'}))),
 123 createDOM('div', {'id': 'c'})));
 124
 125debug('Fallback elements should not be used if <content> element selects any elements.');
 126showReifiedTree(
 127 createDOM('div', {'id': 'a'},
 128 createShadowRoot(createDOM('div', {'id': 'b'}),
 129 createDOM('content', {'select': '.c'},
 130 createDOM('div', {'id': 'f1'}),
 131 createDOM('div', {'id': 'f2'}))),
 132 createDOM('div', {'id': 'c'})));
 133
 134debug('Test for Nested ShadowRoots.');
 135showReifiedTree(
 136 createDOM('div', {'id': 'a'},
 137 createShadowRoot(createDOM('div', {'id': 'b'},
 138 createShadowRoot(createDOM('div', {'id': 'c'}),
 139 createDOM('content'),
 140 createDOM('div', {'id': 'd'})),
 141 createDOM('div', {'id': 'e'})),
 142 createDOM('div', {'id': 'f'}),
 143 createDOM('content'),
 144 createDOM('div', {'id': 'g'})),
 145 createDOM('div', {'id': 'h'}),
 146 createDOM('div', {'id': 'i'})));
 147
 148debug('Test for Multiple ShadowRoots.');
 149showReifiedTree(
 150 createDOM('div', {'id': 'a'},
 151 createShadowRoot(createDOM('div', {'id': 'b'}),
 152 createDOM('content'),
 153 createDOM('div', {'id': 'c'})),
 154 createShadowRoot(createDOM('div', {'id': 'd'}),
 155 createDOM('shadow'),
 156 createDOM('div', {'id': 'e'})),
 157 createDOM('div', {'id': 'f'})));
 158
 159</script>
 160<script src="../../js/resources/js-test-post.js"></script>
 161</body>
 162</html>