Make HTMLConverter work across shadow boundaries
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Dec 2018 01:45:24 +0000 (01:45 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Dec 2018 01:45:24 +0000 (01:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192640

Reviewed by Wenson Hsieh.

Source/WebCore:

Made HTMLConverter work with shadow boundaries by replacing the various tree traversal functions.

Tests: editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html
       editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-3.html

* dom/Position.cpp:
(WebCore::commonShadowIncludingAncestor): Moved from markup.cpp to be shared between HTMLConverter
and serializePreservingVisualAppearanceInternal.
* dom/Position.h:
* editing/cocoa/HTMLConverter.mm:
(HTMLConverter::convert):
(HTMLConverterCaches::propertyValueForNode):
(HTMLConverterCaches::floatPropertyValueForNode):
(HTMLConverter::_blockLevelElementForNode):
(HTMLConverterCaches::colorPropertyValueForNode):
(HTMLConverter::aggregatedAttributesForAncestors):
(HTMLConverter::aggregatedAttributesForElementAndItsAncestors):
(HTMLConverter::_processElement):
(HTMLConverter::_traverseNode):
(HTMLConverter::_traverseFooterNode):
(HTMLConverterCaches::cacheAncestorsOfStartToBeConverted):
(WebCore::attributedStringFromSelection):
* editing/markup.cpp:
(WebCore::commonShadowIncludingAncestor): Moved to Position.cpp.

LayoutTests:

Added tests for generating attributed string out across shadow boundaries based on the tests
of respective names in editing/pasteboard.

* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt: Added.
* editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html: Added.
* editing/mac/attributed-string/resources/dump-attributed-string.js:
(window.dumpAttributedString): Now takes start and end containers and offsets.
(serializeSubtreeWithShadow): Added. This function serializes the content of shadow roots along with
start and end markers.
(serializeSubtreeWithShadow.serializeCharacterData): Added.
(serializeSubtreeWithShadow.serializeNode): Added.
(serializeSubtreeWithShadow.serializeChildNodes): Added.
(serializeSubtreeWithShadow.serializeShadowRootAndChildNodes): Added.
(dumpAttributedString): Deleted.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt: Added.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt: Added.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt: Added.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt: Added.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt: Added.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt: Added.
* platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239190 268f45cc-cd09-0410-ab3c-d52691b4dbfc

28 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html [new file with mode: 0644]
LayoutTests/editing/mac/attributed-string/resources/dump-attributed-string.js
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Position.cpp
Source/WebCore/dom/Position.h
Source/WebCore/editing/cocoa/HTMLConverter.mm
Source/WebCore/editing/markup.cpp

index f2c1c3c..dc4e041 100644 (file)
@@ -1,3 +1,44 @@
+2018-12-13  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Make HTMLConverter work across shadow boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=192640
+
+        Reviewed by Wenson Hsieh.
+
+        Added tests for generating attributed string out across shadow boundaries based on the tests
+        of respective names in editing/pasteboard.
+
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt: Added.
+        * editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html: Added.
+        * editing/mac/attributed-string/resources/dump-attributed-string.js:
+        (window.dumpAttributedString): Now takes start and end containers and offsets.
+        (serializeSubtreeWithShadow): Added. This function serializes the content of shadow roots along with
+        start and end markers.
+        (serializeSubtreeWithShadow.serializeCharacterData): Added.
+        (serializeSubtreeWithShadow.serializeNode): Added.
+        (serializeSubtreeWithShadow.serializeChildNodes): Added.
+        (serializeSubtreeWithShadow.serializeShadowRootAndChildNodes): Added.
+        (dumpAttributedString): Deleted.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt: Added.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt: Added.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt: Added.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt: Added.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt: Added.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt: Added.
+        * platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt: Added.
+
 2018-12-13  Youenn Fablet  <youenn@apple.com>
 
         Trying to play a media element synchronously after setting srcObject should succeed without user gesture
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt
new file mode 100644 (file)
index 0000000..dd8de75
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+hello <span id="host"><#shadow-start><slot></slot> WebKit<#shadow-end>world</span> rocks
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello world WebKit rocks]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html
new file mode 100644 (file)
index 0000000..82d4517
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container">hello <span id="host">world</span> rocks</div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot = host.attachShadow({mode: 'open'});
+shadowRoot.innerHTML = '<slot></slot> WebKit';
+
+if (window.testRunner)
+    dumpAttributedString(document.getElementById('container'));
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt
new file mode 100644 (file)
index 0000000..9757abd
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+hello <span id="host"><#shadow-start><slot></slot> WebKit<#shadow-end><#start>world</span> rocks<#end>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[world WebKit rocks]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html
new file mode 100644 (file)
index 0000000..30b4902
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container">hello <span id="host">world</span> rocks</div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot = host.attachShadow({mode: 'open'});
+shadowRoot.innerHTML = '<slot></slot> WebKit';
+
+if (window.testRunner)
+    dumpAttributedString(container, host.firstChild, 0, container.lastChild, container.lastChild.data.length);
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt
new file mode 100644 (file)
index 0000000..cbe8c1d
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+<span id="host"><#shadow-start>hello <slot></slot><#shadow-end><#start>world WebKit</span> rocks<#end>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[world WebKit rocks]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html
new file mode 100644 (file)
index 0000000..3256b4c
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container"><span id="host">world WebKit</span> rocks</div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot = host.attachShadow({mode: 'open'});
+shadowRoot.innerHTML = 'hello <slot></slot>';
+
+if (window.testRunner)
+    dumpAttributedString(container, host.firstChild, 0, container.lastChild, container.lastChild.data.length);
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt
new file mode 100644 (file)
index 0000000..1bd97d1
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+<span id="host"><#shadow-start><#start>hello <slot></slot><#shadow-end>world Web<#end>Kit</span> rocks
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello world Web]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html
new file mode 100644 (file)
index 0000000..eedd574
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container"><span id="host">world WebKit</span> rocks</div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot = host.attachShadow({mode: 'open'});
+shadowRoot.innerHTML = 'hello <slot></slot>';
+
+if (window.testRunner)
+    dumpAttributedString(container, shadowRoot, 0, host.firstChild, host.firstChild.data.indexOf('Kit'));
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt
new file mode 100644 (file)
index 0000000..1503266
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+<#start><span id="host"><#shadow-start>hello <slot></slot><span style="display:none;"></span><#shadow-end>world</span> WebKit<#end>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello world WebKit]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html
new file mode 100644 (file)
index 0000000..a954b2d
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container"><span id="host">world</span> WebKit</div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot = host.attachShadow({mode: 'open'});
+shadowRoot.innerHTML = 'hello <slot></slot><span style="display:none;"></span>';
+
+if (window.testRunner)
+    dumpAttributedString(container, container, 0, container, container.childNodes.length);
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt
new file mode 100644 (file)
index 0000000..7bc3c4f
--- /dev/null
@@ -0,0 +1,42 @@
+Input:
+<#start><b>hello <span id="host"><#shadow-start><slot style="color: blue;"></slot> Web<#end>Kit<#shadow-end>world</span></b> rocks
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello ]
+    NSFont: Times-Bold 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+[world]
+    NSColor: #0000ff (sRGB)
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #0000ff (sRGB)
+    NSStrokeWidth: 0
+[ Web]
+    NSFont: Times-Bold 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html
new file mode 100644 (file)
index 0000000..f722672
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container"><b>hello <span id="host">world</span></b> rocks</div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot = host.attachShadow({mode: 'open'});
+shadowRoot.innerHTML = '<slot style="color: blue;"></slot> WebKit';
+
+if (window.testRunner)
+    dumpAttributedString(container, container, 0, shadowRoot.lastChild, shadowRoot.lastChild.data.indexOf('Kit'));
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt
new file mode 100644 (file)
index 0000000..ebfb060
--- /dev/null
@@ -0,0 +1,43 @@
+Input:
+<#start><div style="font-style: italic" id="host1"><#shadow-start><slot style="color: blue;"></slot> world<#shadow-end><b>hello</b></div><div id="host2"><#shadow-start><u>WebKit <#end><slot></slot></u><#shadow-end>rocks</div>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello]
+    NSColor: #0000ff (sRGB)
+    NSFont: Times-Italic 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #0000ff (sRGB)
+    NSStrokeWidth: 0
+[ world\n]
+    NSFont: Times-Italic 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+[WebKit ]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (sRGB)
+    NSStrokeWidth: 0
+    NSUnderline: true
+
diff --git a/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html b/LayoutTests/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html
new file mode 100644 (file)
index 0000000..bca4696
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container"><div style="font-style: italic" id="host1"><b>hello</b></div><div id="host2">rocks</div></div>
+<script src="resources/dump-attributed-string.js"></script>
+<script>
+
+const shadowRoot1 = host1.attachShadow({mode: 'open'});
+shadowRoot1.innerHTML = '<slot style="color: blue;"></slot> world';
+
+const shadowRoot2 = host2.attachShadow({mode: 'open'});
+shadowRoot2.innerHTML = '<u>WebKit <slot></slot></u>';
+
+if (window.testRunner)
+    dumpAttributedString(container, container, 0, shadowRoot2.querySelector('u'), 1);
+
+</script>
+</body>
+</html>
index e556011..2647f22 100644 (file)
@@ -4,22 +4,85 @@ var shouldAutoDump = true;
     if (window.testRunner)
         testRunner.dumpAsText();
 
