Title: [138730] trunk
Revision
138730
Author
[email protected]
Date
2013-01-03 13:16:59 -0800 (Thu, 03 Jan 2013)

Log Message

[HTMLTemplateElement] Disallow cycles within template content
https://bugs.webkit.org/show_bug.cgi?id=105066

Reviewed by Ojan Vafai.

Source/WebCore:

Cycles in <template> content aren't quite as bad as cycles in normal
DOM trees, but they can easily cause crashes, e.g. in cloneNode and
innerHTML.

Shadow DOM has an analagous issue, and this patch tackles that problem
at the same time by creating a new method, Node::containsIncludingHostElements.

In order to disallow cycles, the HTMLTemplateElement.content
DocumentFragment needs a pointer to its host. The approach here
creates a new subclass with a host pointer and a new virtual method
to DocumentFragment to identify the subclass.

To avoid unnecessary virtual function calls, also changed how
Document::templateContentsOwnerDocument works to allow fast inlined
access and avoid lazy creation when not needed.

Tests: fast/dom/HTMLTemplateElement/cycles-in-shadow.html
       fast/dom/HTMLTemplateElement/cycles.html
       fast/dom/shadow/shadow-hierarchy-exception.html

* GNUmakefile.list.am:
* Target.pri:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/ContainerNode.cpp:
(WebCore::isInTemplateContent):
(WebCore::containsConsideringHostElements):
(WebCore::checkAcceptChild):
* dom/Document.cpp:
(WebCore::Document::ensureTemplateContentsOwnerDocument): Renamed to make clear that it lazily creates the Document. Updated all existing callers to call this method.
* dom/Document.h:
(Document):
(WebCore::Document::templateContentsOwnerDocument): Fast, inlined accessor for use in checkAcceptChild().
* dom/DocumentFragment.h:
(WebCore::DocumentFragment::isTemplateContent):
* dom/Node.cpp:
(WebCore::Node::containsIncludingShadowDOM): made const, simplified
(WebCore::Node::containsIncludingHostElements): Specialized version of Node::contains that knows how to jump over template content boundaries.
* dom/Node.h:
(Node):
* dom/TemplateContentDocumentFragment.h: Added.
(TemplateContentDocumentFragment): Subclass of DocumentFragment which stores its host template element.
(WebCore::TemplateContentDocumentFragment::create):
(WebCore::TemplateContentDocumentFragment::host):
(WebCore::TemplateContentDocumentFragment::TemplateContentDocumentFragment):
* editing/markup.cpp:
(WebCore::createFragmentForInnerOuterHTML):
* html/HTMLTemplateElement.cpp:
(WebCore::HTMLTemplateElement::content): Construct the new subclass.

LayoutTests:

* fast/dom/HTMLTemplateElement/cycles-expected.txt: Added.
* fast/dom/HTMLTemplateElement/cycles-in-shadow-expected.txt: Added.
* fast/dom/HTMLTemplateElement/cycles-in-shadow.html: Added.
* fast/dom/HTMLTemplateElement/cycles.html: Added.
* fast/dom/shadow/shadow-hierarchy-exception-expected.txt: Added.
* fast/dom/shadow/shadow-hierarchy-exception.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (138729 => 138730)


--- trunk/LayoutTests/ChangeLog	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/LayoutTests/ChangeLog	2013-01-03 21:16:59 UTC (rev 138730)
@@ -1,3 +1,17 @@
+2013-01-03  Adam Klein  <[email protected]>
+
+        [HTMLTemplateElement] Disallow cycles within template content
+        https://bugs.webkit.org/show_bug.cgi?id=105066
+
+        Reviewed by Ojan Vafai.
+
+        * fast/dom/HTMLTemplateElement/cycles-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/cycles-in-shadow-expected.txt: Added.
+        * fast/dom/HTMLTemplateElement/cycles-in-shadow.html: Added.
+        * fast/dom/HTMLTemplateElement/cycles.html: Added.
+        * fast/dom/shadow/shadow-hierarchy-exception-expected.txt: Added.
+        * fast/dom/shadow/shadow-hierarchy-exception.html: Added.
+
 2013-01-03  Alexis Menard  <[email protected]>
 
         Querying transition-timing-function value on the computed style does not return keywords when it should.

Added: trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-expected.txt (0 => 138730)


--- trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-expected.txt	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,14 @@
+Test that cycles are not allowed in template content
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS template.content.appendChild(template) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS template.content.appendChild(outerDiv) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS innerDiv.appendChild(template) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS innerDiv.appendChild(outerDiv) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS innerTemplate.appendChild(outerDiv) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-in-shadow-expected.txt (0 => 138730)


--- trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-in-shadow-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-in-shadow-expected.txt	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,10 @@
+Test that cycle detection traverses over both templates and shadow roots
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS shadowDiv.appendChild(outerDiv) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-in-shadow.html (0 => 138730)


--- trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-in-shadow.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles-in-shadow.html	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+<div id=container>
+  <template><div></div></template>
+</div>
+<script>
+description('Test that cycle detection traverses over both templates and shadow roots');
+var outerDiv = document.getElementById('container');
+var template = document.querySelector('template');
+var div = template.content.firstChild;
+var shadowRoot = div.webkitCreateShadowRoot();
+var shadowDiv = shadowRoot.appendChild(document.createElement('div'));
+shouldThrow('shadowDiv.appendChild(outerDiv)');
+</script>
+<script src=""
+</body>

Added: trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles.html (0 => 138730)


--- trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLTemplateElement/cycles.html	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+description('Test that cycles are not allowed in template content');
+var template = document.createElement('template');
+shouldThrow('template.content.appendChild(template)');
+var outerDiv = document.createElement('div');
+outerDiv.appendChild(template);
+shouldThrow('template.content.appendChild(outerDiv)');
+var innerDiv = template.content.appendChild(document.createElement('div'));
+shouldThrow('innerDiv.appendChild(template)');
+shouldThrow('innerDiv.appendChild(outerDiv)');
+var innerTemplate = innerDiv.appendChild(document.createElement('template'));
+shouldThrow('innerTemplate.appendChild(outerDiv)');
+</script>
+<script src=""

Added: trunk/LayoutTests/fast/dom/shadow/shadow-hierarchy-exception-expected.txt (0 => 138730)


--- trunk/LayoutTests/fast/dom/shadow/shadow-hierarchy-exception-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-hierarchy-exception-expected.txt	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,10 @@
+Appending an ancestor to a shadow tree should throw an exception
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS shadowDiv.appendChild(container) threw exception Error: HierarchyRequestError: DOM Exception 3.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/shadow/shadow-hierarchy-exception.html (0 => 138730)


--- trunk/LayoutTests/fast/dom/shadow/shadow-hierarchy-exception.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-hierarchy-exception.html	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src=""
+<div id=container>
+  <div>
+      <span></span>
+  </div>
+</div>
+<script>
+description('Appending an ancestor to a shadow tree should throw an exception');
+var container = document.getElementById('container');
+var span = container.querySelector('span');
+var shadow = span.webkitCreateShadowRoot();
+var shadowDiv = shadow.appendChild(document.createElement('div'));
+shouldThrow('shadowDiv.appendChild(container)');
+</script>
+<script src=""

Modified: trunk/Source/WebCore/ChangeLog (138729 => 138730)


--- trunk/Source/WebCore/ChangeLog	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/ChangeLog	2013-01-03 21:16:59 UTC (rev 138730)
@@ -1,3 +1,60 @@
+2013-01-03  Adam Klein  <[email protected]>
+
+        [HTMLTemplateElement] Disallow cycles within template content
+        https://bugs.webkit.org/show_bug.cgi?id=105066
+
+        Reviewed by Ojan Vafai.
+
+        Cycles in <template> content aren't quite as bad as cycles in normal
+        DOM trees, but they can easily cause crashes, e.g. in cloneNode and
+        innerHTML.
+
+        Shadow DOM has an analagous issue, and this patch tackles that problem
+        at the same time by creating a new method, Node::containsIncludingHostElements.
+
+        In order to disallow cycles, the HTMLTemplateElement.content
+        DocumentFragment needs a pointer to its host. The approach here
+        creates a new subclass with a host pointer and a new virtual method
+        to DocumentFragment to identify the subclass.
+
+        To avoid unnecessary virtual function calls, also changed how
+        Document::templateContentsOwnerDocument works to allow fast inlined
+        access and avoid lazy creation when not needed.
+
+        Tests: fast/dom/HTMLTemplateElement/cycles-in-shadow.html
+               fast/dom/HTMLTemplateElement/cycles.html
+               fast/dom/shadow/shadow-hierarchy-exception.html
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/ContainerNode.cpp:
+        (WebCore::isInTemplateContent):
+        (WebCore::containsConsideringHostElements):
+        (WebCore::checkAcceptChild):
+        * dom/Document.cpp:
+        (WebCore::Document::ensureTemplateContentsOwnerDocument): Renamed to make clear that it lazily creates the Document. Updated all existing callers to call this method.
+        * dom/Document.h:
+        (Document):
+        (WebCore::Document::templateContentsOwnerDocument): Fast, inlined accessor for use in checkAcceptChild().
+        * dom/DocumentFragment.h:
+        (WebCore::DocumentFragment::isTemplateContent):
+        * dom/Node.cpp:
+        (WebCore::Node::containsIncludingShadowDOM): made const, simplified
+        (WebCore::Node::containsIncludingHostElements): Specialized version of Node::contains that knows how to jump over template content boundaries.
+        * dom/Node.h:
+        (Node):
+        * dom/TemplateContentDocumentFragment.h: Added.
+        (TemplateContentDocumentFragment): Subclass of DocumentFragment which stores its host template element.
+        (WebCore::TemplateContentDocumentFragment::create):
+        (WebCore::TemplateContentDocumentFragment::host):
+        (WebCore::TemplateContentDocumentFragment::TemplateContentDocumentFragment):
+        * editing/markup.cpp:
+        (WebCore::createFragmentForInnerOuterHTML):
+        * html/HTMLTemplateElement.cpp:
+        (WebCore::HTMLTemplateElement::content): Construct the new subclass.
+
 2013-01-02  Jon Lee  <[email protected]>
 
         Revert auto-start plugins to snapshotted plugins after a period of inactivity

Modified: trunk/Source/WebCore/GNUmakefile.list.am (138729 => 138730)


--- trunk/Source/WebCore/GNUmakefile.list.am	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2013-01-03 21:16:59 UTC (rev 138730)
@@ -2961,6 +2961,7 @@
 	Source/WebCore/dom/StyleElement.h \
 	Source/WebCore/dom/TagNodeList.cpp \
 	Source/WebCore/dom/TagNodeList.h \
+	Source/WebCore/dom/TemplateContentDocumentFragment.h \
 	Source/WebCore/dom/Text.cpp \
 	Source/WebCore/dom/TextEvent.cpp \
 	Source/WebCore/dom/TextEvent.h \

Modified: trunk/Source/WebCore/Target.pri (138729 => 138730)


--- trunk/Source/WebCore/Target.pri	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/Target.pri	2013-01-03 21:16:59 UTC (rev 138730)
@@ -1645,6 +1645,7 @@
     dom/StyledElement.h \
     dom/StyleElement.h \
     dom/TagNodeList.h \
+    dom/TemplateContentDocumentFragment.h \
     dom/TextEvent.h \
     dom/TextEventInputType.h \
     dom/Text.h \

Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (138729 => 138730)


--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2013-01-03 21:16:59 UTC (rev 138730)
@@ -54990,6 +54990,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\dom\TemplateContentDocumentFragment.h"
+				>
+			</File>
+			<File
 				RelativePath="..\dom\Text.cpp"
 				>
 				<FileConfiguration

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (138729 => 138730)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2013-01-03 21:16:59 UTC (rev 138730)
@@ -5905,6 +5905,7 @@
 		C5D4AA7A116BAFB60069CA93 /* GlyphMetricsMap.h in Headers */ = {isa = PBXBuildFile; fileRef = C5D4AA78116BAFB60069CA93 /* GlyphMetricsMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		C5E9B67710697E1300C7BB1A /* StorageEventDispatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5E9B67610697E1300C7BB1A /* StorageEventDispatcher.cpp */; };
 		C5EBDD84105EDDEC0056816F /* StorageEventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = C5EBDD81105EDDEC0056816F /* StorageEventDispatcher.h */; };
+		C65046A9167BFB5500CC2A4D /* TemplateContentDocumentFragment.h in Headers */ = {isa = PBXBuildFile; fileRef = C65046A8167BFB5500CC2A4D /* TemplateContentDocumentFragment.h */; };
 		C6A703325C9D0B6CDCBC4D77 /* JSEventTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6A703325C9D0B6CDCBC4D78 /* JSEventTarget.cpp */; };
 		C6B31B2E14F841FB0089F23F /* ScrollbarThemeClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C691614714F6EBA70046375C /* ScrollbarThemeClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		C6D74AD509AA282E000B0A52 /* ModifySelectionListLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D74AD309AA282E000B0A52 /* ModifySelectionListLevel.h */; };
