Bug 1462703 - Set returned CustomElementDefinition again after script runner is set
This would help in the case where it is safe to run script in-place and
the CustomElementDefinition is available before the function exits.
This fixes the tests changed.
MozReview-Commit-ID: Ays91W94WZm
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -325,20 +325,21 @@ CustomElementRegistry::LookupCustomEleme
nsAtom* aTypeAtom)
{
CustomElementDefinition* data = mCustomDefinitions.GetWeak(aTypeAtom);
if (!data) {
RefPtr<CustomElementCreationCallback> callback;
mElementCreationCallbacks.Get(aTypeAtom, getter_AddRefs(callback));
if (callback) {
+ mElementCreationCallbacks.Remove(aTypeAtom);
RefPtr<Runnable> runnable =
new RunCustomElementCreationCallback(this, aTypeAtom, callback);
nsContentUtils::AddScriptRunner(runnable);
- mElementCreationCallbacks.Remove(aTypeAtom);
+ data = mCustomDefinitions.GetWeak(aTypeAtom);
}
}
if (data && data->mLocalName == aNameAtom) {
return data;
}
return nullptr;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -10058,17 +10058,17 @@ nsContentUtils::LookupCustomElementDefin
return nullptr;
}
nsPIDOMWindowInner* window = aDoc->GetInnerWindow();
if (!window) {
return nullptr;
}
- CustomElementRegistry* registry = window->CustomElements();
+ RefPtr<CustomElementRegistry> registry(window->CustomElements());
if (!registry) {
return nullptr;
}
return registry->LookupCustomElementDefinition(aNameAtom, aTypeAtom);
}
/* static */ void
--- a/dom/tests/mochitest/webcomponents/test_custom_element_set_element_creation_callback.html
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_set_element_creation_callback.html
@@ -26,18 +26,16 @@ function simpleTest() {
}
callbackCalled = true;
is(type, "x-html-obj-elem", "Type is passed to the callback.");
customElements.define("x-html-obj-elem", XObjElement);
});
ok(!callbackCalled, "Callback should not be called.");
let el = document.createElement("x-html-obj-elem");
ok(callbackCalled, "Callback should be called.");
- isnot(Object.getPrototypeOf(el), XObjElement.prototype, "Created element is not upgraded.");
- document.body.appendChild(el);
is(Object.getPrototypeOf(el), XObjElement.prototype, "Created element should have the prototype of the custom type.");
}
function multipleDefinitionTest() {
let callbackCalled = false;
class XObjElement1 extends HTMLElement {};
class XObjElement2 extends HTMLElement {};
let callback = (type) => {
@@ -49,18 +47,16 @@ function multipleDefinitionTest() {
customElements.define("x-html-obj-elem1", XObjElement1);
customElements.define("x-html-obj-elem2", XObjElement2);
};
registry.setElementCreationCallback("x-html-obj-elem1", callback);
registry.setElementCreationCallback("x-html-obj-elem2", callback);
ok(!callbackCalled, "Callback should not be called.");
let el1 = document.createElement("x-html-obj-elem1");
ok(callbackCalled, "Callback should be called.");
- isnot(Object.getPrototypeOf(el1), XObjElement1.prototype, "Created element is not upgraded.");
- document.body.appendChild(el1);
is(Object.getPrototypeOf(el1), XObjElement1.prototype, "Created element should have the prototype of the custom type.");
let el2 = document.createElement("x-html-obj-elem2");
is(Object.getPrototypeOf(el2), XObjElement2.prototype, "Created element should have the prototype of the custom type.");
}
function throwIfDefined() {
let callbackCalled = false;
class XObjElement3 extends HTMLElement {};
@@ -96,18 +92,16 @@ function simpleExtendedTest() {
}
callbackCalled = true;
customElements.define("x-extended-button", ExtendButton, { extends: "button" });
is(type, "x-extended-button", "Type is passed to the callback.");
});
ok(!callbackCalled, "Callback should not be called.");
let el = document.createElement("button", { is: "x-extended-button"});
ok(callbackCalled, "Callback should be called.");
- isnot(Object.getPrototypeOf(el), ExtendButton.prototype, "Created element is not upgraded.");
- document.body.appendChild(el);
is(Object.getPrototypeOf(el), ExtendButton.prototype, "Created element should have the prototype of the extended type.");
is(el.getAttribute("is"), "x-extended-button", "The |is| attribute of the created element should be the extended type.");
}
function simpleInnerHTMLTest() {
let callbackCalled = false;
class XObjElement4 extends HTMLElement {};
registry.setElementCreationCallback("x-html-obj-elem5", (type) => {
--- a/dom/tests/mochitest/webcomponents/test_xul_custom_element.xul
+++ b/dom/tests/mochitest/webcomponents/test_xul_custom_element.xul
@@ -307,16 +307,25 @@
document.createElementNS(XUL_NS, "test-built-in-element-1")];
for (let element of elements) {
is(Object.getPrototypeOf(element), XULElement.prototype,
`<${element.localName} is="${element.getAttribute("is")}" /> should not be a custom element.`);
}
}
+ function setElementCreationCallbackCreate() {
+ class TestCustomElement4 extends XULElement {}
+ customElements.setElementCreationCallback(
+ "test-custom-element-4", () => customElements.define("test-custom-element-4", TestCustomElement4));
+
+ let element = document.createElementNS(XUL_NS, "test-custom-element-4");
+ ok(element instanceof TestCustomElement4, "Should be an instance of TestCustomElement4");
+ }
+
function runTest() {
basicCustomElementCreate();
parserBasicElementUpgrade();
tagNameWithoutDash();
upgradeAfterDefine();
basicElementCreateBuiltIn();
@@ -327,16 +336,18 @@
upgradeAfterDefineBuiltIn();
throwForInvalidBuiltInName();
extendingWithoutDashCustomElement();
nonCustomElementCreate();
+ setElementCreationCallbackCreate();
+
SimpleTest.finish();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none">