Backed out changeset f2a5fc3e8c4e (bug 1274159)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Wed, 14 Dec 2016 13:27:22 +0100
changeset 370865 d423f3a721a7165eaa18db503d384256ba7f12b1
parent 370864 39947ae430ccdec68ffae1f6db5041ae370b604b
child 370866 3bef3e41a9c4041270a66ee33666525098d9023e
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1274159
milestone53.0a1
backs outf2a5fc3e8c4eee37aee5e5b875e7afa94ef65208
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
Backed out changeset f2a5fc3e8c4e (bug 1274159)
dom/base/CustomElementRegistry.cpp
dom/base/CustomElementRegistry.h
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/parser/WebIDL.py
dom/bindings/parser/tests/test_constructor.py
dom/bindings/parser/tests/test_constructor_no_interface_object.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
parser/htmlparser/nsHTMLTags.h
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -276,33 +276,16 @@ CustomElementRegistry::LookupCustomEleme
   CustomElementDefinition* data = mCustomDefinitions.Get(typeAtom);
   if (data && data->mLocalName == localNameAtom) {
     return data;
   }
 
   return nullptr;
 }
 
-CustomElementDefinition*
-CustomElementRegistry::LookupCustomElementDefinition(JSContext* aCx,
-                                                     JSObject* aConstructor) const
-{
-  JS::Rooted<JSObject*> constructor(aCx, js::CheckedUnwrap(aConstructor));
-
-  const auto& ptr = mConstructors.lookup(constructor);
-  if (!ptr) {
-    return nullptr;
-  }
-
-  CustomElementDefinition* definition = mCustomDefinitions.Get(ptr->value());
-  MOZ_ASSERT(definition, "Definition must be found in mCustomDefinitions");
-
-  return definition;
-}
-
 void
 CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
 {
   mozilla::dom::NodeInfo* info = aElement->NodeInfo();
 
   // Candidate may be a custom element through extension,
   // in which case the custom element type name will not
   // match the element tag name. e.g. <button is="x-button">.
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -123,20 +123,16 @@ struct CustomElementDefinition
   // The lifecycle callbacks to call for this custom element.
   nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
 
   // A construction stack.
   // TODO: Bug 1287348 - Implement construction stack for upgrading an element
 
   // The document custom element order.
   uint32_t mDocOrder;
-
-  bool IsCustomBuiltIn() {
-    return mType != mLocalName;
-  }
 };
 
 class CustomElementRegistry final : public nsISupports,
                                     public nsWrapperCache
 {
   // Allow nsDocument to access mCustomDefinitions and mCandidatesMap.
   friend class ::nsDocument;
 
@@ -153,19 +149,16 @@ public:
 
   /**
    * Looking up a custom element definition.
    * https://html.spec.whatwg.org/#look-up-a-custom-element-definition
    */
   CustomElementDefinition* LookupCustomElementDefinition(
     const nsAString& aLocalName, const nsAString* aIs = nullptr) const;
 
-  CustomElementDefinition* LookupCustomElementDefinition(
-    JSContext* aCx, JSObject *aConstructor) const;
-
   /**
    * Enqueue created callback or register upgrade candidate for
    * newly created custom elements, possibly extending an existing type.
    * ex. <x-button>, <button is="x-button> (type extension)
    */
   void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension);
 
   void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -14,45 +14,41 @@
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/SizePrintfMacros.h"
 #include "mozilla/Unused.h"
 #include "mozilla/UseCounter.h"
 
 #include "AccessCheck.h"
 #include "jsfriendapi.h"
-#include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDOMGlobalPropertyInitializer.h"
-#include "nsIParserService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIXPConnect.h"
 #include "nsUTF8Utils.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WrapperFactory.h"
 #include "xpcprivate.h"
 #include "XrayWrapper.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Sprintf.h"
 #include "nsGlobalWindow.h"
 
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/DOMErrorBinding.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLSharedObjectElement.h"
-#include "mozilla/dom/HTMLElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElementBinding.h"
 #include "mozilla/dom/HTMLAppletElementBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ResolveSystemBinding.h"
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/XrayExpandoClass.h"
@@ -61,40 +57,16 @@
 #include "ipc/ErrorIPCUtils.h"
 #include "mozilla/UseCounter.h"
 
 namespace mozilla {
 namespace dom {
 
 using namespace workers;
 
-// Forward declare GetConstructorObject methods.
-#define HTML_TAG(_tag, _classname, _interfacename)                             \
-namespace HTML##_interfacename##ElementBinding {                               \
-  JSObject* GetConstructorObject(JSContext*);                                  \
-}
-#define HTML_OTHER(_tag)
-#include "nsHTMLTagList.h"
-#undef HTML_TAG
-#undef HTML_OTHER
-
-typedef JSObject* (*constructorGetterCallback)(JSContext*);
-
-// Mapping of html tag and GetConstructorObject methods.
-#define HTML_TAG(_tag, _classname, _interfacename) HTML##_interfacename##ElementBinding::GetConstructorObject,
-#define HTML_OTHER(_tag) nullptr,
-// We use eHTMLTag_foo (where foo is the tag) which is defined in nsHTMLTags.h
-// to index into this array.
-static const constructorGetterCallback sConstructorGetterCallback[] = {
-  HTMLUnknownElementBinding::GetConstructorObject,
-#include "nsHTMLTagList.h"
-#undef HTML_TAG
-#undef HTML_OTHER
-};
-
 const JSErrorFormatString ErrorFormatString[] = {
 #define MSG_DEF(_name, _argc, _exn, _str) \
   { #_name, _str, _argc, _exn },
 #include "mozilla/dom/Errors.msg"
 #undef MSG_DEF
 };
 
 #define MSG_DEF(_name, _argc, _exn, _str) \
@@ -3388,141 +3360,16 @@ GetDesiredProto(JSContext* aCx, const JS
     aDesiredProto.set(nullptr);
     return true;
   }
 
   aDesiredProto.set(&protoVal.toObject());
   return true;
 }
 
-// https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor
-already_AddRefed<nsGenericHTMLElement>
-CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
-                  ErrorResult& aRv)
-{
-  // Step 1.
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
-  if (!window) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  nsIDocument* doc = window->GetExtantDoc();
-  if (!doc) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  RefPtr<mozilla::dom::CustomElementRegistry> registry(window->CustomElements());
-  if (!registry) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  // Step 2 is in the code output by CGClassConstructor.
-  // Step 3.
-  JSContext* cx = aGlobal.Context();
-  JS::Rooted<JSObject*> newTarget(cx, &aCallArgs.newTarget().toObject());
-  CustomElementDefinition* definition =
-    registry->LookupCustomElementDefinition(cx, newTarget);
-  if (!definition) {
-    aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
-    return nullptr;
-  }
-
-  // The callee might be an Xray. Unwrap it to get actual callee.
-  JS::Rooted<JSObject*> callee(cx, js::CheckedUnwrap(&aCallArgs.callee()));
-  if (!callee) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return nullptr;
-  }
-
-  // And the actual callee might be in different compartment, so enter its
-  // compartment before getting the standard constructor object to compare to,
-  // so we get it from the same global as callee itself.
-  JSAutoCompartment ac(cx, callee);
-  int32_t tag = eHTMLTag_userdefined;
-  if (!definition->IsCustomBuiltIn()) {
-    // Step 4.
-    // If the definition is for an autonomous custom element, the active
-    // function should be HTMLElement.
-    JS::Rooted<JSObject*> constructor(cx, HTMLElementBinding::GetConstructorObject(cx));
-    if (!constructor) {
-      aRv.NoteJSContextException(cx);
-      return nullptr;
-    }
-
-    if (callee != constructor) {
-      aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
-      return nullptr;
-    }
-  } else {
-    // Step 5.
-    // If the definition is for a customized built-in element, the localName
-    // should be defined in the specification.
-    nsIParserService* parserService = nsContentUtils::GetParserService();
-    if (!parserService) {
-      aRv.Throw(NS_ERROR_UNEXPECTED);
-      return nullptr;
-    }
-
-    tag = parserService->HTMLCaseSensitiveAtomTagToId(definition->mLocalName);
-    if (tag == eHTMLTag_userdefined) {
-      aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
-      return nullptr;
-    }
-
-    MOZ_ASSERT(tag <= NS_HTML_TAG_MAX, "tag is out of bounds");
-
-    // If the definition is for a customized built-in element, the active
-    // function should be the localname's element interface.
-    constructorGetterCallback cb = sConstructorGetterCallback[tag];
-    if (!cb) {
-      aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
-      return nullptr;
-    }
-
-    JS::Rooted<JSObject*> constructor(cx, cb(cx));
-    if (!constructor) {
-      aRv.NoteJSContextException(cx);
-      return nullptr;
-    }
-
-    if (callee != constructor) {
-      aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
-      return nullptr;
-    }
-  }
-
-  RefPtr<mozilla::dom::NodeInfo> nodeInfo =
-    doc->NodeInfoManager()->GetNodeInfo(definition->mLocalName,
-                                        nullptr,
-                                        kNameSpaceID_XHTML,
-                                        nsIDOMNode::ELEMENT_NODE);
-  if (!nodeInfo) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  // Step 6 and Step 7 are in the code output by CGClassConstructor.
-  // Step 8.
-  // Construction stack will be implemented in bug 1287348. So we always run
-  // "construction stack is empty" case for now.
-  RefPtr<nsGenericHTMLElement> element;
-  if (tag == eHTMLTag_userdefined) {
-    // Autonomous custom element.
-    element = NS_NewHTMLElement(nodeInfo.forget());
-  } else {
-    // Customized built-in element.
-    element = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
-  }
-
-  return element.forget();
-}
-
 #ifdef DEBUG
 namespace binding_detail {
 void
 AssertReflectorHasGivenProto(JSContext* aCx, JSObject* aReflector,
                              JS::Handle<JSObject*> aGivenProto)
 {
   if (!aGivenProto) {
     // Nothing to assert here
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -37,17 +37,16 @@
 #include "nsISupportsImpl.h"
 #include "qsObjectHelper.h"
 #include "xpcpublic.h"
 #include "nsIVariant.h"
 #include "mozilla/dom/FakeString.h"
 
 #include "nsWrapperCacheInlines.h"
 
-class nsGenericHTMLElement;
 class nsIJSID;
 
 namespace mozilla {
 
 enum UseCounter : int16_t;
 
 namespace dom {
 template<typename DataType> class MozMap;
@@ -3176,23 +3175,16 @@ bool GetSetlikeBackingObject(JSContext* 
                              bool* aBackingObjCreated);
 
 // Get the desired prototype object for an object construction from the given
 // CallArgs.  Null is returned if the default prototype should be used.
 bool
 GetDesiredProto(JSContext* aCx, const JS::CallArgs& aCallArgs,
                 JS::MutableHandle<JSObject*> aDesiredProto);
 
-// This function is expected to be called from the constructor function for an
-// HTML element interface; the global/callargs need to be whatever was passed to
-// that constructor function.
-already_AddRefed<nsGenericHTMLElement>
-CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
-                  ErrorResult& aRv);
-
 void
 SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
                              UseCounter aUseCounter);
 
 // Warnings
 void
 DeprecationWarning(JSContext* aCx, JSObject* aObject,
                    nsIDocument::DeprecatedOperations aOperation);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1633,21 +1633,16 @@ DOMInterfaces = {
         'register': False,
         },
 
 'TestWorkerExposedInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         },
 
-'TestHTMLConstructorInterface' : {
-        'headerFile': 'TestBindingHeader.h',
-        'register': False,
-        },
-
 }
 
 # These are temporary, until they've been converted to use new DOM bindings
 def addExternalIface(iface, nativeType=None, headerFile=None,
                      notflattened=False):
     if iface in DOMInterfaces:
         raise Exception('Interface declared both as WebIDL and External interface')
     domInterface = {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1712,126 +1712,39 @@ class CGClassConstructor(CGAbstractStati
         # the name JS sees is the interface name; for named constructors
         # identifier.name is the actual name.
         name = self._ctor.identifier.name
         if name != "constructor":
             ctorName = name
         else:
             ctorName = self.descriptor.interface.identifier.name
 
-        # [HTMLConstructor] for custom element
-        # This needs to live in bindings code because it directly examines
-        # newtarget and the callee function to do HTMLConstructor specific things.
-        if self._ctor.isHTMLConstructor():
-            htmlConstructorSanityCheck = dedent("""
-                // The newTarget might be a cross-compartment wrapper. Get the underlying object
-                // so we can do the spec's object-identity checks.
-                JS::Rooted<JSObject*> newTarget(cx, js::CheckedUnwrap(&args.newTarget().toObject()));
-                if (!newTarget) {
-                  return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
-                }
-
-                // Step 2 of https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor.
-                // Enter the compartment of our underlying newTarget object, so we end
-                // up comparing to the constructor object for our interface from that global.
-                {
-                  JSAutoCompartment ac(cx, newTarget);
-                  JS::Handle<JSObject*> constructor(GetConstructorObjectHandle(cx));
-                  if (!constructor) {
-                    return false;
-                  }
-                  if (newTarget == constructor) {
-                    return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
-                  }
-                }
-
-                """)
-
-            # If we are unable to get desired prototype from newTarget, then we
-            # fall back to the interface prototype object from newTarget's realm.
-            htmlConstructorFallback = dedent("""
-                if (!desiredProto) {
-                  // Step 7 of https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor.
-                  // This fallback behavior is designed to match analogous behavior for the
-                  // JavaScript built-ins. So we enter the compartment of our underlying
-                  // newTarget object and fall back to the prototype object from that global.
-                  // XXX The spec says to use GetFunctionRealm(), which is not actually
-                  // the same thing as what we have here (e.g. in the case of scripted callable proxies
-                  // whose target is not same-compartment with the proxy, or bound functions, etc).
-                  // https://bugzilla.mozilla.org/show_bug.cgi?id=1317658
-                  {
-                    JSAutoCompartment ac(cx, newTarget);
-                    desiredProto = GetProtoObjectHandle(cx);
-                    if (!desiredProto) {
-                        return false;
-                    }
-                  }
-
-                  // desiredProto is in the compartment of the underlying newTarget object.
-                  // Wrap it into the context compartment.
-                  if (!JS_WrapObject(cx, &desiredProto)) {
-                    return false;
-                  }
-                }
-                """)
-        else:
-            htmlConstructorSanityCheck = ""
-            htmlConstructorFallback = ""
-
-
-        # If we're a constructor, "obj" may not be a function, so calling
-        # XrayAwareCalleeGlobal() on it is not safe.  Of course in the
-        # constructor case either "obj" is an Xray or we're already in the
-        # content compartment, not the Xray compartment, so just
-        # constructing the GlobalObject from "obj" is fine.
         preamble = fill(
             """
             JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
             JS::Rooted<JSObject*> obj(cx, &args.callee());
             $*{chromeOnlyCheck}
             if (!args.isConstructing()) {
               // XXXbz wish I could get the name from the callee instead of
               // Adding more relocations
               return ThrowConstructorWithoutNew(cx, "${ctorName}");
             }
-
-            GlobalObject global(cx, obj);
-            if (global.Failed()) {
-              return false;
-            }
-
-            $*{htmlConstructorSanityCheck}
             JS::Rooted<JSObject*> desiredProto(cx);
             if (!GetDesiredProto(cx, args, &desiredProto)) {
               return false;
             }
-            $*{htmlConstructorFallback}
             """,
             chromeOnlyCheck=chromeOnlyCheck,
-            ctorName=ctorName,
-            htmlConstructorSanityCheck=htmlConstructorSanityCheck,
-            htmlConstructorFallback=htmlConstructorFallback)
-
-        if  self._ctor.isHTMLConstructor():
-            signatures = self._ctor.signatures()
-            assert len(signatures) == 1
-            # Given that HTMLConstructor takes no args, we can just codegen a
-            # call to CreateHTMLElement() in BindingUtils which reuses the
-            # factory thing in HTMLContentSink. Then we don't have to implement
-            # Constructor on all the HTML elements.
-            callGenerator = CGPerSignatureCall(signatures[0][0], signatures[0][1],
-                                               "CreateHTMLElement", True,
-                                               self.descriptor, self._ctor,
-                                               isConstructor=True)
-        else:
-            name = self._ctor.identifier.name
-            nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
-            callGenerator = CGMethodCall(nativeName, True, self.descriptor,
-                                         self._ctor, isConstructor=True,
-                                         constructorName=ctorName)
+            ctorName=ctorName)
+
+        name = self._ctor.identifier.name
+        nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
+        callGenerator = CGMethodCall(nativeName, True, self.descriptor,
+                                     self._ctor, isConstructor=True,
+                                     constructorName=ctorName)
         return preamble + "\n" + callGenerator.define()
 
 
 # Encapsulate the constructor in a helper method to share genConstructorBody with CGJSImplMethod.
 class CGConstructNavigatorObject(CGAbstractMethod):
     """
     Construct a new JS-implemented WebIDL DOM object, for use on navigator.
     """
@@ -7392,33 +7305,36 @@ class CGPerSignatureCall(CGThing):
             cgThings.append(CGGeneric(dedent(
                 """
                 bool foundNonFiniteFloat = false;
                 """)))
             lenientFloatCode = "foundNonFiniteFloat = true;\n"
 
         argsPre = []
         if idlNode.isStatic():
-            # If we're a constructor, the GlobalObject struct will be created in
-            # CGClassConstructor.
-            if not isConstructor:
-                cgThings.append(CGGeneric(dedent(
-                    """
-                    GlobalObject global(cx, xpc::XrayAwareCalleeGlobal(obj));
-                    if (global.Failed()) {
-                      return false;
-                    }
-
-                    """)))
-
+            # If we're a constructor, "obj" may not be a function, so calling
+            # XrayAwareCalleeGlobal() on it is not safe.  Of course in the
+            # constructor case either "obj" is an Xray or we're already in the
+            # content compartment, not the Xray compartment, so just
+            # constructing the GlobalObject from "obj" is fine.
+            if isConstructor:
+                objForGlobalObject = "obj"
+            else:
+                objForGlobalObject = "xpc::XrayAwareCalleeGlobal(obj)"
+            cgThings.append(CGGeneric(fill(
+                """
+                GlobalObject global(cx, ${obj});
+                if (global.Failed()) {
+                  return false;
+                }
+
+                """,
+                obj=objForGlobalObject)))
             argsPre.append("global")
 
-        if isConstructor and idlNode.isHTMLConstructor():
-            argsPre.append("args")
-
         # For JS-implemented interfaces we do not want to base the
         # needsCx decision on the types involved, just on our extended
         # attributes. Also, JSContext is not needed for the static case
         # since GlobalObject already contains the context.
         needsCx = needCx(returnType, arguments, self.extendedAttributes,
                          not descriptor.interface.isJSImplemented(), static)
         if needsCx:
             argsPre.append("cx")
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -1577,71 +1577,61 @@ class IDLInterface(IDLInterfaceOrNamespa
                     raise WebIDLError("[NoInterfaceObject] must take no arguments",
                                       [attr.location])
 
                 if self.ctor():
                     raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
                                       [self.location])
 
                 self._noInterfaceObject = True
-            elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
+            elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
                 if identifier == "Constructor" and not self.hasInterfaceObject():
                     raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
                                       [self.location])
 
                 if identifier == "NamedConstructor" and not attr.hasValue():
                     raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
                                       [attr.location])
 
                 if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
                     raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
                                       [self.location])
 
-                if identifier == "HTMLConstructor":
-                    if not self.hasInterfaceObject():
-                        raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
-                                          [self.location])
-
-                    if not attr.noArguments():
-                        raise WebIDLError(str(identifier) + " must take no arguments",
-                                          [attr.location])
-
                 args = attr.args() if attr.hasArgs() else []
 
                 if self.identifier.name == "Promise":
                     promiseType = BuiltinTypes[IDLBuiltinType.Types.any]
                 else:
                     promiseType = None
                 retType = IDLWrapperType(self.location, self, promiseType)
 
-                if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
+                if identifier == "Constructor" or identifier == "ChromeConstructor":
                     name = "constructor"
                     allowForbidden = True
                 else:
                     name = attr.value()
                     allowForbidden = False
 
                 methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
                                                            allowForbidden=allowForbidden)
 
                 method = IDLMethod(self.location, methodIdentifier, retType,
-                                   args, static=True,
-                                   htmlConstructor=(identifier == "HTMLConstructor"))
+                                   args, static=True)
                 # Constructors are always NewObject and are always
                 # assumed to be able to throw (since there's no way to
                 # indicate otherwise) and never have any other
                 # extended attributes.
                 method.addExtendedAttributes(
                     [IDLExtendedAttribute(self.location, ("NewObject",)),
                      IDLExtendedAttribute(self.location, ("Throws",))])
                 if identifier == "ChromeConstructor":
                     method.addExtendedAttributes(
                         [IDLExtendedAttribute(self.location, ("ChromeOnly",))])
 
-                if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
+                if identifier == "Constructor" or identifier == "ChromeConstructor":
                     method.resolve(self)
                 else:
                     # We need to detect conflicts for NamedConstructors across
                     # interfaces. We first call resolve on the parentScope,
                     # which will merge all NamedConstructors with the same
                     # identifier accross interfaces as overloads.
                     method.resolve(self.parentScope)
 
@@ -4513,17 +4503,17 @@ class IDLMethod(IDLInterfaceMember, IDLS
         'Named',
         'Indexed'
     )
 
     def __init__(self, location, identifier, returnType, arguments,
                  static=False, getter=False, setter=False, creator=False,
                  deleter=False, specialType=NamedOrIndexed.Neither,
                  legacycaller=False, stringifier=False, jsonifier=False,
-                 maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
+                 maplikeOrSetlikeOrIterable=None):
         # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Method)
 
         self._hasOverloads = False
 
         assert isinstance(returnType, IDLType)
 
@@ -4543,20 +4533,16 @@ class IDLMethod(IDLInterfaceMember, IDLS
         assert isinstance(legacycaller, bool)
         self._legacycaller = legacycaller
         assert isinstance(stringifier, bool)
         self._stringifier = stringifier
         assert isinstance(jsonifier, bool)
         self._jsonifier = jsonifier
         assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
         self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
-        assert isinstance(htmlConstructor, bool)
-        # The identifier of a HTMLConstructor must be 'constructor'.
-        assert not htmlConstructor or identifier.name == "constructor"
-        self._htmlConstructor = htmlConstructor
         self._specialType = specialType
         self._unforgeable = False
         self.dependsOn = "Everything"
         self.affects = "Everything"
         self.aliases = []
 
         if static and identifier.name == "prototype":
             raise WebIDLError("The identifier of a static operation must not be 'prototype'",
@@ -4647,19 +4633,16 @@ class IDLMethod(IDLInterfaceMember, IDLS
         return (self.isGetter() or
                 self.isSetter() or
                 self.isCreator() or
                 self.isDeleter() or
                 self.isLegacycaller() or
                 self.isStringifier() or
                 self.isJsonifier())
 
-    def isHTMLConstructor(self):
-        return self._htmlConstructor
-
     def hasOverloads(self):
         return self._hasOverloads
 
     def isIdentifierLess(self):
         """
         True if the method name started with __, and if the method is not a
         maplike/setlike method. Interfaces with maplike/setlike will generate
         methods starting with __ for chrome only backing object access in JS
@@ -4705,18 +4688,16 @@ class IDLMethod(IDLInterfaceMember, IDLS
         assert not self.isCreator()
         assert not method.isCreator()
         assert not self.isDeleter()
         assert not method.isDeleter()
         assert not self.isStringifier()
         assert not method.isStringifier()
         assert not self.isJsonifier()
         assert not method.isJsonifier()
-        assert not self.isHTMLConstructor()
-        assert not method.isHTMLConstructor()
 
         return self
 
     def signatures(self):
         return [(overload.returnType, overload.arguments) for overload in
                 self._overloads]
 
     def finish(self, scope):
--- a/dom/bindings/parser/tests/test_constructor.py
+++ b/dom/bindings/parser/tests/test_constructor.py
@@ -8,33 +8,32 @@ def WebIDLTest(parser, harness):
         harness.check(argument.identifier.name, name, "Argument has the right name")
         harness.check(str(argument.type), type, "Argument has the right return type")
         harness.check(argument.optional, optional, "Argument has the right optional value")
         harness.check(argument.variadic, variadic, "Argument has the right variadic value")
 
     def checkMethod(method, QName, name, signatures,
                     static=True, getter=False, setter=False, creator=False,
                     deleter=False, legacycaller=False, stringifier=False,
-                    chromeOnly=False, htmlConstructor=False):
+                    chromeOnly=False):
         harness.ok(isinstance(method, WebIDL.IDLMethod),
                    "Should be an IDLMethod")
         harness.ok(method.isMethod(), "Method is a method")
         harness.ok(not method.isAttr(), "Method is not an attr")
         harness.ok(not method.isConst(), "Method is not a const")
         harness.check(method.identifier.QName(), QName, "Method has the right QName")
         harness.check(method.identifier.name, name, "Method has the right name")
         harness.check(method.isStatic(), static, "Method has the correct static value")
         harness.check(method.isGetter(), getter, "Method has the correct getter value")
         harness.check(method.isSetter(), setter, "Method has the correct setter value")
         harness.check(method.isCreator(), creator, "Method has the correct creator value")
         harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
         harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
         harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
         harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
-        harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
         harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
 
         sigpairs = zip(method.signatures(), signatures)
         for (gotSignature, expectedSignature) in sigpairs:
             (gotRetType, gotArgs) = gotSignature
             (expectedRetType, expectedArgs) = expectedSignature
 
             harness.check(str(gotRetType), expectedRetType,
@@ -90,184 +89,21 @@ def WebIDLTest(parser, harness):
     harness.ok(isinstance(results[0], WebIDL.IDLInterface),
                "Should be an IDLInterface")
 
     checkMethod(results[0].ctor(), "::TestChromeConstructor::constructor",
                 "constructor", [("TestChromeConstructor (Wrapper)", [])],
                 chromeOnly=True)
 
     parser = parser.reset()
-    parser.parse("""
-        [HTMLConstructor]
-        interface TestHTMLConstructor {
-        };
-    """)
-    results = parser.finish()
-    harness.check(len(results), 1, "Should be one production")
-    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
-               "Should be an IDLInterface")
-
-    checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor",
-                "constructor", [("TestHTMLConstructor (Wrapper)", [])],
-                htmlConstructor=True)
-
-    parser = parser.reset()
     threw = False
     try:
         parser.parse("""
         [Constructor(),
          ChromeConstructor(DOMString a)]
         interface TestChromeConstructor {
         };
         """)
         results = parser.finish()
     except:
         threw = True
 
     harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")
-
-    # Test HTMLConstructor with argument
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor(DOMString a)]
-            interface TestHTMLConstructorWithArgs {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "HTMLConstructor should take no argument")
-
-    # Test HTMLConstructor on a callback interface
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor]
-            callback interface TestHTMLConstructorOnCallbackInterface {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
-
-    # Test HTMLConstructor and Constructor
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [Constructor,
-             HTMLConstructor]
-            interface TestHTMLConstructorAndConstructor {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a Constructor and a HTMLConstructor")
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor,
-             Constructor]
-            interface TestHTMLConstructorAndConstructor {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor,
-             Constructor(DOMString a)]
-            interface TestHTMLConstructorAndConstructor {
-            };
-        """)
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [Constructor(DOMString a),
-             HTMLConstructor]
-            interface TestHTMLConstructorAndConstructor {
-            };
-        """)
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
-
-    # Test HTMLConstructor and ChromeConstructor
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [ChromeConstructor,
-             HTMLConstructor]
-            interface TestHTMLConstructorAndChromeConstructor {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor,
-             ChromeConstructor]
-            interface TestHTMLConstructorAndChromeConstructor {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [ChromeConstructor(DOMString a),
-             HTMLConstructor]
-            interface TestHTMLConstructorAndChromeConstructor {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor,
-             ChromeConstructor(DOMString a)]
-            interface TestHTMLConstructorAndChromeConstructor {
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
--- a/dom/bindings/parser/tests/test_constructor_no_interface_object.py
+++ b/dom/bindings/parser/tests/test_constructor_no_interface_object.py
@@ -29,41 +29,8 @@ def WebIDLTest(parser, harness):
 
     parser = parser.reset()
 
     parser.parse("""
         [NoInterfaceObject, NamedConstructor=FooBar]
         interface TestNamedConstructorNoInterfaceObject {
         };
     """)
-
-    # Test HTMLConstructor and NoInterfaceObject
-    parser = parser.reset()
-
-    threw = False
-    try:
-        parser.parse("""
-            [NoInterfaceObject, HTMLConstructor]
-            interface TestHTMLConstructorNoInterfaceObject {
-            };
-        """)
-
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Should have thrown.")
-
-    parser = parser.reset()
-
-    threw = False
-    try:
-        parser.parse("""
-            [HTMLConstructor, NoInterfaceObject]
-            interface TestHTMLConstructorNoInterfaceObject {
-            };
-        """)
-
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(threw, "Should have thrown.")
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -1420,18 +1420,12 @@ public:
   void NeedsSubjectPrincipalMethod(Maybe<nsIPrincipal*>);
   bool NeedsSubjectPrincipalAttr(Maybe<nsIPrincipal*>);
   void SetNeedsSubjectPrincipalAttr(bool, Maybe<nsIPrincipal*>);
   void NeedsCallerTypeMethod(CallerType);
   bool NeedsCallerTypeAttr(CallerType);
   void SetNeedsCallerTypeAttr(bool, CallerType);
 };
 
-class TestHTMLConstructorInterface : public nsGenericHTMLElement
-{
-public:
-  virtual nsISupports* GetParentObject();
-};
-
 } // namespace dom
 } // namespace mozilla
 
 #endif /* TestBindingHeader_h */
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -1257,12 +1257,8 @@ interface TestSecureContextInterface {
 
 [Exposed=(Window,Worker)]
 interface TestWorkerExposedInterface {
   [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
   [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   [NeedsCallerType] void needsCallerTypeMethod();
   [NeedsCallerType] attribute boolean needsCallerTypeAttr;
 };
-
-[HTMLConstructor]
-interface TestHTMLConstructorInterface {
-};
--- a/parser/htmlparser/nsHTMLTags.h
+++ b/parser/htmlparser/nsHTMLTags.h
@@ -12,20 +12,16 @@
 class nsIAtom;
 
 /*
    Declare the enum list using the magic of preprocessing
    enum values are "eHTMLTag_foo" (where foo is the tag)
 
    To change the list of tags, see nsHTMLTagList.h
 
-   These enum values are used as the index of array in various places.
-   If we change the structure of the enum by adding entries to it or removing
-   entries from it _directly_, not via nsHTMLTagList.h, don't forget to update
-   dom/bindings/BindingUtils.cpp and dom/html/nsHTMLContentSink.cpp as well.
  */
 #define HTML_TAG(_tag, _classname, _interfacename) eHTMLTag_##_tag,
 #define HTML_OTHER(_tag) eHTMLTag_##_tag,
 enum nsHTMLTag {
   /* this enum must be first and must be zero */
   eHTMLTag_unknown = 0,
 #include "nsHTMLTagList.h"