Skip to content

Commit

Permalink
Clear the custom element reaction queue if upgrading fails
Browse files Browse the repository at this point in the history
Fixes WICG/webcomponents#563, and an analogous
issue when the constructor uses return-override, by ensuring that all
exceptions go through the same path, which both sets the custom element
state to "failed", and clears the custom element reaction queue.
  • Loading branch information
domenic committed Sep 15, 2016
1 parent 73af751 commit d00b810
Showing 1 changed file with 43 additions and 41 deletions.
84 changes: 43 additions & 41 deletions source
Expand Up @@ -66692,62 +66692,64 @@ customElements.define("x-foo", class extends HTMLElement {
data-x="concept-custom-element-definition-constructor">constructor</span>.</p></li>

<li>
<p>Let <var>constructResult</var> be <span>Construct</span>(<var>C</var>).</p>
<p>Run the following substeps while catching any exceptions:</p>

<p class="note">If <var>C</var> <a href="#custom-element-conformance">non-conformantly</a> uses
an API decorated with the <code data-x="CEReactions">[CEReactions]</code> extended attribute,
then the reactions enqueued at the beginning of this algorithm will execute during this step,
before <var>C</var> finishes and control returns to this algorithm. Otherwise, they will execute
after <var>C</var> and the rest of the upgrade process finishes.</p>
</li>
<ol>
<li>
<p>Let <var>constructResult</var> be <span>Construct</span>(<var>C</var>).</p>

<li>
<p>Remove the last entry from the end of <var>definition</var>'s <span
data-x="concept-custom-element-definition-construction-stack">construction stack</span>.</p>
<p class="note">If <var>C</var> <a href="#custom-element-conformance">non-conformantly</a>
uses an API decorated with the <code data-x="CEReactions">[CEReactions]</code> extended
attribute, then the reactions enqueued at the beginning of this algorithm will execute during
this step, before <var>C</var> finishes and control returns to this algorithm. Otherwise, they
will execute after <var>C</var> and the rest of the upgrade process finishes.</p>
</li>

<div class="note">
<p>Assuming <var>C</var> calls <code data-x="">super()</code> (as it will if it is <a
href="#custom-element-conformance">conformant</a>), and that the call succeeds, this will be
the <span data-x="concept-already-constructed-marker"><i>already
constructed</i> marker</span> that replaced the <var>element</var> we pushed at the beginning
of this algorithm. (The <a href="#html-element-constructors">HTML element constructor</a>
carries out this replacement.)</p>

<p>If <var>C</var> does not call <code data-x="">super()</code> (i.e. it is not <a
href="#custom-element-conformance">conformant</a>), or if any step in the <a
href="#html-element-constructors">HTML element constructor</a> throws, then this entry will
still be <var>element</var>.</p>
</div>
</li>
<li>
<p>If <span>SameValue</span>(<var>constructResult</var>, <var>element</var>) is false,
then throw an <span>"<code>InvalidStateError</code>"</span> <code>DOMException</code>.</p>

<li>
<p>If <var>constructResult</var> is an abrupt completion, then:</p>
<p class="note">This can occur if <var>C</var> constructs another instance of the same custom
element before calling <code data-x="">super()</code>, or if <var>C</var> uses JavaScript's
<code data-x="">return</code>-override feature to return an arbitrary object from the
constructor.</p>
</li>
</ol>

<p>Then, perform the following substep, regardless of whether the above steps threw an exception
or not:</p>

<ol>
<li><p>Set <var>element</var>'s <span>custom element state</span> to "<code
data-x="">failed</code>".</p></li>
<li>
<p>Remove the last entry from the end of <var>definition</var>'s <span
data-x="concept-custom-element-definition-construction-stack">construction stack</span>.</p>

<li><p>Return <var>constructResult</var> (i.e., rethrow the exception), and terminate these
steps.</p></li>
<div class="note">
<p>Assuming <var>C</var> calls <code data-x="">super()</code> (as it will if it is <a
href="#custom-element-conformance">conformant</a>), and that the call succeeds, this will be
the <span data-x="concept-already-constructed-marker"><i>already
constructed</i> marker</span> that replaced the <var>element</var> we pushed at the beginning
of this algorithm. (The <a href="#html-element-constructors">HTML element constructor</a>
carries out this replacement.)</p>

<p>If <var>C</var> does not call <code data-x="">super()</code> (i.e. it is not <a
href="#custom-element-conformance">conformant</a>), or if any step in the <a
href="#html-element-constructors">HTML element constructor</a> throws, then this entry will
still be <var>element</var>.</p>
</div>
</li>
</ol>
</li>

<li>
<p>If <span>SameValue</span>(<var>constructResult</var>.[[value]], <var>element</var>) is false,
then:</p>
<p>Finally, if the above steps threw an exception, then:</p>

<ol>
<li><p>Set <var>element</var>'s <span>custom element state</span> to "<code
data-x="">failed</code>".</p></li>

<li><p>Throw an <span>"<code>InvalidStateError</code>"</span> <code>DOMException</code>, and
terminate these steps.</p></li>
</ol>
<li><p>Empty <var>element</var>'s <span>custom element reaction queue</span>.</p>

<p class="note">This can occur if <var>C</var> constructs another instance of the same custom
element before calling <code data-x="">super()</code>, or if <var>C</var> uses JavaScript's
<code data-x="">return</code>-override feature to return an arbitrary object from the
constructor.</p>
<li><p>Rethrow the exception, and terminate this algorithm.</p></li>
</ol>
</li>

<li><p>Set <var>element</var>'s <span>custom element state</span> to "<code
Expand Down

0 comments on commit d00b810

Please sign in to comment.