Bug 1396620 - Part 1: Remove created callback for custom elements; r=jdai,smaug

MozReview-Commit-ID: IDovq3OZwgy

--HG--
extra : rebase_source : bae891833d4f8139fed2ed31af85173694c7eb11
This commit is contained in:
Edgar Chen 2017-10-13 23:36:54 +08:00
Родитель c351c5f556
Коммит 698fdbc62e
17 изменённых файлов: 26 добавлений и 321 удалений

Просмотреть файл

@ -23,38 +23,6 @@ CustomElementCallback::Call()
{
IgnoredErrorResult rv;
switch (mType) {
case nsIDocument::eCreated:
{
// For the duration of this callback invocation, the element is being created
// flag must be set to true.
mOwnerData->mElementIsBeingCreated = true;
// The callback hasn't actually been invoked yet, but we need to flip
// this now in order to enqueue the connected callback. This is a spec
// bug (w3c bug 27437).
mOwnerData->mCreatedCallbackInvoked = true;
// If ELEMENT is connected, enqueue connected callback for ELEMENT.
nsIDocument* document = mThisObject->GetComposedDoc();
if (document) {
NodeInfo* ni = mThisObject->NodeInfo();
// We need to do this because at this point, CustomElementDefinition is
// not set to CustomElementData yet, so EnqueueLifecycleCallback will
// fail to find the CE definition for this custom element.
// This will go away eventually since there is no created callback in v1.
CustomElementDefinition* definition =
nsContentUtils::LookupCustomElementDefinition(document,
ni->LocalName(), ni->NamespaceID(),
mOwnerData->GetCustomElementType());
nsContentUtils::EnqueueLifecycleCallback(
nsIDocument::eConnected, mThisObject, nullptr, nullptr, definition);
}
static_cast<LifecycleCreatedCallback *>(mCallback.get())->Call(mThisObject, rv);
mOwnerData->mElementIsBeingCreated = false;
break;
}
case nsIDocument::eConnected:
static_cast<LifecycleConnectedCallback *>(mCallback.get())->Call(mThisObject, rv);
break;
@ -84,12 +52,10 @@ CustomElementCallback::Traverse(nsCycleCollectionTraversalCallback& aCb) const
CustomElementCallback::CustomElementCallback(Element* aThisObject,
nsIDocument::ElementCallbackType aCallbackType,
mozilla::dom::CallbackFunction* aCallback,
CustomElementData* aOwnerData)
mozilla::dom::CallbackFunction* aCallback)
: mThisObject(aThisObject),
mCallback(aCallback),
mType(aCallbackType),
mOwnerData(aOwnerData)
mType(aCallbackType)
{
}
//-----------------------------------------------------
@ -130,9 +96,7 @@ CustomElementData::CustomElementData(nsAtom* aType)
}
CustomElementData::CustomElementData(nsAtom* aType, State aState)
: mElementIsBeingCreated(false)
, mCreatedCallbackInvoked(true)
, mState(aState)
: mState(aState)
, mType(aType)
{
}
@ -350,19 +314,12 @@ CustomElementRegistry::CreateCustomElementCallback(
CustomElementDefinition* aDefinition)
{
MOZ_ASSERT(aDefinition, "CustomElementDefinition should not be null");
RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData();
MOZ_ASSERT(elementData, "CustomElementData should exist");
MOZ_ASSERT(aCustomElement->GetCustomElementData(),
"CustomElementData should exist");
// Let CALLBACK be the callback associated with the key NAME in CALLBACKS.
CallbackFunction* func = nullptr;
switch (aType) {
case nsIDocument::eCreated:
if (aDefinition->mCallbacks->mCreatedCallback.WasPassed()) {
func = aDefinition->mCallbacks->mCreatedCallback.Value();
}
break;
case nsIDocument::eConnected:
if (aDefinition->mCallbacks->mConnectedCallback.WasPassed()) {
func = aDefinition->mCallbacks->mConnectedCallback.Value();
@ -393,17 +350,9 @@ CustomElementRegistry::CreateCustomElementCallback(
return nullptr;
}
if (aType == nsIDocument::eCreated) {
elementData->mCreatedCallbackInvoked = false;
} else if (!elementData->mCreatedCallbackInvoked) {
// Callbacks other than created callback must not be enqueued
// until after the created callback has been invoked.
return nullptr;
}
// Add CALLBACK to ELEMENT's callback queue.
auto callback =
MakeUnique<CustomElementCallback>(aCustomElement, aType, func, elementData);
MakeUnique<CustomElementCallback>(aCustomElement, aType, func);
if (aArgs) {
callback->SetArgs(*aArgs);
@ -415,26 +364,6 @@ CustomElementRegistry::CreateCustomElementCallback(
return Move(callback);
}
void
CustomElementRegistry::SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
CustomElementDefinition* aDefinition)
{
auto callback = CreateCustomElementCallback(aType, aCustomElement, nullptr,
nullptr, aDefinition);
if (!callback) {
return;
}
UniquePtr<CustomElementReaction> reaction(Move(
MakeUnique<CustomElementCallbackReaction>(Move(callback))));
RefPtr<SyncInvokeReactionRunnable> runnable =
new SyncInvokeReactionRunnable(Move(reaction), aCustomElement);
nsContentUtils::AddScriptRunner(runnable);
}
/* static */ void
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
@ -532,9 +461,7 @@ static const char* kLifeCycleCallbackNames[] = {
"connectedCallback",
"disconnectedCallback",
"adoptedCallback",
"attributeChangedCallback",
// The life cycle callbacks from v0 spec.
"createdCallback"
"attributeChangedCallback"
};
static void
@ -1007,11 +934,6 @@ CustomElementRegistry::Upgrade(Element* aElement,
// Step 9.
aElement->SetCustomElementDefinition(aDefinition);
// This is for old spec.
nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eCreated,
aElement, nullptr,
nullptr, aDefinition);
}
//-----------------------------------------------------
@ -1183,11 +1105,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition)
cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
}
if (callbacks->mCreatedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mCreatedCallback");
cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
}
if (callbacks->mConnectedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mConnectedCallback");
cb.NoteXPCOMChild(callbacks->mConnectedCallback.Value());

Просмотреть файл

@ -51,8 +51,7 @@ class CustomElementCallback
public:
CustomElementCallback(Element* aThisObject,
nsIDocument::ElementCallbackType aCallbackType,
CallbackFunction* aCallback,
CustomElementData* aOwnerData);
CallbackFunction* aCallback);
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
void Call();
void SetArgs(LifecycleCallbackArgs& aArgs)
@ -79,9 +78,6 @@ private:
// used by the attribute changed callback.
LifecycleCallbackArgs mArgs;
LifecycleAdoptedCallbackArgs mAdoptedCallbackArgs;
// CustomElementData that contains this callback in the
// callback queue.
CustomElementData* mOwnerData;
};
class CustomElementConstructor final : public CallbackFunction
@ -115,11 +111,6 @@ struct CustomElementData
explicit CustomElementData(nsAtom* aType);
CustomElementData(nsAtom* aType, State aState);
// Element is being created flag as described in the custom elements spec.
bool mElementIsBeingCreated;
// Flag to determine if the created callback has been invoked, thus it
// determines if other callbacks can be enqueued.
bool mCreatedCallbackInvoked;
// Custom element state as described in the custom element spec.
State mState;
// custom element reaction queue as described in the custom element spec.
@ -385,10 +376,6 @@ public:
void GetCustomPrototype(nsAtom* aAtom,
JS::MutableHandle<JSObject*> aPrototype);
void SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
CustomElementDefinition* aDefinition);
/**
* Upgrade an element.
* https://html.spec.whatwg.org/multipage/scripting.html#upgrades
@ -477,31 +464,6 @@ private:
CustomElementRegistry* mRegistry;
};
class SyncInvokeReactionRunnable : public mozilla::Runnable {
public:
SyncInvokeReactionRunnable(
UniquePtr<CustomElementReaction> aReaction, Element* aCustomElement)
: Runnable(
"dom::CustomElementRegistry::SyncInvokeReactionRunnable")
, mReaction(Move(aReaction))
, mCustomElement(aCustomElement)
{
}
NS_IMETHOD Run() override
{
// It'll never throw exceptions, because all the exceptions are handled
// by Lifecycle*Callback::Call function.
ErrorResult rv;
mReaction->Invoke(mCustomElement, rv);
return NS_OK;
}
private:
UniquePtr<CustomElementReaction> mReaction;
Element* mCustomElement;
};
public:
nsISupports* GetParentObject() const;

Просмотреть файл

@ -10224,27 +10224,6 @@ nsContentUtils::GetElementDefinitionIfObservingAttr(Element* aCustomElement,
return definition;
}
/* static */ void
nsContentUtils::SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
Element* aElement,
CustomElementDefinition* aDefinition)
{
MOZ_ASSERT(aElement);
nsIDocument* doc = aElement->OwnerDoc();
nsPIDOMWindowInner* window(doc->GetInnerWindow());
if (!window) {
return;
}
RefPtr<CustomElementRegistry> registry(window->CustomElements());
if (!registry) {
return;
}
registry->SyncInvokeReactions(aType, aElement, aDefinition);
}
/* static */ void
nsContentUtils::EnqueueUpgradeReaction(Element* aElement,
CustomElementDefinition* aDefinition)

Просмотреть файл

@ -3053,10 +3053,6 @@ public:
nsAtom* aExtensionType,
nsAtom* aAttrName);
static void SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
Element* aCustomElement,
mozilla::dom::CustomElementDefinition* aDefinition);
static void EnqueueUpgradeReaction(Element* aElement,
mozilla::dom::CustomElementDefinition* aDefinition);

Просмотреть файл

@ -6448,9 +6448,6 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
element->SetCustomElementDefinition(definition);
// It'll be removed when we deprecate custom elements v0.
nsContentUtils::SyncInvokeReactions(nsIDocument::eCreated, element,
definition);
NS_ENSURE_TRUE(element, false);
}

Просмотреть файл

@ -2851,7 +2851,6 @@ public:
}
enum ElementCallbackType {
eCreated,
eConnected,
eDisconnected,
eAdopted,

Просмотреть файл

@ -1,8 +1,8 @@
var proto = Object.create(HTMLElement.prototype);
proto.magicNumber = 42;
proto.createdCallback = function() {
proto.connectedCallback = function() {
finishTest(this.magicNumber === 42);
};
document.registerElement("x-foo", { prototype: proto });
document.createElement("x-foo");
document.firstChild.appendChild(document.createElement("x-foo"));

Просмотреть файл

@ -21,19 +21,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
<script type="application/javascript"><![CDATA[
/** Test for Bug 1130028 **/
SimpleTest.waitForExplicitFinish();
var connectedCallbackCount = 0;
var createdCallbackCount = 0;
// Callback should be called once by element created in chrome,
// and once by element created in content.
function createdCallbackCalled() {
createdCallbackCount++;
ok(true, "Created callback called, should be called twice in test.");
// Callback should be called only once by element created in content.
function connectedCallbackCalled() {
connectedCallbackCount++;
is(connectedCallbackCount, 1, "Connected callback called, should be called once in test.");
is(this.magicNumber, 42, "Callback should be able to see the custom prototype.");
if (createdCallbackCount == 2) {
SimpleTest.finish();
}
}
function startTests() {
@ -45,10 +39,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
var proto = Object.create(frame.contentWindow.HTMLElement.prototype);
proto.magicNumber = 42;
proto.createdCallback = createdCallbackCalled;
frame.contentDocument.registerElement("x-bar", { prototype: proto });
proto.connectedCallback = connectedCallbackCalled;
frame.contentDocument.createElement("x-bar");
frame.contentDocument.registerElement("x-bar", { prototype: proto });
is(connectedCallbackCount, 1, "Connected callback should be called by element created in content.");
var element = frame.contentDocument.createElement("x-bar");
is(element.magicNumber, 42, "Should be able to see the custom prototype on created element.");
}
]]></script>

Просмотреть файл

@ -26,8 +26,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
SimpleTest.waitForExplicitFinish();
function finishTest(canSeePrototype) {
ok(true, "createdCallback called when reigsterElement was called with an extended principal.");
ok(canSeePrototype, "createdCallback should be able to see custom prototype.");
ok(true, "connectedCallback called when reigsterElement was called with an extended principal.");
ok(canSeePrototype, "connectedCallback should be able to see custom prototype.");
SimpleTest.finish();
}

Просмотреть файл

@ -8,16 +8,13 @@ support-files =
[test_bug1176757.html]
[test_bug1276240.html]
[test_content_element.html]
[test_custom_element_adopt_callbacks.html]
[test_custom_element_callback_innerhtml.html]
skip-if = true # disabled - See bug 1390396
[test_custom_element_clone_callbacks_extended.html]
[test_custom_element_htmlconstructor.html]
skip-if = os == 'android' # bug 1323645
support-files =
htmlconstructor_autonomous_tests.js
htmlconstructor_builtin_tests.js
[test_custom_element_import_node_created_callback.html]
[test_custom_element_in_shadow.html]
skip-if = true # disabled - See bug 1390396
[test_custom_element_register_invalid_callbacks.html]

Просмотреть файл

@ -1,29 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1081039
-->
<head>
<title>Test callbacks for adopted custom elements.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<template id="template"><x-foo></x-foo></template>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081039">Bug 1081039</a>
<script>
var p = Object.create(HTMLElement.prototype);
p.createdCallback = function() {
ok(false, "Created callback should not be called for adopted node.");
};
document.registerElement("x-foo", { prototype: p });
var template = document.getElementById("template");
var adoptedFoo = document.adoptNode(template.content.firstChild);
is(adoptedFoo.nodeName, "X-FOO");
</script>
</body>
</html>

Просмотреть файл

@ -1,40 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1081039
-->
<head>
<title>Test callbacks for cloned extended custom elements.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081039">Bug 1081039</a>
<script>
SimpleTest.waitForExplicitFinish();
// Test to make sure created callback is called on clones created after
// registering the custom element.
var count = 0;
var p = Object.create(HTMLButtonElement.prototype);
p.createdCallback = function() { // should be called by createElement and cloneNode
is(this.__proto__, p, "Correct prototype should be set on custom elements.");
if (++count == 2) {
SimpleTest.finish();
}
};
document.registerElement("x-foo", { prototype: p, extends: "button" });
var foo = document.createElement("button", {is: "x-foo"});
is(foo.getAttribute("is"), "x-foo");
var fooClone = foo.cloneNode(true);
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

Просмотреть файл

@ -1,34 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1093680
-->
<head>
<title>Test created callback order for imported custom element.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<template id="template"><x-foo><span></span></x-foo></template>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1093680">Bug 1093680</a>
<script>
var fooProtoCreatedCallbackCalled = false;
var fooProto = Object.create(HTMLElement.prototype);
fooProto.createdCallback = function() {
ok(this.firstElementChild, "When the created callback is called, the element should already have a child because the callback should only be called after cloning all the contents.");
fooProtoCreatedCallbackCalled = true;
};
document.registerElement("x-foo", { prototype: fooProto });
var template = document.getElementById("template");
// Importing node will implicityly clone the conent in the main document.
var adoptedFoo = document.importNode(template.content, true);
ok(fooProtoCreatedCallbackCalled, "Created callback should be called after importing custom element into document");
</script>
</body>
</html>

Просмотреть файл

@ -19,7 +19,6 @@ const testWindow = iframe.contentDocument.defaultView;
// This is for backward compatibility.
// We should do the same checks for the callbacks from v0 spec.
[
'createdCallback',
'attributeChangedCallback',
].forEach(callback => {
var c = class {};

Просмотреть файл

@ -14,37 +14,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=783129
<script>
var container = document.getElementById("container");
function createdCallbackFromMainDoc() {
var createdCallbackCalled = false;
var assocDoc = document.implementation.createHTMLDocument();
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
is(createdCallbackCalled, false, "created callback should only be called once in this tests.");
createdCallbackCalled = true;
runNextTest();
};
assocDoc.registerElement("x-associated-doc-callback-elem", { prototype: proto });
document.createElement("x-associated-doc-callback-elem");
}
function createdCallbackFromDocHTMLNamespace() {
var createdCallbackCalled = false;
var assocDoc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
var somediv = assocDoc.createElement("div");
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
is(createdCallbackCalled, false, "created callback should only be called once in this tests.");
createdCallbackCalled = true;
runNextTest();
};
assocDoc.registerElement("x-assoc-doc-with-ns-callback-elem", { prototype: proto });
document.createElement("x-assoc-doc-with-ns-callback-elem");
}
function registerNoRegistryDoc() {
var assocDoc = document.implementation.createDocument(null, "html");
try {
@ -65,8 +34,6 @@ function runNextTest() {
}
var testFunctions = [
createdCallbackFromMainDoc,
createdCallbackFromDocHTMLNamespace,
registerNoRegistryDoc,
SimpleTest.finish
];

Просмотреть файл

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
callback LifecycleCreatedCallback = void();
callback LifecycleConnectedCallback = void();
callback LifecycleDisconnectedCallback = void();
callback LifecycleAdoptedCallback = void(Document? oldDocument,
@ -21,7 +20,6 @@ callback LifecycleAttributeChangedCallback = void(DOMString attrName,
DOMString? namespaceURI);
dictionary LifecycleCallbacks {
LifecycleCreatedCallback? createdCallback;
LifecycleConnectedCallback? connectedCallback;
LifecycleDisconnectedCallback? disconnectedCallback;
LifecycleAdoptedCallback? adoptedCallback;

Просмотреть файл

@ -16,14 +16,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094930
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var proto = {
createdCallback: function() {
ok(true, "createdCallback was called");
connectedCallback: function() {
ok(true, "connectedCallback was called");
SimpleTest.finish()
}
};
var f = document.registerElement.call(frames[0].document, "x-foo", { prototype: proto });
var inst = new f();
frames[0].document.firstChild.appendChild(new f());
</script>
</body>
</html>