mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-24 08:07:30 +09:00
Bug 1359346 - Implement custom element state;
https://dom.spec.whatwg.org/#concept-element-custom-element-state Tag UXP Issue #1344
This commit is contained in:
parent
5ad5f4e1ec
commit
cb89330bf3
3 changed files with 44 additions and 22 deletions
|
|
@ -78,12 +78,21 @@ CustomElementCallback::CustomElementCallback(Element* aThisObject,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------
|
||||||
|
// CustomElementData
|
||||||
|
|
||||||
CustomElementData::CustomElementData(nsIAtom* aType)
|
CustomElementData::CustomElementData(nsIAtom* aType)
|
||||||
: mType(aType),
|
: CustomElementData(aType, CustomElementData::State::eUndefined)
|
||||||
mCurrentCallback(-1),
|
{
|
||||||
mElementIsBeingCreated(false),
|
}
|
||||||
mCreatedCallbackInvoked(true),
|
|
||||||
mAssociatedMicroTask(-1)
|
CustomElementData::CustomElementData(nsIAtom* aType, State aState)
|
||||||
|
: mType(aType)
|
||||||
|
, mCurrentCallback(-1)
|
||||||
|
, mElementIsBeingCreated(false)
|
||||||
|
, mCreatedCallbackInvoked(true)
|
||||||
|
, mAssociatedMicroTask(-1)
|
||||||
|
, mState(aState)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,6 +108,9 @@ CustomElementData::RunCallbackQueue()
|
||||||
mCurrentCallback = -1;
|
mCurrentCallback = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------
|
||||||
|
// CustomElementRegistry
|
||||||
|
|
||||||
// Only needed for refcounted objects.
|
// Only needed for refcounted objects.
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
|
||||||
|
|
||||||
|
|
@ -305,10 +317,15 @@ CustomElementRegistry::SetupCustomElement(Element* aElement,
|
||||||
aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *aTypeExtension, true);
|
aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *aTypeExtension, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomElementDefinition* data = LookupCustomElementDefinition(
|
// SetupCustomElement() should be called with an element that don't have
|
||||||
|
// CustomElementData setup, if not we will hit the assertion in
|
||||||
|
// SetCustomElementData().
|
||||||
|
aElement->SetCustomElementData(new CustomElementData(typeAtom));
|
||||||
|
|
||||||
|
CustomElementDefinition* definition = LookupCustomElementDefinition(
|
||||||
aElement->NodeInfo()->LocalName(), aTypeExtension);
|
aElement->NodeInfo()->LocalName(), aTypeExtension);
|
||||||
|
|
||||||
if (!data) {
|
if (!definition) {
|
||||||
// The type extension doesn't exist in the registry,
|
// The type extension doesn't exist in the registry,
|
||||||
// thus we don't need to enqueue callback or adjust
|
// thus we don't need to enqueue callback or adjust
|
||||||
// the "is" attribute, but it is possibly an upgrade candidate.
|
// the "is" attribute, but it is possibly an upgrade candidate.
|
||||||
|
|
@ -316,7 +333,7 @@ CustomElementRegistry::SetupCustomElement(Element* aElement,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->mLocalName != tagAtom) {
|
if (definition->mLocalName != tagAtom) {
|
||||||
// The element doesn't match the local name for the
|
// The element doesn't match the local name for the
|
||||||
// definition, thus the element isn't a custom element
|
// definition, thus the element isn't a custom element
|
||||||
// and we don't need to do anything more.
|
// and we don't need to do anything more.
|
||||||
|
|
@ -325,7 +342,7 @@ CustomElementRegistry::SetupCustomElement(Element* aElement,
|
||||||
|
|
||||||
// Enqueuing the created callback will set the CustomElementData on the
|
// Enqueuing the created callback will set the CustomElementData on the
|
||||||
// element, causing prototype swizzling to occur in Element::WrapObject.
|
// element, causing prototype swizzling to occur in Element::WrapObject.
|
||||||
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, data);
|
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -334,7 +351,8 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
|
||||||
LifecycleCallbackArgs* aArgs,
|
LifecycleCallbackArgs* aArgs,
|
||||||
CustomElementDefinition* aDefinition)
|
CustomElementDefinition* aDefinition)
|
||||||
{
|
{
|
||||||
CustomElementData* elementData = aCustomElement->GetCustomElementData();
|
RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData();
|
||||||
|
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
||||||
|
|
||||||
// Let DEFINITION be ELEMENT's definition
|
// Let DEFINITION be ELEMENT's definition
|
||||||
CustomElementDefinition* definition = aDefinition;
|
CustomElementDefinition* definition = aDefinition;
|
||||||
|
|
@ -354,16 +372,6 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elementData) {
|
|
||||||
// Create the custom element data the first time
|
|
||||||
// that we try to enqueue a callback.
|
|
||||||
elementData = new CustomElementData(definition->mType);
|
|
||||||
// aCustomElement takes ownership of elementData
|
|
||||||
aCustomElement->SetCustomElementData(elementData);
|
|
||||||
MOZ_ASSERT(aType == nsIDocument::eCreated,
|
|
||||||
"First callback should be the created callback");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let CALLBACK be the callback associated with the key NAME in CALLBACKS.
|
// Let CALLBACK be the callback associated with the key NAME in CALLBACKS.
|
||||||
CallbackFunction* func = nullptr;
|
CallbackFunction* func = nullptr;
|
||||||
switch (aType) {
|
switch (aType) {
|
||||||
|
|
@ -881,8 +889,6 @@ CustomElementRegistry::Upgrade(Element* aElement,
|
||||||
}
|
}
|
||||||
} // Leave prototype's compartment.
|
} // Leave prototype's compartment.
|
||||||
|
|
||||||
// Enqueuing the created callback will set the CustomElementData on the
|
|
||||||
// element, causing prototype swizzling to occur in Element::WrapObject.
|
|
||||||
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition);
|
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,18 @@ struct CustomElementData
|
||||||
{
|
{
|
||||||
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
|
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#concept-element-custom-element-state
|
||||||
|
// CustomElementData is only created on the element which is a custom element
|
||||||
|
// or an upgrade candidate, so the state of an element without
|
||||||
|
// CustomElementData is "uncustomized".
|
||||||
|
enum class State {
|
||||||
|
eUndefined,
|
||||||
|
eFailed,
|
||||||
|
eCustom
|
||||||
|
};
|
||||||
|
|
||||||
explicit CustomElementData(nsIAtom* aType);
|
explicit CustomElementData(nsIAtom* aType);
|
||||||
|
CustomElementData(nsIAtom* aType, State aState);
|
||||||
// Objects in this array are transient and empty after each microtask
|
// Objects in this array are transient and empty after each microtask
|
||||||
// checkpoint.
|
// checkpoint.
|
||||||
nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
|
nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
|
||||||
|
|
@ -89,6 +100,8 @@ struct CustomElementData
|
||||||
// it is used to determine if a new queue needs to be pushed onto the
|
// it is used to determine if a new queue needs to be pushed onto the
|
||||||
// processing stack.
|
// processing stack.
|
||||||
int32_t mAssociatedMicroTask;
|
int32_t mAssociatedMicroTask;
|
||||||
|
// Custom element state as described in the custom element spec.
|
||||||
|
State mState;
|
||||||
|
|
||||||
// Empties the callback queue.
|
// Empties the callback queue.
|
||||||
void RunCallbackQueue();
|
void RunCallbackQueue();
|
||||||
|
|
|
||||||
|
|
@ -3550,6 +3550,9 @@ CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
|
||||||
element = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
|
element = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
element->SetCustomElementData(
|
||||||
|
new CustomElementData(definition->mType, CustomElementData::State::eCustom));
|
||||||
|
|
||||||
return element.forget();
|
return element.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue