зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1301024 - Part 2: Implement create an element steps. r=smaug
This commit is contained in:
Родитель
ca4066029e
Коммит
cc16112226
|
@ -939,7 +939,7 @@ DoUpgrade(Element* aElement,
|
|||
} // anonymous namespace
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#upgrades
|
||||
void
|
||||
/* static */ void
|
||||
CustomElementRegistry::Upgrade(Element* aElement,
|
||||
CustomElementDefinition* aDefinition,
|
||||
ErrorResult& aRv)
|
||||
|
@ -977,8 +977,10 @@ CustomElementRegistry::Upgrade(Element* aElement,
|
|||
(attrValue.IsEmpty() ? VoidString() : attrValue),
|
||||
(namespaceURI.IsEmpty() ? VoidString() : namespaceURI)
|
||||
};
|
||||
EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, aElement,
|
||||
&args, aDefinition);
|
||||
nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(),
|
||||
nsIDocument::eAttributeChanged,
|
||||
aElement,
|
||||
&args, aDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1003,7 +1005,9 @@ CustomElementRegistry::Upgrade(Element* aElement,
|
|||
data->mState = CustomElementData::State::eCustom;
|
||||
|
||||
// This is for old spec.
|
||||
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition);
|
||||
nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(),
|
||||
nsIDocument::eCreated,
|
||||
aElement, nullptr, aDefinition);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
|
|
@ -362,11 +362,15 @@ public:
|
|||
void GetCustomPrototype(nsIAtom* 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
|
||||
*/
|
||||
void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
|
||||
static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
~CustomElementRegistry();
|
||||
|
@ -375,9 +379,6 @@ private:
|
|||
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition);
|
||||
|
||||
void SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
CustomElementDefinition* aDefinition);
|
||||
/**
|
||||
* Registers an unresolved custom element that is a candidate for
|
||||
* upgrade when the definition is registered via registerElement.
|
||||
|
|
|
@ -10154,6 +10154,49 @@ 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)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
nsIDocument* doc = aElement->OwnerDoc();
|
||||
nsPIDOMWindowInner* window(doc->GetInnerWindow());
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomElementReactionsStack* stack =
|
||||
doc->GetDocGroup()->CustomElementReactionsStack();
|
||||
stack->EnqueueUpgradeReaction(registry, aElement, aDefinition);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
|
||||
nsIDocument::ElementCallbackType aType,
|
||||
|
|
|
@ -2998,6 +2998,13 @@ public:
|
|||
nsIAtom* aExtensionType,
|
||||
nsIAtom* aAttrName);
|
||||
|
||||
static void SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition);
|
||||
|
||||
static void EnqueueUpgradeReaction(Element* aElement,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition);
|
||||
|
||||
static void EnqueueLifecycleCallback(nsIDocument* aDoc,
|
||||
nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
|
|
|
@ -223,6 +223,26 @@ public:
|
|||
int32_t mStackPos;
|
||||
};
|
||||
|
||||
static void
|
||||
DoCustomElementCreate(Element** aElement, nsIDocument* aDoc,
|
||||
CustomElementConstructor* aConstructor, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<Element> element =
|
||||
aConstructor->Construct("Custom Element Create", aRv);
|
||||
if (aRv.Failed() || !element->IsHTMLElement()) {
|
||||
aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
|
||||
element->HasChildren() || element->GetAttrCount()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
element.forget(aElement);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
FromParser aFromParser, const nsAString* aIs)
|
||||
|
@ -238,6 +258,81 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
|
|||
|
||||
int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-create-element
|
||||
// We only handle the "synchronous custom elements flag is set" now.
|
||||
// For the unset case (e.g. cloning a node), see bug 1319342 for that.
|
||||
// Step 4.
|
||||
CustomElementDefinition* definition = nullptr;
|
||||
if (CustomElementRegistry::IsCustomElementEnabled()) {
|
||||
definition =
|
||||
nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
|
||||
nodeInfo->LocalName(),
|
||||
nodeInfo->NamespaceID(),
|
||||
aIs);
|
||||
}
|
||||
|
||||
// It might be a problem that parser synchronously calls constructor, so filed
|
||||
// bug 1378079 to figure out what we should do for parser case.
|
||||
if (definition) {
|
||||
/*
|
||||
* Synchronous custom elements flag is determined by 3 places in spec,
|
||||
* 1) create an element for a token, the flag is determined by
|
||||
* "will execute script" which is not originally created
|
||||
* for the HTML fragment parsing algorithm.
|
||||
* 2) createElement and createElementNS, the flag is the same as
|
||||
* NOT_FROM_PARSER.
|
||||
* 3) clone a node, our implementation will not go into this function.
|
||||
* For the unset case which is non-synchronous only applied for
|
||||
* inner/outerHTML.
|
||||
*/
|
||||
bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT ||
|
||||
aFromParser == dom::NOT_FROM_PARSER;
|
||||
// Per discussion in https://github.com/w3c/webcomponents/issues/635,
|
||||
// use entry global in those places that are called from JS APIs.
|
||||
nsIGlobalObject* global = GetEntryGlobal();
|
||||
MOZ_ASSERT(global);
|
||||
AutoEntryScript aes(global, "create custom elements");
|
||||
JSContext* cx = aes.cx();
|
||||
ErrorResult rv;
|
||||
|
||||
// Step 5.
|
||||
if (definition->IsCustomBuiltIn()) {
|
||||
// SetupCustomElement() should be called with an element that don't have
|
||||
// CustomElementData setup, if not we will hit the assertion in
|
||||
// SetCustomElementData().
|
||||
nsCOMPtr<nsIAtom> tagAtom = nodeInfo->NameAtom();
|
||||
nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
|
||||
// Built-in element
|
||||
*aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
|
||||
(*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
|
||||
if (synchronousCustomElements) {
|
||||
CustomElementRegistry::Upgrade(*aResult, definition, rv);
|
||||
} else {
|
||||
nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
|
||||
}
|
||||
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
aes.ReportException();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Step 6.1.
|
||||
if (synchronousCustomElements) {
|
||||
DoCustomElementCreate(aResult, nodeInfo->GetDocument(),
|
||||
definition->mConstructor, rv);
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Step 6.2.
|
||||
NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
|
||||
nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Per the Custom Element specification, unknown tags that are valid custom
|
||||
// element names should be HTMLElement instead of HTMLUnknownElement.
|
||||
bool isCustomElementName = (tag == eHTMLTag_userdefined &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче