Bug 1544144 - Fix custom HTML element creation when using prototype and XHTML. r=smaug
authorBrendan Dahl <bdahl@mozilla.com>
Mon, 15 Apr 2019 10:56:03 +0000
changeset 469517 fcd532097b93
parent 469516 90786b7142a8
child 469518 f17ab3584d22
push id35873
push userccoroiu@mozilla.com
push dateMon, 15 Apr 2019 21:36:26 +0000
treeherdermozilla-central@b8f49a14c458 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1544144
milestone68.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 1544144 - Fix custom HTML element creation when using prototype and XHTML. r=smaug Use the correct global for custom HTML elements created from a prototype. Also, add an error message to make it easier to spot when the PrototypeDocumentSink fails. Differential Revision: https://phabricator.services.mozilla.com/D27401
dom/base/Document.h
dom/base/nsContentUtils.cpp
dom/prototype/PrototypeDocumentContentSink.cpp
dom/prototype/PrototypeDocumentContentSink.h
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -2155,16 +2155,21 @@ class Document : public nsINode,
     if (IsSVGDocument()) {
       return false;
     }
     return AllowXULXBL();
   }
 
   bool IsScriptEnabled();
 
+  /**
+   * Returns true if this document was created from a nsXULPrototypeDocument.
+   */
+  bool HasPrototypeDocument() const { return mPrototypeDocument; }
+
   bool IsTopLevelContentDocument() const { return mIsTopLevelContentDocument; }
   void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument) {
     mIsTopLevelContentDocument = aIsTopLevelContentDocument;
     // When a document is set as TopLevelContentDocument, it must be
     // allowpaymentrequest. We handle the false case while a document is
     // appended in SetSubDocumentFor
     if (aIsTopLevelContentDocument) {
       SetAllowPaymentRequest(true);
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9570,21 +9570,22 @@ nsresult nsContentUtils::NewXULOrHTMLEle
                                      aFromParser == dom::NOT_FROM_PARSER;
     // Per discussion in https://github.com/w3c/webcomponents/issues/635,
     // use entry global in those places that are called from JS APIs and use the
     // node document's global object if it is called from parser.
     nsIGlobalObject* global;
     if (aFromParser == dom::NOT_FROM_PARSER) {
       global = GetEntryGlobal();
 
-      // XUL documents always use NOT_FROM_PARSER for non-XUL elements. We can
-      // get the global from the document in that case.
+      // Documents created from the PrototypeDocumentSink always use
+      // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
+      // document in that case.
       if (!global) {
         Document* doc = nodeInfo->GetDocument();
-        if (doc && doc->IsXULDocument()) {
+        if (doc && doc->HasPrototypeDocument()) {
           global = doc->GetScopeObject();
         }
       }
     } else {
       global = nodeInfo->GetDocument()->GetScopeObject();
     }
     if (!global) {
       // In browser chrome code, one may have access to a document which doesn't
--- a/dom/prototype/PrototypeDocumentContentSink.cpp
+++ b/dom/prototype/PrototypeDocumentContentSink.cpp
@@ -410,16 +410,27 @@ nsresult PrototypeDocumentContentSink::I
 
 void PrototypeDocumentContentSink::CloseElement(Element* aElement) {
   if (aElement->IsXULElement(nsGkAtoms::linkset)) {
     aElement->DoneAddingChildren(false);
   }
 }
 
 nsresult PrototypeDocumentContentSink::ResumeWalk() {
+  nsresult rv = ResumeWalkInternal();
+  if (NS_FAILED(rv)) {
+    nsContentUtils::ReportToConsoleNonLocalized(
+        NS_LITERAL_STRING("Failed to load document from prototype document."),
+        nsIScriptError::errorFlag, NS_LITERAL_CSTRING("Prototype Document"),
+        mDocument, mDocumentURI);
+  }
+  return rv;
+}
+
+nsresult PrototypeDocumentContentSink::ResumeWalkInternal() {
   MOZ_ASSERT(mStillWalking);
   // Walk the prototype and build the delegate content model. The
   // walk is performed in a top-down, left-to-right fashion. That
   // is, a parent is built before any of its children; a node is
   // only built after all of its siblings to the left are fully
   // constructed.
   //
   // It is interruptable so that transcluded documents (e.g.,
--- a/dom/prototype/PrototypeDocumentContentSink.h
+++ b/dom/prototype/PrototypeDocumentContentSink.h
@@ -178,21 +178,27 @@ class PrototypeDocumentContentSink final
   /**
    * The current prototype that we are walking to construct the
    * content model.
    */
   RefPtr<nsXULPrototypeDocument> mCurrentPrototype;
   nsresult CreateAndInsertPI(const nsXULPrototypePI* aProtoPI);
   nsresult ExecuteScript(nsXULPrototypeScript* aScript);
   nsresult LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock);
+
+  /**
+   * A wrapper around ResumeWalkInternal to report walking errors.
+   */
+  nsresult ResumeWalk();
+
   /**
    * Resume (or initiate) an interrupted (or newly prepared)
    * prototype walk.
    */
-  nsresult ResumeWalk();
+  nsresult ResumeWalkInternal();
 
   /**
    * Called at the end of ResumeWalk(), from StyleSheetLoaded(),
    * and from DocumentL10n.
    * If walking, stylesheets and l10n are not blocking, it
    * will trigger `DoneWalking()`.
    */
   nsresult MaybeDoneWalking();