forked from mirrors/gecko-dev
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
This commit is contained in:
parent
2022970c76
commit
fd8d6b1590
9 changed files with 359 additions and 9 deletions
|
|
@ -10,6 +10,7 @@
|
||||||
#include "mozilla/CycleCollectedJSContext.h"
|
#include "mozilla/CycleCollectedJSContext.h"
|
||||||
#include "mozilla/dom/CustomElementRegistryBinding.h"
|
#include "mozilla/dom/CustomElementRegistryBinding.h"
|
||||||
#include "mozilla/dom/HTMLElementBinding.h"
|
#include "mozilla/dom/HTMLElementBinding.h"
|
||||||
|
#include "mozilla/dom/XULElementBinding.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/WebComponentsBinding.h"
|
#include "mozilla/dom/WebComponentsBinding.h"
|
||||||
#include "mozilla/dom/DocGroup.h"
|
#include "mozilla/dom/DocGroup.h"
|
||||||
|
|
@ -356,6 +357,7 @@ CustomElementRegistry::RunCustomElementCreationCallback::Run()
|
||||||
|
|
||||||
CustomElementDefinition*
|
CustomElementDefinition*
|
||||||
CustomElementRegistry::LookupCustomElementDefinition(nsAtom* aNameAtom,
|
CustomElementRegistry::LookupCustomElementDefinition(nsAtom* aNameAtom,
|
||||||
|
int32_t aNameSpaceID,
|
||||||
nsAtom* aTypeAtom)
|
nsAtom* aTypeAtom)
|
||||||
{
|
{
|
||||||
CustomElementDefinition* data = mCustomDefinitions.GetWeak(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;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -688,6 +690,24 @@ CustomElementRegistry::GetDocGroup() const
|
||||||
return mWindow ? mWindow->GetDocGroup() : nullptr;
|
return mWindow ? mWindow->GetDocGroup() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
CustomElementRegistry::InferNamespace(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> constructor)
|
||||||
|
{
|
||||||
|
JSObject* XULConstructor = XULElement_Binding::GetConstructorObject(aCx);
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> 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
|
// https://html.spec.whatwg.org/multipage/scripting.html#element-definition
|
||||||
void
|
void
|
||||||
CustomElementRegistry::Define(JSContext* aCx,
|
CustomElementRegistry::Define(JSContext* aCx,
|
||||||
|
|
@ -720,12 +740,13 @@ CustomElementRegistry::Define(JSContext* aCx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t nameSpaceID = InferNamespace(aCx, constructor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2. If name is not a valid custom element name, then throw a "SyntaxError"
|
* 2. If name is not a valid custom element name, then throw a "SyntaxError"
|
||||||
* DOMException and abort these steps.
|
* DOMException and abort these steps.
|
||||||
*/
|
*/
|
||||||
nsIDocument* doc = mWindow->GetExtantDoc();
|
nsIDocument* doc = mWindow->GetExtantDoc();
|
||||||
uint32_t nameSpaceID = doc ? doc->GetDefaultNamespaceID() : kNameSpaceID_XHTML;
|
|
||||||
RefPtr<nsAtom> nameAtom(NS_Atomize(aName));
|
RefPtr<nsAtom> nameAtom(NS_Atomize(aName));
|
||||||
if (!nsContentUtils::IsCustomElementName(nameAtom, nameSpaceID)) {
|
if (!nsContentUtils::IsCustomElementName(nameAtom, nameSpaceID)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||||
|
|
@ -945,6 +966,7 @@ CustomElementRegistry::Define(JSContext* aCx,
|
||||||
RefPtr<CustomElementDefinition> definition =
|
RefPtr<CustomElementDefinition> definition =
|
||||||
new CustomElementDefinition(nameAtom,
|
new CustomElementDefinition(nameAtom,
|
||||||
localNameAtom,
|
localNameAtom,
|
||||||
|
nameSpaceID,
|
||||||
&aFunctionConstructor,
|
&aFunctionConstructor,
|
||||||
std::move(observedAttributes),
|
std::move(observedAttributes),
|
||||||
std::move(callbacksHolder));
|
std::move(callbacksHolder));
|
||||||
|
|
@ -1471,11 +1493,13 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CustomElementDefinition, Release)
|
||||||
|
|
||||||
CustomElementDefinition::CustomElementDefinition(nsAtom* aType,
|
CustomElementDefinition::CustomElementDefinition(nsAtom* aType,
|
||||||
nsAtom* aLocalName,
|
nsAtom* aLocalName,
|
||||||
|
int32_t aNamespaceID,
|
||||||
Function* aConstructor,
|
Function* aConstructor,
|
||||||
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
||||||
UniquePtr<LifecycleCallbacks>&& aCallbacks)
|
UniquePtr<LifecycleCallbacks>&& aCallbacks)
|
||||||
: mType(aType),
|
: mType(aType),
|
||||||
mLocalName(aLocalName),
|
mLocalName(aLocalName),
|
||||||
|
mNamespaceID(aNamespaceID),
|
||||||
mConstructor(new CustomElementConstructor(aConstructor)),
|
mConstructor(new CustomElementConstructor(aConstructor)),
|
||||||
mObservedAttributes(std::move(aObservedAttributes)),
|
mObservedAttributes(std::move(aObservedAttributes)),
|
||||||
mCallbacks(std::move(aCallbacks))
|
mCallbacks(std::move(aCallbacks))
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,7 @@ struct CustomElementDefinition
|
||||||
|
|
||||||
CustomElementDefinition(nsAtom* aType,
|
CustomElementDefinition(nsAtom* aType,
|
||||||
nsAtom* aLocalName,
|
nsAtom* aLocalName,
|
||||||
|
int32_t aNamespaceID,
|
||||||
Function* aConstructor,
|
Function* aConstructor,
|
||||||
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
|
||||||
UniquePtr<LifecycleCallbacks>&& aCallbacks);
|
UniquePtr<LifecycleCallbacks>&& aCallbacks);
|
||||||
|
|
@ -168,6 +169,9 @@ struct CustomElementDefinition
|
||||||
// The localname to (e.g. <button is=type> -- this would be button).
|
// The localname to (e.g. <button is=type> -- this would be button).
|
||||||
RefPtr<nsAtom> mLocalName;
|
RefPtr<nsAtom> mLocalName;
|
||||||
|
|
||||||
|
// The namespace for this custom element
|
||||||
|
int32_t mNamespaceID;
|
||||||
|
|
||||||
// The custom element constructor.
|
// The custom element constructor.
|
||||||
RefPtr<CustomElementConstructor> mConstructor;
|
RefPtr<CustomElementConstructor> mConstructor;
|
||||||
|
|
||||||
|
|
@ -399,7 +403,7 @@ public:
|
||||||
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
|
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
|
||||||
*/
|
*/
|
||||||
CustomElementDefinition* LookupCustomElementDefinition(
|
CustomElementDefinition* LookupCustomElementDefinition(
|
||||||
nsAtom* aNameAtom, nsAtom* aTypeAtom);
|
nsAtom* aNameAtom, int32_t aNameSpaceID, nsAtom* aTypeAtom);
|
||||||
|
|
||||||
CustomElementDefinition* LookupCustomElementDefinition(
|
CustomElementDefinition* LookupCustomElementDefinition(
|
||||||
JSContext* aCx, JSObject *aConstructor) const;
|
JSContext* aCx, JSObject *aConstructor) const;
|
||||||
|
|
@ -555,6 +559,8 @@ private:
|
||||||
CustomElementRegistry* mRegistry;
|
CustomElementRegistry* mRegistry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int32_t InferNamespace(JSContext* aCx, JS::Handle<JSObject*> constructor);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nsISupports* GetParentObject() const;
|
nsISupports* GetParentObject() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10002,6 +10002,15 @@ nsContentUtils::NewXULOrHTMLElement(Element** aResult, mozilla::dom::NodeInfo* a
|
||||||
nsIGlobalObject* global;
|
nsIGlobalObject* global;
|
||||||
if (aFromParser == dom::NOT_FROM_PARSER) {
|
if (aFromParser == dom::NOT_FROM_PARSER) {
|
||||||
global = GetEntryGlobal();
|
global = GetEntryGlobal();
|
||||||
|
|
||||||
|
// XUL documents always use NOT_FROM_PARSER for non-XUL elements. We can
|
||||||
|
// get the global from the document in that case.
|
||||||
|
if (!global) {
|
||||||
|
nsIDocument* doc = nodeInfo->GetDocument();
|
||||||
|
if (doc && doc->IsXULDocument()) {
|
||||||
|
global = doc->GetScopeObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
global = nodeInfo->GetDocument()->GetScopeObject();
|
global = nodeInfo->GetDocument()->GetScopeObject();
|
||||||
}
|
}
|
||||||
|
|
@ -10122,7 +10131,7 @@ nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return registry->LookupCustomElementDefinition(aNameAtom, aTypeAtom);
|
return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID, aTypeAtom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
|
|
|
||||||
|
|
@ -3811,10 +3811,7 @@ HTMLConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp,
|
||||||
// determination of what sort of element we're planning to construct.
|
// determination of what sort of element we're planning to construct.
|
||||||
// Technically, this should happen (implicitly) in step 8, but this
|
// Technically, this should happen (implicitly) in step 8, but this
|
||||||
// determination is side-effect-free, so it's OK.
|
// determination is side-effect-free, so it's OK.
|
||||||
int32_t ns = doc->GetDefaultNamespaceID();
|
int32_t ns = definition->mNamespaceID;
|
||||||
if (ns != kNameSpaceID_XUL) {
|
|
||||||
ns = kNameSpaceID_XHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructorGetterCallback cb = nullptr;
|
constructorGetterCallback cb = nullptr;
|
||||||
if (ns == kNameSpaceID_XUL) {
|
if (ns == kNameSpaceID_XUL) {
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,6 @@ prefs =
|
||||||
dom.webcomponents.customelements.enabled=false
|
dom.webcomponents.customelements.enabled=false
|
||||||
|
|
||||||
[test_xul_custom_element.xul]
|
[test_xul_custom_element.xul]
|
||||||
|
[test_custom_element_namespace.html]
|
||||||
|
[test_custom_element_namespace.xhtml]
|
||||||
|
[test_custom_element_namespace.xul]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Custom Elements in an HTML document</title>
|
||||||
|
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||||
|
<script>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
|
||||||
|
class TestXULCustomElement extends XULElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
get connected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("test-xul-element", TestXULCustomElement);
|
||||||
|
|
||||||
|
class TestHTMLCustomElement extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
get connected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("test-html-element", TestHTMLCustomElement);
|
||||||
|
|
||||||
|
function checkElement(element, ns, connected, type) {
|
||||||
|
is(element.namespaceURI, ns, `${type} should have the correct namespace`);
|
||||||
|
if (connected) {
|
||||||
|
ok(element.connected, `${type} should have applied the class`);
|
||||||
|
} else {
|
||||||
|
is(element.connected, undefined, `${type} should not have applied the class`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
let element = new TestXULCustomElement();
|
||||||
|
checkElement(element, XUL_NS, true, "instantiated XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("xul2");
|
||||||
|
checkElement(element, HTML_NS, false, "parsed XUL as HTML");
|
||||||
|
|
||||||
|
element = document.createElement("test-xul-element");
|
||||||
|
checkElement(element, HTML_NS, false, "document.createElement(XUL)");
|
||||||
|
|
||||||
|
element = document.createXULElement("test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createXULElement(XUL)");
|
||||||
|
|
||||||
|
element = document.createElementNS(XUL_NS, "test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createElementNS(XUL, XUL)");
|
||||||
|
|
||||||
|
element = document.createElementNS(HTML_NS, "test-xul-element");
|
||||||
|
checkElement(element, HTML_NS, false, "document.createElementNS(HTML, XUL)");
|
||||||
|
|
||||||
|
element = new TestHTMLCustomElement();
|
||||||
|
checkElement(element, HTML_NS, true, "instantiated HTML");
|
||||||
|
|
||||||
|
element = document.getElementById("html2");
|
||||||
|
checkElement(element, HTML_NS, true, "parsed HTML as HTML");
|
||||||
|
|
||||||
|
element = document.createElement("test-html-element");
|
||||||
|
checkElement(element, HTML_NS, true, "document.createElement(HTML)");
|
||||||
|
|
||||||
|
element = document.createXULElement("test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createXULElement(HTML)");
|
||||||
|
|
||||||
|
element = document.createElementNS(XUL_NS, "test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createElementNS(XUL, HTML)");
|
||||||
|
|
||||||
|
element = document.createElementNS(HTML_NS, "test-html-element");
|
||||||
|
checkElement(element, HTML_NS, true, "document.createElementNS(HTML, HTML)");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="runTest();">
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
<test-xul-element id="xul2"/>
|
||||||
|
<test-html-element id="html2"/>
|
||||||
|
</div>
|
||||||
|
<pre id="test"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Custom Elements in an XHTML document</title>
|
||||||
|
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||||
|
<script>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
|
||||||
|
class TestXULCustomElement extends XULElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
get connected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("test-xul-element", TestXULCustomElement);
|
||||||
|
|
||||||
|
class TestHTMLCustomElement extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
get connected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("test-html-element", TestHTMLCustomElement);
|
||||||
|
|
||||||
|
function checkElement(element, ns, connected, type) {
|
||||||
|
is(element.namespaceURI, ns, `${type} should have the correct namespace`);
|
||||||
|
if (connected) {
|
||||||
|
ok(element.connected, `${type} should have applied the class`);
|
||||||
|
} else {
|
||||||
|
is(element.connected, undefined, `${type} should not have applied the class`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
let element = new TestXULCustomElement();
|
||||||
|
checkElement(element, XUL_NS, true, "instantiated XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("xul1");
|
||||||
|
checkElement(element, XUL_NS, true, "parsed XUL as XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("xul2");
|
||||||
|
checkElement(element, HTML_NS, false, "parsed XUL as HTML");
|
||||||
|
|
||||||
|
element = document.createElement("test-xul-element");
|
||||||
|
checkElement(element, HTML_NS, false, "document.createElement(XUL)");
|
||||||
|
|
||||||
|
element = document.createXULElement("test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createXULElement(XUL)");
|
||||||
|
|
||||||
|
element = document.createElementNS(XUL_NS, "test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createElementNS(XUL, XUL)");
|
||||||
|
|
||||||
|
element = document.createElementNS(HTML_NS, "test-xul-element");
|
||||||
|
checkElement(element, HTML_NS, false, "document.createElementNS(HTML, XUL)");
|
||||||
|
|
||||||
|
element = new TestHTMLCustomElement();
|
||||||
|
checkElement(element, HTML_NS, true, "instantiated HTML");
|
||||||
|
|
||||||
|
element = document.getElementById("html1");
|
||||||
|
checkElement(element, XUL_NS, false, "parsed HTML as XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("html2");
|
||||||
|
checkElement(element, HTML_NS, true, "parsed HTML as HTML");
|
||||||
|
|
||||||
|
element = document.createElement("test-html-element");
|
||||||
|
checkElement(element, HTML_NS, true, "document.createElement(HTML)");
|
||||||
|
|
||||||
|
element = document.createXULElement("test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createXULElement(HTML)");
|
||||||
|
|
||||||
|
element = document.createElementNS(XUL_NS, "test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createElementNS(XUL, HTML)");
|
||||||
|
|
||||||
|
element = document.createElementNS(HTML_NS, "test-html-element");
|
||||||
|
checkElement(element, HTML_NS, true, "document.createElementNS(HTML, HTML)");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="runTest();">
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content">
|
||||||
|
<test-xul-element xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="xul1"/>
|
||||||
|
<test-html-element xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="html1"/>
|
||||||
|
<test-xul-element id="xul2"/>
|
||||||
|
<test-html-element id="html2"/>
|
||||||
|
</div>
|
||||||
|
<pre id="test"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||||
|
|
||||||
|
<window title="XUL Custom Elements"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
onload="runTest();">
|
||||||
|
<title>Custom Elements in a XUL document</title>
|
||||||
|
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||||
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
|
||||||
|
class TestXULCustomElement extends XULElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
get connected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("test-xul-element", TestXULCustomElement);
|
||||||
|
|
||||||
|
class TestHTMLCustomElement extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
get connected() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("test-html-element", TestHTMLCustomElement);
|
||||||
|
|
||||||
|
function checkElement(element, ns, connected, type) {
|
||||||
|
is(element.namespaceURI, ns, `${type} should have the correct namespace`);
|
||||||
|
if (connected) {
|
||||||
|
ok(element.connected, `${type} should have applied the class`);
|
||||||
|
} else {
|
||||||
|
is(element.connected, undefined, `${type} should not have applied the class`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
let element = new TestXULCustomElement();
|
||||||
|
checkElement(element, XUL_NS, true, "instantiated XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("xul1");
|
||||||
|
checkElement(element, XUL_NS, true, "parsed XUL as XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("xul2");
|
||||||
|
checkElement(element, HTML_NS, false, "parsed XUL as HTML");
|
||||||
|
|
||||||
|
element = document.createElement("test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createElement(XUL)");
|
||||||
|
|
||||||
|
element = document.createXULElement("test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createXULElement(XUL)");
|
||||||
|
|
||||||
|
element = document.createElementNS(XUL_NS, "test-xul-element");
|
||||||
|
checkElement(element, XUL_NS, true, "document.createElementNS(XUL, XUL)");
|
||||||
|
|
||||||
|
element = document.createElementNS(HTML_NS, "test-xul-element");
|
||||||
|
checkElement(element, HTML_NS, false, "document.createElementNS(HTML, XUL)");
|
||||||
|
|
||||||
|
element = new TestHTMLCustomElement();
|
||||||
|
checkElement(element, HTML_NS, true, "instantiated HTML");
|
||||||
|
|
||||||
|
element = document.getElementById("html1");
|
||||||
|
checkElement(element, XUL_NS, false, "parsed HTML as XUL");
|
||||||
|
|
||||||
|
element = document.getElementById("html2");
|
||||||
|
checkElement(element, HTML_NS, true, "parsed HTML as HTML");
|
||||||
|
|
||||||
|
element = document.createElement("test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createElement(HTML)");
|
||||||
|
|
||||||
|
element = document.createXULElement("test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createXULElement(HTML)");
|
||||||
|
|
||||||
|
element = document.createElementNS(XUL_NS, "test-html-element");
|
||||||
|
checkElement(element, XUL_NS, false, "document.createElementNS(XUL, HTML)");
|
||||||
|
|
||||||
|
element = document.createElementNS(HTML_NS, "test-html-element");
|
||||||
|
checkElement(element, HTML_NS, true, "document.createElementNS(HTML, HTML)");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<test-xul-element id="xul1"/>
|
||||||
|
<test-html-element id="html1"/>
|
||||||
|
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
<test-xul-element id="xul2"/>
|
||||||
|
<test-html-element id="html2"/>
|
||||||
|
</div>
|
||||||
|
<pre id="test"></pre>
|
||||||
|
</body>
|
||||||
|
</window>
|
||||||
|
|
@ -382,7 +382,7 @@ nsHtml5TreeOperation::CreateHTMLElement(
|
||||||
dom::CustomElementDefinition* definition = nullptr;
|
dom::CustomElementDefinition* definition = nullptr;
|
||||||
|
|
||||||
// Avoid overhead by checking if custom elements pref is enabled or not.
|
// Avoid overhead by checking if custom elements pref is enabled or not.
|
||||||
if (nsContentUtils::IsCustomElementsEnabled()) {
|
if (dom::CustomElementRegistry::IsCustomElementEnabled(document)) {
|
||||||
if (aAttributes) {
|
if (aAttributes) {
|
||||||
nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS);
|
nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS);
|
||||||
if (is) {
|
if (is) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue