Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp

Issue 2200613002: The HTML parser synchronously creates custom elements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Eliminate redundant TODOs. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
index 33ce143691dd2ac4856f5e2383c97d4e3ffe9a29..cf1b5684335d66c54e55d1be5fd07342eb66e361 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
@@ -26,6 +26,8 @@
#include "core/html/parser/HTMLConstructionSite.h"
+#include "bindings/core/v8/Microtask.h"
+#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/HTMLElementFactory.h"
#include "core/HTMLNames.h"
#include "core/dom/Comment.h"
@@ -33,9 +35,15 @@
#include "core/dom/DocumentType.h"
#include "core/dom/Element.h"
#include "core/dom/ElementTraversal.h"
+#include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
#include "core/dom/ScriptLoader.h"
#include "core/dom/TemplateContentDocumentFragment.h"
#include "core/dom/Text.h"
+#include "core/dom/custom/CEReactionsScope.h"
+#include "core/dom/custom/CustomElementDefinition.h"
+#include "core/dom/custom/CustomElementDescriptor.h"
+#include "core/dom/custom/CustomElementsRegistry.h"
+#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLHtmlElement.h"
@@ -44,6 +52,7 @@
#include "core/html/HTMLTemplateElement.h"
#include "core/html/parser/AtomicHTMLToken.h"
#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/html/parser/HTMLParserReentryPermit.h"
#include "core/html/parser/HTMLStackItem.h"
#include "core/html/parser/HTMLToken.h"
#include "core/loader/FrameLoader.h"
@@ -314,8 +323,9 @@ void HTMLConstructionSite::executeQueuedTasks()
// We might be detached now.
}
-HTMLConstructionSite::HTMLConstructionSite(Document& document, ParserContentPolicy parserContentPolicy)
- : m_document(&document)
+HTMLConstructionSite::HTMLConstructionSite(HTMLParserReentryPermit* reentryPermit, Document& document, ParserContentPolicy parserContentPolicy)
+ : m_reentryPermit(reentryPermit)
+ , m_document(&document)
, m_attachmentRoot(document)
, m_parserContentPolicy(parserContentPolicy)
, m_isParsingFragment(false)
@@ -747,17 +757,111 @@ inline Document& HTMLConstructionSite::ownerDocumentForCurrentNode()
return currentNode()->document();
}
+// "look up a custom element definition" for a token
+// https://html.spec.whatwg.org/#look-up-a-custom-element-definition
+CustomElementDefinition* HTMLConstructionSite::lookUpCustomElementDefinition(Document& document, AtomicHTMLToken* token)
+{
+ // "2. If document does not have a browsing context, return null."
+ LocalDOMWindow* window = document.domWindow();
+ if (!window)
+ return nullptr;
+
+ // "3. Let registry be document's browsing context's Window's
+ // CustomElementsRegistry object."
+ CustomElementsRegistry* registry = window->maybeCustomElements();
+ if (!registry)
+ return nullptr;
+
+ const AtomicString& localName = token->name();
+ const Attribute* isAttribute = token->getAttributeItem(HTMLNames::isAttr);
+ const AtomicString& name = isAttribute ? isAttribute->value() : localName;
+ CustomElementDescriptor descriptor(name, localName);
+
+ // 4.-6.
+ return registry->definitionFor(descriptor);
+}
+
+// "create an element for a token"
+// https://html.spec.whatwg.org/#create-an-element-for-the-token
+// TODO(dominicc): When form association is separate from creation,
+// unify this with foreign element creation. Add a namespace parameter
+// and check for HTML namespace to lookupCustomElementDefinition.
HTMLElement* HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token)
{
+ // "1. Let document be intended parent's node document."
Document& document = ownerDocumentForCurrentNode();
+
// Only associate the element with the current form if we're creating the new element
// in a document with a browsing context (rather than in <template> contents).
+ // TODO(dominicc): Change form to happen after element creation when
+ // implementing customized built-in elements.
HTMLFormElement* form = document.frame() ? m_form.get() : nullptr;
- // FIXME: This can't use HTMLConstructionSite::createElement because we
- // have to pass the current form element. We should rework form association
- // to occur after construction to allow better code sharing here.
- HTMLElement* element = HTMLElementFactory::createHTMLElement(token->name(), document, form, getCreateElementFlags());
- setAttributes(element, token, m_parserContentPolicy);
+
+ // "2. Let local name be the tag name of the token."
+ // "3. Let is be the value of the "is" attribute in the giev token ..." etc.
+ // "4. Let definition be the result of looking up a custom element ..." etc.
+ CustomElementDefinition* definition = m_isParsingFragment ? nullptr : lookUpCustomElementDefinition(document, token);
+ // "5. If definition is non-null and the parser was not originally created
+ // for the HTML fragment parsing algorithm, then let will execute script
+ // be true."
+ bool willExecuteScript = definition && !m_isParsingFragment;
+
+ HTMLElement* element;
+
+ if (willExecuteScript) {
+ // "6.1 Increment the parser's script nesting level."
+ HTMLParserReentryPermit::ScriptNestingLevelIncrementer incrementScriptNestingLevel = m_reentryPermit->incrementScriptNestingLevel();
+
+ // "6.2 Set the parser pause flag to true."
+ m_reentryPermit->pause();
+
+ // TODO(dominicc): Change this once resolved:
+ // https://github.com/whatwg/html/issues/1630
+ IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWrites(
+ &document);
+
+ // "6.3 If the JavaScript execution context stack is empty,
+ // then perform a microtask checkpoint."
+
+ // TODO(dominicc): This is the way the Blink HTML parser
+ // performs checkpoints, but note the spec is different--it
+ // talks about the JavaScript stack, not the script nesting
+ // level.
+ if (1u == m_reentryPermit->scriptNestingLevel())
+ Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate());
+
+ // "6.4 Push a new element queue onto the custom element
+ // reactions stack."
+ CEReactionsScope reactions;
+
+ // 7.
+ QualifiedName elementQName(nullAtom, token->name(), HTMLNames::xhtmlNamespaceURI);
+ element = definition->createElementSync(document, elementQName);
+
+ // "8. Append each attribute in the given token to element."
+ // We don't use setAttributes here because the custom element
+ // constructor may have manipulated attributes.
+ for (const auto& attribute : token->attributes())
+ element->setAttribute(attribute.name(), attribute.value());
+
+ // "9. If will execute script is true, then ..." etc. The
+ // CEReactionsScope and ScriptNestingLevelIncrementer
+ // destructors implement steps 9.1-4.
+ } else {
+ // FIXME: This can't use
+ // HTMLConstructionSite::createElement because we have to
+ // pass the current form element. We should rework form
+ // association to occur after construction to allow better
+ // code sharing here.
+ element = HTMLElementFactory::createHTMLElement(token->name(), document, form, getCreateElementFlags());
+
+ // "8. Append each attribute in the given token to element."
+ setAttributes(element, token, m_parserContentPolicy);
+ }
+
+ // TODO(dominicc): Implement steps 10-12 when customized built-in
+ // elements are implemented.
+
return element;
}

Powered by Google App Engine
This is Rietveld 408576698