Implement Document.cloneNode()
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Dec 2013 22:06:45 +0000 (22:06 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Dec 2013 22:06:45 +0000 (22:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=11646

Reviewed by Darin Adler.

Source/WebCore:

Merge https://chromium.googlesource.com/chromium/blink/+/dc7879025e01d63be9fcf6a84ca6c9b8b5768a80

Implement the behavior specified in the current DOM4 working draft:
http://www.w3.org/TR/2013/WD-dom-20131107/#dom-node-clonenode

Tests: fast/dom/Document/clone-node.html
       fast/dom/HTMLDocument/clone-node-quirks-mode.html
       svg/custom/clone-node.html

* dom/Document.cpp:
(WebCore::Document::cloneNode):
(WebCore::Document::cloneDocumentWithoutChildren):
(WebCore::Document::cloneDataFromDocument):
* dom/Document.h:
* html/HTMLDocument.cpp:
(WebCore::HTMLDocument::cloneDocumentWithoutChildren):
* html/HTMLDocument.h:
* svg/SVGDocument.cpp:
(WebCore::SVGDocument::cloneDocumentWithoutChildren):
* svg/SVGDocument.h:

LayoutTests:

* dom/xhtml/level3/core/documentgetinputencoding04-expected.txt:
* dom/xhtml/level3/core/documentgetxmlencoding05-expected.txt:
* dom/xhtml/level3/core/nodeisequalnode01-expected.txt:
* dom/xhtml/level3/core/nodeisequalnode21-expected.txt:
* dom/xhtml/level3/core/nodeisequalnode25-expected.txt:
* dom/xhtml/level3/core/nodeisequalnode26-expected.txt:
* fast/dom/Document/clone-node-expected.txt: Added.
* fast/dom/Document/clone-node.html: Added.
* fast/dom/HTMLDocument/clone-node-quirks-mode-expected.txt: Added.
* fast/dom/HTMLDocument/clone-node-quirks-mode.html: Added.
* svg/custom/clone-node-expected.txt: Added.
* svg/custom/clone-node.html: Added.

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

20 files changed:
LayoutTests/ChangeLog
LayoutTests/dom/xhtml/level3/core/documentgetinputencoding04-expected.txt
LayoutTests/dom/xhtml/level3/core/documentgetxmlencoding05-expected.txt
LayoutTests/dom/xhtml/level3/core/nodeisequalnode01-expected.txt
LayoutTests/dom/xhtml/level3/core/nodeisequalnode21-expected.txt
LayoutTests/dom/xhtml/level3/core/nodeisequalnode25-expected.txt
LayoutTests/dom/xhtml/level3/core/nodeisequalnode26-expected.txt
LayoutTests/fast/dom/Document/clone-node-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/Document/clone-node.html [new file with mode: 0644]
LayoutTests/fast/dom/HTMLDocument/clone-node-quirks-mode-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/HTMLDocument/clone-node-quirks-mode.html [new file with mode: 0644]
LayoutTests/svg/custom/clone-node-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/clone-node.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLDocument.cpp
Source/WebCore/html/HTMLDocument.h
Source/WebCore/svg/SVGDocument.cpp
Source/WebCore/svg/SVGDocument.h

index 66d029b..694b516 100644 (file)
@@ -1,3 +1,23 @@
+2013-12-09  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Implement Document.cloneNode()
+        https://bugs.webkit.org/show_bug.cgi?id=11646
+
+        Reviewed by Darin Adler.
+
+        * dom/xhtml/level3/core/documentgetinputencoding04-expected.txt:
+        * dom/xhtml/level3/core/documentgetxmlencoding05-expected.txt:
+        * dom/xhtml/level3/core/nodeisequalnode01-expected.txt:
+        * dom/xhtml/level3/core/nodeisequalnode21-expected.txt:
+        * dom/xhtml/level3/core/nodeisequalnode25-expected.txt:
+        * dom/xhtml/level3/core/nodeisequalnode26-expected.txt:
+        * fast/dom/Document/clone-node-expected.txt: Added.
+        * fast/dom/Document/clone-node.html: Added.
+        * fast/dom/HTMLDocument/clone-node-quirks-mode-expected.txt: Added.
+        * fast/dom/HTMLDocument/clone-node-quirks-mode.html: Added.
+        * svg/custom/clone-node-expected.txt: Added.
+        * svg/custom/clone-node.html: Added.
+
 2013-12-09  Mario Sanchez Prada  <mario.prada@samsung.com>
 
         [ATK] Translate ATK_ROLE_SECTION into "AXSection" in DRT/WKTR
index 03f629d..3b5b860 100644 (file)
@@ -1,3 +1,2 @@
 Test   http://www.w3.org/2001/DOM-Test-Suite/level3/core/documentgetinputencoding04
-Status error
-Message        Line 98: TypeError
+Status Success
index 42210aa..6a77fc6 100644 (file)
@@ -1,3 +1,2 @@
 Test   http://www.w3.org/2001/DOM-Test-Suite/level3/core/documentgetxmlencoding05
-Status error
-Message        Line 98: TypeError
+Status Success
index 79f24f7..5db67b7 100644 (file)
@@ -1,3 +1,2 @@
 Test   http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodeisequalnode01
-Status failure
-Message        nodeisequalnode01: assertTrue failed
+Status Success
index 1fbcf95..1a22dec 100644 (file)
@@ -1,3 +1,2 @@
 Test   http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodeisequalnode21
-Status failure
-Message        nodeisequalnode21: assertTrue failed
+Status Success
index 025d811..5c9b483 100644 (file)
@@ -1,3 +1,3 @@
 Test   http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodeisequalnode25
 Status error
-Message        Line 123: TypeError
+Message        Line 125: TypeError
index 7e11299..60781a7 100644 (file)
@@ -1,3 +1,3 @@
 Test   http://www.w3.org/2001/DOM-Test-Suite/level3/core/nodeisequalnode26
 Status error
-Message        Line 123: TypeError
+Message        Line 125: TypeError
diff --git a/LayoutTests/fast/dom/Document/clone-node-expected.txt b/LayoutTests/fast/dom/Document/clone-node-expected.txt
new file mode 100644 (file)
index 0000000..70418d2
--- /dev/null
@@ -0,0 +1,16 @@
+Tests cloneNode for Document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS doc.cloneNode(false).__proto__ is Document.prototype
+PASS className(doc.cloneNode(false)) is "Document"
+PASS doc.cloneNode(true).documentElement.localName is "root"
+PASS document.cloneNode(true).compatMode is "CSS1Compat"
+PASS document.cloneNode(false).URL is document.URL
+PASS document.cloneNode(false).baseURI is document.baseURI
+PASS document.cloneNode(false).characterSet is document.characterSet
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/Document/clone-node.html b/LayoutTests/fast/dom/Document/clone-node.html
new file mode 100644 (file)
index 0000000..13a098a
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../../resources/js-test-pre.js"></script>
+<script>
+description('Tests cloneNode for Document.');
+
+function className(object) {
+    return Object.prototype.toString.call(object).slice(8, -1);
+}
+
+var doc = document.implementation.createDocument('', 'root', null);
+
+shouldBe('doc.cloneNode(false).__proto__', 'Document.prototype');
+shouldBeEqualToString('className(doc.cloneNode(false))', 'Document');
+shouldBeEqualToString('doc.cloneNode(true).documentElement.localName', 'root');
+shouldBeEqualToString('document.cloneNode(true).compatMode', 'CSS1Compat');
+shouldBe('document.cloneNode(false).URL', 'document.URL');
+shouldBe('document.cloneNode(false).baseURI', 'document.baseURI');
+shouldBe('document.cloneNode(false).characterSet', 'document.characterSet');
+
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/HTMLDocument/clone-node-quirks-mode-expected.txt b/LayoutTests/fast/dom/HTMLDocument/clone-node-quirks-mode-expected.txt
new file mode 100644 (file)
index 0000000..588745e
--- /dev/null
@@ -0,0 +1,17 @@
+Tests cloneNode for HTMLDocument.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.cloneNode(false).__proto__ is HTMLDocument.prototype
+PASS className(document.cloneNode(false)) is "HTMLDocument"
+PASS document.cloneNode(true).title is document.title
+PASS document.cloneNode(true).compatMode is "BackCompat"
+PASS doc.cloneNode(false).__proto__ is HTMLDocument.prototype
+PASS className(doc.cloneNode(false)) is "HTMLDocument"
+PASS doc.cloneNode(true).title is doc.title
+PASS doc.cloneNode(true).compatMode is "CSS1Compat"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/HTMLDocument/clone-node-quirks-mode.html b/LayoutTests/fast/dom/HTMLDocument/clone-node-quirks-mode.html
new file mode 100644 (file)
index 0000000..91a31d2
--- /dev/null
@@ -0,0 +1,22 @@
+<title>Tests HTMLDocument cloneNode</title>
+<script src="../../../resources/js-test-pre.js"></script>
+<script>
+description('Tests cloneNode for HTMLDocument.');
+
+function className(object) {
+    return Object.prototype.toString.call(object).slice(8, -1);
+}
+
+shouldBe('document.cloneNode(false).__proto__', 'HTMLDocument.prototype');
+shouldBeEqualToString('className(document.cloneNode(false))', 'HTMLDocument');
+shouldBe('document.cloneNode(true).title', 'document.title');
+shouldBeEqualToString('document.cloneNode(true).compatMode', 'BackCompat');
+
+var doc = document.implementation.createHTMLDocument('title');
+shouldBe('doc.cloneNode(false).__proto__', 'HTMLDocument.prototype');
+shouldBeEqualToString('className(doc.cloneNode(false))', 'HTMLDocument');
+shouldBe('doc.cloneNode(true).title', 'doc.title');
+shouldBeEqualToString('doc.cloneNode(true).compatMode', 'CSS1Compat');
+
+</script>
+<script src="../../../resources/js-test-post.js"></script>
diff --git a/LayoutTests/svg/custom/clone-node-expected.txt b/LayoutTests/svg/custom/clone-node-expected.txt
new file mode 100644 (file)
index 0000000..1e64af5
--- /dev/null
@@ -0,0 +1,12 @@
+Tests cloneNode for SVGDocument.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS svgDoc.cloneNode(false).__proto__ is SVGDocument.prototype
+PASS className(svgDoc.cloneNode(false)) is "SVGDocument"
+PASS svgDoc.cloneNode(true).compatMode is "CSS1Compat"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/custom/clone-node.html b/LayoutTests/svg/custom/clone-node.html
new file mode 100644 (file)
index 0000000..d100cbe
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="../../resources/js-test-pre.js"></script>
+<script>
+
+description('Tests cloneNode for SVGDocument.');
+
+function className(object) {
+    return Object.prototype.toString.call(object).slice(8, -1);
+}
+
+var svgDoc = document.implementation.createDocument('http://www.w3.org/2000/svg', 'svg', null);
+
+shouldBe('svgDoc.cloneNode(false).__proto__', 'SVGDocument.prototype');
+shouldBeEqualToString('className(svgDoc.cloneNode(false))', 'SVGDocument');
+shouldBeEqualToString('svgDoc.cloneNode(true).compatMode', 'CSS1Compat');
+
+</script>
+<script src="../../resources/js-test-post.js"></script>
index 2023950..2c8825e 100644 (file)
@@ -1,3 +1,31 @@
+2013-12-09  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Implement Document.cloneNode()
+        https://bugs.webkit.org/show_bug.cgi?id=11646
+
+        Reviewed by Darin Adler.
+
+        Merge https://chromium.googlesource.com/chromium/blink/+/dc7879025e01d63be9fcf6a84ca6c9b8b5768a80
+
+        Implement the behavior specified in the current DOM4 working draft:
+        http://www.w3.org/TR/2013/WD-dom-20131107/#dom-node-clonenode
+
+        Tests: fast/dom/Document/clone-node.html
+               fast/dom/HTMLDocument/clone-node-quirks-mode.html
+               svg/custom/clone-node.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::cloneNode):
+        (WebCore::Document::cloneDocumentWithoutChildren):
+        (WebCore::Document::cloneDataFromDocument):
+        * dom/Document.h:
+        * html/HTMLDocument.cpp:
+        (WebCore::HTMLDocument::cloneDocumentWithoutChildren):
+        * html/HTMLDocument.h:
+        * svg/SVGDocument.cpp:
+        (WebCore::SVGDocument::cloneDocumentWithoutChildren):
+        * svg/SVGDocument.h:
+
 2013-12-09  Andreas Kling  <akling@apple.com>
 
         REGRESSION(r160260): Memory pressure signal causes web process to hang.
index 0578555..e94f273 100644 (file)
@@ -3025,10 +3025,30 @@ bool Document::canReplaceChild(Node* newChild, Node* oldChild)
     return true;
 }
 
