- From: David Flanagan <dflanagan@mozilla.com>
- Date: Fri, 28 Oct 2011 11:49:02 -0700
I'm replying to my own post because I've tested it and found that browsers are not interoperable on this point, so we really do need to clarify this in the spec. First of all, the following code obviously runs the specified code and displays an alert: var s0 = document.createElement("script"); document.head.appendChild(s0); var t0 = document.createTextNode("alert('added a text node child');"); s0.appendChild(t0); All browsers do that correctly. The case I'm interested in is this one: var s1 = document.createElement("script"); var t1 = document.createTextNode(""); s1.appendChild(t1); document.head.appendChild(s1); t1.appendData("alert('changed text node data');"); Firefox runs this script and Chrome, Safari and Opera do not. (I don't have a windows installation, so I haven't tested IE) Step 4 of the "prepare a script" algorithm says: " If the element has no |src <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#attr-script-src>| attribute, and its child nodes, if any, consist only of comment nodes and empty text nodes <http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#text-node>, then the user agent must abort these steps at this point. The script is not executed." So when the script is added to the document, it has only an empty text node, and it does not execute, and (this is the important part) it does not get its already started flag set. So it should still be runnable. One thing that is supposed to trigger script execution is "the script element is in a Document and its child nodes are changed". My original point in this post was that "child nodes are changed" isn't specific enough. The most obvious interpretation to me would be "a child is inserted or deleted". Firefox has a more sophisticated interpretation that seems to boil down to "when the value of the text idl attribute changes". Is Firefox correct here? We're not done yet, though. If I comment out the appendData() call in the code above and replace it with this line: s1.appendChild(document.createTextNode("alert('then added a new text node');")); Firefox now runs this new script. But Chrome, Safari and Opera still don't run it. So the issue here isn't that the other browsers differ from Firefox on the interpretation of "child nodes are changed". Apparently the other browsers are marking the script with the empty text node as already started, and aren't allowing it to run when a change happens later. And this isn't just limited to the empty text node case. If I change that empty text node into a <div> element, or to a comment, Firefox still (correctly) runs a script inserted later, and the other browsers still (incorrectly) fail to run it. Frankly, from an implementation standpoint, having to do what the spec says (and what Firefox does) seems unnecessarily complex. One way to simplify things and to bring Chrome, Safari and Opera into compliance would be to change step 4 of the prepare a script algorithm so that it only aborts if the script tag has no children at all. If it has children then the already_started flag would be set, and the script would never run again even if those children do not define any script content. Making this change would also simplify that second trigger for preparing the script. Instead of a vague "its child nodes are changed", the spec could just say "a child is inserted". David On 10/27/11 4:03 PM, David Flanagan wrote: > ?4.3.1 The Script Element says: >> >> When a |script >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element>| >> element that is not marked as being "parser-inserted" >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#parser-inserted> >> experiences one of the events listed in the following list, the user >> agent must synchronously prepare >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#prepare-a-script> >> the |script >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element>| >> element: >> >> * The |script >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element>| >> element gets inserted into a document >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#insert-an-element-into-a-document>. >> * The |script >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element>| >> element is in a |Document| >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#in-a-document> >> and its child nodes are changed. >> * The |script >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element>| >> element is in a |Document| >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#in-a-document> >> and has a |src >> <http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#attr-script-src>| >> attribute set where previously the element had no such attribute. >> > Bullet point 2 seems ambiguous to me. Does it mean only that the list > of children changes, or does it mean that any change to any child node > also causes the script to be prepared? In particular, if a script > with no src attribute whose only child is an empty text node is > inserted into the document, the prepare() algorithm will abort before > the already_started flag is set. Later, if I do > script.firstChild.insertData(jscode) does that trigger script execution? > > I haven't tried it out yet to see what browsers do, but I think that > the spec should be clarified to make it explicit. > > David
Received on Friday, 28 October 2011 11:49:02 UTC