From fd8d6b1590a9833973b0b470ae2e0c35430f34f0 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Wed, 15 Aug 2018 10:31:16 +0000 Subject: [PATCH] Bug 1480465: Infer the namespace for custom elements at definition time by following the class hierarchy. r=smaug When a custom element is defined we can check whether its class is an instance of XULElement or HTMLElement and tag the defintion with a namespace accordingly. This allows us to know the correct namespace for the custom element when created. Differential Revision: https://phabricator.services.mozilla.com/D2680 --HG-- extra : moz-landing-system : lando --- dom/base/CustomElementRegistry.cpp | 28 ++++- dom/base/CustomElementRegistry.h | 8 +- dom/base/nsContentUtils.cpp | 11 +- dom/bindings/BindingUtils.cpp | 5 +- .../webcomponents/chrome_disabled.ini | 3 + .../test_custom_element_namespace.html | 95 +++++++++++++++ .../test_custom_element_namespace.xhtml | 104 ++++++++++++++++ .../test_custom_element_namespace.xul | 112 ++++++++++++++++++ parser/html/nsHtml5TreeOperation.cpp | 2 +- 9 files changed, 359 insertions(+), 9 deletions(-) create mode 100644 dom/tests/mochitest/webcomponents/test_custom_element_namespace.html create mode 100644 dom/tests/mochitest/webcomponents/test_custom_element_namespace.xhtml create mode 100644 dom/tests/mochitest/webcomponents/test_custom_element_namespace.xul diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index d6b7821dbd1a..781ca153c625 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -10,6 +10,7 @@ #include "mozilla/CycleCollectedJSContext.h" #include "mozilla/dom/CustomElementRegistryBinding.h" #include "mozilla/dom/HTMLElementBinding.h" +#include "mozilla/dom/XULElementBinding.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/WebComponentsBinding.h" #include "mozilla/dom/DocGroup.h" @@ -356,6 +357,7 @@ CustomElementRegistry::RunCustomElementCreationCallback::Run() CustomElementDefinition* CustomElementRegistry::LookupCustomElementDefinition(nsAtom* aNameAtom, + int32_t aNameSpaceID, nsAtom* aTypeAtom) { CustomElementDefinition* data = mCustomDefinitions.GetWeak(aTypeAtom); @@ -373,7 +375,7 @@ CustomElementRegistry::LookupCustomElementDefinition(nsAtom* aNameAtom, } } - if (data && data->mLocalName == aNameAtom) { + if (data && data->mLocalName == aNameAtom && data->mNamespaceID == aNameSpaceID) { return data; } @@ -688,6 +690,24 @@ CustomElementRegistry::GetDocGroup() const return mWindow ? mWindow->GetDocGroup() : nullptr; } +int32_t +CustomElementRegistry::InferNamespace(JSContext* aCx, + JS::Handle constructor) +{ + JSObject* XULConstructor = XULElement_Binding::GetConstructorObject(aCx); + + JS::Rooted proto(aCx, constructor); + while (proto) { + if (proto == XULConstructor) { + return kNameSpaceID_XUL; + } + + JS_GetPrototype(aCx, proto, &proto); + } + + return kNameSpaceID_XHTML; +} + // https://html.spec.whatwg.org/multipage/scripting.html#element-definition void CustomElementRegistry::Define(JSContext* aCx, @@ -720,12 +740,13 @@ CustomElementRegistry::Define(JSContext* aCx, return; } + int32_t nameSpaceID = InferNamespace(aCx, constructor); + /** * 2. If name is not a valid custom element name, then throw a "SyntaxError" * DOMException and abort these steps. */ nsIDocument* doc = mWindow->GetExtantDoc(); - uint32_t nameSpaceID = doc ? doc->GetDefaultNamespaceID() : kNameSpaceID_XHTML; RefPtr nameAtom(NS_Atomize(aName)); if (!nsContentUtils::IsCustomElementName(nameAtom, nameSpaceID)) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); @@ -945,6 +966,7 @@ CustomElementRegistry::Define(JSContext* aCx, RefPtr definition = new CustomElementDefinition(nameAtom, localNameAtom, + nameSpaceID, &aFunctionConstructor, std::move(observedAttributes), std::move(callbacksHolder)); @@ -1471,11 +1493,13 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CustomElementDefinition, Release) CustomElementDefinition::CustomElementDefinition(nsAtom* aType, nsAtom* aLocalName, + int32_t aNamespaceID, Function* aConstructor, nsTArray>&& aObservedAttributes, UniquePtr&& aCallbacks) : mType(aType), mLocalName(aLocalName), + mNamespaceID(aNamespaceID), mConstructor(new CustomElementConstructor(aConstructor)), mObservedAttributes(std::move(aObservedAttributes)), mCallbacks(std::move(aCallbacks)) diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h index 8f28fa2ae920..2886ae5a63dd 100644 --- a/dom/base/CustomElementRegistry.h +++ b/dom/base/CustomElementRegistry.h @@ -157,6 +157,7 @@ struct CustomElementDefinition CustomElementDefinition(nsAtom* aType, nsAtom* aLocalName, + int32_t aNamespaceID, Function* aConstructor, nsTArray>&& aObservedAttributes, UniquePtr&& aCallbacks); @@ -168,6 +169,9 @@ struct CustomElementDefinition // The localname to (e.g.