Re: [whatwg/dom] Side effects due to tree insertion or removal (script, iframe) (#808)

I've discussed this a bit with Tab and at length with Anne and I've tried to compile and synthetize the UA behaviors in various scenarios.

I'm posting this before I submit the report on the current state of UAs (base on Anne's work chasing down inconsistencies), to make sure:

- I didn't forget something important
- We agree on the conceptual framework
- We agree on the terminology

----

### Timeline

Given a composite DOM operation (adding a fragment with several children, or setting `el.textContent` when `el` has several children) I propose we speak of:

- *synchronous* effects, intermingled with tree operations. e.g.: running inline scripts in Safari
- *tightly async* effects, queued and happening either just before or just after the tree manipulations but before control is given back to the JS that set the operation in motion. e.g.: mutation events (before), `connectedCallback` (after), ...
- *fully async* effects, queued for a later tick. e.g.: mutation observers, layout (unless forced from JS), ...

There are several tightly async queues. We'll say that queues that are closer in time to DOM tree manipulations are tighter.

The terminology here probably isn't optimal, because one might be tempted to say that a queue that is less tight is looser, perhaps seeding confusion...

### Effect typology

I've also tried to categorize the nature of the effects we deal with that are either synchronous or tightly async, at least in some UAs:

1) DOM tree mutations
2) non-JS effects (i.e. things that don't cause user JS to run)
    1) Other DOM node mutations, (like setting `button.form` when inserting a button in a form, or setting `contentWindow` to `null` when removing an `iframe`)
    2) CSSOM operations (incl. reacting to the insertion of `<meta content=alternative>`)
    3) Other environment changes like setting named properties on the global object
3) JS effects
    1) Inline scripts
    2) Mutation events
    3) Custom element hooks
    4) iframe.onunload

AFAICT 2.x operations don't trigger JS because they either mutate internal slots, or operate on objects that are locked and can't be spied upon using setters.

I've only investigated this from JS, which makes it impossible to determine whether 2.x effects are synchronous or tightly async, with queues tighter than the JS ones. It shouldn't matter as far as WebCompat or specs are concerned, since these details are not user visible. I may refer to these as "synchronous 2.x" for convenience.

### Going forward

Provided that the UAs have different behavior, it is unlikely that user code in production relies on their timelines and this gives us leeway to reorder things.

It would seem ideal to
- make synchronous JS tightly async
- make all 2.x (non-JS) effects synchronous or tighter than JS, such that 2.x operations appear atomic when seen from JS
- agree on a common timeline across UAs
    - including for reentrant behavior when tightly async JS causes another tree mutation


-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/808#issuecomment-1431007599
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/dom/issues/808/1431007599@github.com>

Received on Wednesday, 15 February 2023 09:27:49 UTC