Diff
Modified: trunk/LayoutTests/ChangeLog (190982 => 190983)
--- trunk/LayoutTests/ChangeLog 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/ChangeLog 2015-10-13 13:12:25 UTC (rev 190983)
@@ -1,3 +1,23 @@
+2015-10-12 Antti Koivisto <[email protected]>
+
+ Implement iterator for traversing composed DOM
+ https://bugs.webkit.org/show_bug.cgi?id=149997
+
+ Reviewed by Ryosuke Niwa.
+
+ * TestExpectations:
+
+ Re-enable fast/html/details-replace-text.html which is fixed by this change.
+
+ * fast/forms/select-listbox-focus-displaynone-expected.txt:
+ * fast/repaint/text-in-relative-positioned-inline-expected.txt:
+ * fullscreen/full-screen-fixed-pos-parent-expected.txt:
+ * platform/mac-mavericks/fast/html/details-open2-expected.txt:
+ * platform/mac/fast/html/details-add-child-2-expected.txt:
+ * platform/mac/fast/html/details-open2-expected.txt:
+
+ Non-visual whitespace changes.
+
2015-10-12 Zalan Bujtas <[email protected]>
[Win] Update anonymous table results for Windows port.
Modified: trunk/LayoutTests/TestExpectations (190982 => 190983)
--- trunk/LayoutTests/TestExpectations 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/TestExpectations 2015-10-13 13:12:25 UTC (rev 190983)
@@ -672,7 +672,6 @@
webkit.org/b/149082 http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overridesexpires.html [ Pass Failure ]
webkit.org/b/148695 fast/shadow-dom [ Failure ImageOnlyFailure ]
-webkit.org/b/149997 fast/html/details-replace-text.html [ Failure ]
# Marks as flaky (see also https://bugs.webkit.org/show_bug.cgi?id=132388)
Modified: trunk/LayoutTests/fast/forms/select-listbox-focus-displaynone-expected.txt (190982 => 190983)
--- trunk/LayoutTests/fast/forms/select-listbox-focus-displaynone-expected.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/fast/forms/select-listbox-focus-displaynone-expected.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -1 +1 @@
- PASS
+ PASS
Modified: trunk/LayoutTests/fast/repaint/text-in-relative-positioned-inline-expected.txt (190982 => 190983)
--- trunk/LayoutTests/fast/repaint/text-in-relative-positioned-inline-expected.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/fast/repaint/text-in-relative-positioned-inline-expected.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -4,5 +4,4 @@
RenderBlock {HTML} at (0,0) size 800x600
RenderBody {BODY} at (8,8) size 784x584
RenderBlock {DIV} at (100,0) size 684x100
- RenderText {#text} at (0,0) size 0x0
RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#008000]
Modified: trunk/LayoutTests/fullscreen/full-screen-fixed-pos-parent-expected.txt (190982 => 190983)
--- trunk/LayoutTests/fullscreen/full-screen-fixed-pos-parent-expected.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/fullscreen/full-screen-fixed-pos-parent-expected.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -1,2 +1 @@
-
Modified: trunk/LayoutTests/platform/mac/fast/html/details-add-child-2-expected.txt (190982 => 190983)
--- trunk/LayoutTests/platform/mac/fast/html/details-add-child-2-expected.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/platform/mac/fast/html/details-add-child-2-expected.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -12,3 +12,5 @@
RenderInline {B} at (0,0) size 144x18
RenderText {#text} at (0,0) size 144x18
text run at (0,0) width 144: "should have bold test"
+ RenderText {#text} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
Modified: trunk/LayoutTests/platform/mac/fast/html/details-open2-expected.txt (190982 => 190983)
--- trunk/LayoutTests/platform/mac/fast/html/details-open2-expected.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/platform/mac/fast/html/details-open2-expected.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -10,5 +10,7 @@
text run at (16,0) width 61: "summary"
RenderBlock (anonymous) at (0,18) size 784x23
RenderTextControl {INPUT} at (2,2) size 137x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
layer at (13,31) size 130x13
RenderBlock {DIV} at (3,3) size 131x13
Modified: trunk/LayoutTests/platform/mac-mavericks/fast/html/details-open2-expected.txt (190982 => 190983)
--- trunk/LayoutTests/platform/mac-mavericks/fast/html/details-open2-expected.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/LayoutTests/platform/mac-mavericks/fast/html/details-open2-expected.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -10,5 +10,7 @@
text run at (16,0) width 61: "summary"
RenderBlock (anonymous) at (0,18) size 784x23
RenderTextControl {INPUT} at (2,2) size 146x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
layer at (13,31) size 139x13
RenderBlock {DIV} at (3,3) size 140x13
Modified: trunk/Source/WebCore/CMakeLists.txt (190982 => 190983)
--- trunk/Source/WebCore/CMakeLists.txt 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/CMakeLists.txt 2015-10-13 13:12:25 UTC (rev 190983)
@@ -1412,6 +1412,7 @@
dom/ClipboardEvent.cpp
dom/CollectionIndexCache.cpp
dom/Comment.cpp
+ dom/ComposedTreeIterator.cpp
dom/CompositionEvent.cpp
dom/ContainerNode.cpp
dom/ContainerNodeAlgorithms.cpp
Modified: trunk/Source/WebCore/ChangeLog (190982 => 190983)
--- trunk/Source/WebCore/ChangeLog 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/ChangeLog 2015-10-13 13:12:25 UTC (rev 190983)
@@ -1,3 +1,74 @@
+2015-10-12 Antti Koivisto <[email protected]>
+
+ Implement iterator for traversing composed DOM
+ https://bugs.webkit.org/show_bug.cgi?id=149997
+
+ Reviewed by Ryosuke Niwa.
+
+ ComposedTreeIterator traverses the DOM in composed tree order. This means it enters
+ shadow trees and follows slots created by Shadow DOM API correctly.
+
+ auto children = composedTreeChildren(containerNode);
+ for (auto& composedChild : children)
+ ...
+
+ auto descendants = composedTreeDescendants(containerNode);
+ for (auto& composedDescendant : descendants)
+ ...
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/ComposedTreeIterator.cpp: Added.
+ (WebCore::ComposedTreeIterator::initializeShadowStack):
+ (WebCore::ComposedTreeIterator::traverseNextInShadowTree):
+ (WebCore::ComposedTreeIterator::traverseNextSiblingSlot):
+ (WebCore::ComposedTreeIterator::traversePreviousSiblingSlot):
+ (WebCore::ComposedTreeIterator::traverseParentInShadowTree):
+ * dom/ComposedTreeIterator.h: Added.
+ (WebCore::ComposedTreeIterator::operator*):
+ (WebCore::ComposedTreeIterator::operator->):
+ (WebCore::ComposedTreeIterator::operator==):
+ (WebCore::ComposedTreeIterator::operator!=):
+ (WebCore::ComposedTreeIterator::ShadowContext::ShadowContext):
+ (WebCore::ComposedTreeIterator::ComposedTreeIterator):
+ (WebCore::ComposedTreeIterator::traverseNext):
+ (WebCore::ComposedTreeIterator::traverseNextSibling):
+ (WebCore::ComposedTreeIterator::traversePreviousSibling):
+ (WebCore::ComposedTreeIterator::traverseParent):
+ (WebCore::ComposedTreeChildAdapter::Iterator::Iterator):
+ (WebCore::ComposedTreeChildAdapter::Iterator::operator++):
+ (WebCore::ComposedTreeChildAdapter::Iterator::operator--):
+ (WebCore::ComposedTreeChildAdapter::ComposedTreeChildAdapter):
+ (WebCore::ComposedTreeChildAdapter::begin):
+ (WebCore::ComposedTreeChildAdapter::end):
+ (WebCore::ComposedTreeChildAdapter::at):
+ (WebCore::composedTreeChildren):
+ * dom/NodeRenderingTraversal.cpp:
+ (WebCore::NodeRenderingTraversal::parentSlow):
+ (WebCore::NodeRenderingTraversal::nextInScope):
+ (WebCore::NodeRenderingTraversal::firstChildSlow): Deleted.
+ (WebCore::NodeRenderingTraversal::nextSiblingSlow): Deleted.
+ (WebCore::NodeRenderingTraversal::previousSiblingSlow): Deleted.
+ * dom/NodeRenderingTraversal.h:
+ (WebCore::NodeRenderingTraversal::parent):
+ (WebCore::NodeRenderingTraversal::firstChild): Deleted.
+ (WebCore::NodeRenderingTraversal::nextSibling): Deleted.
+ (WebCore::NodeRenderingTraversal::previousSibling): Deleted.
+ * style/RenderTreePosition.cpp:
+ (WebCore::RenderTreePosition::computeNextSibling):
+
+ Restore the full assert.
+
+ (WebCore::RenderTreePosition::invalidateNextSibling):
+ (WebCore::RenderTreePosition::previousSiblingRenderer):
+ (WebCore::RenderTreePosition::nextSiblingRenderer):
+
+ Make these member functions.
+ Use the iterator. This is fixes some bugs and allows enabling a test case.
+
+ * style/RenderTreePosition.h:
+ * style/StyleResolveTree.cpp:
+ (WebCore::Style::textRendererIsNeeded):
+
2015-10-13 ChangSeok Oh <[email protected]>
[GTK] Use GUniquePtr for GtkIconInfo
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (190982 => 190983)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2015-10-13 13:12:25 UTC (rev 190983)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugSuffix|Win32">
@@ -13705,6 +13705,20 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="..\dom\ComposedTreeIterator.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug_WinCairo|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug_WinCairo|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WinCairo|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WinCairo|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
+ </ClCompile>
<ClCompile Include="..\dom\CompositionEvent.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -21949,6 +21963,7 @@
<ClInclude Include="..\dom\ClipboardEvent.h" />
<ClInclude Include="..\dom\CollectionIndexCache.h" />
<ClInclude Include="..\dom\Comment.h" />
+ <ClInclude Include="..\dom\ComposedTreeIterator.h" />
<ClInclude Include="..\dom\CompositionEvent.h" />
<ClInclude Include="..\dom\ContainerNode.h" />
<ClInclude Include="..\dom\ContextDestructionObserver.h" />
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (190982 => 190983)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2015-10-13 13:12:25 UTC (rev 190983)
@@ -6422,6 +6422,8 @@
E44B4BB3141650D7002B1D8B /* SelectorChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E44B4BB1141650D7002B1D8B /* SelectorChecker.cpp */; };
E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = E44B4BB2141650D7002B1D8B /* SelectorChecker.h */; };
E44EE3A817577EBD00EEE8CF /* FontGenericFamilies.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E44EE3A617576E5500EEE8CF /* FontGenericFamilies.cpp */; };
+ E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E44FA1841BCA6B5A0091B6EF /* ComposedTreeIterator.h */; settings = {ASSET_TAGS = (); }; };
+ E44FA1871BCA91560091B6EF /* ComposedTreeIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E44FA1861BCA91560091B6EF /* ComposedTreeIterator.cpp */; settings = {ASSET_TAGS = (); }; };
E45322AB140CE267005A0F92 /* SelectorQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E45322A9140CE267005A0F92 /* SelectorQuery.cpp */; };
E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E45322AA140CE267005A0F92 /* SelectorQuery.h */; };
E453901D0EAFCACA003695C8 /* MIMETypeRegistryIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E45390180EAFCACA003695C8 /* MIMETypeRegistryIOS.mm */; };
@@ -14240,6 +14242,8 @@
E44B4BB2141650D7002B1D8B /* SelectorChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorChecker.h; sourceTree = "<group>"; };
E44EE3A617576E5500EEE8CF /* FontGenericFamilies.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FontGenericFamilies.cpp; sourceTree = "<group>"; };
E44EE3A717576E5500EEE8CF /* FontGenericFamilies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontGenericFamilies.h; sourceTree = "<group>"; };
+ E44FA1841BCA6B5A0091B6EF /* ComposedTreeIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComposedTreeIterator.h; sourceTree = "<group>"; };
+ E44FA1861BCA91560091B6EF /* ComposedTreeIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComposedTreeIterator.cpp; sourceTree = "<group>"; };
E45322A9140CE267005A0F92 /* SelectorQuery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectorQuery.cpp; sourceTree = "<group>"; };
E45322AA140CE267005A0F92 /* SelectorQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectorQuery.h; sourceTree = "<group>"; };
E45390180EAFCACA003695C8 /* MIMETypeRegistryIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MIMETypeRegistryIOS.mm; sourceTree = "<group>"; };
@@ -23525,6 +23529,8 @@
6550B697099DF0270090D781 /* Comment.cpp */,
6550B698099DF0270090D781 /* Comment.h */,
85089CC70A98C22600A275AA /* Comment.idl */,
+ E44FA1861BCA91560091B6EF /* ComposedTreeIterator.cpp */,
+ E44FA1841BCA6B5A0091B6EF /* ComposedTreeIterator.h */,
79F2F59E1091939A000D87CB /* CompositionEvent.cpp */,
79F2F59F1091939A000D87CB /* CompositionEvent.h */,
79F2F5A01091939A000D87CB /* CompositionEvent.idl */,
@@ -26123,6 +26129,7 @@
B27B28260CEF0C0700D39D54 /* JSSVGFontElement.h in Headers */,
A83B79050CCAFF15000B0825 /* JSSVGFontFaceElement.h in Headers */,
A83B79000CCAFF15000B0825 /* JSSVGFontFaceFormatElement.h in Headers */,
+ E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */,
A83B79020CCAFF15000B0825 /* JSSVGFontFaceNameElement.h in Headers */,
A83B78FE0CCAFF15000B0825 /* JSSVGFontFaceSrcElement.h in Headers */,
A83B78FC0CCAFF15000B0825 /* JSSVGFontFaceUriElement.h in Headers */,
@@ -29980,6 +29987,7 @@
517A63C41B74318B00E7DCDC /* KeyedEncoderCF.cpp in Sources */,
A513B3D8114B166A001C429B /* KeyEventCocoa.mm in Sources */,
2655413A1489811C000DFC5D /* KeyEventIOS.mm in Sources */,
+ E44FA1871BCA91560091B6EF /* ComposedTreeIterator.cpp in Sources */,
935C477009AC4D7300A6AAB4 /* KeyEventMac.mm in Sources */,
316FE1190E6E1DA700BF6088 /* KeyframeAnimation.cpp in Sources */,
BC5EBA100E823E4700B25965 /* KeyframeList.cpp in Sources */,
Added: trunk/Source/WebCore/dom/ComposedTreeIterator.cpp (0 => 190983)
--- trunk/Source/WebCore/dom/ComposedTreeIterator.cpp (rev 0)
+++ trunk/Source/WebCore/dom/ComposedTreeIterator.cpp 2015-10-13 13:12:25 UTC (rev 190983)
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ComposedTreeIterator.h"
+
+#include "HTMLSlotElement.h"
+
+namespace WebCore {
+
+void ComposedTreeIterator::initializeShadowStack()
+{
+ // This code sets up the iterator for arbitrary node/root pair. It is not needed in common cases
+ // or completes fast because node and root are close (like in composedTreeChildren(*parent).at(node) case).
+ auto* node = m_current;
+ while (node != &m_root) {
+ auto* parent = node->parentNode();
+ if (!parent) {
+ m_current = nullptr;
+ return;
+ }
+ if (is<ShadowRoot>(*parent)) {
+ auto& shadowRoot = downcast<ShadowRoot>(*parent);
+ if (m_shadowStack.isEmpty() || m_shadowStack.last().host != shadowRoot.host())
+ m_shadowStack.append(shadowRoot.host());
+ node = shadowRoot.host();
+ continue;
+ }
+ if (auto* shadowRoot = parent->shadowRoot()) {
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ m_shadowStack.append(shadowRoot->host());
+ auto* assignedSlot = shadowRoot->findAssignedSlot(*node);
+ if (assignedSlot) {
+ size_t index = assignedSlot->assignedNodes()->find(node);
+ ASSERT(index != notFound);
+
+ m_shadowStack.last().currentSlot = assignedSlot;
+ m_shadowStack.last().currentSlotNodeIndex = index;
+ node = assignedSlot;
+ continue;
+ }
+ // The node is not part of the composed tree.
+#else
+ m_current = nullptr;
+ return;
+#endif
+ }
+ node = parent;
+ }
+ m_shadowStack.reverse();
+}
+
+void ComposedTreeIterator::traverseNextInShadowTree()
+{
+ ASSERT(!m_shadowStack.isEmpty());
+
+ auto* shadowContext = &m_shadowStack.last();
+
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ if (is<HTMLSlotElement>(*m_current) && !shadowContext->currentSlot) {
+ auto& slot = downcast<HTMLSlotElement>(*m_current);
+ if (auto* assignedNodes = slot.assignedNodes()) {
+ shadowContext->currentSlot = &slot;
+ shadowContext->currentSlotNodeIndex = 0;
+ m_current = assignedNodes->at(0);
+ return;
+ }
+ }
+#endif
+
+ m_current = NodeTraversal::next(*m_current, shadowContext->host);
+
+ while (!m_current) {
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ if (auto* slot = shadowContext->currentSlot) {
+ bool nextNodeInSameSlot = ++shadowContext->currentSlotNodeIndex < slot->assignedNodes()->size();
+ if (nextNodeInSameSlot) {
+ m_current = slot->assignedNodes()->at(shadowContext->currentSlotNodeIndex);
+ return;
+ }
+ m_current = NodeTraversal::nextSkippingChildren(*slot, shadowContext->host);
+ shadowContext->currentSlot = nullptr;
+ continue;
+ }
+#endif
+ auto& previousHost = *shadowContext->host;
+ m_shadowStack.removeLast();
+
+ if (m_shadowStack.isEmpty()) {
+ m_current = NodeTraversal::nextSkippingChildren(previousHost, &m_root);
+ return;
+ }
+ shadowContext = &m_shadowStack.last();
+ m_current = NodeTraversal::nextSkippingChildren(previousHost, shadowContext->host);
+ }
+}
+
+void ComposedTreeIterator::traverseParentInShadowTree()
+{
+ ASSERT(!m_shadowStack.isEmpty());
+
+ auto& shadowContext = m_shadowStack.last();
+
+ auto* parent = m_current->parentNode();
+ if (is<ShadowRoot>(parent)) {
+ ASSERT(shadowContext.host == downcast<ShadowRoot>(*parent).host());
+
+ m_current = shadowContext.host;
+ m_shadowStack.removeLast();
+ return;
+ }
+ if (parent->shadowRoot()) {
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ ASSERT(shadowContext.host == parent);
+
+ auto* slot = shadowContext.currentSlot;
+ ASSERT(slot->assignedNodes()->at(shadowContext.currentSlotNodeIndex) == m_current);
+
+ m_current = slot;
+ shadowContext.currentSlot = nullptr;
+ return;
+#else
+ m_current = nullptr;
+ return;
+#endif
+ }
+ m_current = parent;
+}
+
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+void ComposedTreeIterator::traverseNextSiblingSlot()
+{
+ ASSERT(m_current->parentNode()->shadowRoot());
+ ASSERT(!m_shadowStack.isEmpty());
+ ASSERT(m_shadowStack.last().host == m_current->parentNode());
+
+ auto& shadowContext = m_shadowStack.last();
+
+ if (!shadowContext.currentSlot) {
+ m_current = nullptr;
+ return;
+ }
+ auto* slotNodes = shadowContext.currentSlot->assignedNodes();
+ ASSERT(slotNodes->at(shadowContext.currentSlotNodeIndex) == m_current);
+
+ bool nextNodeInSameSlot = ++shadowContext.currentSlotNodeIndex < slotNodes->size();
+ m_current = nextNodeInSameSlot ? slotNodes->at(shadowContext.currentSlotNodeIndex) : nullptr;
+}
+
+void ComposedTreeIterator::traversePreviousSiblingSlot()
+{
+ ASSERT(m_current->parentNode()->shadowRoot());
+ ASSERT(!m_shadowStack.isEmpty());
+ ASSERT(m_shadowStack.last().host == m_current->parentNode());
+
+ auto& shadowContext = m_shadowStack.last();
+
+ if (!shadowContext.currentSlot) {
+ m_current = nullptr;
+ return;
+ }
+ auto* slotNodes = shadowContext.currentSlot->assignedNodes();
+ ASSERT(slotNodes->at(shadowContext.currentSlotNodeIndex) == m_current);
+
+ bool previousNodeInSameSlot = shadowContext.currentSlotNodeIndex > 0;
+ m_current = previousNodeInSameSlot ? slotNodes->at(--shadowContext.currentSlotNodeIndex) : nullptr;
+}
+#endif
+
+}
Added: trunk/Source/WebCore/dom/ComposedTreeIterator.h (0 => 190983)
--- trunk/Source/WebCore/dom/ComposedTreeIterator.h (rev 0)
+++ trunk/Source/WebCore/dom/ComposedTreeIterator.h 2015-10-13 13:12:25 UTC (rev 190983)
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "HTMLSlotElement.h"
+#include "NodeTraversal.h"
+#include "ShadowRoot.h"
+
+#ifndef ComposedTreeIterator_h
+#define ComposedTreeIterator_h
+
+namespace WebCore {
+
+class HTMLSlotElement;
+
+class ComposedTreeIterator {
+public:
+ ComposedTreeIterator(ContainerNode& root);
+ ComposedTreeIterator(ContainerNode& root, Node& current);
+
+ Node& operator*() { return *m_current; }
+ Node* operator->() { return m_current; }
+
+ bool operator==(const ComposedTreeIterator& other) const { return m_current == other.m_current; }
+ bool operator!=(const ComposedTreeIterator& other) const { return m_current != other.m_current; }
+
+ ComposedTreeIterator& operator++() { return traverseNextSibling(); }
+
+ ComposedTreeIterator& traverseNext();
+ ComposedTreeIterator& traverseNextSibling();
+ ComposedTreeIterator& traversePreviousSibling();
+ ComposedTreeIterator& traverseParent();
+
+private:
+ void initializeShadowStack();
+ void traverseNextInShadowTree();
+ void traverseParentInShadowTree();
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ void traverseNextSiblingSlot();
+ void traversePreviousSiblingSlot();
+#endif
+
+ ContainerNode& m_root;
+ Node* m_current { 0 };
+
+ struct ShadowContext {
+ ShadowContext(Element* host)
+ : host(host)
+ { }
+
+ Element* host;
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ HTMLSlotElement* currentSlot { nullptr };
+ unsigned currentSlotNodeIndex { 0 };
+#endif
+ };
+ Vector<ShadowContext, 4> m_shadowStack;
+};
+
+inline ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root)
+ : m_root(root)
+{
+ ASSERT(!is<ShadowRoot>(m_root));
+}
+
+inline ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root, Node& current)
+ : m_root(root)
+ , m_current(¤t)
+{
+ ASSERT(!is<ShadowRoot>(m_root));
+ ASSERT(!is<ShadowRoot>(m_current));
+
+ bool mayNeedShadowStack = m_root.shadowRoot() || (m_current != &m_root && current.parentNode() != &m_root);
+ if (mayNeedShadowStack)
+ initializeShadowStack();
+}
+
+inline ComposedTreeIterator& ComposedTreeIterator::traverseNext()
+{
+ if (auto* shadowRoot = m_current->shadowRoot()) {
+ m_shadowStack.append(shadowRoot->host());
+ m_current = shadowRoot;
+ }
+
+ if (m_shadowStack.isEmpty())
+ m_current = NodeTraversal::next(*m_current, &m_root);
+ else
+ traverseNextInShadowTree();
+
+ return *this;
+}
+
+inline ComposedTreeIterator& ComposedTreeIterator::traverseNextSibling()
+{
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ bool isAssignedToSlot = !m_shadowStack.isEmpty() && m_current->parentNode()->shadowRoot();
+ if (isAssignedToSlot) {
+ traverseNextSiblingSlot();
+ return *this;
+ }
+#endif
+ m_current = m_current->nextSibling();
+ return *this;
+}
+
+inline ComposedTreeIterator& ComposedTreeIterator::traversePreviousSibling()
+{
+#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
+ bool isAssignedToSlot = !m_shadowStack.isEmpty() && m_current->parentNode()->shadowRoot();
+ if (isAssignedToSlot) {
+ traversePreviousSiblingSlot();
+ return *this;
+ }
+#endif
+ m_current = m_current->previousSibling();
+ return *this;
+}
+
+inline ComposedTreeIterator& ComposedTreeIterator::traverseParent()
+{
+ if (m_shadowStack.isEmpty())
+ m_current = m_current->parentNode();
+ else
+ traverseParentInShadowTree();
+
+ return *this;
+}
+
+class ComposedTreeDescendantAdapter {
+public:
+ ComposedTreeDescendantAdapter(ContainerNode& parent)
+ : m_parent(parent)
+ { }
+
+ ComposedTreeIterator begin() { return ComposedTreeIterator(m_parent, m_parent).traverseNext(); }
+ ComposedTreeIterator end() { return ComposedTreeIterator(m_parent); }
+ ComposedTreeIterator at(const Node& child) { return ComposedTreeIterator(m_parent, const_cast<Node&>(child)); }
+
+private:
+ ContainerNode& m_parent;
+};
+
+class ComposedTreeChildAdapter {
+public:
+ class Iterator : public ComposedTreeIterator {
+ public:
+ Iterator(ContainerNode& root)
+ : ComposedTreeIterator(root)
+ { }
+ Iterator(ContainerNode& root, Node& current)
+ : ComposedTreeIterator(root, current)
+ { }
+
+ Iterator& operator++() { return static_cast<Iterator&>(traverseNextSibling()); }
+ Iterator& operator--() { return static_cast<Iterator&>(traversePreviousSibling()); }
+ };
+
+ ComposedTreeChildAdapter(ContainerNode& parent)
+ : m_parent(parent)
+ { }
+
+ Iterator begin() { return static_cast<Iterator&>(Iterator(m_parent, m_parent).traverseNext()); }
+ Iterator end() { return Iterator(m_parent); }
+ Iterator at(const Node& child) { return Iterator(m_parent, const_cast<Node&>(child)); }
+
+private:
+ ContainerNode& m_parent;
+};
+
+// FIXME: We should have const versions too.
+inline ComposedTreeDescendantAdapter composedTreeDescendants(ContainerNode& parent)
+{
+ return ComposedTreeDescendantAdapter(parent);
+}
+
+inline ComposedTreeChildAdapter composedTreeChildren(ContainerNode& parent)
+{
+ return ComposedTreeChildAdapter(parent);
+}
+
+}
+
+#endif
Modified: trunk/Source/WebCore/dom/DOMAllInOne.cpp (190982 => 190983)
--- trunk/Source/WebCore/dom/DOMAllInOne.cpp 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/dom/DOMAllInOne.cpp 2015-10-13 13:12:25 UTC (rev 190983)
@@ -42,6 +42,7 @@
#include "ClipboardEvent.cpp"
#include "CollectionIndexCache.cpp"
#include "Comment.cpp"
+#include "ComposedTreeIterator.cpp"
#include "CompositionEvent.cpp"
#include "ContainerNode.cpp"
#include "ContainerNodeAlgorithms.cpp"
Modified: trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp (190982 => 190983)
--- trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/dom/NodeRenderingTraversal.cpp 2015-10-13 13:12:25 UTC (rev 190983)
@@ -95,27 +95,6 @@
return traverseParent(node, CrossShadowRoot);
}
-Node* firstChildSlow(const Node* node)
-{
- ASSERT(!node->isShadowRoot());
-
- return traverseFirstChild(node, DontCrossShadowRoot);
-}
-
-Node* nextSiblingSlow(const Node* node)
-{
- ASSERT(!node->isShadowRoot());
-
- return traverseNextSibling(node);
-}
-
-Node* previousSiblingSlow(const Node* node)
-{
- ASSERT(!node->isShadowRoot());
-
- return traversePreviousSibling(node);
-}
-
Node* nextInScope(const Node* node)
{
if (Node* next = traverseFirstChild(node, DontCrossShadowRoot))
Modified: trunk/Source/WebCore/dom/NodeRenderingTraversal.h (190982 => 190983)
--- trunk/Source/WebCore/dom/NodeRenderingTraversal.h 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/dom/NodeRenderingTraversal.h 2015-10-13 13:12:25 UTC (rev 190983)
@@ -35,9 +35,6 @@
namespace NodeRenderingTraversal {
ContainerNode* parent(const Node*);
-Node* firstChild(const Node*);
-Node* nextSibling(const Node*);
-Node* previousSibling(const Node*);
Node* nextInScope(const Node*);
Node* previousInScope(const Node*);
@@ -45,9 +42,6 @@
Node* lastChildInScope(const Node*);
ContainerNode* parentSlow(const Node*);
-Node* firstChildSlow(const Node*);
-Node* nextSiblingSlow(const Node*);
-Node* previousSiblingSlow(const Node*);
inline ContainerNode* parent(const Node* node)
{
@@ -59,38 +53,8 @@
return node->parentNodeGuaranteedHostFree();
}
-inline Node* firstChild(const Node* node)
-{
- ASSERT(!node->isPseudoElement());
- if (node->needsNodeRenderingTraversalSlowPath())
- return firstChildSlow(node);
-
- ASSERT(nextSiblingSlow(node) == node->nextSibling());
- return node->firstChild();
}
-inline Node* nextSibling(const Node* node)
-{
- ASSERT(!node->isPseudoElement());
- if (node->needsNodeRenderingTraversalSlowPath())
- return nextSiblingSlow(node);
-
- ASSERT(nextSiblingSlow(node) == node->nextSibling());
- return node->nextSibling();
-}
-
-inline Node* previousSibling(const Node* node)
-{
- ASSERT(!node->isPseudoElement());
- if (node->needsNodeRenderingTraversalSlowPath())
- return previousSiblingSlow(node);
-
- ASSERT(previousSiblingSlow(node) == node->previousSibling());
- return node->previousSibling();
-}
-
-}
-
} // namespace WebCore
#endif
Modified: trunk/Source/WebCore/style/RenderTreePosition.cpp (190982 => 190983)
--- trunk/Source/WebCore/style/RenderTreePosition.cpp 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/style/RenderTreePosition.cpp 2015-10-13 13:12:25 UTC (rev 190983)
@@ -26,6 +26,7 @@
#include "config.h"
#include "RenderTreePosition.h"
+#include "ComposedTreeIterator.h"
#include "NodeRenderingTraversal.h"
#include "PseudoElement.h"
#include "RenderObject.h"
@@ -40,14 +41,11 @@
#if !ASSERT_DISABLED
const unsigned _oNSquaredAvoidanceLimit_ = 20;
bool skipAssert = m_parent.isRenderView() || ++m_assertionLimitCounter > oNSquaredAvoidanceLimit;
- // FIXME: Traversal needs to know about slots and this needs be removed.
- skipAssert = skipAssert || (node.parentElement() && node.parentElement()->shadowRoot());
-
- ASSERT(skipAssert || nextSiblingRenderer(node, m_parent) == m_nextSibling);
+ ASSERT(skipAssert || nextSiblingRenderer(node) == m_nextSibling);
#endif
return;
}
- m_nextSibling = nextSiblingRenderer(node, m_parent);
+ m_nextSibling = nextSiblingRenderer(node);
m_hasValidNextSibling = true;
}
@@ -59,35 +57,41 @@
m_hasValidNextSibling = false;
}
-RenderObject* RenderTreePosition::previousSiblingRenderer(const Text& textNode)
+RenderObject* RenderTreePosition::previousSiblingRenderer(const Text& textNode) const
{
if (textNode.renderer())
return textNode.renderer()->previousSibling();
- for (Node* sibling = NodeRenderingTraversal::previousSibling(&textNode); sibling; sibling = NodeRenderingTraversal::previousSibling(sibling)) {
- RenderObject* renderer = sibling->renderer();
+
+ auto* parentElement = m_parent.element();
+
+ auto composedChildren = composedTreeChildren(*parentElement);
+ for (auto it = composedChildren.at(textNode), end = composedChildren.end(); it != end; --it) {
+ RenderObject* renderer = it->renderer();
if (renderer && !RenderTreePosition::isRendererReparented(*renderer))
return renderer;
}
- if (auto* parent = textNode.parentElement()) {
- if (auto* before = parent->beforePseudoElement())
- return before->renderer();
- }
+ if (auto* before = parentElement->beforePseudoElement())
+ return before->renderer();
return nullptr;
}
-RenderObject* RenderTreePosition::nextSiblingRenderer(const Node& node, const RenderElement& parentRenderer)
+RenderObject* RenderTreePosition::nextSiblingRenderer(const Node& node) const
{
- if (!parentRenderer.element())
+ auto* parentElement = m_parent.element();
+ if (!parentElement)
return nullptr;
if (node.isAfterPseudoElement())
return nullptr;
- Node* sibling = node.isBeforePseudoElement() ? NodeRenderingTraversal::firstChild(parentRenderer.element()) : NodeRenderingTraversal::nextSibling(&node);
- for (; sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
- RenderObject* renderer = sibling->renderer();
+
+ auto composedChildren = composedTreeChildren(*parentElement);
+
+ auto it = node.isBeforePseudoElement() ? composedChildren.begin() : composedChildren.at(node);
+ for (auto end = composedChildren.end(); it != end; ++it) {
+ RenderObject* renderer = it->renderer();
if (renderer && !isRendererReparented(*renderer))
return renderer;
}
- if (PseudoElement* after = parentRenderer.element()->afterPseudoElement())
+ if (PseudoElement* after = parentElement->afterPseudoElement())
return after->renderer();
return nullptr;
}
Modified: trunk/Source/WebCore/style/RenderTreePosition.h (190982 => 190983)
--- trunk/Source/WebCore/style/RenderTreePosition.h 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/style/RenderTreePosition.h 2015-10-13 13:12:25 UTC (rev 190983)
@@ -61,8 +61,8 @@
void computeNextSibling(const Node&);
void invalidateNextSibling(const RenderObject&);
- static RenderObject* previousSiblingRenderer(const Text&);
- static RenderObject* nextSiblingRenderer(const Node&, const RenderElement& parentRenderer);
+ RenderObject* previousSiblingRenderer(const Text&) const;
+ RenderObject* nextSiblingRenderer(const Node&) const;
static bool isRendererReparented(const RenderObject&);
private:
Modified: trunk/Source/WebCore/style/StyleResolveTree.cpp (190982 => 190983)
--- trunk/Source/WebCore/style/StyleResolveTree.cpp 2015-10-13 13:05:37 UTC (rev 190982)
+++ trunk/Source/WebCore/style/StyleResolveTree.cpp 2015-10-13 13:12:25 UTC (rev 190983)
@@ -30,6 +30,7 @@
#include "AnimationController.h"
#include "AuthorStyleSheets.h"
#include "CSSFontSelector.h"
+#include "ComposedTreeIterator.h"
#include "ElementIterator.h"
#include "ElementRareData.h"
#include "FlowThreadController.h"
@@ -262,7 +263,7 @@
if (parentRenderer.style().preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
return true;
- RenderObject* previousRenderer = RenderTreePosition::previousSiblingRenderer(textNode);
+ RenderObject* previousRenderer = renderTreePosition.previousSiblingRenderer(textNode);
if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span>
return false;
@@ -277,7 +278,7 @@
RenderObject* first = parentRenderer.firstChild();
while (first && first->isFloatingOrOutOfFlowPositioned())
first = first->nextSibling();
- RenderObject* nextRenderer = RenderTreePosition::nextSiblingRenderer(textNode, parentRenderer);
+ RenderObject* nextRenderer = renderTreePosition.nextSiblingRenderer(textNode);
if (!first || nextRenderer == first) {
// Whitespace at the start of a block just goes away. Don't even make a render object for this text.
return false;