Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce DOM post-connection steps #1261

Merged
merged 14 commits into from
Jun 5, 2024
86 changes: 84 additions & 2 deletions dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -2645,12 +2645,70 @@ of a <var>node</var> into a <var>parent</var> before a <var>child</var>, run the

<p><a lt="Other applicable specifications">Specifications</a> may define
<dfn export id=concept-node-insert-ext>insertion steps</dfn> for all or some <a for=/>nodes</a>. The
algorithm is passed <var ignore>insertedNode</var>, as indicated in the <a for=/>insert</a>
algorithm below.
algorithm is passed <var>insertedNode</var>, as indicated in the <a for=/>insert</a> algorithm
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
below. These steps must not modify the <a>node tree</a> that <var>insertedNode</var>
<a>participates</a> in, create <a for=/>browsing contexts</a>, <a lt="fire an event">fire
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
events</a>, or otherwise execute JavaScript. These steps may [=queue a global task|queue tasks=] to
do these things asynchronously, however.

<div class=example id=example-foo-what-do-i-put-here>
<p>While the <a>insertion steps</a> cannot execute JavaScript (among other things), they will
indeed have script-observable consequences. Consider the below example:

<pre class=lang-javascript><code>
const h1 = document.querySelector('h1');

const fragment = new DocumentFragment();
const script = fragment.appendChild(document.createElement('script'));
const style = fragment.appendChild(document.createElement('style'));

script.innerText= 'console.log(getComputedStyle(h1).color)'; // Prints 'rgb(255, 0, 0)'
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
style.innerText = 'h1 {color: rgb(255, 0, 0);}';

document.body.append(fragment);
</code></pre>

<p>The script in the above example prints <code class=lang-javascript>'rgb(255, 0, 0)'</code>
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
because the following happen in order:

<ol>
<li>
<p>The <a for=/>insert</a> algorithm runs, which will insert the <{script}> and <code><a element
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
spec=HTML>style</a></code> elements in order.

<ol>
<li>The HTML Standard's <a>insertion steps</a> run for the <{script}> element; they do nothing.
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
[[!HTML]]

<li>The HTML Standard's <a>insertion steps</a> run for the <code><a element
spec=HTML>style</a></code> element; they immediately apply its style rules to the document.
[[!HTML]]

<li>The HTML Standard's <a>post-connection steps</a> run for the <{script}> element; they run the
script, which immediately observes the style rules that were applied in the above step.
[[!HTML]]
</ol>
</li>
</ol>
</div>

<!-- See https://github.com/whatwg/dom/issues/34#issuecomment-125571750 for why we might need to
adjust this further based on the requirements of the script element. There might be other ways
to define that though as Olli suggests, so leaving that out for now. -->

<p><a lt="Other applicable specifications">Specifications</a> may also define <dfn export
id=concept-node-post-connection-ext>post-connection steps</dfn> for all or some <a for=/>nodes</a>.
The algorithm is passed <var ignore>connectedNode</var>, as indicated in the <a for=/>insert</a>
algorithm below.

<p class=note>The purpose of the <a>post-connection steps</a> is to provide an opportunity for <a
for=/>nodes</a> to perform any connection-related operations that modify the <a>node tree</a> that
<var ignore>connectedNode</var> <a>participates</a> in, create <a for=/>browsing contexts</a>, or
otherwise execute JavaScript. These steps allow a batch of <a>nodes</a> to be <a for=/>inserted</a>
<em>atomically</em> with respect to script, with all major side effects occurring <em>after</em> the
batch insertions into the <a>node tree</a> is complete. This ensures that all pending <a>node
tree</a> insertions completely finish before more insertions can occur.

domfarolino marked this conversation as resolved.
Show resolved Hide resolved
<p><a lt="other applicable specifications">Specifications</a> may define
<dfn export id=concept-node-children-changed-ext>children changed steps</dfn> for all or some
<a for=/>nodes</a>. The algorithm is passed no argument and is called from <a for=/>insert</a>,
Expand Down Expand Up @@ -2752,6 +2810,30 @@ before a <var>child</var>, with an optional <i>suppress observers flag</i>, run
<var>parent</var> with <var>nodes</var>, « », <var>previousSibling</var>, and <var>child</var>.

<li><p>Run the <a>children changed steps</a> for <var>parent</var>.

<li>
<p>Let <var>staticNodeList</var> be a <a for=/>list</a> of <a for=/>nodes</a>, initially
empty.</p>
domfarolino marked this conversation as resolved.
Show resolved Hide resolved

<p class="note">We collect all <a for=/>nodes</a> <em>before</em> calling the <a>post-connection
steps</a> on any one of them, instead of calling the <a>post-connection steps</a> <em>while</em>
we're traversing the <a>node tree</a>. This is because the <a>post-connection steps</a> can modify
the tree's structure, making live traversal unsafe, possibly leading to the <a>post-connection
steps</a> being called multiple times on the same <a>node</a>.</p>
</li>

<li>
<p>For each <var>node</var> in <var>nodes</var>, in <a>tree order</a>:
domfarolino marked this conversation as resolved.
Show resolved Hide resolved

<ol>
<li><p>For each <a>shadow-including inclusive descendant</a> <var>inclusiveDescendant</var> of
<var>node</var>, in <a>shadow-including tree order</a>, <a for=list>append</a>
<var>inclusiveDescendant</var> to <var>staticNodeList</var>.
</ol>
</li>
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
domfarolino marked this conversation as resolved.
Show resolved Hide resolved

<li><p><a for=list>For each</a> <var>node</var> in <var>staticNodeList</var>, if <var>node</var> is
domfarolino marked this conversation as resolved.
Show resolved Hide resolved
<a>connected</a>, then run the <a>post-connection steps</a> with <var>node</var>.
</ol>


Expand Down
Loading