-PassRefPtr<Node> Document::cloneNode(bool /*deep*/)
+PassRefPtr<Node> Document::cloneNode(bool deep)
 {
-    // Spec says cloning Document nodes is "implementation dependent" and we do not support it.
-    return nullptr;
+    RefPtr<Document> clone = cloneDocumentWithoutChildren();
+    clone->cloneDataFromDocument(*this);
+    if (deep)
+        cloneChildNodes(clone.get());
+    return clone.release();
+}
+
+PassRefPtr<Document> Document::cloneDocumentWithoutChildren() const
+{
+    return isXHTMLDocument() ? createXHTML(nullptr, url()) : create(nullptr, url());
+}
+
+void Document::cloneDataFromDocument(const Document& other)
+{
+    ASSERT(m_url == other.url());
+    m_baseURL = other.baseURL();
+    m_baseURLOverride = other.baseURLOverride();
+    m_documentURI = other.documentURI();
+
+    setCompatibilityMode(other.compatibilityMode());
+    setSecurityOrigin(other.securityOrigin());
+    setDecoder(other.decoder());
 }
 
 StyleSheetList* Document::styleSheets()
index 719146f..6d80bc7 100644 (file)
@@ -1188,6 +1188,8 @@ protected:
 
     void clearXMLVersion() { m_xmlVersion = String(); }
 
