Skip to content

Commit a57c887

Browse files
authored
Take care of missing custom element reactions
As discussed in WICG/webcomponents#186, there are certain scenarios where custom element reactions could be enqueued, but the custom element reactions stack is empty. The most prominent of these is editing operations. We solve this issue in two parts: - First, introduce the backup element queue (similar to the old "base element queue" concept; see WICG/webcomponents#457). This takes care of cases like editing which cannot be solved in any other way. - Also, we mandate that [CEReactions] be applied to nonstandard APIs that modify the DOM, including a list of what we've identified so far. Closes WICG/webcomponents#186.
1 parent 688df43 commit a57c887

File tree

2 files changed

+113
-12
lines changed

2 files changed

+113
-12
lines changed

images/custom-element-reactions.svg

Lines changed: 38 additions & 5 deletions
Loading

source

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,6 +3104,7 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d
31043104
<li><dfn data-noexport="" data-x-href="https://dom.spec.whatwg.org/#interface-node"><code>Node</code></dfn> interface</li>
31053105
<li><dfn data-noexport="" data-x-href="https://dom.spec.whatwg.org/#interface-nodelist"><code>NodeList</code></dfn> interface</li>
31063106
<li><dfn data-noexport="" data-x-href="https://dom.spec.whatwg.org/#interface-processinginstruction"><code>ProcessingInstruction</code></dfn> interface</li>
3107+
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-shadowroot"><code>ShadowRoot</code></dfn> interface</li>
31073108
<li><dfn data-noexport="" data-x-href="https://dom.spec.whatwg.org/#interface-text"><code>Text</code></dfn> interface</li>
31083109

