<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197463] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197463">197463</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-02 13:56:47 -0800 (Wed, 02 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make HTML parser construct custom elements
https://bugs.webkit.org/show_bug.cgi?id=154908
Source/WebCore:

&lt;rdar://problem/24923735&gt;

Reviewed by Antti Koivisto.

Added the support for instantiating custom elements inside the parser. Based on Jan F2F discussion,
the HTML parser is going to synchronously construct custom elements. When a custom element constructor
throws, the HTML parser creates a HTMLUnknownElement instead.

In our implementation, we pause the parser completely and construct custom elements using the same
mechanism used to run author scripts. It's possible that we may want to apply some optimizations to
to make custom element construction but it's probably a good idea to get semantics right first.

Tests: fast/custom-elements/parser/parser-constructs-custom-elements.html
       fast/custom-elements/parser/parser-fallsback-to-unknown-element.html
       fast/custom-elements/parser/parser-sets-attributes-and-children.html
       fast/custom-elements/parser/parser-uses-constructed-element.html

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::constructElement): Added ShouldClearException as an argument
to be used by the HTML parser since the parser can't re-throw to anywhere or fail parsing.

* bindings/js/JSCustomElementInterface.h:
(WebCore::JSCustomElementInterface::ShouldClearException): Added.

* dom/Document.cpp:
(WebCore::createHTMLElementWithNameValidation): Do not clear the exception here since createElement
must re-throw the exception thrown by a custom element constructor.
(WebCore::Document::createElementForBindings):

* dom/make_names.pl:
(printFactoryCppFile): Added ConstructorFunctionMapEntry which contains the constructor function
as well as the qualified name.
(printFactoryHeaderFile): Added a variant of createKnownElement and createElement that takes
AtomicString instead of QualifiedName.

* html/parser/HTMLConstructionSite.cpp:
(WebCore::setAttributes): Added a variant that takes Vector&lt;Attribute&gt;.
(WebCore::HTMLConstructionSite::insertHTMLElementOrFindCustomElementInterface): Added. Returns a
custom element interface when the element doesn't match any builtin element and there is a custom
element definition that matches the specified name.
(WebCore::HTMLConstructionSite::insertCustomElement): Added. Like insertElement but also sets the
attributes on the newly created custom element.
(WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Extracted from
createHTMLElement. When customElementInterface is not nullptr, we optionally find the custom
element interface and return nullptr.
(WebCore::HTMLConstructionSite::createHTMLElement):
* html/parser/HTMLConstructionSite.h:

* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder): Create a custom element when there
is a pending custom element to create (i.e. m_customElementToConstruct is not empty).
(WebCore::HTMLDocumentParser::isWaitingForScripts):

* html/parser/HTMLStackItem.h:
(WebCore::HTMLStackItem::create): Added a variant used for custom elements.
(WebCore::HTMLStackItem::HTMLStackItem): Ditto.

* html/parser/HTMLTreeBuilder.cpp:
(WebCore::CustomElementConstructionData::CustomElementConstructionData): Added. It needs to be in
the cpp file to avoid introducing more header dependencies in HTMLTreeBuilder.h.
(WebCore::CustomElementConstructionData::~CustomElementConstructionData): Ditto.
(WebCore::HTMLTreeBuilder::processStartTagForInBody): Use insertGenericHTMLElement when creating
a generic element that could be custom elements.
(WebCore::HTMLTreeBuilder::insertGenericHTMLElement): Added. Create and insert a new element
or set m_customElementToConstruct so that the HTMLDocumentParser will create a custom element later.
(WebCore::HTMLTreeBuilder::didCreateCustomOrCallbackElement): Added. Called by HTMLDocumentParser
when it finishes creating a new custom element.

* html/parser/HTMLTreeBuilder.h:
(WebCore::HTMLTreeBuilder::takeCustomElementConstructionData): Added.
(WebCore::HTMLTreeBuilder::hasParserBlockingScriptWork): Renamed from hasParserBlockingScript.
Checks the existence of m_customElementToConstruct as well as m_scriptToProcess.

LayoutTests:


Reviewed by Antti Koivisto.

Added W3C testharness.js based tests for instantiating custom elements inside the HTML parser.

