Clean scope

# John J Barton (14 years ago)

JavaScript's ability to close over variables in nesting scopes sometimes surprises me. I'd like to be able to say "function uses a clean scope". Is there something like this in the works? Or maybe it exists? Thanks, jjb

# Dmitry A. Soshnikov (14 years ago)

In case if you don't use free variables, neither eval and nor inner functions, then implementations (I am sure) provide optimizations not capturing parent scope's bindings (at least I know one such an implementation -- V8) -- these are your "clean functions". However, theoretically, all functions in ECMAScript are closures (except maybe those which are created via the Function constructor which have only global environment as their [[Scope]]). So, no, you can't specify explicitly whether or not you need to capture lexical vars.

Info about optimizations: bit.ly/niboMr

Dmitry.

# Juriy Zaytsev (14 years ago)

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

# Allen Wirfs-Brock (14 years ago)

On Aug 17, 2011, at 9:14 AM, Juriy Zaytsev wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

or (null,eval)("function() { /.../}");

# Rick Waldron (14 years ago)

On Wed, Aug 17, 2011 at 12:36 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Aug 17, 2011, at 9:14 AM, Juriy Zaytsev wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

or (null,eval)("function() { /.../ }");

This actually produces...

syntax error, unexpected token

# John J Barton (14 years ago)

On Wed, Aug 17, 2011 at 9:14 AM, Juriy Zaytsev <kangax at gmail.com> wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

No, I mean a scope with JavaScript built-ins only, no 'host' functions, no |window| properties.