+    virtual PassRefPtr<Document> cloneDocumentWithoutChildren() const;
+
 private:
     friend class Node;
     friend class IgnoreDestructiveWriteCountIncrementer;
@@ -1214,6 +1216,7 @@ private:
     virtual NodeType nodeType() const OVERRIDE;
     virtual bool childTypeAllowed(NodeType) const OVERRIDE;
     virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE;
+    void cloneDataFromDocument(const Document&);
 
     virtual void refScriptExecutionContext() OVERRIDE { ref(); }
     virtual void derefScriptExecutionContext() OVERRIDE { deref(); }
index 1e0764b..17e206e 100644 (file)
@@ -365,4 +365,9 @@ bool HTMLDocument::isFrameSet() const
     return bodyElement && isHTMLFrameSetElement(bodyElement);
 }
 
+PassRefPtr<Document> HTMLDocument::cloneDocumentWithoutChildren() const
+{
+    return create(nullptr, url());
+}
+
 }
index 29752f3..15340de 100644 (file)
@@ -88,6 +88,8 @@ private:
     virtual bool isFrameSet() const;
     virtual PassRefPtr<DocumentParser> createParser();
 
+    virtual PassRefPtr<Document> cloneDocumentWithoutChildren() const OVERRIDE FINAL;
+
     DocumentOrderedMap m_documentNamedItem;
     DocumentOrderedMap m_windowNamedItem;
 };
index cbaa2e7..d735da4 100644 (file)
@@ -100,6 +100,11 @@ bool SVGDocument::childShouldCreateRenderer(const Node& child) const
     return true;
 }
 
+PassRefPtr<Document> SVGDocument::cloneDocumentWithoutChildren() const
+{
+    return create(nullptr, url());
+}
+
 }
 
 // vim:ts=4:noet
index 04b228c..6222ef2 100644 (file)
@@ -53,6 +53,8 @@ private:
 
     virtual bool childShouldCreateRenderer(const Node&) const OVERRIDE;
 
+    virtual PassRefPtr<Document> cloneDocumentWithoutChildren() const OVERRIDE;
+
     FloatPoint m_translate;
 };