* fast/custom-elements/parser: Added.
* fast/custom-elements/parser/parser-constructs-custom-elements-expected.txt: Added.
* fast/custom-elements/parser/parser-constructs-custom-elements.html: Added.
* fast/custom-elements/parser/parser-fallsback-to-unknown-element-expected.txt: Added.
* fast/custom-elements/parser/parser-fallsback-to-unknown-element.html: Added.
* fast/custom-elements/parser/parser-sets-attributes-and-children-expected.txt: Added.
* fast/custom-elements/parser/parser-sets-attributes-and-children.html: Added.
* fast/custom-elements/parser/parser-uses-constructed-element-expected.txt: Added.
* fast/custom-elements/parser/parser-uses-constructed-element.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp">trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSCustomElementInterfaceh">trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredommake_namespl">trunk/Source/WebCore/dom/make_names.pl</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLConstructionSitecpp">trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLConstructionSiteh">trunk/Source/WebCore/html/parser/HTMLConstructionSite.h</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLDocumentParsercpp">trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLStackItemh">trunk/Source/WebCore/html/parser/HTMLStackItem.h</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLTreeBuildercpp">trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLTreeBuilderh">trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/fast/custom-elements/parser/</li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparserconstructscustomelementsexpectedtxt">trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparserconstructscustomelementshtml">trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparserfallsbacktounknownelementexpectedtxt">trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparserfallsbacktounknownelementhtml">trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparsersetsattributesandchildrenexpectedtxt">trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparsersetsattributesandchildrenhtml">trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children.html</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparserusesconstructedelementexpectedtxt">trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcustomelementsparserparserusesconstructedelementhtml">trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/LayoutTests/ChangeLog        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-03-01  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Make HTML parser construct custom elements
+        https://bugs.webkit.org/show_bug.cgi?id=154908
+
+        Reviewed by Antti Koivisto.
+
+        Added W3C testharness.js based tests for instantiating custom elements inside the HTML parser.
+
+        * fast/custom-elements/parser: Added.
+        * fast/custom-elements/parser/parser-constructs-custom-elements-expected.txt: Added.
+        * fast/custom-elements/parser/parser-constructs-custom-elements.html: Added.
+        * fast/custom-elements/parser/parser-fallsback-to-unknown-element-expected.txt: Added.
+        * fast/custom-elements/parser/parser-fallsback-to-unknown-element.html: Added.
+        * fast/custom-elements/parser/parser-sets-attributes-and-children-expected.txt: Added.
+        * fast/custom-elements/parser/parser-sets-attributes-and-children.html: Added.
+        * fast/custom-elements/parser/parser-uses-constructed-element-expected.txt: Added.
+        * fast/custom-elements/parser/parser-uses-constructed-element.html: Added.
+
</ins><span class="cx"> 2016-03-02  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Align HTMLInputElement.maxLength with the specification
</span></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparserconstructscustomelementsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements-expected.txt (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements-expected.txt        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+
+PASS HTML parser must NOT create a custom element before defineElement is called 
+PASS HTML parser must create a defined custom element before executing inline scripts 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparserconstructscustomelementshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements.html (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-constructs-custom-elements.html        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Changes to the HTML parser&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;HTML parser creates a custom element&quot;&gt;
+&lt;script src=&quot;../../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;link rel='stylesheet' href='../../../resources/testharness.css'&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;my-custom-element id=&quot;instance1&quot;&gt;&lt;/my-custom-element&gt;
+&lt;script&gt;
+
+class MyCustomElement extends HTMLElement { };
+
+test(function () {
+    var customElement = document.getElementById('instance1');
+
+    assert_true(customElement instanceof HTMLElement, 'An unresolved custom element must be an instance of HTMLElement');
+    assert_false(customElement instanceof MyCustomElement, 'An unresolved custom element must NOT be an instance of that custom element');
+    assert_equals(customElement.localName, 'my-custom-element');
+    assert_equals(customElement.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
+
+}, 'HTML parser must NOT create a custom element before defineElement is called');
+
+document.defineCustomElement('my-custom-element', MyCustomElement);
+
+&lt;/script&gt;
+&lt;my-custom-element id=&quot;instance2&quot;&gt;&lt;/my-custom-element&gt;
+&lt;script&gt;
+
+test(function () {
+    var customElement = document.getElementById('instance2');
+
+    assert_true(customElement instanceof HTMLElement, 'A resolved custom element must be an instance of HTMLElement');
+    assert_false(customElement instanceof HTMLUnknownElement, 'A resolved custom element must NOT be an instance of HTMLUnknownElement');
+    assert_true(customElement instanceof MyCustomElement, 'A resolved custom element must be an instance of that custom element');
+    assert_equals(customElement.localName, 'my-custom-element');
+    assert_equals(customElement.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
+
+}, 'HTML parser must create a defined custom element before executing inline scripts');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparserfallsbacktounknownelementexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element-expected.txt (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element-expected.txt        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+PASS HTML parser must create a fallback HTMLUnknownElement when a custom element constructor returns a Text node 
+PASS HTML parser must create a fallback HTMLUnknownElement when a custom element constructor returns non-Element object 
+PASS HTML parser must create a fallback HTMLUnknownElement when a custom element constructor does not call super() 
+PASS HTML parser must create a fallback HTMLUnknownElement when a custom element constructor throws an exception 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparserfallsbacktounknownelementhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element.html (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-fallsback-to-unknown-element.html        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,88 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Changes to the HTML parser&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;HTML parser must fallback to creating a HTMLUnknownElement when a custom element construction fails&quot;&gt;
+&lt;script src=&quot;../../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;link rel='stylesheet' href='../../../resources/testharness.css'&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+class ReturnsTextNode extends HTMLElement {
+    constructor() {
+        super();
+        return document.createTextNode('some text');
+    }
+};
+document.defineCustomElement('returns-text', ReturnsTextNode);
+
+class ReturnsNonElementObject extends HTMLElement {
+    constructor() {
+        super();
+        return {};
+    }
+};
+document.defineCustomElement('returns-non-element-object', ReturnsNonElementObject);
+
+class LacksSuperCall extends HTMLElement {
+    constructor() { }
+};
+document.defineCustomElement('lacks-super-call', LacksSuperCall);
+
+class ThrowsException extends HTMLElement {
+    constructor() {
+        throw 'Bad';
+    }
+};
+document.defineCustomElement('throws-exception', ThrowsException);
+
+&lt;/script&gt;
+&lt;returns-text&gt;&lt;/returns-text&gt;
+&lt;returns-non-element-object&gt;&lt;/returns-non-element-object&gt;
+&lt;lacks-super-call&gt;&lt;/lacks-super-call&gt;
+&lt;throws-exception&gt;&lt;/throws-exception&gt;
+&lt;script&gt;
+
+test(function () {
+    var instance = document.querySelector('returns-text');
+
+    assert_false(instance instanceof ReturnsTextNode, 'HTML parser must NOT instantiate a custom element when the constructor returns a Text node');
+    assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+    assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor returns a Text node');
+
+test(function () {
+    var instance = document.querySelector('returns-non-element-object');
+
+    assert_false(instance instanceof ReturnsNonElementObject, 'HTML parser must NOT instantiate a custom element when the constructor returns a non-Element object');
+    assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+    assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor returns non-Element object');
+
+test(function () {
+    var instance = document.querySelector('lacks-super-call');
+
+    assert_false(instance instanceof LacksSuperCall, 'HTML parser must NOT instantiate a custom element when the constructor does not call super()');
+    assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+    assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor does not call super()');
+
+test(function () {
+    var instance = document.querySelector('throws-exception');
+
+    assert_false(instance instanceof ThrowsException, 'HTML parser must NOT instantiate a custom element when the constructor throws an exception');
+    assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+    assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor throws an exception');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparsersetsattributesandchildrenexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children-expected.txt (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children-expected.txt        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+hello world
+
+PASS HTML parser must set the attributes 
+PASS HTML parser must append child nodes 
+PASS HTML parser must set the attributes or append children before calling constructor 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparsersetsattributesandchildrenhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children.html (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-sets-attributes-and-children.html        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Changes to the HTML parser&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;HTML parser must set the attributes and append the children on a custom element&quot;&gt;
+&lt;script src=&quot;../../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;link rel='stylesheet' href='../../../resources/testharness.css'&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+var numberOfAttributesInConstructor;
+var numberOfChildNodesInConstructor;
+
+class MyCustomElement extends HTMLElement {
+    constructor(...args) {
+        super(...args);
+        numberOfAttributesInConstructor = this.attributes.length;
+        numberOfChildNodesInConstructor = this.childNodes.length;
+    }
+};
+document.defineCustomElement('my-custom-element', MyCustomElement);
+
+&lt;/script&gt;
+&lt;my-custom-element id=&quot;custom-element-id&quot; class=&quot;class1 class2&quot;&gt;hello &lt;b&gt;world&lt;/b&gt;&lt;/my-custom-element&gt;
+&lt;script&gt;
+
+var customElement = document.querySelector('my-custom-element');
+
+test(function () {
+    assert_equals(customElement.getAttribute('id'), 'custom-element-id', 'HTML parser must preserve the id attribute');
+    assert_equals(customElement.id, 'custom-element-id', 'HTML parser must preserve the semantics of reflect for the id attribute');
+    assert_equals(customElement.getAttribute('class'), 'class1 class2', 'HTML parser must preserve the class attribute');
+    assert_equals(customElement.classList.length, 2, 'HTML parser must initialize classList on custom elements');
+    assert_equals(customElement.classList[0], 'class1', 'HTML parser must initialize classList on custom elements');
+    assert_equals(customElement.classList[1], 'class2', 'HTML parser must initialize classList on custom elements');
+
+    assert_equals(customElement.childNodes.length, 2, 'HTML parser must append child nodes');
+    assert_equals(customElement.classList[0], 'class1', 'HTML parser must initialize classList on custom elements');
+    assert_equals(customElement.classList[1], 'class2', 'HTML parser must initialize classList on custom elements');
+
+}, 'HTML parser must set the attributes');
+
+test(function () {
+    assert_equals(customElement.childNodes.length, 2, 'HTML parser must append child nodes');
+    assert_true(customElement.firstChild instanceof Text, 'HTML parser must append Text node child to a custom element');
+    assert_equals(customElement.firstChild.data, 'hello ', 'HTML parser must append Text node child to a custom element');
+    assert_true(customElement.lastChild instanceof HTMLElement, 'HTML parser must append a builtin element child to a custom element');
+    assert_true(customElement.lastChild.firstChild instanceof Text, 'HTML parser must preserve grandchild nodes of a custom element');
+    assert_equals(customElement.lastChild.firstChild.data, 'world', 'HTML parser must preserve grandchild nodes of a custom element');
+}, 'HTML parser must append child nodes');
+
+test(function () {
+    assert_equals(numberOfAttributesInConstructor, 0, 'HTML parser must not set attributes on a custom element before invoking the constructor');
+    assert_equals(numberOfChildNodesInConstructor, 0, 'HTML parser must not append child nodes to a custom element before invoking the constructor');
+}, 'HTML parser must set the attributes or append children before calling constructor');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparserusesconstructedelementexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element-expected.txt (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element-expected.txt        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+
+PASS HTML parser must use the returned value of the custom element constructor instead of the one created before super() call 
+PASS HTML parser must use the returned value of the custom element constructor instead using the one created in super() call 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcustomelementsparserparserusesconstructedelementhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element.html (0 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element.html                                (rev 0)
+++ trunk/LayoutTests/fast/custom-elements/parser/parser-uses-constructed-element.html        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;Custom Elements: Changes to the HTML parser&lt;/title&gt;
+&lt;meta name=&quot;author&quot; title=&quot;Ryosuke Niwa&quot; href=&quot;mailto:rniwa@webkit.org&quot;&gt;
+&lt;meta name=&quot;assert&quot; content=&quot;HTML parser must construct a custom element instead of upgrading&quot;&gt;
+&lt;script src=&quot;../../../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;link rel='stylesheet' href='../../../resources/testharness.css'&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+let anotherElementCreatedBeforeSuperCall = undefined;
+let elementCreatedBySuperCall = undefined;
+let shouldCreateElementBeforeSuperCall = true;
+class InstantiatesItselfBeforeSuper extends HTMLElement {
+    constructor() {
+        if (shouldCreateElementBeforeSuperCall) {
+            shouldCreateElementBeforeSuperCall = false;
+            anotherElementCreatedBeforeSuperCall = new InstantiatesItselfBeforeSuper();
+        }
+        super();
+        elementCreatedBySuperCall = this;
+    }
+};
+document.defineCustomElement('instantiates-itself-before-super', InstantiatesItselfBeforeSuper);
+
+let shouldCreateAnotherInstance = true;
+let anotherInstance = undefined;
+let firstInstance = undefined;
+class ReturnsAnotherInstance extends HTMLElement {
+    constructor() {
+        super();
+        if (shouldCreateAnotherInstance) {
+            shouldCreateAnotherInstance = false;
+            firstInstance = this;
+            anotherInstance = new ReturnsAnotherInstance;
+            return anotherInstance;
+        } else
+            return this;
+    }
+};
+document.defineCustomElement('returns-another-instance', ReturnsAnotherInstance);
+
+&lt;/script&gt;
+&lt;instantiates-itself-before-super&gt;&lt;/instantiates-itself-before-super&gt;
+&lt;returns-another-instance&gt;&lt;/returns-another-instance&gt;
+&lt;script&gt;
+
+test(function () {
+    var instance = document.querySelector('instantiates-itself-before-super');
+
+    assert_equals(instance, elementCreatedBySuperCall, 'HTML parser must insert the element returned by the custom element constructor');
+    assert_not_equals(instance, anotherElementCreatedBeforeSuperCall, 'HTML parser must not insert another instance of the custom element created before super() call');
+    assert_equals(anotherElementCreatedBeforeSuperCall.parentNode, null, 'HTML parser must not insert another instance of the custom element created before super() call');
+
+}, 'HTML parser must use the returned value of the custom element constructor instead of the one created before super() call');
+
+test(function () {
+    var instance = document.querySelector('returns-another-instance');
+
+    assert_equals(instance, anotherInstance, 'HTML parser must insert the element returned by the custom element constructor');
+    assert_not_equals(instance, firstInstance, 'HTML parser must not insert the element created by super() call if the constructor returned another element');
+    assert_equals(firstInstance.parentNode, null, 'HTML parser must not insert the element created by super() call if the constructor returned another element');
+
+}, 'HTML parser must use the returned value of the custom element constructor instead using the one created in super() call');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/ChangeLog        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -1,3 +1,80 @@
</span><ins>+2016-03-01  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Make HTML parser construct custom elements
+        https://bugs.webkit.org/show_bug.cgi?id=154908
+        &lt;rdar://problem/24923735&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Added the support for instantiating custom elements inside the parser. Based on Jan F2F discussion,
+        the HTML parser is going to synchronously construct custom elements. When a custom element constructor
+        throws, the HTML parser creates a HTMLUnknownElement instead.
+
+        In our implementation, we pause the parser completely and construct custom elements using the same
+        mechanism used to run author scripts. It's possible that we may want to apply some optimizations to
+        to make custom element construction but it's probably a good idea to get semantics right first.
+
+        Tests: fast/custom-elements/parser/parser-constructs-custom-elements.html
+               fast/custom-elements/parser/parser-fallsback-to-unknown-element.html
+               fast/custom-elements/parser/parser-sets-attributes-and-children.html
+               fast/custom-elements/parser/parser-uses-constructed-element.html
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::constructElement): Added ShouldClearException as an argument
+        to be used by the HTML parser since the parser can't re-throw to anywhere or fail parsing.
+
+        * bindings/js/JSCustomElementInterface.h:
+        (WebCore::JSCustomElementInterface::ShouldClearException): Added.
+
+        * dom/Document.cpp:
+        (WebCore::createHTMLElementWithNameValidation): Do not clear the exception here since createElement
+        must re-throw the exception thrown by a custom element constructor.
+        (WebCore::Document::createElementForBindings):
+
+        * dom/make_names.pl:
+        (printFactoryCppFile): Added ConstructorFunctionMapEntry which contains the constructor function
+        as well as the qualified name.
+        (printFactoryHeaderFile): Added a variant of createKnownElement and createElement that takes
+        AtomicString instead of QualifiedName.
+
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::setAttributes): Added a variant that takes Vector&lt;Attribute&gt;.
+        (WebCore::HTMLConstructionSite::insertHTMLElementOrFindCustomElementInterface): Added. Returns a
+        custom element interface when the element doesn't match any builtin element and there is a custom
+        element definition that matches the specified name.
+        (WebCore::HTMLConstructionSite::insertCustomElement): Added. Like insertElement but also sets the
+        attributes on the newly created custom element.
+        (WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Extracted from
+        createHTMLElement. When customElementInterface is not nullptr, we optionally find the custom
+        element interface and return nullptr.
+        (WebCore::HTMLConstructionSite::createHTMLElement):
+        * html/parser/HTMLConstructionSite.h:
+
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder): Create a custom element when there
+        is a pending custom element to create (i.e. m_customElementToConstruct is not empty).
+        (WebCore::HTMLDocumentParser::isWaitingForScripts):
+
+        * html/parser/HTMLStackItem.h:
+        (WebCore::HTMLStackItem::create): Added a variant used for custom elements.
+        (WebCore::HTMLStackItem::HTMLStackItem): Ditto.
+
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::CustomElementConstructionData::CustomElementConstructionData): Added. It needs to be in
+        the cpp file to avoid introducing more header dependencies in HTMLTreeBuilder.h.
+        (WebCore::CustomElementConstructionData::~CustomElementConstructionData): Ditto.
+        (WebCore::HTMLTreeBuilder::processStartTagForInBody): Use insertGenericHTMLElement when creating
+        a generic element that could be custom elements.
+        (WebCore::HTMLTreeBuilder::insertGenericHTMLElement): Added. Create and insert a new element
+        or set m_customElementToConstruct so that the HTMLDocumentParser will create a custom element later.
+        (WebCore::HTMLTreeBuilder::didCreateCustomOrCallbackElement): Added. Called by HTMLDocumentParser
+        when it finishes creating a new custom element.
+
+        * html/parser/HTMLTreeBuilder.h:
+        (WebCore::HTMLTreeBuilder::takeCustomElementConstructionData): Added.
+        (WebCore::HTMLTreeBuilder::hasParserBlockingScriptWork): Renamed from hasParserBlockingScript.
+        Checks the existence of m_customElementToConstruct as well as m_scriptToProcess.
+
</ins><span class="cx"> 2016-03-02  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use IndentTextOrNot instead of passing isFirstLine/shouldIndentText as bool.
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;Element&gt; JSCustomElementInterface::constructElement(const AtomicString&amp; tagName)
</del><ins>+RefPtr&lt;Element&gt; JSCustomElementInterface::constructElement(const AtomicString&amp; tagName, ShouldClearException shouldClearException)
</ins><span class="cx"> {
</span><span class="cx">     if (!canInvokeCallback())
</span><span class="cx">         return nullptr;
</span><span class="lines">@@ -88,6 +88,9 @@
</span><span class="cx">     JSValue newElement = construct(state, m_constructor.get(), constructType, constructData, args);
</span><span class="cx">     InspectorInstrumentation::didCallFunction(cookie, context);
</span><span class="cx"> 
</span><ins>+    if (shouldClearException == ShouldClearException::Clear &amp;&amp; state-&gt;hadException())
+        state-&gt;clearException();
+
</ins><span class="cx">     if (newElement.isEmpty())
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSCustomElementInterfaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -59,7 +59,8 @@
</span><span class="cx">         return adoptRef(*new JSCustomElementInterface(callback, globalObject));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    RefPtr&lt;Element&gt; constructElement(const AtomicString&amp;);
</del><ins>+    enum class ShouldClearException { Clear, DoNotClear };
+    RefPtr&lt;Element&gt; constructElement(const AtomicString&amp;, ShouldClearException);
</ins><span class="cx"> 
</span><span class="cx">     ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
</span><span class="cx">     JSC::JSObject* constructor() { return m_constructor.get(); }
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -879,35 +879,35 @@
</span><span class="cx">     clearStyleResolver();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static RefPtr&lt;Element&gt; createHTMLElementWithNameValidation(Document&amp; document, const QualifiedName qualifiedName, ExceptionCode&amp; ec)
</del><ins>+static RefPtr&lt;Element&gt; createHTMLElementWithNameValidation(Document&amp; document, const AtomicString&amp; localName, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    RefPtr&lt;HTMLElement&gt; element = HTMLElementFactory::createKnownElement(qualifiedName, document);
</del><ins>+    RefPtr&lt;HTMLElement&gt; element = HTMLElementFactory::createKnownElement(localName, document);
</ins><span class="cx">     if (LIKELY(element))
</span><span class="cx">         return element;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CUSTOM_ELEMENTS)
</span><span class="cx">     auto* definitions = document.customElementDefinitions();
</span><span class="cx">     if (UNLIKELY(definitions)) {
</span><del>-        if (auto* interface = definitions-&gt;findInterface(qualifiedName))
-            return interface-&gt;constructElement(qualifiedName.localName());
</del><ins>+        if (auto* interface = definitions-&gt;findInterface(localName))
+            return interface-&gt;constructElement(localName, JSCustomElementInterface::ShouldClearException::DoNotClear);
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(!Document::isValidName(qualifiedName.localName()))) {
</del><ins>+    if (UNLIKELY(!Document::isValidName(localName))) {
</ins><span class="cx">         ec = INVALID_CHARACTER_ERR;
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return HTMLUnknownElement::create(qualifiedName, document);
</del><ins>+    return HTMLUnknownElement::create(QualifiedName(nullAtom, localName, xhtmlNamespaceURI), document);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;Element&gt; Document::createElementForBindings(const AtomicString&amp; name, ExceptionCode&amp; ec)
</span><span class="cx"> {
</span><span class="cx">     if (isHTMLDocument())
</span><del>-        return createHTMLElementWithNameValidation(*this, QualifiedName(nullAtom, name.convertToASCIILowercase(), xhtmlNamespaceURI), ec);
</del><ins>+        return createHTMLElementWithNameValidation(*this, name.convertToASCIILowercase(), ec);
</ins><span class="cx"> 
</span><span class="cx">     if (isXHTMLDocument())
</span><del>-        return createHTMLElementWithNameValidation(*this, QualifiedName(nullAtom, name, xhtmlNamespaceURI), ec);
</del><ins>+        return createHTMLElementWithNameValidation(*this, name, ec);
</ins><span class="cx"> 
</span><span class="cx">     if (!isValidName(name)) {
</span><span class="cx">         ec = INVALID_CHARACTER_ERR;
</span></span></pre></div>
<a id="trunkSourceWebCoredommake_namespl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/make_names.pl (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/make_names.pl        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/dom/make_names.pl        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -986,10 +986,28 @@
</span><span class="cx">         $argumentList = &quot;name, document, createdByParser&quot;;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    my $lowercaseNamespacePrefix = lc($parameters{namespacePrefix});
+
</ins><span class="cx">     printConstructors($F, \%tagConstructorMap);
</span><span class="cx"> 
</span><span class="cx">     print F &lt;&lt;END
</span><del>-static NEVER_INLINE void populate$parameters{namespace}FactoryMap(HashMap&lt;AtomicStringImpl*, $parameters{namespace}ConstructorFunction&gt;&amp; map)
</del><ins>+
+struct ConstructorFunctionMapEntry {
+    ConstructorFunctionMapEntry($parameters{namespace}ConstructorFunction function, const QualifiedName&amp; name)
+        : function(function)
+        , qualifiedName(&amp;name)
+    { }
+
+    ConstructorFunctionMapEntry()
+        : function(nullptr)
+        , qualifiedName(nullptr)
+    { }
+
+    $parameters{namespace}ConstructorFunction function;
+    const QualifiedName* qualifiedName; // Use pointer instead of reference so that emptyValue() in HashMap is cheap to create.
+};
+
+static NEVER_INLINE void populate$parameters{namespace}FactoryMap(HashMap&lt;AtomicStringImpl*, ConstructorFunctionMapEntry&gt;&amp; map)
</ins><span class="cx"> {
</span><span class="cx">     struct TableEntry {
</span><span class="cx">         const QualifiedName&amp; name;
</span><span class="lines">@@ -1006,25 +1024,42 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; i &lt; WTF_ARRAY_LENGTH(table); ++i)
</span><del>-        map.add(table[i].name.localName().impl(), table[i].function);
</del><ins>+        map.add(table[i].name.localName().impl(), ConstructorFunctionMapEntry(table[i].function, table[i].name));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createKnownElement(const QualifiedName&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
</del><ins>+
+static ConstructorFunctionMapEntry find$parameters{namespace}ElementConstructorFunction(const AtomicString&amp; localName)
</ins><span class="cx"> {
</span><del>-    static NeverDestroyed&lt;HashMap&lt;AtomicStringImpl*, $parameters{namespace}ConstructorFunction&gt;&gt; functions;
-    if (functions.get().isEmpty())
-        populate$parameters{namespace}FactoryMap(functions);
-    $parameters{namespace}ConstructorFunction function = functions.get().get(name.localName().impl());
-    if (LIKELY(function))
-        return function($argumentList);
</del><ins>+    static NeverDestroyed&lt;HashMap&lt;AtomicStringImpl*, ConstructorFunctionMapEntry&gt;&gt; map;
+    if (map.get().isEmpty())
+        populate$parameters{namespace}FactoryMap(map);
+    return map.get().get(localName.impl());
+}
+
+RefPtr&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createKnownElement(const AtomicString&amp; localName, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
+{
+    const ConstructorFunctionMapEntry&amp; entry = find$parameters{namespace}ElementConstructorFunction(localName);
+    if (LIKELY(entry.function)) {
+        ASSERT(entry.qualifiedName);
+        const auto&amp; name = *entry.qualifiedName;
+        return entry.function($argumentList);
+    }
</ins><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createElement(const QualifiedName&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
</del><ins>+Ref&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createElement(const AtomicString&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr&lt;$parameters{namespace}Element&gt; element = $parameters{namespace}ElementFactory::createKnownElement($argumentList);
</span><span class="cx">     if (LIKELY(element))
</span><span class="cx">         return element.releaseNonNull();
</span><ins>+    return $parameters{fallbackInterfaceName}::create(QualifiedName(nullAtom, name, ${lowercaseNamespacePrefix}NamespaceURI), document);
+}
+
+Ref&lt;$parameters{namespace}Element&gt; $parameters{namespace}ElementFactory::createElement(const QualifiedName&amp; name, Document&amp; document$formElementArgumentForDefinition, bool createdByParser)
+{
+    const ConstructorFunctionMapEntry&amp; entry = find$parameters{namespace}ElementConstructorFunction(name.localName());
+    if (LIKELY(entry.function))
+        return entry.function($argumentList);
</ins><span class="cx">     return $parameters{fallbackInterfaceName}::create(name, document);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1065,12 +1100,15 @@
</span><span class="cx"> END
</span><span class="cx"> ;
</span><span class="cx"> 
</span><del>-print F &quot;        static RefPtr&lt;$parameters{namespace}Element&gt; createKnownElement(const QualifiedName&amp;, Document&amp;&quot;;
</del><ins>+print F &quot;        static RefPtr&lt;$parameters{namespace}Element&gt; createKnownElement(const AtomicString&amp; localName, Document&amp;&quot;;
</ins><span class="cx"> print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
</span><span class="cx"> print F &quot;, bool createdByParser = false);\n\n&quot;;
</span><del>-print F &quot;        static Ref&lt;$parameters{namespace}Element&gt; createElement(const QualifiedName&amp;, Document&amp;&quot;;
</del><ins>+print F &quot;        static Ref&lt;$parameters{namespace}Element&gt; createElement(const AtomicString&amp; localName, Document&amp;&quot;;
</ins><span class="cx"> print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
</span><span class="cx"> print F &quot;, bool createdByParser = false);\n&quot;;
</span><ins>+print F &quot;        static Ref&lt;$parameters{namespace}Element&gt; createElement(const QualifiedName&amp; localName, Document&amp;&quot;;
+print F &quot;, HTMLFormElement* = nullptr&quot; if $parameters{namespace} eq &quot;HTML&quot;;
+print F &quot;, bool createdByParser = false);\n&quot;;
</ins><span class="cx"> 
</span><span class="cx"> printf F&lt;&lt;END
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLConstructionSitecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;HTMLTreeBuilder.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Comment.h&quot;
</span><ins>+#include &quot;CustomElementDefinitions.h&quot;
</ins><span class="cx"> #include &quot;DocumentFragment.h&quot;
</span><span class="cx"> #include &quot;DocumentType.h&quot;
</span><span class="cx"> #include &quot;Frame.h&quot;
</span><span class="lines">@@ -43,6 +44,7 @@
</span><span class="cx"> #include &quot;HTMLPictureElement.h&quot;
</span><span class="cx"> #include &quot;HTMLScriptElement.h&quot;
</span><span class="cx"> #include &quot;HTMLTemplateElement.h&quot;
</span><ins>+#include &quot;HTMLUnknownElement.h&quot;
</ins><span class="cx"> #include &quot;NotImplemented.h&quot;
</span><span class="cx"> #include &quot;SVGElement.h&quot;
</span><span class="cx"> #include &quot;Text.h&quot;
</span><span class="lines">@@ -51,13 +53,18 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace HTMLNames;
</span><span class="cx"> 
</span><del>-static inline void setAttributes(Element&amp; element, AtomicHTMLToken* token, ParserContentPolicy parserContentPolicy)
</del><ins>+static inline void setAttributes(Element&amp; element, Vector&lt;Attribute&gt;&amp; attributes, ParserContentPolicy parserContentPolicy)
</ins><span class="cx"> {
</span><span class="cx">     if (!scriptingContentIsAllowed(parserContentPolicy))
</span><del>-        element.stripScriptingAttributes(token-&gt;attributes());
-    element.parserSetAttributes(token-&gt;attributes());
</del><ins>+        element.stripScriptingAttributes(attributes);
+    element.parserSetAttributes(attributes);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline void setAttributes(Element&amp; element, AtomicHTMLToken* token, ParserContentPolicy parserContentPolicy)
+{
+    setAttributes(element, token-&gt;attributes(), parserContentPolicy);
+}
+
</ins><span class="cx"> static bool hasImpliedEndTag(const HTMLStackItem&amp; item)
</span><span class="cx"> {
</span><span class="cx">     return item.hasTagName(ddTag)
</span><span class="lines">@@ -482,6 +489,26 @@
</span><span class="cx">     m_openElements.push(HTMLStackItem::create(element.releaseNonNull(), *token));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+JSCustomElementInterface* HTMLConstructionSite::insertHTMLElementOrFindCustomElementInterface(AtomicHTMLToken* token)
+{
+    JSCustomElementInterface* interface = nullptr;
+    RefPtr&lt;Element&gt; element = createHTMLElementOrFindCustomElementInterface(token, &amp;interface);
+    if (UNLIKELY(interface))
+        return interface;
+    attachLater(&amp;currentNode(), element);
+    m_openElements.push(HTMLStackItem::create(element.releaseNonNull(), *token));
+    return nullptr;
+}
+
+void HTMLConstructionSite::insertCustomElement(Ref&lt;Element&gt;&amp;&amp; element, const AtomicString&amp; localName, Vector&lt;Attribute&gt;&amp; attributes)
+{
+    setAttributes(element.get(), attributes, m_parserContentPolicy);
+    attachLater(&amp;currentNode(), element.ptr());
+    m_openElements.push(HTMLStackItem::create(WTFMove(element), localName, attributes));
+}
+#endif
+
</ins><span class="cx"> void HTMLConstructionSite::insertSelfClosingHTMLElement(AtomicHTMLToken* token)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(token-&gt;type() == HTMLToken::StartTag);
</span><span class="lines">@@ -633,28 +660,53 @@
</span><span class="cx">     return currentNode().document();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref&lt;Element&gt; HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token)
</del><ins>+RefPtr&lt;Element&gt; HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface(
+    AtomicHTMLToken* token, JSCustomElementInterface** customElementInterface)
</ins><span class="cx"> {
</span><del>-    QualifiedName tagName(nullAtom, token-&gt;name(), xhtmlNamespaceURI);
</del><ins>+    auto&amp; localName = token-&gt;name();
</ins><span class="cx">     // FIXME: This can't use HTMLConstructionSite::createElement because we
</span><span class="cx">     // have to pass the current form element.  We should rework form association
</span><span class="cx">     // to occur after construction to allow better code sharing here.
</span><span class="cx">     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#create-an-element-for-the-token
</span><span class="cx">     Document&amp; ownerDocument = ownerDocumentForCurrentNode();
</span><span class="cx">     bool insideTemplateElement = !ownerDocument.frame();
</span><del>-    Ref&lt;Element&gt; element = HTMLElementFactory::createElement(tagName, ownerDocument, insideTemplateElement ? nullptr : form(), true);
-    
</del><ins>+    RefPtr&lt;Element&gt; element = HTMLElementFactory::createKnownElement(localName, ownerDocument, insideTemplateElement ? nullptr : form(), true);
+    if (UNLIKELY(!element)) {
+
+#if ENABLE(CUSTOM_ELEMENTS)
+        auto* definitions = ownerDocumentForCurrentNode().customElementDefinitions();
+        if (customElementInterface &amp;&amp; UNLIKELY(definitions)) {
+            if (auto* interface = definitions-&gt;findInterface(localName)) {
+                *customElementInterface = interface;
+                return nullptr;
+            }
+        }
+#else
+        UNUSED_PARAM(customElementInterface);
+#endif
+
+        element = HTMLUnknownElement::create(QualifiedName(nullAtom, localName, xhtmlNamespaceURI), ownerDocumentForCurrentNode());
+    }
+    ASSERT(element);
+
</ins><span class="cx">     // FIXME: This is a hack to connect images to pictures before the image has
</span><span class="cx">     // been inserted into the document. It can be removed once asynchronous image
</span><span class="cx">     // loading is working.
</span><del>-    if (is&lt;HTMLPictureElement&gt;(currentNode()) &amp;&amp; is&lt;HTMLImageElement&gt;(element))
-        downcast&lt;HTMLImageElement&gt;(element.get()).setPictureElement(&amp;downcast&lt;HTMLPictureElement&gt;(currentNode()));
</del><ins>+    if (is&lt;HTMLPictureElement&gt;(currentNode()) &amp;&amp; is&lt;HTMLImageElement&gt;(*element))
+        downcast&lt;HTMLImageElement&gt;(*element).setPictureElement(&amp;downcast&lt;HTMLPictureElement&gt;(currentNode()));
</ins><span class="cx"> 
</span><del>-    setAttributes(element.get(), token, m_parserContentPolicy);
</del><ins>+    setAttributes(*element, token, m_parserContentPolicy);
</ins><span class="cx">     ASSERT(element-&gt;isHTMLElement());
</span><span class="cx">     return element;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Ref&lt;Element&gt; HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token)
+{
+    RefPtr&lt;Element&gt; element = createHTMLElementOrFindCustomElementInterface(token, nullptr);
+    ASSERT(element);
+    return element.releaseNonNull();
+}
+
</ins><span class="cx"> Ref&lt;HTMLStackItem&gt; HTMLConstructionSite::createElementFromSavedToken(HTMLStackItem* item)
</span><span class="cx"> {
</span><span class="cx">     // NOTE: Moving from item -&gt; token -&gt; item copies the Attribute vector twice!
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLConstructionSiteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLConstructionSite.h (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLConstructionSite.h        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/html/parser/HTMLConstructionSite.h        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -84,6 +84,7 @@
</span><span class="cx"> class Document;
</span><span class="cx"> class Element;
</span><span class="cx"> class HTMLFormElement;
</span><ins>+class JSCustomElementInterface;
</ins><span class="cx"> 
</span><span class="cx"> class HTMLConstructionSite {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(HTMLConstructionSite);
</span><span class="lines">@@ -103,6 +104,10 @@
</span><span class="cx">     void insertCommentOnDocument(AtomicHTMLToken*);
</span><span class="cx">     void insertCommentOnHTMLHtmlElement(AtomicHTMLToken*);
</span><span class="cx">     void insertHTMLElement(AtomicHTMLToken*);
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+    JSCustomElementInterface* insertHTMLElementOrFindCustomElementInterface(AtomicHTMLToken*);
+    void insertCustomElement(Ref&lt;Element&gt;&amp;&amp;, const AtomicString&amp; localName, Vector&lt;Attribute&gt;&amp;);
+#endif
</ins><span class="cx">     void insertSelfClosingHTMLElement(AtomicHTMLToken*);
</span><span class="cx">     void insertFormattingElement(AtomicHTMLToken*);
</span><span class="cx">     void insertHTMLHeadElement(AtomicHTMLToken*);
</span><span class="lines">@@ -194,6 +199,7 @@
</span><span class="cx"> 
</span><span class="cx">     void findFosterSite(HTMLConstructionSiteTask&amp;);
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;Element&gt; createHTMLElementOrFindCustomElementInterface(AtomicHTMLToken*, JSCustomElementInterface**);
</ins><span class="cx">     Ref&lt;Element&gt; createHTMLElement(AtomicHTMLToken*);
</span><span class="cx">     Ref&lt;Element&gt; createElement(AtomicHTMLToken*, const AtomicString&amp; namespaceURI);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLDocumentParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx"> #include &quot;HTMLPreloadScanner.h&quot;
</span><span class="cx"> #include &quot;HTMLScriptRunner.h&quot;
</span><span class="cx"> #include &quot;HTMLTreeBuilder.h&quot;
</span><ins>+#include &quot;HTMLUnknownElement.h&quot;
+#include &quot;JSCustomElementInterface.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -188,8 +190,24 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(scriptingContentIsAllowed(parserContentPolicy()));
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+    if (std::unique_ptr&lt;CustomElementConstructionData&gt; constructionData = m_treeBuilder-&gt;takeCustomElementConstructionData()) {
+        ASSERT(!m_treeBuilder-&gt;hasParserBlockingScriptWork());
+
+        RefPtr&lt;Element&gt; newElement = constructionData-&gt;interface-&gt;constructElement(constructionData-&gt;name, JSCustomElementInterface::ShouldClearException::Clear);
+        if (!newElement) {
+            // FIXME: This call to docuemnt() is wrong for elements inside a template element.
+            newElement = HTMLUnknownElement::create(QualifiedName(nullAtom, constructionData-&gt;name, xhtmlNamespaceURI), *document());
+        }
+
+        m_treeBuilder-&gt;didCreateCustomOrCallbackElement(newElement.releaseNonNull(), *constructionData);
+        return;
+    }
+#endif
+
</ins><span class="cx">     TextPosition scriptStartPosition = TextPosition::belowRangePosition();
</span><span class="cx">     if (auto scriptElement = m_treeBuilder-&gt;takeScriptToProcess(scriptStartPosition)) {
</span><ins>+        ASSERT(!m_treeBuilder-&gt;hasParserBlockingScriptWork());
</ins><span class="cx">         // We will not have a scriptRunner when parsing a DocumentFragment.
</span><span class="cx">         if (m_scriptRunner)
</span><span class="cx">             m_scriptRunner-&gt;execute(scriptElement.release(), scriptStartPosition);
</span><span class="lines">@@ -459,7 +477,7 @@
</span><span class="cx">     // The script runner will hold the script until its loaded and run. During
</span><span class="cx">     // any of this time, we want to count ourselves as &quot;waiting for a script&quot; and thus
</span><span class="cx">     // run the preload scanner, as well as delay completion of parsing.
</span><del>-    bool treeBuilderHasBlockingScript = m_treeBuilder-&gt;hasParserBlockingScript();
</del><ins>+    bool treeBuilderHasBlockingScript = m_treeBuilder-&gt;hasParserBlockingScriptWork();
</ins><span class="cx">     bool scriptRunnerHasBlockingScript = m_scriptRunner &amp;&amp; m_scriptRunner-&gt;hasParserBlockingScript();
</span><span class="cx">     // Since the parser is paused while a script runner has a blocking script, it should
</span><span class="cx">     // never be possible to end up with both objects holding a blocking script.
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLStackItemh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLStackItem.h (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLStackItem.h        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/html/parser/HTMLStackItem.h        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> public:
</span><span class="cx">     // Normal HTMLElementStack and HTMLFormattingElementList items.
</span><span class="cx">     static Ref&lt;HTMLStackItem&gt; create(Ref&lt;Element&gt;&amp;&amp;, AtomicHTMLToken&amp;, const AtomicString&amp; namespaceURI = HTMLNames::xhtmlNamespaceURI);
</span><ins>+    static Ref&lt;HTMLStackItem&gt; create(Ref&lt;Element&gt;&amp;&amp;, const AtomicString&amp;, const Vector&lt;Attribute&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // Document fragment or element for parsing context.
</span><span class="cx">     static Ref&lt;HTMLStackItem&gt; create(Element&amp;);
</span><span class="lines">@@ -62,6 +63,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     HTMLStackItem(Ref&lt;Element&gt;&amp;&amp;, AtomicHTMLToken&amp;, const AtomicString&amp; namespaceURI);
</span><ins>+    HTMLStackItem(Ref&lt;Element&gt;&amp;&amp;, const AtomicString&amp; localName, const AtomicString&amp; namespaceURI, const Vector&lt;Attribute&gt;&amp;);
</ins><span class="cx">     explicit HTMLStackItem(Element&amp;);
</span><span class="cx">     explicit HTMLStackItem(DocumentFragment&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -89,6 +91,21 @@
</span><span class="cx">     return adoptRef(*new HTMLStackItem(WTFMove(element), token, namespaceURI));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline HTMLStackItem::HTMLStackItem(Ref&lt;Element&gt;&amp;&amp; element, const AtomicString&amp; localName, const AtomicString&amp; namespaceURI, const Vector&lt;Attribute&gt;&amp; attributes)
+    : m_node(WTFMove(element))
+    , m_namespaceURI(namespaceURI)
+    , m_localName(localName)
+    , m_attributes(attributes)
+{
+    // FIXME: We should find a way to move the attributes vector in the normal code path instead of copying it.
+}
+
+inline Ref&lt;HTMLStackItem&gt; HTMLStackItem::create(Ref&lt;Element&gt;&amp;&amp; element, const AtomicString&amp; localName, const Vector&lt;Attribute&gt;&amp; attributes)
+{
+    auto&amp; namespaceURI = element.get().namespaceURI();
+    return adoptRef(*new HTMLStackItem(WTFMove(element), localName, namespaceURI, attributes));
+}
+
</ins><span class="cx"> inline HTMLStackItem::HTMLStackItem(Element&amp; element)
</span><span class="cx">     : m_node(element)
</span><span class="cx">     , m_namespaceURI(element.namespaceURI())
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLTreeBuildercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;HTMLFormElement.h&quot;
</span><span class="cx"> #include &quot;HTMLOptGroupElement.h&quot;
</span><span class="cx"> #include &quot;HTMLParserIdioms.h&quot;
</span><ins>+#include &quot;JSCustomElementInterface.h&quot;
</ins><span class="cx"> #include &quot;LocalizedStrings.h&quot;
</span><span class="cx"> #include &quot;NotImplemented.h&quot;
</span><span class="cx"> #include &quot;XLinkNames.h&quot;
</span><span class="lines">@@ -50,6 +51,19 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace HTMLNames;
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+
+CustomElementConstructionData::CustomElementConstructionData(Ref&lt;JSCustomElementInterface&gt;&amp;&amp; interface, const AtomicString&amp; name, const Vector&lt;Attribute&gt;&amp; attributes)
+    : interface(WTFMove(interface))
+    , name(name)
+    , attributes(attributes) // FIXME: Avoid copying attributes.
+{ }
+
+CustomElementConstructionData::~CustomElementConstructionData()
+{ }
+
+#endif
+
</ins><span class="cx"> namespace {
</span><span class="cx"> 
</span><span class="cx"> inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
</span><span class="lines">@@ -896,9 +910,27 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     m_tree.reconstructTheActiveFormattingElements();
</span><ins>+    insertGenericHTMLElement(token);
+}
+
+inline void HTMLTreeBuilder::insertGenericHTMLElement(AtomicHTMLToken&amp; token)
+{
+#if ENABLE(CUSTOM_ELEMENTS)
+    auto* interface = m_tree.insertHTMLElementOrFindCustomElementInterface(&amp;token);
+    if (UNLIKELY(interface))
+        m_customElementToConstruct = std::make_unique&lt;CustomElementConstructionData&gt;(*interface, token.name(), token.attributes());
+#else
</ins><span class="cx">     m_tree.insertHTMLElement(&amp;token);
</span><ins>+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+void HTMLTreeBuilder::didCreateCustomOrCallbackElement(Ref&lt;Element&gt;&amp;&amp; element, CustomElementConstructionData&amp; data)
+{
+    m_tree.insertCustomElement(WTFMove(element), data.name, data.attributes);
+}
+#endif
+
</ins><span class="cx"> #if ENABLE(TEMPLATE_ELEMENT)
</span><span class="cx"> 
</span><span class="cx"> void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken&amp; token)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLTreeBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h (197462 => 197463)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h        2016-03-02 21:42:22 UTC (rev 197462)
+++ trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h        2016-03-02 21:56:47 UTC (rev 197463)
</span><span class="lines">@@ -34,8 +34,20 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class JSCustomElementInterface;
</ins><span class="cx"> class HTMLDocumentParser;
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+struct CustomElementConstructionData {
+    CustomElementConstructionData(Ref&lt;JSCustomElementInterface&gt;&amp;&amp;, const AtomicString&amp; name, const Vector&lt;Attribute&gt;&amp;);
+    ~CustomElementConstructionData();
+
+    Ref&lt;JSCustomElementInterface&gt; interface;
+    AtomicString name;
+    Vector&lt;Attribute&gt; attributes;
+};
+#endif
+
</ins><span class="cx"> class HTMLTreeBuilder {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -49,11 +61,16 @@
</span><span class="cx"> 
</span><span class="cx">     void constructTree(AtomicHTMLToken&amp;);
</span><span class="cx"> 
</span><del>-    bool hasParserBlockingScript() const;
</del><ins>+    bool hasParserBlockingScriptWork() const;
</ins><span class="cx"> 
</span><span class="cx">     // Must be called to take the parser-blocking script before calling the parser again.
</span><span class="cx">     RefPtr&lt;Element&gt; takeScriptToProcess(TextPosition&amp; scriptStartPosition);
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+    std::unique_ptr&lt;CustomElementConstructionData&gt; takeCustomElementConstructionData() { return WTFMove(m_customElementToConstruct); }
+    void didCreateCustomOrCallbackElement(Ref&lt;Element&gt;&amp;&amp;, CustomElementConstructionData&amp;);
+#endif
+
</ins><span class="cx">     // Done, close any open tags, etc.
</span><span class="cx">     void finished();
</span><span class="cx"> 
</span><span class="lines">@@ -165,6 +182,8 @@
</span><span class="cx"> 
</span><span class="cx">     void resetInsertionModeAppropriately();
</span><span class="cx"> 
</span><ins>+    void insertGenericHTMLElement(AtomicHTMLToken&amp;);
+
</ins><span class="cx"> #if ENABLE(TEMPLATE_ELEMENT)
</span><span class="cx">     void processTemplateStartTag(AtomicHTMLToken&amp;);
</span><span class="cx">     bool processTemplateEndTag(AtomicHTMLToken&amp;);
</span><span class="lines">@@ -204,6 +223,10 @@
</span><span class="cx">     RefPtr&lt;Element&gt; m_scriptToProcess; // &lt;script&gt; tag which needs processing before resuming the parser.
</span><span class="cx">     TextPosition m_scriptToProcessStartPosition; // Starting line number of the script tag needing processing.
</span><span class="cx"> 
</span><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+    std::unique_ptr&lt;CustomElementConstructionData&gt; m_customElementToConstruct;
+#endif
+
</ins><span class="cx">     bool m_shouldSkipLeadingNewline { false };
</span><span class="cx"> 
</span><span class="cx">     bool m_framesetOk { true };
</span><span class="lines">@@ -235,10 +258,15 @@
</span><span class="cx">     return !!m_fragmentContext.fragment();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool HTMLTreeBuilder::hasParserBlockingScript() const
</del><ins>+inline bool HTMLTreeBuilder::hasParserBlockingScriptWork() const
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_destroyed);
</span><del>-    return !!m_scriptToProcess;
</del><ins>+#if ENABLE(CUSTOM_ELEMENTS)
+    ASSERT(!(m_scriptToProcess &amp;&amp; m_customElementToConstruct));
+    return m_scriptToProcess || m_customElementToConstruct;
+#else
+    return m_scriptToProcess;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline DocumentFragment* HTMLTreeBuilder::FragmentParsingContext::fragment() const
</span></span></pre>
</div>
</div>

</body>
</html>