-    function dumpAttributedString(container) {
+    window.dumpAttributedString = function dumpAttributedString(root = document.body, startContainer, startOffset, endContainer, endOffset) {
         shouldAutoDump = false;
 
-        var body = document.body;
-        if (!container)
-            container = body;
+        const markup = serializeSubtreeWithShadow(root, startContainer, startOffset, endContainer, endOffset).trim();
 
-        var range = document.createRange();
-        range.selectNodeContents(container);
+        if (!startContainer)
+            startContainer = root;
+        if (startOffset == undefined)
+            startOffset = 0;
+        if (!endContainer)
+            endContainer = root;
+        if (endOffset == undefined)
+            endOffset = endContainer.childNodes.length;
 
-        var pre = document.createElement('pre');
-        var result = serializeAttributedString(textInputController.legacyAttributedString(container, 0, container, container.childNodes.length));
-        pre.textContent = 'Input:\n' + container.innerHTML.trim() + '\n\nOutput:\n' + result;
+        const pre = document.createElement('pre');
+        const result = serializeAttributedString(textInputController.legacyAttributedString(startContainer, startOffset, endContainer, endOffset));
+        pre.textContent = 'Input:\n' + markup + '\n\nOutput:\n' + result;
 
-        body.innerHTML = '';
-        body.appendChild(pre);
+        document.body.innerHTML = '';
+        document.body.appendChild(pre);
+    }
+
+    function serializeSubtreeWithShadow(parent, startContainer, startOffset, endContainer, endOffset) {
+        function serializeCharacterData(node) {
+            let data = node.data;
+            let result = data;
+            if (node == startContainer && node == endContainer) {
+                result = data.substring(0, startOffset);
+                result += '<#start>';
+                result = data.substring(startOffset, endOffset);
+                result += '<#end>';
+                result += data.substring(endOffset);
+            } else if (node == startContainer) {
+                result = data.substring(0, startOffset);
+                result += '<#start>';
+                result += data.substring(startOffset);
+            } else if (node == endContainer) {
+                result = data.substring(0, endOffset);
+                result += '<#end>';
+                result += data.substring(endOffset);
+            }
+            return result;
+        }
+
+        function serializeNode(node) {
+            if (node.nodeType == Node.TEXT_NODE)
+                return serializeCharacterData(node);
+            if (node.nodeType == Node.COMMENT_NODE)
+                return '<!--' + node.nodeValue + '-->';
+            if (node.nodeType == Node.CDATA_SECTION_NODE)
+                return '<!--[CDATA[' + node.nodeValue + '-->';
+
+            const elementTags = node.cloneNode(false).outerHTML;
+            const endTagIndex = elementTags.lastIndexOf('</');
+            const startTag = endTagIndex >= 0 ? elementTags.substring(0, endTagIndex) : elementTags;
+            const endTag = endTagIndex >= 0 ? elementTags.substring(endTagIndex) : '';
+            return startTag + serializeShadowRootAndChildNodes(node) + endTag;
+        }
+
+        function serializeChildNodes(node) {
+            let result = '';
+            for (let i = 0; i < node.childNodes.length; i++) {
+                if (node == startContainer && i == startOffset)
+                    result += '<#start>';
+                result += serializeNode(node.childNodes[i]);
+                if (node == endContainer && i + 1 == endOffset)
+                    result += '<#end>';
+            }
+            return result;
+        }
+
+        function serializeShadowRootAndChildNodes(node) {
+            const shadowRoot = node.nodeType == Node.ELEMENT_NODE ? internals.shadowRoot(node) : null;
+            if (!shadowRoot)
+                return serializeChildNodes(node);
+            return `<#shadow-start>${serializeChildNodes(shadowRoot)}<#shadow-end>${serializeChildNodes(node)}`;
+        }
+
+        return serializeShadowRootAndChildNodes(parent);
     }
 
     window.serializeAttributedString = function (attributedString) {
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1-expected.txt
new file mode 100644 (file)
index 0000000..f6af1e5
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+hello <span id="host"><#shadow-start><slot></slot> WebKit<#shadow-end>world</span> rocks
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello world WebKit rocks]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2-expected.txt
new file mode 100644 (file)
index 0000000..93dd775
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+hello <span id="host"><#shadow-start><slot></slot> WebKit<#shadow-end><#start>world</span> rocks<#end>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[world WebKit rocks]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3-expected.txt
new file mode 100644 (file)
index 0000000..e0a6c0e
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+<span id="host"><#shadow-start>hello <slot></slot><#shadow-end><#start>world WebKit</span> rocks<#end>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[world WebKit rocks]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4-expected.txt
new file mode 100644 (file)
index 0000000..c63c4ae
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+<span id="host"><#shadow-start><#start>hello <slot></slot><#shadow-end>world Web<#end>Kit</span> rocks
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello world Web]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5-expected.txt
new file mode 100644 (file)
index 0000000..8dff373
--- /dev/null
@@ -0,0 +1,31 @@
+Input:
+<#start><span id="host"><#shadow-start>hello <slot></slot><span style="display:none;"></span><#shadow-end>world</span> WebKit<#end>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello world WebKit]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1-expected.txt
new file mode 100644 (file)
index 0000000..63afb27
--- /dev/null
@@ -0,0 +1,42 @@
+Input:
+<#start><b>hello <span id="host"><#shadow-start><slot style="color: blue;"></slot> Web<#end>Kit<#shadow-end>world</span></b> rocks
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello ]
+    NSFont: Times-Bold 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+[world]
+    NSColor: #0000ff (NSCustomColorSpace)
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #0000ff (NSCustomColorSpace)
+    NSStrokeWidth: 0
+[ Web]
+    NSFont: Times-Bold 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+
diff --git a/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt b/LayoutTests/platform/mac-sierra/editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2-expected.txt
new file mode 100644 (file)
index 0000000..214cddd
--- /dev/null
@@ -0,0 +1,43 @@
+Input:
+<#start><div style="font-style: italic" id="host1"><#shadow-start><slot style="color: blue;"></slot> world<#shadow-end><b>hello</b></div><div id="host2"><#shadow-start><u>WebKit <#end><slot></slot></u><#shadow-end>rocks</div>
+
+Output:
+NSParagraphStyle:
+Alignment 4
+    LineSpacing: 0
+    ParagraphSpacing: 0
+    ParagraphSpacingBefore: 0
+    HeadIndent: 0
+    TailIndent: 0
+    FirstLineHeadIndent: 0
+    LineHeight: 0/0
+    LineHeightMultiple: 0
+    LineBreakMode: 0
+    Tabs: ()
+    DefaultTabInterval: 36
+    Blocks: (
+)
+    Lists: (
+)
+    BaseWritingDirection: 0
+    HyphenationFactor: 0
+    TighteningForTruncation: YES
+    HeaderLevel: 0
+[hello]
+    NSColor: #0000ff (NSCustomColorSpace)
+    NSFont: Times-BoldItalic 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #0000ff (NSCustomColorSpace)
+    NSStrokeWidth: 0
+[ world\n]
+    NSFont: Times-Italic 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+[WebKit ]
+    NSFont: Times-Roman 16.00 pt.
+    NSKern: 0pt
+    NSStrokeColor: #000000 (NSCustomColorSpace)
+    NSStrokeWidth: 0
+    NSUnderline: true
+
index a7f8cfa..2aa32c2 100644 (file)
@@ -1,3 +1,41 @@
+2018-12-13  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Make HTMLConverter work across shadow boundaries
+        https://bugs.webkit.org/show_bug.cgi?id=192640
+
+        Reviewed by Wenson Hsieh.
+
+        Made HTMLConverter work with shadow boundaries by replacing the various tree traversal functions.
+
+        Tests: editing/mac/attributed-string/attributed-string-across-shadow-boundaries-1.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-2.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-3.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-4.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-5.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-1.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-2.html
+               editing/mac/attributed-string/attributed-string-across-shadow-boundaries-with-style-3.html
+
+        * dom/Position.cpp:
+        (WebCore::commonShadowIncludingAncestor): Moved from markup.cpp to be shared between HTMLConverter
+        and serializePreservingVisualAppearanceInternal.
+        * dom/Position.h:
+        * editing/cocoa/HTMLConverter.mm:
+        (HTMLConverter::convert):
+        (HTMLConverterCaches::propertyValueForNode):
+        (HTMLConverterCaches::floatPropertyValueForNode):
+        (HTMLConverter::_blockLevelElementForNode):
+        (HTMLConverterCaches::colorPropertyValueForNode):
+        (HTMLConverter::aggregatedAttributesForAncestors):
+        (HTMLConverter::aggregatedAttributesForElementAndItsAncestors):
+        (HTMLConverter::_processElement):
+        (HTMLConverter::_traverseNode):
+        (HTMLConverter::_traverseFooterNode):
+        (HTMLConverterCaches::cacheAncestorsOfStartToBeConverted):
+        (WebCore::attributedStringFromSelection):
+        * editing/markup.cpp:
+        (WebCore::commonShadowIncludingAncestor): Moved to Position.cpp.
+
 2018-12-13  Youenn Fablet  <youenn@apple.com>
 
         Trying to play a media element synchronously after setting srcObject should succeed without user gesture
