The global object should not be the "global scope instance object"
allen at wirfs-brock.com
Thu Jan 26 14:20:06 PST 2012
On Jan 26, 2012, at 11:51 AM, Brendan Eich wrote:
>> Andreas Rossberg <mailto:rossberg at google.com>
>> January 26, 2012 11:26 AM
>> I still like the idea of cross-script shadowing (aka nested scopes),
>> but one concern was that it is not clear what names would be in scope
>> for, say, a piece of JS code in a random HTML attribute somewhere on
>> the page.
> We could say event handler attributes are scoped by the most-nested scope -- the scope due to the last <script> element that was closed before the element with the event handler attribute was processed.
> This means generated scripts (document.write or DOM create* calls) do not see the generating script's let and const bindings.
Why closed? All declarations within a Program are instantiated before evaluating any code in its <script> element so generated scripts should be able to reference the bindings for those declarations. However, if such reference are actually evaluated they might fall into the bindings' temporal dead zones.
> But it's worse than that. What about <script async src="..."> (or the HTML4-era, not fully supported on all browsers <scriptdefer src="...">? Async scripts are not supposed to have global effects other than defining functions that the page or app author ensures won't be called till after all content (or at least all scripts, or at least all of the needed async scripts) has finished loading.
Is this a specified restriction? If it is, I haven't been able to find it anywhere.
> In what scope do async script let/const top-level bindings go?
If it is a specified restriction then I would think that when a browser ES implementation actually processes such scripts they should reject any top level declarations other than functions. Regardless, it seems likely that indeterminate load ordering problems created by HTML need to be solved at that level. Why don't script elements have a dependency attribute:
> The situation is messy enough that I question the win of nesting scopes. True, a global object subject to async-loaded effects is no picnic, but it is the devil we know. And these var and function bindings, however racy, are not supposed to be lexical, as let and const are.
I think these are the alternatives we currently have under consideration:
SQ (status quo): every top level declaration are all implemented as properties of the global object
STL (Single Top Level): All script blocks share a declarative environment for new (not var and function) kinds of declarations that shadows the global object. Scripts with duplicate declarations are rejected.
TLpSi (Top Level per script, isolated): Each script block has a declarative environment for new (not var and function) kinds of declarations. Each shadows the global object but are invisible to each other.
TLpSn (Top Level per script, nested): Each script block has a declarative environment for new (not var and function) kinds of declarations. Each is logically nest within and shadows the previously processed script
STL is what I'm proposing. I think that TLpSn corresponds to Andreas preference. One way to look at TLpSn is that uses shadowing to accept the duplicate declarations that STL rejects. This seems like a problem that is better addressed by using modules. TLpBn also raises issues like, what scope does an indirect eval use? I haven't head anyone recently advocating for TLpSi. You can achieve almost the same thing using SQ by wrapping a block around each script body.
In general, when I start think about the ways that lexical declarations in separate scripts might interact I run into issue that are probably best resolved using modules. I'm inclined to favor the simpler solution and leave it to modules to deal with managing actual interdependencies cases.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss