- From: liorean <liorean@gmail.com>
- Date: Thu, 31 May 2007 09:08:12 +0200
On 31/05/07, Jonas Sicking <jonas at sicking.cc> wrote: > > 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. > > What we do is that we don't execute the script until it is inserted into > the DOM. This is consistent with how most elements work, i.e. they don't > affect the document until they are actually inserted into it. Neither would my suggested behaviour, but executing ONLY when inserting into the document hierarchy would be entirely acceptable in my view. It only makes for script.parentNode.replaceChild(script,script) instead of script.evaluate(true) as the way to evaluate the script after changing it. It relies on being able to execute more than one, but a script.cloneNode(true) should be able to deal with even that. > This way you can build a script element containing whatever you want and > then insert it into the document. You can even build a script element > with both src set and has inline content so that you'll get the fallback > behaviour exactly like parsed elements. Which you can in my suggestion too. Any of the actions that mark it as unexecuted will make inserting/reinserting it into the document hierarchy send it to the scripting engine. I have in no way specified any other handling when sending it to the scripting engine than the default with regards to where the code to parse comes from. > > 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...) > > What we've said is that once a script element can be executed it is, and > then it never is again. A script element can be executed once it's in > the document and it has either inline content or a src attribute set. As mentioned I don't like the idea of not being able to execute it again. But as long as the execution flag is not preserved through a cloneNode, and the node is guaranteed to be cloneable in all user agents, I don't mind, all the functionality of my suggestion would be replicatable then. > > 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. > > That would make doing > > myScript.src = myScript.src > and > myScript.textContent = myScript.textContent > > reevaluate the scripts. It would also make the for-loop in the example I > gave above reevaluate the first script part over and over again. The myScript.src example, yes. The myScript.textContent example no. I'm not sure I recall correctly here, but changing the inline content doesn't trigger a load event (which is the only way in my suggestion to trigger execution automatically), does it? So it wouldn't automatically execute it again, only set the unexecuted flag. Reinserting it into the document or calling script.evaluate() would be needed to execute it again. > I don't think any solution here is going to be particularly logical, so > I'd opt for what's simple. I'd like the simple solution to be one that allows what in my suggestion would be: function evaluate(source){ script.textContent=source; script.evaluate(); } which is equivalent to a version of eval executing in the global scope that allows for evaluating other languages. The way Mozilla's only-ever-evaluate-once handling works, I'd probably have to code it more like this: function evaluate(source){ var newScript=script.cloneNode(true); newScript.textContent=source; script.parentNode.replaceChild(newScript,script); } But I'm not sure cloning script elements is interoperable. I haven't done any testing for that. > >> 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. > > I don't see that being able to reuse elements adds any value. Could you > give an example where it does? The global eval equivalent is an example. It's not much of an improvement over the cloneNode example but I'd like the performance to be as close to a plain eval as possible. Ability to switch type, charset, language attributes in chosen user agents may be useful for things like testing E4X support or ES4 support, or correct broken encodings. Ability to execute an external resource again may be useful. All of these are already possible however, so I don't think they are strong use cases. > I do however think that allowing reuse causes a lot of weird edge cases > that needs to be defined and that authors need to learn. I don't deny that. I was just trying to make a logical behaviour for inline content and attribute changes while preserving the Internet Explorer behaviour when modifying the src attribute. -- David "liorean" Andersson
Received on Thursday, 31 May 2007 00:08:12 UTC