Commit da0d0c50 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

custom-elements: Handle V0 type extension as close to element creation as possible.

Move V0 type extension handling in Element::
AttributeChangedFromParserOrByCloning() to its callsites close to
element creation.

* HTMLConstructionSite:
  Move 'is' attribute lookup from LookUpCustomElementDefinition() to
  CreateElement() in order to avoid looking up 'is' again.

* XMLDocumentParser:
  Convert libxml attributes to blink::Attribute before element creation
  to find 'is' attribute easily.

This CL has no behavior changes, and is a preparation to consolidate
V0 type extension handling and element creation.

Bug: 808302, 808311, 807871
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Ibb4254720f1bed8b92e878fa7b29c986bfa1f87d
Reviewed-on: https://chromium-review.googlesource.com/898685Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#534035}
parent 9d5eb0ba
...@@ -1291,6 +1291,11 @@ Node* Document::importNode(Node* imported_node, ...@@ -1291,6 +1291,11 @@ Node* Document::importNode(Node* imported_node,
} }
Element* new_element = Element* new_element =
createElement(old_element->TagQName(), kCreatedByImportNode); createElement(old_element->TagQName(), kCreatedByImportNode);
const AtomicString& is = old_element->FastGetAttribute(HTMLNames::isAttr);
if (!is.IsNull() &&
!V0CustomElement::IsValidName(new_element->localName()))
V0CustomElementRegistrationContext::SetTypeExtension(new_element, is);
// TODO(tkent): Handle V1 custom built-in elements. crbug.com/807871
new_element->CloneDataFromElement(*old_element); new_element->CloneDataFromElement(*old_element);
......
...@@ -280,7 +280,12 @@ Element* Element::CloneElementWithoutChildren() { ...@@ -280,7 +280,12 @@ Element* Element::CloneElementWithoutChildren() {
} }
Element* Element::CloneElementWithoutAttributesAndChildren() { Element* Element::CloneElementWithoutAttributesAndChildren() {
return GetDocument().createElement(TagQName(), kCreatedByCloneNode); auto* element = GetDocument().createElement(TagQName(), kCreatedByCloneNode);
const AtomicString& is = FastGetAttribute(HTMLNames::isAttr);
if (!is.IsNull() && !V0CustomElement::IsValidName(element->localName()))
V0CustomElementRegistrationContext::SetTypeExtension(element, is);
// TODO(tkent): Handle V1 custom built-in elements. crbug.com/807871
return element;
} }
Attr* Element::DetachAttribute(size_t index) { Attr* Element::DetachAttribute(size_t index) {
...@@ -1501,12 +1506,11 @@ const QualifiedName& Element::SubResourceAttributeName() const { ...@@ -1501,12 +1506,11 @@ const QualifiedName& Element::SubResourceAttributeName() const {
return QualifiedName::Null(); return QualifiedName::Null();
} }
// TODO(tkent): Remove this function, and call AttributeChanged directly.
inline void Element::AttributeChangedFromParserOrByCloning( inline void Element::AttributeChangedFromParserOrByCloning(
const QualifiedName& name, const QualifiedName& name,
const AtomicString& new_value, const AtomicString& new_value,
AttributeModificationReason reason) { AttributeModificationReason reason) {
if (name == isAttr && !V0CustomElement::IsValidName(localName()))
V0CustomElementRegistrationContext::SetTypeExtension(this, new_value);
AttributeChanged( AttributeChanged(
AttributeModificationParams(name, g_null_atom, new_value, reason)); AttributeModificationParams(name, g_null_atom, new_value, reason));
} }
......
...@@ -225,8 +225,13 @@ void HTMLScriptElement::SetScriptElementForBinding( ...@@ -225,8 +225,13 @@ void HTMLScriptElement::SetScriptElementForBinding(
} }
Element* HTMLScriptElement::CloneElementWithoutAttributesAndChildren() { Element* HTMLScriptElement::CloneElementWithoutAttributesAndChildren() {
return new HTMLScriptElement(GetDocument(), false, loader_->AlreadyStarted(), auto* element = new HTMLScriptElement(GetDocument(), false,
false); loader_->AlreadyStarted(), false);
const AtomicString& is = FastGetAttribute(HTMLNames::isAttr);
if (!is.IsNull() && !V0CustomElement::IsValidName(element->localName()))
V0CustomElementRegistrationContext::SetTypeExtension(element, is);
// TODO(tkent): Handle V1 custom built-in elements. crbug.com/807871
return element;
} }
void HTMLScriptElement::Trace(blink::Visitor* visitor) { void HTMLScriptElement::Trace(blink::Visitor* visitor) {
......
...@@ -412,6 +412,12 @@ void HTMLConstructionSite::InsertHTMLHtmlStartTagBeforeHTML( ...@@ -412,6 +412,12 @@ void HTMLConstructionSite::InsertHTMLHtmlStartTagBeforeHTML(
AtomicHTMLToken* token) { AtomicHTMLToken* token) {
DCHECK(document_); DCHECK(document_);
HTMLHtmlElement* element = HTMLHtmlElement::Create(*document_); HTMLHtmlElement* element = HTMLHtmlElement::Create(*document_);
if (const Attribute* is_attribute =
token->GetAttributeItem(HTMLNames::isAttr)) {
V0CustomElementRegistrationContext::SetTypeExtension(element,
is_attribute->Value());
}
// TODO(tkent): Handle V1 custom built-in element. crbug.com/808311
SetAttributes(element, token, parser_content_policy_); SetAttributes(element, token, parser_content_policy_);
AttachLater(attachment_root_, element); AttachLater(attachment_root_, element);
open_elements_.PushHTMLHtmlElement(HTMLStackItem::Create(element, token)); open_elements_.PushHTMLHtmlElement(HTMLStackItem::Create(element, token));
...@@ -736,6 +742,12 @@ void HTMLConstructionSite::InsertScriptElement(AtomicHTMLToken* token) { ...@@ -736,6 +742,12 @@ void HTMLConstructionSite::InsertScriptElement(AtomicHTMLToken* token) {
HTMLScriptElement* element = HTMLScriptElement* element =
HTMLScriptElement::Create(OwnerDocumentForCurrentNode(), parser_inserted, HTMLScriptElement::Create(OwnerDocumentForCurrentNode(), parser_inserted,
already_started, created_during_document_write); already_started, created_during_document_write);
if (const Attribute* is_attribute =
token->GetAttributeItem(HTMLNames::isAttr)) {
V0CustomElementRegistrationContext::SetTypeExtension(element,
is_attribute->Value());
}
// TODO(tkent): Handle V1 custom built-in element. crbug.com/808311
SetAttributes(element, token, parser_content_policy_); SetAttributes(element, token, parser_content_policy_);
if (ScriptingContentIsAllowed(parser_content_policy_)) if (ScriptingContentIsAllowed(parser_content_policy_))
AttachLater(CurrentNode(), element); AttachLater(CurrentNode(), element);
...@@ -837,7 +849,8 @@ inline Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() { ...@@ -837,7 +849,8 @@ inline Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() {
// https://html.spec.whatwg.org/#look-up-a-custom-element-definition // https://html.spec.whatwg.org/#look-up-a-custom-element-definition
CustomElementDefinition* HTMLConstructionSite::LookUpCustomElementDefinition( CustomElementDefinition* HTMLConstructionSite::LookUpCustomElementDefinition(
Document& document, Document& document,
AtomicHTMLToken* token) { AtomicHTMLToken* token,
const AtomicString& is) {
// "2. If document does not have a browsing context, return null." // "2. If document does not have a browsing context, return null."
LocalDOMWindow* window = document.ExecutingWindow(); LocalDOMWindow* window = document.ExecutingWindow();
if (!window) if (!window)
...@@ -850,8 +863,7 @@ CustomElementDefinition* HTMLConstructionSite::LookUpCustomElementDefinition( ...@@ -850,8 +863,7 @@ CustomElementDefinition* HTMLConstructionSite::LookUpCustomElementDefinition(
return nullptr; return nullptr;
const AtomicString& local_name = token->GetName(); const AtomicString& local_name = token->GetName();
const Attribute* is_attribute = token->GetAttributeItem(HTMLNames::isAttr); const AtomicString& name = !is.IsNull() ? is : local_name;
const AtomicString& name = is_attribute ? is_attribute->Value() : local_name;
CustomElementDescriptor descriptor(name, local_name); CustomElementDescriptor descriptor(name, local_name);
// 4.-6. // 4.-6.
...@@ -869,8 +881,10 @@ Element* HTMLConstructionSite::CreateElement( ...@@ -869,8 +881,10 @@ Element* HTMLConstructionSite::CreateElement(
// "2. Let local name be the tag name of the token." // "2. Let local name be the tag name of the token."
QualifiedName tag_name(g_null_atom, token->GetName(), namespace_uri); QualifiedName tag_name(g_null_atom, token->GetName(), namespace_uri);
// "3. Let is be the value of the "is" attribute in the given token ..." etc. // "3. Let is be the value of the "is" attribute in the given token ..." etc.
const Attribute* is_attribute = token->GetAttributeItem(HTMLNames::isAttr);
const AtomicString& is = is_attribute ? is_attribute->Value() : g_null_atom;
// "4. Let definition be the result of looking up a custom element ..." etc. // "4. Let definition be the result of looking up a custom element ..." etc.
auto* definition = LookUpCustomElementDefinition(document, token); auto* definition = LookUpCustomElementDefinition(document, token, is);
// "5. If definition is non-null and the parser was not originally created // "5. If definition is non-null and the parser was not originally created
// for the HTML fragment parsing algorithm, then let will execute script // for the HTML fragment parsing algorithm, then let will execute script
// be true." // be true."
...@@ -914,6 +928,8 @@ Element* HTMLConstructionSite::CreateElement( ...@@ -914,6 +928,8 @@ Element* HTMLConstructionSite::CreateElement(
GetCreateElementFlags()); GetCreateElementFlags());
} else { } else {
element = document.createElement(tag_name, GetCreateElementFlags()); element = document.createElement(tag_name, GetCreateElementFlags());
if (!is.IsNull() && !V0CustomElement::IsValidName(tag_name.LocalName()))
V0CustomElementRegistrationContext::SetTypeExtension(element, is);
} }
// Definition for the created element does not exist here and it cannot be // Definition for the created element does not exist here and it cannot be
// custom or failed. // custom or failed.
......
...@@ -262,8 +262,10 @@ class HTMLConstructionSite final { ...@@ -262,8 +262,10 @@ class HTMLConstructionSite final {
void ExecuteTask(HTMLConstructionSiteTask&); void ExecuteTask(HTMLConstructionSiteTask&);
void QueueTask(const HTMLConstructionSiteTask&); void QueueTask(const HTMLConstructionSiteTask&);
CustomElementDefinition* LookUpCustomElementDefinition(Document&, CustomElementDefinition* LookUpCustomElementDefinition(
AtomicHTMLToken*); Document&,
AtomicHTMLToken*,
const AtomicString& is);
HTMLParserReentryPermit* reentry_permit_; HTMLParserReentryPermit* reentry_permit_;
Member<Document> document_; Member<Document> document_;
......
...@@ -148,7 +148,12 @@ Document& SVGScriptElement::GetDocument() const { ...@@ -148,7 +148,12 @@ Document& SVGScriptElement::GetDocument() const {
} }
Element* SVGScriptElement::CloneElementWithoutAttributesAndChildren() { Element* SVGScriptElement::CloneElementWithoutAttributesAndChildren() {
return new SVGScriptElement(GetDocument(), false, loader_->AlreadyStarted()); auto* element =
new SVGScriptElement(GetDocument(), false, loader_->AlreadyStarted());
const AtomicString& is = FastGetAttribute(HTMLNames::isAttr);
if (!is.IsNull() && !V0CustomElement::IsValidName(element->localName()))
V0CustomElementRegistrationContext::SetTypeExtension(element, is);
return element;
} }
void SVGScriptElement::DispatchLoadEvent() { void SVGScriptElement::DispatchLoadEvent() {
......
...@@ -951,26 +951,36 @@ void XMLDocumentParser::StartElementNs(const AtomicString& local_name, ...@@ -951,26 +951,36 @@ void XMLDocumentParser::StartElementNs(const AtomicString& local_name,
bool is_first_element = !saw_first_element_; bool is_first_element = !saw_first_element_;
saw_first_element_ = true; saw_first_element_ = true;
QualifiedName q_name(prefix, local_name, adjusted_uri);
Element* new_element =
current_node_->GetDocument().createElement(q_name, kCreatedByParser);
if (!new_element) {
StopParsing();
return;
}
Vector<Attribute> prefixed_attributes; Vector<Attribute> prefixed_attributes;
DummyExceptionStateForTesting exception_state; DummyExceptionStateForTesting exception_state;
HandleNamespaceAttributes(prefixed_attributes, libxml_namespaces, HandleNamespaceAttributes(prefixed_attributes, libxml_namespaces,
nb_namespaces, exception_state); nb_namespaces, exception_state);
if (exception_state.HadException()) { if (exception_state.HadException()) {
SetAttributes(new_element, prefixed_attributes, GetParserContentPolicy());
StopParsing(); StopParsing();
return; return;
} }
HandleElementAttributes(prefixed_attributes, libxml_attributes, nb_attributes, HandleElementAttributes(prefixed_attributes, libxml_attributes, nb_attributes,
prefix_to_namespace_map_, exception_state); prefix_to_namespace_map_, exception_state);
QualifiedName q_name(prefix, local_name, adjusted_uri);
Element* new_element =
current_node_->GetDocument().createElement(q_name, kCreatedByParser);
if (!new_element) {
StopParsing();
return;
}
for (const auto& attr : prefixed_attributes) {
if (attr.GetName() == isAttr) {
if (!V0CustomElement::IsValidName(local_name)) {
V0CustomElementRegistrationContext::SetTypeExtension(new_element,
attr.Value());
}
break;
}
}
// TODO(tkent): Support V1 custom built-in elements. crbug.com/808302
SetAttributes(new_element, prefixed_attributes, GetParserContentPolicy()); SetAttributes(new_element, prefixed_attributes, GetParserContentPolicy());
if (exception_state.HadException()) { if (exception_state.HadException()) {
StopParsing(); StopParsing();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment