Bug 1017896 - Ensure there is a template contents owner when creating template elements. r=bz
authorWilliam Chen <wchen@mozilla.com>
Wed, 04 Jun 2014 14:47:31 -0700
changeset 205909 91ad28afdd77610e271e28eac36e572de6904bdc
parent 205908 a76d3c8b0f6421112bdb0516108d0651526b3d0e
child 205910 703903939a5e1d2e83cd0970c167d7d333a959e6
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1017896
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1017896 - Ensure there is a template contents owner when creating template elements. r=bz
content/base/src/nsDocument.cpp
content/html/content/src/HTMLTemplateElement.cpp
content/html/content/src/HTMLTemplateElement.h
dom/tests/mochitest/webcomponents/mochitest.ini
dom/tests/mochitest/webcomponents/test_bug1017896.html
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -4508,16 +4508,21 @@ nsDocument::SetScriptGlobalObject(nsIScr
   }
 
   // Set our visibility state, but do not fire the event.  This is correct
   // because either we're coming out of bfcache (in which case IsVisible() will
   // still test false at this point and no state change will happen) or we're
   // doing the initial document load and don't want to fire the event for this
   // change.
   mVisibilityState = GetVisibilityState();
+
+  // The global in the template contents owner document should be the same.
+  if (mTemplateContentsOwner && mTemplateContentsOwner != this) {
+    mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
+  }
 }
 
 nsIScriptGlobalObject*
 nsDocument::GetScriptHandlingObjectInternal() const
 {
   MOZ_ASSERT(!mScriptGlobalObject,
              "Do not call this when mScriptGlobalObject is set!");
   if (mHasHadDefaultView) {
@@ -9438,17 +9443,16 @@ nsDocument::GetCurrentContentSink()
 
 nsIDocument*
 nsDocument::GetTemplateContentsOwner()
 {
   if (!mTemplateContentsOwner) {
     bool hasHadScriptObject = true;
     nsIScriptGlobalObject* scriptObject =
       GetScriptHandlingObject(hasHadScriptObject);
-    NS_ENSURE_TRUE(scriptObject || !hasHadScriptObject, nullptr);
 
     nsCOMPtr<nsIDOMDocument> domDocument;
     nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
                                     EmptyString(), // aNamespaceURI
                                     EmptyString(), // aQualifiedName
                                     nullptr, // aDoctype
                                     nsIDocument::GetDocumentURI(),
                                     nsIDocument::GetDocBaseURI(),
@@ -9456,22 +9460,26 @@ nsDocument::GetTemplateContentsOwner()
                                     true, // aLoadedAsData
                                     scriptObject, // aEventObject
                                     DocumentFlavorHTML);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     mTemplateContentsOwner = do_QueryInterface(domDocument);
     NS_ENSURE_TRUE(mTemplateContentsOwner, nullptr);
 
-    mTemplateContentsOwner->SetScriptHandlingObject(scriptObject);
+    nsDocument* doc = static_cast<nsDocument*>(mTemplateContentsOwner.get());
+    doc->mHasHadScriptHandlingObject = hasHadScriptObject;
+
+    if (!scriptObject) {
+      mTemplateContentsOwner->SetScopeObject(GetScopeObject());
+    }
 
     // Set |doc| as the template contents owner of itself so that
     // |doc| is the template contents owner of template elements created
     // by |doc|.
-    nsDocument* doc = static_cast<nsDocument*>(mTemplateContentsOwner.get());
     doc->mTemplateContentsOwner = doc;
   }
 
   return mTemplateContentsOwner;
 }
 
 void
 nsDocument::RegisterHostObjectUri(const nsACString& aUri)
--- a/content/html/content/src/HTMLTemplateElement.cpp
+++ b/content/html/content/src/HTMLTemplateElement.cpp
@@ -6,51 +6,33 @@
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/HTMLTemplateElementBinding.h"
 
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIAtom.h"
 #include "nsRuleData.h"
 
-using namespace mozilla::dom;
-
-nsGenericHTMLElement*
-NS_NewHTMLTemplateElement(already_AddRefed<nsINodeInfo>&& aNodeInfo,
-                          FromParser aFromParser)
-{
-  HTMLTemplateElement* it = new HTMLTemplateElement(aNodeInfo);
-  nsresult rv = it->Init();
-  if (NS_FAILED(rv)) {
-    delete it;
-    return nullptr;
-  }
-
-  return it;
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT(Template)
 
 namespace mozilla {
 namespace dom {
 
 HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
   SetHasWeirdParserInsertionMode();
-}
 
-nsresult
-HTMLTemplateElement::Init()
-{
   nsIDocument* contentsOwner = OwnerDoc()->GetTemplateContentsOwner();
-  NS_ENSURE_TRUE(contentsOwner, NS_ERROR_UNEXPECTED);
+  if (!contentsOwner) {
+    MOZ_CRASH("There should always be a template contents owner.");
+  }
 
   mContent = contentsOwner->CreateDocumentFragment();
   mContent->SetHost(this);
-
-  return NS_OK;
 }
 
 HTMLTemplateElement::~HTMLTemplateElement()
 {
   if (mContent) {
     mContent->SetHost(nullptr);
   }
 }
@@ -72,17 +54,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // QueryInterface implementation for HTMLTemplateElement
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTemplateElement)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(HTMLTemplateElement)
+NS_IMPL_ELEMENT_CLONE(HTMLTemplateElement)
 
 JSObject*
 HTMLTemplateElement::WrapNode(JSContext *aCx)
 {
   return HTMLTemplateElementBinding::Wrap(aCx, this);
 }
 
 } // namespace dom
--- a/content/html/content/src/HTMLTemplateElement.h
+++ b/content/html/content/src/HTMLTemplateElement.h
@@ -23,18 +23,16 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTemplateElement,
                                            nsGenericHTMLElement)
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
-  nsresult Init();
-
   DocumentFragment* Content()
   {
     return mContent;
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
 
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 support-files =
   inert_style.css
 
 [test_bug900724.html]
+[test_bug1017896.html]
 [test_content_element.html]
 [test_nested_content_element.html]
 [test_dest_insertion_points.html]
 [test_dest_insertion_points_shadow.html]
 [test_fallback_dest_insertion_points.html]
 [test_dynamic_content_element_matching.html]
 [test_document_register.html]
 [test_document_register_base_queue.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_bug1017896.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1017896
+-->
+<head>
+  <title>Test template element in stale document.</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017896">Bug 1017896</a>
+<div id="container"></div>
+<script>
+
+SimpleTest.waitForExplicitFinish();
+
+var frame = document.createElement("iframe");
+document.getElementById("container").appendChild(frame);
+
+var staleFrameDoc = frame.contentDocument;
+
+setTimeout(function() {
+  var v = staleFrameDoc.createElement("div");
+  v.innerHTML = "<template>Content</template>";
+  is(v.firstChild.content.childNodes.length, 1, "Template should have one child in template content.");
+  SimpleTest.finish();
+}, 0);
+
+</script>
+</body>
+</html>