index d167a7e..f23627f 100644 (file)
@@ -1601,6 +1601,18 @@ TextStream& operator<<(TextStream& stream, const Position& position)
     return stream;
 }
 
+RefPtr<Node> commonShadowIncludingAncestor(const Position& a, const Position& b)
+{
+    auto* commonScope = commonTreeScope(a.containerNode(), b.containerNode());
+    if (!commonScope)
+        return nullptr;
+    auto* nodeA = commonScope->ancestorNodeInThisScope(a.containerNode());
+    ASSERT(nodeA);
+    auto* nodeB = commonScope->ancestorNodeInThisScope(b.containerNode());
+    ASSERT(nodeB);
+    return Range::commonAncestorContainer(nodeA, nodeB);
+}
+
 } // namespace WebCore
 
 #if ENABLE(TREE_DEBUGGING)
index 2f15868..77df853 100644 (file)
@@ -333,6 +333,8 @@ inline bool offsetIsBeforeLastNodeOffset(int offset, Node* anchorNode)
     return offset < currentOffset;
 }
 
+RefPtr<Node> commonShadowIncludingAncestor(const Position&, const Position&);
+
 WTF::TextStream& operator<<(WTF::TextStream&, const Position&);
 
 } // namespace WebCore
index d3b9d76..fb47eef 100644 (file)
@@ -34,6 +34,7 @@
 #import "CharacterData.h"
 #import "ColorCocoa.h"
 #import "ColorMac.h"