31093110
<li><dfn data-noexport="" data-x-href="https://dom.spec.whatwg.org/#concept-node-document">node document</dfn> concept</li>
@@ -66841,13 +66842,23 @@ customElements.define("x-foo", class extends HTMLElement {
6684166842
<hr>
6684266843

6684366844
<p>Each <span>unit of related similar-origin browsing contexts</span> has a <dfn>custom element
66844-
reactions stack</dfn>, which is initially empty. Each item in the stack is an <dfn>element
66845-
queue</dfn>, which is initially empty as well; the <span>element queue</span> at the top of the
66846-
stack is called the <dfn>current element queue</dfn>. Each item in an <span>element queue</span>
66847-
is an element. (The elements are not necessarily <span
66845+
reactions stack</dfn>, which is initially empty. The <dfn>current element queue</dfn> is the
66846+
<span>element queue</span> at the top of the <span>custom element reactions stack</span>. Each
66847+
item in the stack is an <dfn>element queue</dfn>, which is initially empty as well. Each item in
66848+
an <span>element queue</span> is an element. (The elements are not necessarily <span
6684866849
data-x="concept-element-custom">custom</span> yet, since this queue is used for <span
6684966850
data-x="custom-element-upgrades">upgrades</span> as well.)</p>
6685066851

66852+
<p>Each <span>custom element reactions stack</span> has an associated <dfn>backup element
66853+
queue</dfn>, which an initially-empty <span>element queue</span>. Elements are pushed onto the
66854+
<span>backup element queue</span> during operations that affect the DOM without going through an
66855+
API decorated with <code data-x="CEReactions">[CEReactions]</code>, or through the parser's
66856+
<span>create an element for the token</span> algorithm. An example of this is a user-initiated
66857+
editing operation which modifies the descendants or attributes of an <span>editable</span>
66858+
element. To prevent reentrancy when processing the <span>backup element queue</span>, each
66859+
<span>custom element reactions stack</span> also has a <dfn>processing the backup element
66860+
queue</dfn> flag, initially unset.</p>
66861+
6685166862
<p>All elements have an associated <dfn>custom element reaction queue</dfn>, initially empty. Each
6685266863
item in the <span>custom element reaction queue</span> is of one of two types:</p>
6685366864

@@ -66862,7 +66873,38 @@ customElements.define("x-foo", class extends HTMLElement {
6686266873

6686366874
<p>This is all summarised in the following schematic diagram:</p>
6686466875

66865-
<p><img src="/images/custom-element-reactions.svg" style="width: 80%; max-width: 560px;" alt="A custom elements reaction stack consists of a stack of element queues. Zooming in on a particular queue, we see that it contains a number of elements (in our example, &lt;x-a&gt;, then &lt;x-b&gt;, then &lt;x-c&gt;). Any particular element in the queue then has a custom element reaction queue. Zooming in on the custom element reaction queue, we see that it contains a variety of queued-up reactions (in our example, upgrade, then attribute changed, then another attribute changed, then connected)."></p>
66876+
<p><img src="/images/custom-element-reactions.svg" style="width: 80%; max-width: 580px;" alt="A custom element reactions stack consists of a stack of element queues. Zooming in on a particular queue, we see that it contains a number of elements (in our example, &lt;x-a&gt;, then &lt;x-b&gt;, then &lt;x-c&gt;). Any particular element in the queue then has a custom element reaction queue. Zooming in on the custom element reaction queue, we see that it contains a variety of queued-up reactions (in our example, upgrade, then attribute changed, then another attribute changed, then connected)."></p>
66877+
66878+
<p>To <dfn>enqueue an element on the appropriate element queue</dfn>, given an element
66879+
<var>element</var>, run the following steps:</p>
66880+
66881+
<ol>
66882+
<li>
66883+
<p>If the <span>custom element reactions stack</span> is empty, then:</p>
66884+
66885+
<ol>
66886+
<li><p>Add <var>element</var> to the <span>backup element queue</span>.</p></li>
66887+
66888+
<li><p>If the <span>processing the backup element queue</span> flag is set, abort this
66889+
algorithm.</p></li>
66890+
66891+
<li><p>Set the <span>processing the backup element queue</span> flag.</p></li>
66892+
66893+
<li>
66894+
<p><span>Queue a microtask</span> to perform the following steps:</p>
66895+
66896+
<ol>
66897+
<li><p><span>Invoke custom element reactions</span> in the <span>backup element
66898+
queue</span>.</p></li>
66899+
66900+
<li><p>Unset the <span>processing the backup element queue</span> flag.</p></li>
66901+
</ol>
66902+
</li>
66903+
</ol>
66904+
</li>
66905+
66906+
<li><p>Otherwise, add <var>element</var> to the <span>current element queue</span>.</p></li>
66907+
</ol>
6686666908

6686766909
<p>To <dfn data-export="">enqueue a custom element callback reaction</dfn>, given a <span>custom
6686866910
element</span> <var>element</var>, a callback name <var>callbackName</var>, and a list of
@@ -66903,7 +66945,8 @@ customElements.define("x-foo", class extends HTMLElement {
6690366945
reaction queue</span>, with callback function <var>callback</var> and arguments
6690466946
<var>args</var>.</p></li>
6690566947

66906-
<li><p>Add <var>element</var> to the <span>current element queue</span>.</p></li>
66948+
<li><p><span>Enqueue an element on the appropriate element queue</span> given
66949+
<var>element</var>.</p></li>
6690766950
</ol>
6690866951

6690966952
<p>To <dfn data-export="">enqueue a custom element upgrade reaction</dfn>, given an element
@@ -66915,7 +66958,8 @@ customElements.define("x-foo", class extends HTMLElement {
6691566958
reaction queue</span>, with <span>custom element definition</span>
6691666959
<var>definition</var>.</p></li>
6691766960

66918-
<li><p>Add <var>element</var> to the <span>current element queue</span>.</p></li>
66961+
<li><p><span>Enqueue an element on the appropriate element queue</span> given
66962+
<var>element</var>.</p></li>
6691966963
</ol>
6692066964

6692166965
<p>To <dfn>invoke custom element reactions</dfn> in an <span>element queue</span>
@@ -66999,6 +67043,30 @@ customElements.define("x-foo", class extends HTMLElement {
6699967043
and helping implementations easily pinpoint all cases where these steps are necessary.</p>
6700067044
</div>
6700167045

67046+
<p>Any nonstandard APIs introduced by the user agent that could modify the DOM in such a way as to
67047+
cause <span data-x="enqueue a custom element callback reaction">enqueuing a custom element
67048+
callback reaction</span> or <span data-x="enqueue a custom element upgrade reaction">enqueuing a
67049+
custom element upgrade reaction</span>, for example by modifying any attributes or child elements,
67050+
must also be decorated with the <code data-x="CEReactions">[CEReactions]</code> attribute.</p>
67051+
67052+
<div class="note">
67053+
<p>As of the time of this writing, the following nonstandard or not-yet-standardized APIs are
67054+
known to fall into this category:</p>
67055+
67056+
<ul>
67057+
<li><p><code>HTMLElement</code>'s <code data-x="">innerText</code> and <code
67058+
data-x="">outerText</code> IDL attributes</p></li>
67059+
67060+
<li><p><code>HTMLInputElement</code>'s <code data-x="">webkitdirectory</code> and <code
67061+
data-x="">incremental</code> IDL attributes</p></li>
67062+
67063+
<li><p><code>HTMLLinkElement</code>'s <code data-x="">disabled</code> and <code
67064+
data-x="">scope</code> IDL attributes</p></li>
67065+
67066+
<li><p><code>ShadowRoot</code>'s <code data-x="">innerHTML</code> IDL attribute</p></li>
67067+
</ul>
67068+
</div>
67069+
6700267070

6700367071
<!--TOPIC:HTML-->
6700467072
<h3 id="common-idioms">Common idioms without dedicated elements</h3>

0 commit comments

Comments
 (0)