@@ -13365,6 +13366,7 @@
 		C5EBDD81105EDDEC0056816F /* StorageEventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageEventDispatcher.h; sourceTree = "<group>"; };
 		C5F765B414E1D414006C899B /* PasteboardStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardStrategy.h; sourceTree = "<group>"; };
 		C5F765BA14E1ECF4006C899B /* PlatformPasteboardMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformPasteboardMac.mm; sourceTree = "<group>"; };
+		C65046A8167BFB5500CC2A4D /* TemplateContentDocumentFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateContentDocumentFragment.h; sourceTree = "<group>"; };
 		C691614714F6EBA70046375C /* ScrollbarThemeClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollbarThemeClient.h; sourceTree = "<group>"; };
 		C6A703325C9D0B6CDCBC4D78 /* JSEventTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventTarget.cpp; sourceTree = "<group>"; };
 		C6D74AD309AA282E000B0A52 /* ModifySelectionListLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModifySelectionListLevel.h; sourceTree = "<group>"; };
@@ -22278,6 +22280,7 @@
 				AA4C3A750B2B1679002334A2 /* StyleElement.h */,
 				BCE3BEC00D222B1D007E06E4 /* TagNodeList.cpp */,
 				BCE3BEC10D222B1D007E06E4 /* TagNodeList.h */,
+				C65046A8167BFB5500CC2A4D /* TemplateContentDocumentFragment.h */,
 				6550B69B099DF0270090D781 /* Text.cpp */,
 				6550B69C099DF0270090D781 /* Text.h */,
 				93EEC1F609C2877700C515D1 /* Text.idl */,
@@ -25704,6 +25707,7 @@
 				A8CFF0510A154F09000A4234 /* TableLayout.h in Headers */,
 				BCE3BEC30D222B1D007E06E4 /* TagNodeList.h in Headers */,
 				F55B3DD61251F12D003EF269 /* TelephoneInputType.h in Headers */,
+				C65046A9167BFB5500CC2A4D /* TemplateContentDocumentFragment.h in Headers */,
 				6550B6A6099DF0270090D781 /* Text.h in Headers */,
 				93309E17099E64920056E581 /* TextAffinity.h in Headers */,
 				CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */,

Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (138729 => 138730)


--- trunk/Source/WebCore/dom/ContainerNode.cpp	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp	2013-01-03 21:16:59 UTC (rev 138730)
@@ -47,6 +47,7 @@
 #include "RenderTheme.h"
 #include "RenderWidget.h"
 #include "RootInlineBox.h"
+#include "TemplateContentDocumentFragment.h"
 #include <wtf/CurrentTime.h>
 #include <wtf/Vector.h>
 
@@ -137,6 +138,24 @@
     return true;
 }
 
+static inline bool isInTemplateContent(const Node* node)
+{
+#if ENABLE(TEMPLATE_ELEMENT)
+    Document* document = node->document();
+    return document && document == document->templateContentsOwnerDocument();
+#else
+    UNUSED(node);
+    return false;
+#endif
+}
+
+static inline bool containsConsideringHostElements(const Node* newChild, const Node* newParent)
+{
+    return (newParent->isInShadowTree() || isInTemplateContent(newParent))
+        ? newChild->containsIncludingHostElements(newParent)
+        : newChild->contains(newParent);
+}
+
 static inline ExceptionCode checkAcceptChild(ContainerNode* newParent, Node* newChild, Node* oldChild)
 {
     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
@@ -148,7 +167,7 @@
         ASSERT(!newParent->isReadOnlyNode());
         ASSERT(!newParent->isDocumentTypeNode());
         ASSERT(isChildTypeAllowed(newParent, newChild));
-        if (newChild->contains(newParent))
+        if (containsConsideringHostElements(newChild, newParent))
             return HIERARCHY_REQUEST_ERR;
         return 0;
     }
@@ -162,7 +181,7 @@
         return NO_MODIFICATION_ALLOWED_ERR;
     if (newChild->inDocument() && newChild->isDocumentTypeNode())
         return HIERARCHY_REQUEST_ERR;
-    if (newChild->contains(newParent))
+    if (containsConsideringHostElements(newChild, newParent))
         return HIERARCHY_REQUEST_ERR;
 
     if (oldChild && newParent->isDocumentNode()) {

Modified: trunk/Source/WebCore/dom/Document.cpp (138729 => 138730)


--- trunk/Source/WebCore/dom/Document.cpp	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/dom/Document.cpp	2013-01-03 21:16:59 UTC (rev 138730)
@@ -5945,18 +5945,15 @@
 }
 
 #if ENABLE(TEMPLATE_ELEMENT)
-Document* Document::templateContentsOwnerDocument()
+Document* Document::ensureTemplateContentsOwnerDocument()
 {
-    // If DOCUMENT does not have a browsing context, Let TEMPLATE CONTENTS OWNER be DOCUMENT and abort these steps.
-    if (!m_frame)
-        return this;
+    if (const Document* document = templateContentsOwnerDocument())
+        return const_cast<Document*>(document);
 
-    if (!m_templateContentsOwnerDocument) {
-        if (isHTMLDocument())
-            m_templateContentsOwnerDocument = HTMLDocument::create(0, blankURL());
-        else
-            m_templateContentsOwnerDocument = Document::create(0, blankURL());
-    }
+    if (isHTMLDocument())
+        m_templateContentsOwnerDocument = HTMLDocument::create(0, blankURL());
+    else
+        m_templateContentsOwnerDocument = Document::create(0, blankURL());
 
     return m_templateContentsOwnerDocument.get();
 }

Modified: trunk/Source/WebCore/dom/Document.h (138729 => 138730)


--- trunk/Source/WebCore/dom/Document.h	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/dom/Document.h	2013-01-03 21:16:59 UTC (rev 138730)
@@ -1192,7 +1192,8 @@
 #endif
 
 #if ENABLE(TEMPLATE_ELEMENT)
-    Document* templateContentsOwnerDocument();
+    const Document* templateContentsOwnerDocument() const;
+    Document* ensureTemplateContentsOwnerDocument();
 #endif
 
     virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0);
@@ -1570,6 +1571,17 @@
         didRemoveAllPendingStylesheet();
 }
 
+#if ENABLE(TEMPLATE_ELEMENT)
+inline const Document* Document::templateContentsOwnerDocument() const
+{
+    // If DOCUMENT does not have a browsing context, Let TEMPLATE CONTENTS OWNER be DOCUMENT and abort these steps.
+    if (!m_frame)
+        return this;
+
+    return m_templateContentsOwnerDocument.get();
+}
+#endif
+
 // Put these methods here, because they require the Document definition, but we really want to inline them.
 
 inline bool Node::isDocumentNode() const

Modified: trunk/Source/WebCore/dom/DocumentFragment.h (138729 => 138730)


--- trunk/Source/WebCore/dom/DocumentFragment.h	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/dom/DocumentFragment.h	2013-01-03 21:16:59 UTC (rev 138730)
@@ -37,6 +37,7 @@
     bool parseXML(const String&, Element* contextElement, FragmentScriptingPermission = AllowScriptingContent);
     
     virtual bool canContainRangeEndPoint() const { return true; }
+    virtual bool isTemplateContent() const { return false; }
 
 protected:
     DocumentFragment(Document*, ConstructionType = CreateContainer);

Modified: trunk/Source/WebCore/dom/Node.cpp (138729 => 138730)


--- trunk/Source/WebCore/dom/Node.cpp	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/dom/Node.cpp	2013-01-03 21:16:59 UTC (rev 138730)
@@ -46,6 +46,7 @@
 #include "DOMImplementation.h"
 #include "DOMSettableTokenList.h"
 #include "Document.h"
+#include "DocumentFragment.h"
 #include "DocumentType.h"
 #include "Element.h"
 #include "ElementRareData.h"
@@ -96,6 +97,7 @@
 #include "StorageEvent.h"
 #include "StyleResolver.h"
 #include "TagNodeList.h"
+#include "TemplateContentDocumentFragment.h"
 #include "Text.h"
 #include "TextEvent.h"
 #include "TreeScopeAdopter.h"
@@ -1055,17 +1057,32 @@
     return this == node || node->isDescendantOf(this);
 }
 
