Title: [196998] trunk
Revision
196998
Author
[email protected]
Date
2016-02-23 14:35:44 -0800 (Tue, 23 Feb 2016)

Log Message

Calling importNode on shadow root causes a crash
https://bugs.webkit.org/show_bug.cgi?id=154570

Reviewed by Anders Carlsson.

Source/WebCore:

The bug was caused by a missing check in cloneNode. Added cloneNodeForBindings to explicitly throw
an NotSupportedError when it's called on a shadow root. We don't clone shadow root when deep-cloning
the tree so we don't have to check that condition.

The behavior of cloneNode is specified at:
http://w3c.github.io/webcomponents/spec/shadow/#the-shadowroot-interface
(it current says we should throw DATA_CLONE_ERR but I have an spec bug filed at
https://github.com/w3c/webcomponents/issues/393)

The behavior of importNode and adoptNode are specified in DOM4 specification:
https://dom.spec.whatwg.org/#dom-document-importnode
https://dom.spec.whatwg.org/#dom-document-adoptnode

Tests: fast/shadow-dom/Document-prototype-adoptNode.html
       fast/shadow-dom/Document-prototype-importNode.html
       fast/shadow-dom/Node-prototype-cloneNode.html

* dom/Document.cpp:
(WebCore::Document::importNode): Throw NotSupportedError when importing a shadow root.
* dom/Node.cpp:
(WebCore::Node::cloneNodeForBindings): Added.
* dom/Node.h:
* dom/Node.idl: Use cloneNodeForBindings here.

LayoutTests:

Added W3C-style testharness tests for calling cloneNode on a shadow root.

Also added tests for adoptNode and importNode.

* fast/shadow-dom/Document-prototype-adoptNode-expected.txt: Added.
* fast/shadow-dom/Document-prototype-adoptNode.html: Added.
* fast/shadow-dom/Document-prototype-importNode-expected.txt: Added.
* fast/shadow-dom/Document-prototype-importNode.html: Added.
* fast/shadow-dom/Node-prototype-cloneNode-expected.txt: Added.
* fast/shadow-dom/Node-prototype-cloneNode.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (196997 => 196998)


--- trunk/LayoutTests/ChangeLog	2016-02-23 22:29:01 UTC (rev 196997)
+++ trunk/LayoutTests/ChangeLog	2016-02-23 22:35:44 UTC (rev 196998)
@@ -1,3 +1,21 @@
+2016-02-22  Ryosuke Niwa  <[email protected]>
+
+        Calling importNode on shadow root causes a crash
+        https://bugs.webkit.org/show_bug.cgi?id=154570
+
+        Reviewed by Anders Carlsson.
+
+        Added W3C-style testharness tests for calling cloneNode on a shadow root.
+
+        Also added tests for adoptNode and importNode.
+
+        * fast/shadow-dom/Document-prototype-adoptNode-expected.txt: Added.
+        * fast/shadow-dom/Document-prototype-adoptNode.html: Added.
+        * fast/shadow-dom/Document-prototype-importNode-expected.txt: Added.
+        * fast/shadow-dom/Document-prototype-importNode.html: Added.
+        * fast/shadow-dom/Node-prototype-cloneNode-expected.txt: Added.
+        * fast/shadow-dom/Node-prototype-cloneNode.html: Added.
+
 2016-02-23  Daniel Bates  <[email protected]>
 
         REGRESSION (r196892): No longer emit error message when CSP form-action directive is used as a source _expression_

Added: trunk/LayoutTests/fast/shadow-dom/Document-prototype-adoptNode-expected.txt (0 => 196998)


--- trunk/LayoutTests/fast/shadow-dom/Document-prototype-adoptNode-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Document-prototype-adoptNode-expected.txt	2016-02-23 22:35:44 UTC (rev 196998)
@@ -0,0 +1,4 @@
+
+PASS adoptNode on a shadow root in open mode must throw a HierarchyRequestError 
+PASS adoptNode on a shadow root in closed mode must throw a HierarchyRequestError 
+

Added: trunk/LayoutTests/fast/shadow-dom/Document-prototype-adoptNode.html (0 => 196998)


--- trunk/LayoutTests/fast/shadow-dom/Document-prototype-adoptNode.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Document-prototype-adoptNode.html	2016-02-23 22:35:44 UTC (rev 196998)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>DOM and Shadow DOM: Document.prototype.adoptNode</title>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="The adoptNode(node) method must throw a HierarchyRequestError exception if node is a shadow root.">
+<link rel="help" href=""
+<script src=""
+<script src=""
+<link rel='stylesheet' href=''>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+function testAdoptNode(mode) {
+    test(function () {
+        var newDocument = document.implementation.createHTMLDocument();
+        assert_throws({'name': 'HierarchyRequestError'}, function () {
+            var element = document.createElement('div');
+            var shadowRoot = element.attachShadow({mode: mode});
+            newDocument.adoptNode(shadowRoot);
+        });
+    }, 'adoptNode on a shadow root in ' + mode + ' mode must throw a HierarchyRequestError');
+}
+
+testAdoptNode('open');
+testAdoptNode('closed');
+
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/shadow-dom/Document-prototype-importNode-expected.txt (0 => 196998)


--- trunk/LayoutTests/fast/shadow-dom/Document-prototype-importNode-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Document-prototype-importNode-expected.txt	2016-02-23 22:35:44 UTC (rev 196998)
@@ -0,0 +1,4 @@
+
+PASS importNode on a shadow root in open mode must throw a NotSupportedError 
+PASS importNode on a shadow root in closed mode must throw a NotSupportedError 
+

Added: trunk/LayoutTests/fast/shadow-dom/Document-prototype-importNode.html (0 => 196998)


--- trunk/LayoutTests/fast/shadow-dom/Document-prototype-importNode.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Document-prototype-importNode.html	2016-02-23 22:35:44 UTC (rev 196998)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>DOM and Shadow DOM: Document.prototype.importNode</title>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="The importNode(node, deep) method must throw a NotSupportedError exception if node is a shadow root.">
+<link rel="help" href=""
+<script src=""
+<script src=""
+<link rel='stylesheet' href=''>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+function testImportNode(mode) {
+    test(function () {
+        var newDocument = document.implementation.createHTMLDocument();
+        assert_throws({'name': 'NotSupportedError'}, function () {
+            var element = document.createElement('div');
+            var shadowRoot = element.attachShadow({mode: mode});
+            newDocument.importNode(shadowRoot);
+        });
+    }, 'importNode on a shadow root in ' + mode + ' mode must throw a NotSupportedError');
+}
+
+testImportNode('open');
+testImportNode('closed');
+
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/shadow-dom/Node-prototype-cloneNode-expected.txt (0 => 196998)


--- trunk/LayoutTests/fast/shadow-dom/Node-prototype-cloneNode-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Node-prototype-cloneNode-expected.txt	2016-02-23 22:35:44 UTC (rev 196998)
@@ -0,0 +1,5 @@
+
+PASS cloneNode on a shadow root in open mode must throw a NotSupportedError 
+PASS cloneNode on a shadow root in closed mode must throw a NotSupportedError 
+PASS cloneNode on an open shadow root must throw a NotSupportedError 
+

Added: trunk/LayoutTests/fast/shadow-dom/Node-prototype-cloneNode.html (0 => 196998)


--- trunk/LayoutTests/fast/shadow-dom/Node-prototype-cloneNode.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/Node-prototype-cloneNode.html	2016-02-23 22:35:44 UTC (rev 196998)
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Shadow DOM: Extensions to Node interface</title>
+<meta name="author" title="Ryosuke Niwa" href=""
+<meta name="assert" content="Invoking the cloneNode() method on a ShadowRoot instance must always throw a NotSupportedError.">
+<link rel="help" href=""
+<script src=""
+<script src=""
+<link rel='stylesheet' href=''>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+function testCloneNode(mode) {
+    test(function () {
+        assert_throws({'name': 'NotSupportedError'}, function () {
+            var element = document.createElement('div');
+            var shadowRoot = element.attachShadow({mode: mode});
+            shadowRoot.cloneNode(false);
+        }, 'cloneNode(false) on a shadow root in ' + mode + ' mode must throw a NotSupportedError');
+
+        assert_throws({'name': 'NotSupportedError'}, function () {
+            var element = document.createElement('div');
+            var shadowRoot = element.attachShadow({mode: mode});
+            shadowRoot.cloneNode(false);
+        }, 'cloneNode(true) on a closed shadow root must throw a NotSupportedError');
+
+    }, 'cloneNode on a shadow root in ' + mode + ' mode must throw a NotSupportedError');
+}
+
+testCloneNode('open');
+testCloneNode('closed');
+
+test(function () {
+    var element = document.createElement('div');
+    var shadowRoot = element.attachShadow({mode: 'open'});
+
+    assert_equals(element.cloneNode(false).shadowRoot, null, 'cloneNode(false) on an open shadow host mode must clone its shadow root');
+    assert_equals(element.cloneNode(true).shadowRoot, null, 'cloneNode(true) on an open shadow host mode must clone its shadow root');
+}, 'cloneNode on an open shadow root must throw a NotSupportedError');
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (196997 => 196998)


--- trunk/Source/WebCore/ChangeLog	2016-02-23 22:29:01 UTC (rev 196997)
+++ trunk/Source/WebCore/ChangeLog	2016-02-23 22:35:44 UTC (rev 196998)
@@ -1,3 +1,34 @@
+2016-02-22  Ryosuke Niwa  <[email protected]>
+
+        Calling importNode on shadow root causes a crash
+        https://bugs.webkit.org/show_bug.cgi?id=154570
+
+        Reviewed by Anders Carlsson.
+
+        The bug was caused by a missing check in cloneNode. Added cloneNodeForBindings to explicitly throw
+        an NotSupportedError when it's called on a shadow root. We don't clone shadow root when deep-cloning
+        the tree so we don't have to check that condition.
+
+        The behavior of cloneNode is specified at:
+        http://w3c.github.io/webcomponents/spec/shadow/#the-shadowroot-interface
+        (it current says we should throw DATA_CLONE_ERR but I have an spec bug filed at
+        https://github.com/w3c/webcomponents/issues/393)
+
+        The behavior of importNode and adoptNode are specified in DOM4 specification:
+        https://dom.spec.whatwg.org/#dom-document-importnode
+        https://dom.spec.whatwg.org/#dom-document-adoptnode
+
+        Tests: fast/shadow-dom/Document-prototype-adoptNode.html
+               fast/shadow-dom/Document-prototype-importNode.html
+               fast/shadow-dom/Node-prototype-cloneNode.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::importNode): Throw NotSupportedError when importing a shadow root.
+        * dom/Node.cpp:
+        (WebCore::Node::cloneNodeForBindings): Added.
+        * dom/Node.h:
+        * dom/Node.idl: Use cloneNodeForBindings here.
+
 2016-02-23  Daniel Bates  <[email protected]>
 
         REGRESSION (r196892): No longer emit error message when CSP form-action directive is used as a source _expression_

Modified: trunk/Source/WebCore/dom/Document.cpp (196997 => 196998)


--- trunk/Source/WebCore/dom/Document.cpp	2016-02-23 22:29:01 UTC (rev 196997)
+++ trunk/Source/WebCore/dom/Document.cpp	2016-02-23 22:35:44 UTC (rev 196998)
@@ -985,12 +985,15 @@
     }
 
     switch (importedNode->nodeType()) {
+    case DOCUMENT_FRAGMENT_NODE:
+        if (importedNode->isShadowRoot())
+            break;
+        FALLTHROUGH;
     case ELEMENT_NODE:
     case TEXT_NODE:
     case CDATA_SECTION_NODE:
     case PROCESSING_INSTRUCTION_NODE:
     case COMMENT_NODE:
-    case DOCUMENT_FRAGMENT_NODE:
         return importedNode->cloneNodeInternal(document(), deep ? CloningOperation::Everything : CloningOperation::OnlySelf);
 
     case ATTRIBUTE_NODE:

Modified: trunk/Source/WebCore/dom/Node.cpp (196997 => 196998)


--- trunk/Source/WebCore/dom/Node.cpp	2016-02-23 22:29:01 UTC (rev 196997)
+++ trunk/Source/WebCore/dom/Node.cpp	2016-02-23 22:35:44 UTC (rev 196998)
@@ -602,6 +602,15 @@
     }
 }
 