+#import "ComposedTreeIterator.h"
 #import "Document.h"
 #import "DocumentLoader.h"
 #import "Editing.h"
@@ -494,12 +495,12 @@ NSAttributedString *HTMLConverter::convert()
     m_dataSource = commonAncestorContainer->document().frame()->loader().documentLoader();
     if (!m_dataSource)
         return nil;
-    
+
     _domRangeStartIndex = 0;
     _traverseNode(*commonAncestorContainer, 0, false /* embedded */);
     if (_domRangeStartIndex > 0 && _domRangeStartIndex <= [_attrStr length])
         [_attrStr deleteCharactersInRange:NSMakeRange(0, _domRangeStartIndex)];
-    
+
     return [[_attrStr retain] autorelease];
 }
 
@@ -665,7 +666,7 @@ static bool stringFromCSSValue(CSSValue& value, String& result)
 String HTMLConverterCaches::propertyValueForNode(Node& node, CSSPropertyID propertyId)
 {
     if (!is<Element>(node)) {
-        if (Node* parent = node.parentNode())
+        if (Node* parent = node.parentInComposedTree())
             return propertyValueForNode(*parent, propertyId);
         return String();
     }
@@ -773,7 +774,7 @@ String HTMLConverterCaches::propertyValueForNode(Node& node, CSSPropertyID prope
     }
 
     if (inherit) {
-        if (Node* parent = node.parentNode())
+        if (Node* parent = node.parentInComposedTree())
             return propertyValueForNode(*parent, propertyId);
     }
     
@@ -810,7 +811,7 @@ static inline bool floatValueFromPrimitiveValue(CSSPrimitiveValue& primitiveValu
 bool HTMLConverterCaches::floatPropertyValueForNode(Node& node, CSSPropertyID propertyId, float& result)
 {
     if (!is<Element>(node)) {
-        if (ContainerNode* parent = node.parentNode())
+        if (ContainerNode* parent = node.parentInComposedTree())
             return floatPropertyValueForNode(*parent, propertyId, result);
         return false;
     }
@@ -843,7 +844,7 @@ bool HTMLConverterCaches::floatPropertyValueForNode(Node& node, CSSPropertyID pr
     }
 
     if (inherit) {
-        if (ContainerNode* parent = node.parentNode())
+        if (ContainerNode* parent = node.parentInComposedTree())
             return floatPropertyValueForNode(*parent, propertyId, result);
     }
 
@@ -950,7 +951,7 @@ Element* HTMLConverter::_blockLevelElementForNode(Node* node)
 {
     Element* element = node->parentElement();
     if (element && !_caches->isBlockElement(*element))
-        element = _blockLevelElementForNode(element->parentNode());
+        element = _blockLevelElementForNode(element->parentInComposedTree());
     return element;
 }
 
@@ -969,7 +970,7 @@ static Color normalizedColor(Color color, bool ignoreBlack)
 Color HTMLConverterCaches::colorPropertyValueForNode(Node& node, CSSPropertyID propertyId)
 {
     if (!is<Element>(node)) {
-        if (Node* parent = node.parentNode())
+        if (Node* parent = node.parentInComposedTree())
             return colorPropertyValueForNode(*parent, propertyId);
         return Color();
     }
@@ -1005,7 +1006,7 @@ Color HTMLConverterCaches::colorPropertyValueForNode(Node& node, CSSPropertyID p
     }
 
     if (inherit) {
-        if (Node* parent = node.parentNode())
+        if (Node* parent = node.parentInComposedTree())
             return colorPropertyValueForNode(*parent, propertyId);
     }
 
@@ -1261,9 +1262,9 @@ NSDictionary* HTMLConverter::attributesForElement(Element& element)
 
 NSDictionary* HTMLConverter::aggregatedAttributesForAncestors(CharacterData& node)
 {
-    Node* ancestor = node.parentNode();
+    Node* ancestor = node.parentInComposedTree();
     while (ancestor && !is<Element>(*ancestor))
-        ancestor = ancestor->parentNode();
+        ancestor = ancestor->parentInComposedTree();
     if (!ancestor)
         return nullptr;
     return aggregatedAttributesForElementAndItsAncestors(downcast<Element>(*ancestor));
@@ -1278,9 +1279,9 @@ NSDictionary* HTMLConverter::aggregatedAttributesForElementAndItsAncestors(Eleme
     NSDictionary* attributesForCurrentElement = attributesForElement(element);
     ASSERT(attributesForCurrentElement);
 
-    Node* ancestor = element.parentNode();
+    Node* ancestor = element.parentInComposedTree();
     while (ancestor && !is<Element>(*ancestor))
-        ancestor = ancestor->parentNode();
+        ancestor = ancestor->parentInComposedTree();
 
     if (!ancestor) {
         cachedAttributes = attributesForCurrentElement;
@@ -1852,7 +1853,7 @@ BOOL HTMLConverter::_processElement(Element& element, NSInteger depth)
         Element* tableElement = &element;
         if (displayValue == "table-row-group") {
             // If we are starting in medias res, the first thing we see may be the tbody, so go up to the table
-            tableElement = _blockLevelElementForNode(element.parentNode());
+            tableElement = _blockLevelElementForNode(element.parentInComposedTree());
             if (!tableElement || _caches->propertyValueForNode(*tableElement, CSSPropertyDisplay) != "table")
                 tableElement = &element;
         }
@@ -1923,7 +1924,7 @@ BOOL HTMLConverter::_processElement(Element& element, NSInteger depth)
             retval = NO;
         }
     } else if (element.hasTagName(brTag)) {
-        Element* blockElement = _blockLevelElementForNode(element.parentNode());
+        Element* blockElement = _blockLevelElementForNode(element.parentInComposedTree());
         NSString *breakClass = element.getAttribute(classAttr);
         NSString *blockTag = blockElement ? (NSString *)blockElement->tagName() : nil;
         BOOL isExtraBreak = [@"Apple-interchange-newline" isEqualToString:breakClass];
@@ -2285,17 +2286,18 @@ void HTMLConverter::_traverseNode(Node& node, unsigned depth, bool embedded)
     bool isStart = false;
     bool isEnd = false;
     if (&node == m_start.containerNode()) {
-        startOffset = m_start.offsetInContainerNode();
+        startOffset = m_start.computeOffsetInContainerNode();
         isStart = true;
         _flags.reachedStart = YES;
     }
     if (&node == m_end.containerNode()) {
-        endOffset = m_end.offsetInContainerNode();
+        endOffset = m_end.computeOffsetInContainerNode();
         isEnd = true;
     }
     
     if (node.isDocumentNode() || node.isDocumentFragment()) {
         Node* child = node.firstChild();
+        ASSERT(child == firstChildInComposedTreeIgnoringUserAgentShadow(node));
         for (NSUInteger i = 0; child; i++) {
             if (isStart && i == startOffset)
                 _domRangeStartIndex = [_attrStr length];
@@ -2305,6 +2307,7 @@ void HTMLConverter::_traverseNode(Node& node, unsigned depth, bool embedded)
                 _flags.reachedEnd = YES;
             if (_flags.reachedEnd)
                 break;
+            ASSERT(child->nextSibling() == nextSiblingInComposedTreeIgnoringUserAgentShadow(*child));
             child = child->nextSibling();
         }
     } else if (is<Element>(node)) {
@@ -2312,17 +2315,21 @@ void HTMLConverter::_traverseNode(Node& node, unsigned depth, bool embedded)
         if (_enterElement(element, embedded)) {
             NSUInteger startIndex = [_attrStr length];
             if (_processElement(element, depth)) {
-                Node* child = node.firstChild();
-                for (NSUInteger i = 0; child; i++) {
-                    if (isStart && i == startOffset)
-                        _domRangeStartIndex = [_attrStr length];
-                    if ((!isStart || startOffset <= i) && (!isEnd || endOffset > i))
-                        _traverseNode(*child, depth + 1, embedded);
-                    if (isEnd && i + 1 >= endOffset)
-                        _flags.reachedEnd = YES;
-                    if (_flags.reachedEnd)
-                        break;
-                    child = child->nextSibling();
+                if (auto* shadowRoot = shadowRootIgnoringUserAgentShadow(element)) // Traverse through shadow root to detect start and end.
+                    _traverseNode(*shadowRoot, depth + 1, embedded);
+                else {
+                    auto* child = firstChildInComposedTreeIgnoringUserAgentShadow(node);
+                    for (NSUInteger i = 0; child; i++) {
+                        if (isStart && i == startOffset)
+                            _domRangeStartIndex = [_attrStr length];
+                        if ((!isStart || startOffset <= i) && (!isEnd || endOffset > i))
+                            _traverseNode(*child, depth + 1, embedded);
+                        if (isEnd && i + 1 >= endOffset)
+                            _flags.reachedEnd = YES;
+                        if (_flags.reachedEnd)
+                            break;
+                        child = nextSiblingInComposedTreeIgnoringUserAgentShadow(*child);
+                    }
                 }
                 _exitElement(element, depth, startIndex);
             }
@@ -2346,19 +2353,19 @@ void HTMLConverter::_traverseFooterNode(Element& element, unsigned depth)
     bool isStart = false;
     bool isEnd = false;
     if (&element == m_start.containerNode()) {
-        startOffset = m_start.offsetInContainerNode();
+        startOffset = m_start.computeOffsetInContainerNode();
         isStart = true;
         _flags.reachedStart = YES;
     }
     if (&element == m_end.containerNode()) {
-        endOffset = m_end.offsetInContainerNode();
+        endOffset = m_end.computeOffsetInContainerNode();
         isEnd = true;
     }
     
     if (_enterElement(element, YES)) {
         NSUInteger startIndex = [_attrStr length];
         if (_processElement(element, depth)) {
-            Node* child = element.firstChild();
+            auto* child = firstChildInComposedTreeIgnoringUserAgentShadow(element);
             for (NSUInteger i = 0; child; i++) {
                 if (isStart && i == startOffset)
                     _domRangeStartIndex = [_attrStr length];
@@ -2368,7 +2375,7 @@ void HTMLConverter::_traverseFooterNode(Element& element, unsigned depth)
                     _flags.reachedEnd = YES;
                 if (_flags.reachedEnd)
                     break;
-                child = child->nextSibling();
+                child = nextSiblingInComposedTreeIgnoringUserAgentShadow(*child);
             }
             _exitElement(element, depth, startIndex);
         }
@@ -2388,17 +2395,17 @@ void HTMLConverter::_adjustTrailingNewline()
 
 Node* HTMLConverterCaches::cacheAncestorsOfStartToBeConverted(const Position& start, const Position& end)
 {
-    Node* commonAncestor = Range::commonAncestorContainer(start.containerNode(), end.containerNode());
+    auto commonAncestor = commonShadowIncludingAncestor(start, end);
     Node* ancestor = start.containerNode();
 
     while (ancestor) {
         m_ancestorsUnderCommonAncestor.add(ancestor);
         if (ancestor == commonAncestor)
             break;
-        ancestor = ancestor->parentNode();
+        ancestor = ancestor->parentInComposedTree();
     }
 
-    return commonAncestor;
+    return commonAncestor.get();
 }
 
 #if !PLATFORM(IOS_FAMILY)
@@ -2465,9 +2472,7 @@ NSAttributedString *attributedStringFromRange(Range& range)
 
 NSAttributedString *attributedStringFromSelection(const VisibleSelection& selection)
 {
-    auto range = selection.toNormalizedRange();
-    ASSERT(range);
-    return attributedStringBetweenStartAndEnd(range->startPosition(), range->endPosition());
+    return attributedStringBetweenStartAndEnd(selection.start(), selection.end());
 }
 
 NSAttributedString *attributedStringBetweenStartAndEnd(const Position& start, const Position& end)
index 124ea5b..795b12d 100644 (file)
@@ -818,18 +818,6 @@ static Node* highestAncestorToWrapMarkup(const Position& start, const Position&
     return specialCommonAncestor;
 }
 
-static RefPtr<Node> commonShadowIncludingAncestor(const Position& a, const Position& b)
-{
-    TreeScope* commonScope = commonTreeScope(a.containerNode(), b.containerNode());
-    if (!commonScope)
-        return nullptr;
-    auto* nodeA = commonScope->ancestorNodeInThisScope(a.containerNode());
-    ASSERT(nodeA);
-    auto* nodeB = commonScope->ancestorNodeInThisScope(b.containerNode());
-    ASSERT(nodeB);
-    return Range::commonAncestorContainer(nodeA, nodeB);
-}
-
 static String serializePreservingVisualAppearanceInternal(const Position& start, const Position& end, Vector<Node*>* nodes, ResolveURLs urlsToResolve, SerializeComposedTree serializeComposedTree,
     AnnotateForInterchange annotate, ConvertBlocksToInlines convertBlocksToInlines, MSOListMode msoListMode)
 {