-bool Node::containsIncludingShadowDOM(Node* node)
+bool Node::containsIncludingShadowDOM(const Node* node) const
 {
-    if (!node)
-        return false;
-    for (Node* n = node; n; n = n->parentOrHostNode()) {
-        if (n == this)
+    for (; node; node = node->parentOrHostNode()) {
+        if (node == this)
             return true;
     }
     return false;
 }
 
+bool Node::containsIncludingHostElements(const Node* node) const
+{
+#if ENABLE(TEMPLATE_ELEMENT)
+    while (node) {
+        if (node == this)
+            return true;
+        if (node->isDocumentFragment() && static_cast<const DocumentFragment*>(node)->isTemplateContent())
+            node = static_cast<const TemplateContentDocumentFragment*>(node)->host();
+        else
+            node = node->parentOrHostNode();
+    }
+    return false;
+#else
+    return containsIncludingShadowDOM(node);
+#endif
+}
+
 void Node::attach()
 {
     ASSERT(!attached());

Modified: trunk/Source/WebCore/dom/Node.h (138729 => 138730)


--- trunk/Source/WebCore/dom/Node.h	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/dom/Node.h	2013-01-03 21:16:59 UTC (rev 138730)
@@ -277,6 +277,7 @@
     Node* nonBoundaryShadowTreeRootNode();
 
     // Node's parent, shadow tree host.
+    // FIXME: These methods should be renamed parentOrShadowHost*
     ContainerNode* parentOrHostNode() const;
     Element* parentOrHostElement() const;
     void setParentOrHostNode(ContainerNode*);
@@ -488,7 +489,8 @@
     void checkSetPrefix(const AtomicString& prefix, ExceptionCode&);
     bool isDescendantOf(const Node*) const;
     bool contains(const Node*) const;
-    bool containsIncludingShadowDOM(Node*);
+    bool containsIncludingShadowDOM(const Node*) const;
+    bool containsIncludingHostElements(const Node*) const;
 
     // Used to determine whether range offsets use characters or node indices.
     virtual bool offsetInCharacters() const;

Added: trunk/Source/WebCore/dom/TemplateContentDocumentFragment.h (0 => 138730)


--- trunk/Source/WebCore/dom/TemplateContentDocumentFragment.h	                        (rev 0)
+++ trunk/Source/WebCore/dom/TemplateContentDocumentFragment.h	2013-01-03 21:16:59 UTC (rev 138730)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#ifndef TemplateContentDocumentFragment_h
+#define TemplateContentDocumentFragment_h
+
+#if ENABLE(TEMPLATE_ELEMENT)
+
+#include "DocumentFragment.h"
+
+namespace WebCore {
+
+class TemplateContentDocumentFragment : public DocumentFragment {
+public:
+    static PassRefPtr<TemplateContentDocumentFragment> create(Document* document, const Element* host)
+    {
+        return adoptRef(new TemplateContentDocumentFragment(document, host));
+    }
+
+    const Element* host() const { return m_host; }
+
+private:
+    TemplateContentDocumentFragment(Document* document, const Element* host)
+        : DocumentFragment(document, CreateDocumentFragment)
+        , m_host(host)
+    {
+    }
+
+    virtual bool isTemplateContent() const OVERRIDE { return true; }
+
+    const Element* m_host;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(TEMPLATE_ELEMENT)
+
+#endif // TemplateContentDocumentFragment_h

Modified: trunk/Source/WebCore/editing/markup.cpp (138729 => 138730)


--- trunk/Source/WebCore/editing/markup.cpp	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/editing/markup.cpp	2013-01-03 21:16:59 UTC (rev 138730)
@@ -996,7 +996,7 @@
     Document* document = contextElement->document();
 #if ENABLE(TEMPLATE_ELEMENT)
     if (contextElement->hasTagName(templateTag))
-        document = document->templateContentsOwnerDocument();
+        document = document->ensureTemplateContentsOwnerDocument();
 #endif
     RefPtr<DocumentFragment> fragment = DocumentFragment::create(document);
 

Modified: trunk/Source/WebCore/html/HTMLTemplateElement.cpp (138729 => 138730)


--- trunk/Source/WebCore/html/HTMLTemplateElement.cpp	2013-01-03 21:00:37 UTC (rev 138729)
+++ trunk/Source/WebCore/html/HTMLTemplateElement.cpp	2013-01-03 21:16:59 UTC (rev 138730)
@@ -37,6 +37,7 @@
 #include "DOMImplementation.h"
 #include "DocumentFragment.h"
 #include "HTMLDocument.h"
+#include "TemplateContentDocumentFragment.h"
 #include "markup.h"
 
 namespace WebCore {
@@ -62,7 +63,7 @@
 DocumentFragment* HTMLTemplateElement::content() const
 {
     if (!m_content)
-        m_content = DocumentFragment::create(ownerDocument()->templateContentsOwnerDocument());
+        m_content = TemplateContentDocumentFragment::create(document()->ensureTemplateContentsOwnerDocument(), this);
 
     return m_content.get();
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to