+RefPtr<Node> Node::cloneNodeForBindings(bool deep, ExceptionCode& ec)
+{
+    if (UNLIKELY(isShadowRoot())) {
+        ec = NOT_SUPPORTED_ERR;
+        return nullptr;
+    }
+    return cloneNode(deep);
+}
+
 const AtomicString& Node::prefix() const
 {
     // For nodes other than elements and attributes, the prefix is always null

Modified: trunk/Source/WebCore/dom/Node.h (196997 => 196998)


--- trunk/Source/WebCore/dom/Node.h	2016-02-23 22:29:01 UTC (rev 196997)
+++ trunk/Source/WebCore/dom/Node.h	2016-02-23 22:35:44 UTC (rev 196998)
@@ -181,6 +181,7 @@
     };
     virtual Ref<Node> cloneNodeInternal(Document&, CloningOperation) = 0;
     Ref<Node> cloneNode(bool deep) { return cloneNodeInternal(document(), deep ? CloningOperation::Everything : CloningOperation::OnlySelf); }
+    RefPtr<Node> cloneNodeForBindings(bool deep, ExceptionCode&);
 
     virtual const AtomicString& localName() const;
     virtual const AtomicString& namespaceURI() const;

Modified: trunk/Source/WebCore/dom/Node.idl (196997 => 196998)


--- trunk/Source/WebCore/dom/Node.idl	2016-02-23 22:29:01 UTC (rev 196997)
+++ trunk/Source/WebCore/dom/Node.idl	2016-02-23 22:35:44 UTC (rev 196998)
@@ -70,7 +70,7 @@
     [Custom, RaisesException] Node appendChild([CustomReturn] Node newChild);
 
     boolean            hasChildNodes();
-    [NewObject] Node cloneNode([Default=Undefined] optional boolean deep);
+    [NewObject, RaisesException, ImplementedAs=cloneNodeForBindings] Node cloneNode([Default=Undefined] optional boolean deep);
     void               normalize();
 
     // Introduced in DOM Level 2:
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to