function walkTheWalk(position) { "use empty"; var from = parent.location; // error, should have said position.parent, but it works?!? }

# Allen Wirfs-Brock (14 years ago)

On Aug 17, 2011, at 10:37 AM, Rick Waldron wrote:

On Wed, Aug 17, 2011 at 12:36 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

On Aug 17, 2011, at 9:14 AM, Juriy Zaytsev wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

or (null,eval)("function() { /.../ }");

This actually produces...

syntax error, unexpected token

works for me in FF6

# Mark S. Miller (14 years ago)

On Wed, Aug 17, 2011 at 11:30 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Aug 17, 2011, at 10:37 AM, Rick Waldron wrote:

On Wed, Aug 17, 2011 at 12:36 PM, Allen Wirfs-Brock <allen at wirfs-brock.com

wrote:

On Aug 17, 2011, at 9:14 AM, Juriy Zaytsev wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

or (null,eval)("function() { /.../ }");

This actually produces...

syntax error, unexpected token

works for me in FF6

According to ES5.1, the argument to eval is parsed as a Program. So there's no reason to expect the above to work. Try

(null,eval)("(function() { /.../ })");

instead.

# Douglas Crockford (14 years ago)

On 11:59 AM, John J Barton wrote:

JavaScript's ability to close over variables in nesting scopes sometimes surprises me. I'd like to be able to say "function uses a clean scope". Is there something like this in the works? Or maybe it exists?

JSLint produces a report that indicates which variables are global, local, inner, or closure. That way you won't be surprised.

# Andrew Oakley (14 years ago)

On Wed, 17 Aug 2011 10:38:43 -0700 John J Barton <johnjbarton at johnjbarton.com> wrote:

On Wed, Aug 17, 2011 at 9:14 AM, Juriy Zaytsev <kangax at gmail.com> wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

No, I mean a scope with JavaScript built-ins only, no 'host' functions, no |window| properties.

function walkTheWalk(position) { "use empty"; var from = parent.location; // error, should have said position.parent, but it works?!? }

There really isn't a nice way to do this. I don't think that using function constructors or eval improve things in any way.

Perhaps a lint program could be modified to detect this? You could use a "use ..." prologue to indicate to the linter that this is desired. Douglas Crockford's JSLint contains a full blown parser and could probably be modified to do this fairly easily.

# Mike Samuel (14 years ago)

2011/8/17 John J Barton <johnjbarton at johnjbarton.com>:

On Wed, Aug 17, 2011 at 9:14 AM, Juriy Zaytsev <kangax at gmail.com> wrote:

What do you mean by "clean scope"? All scope chains have at least global scope in them. Is that what "clean scope" chain would be — the one including global scope only? That's pretty much what Function constructor does.

No, I mean a scope with JavaScript built-ins only, no 'host' functions,  no |window| properties.

function walkTheWalk(position) {  "use empty";   var from = parent.location; // error, should have said position.parent, but it works?!? }

Haven't there been various proposals/schemes for an eval that takes an object to serve as the scope root as the second argument?

dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts

In SpiderMonkey implementation (built into Firefox, Thunderbird), up to version 1.7, it is possible to pass a calling context as a second argument for eval function.

This violated closures in abominable ways, but it could be made to respect closures.

If that second argument were explicitly null, then using an object containing only the builtins as defined at interpreter start, would get these semantics.

# Brendan Eich (14 years ago)

On Aug 17, 2011, at 12:04 PM, Mike Samuel wrote:

In SpiderMonkey implementation (built into Firefox, Thunderbird), up to version 1.7, it is possible to pass a calling context as a second argument for eval function.

This violated closures in abominable ways, but it could be made to respect closures.

That was fixed a while ago:

bugzilla.mozilla.org/show_bug.cgi?id=442333

(more fun in followup bug).

If that second argument were explicitly null, then using an object containing only the builtins as defined at interpreter start, would get these semantics.

Mozilla has evalInSandbox built-ins. We've talked about them, but no one has produced a strawman based on this work. The module loader API:

harmony:module_loaders

provides enough functionality.

# John J Barton (14 years ago)

On Wed, Aug 17, 2011 at 4:15 PM, Brendan Eich <brendan at mozilla.com> wrote:

Mozilla has evalInSandbox built-ins.

Unfortunately I have quite a lot of experience with evalInSandbox.

We've talked about them, but no one has produced a strawman based on this work. The module loader API:

harmony:module_loaders

provides enough functionality.

Thanks, that is what I was looking for.

jjb

# Brendan Eich (14 years ago)

On Aug 17, 2011, at 4:25 PM, John J Barton wrote:

On Wed, Aug 17, 2011 at 4:15 PM, Brendan Eich <brendan at mozilla.com> wrote:

Mozilla has evalInSandbox built-ins.

Unfortunately I have quite a lot of experience with evalInSandbox.

If you mean Firebug vs. evalInSandbox, if I recall correctly, the problem is that a debugger doesn't want as much isolation as the security use-cases that motivated evalInSandbox want. Is that right?

# David Herman (14 years ago)

Mozilla has evalInSandbox built-ins. We've talked about them, but no one has produced a strawman based on this work. The module loader API:

harmony:module_loaders

provides enough functionality.

In fact, I think "sandbox" is a pretty good intuition for what a loader is. And it makes sense to think of loader.eval(str) as an OO version of evalInSandbox. But it should give you much more fine-grained control over exactly how you want to set up the sandbox than just the global scope.

# Brendan Eich (14 years ago)

On Aug 17, 2011, at 4:39 PM, Brendan Eich wrote:

On Aug 17, 2011, at 4:25 PM, John J Barton wrote:

On Wed, Aug 17, 2011 at 4:15 PM, Brendan Eich <brendan at mozilla.com> wrote:

Mozilla has evalInSandbox built-ins.

Unfortunately I have quite a lot of experience with evalInSandbox.

If you mean Firebug vs. evalInSandbox, if I recall correctly, the problem is that a debugger doesn't want as much isolation as the security use-cases that motivated evalInSandbox want. Is that right?

From corresponding with John, this seems like a combo of out of date MDC docs on evalInSandbox (it uses proxy-based membranes aggressively for security, but the docs predate that), and the common line number problem with all eval variants, where multiple lines in the eval'ed source do not have usable line numbers:

bugzilla.mozilla.org/show_bug.cgi?id=307984

We have discussed various fixes to propagate accurate, invertible source coordinates through nested evals in bugzilla bugs in the past. Firebug has tried crypto-hashing source strings, IIRC. Does anyone have a solid solution?