-
Notifications
You must be signed in to change notification settings - Fork 298
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
Hook for SVG and HTML script element insertion #575
Comments
Maybe the way to go here is to always notify post- |
Oh joy, if I change things to
s2 will not execute in Chrome and Edge, but does execute in Firefox. Safari will throw an error for s1 because in Safari s2 is not in the tree yet when s1 executes. So maybe another thing that's needed here is that |
Per https://html.spec.whatwg.org/#prepare-a-script browsers need to do a "connected" check, which means Firefox has a bug. (I want to check though if that check is correct or if it needs to be browsing-context connected.) Another concern here is how this slightly post-insert notification interacts with slot changes. Basically, at what point do the shadow tree changes happen relative to notifying external consumers (which can execute script)? |
With the following example I still get a <div id=host></div>
<script>
const host = document.getElementById("host"),
shadow = host.attachShadow({ mode: "closed" }),
slot = shadow.appendChild(document.createElement("slot")),
df = document.createDocumentFragment(),
s1 = df.appendChild(document.createElement("script")),
s2 = df.appendChild(document.createElement("script"));
slot.addEventListener("slotchange", e => console.log(e));
s1.textContent = "df.appendChild(s1); df.appendChild(s2);";
s2.textContent = "console.log('hmm');";
host.appendChild(df);
</script> |
I also tested custom elements: <script>
customElements.define("ce-1", class CE1 extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
console.log("ce-1 connected");
}
});
const df = document.createDocumentFragment(),
s = df.appendChild(document.createElement("script")),
ce1 = df.appendChild(document.createElement("ce-1"));
s.textContent = "df.appendChild(ce1);";
document.head.appendChild(df);
</script> This logs "ce-1 connected" in Chrome and Firefox. It doesn't log anything in Safari. I'm inclined to side with Chrome and Firefox here. |
<div id=host></div>
<script>
const host = document.getElementById("host"),
shadow = host.attachShadow({ mode: "closed" }),
slot = shadow.appendChild(document.createElement("slot")),
df = document.createDocumentFragment(),
s1 = df.appendChild(document.createElement("script")),
s2 = df.appendChild(document.createElement("script"));
slot.addEventListener("slotchange", e => console.log(e));
s1.textContent = "df.appendChild(s1); df.appendChild(s2);";
s2.textContent = "console.log('hmm');";
host.appendChild(df);
</script>
<script>
customElements.define("ce-1", class CE1 extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
console.log("ce-1 connected");
}
});
const df = document.createDocumentFragment(),
s = df.appendChild(document.createElement("script")),
ce1 = df.appendChild(document.createElement("ce-1"));
s.textContent = "df.appendChild(ce1);";
document.head.appendChild(df);
</script> |
Another snippet that exposes differences between Firefox and Safari: <body>
<select id="select"><option selected>1</option></select>
<script>
var select = document.getElementById("select");
var script = document.createElement("script");
script.textContent = "console.log(select.selectedIndex);";
var option = document.createElement("option");
option.textContent = "2";
option.selected = true;
select.append(script, option);
</script> Changing selectedness of options is defined as part of inserting steps, AFAIK. This prints 0 in Safari and 1 in Firefox. |
Safari follows the current spec entirely for this one snippet, here is what the Live DOM Viewer says:
Which means it first inserts I'm not really sure what to do with this information, in which way do we want the spec to go? Do we want to specify less differences between inserting a |
I guess that answers my question: we want children being inserted as part of a |
For any given insert operation, these steps run for each inserted node synchronously after all node insertions are complete. This closes #732. The goal here is to separate the following: 1. Script-observable but not-script-executing insertion side effects - This includes synchronously applying styles to the document, etc... 2. Script-executing insertion side effects - This includes creating an iframe's document and synchronously firing its load event For any given call to insert, the above model allows us to keep all of (1) running synchronously after each node's insertion (as part of its insertion steps), while pushing all script-executing (or DOM tree-modifying or frame tree-modifying etc.) side effects to the new set of post-connection steps, which run synchronously during insertion, but _after all_ nodes finish their insertion. This essentially makes insertions "atomic" from the perspective of script, since script will not run until a given batch of DOM insertions are complete. This two-stage approach aligns the spec with a model most similar to Blink & Gecko's implementation, and fixes #808. This PR also helps out with whatwg/html#1127 and #575 (per #732 (comment)). To accomplish, this we audited all insertion side effects on the web platform in https://docs.google.com/document/d/1Fu_pgSBziVIBG4MLjorpfkLTpPD6-XI3dTVrx4CZoqY/edit#heading=h.q06t2gg4vpw, and catalogued whether they have script-observable side-effects, whether they invoke script, whether we have tests for them, and how each implementation handles them. This gave us a list of present "insertion steps" that should move to the "post-connection steps", because they invoke script and therefore prevent insertions from being "atomic". This PR is powerless without counterpart changes to HTML, which will actually _use_ the post-connection steps for all current insertion steps that invoke script or modify the frame tree. The follow-up HTML work is tracked here: - whatwg/html#10188 - whatwg/html#10241
For any given insert operation, these steps run for each inserted node synchronously after all node insertions are complete. This closes whatwg#732. The goal here is to separate the following: 1. Script-observable but not-script-executing insertion side effects - This includes synchronously applying styles to the document, etc... 2. Script-executing insertion side effects - This includes creating an iframe's document and synchronously firing its load event For any given call to insert, the above model allows us to keep all of (1) running synchronously after each node's insertion (as part of its insertion steps), while pushing all script-executing (or DOM tree-modifying or frame tree-modifying etc.) side effects to the new set of post-connection steps, which run synchronously during insertion, but _after all_ nodes finish their insertion. This essentially makes insertions "atomic" from the perspective of script, since script will not run until a given batch of DOM insertions are complete. This two-stage approach aligns the spec with a model most similar to Blink & Gecko's implementation, and fixes whatwg#808. This PR also helps out with whatwg/html#1127 and whatwg#575 (per whatwg#732 (comment)). To accomplish, this we audited all insertion side effects on the web platform in https://docs.google.com/document/d/1Fu_pgSBziVIBG4MLjorpfkLTpPD6-XI3dTVrx4CZoqY/edit#heading=h.q06t2gg4vpw, and catalogued whether they have script-observable side-effects, whether they invoke script, whether we have tests for them, and how each implementation handles them. This gave us a list of present "insertion steps" that should move to the "post-connection steps", because they invoke script and therefore prevent insertions from being "atomic". This PR is powerless without counterpart changes to HTML, which will actually _use_ the post-connection steps for all current insertion steps that invoke script or modify the frame tree. The follow-up HTML work is tracked here: - whatwg/html#10188 - whatwg/html#10241
@annevk I get the sense that we can close this issue now that #1261 and whatwg/html#10188 have landed. Do you agree? |
Yeah, nice! |
Given http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=4098 we need to do something special for script elements, in particular when inserted from a
DocumentFragment
node. It's my understanding this only affects script elements, but I haven't verified.whatwg/html#1127 has an idea as to how to address this.
The text was updated successfully, but these errors were encountered: