Re: [whatwg] setting .src of a SCRIPT element

On 31/05/07, Jonas Sicking <jonas@sicking.cc> wrote:
> > I think IE's behaviour is pretty useful and I'd like the spec to make
> > this standards-compliant. It is a common technique to create SCRIPT
> > elements dynamically to load data (particularly because this gets
> > around cross-domain limitations). Firefox's implementation means one
> > has to create a new SCRIPT element each time, keep track of them, and
> > remove them from the document again, whereas with IE's implementation
> > you can have one "data loader" SCRIPT element and set its .src
> > repeatedly.
>
> The reason I designed it this way was that it felt like the least
> illogical behavior. In general a document behaves according to its
> current DOM. I.e. it doesn't matter what the DOM looked like before, or
> how it got to be in the current state, it only matters what's in the DOM
> now.
>
> For <style> elements this work great. Whenever the contents of a <style>
> is changed the UA can drop the current style rules associated with the
> element, reparse or reload the new stylesheet, and apply the new style
> rules to the document. (There was a bug in Firefox up to version 2,
> where certain DOM mutations inside the <style> weren't detected, but
> that has been fixed in Firefox 3).
>
> For <script> things are a lot worse. If the contents of a <script>
> element is changed it is impossible to 'drop' the script that was there
> before. Once the contents of a <script> has executed, it can never be
> unexecuted. And since we can't undo what the <script> has already done,
> it feels weird to redo the new thing that you're asking it to do.

The difference there is that the styles are continually effective,
while the script only does it's effect once. The idea of undoing the
script doesn't make sense since it's no longer in effect. It may have
set up the envirnment or changed things in it, but after that, the
script itself is finished. Everything after that are side effects of
the script having been there, it's not actually the script being in
place.

What I'm trying to say here is that undoing the script after it has
executed amounts to exactly no change because the script is no longer
in effect which means there is no effect to remove. In my opinion
changing the source should just replace the no-longer-in-effect script
with a new one, and send that one to the ECMAScript engine for
parsing.

> Another thing that would be weird would be inline scripts. How would the
> following behave:
> s = document.createElement('script');
> document.head.appendChild(s);
> for (i = 0; i < 10; i++) {
>    s.textContent += "a" + i + " += 5;";
> }
> Would you reexecute the entire script every time data was appended to
> the script? Would you try to just execute the new parts? Would you do
> nothing? IE gets around this problem by not supporting dynamically
> created inline scripts at all, which I think is a really bad solution.

I agree this is a problem. I see several non-solutions that simply
would close the issue without dealing with valid concerns. The only
solution I see that actually handles most concerns is to not execute
inline scripts at all without some API call on the script element to
tell that it's been set up fully. What if you were building a script
body in many text nodes and CDATA nodes and  entity reference nodes
where you only have a final, executable form once you have set it all
up? It makes sense to me to have an API function for triggering
evaluation of the script inline contents.

So, what are these issues I talk about? Well, mostly it's questions
about what is appropriate to do in cases like:
1. We have a script element, without inline content, in the document
hierarchy. A src attribute is added.
2. We have a script element, with either a src attribute or inline
content, in the document hierarchy. A type attribute is added, removed
or modified.
3. We have a script element, with inline contents, in the document
hierarchy. A src attribute is added.
4. We have a script element, with no inline content but with a src
attribute, in the document hierarchy. Inline content is added.
5. We have a script element, with inline content and a src attribute,
in the document hierarchy. The src attribute is removed.
6. We have a script element, in the document hierarchy. It is removed
from and reinserted into the document hierarchy.
7. We have a script element, with inline content, in the document
hierarchy. The inline content is changed.
8. We have a script element, without inline content, not in the
document hierarchy. A src attribute is added.
9. We have a script element, with a src attribute, in the document
hierarchy. The src attribute is changed.

(An similar example cases, on and on...)



I think it would be logical to handle DOM manipulation like so:
- Any script element: If a src, type, defer, async, language, charset,
for or event attribute is added, removed or changed, the script is
flagged as unexecuted.
- Any script element: If a src attribute is added or changed, load
that resource.
- A script element, without src attribute: If inline content is
changed, removed or added, the script is flagged as unexecuted.

I think it would be logical to handle execution of script like so:
- A script element, with an unexecuted flag: If inserted into the
document hierarchy, the script is sent to the scripting engine queue
and flagged as executed.
- A script element, with an unexecuted flag, in the document
hierarchy: If an evaluation method on the script element is called or
the loading of a resource completes, the script is sent to the
scripting engine queue and flagged as executed.
- A script element, with an executed flag: If an evaluation method on
the script is called with a first argument of true, the script is sent
to the scripting engine queue again.

Or at least something like that. It would have to be expanded, since I
haven't even taken the for, event, defer and async attributes into
account here nor the initial document parsing. Why an executed flag?
Because I doubt authors would like their scripts reexecuted just
because they move an ancestor element in the document or something
similar.

> So I opted for 'killing' script elements once they have executed, they
> become in effect dead elements. This felt simple and consistent.

ECMAScript doesn't have a continuous effect, nor does it have
incremental parsing/execution. All of the script is executed in one go
unless it calls a halting function like alert, but then the script
execution is just delayed and not cancelled. After executing the
script is no longer in effect, though it might have had persistent
side effects.

In the face of that it doesn't seem like killing the script element is
much good the script itself dies of itself after execution. This
behaviour of Gecko only prevents element reuse if you ask me, and
that's not particularly desired.
-- 
David "liorean" Andersson

Received on Thursday, 31 May 2007 05:24:33 UTC