Bug 1354013 - Creating customized built-in elements without relevant definitions registered first shouldn't throw NotFoundError; r=wchen
authorEdgar Chen <echen@mozilla.com>
Thu, 06 Apr 2017 17:00:41 +0800
changeset 357176 448fa97e51939ab7b78c2818c337b20d57334495
parent 357175 553d3684230c42f38b5dae8b4741ede603ac1589
child 357177 2180cc0cf12125e6bd1c68854372ae994f58dfc1
push id90063
push userechen@mozilla.com
push dateTue, 09 May 2017 06:16:06 +0000
treeherdermozilla-inbound@448fa97e5193 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswchen
bugs1354013
milestone55.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 1354013 - Creating customized built-in elements without relevant definitions registered first shouldn't throw NotFoundError; r=wchen per spec change: https://github.com/w3c/webcomponents/issues/608 MozReview-Commit-ID: 3W4qTndQsP7
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/tests/mochitest/webcomponents/test_document_register.html
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -5740,22 +5740,20 @@ nsDocument::CreateElement(const nsAStrin
     nsContentUtils::ASCIIToLower(aTagName, lcTagName);
   }
 
   const nsString* is = nullptr;
   CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
   if (aOptions.IsElementCreationOptions()) {
     const ElementCreationOptions& options =
       aOptions.GetAsElementCreationOptions();
-    // Throw NotFoundError if 'is' is not-null and definition is null
-    is = CheckCustomElementName(options,
-                                needsLowercase ? lcTagName : aTagName,
-                                mDefaultElementType, rv);
-    if (rv.Failed()) {
-      return nullptr;
+
+    if (CustomElementRegistry::IsCustomElementEnabled() &&
+        options.mIs.WasPassed()) {
+      is = &options.mIs.Value();
     }
 
     // Check 'pseudo' and throw an exception if it's not one allowed
     // with CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC.
     if (options.mPseudo.WasPassed()) {
       pseudoType = GetPseudoElementType(options.mPseudo.Value(), rv);
       if (rv.Failed() ||
           pseudoType == CSSPseudoElementType::NotPseudo ||
@@ -5804,22 +5802,21 @@ nsDocument::CreateElementNS(const nsAStr
                                             mNodeInfoManager,
                                             nsIDOMNode::ELEMENT_NODE,
                                             getter_AddRefs(nodeInfo));
   if (rv.Failed()) {
     return nullptr;
   }
 
   const nsString* is = nullptr;
-  if (aOptions.IsElementCreationOptions()) {
-    // Throw NotFoundError if 'is' is not-null and definition is null
-    is = CheckCustomElementName(aOptions.GetAsElementCreationOptions(),
-                                aQualifiedName, nodeInfo->NamespaceID(), rv);
-    if (rv.Failed()) {
-      return nullptr;
+  if (CustomElementRegistry::IsCustomElementEnabled() &&
+      aOptions.IsElementCreationOptions()) {
+    const ElementCreationOptions& options = aOptions.GetAsElementCreationOptions();
+    if (options.mIs.WasPassed()) {
+      is = &options.mIs.Value();
     }
   }
 
   nsCOMPtr<Element> element;
   rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
                      NOT_FROM_PARSER, is);
   if (rv.Failed()) {
     return nullptr;
@@ -13182,40 +13179,16 @@ nsIDocument::UpdateStyleBackendType()
   if (!mDocumentContainer) {
     NS_WARNING("stylo: No docshell yet, assuming Gecko style system");
   } else if (nsLayoutUtils::SupportsServoStyleBackend(this)) {
     mStyleBackendType = StyleBackendType::Servo;
   }
 #endif
 }
 
-const nsString*
-nsDocument::CheckCustomElementName(const ElementCreationOptions& aOptions,
-                                   const nsAString& aLocalName,
-                                   uint32_t aNamespaceID,
-                                   ErrorResult& rv)
-{
-  // only check aOptions if 'is' is passed and the webcomponents preference
-  // is enabled
-  if (!aOptions.mIs.WasPassed() ||
-      !CustomElementRegistry::IsCustomElementEnabled()) {
-      return nullptr;
-  }
-
-  const nsString* is = &aOptions.mIs.Value();
-
-  // Throw NotFoundError if 'is' is not-null and definition is null
-  if (!nsContentUtils::LookupCustomElementDefinition(this, aLocalName,
-                                                     aNamespaceID, is)) {
-      rv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
-  }
-
-  return is;
-}
-
 /**
  * Helper function for |nsDocument::PrincipalFlashClassification|
  *
  * Adds a table name string to a table list (a comma separated string). The
  * table will not be added if the name is an empty string.
  */
 static void
 MaybeAddTableToTableList(const nsACString& aTableNames,
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -1458,30 +1458,16 @@ protected:
   mozilla::dom::FlashClassification mFlashClassification;
   // Do not use this value directly. Call the |IsThirdParty()| method, which
   // caches its result here.
   mozilla::Maybe<bool> mIsThirdParty;
 private:
   void UpdatePossiblyStaleDocumentState();
   static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
 
-  /**
-   * Check if the passed custom element name, aOptions.mIs, is a registered
-   * custom element type or not, then return the custom element name for future
-   * usage.
-   *
-   * If there is no existing custom element definition for this name, throw a
-   * NotFoundError.
-   */
-  const nsString* CheckCustomElementName(
-    const mozilla::dom::ElementCreationOptions& aOptions,
-    const nsAString& aLocalName,
-    uint32_t aNamespaceID,
-    ErrorResult& rv);
-
 public:
   virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
     GetCustomElementRegistry() override;
 
   // Check whether web components are enabled for the global of aObject.
   static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
   // Check whether web components are enabled for the global of the document
   // this nodeinfo comes from.
--- a/dom/tests/mochitest/webcomponents/test_document_register.html
+++ b/dom/tests/mochitest/webcomponents/test_document_register.html
@@ -98,62 +98,22 @@ function startTest() {
   var extendedProto = Object.create(HTMLButtonElement.prototype);
   var buttonConstructor = document.registerElement("x-extended-button", { prototype: extendedProto, extends: "button" });
   var extendedButton = document.createElement("button", {is: "x-extended-button"});
   is(extendedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
   is(extendedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
   is(extendedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
   is(extendedButton.type, "submit", "Created element should be a button with type of \"submit\"");
 
-  // document.createElementNS with different namespace than definition.
-  try {
-    var svgButton = document.createElementNS("http://www.w3.org/2000/svg", "button", {is: "x-extended-button"});
-    ok(false, "An exception should've been thrown");
-  } catch(err) {
-    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
-  }
-
-  // document.createElementNS with no namespace.
-  try {
-    var noNamespaceButton = document.createElementNS("", "button", {is: "x-extended-button"});
-    ok(false, "An exception should've been thrown");
-  } catch(err) {
-    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
-  }
-
-  // document.createElement with non-existant extended type.
-  try {
-    var normalButton = document.createElement("button", {is: "x-non-existant"});
-    ok(false, "An exception should've been thrown");
-  } catch(err) {
-    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
-  }
-
-  // document.createElement with exteneded type that does not match with local name of element.
-  try {
-    var normalDiv = document.createElement("div", {is: "x-extended-button"});
-    ok(false, "An exception should've been thrown");
-  } catch(err) {
-    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
-  }
-
   // Custom element constructor.
   var constructedButton = new buttonConstructor();
   is(constructedButton.tagName, "BUTTON", "Created element should have local name of BUTTON");
   is(constructedButton.__proto__, extendedProto, "Created element should have the prototype of the extended type.");
   is(constructedButton.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
 
-  // document.createElement with different namespace than definition for extended element.
-  try {
-    var htmlText = document.createElement("text", {is: "x-extended-text"});
-    ok(false, "An exception should've been thrown");
-  } catch(err) {
-    is(err.name, "NotFoundError", "A NotFoundError exception should've been thrown");
-  }
-
   // Try creating an element with a custom element name, but not in the html namespace.
   var htmlNamespaceProto = Object.create(HTMLElement.prototype);
   document.registerElement("x-in-html-namespace", { prototype: htmlNamespaceProto });
   var wrongNamespaceElem = document.createElementNS("http://www.w3.org/2000/svg", "x-in-html-namespace");
   isnot(wrongNamespaceElem.__proto__, htmlNamespaceProto, "Definition for element in html namespace should not apply to SVG elements.");
 }
 
 startTest();