Skip to content

Instantly share code, notes, and snippets.

@ajklein
Last active Nov 28, 2017
Embed
What would you like to do?
Parameter scoping and sloppy eval
// What does this code do?
function f(x = eval("var z = 2; 1"), y = z) {
return [x, y, z];
}
f();
// Spec says to throw a ReferenceError, since 'z' is not visible either
// to other parameters in the list, or to the function body.
//
// Results in various engines:
//
// V8, SpiderMonkey, recent Chakra: ReferenceError: z is not defined
// Chakra (until recently): (early) SyntaxError: 'eval' is not allowed in the default initializer
// JavaScriptCore: returns [1, 2, 2]
// What about this?
function g(x = eval("var z = 2; 1"), y = z) {
var z;
return [x, y, z];
}
g();
// Spec, SM, V8: ReferenceError: z is not defined
// JSC: returns [1, 2, undefined]
// Proposal: switch the spec to the JavaScriptCore behavior.
@littledan

This comment has been minimized.

Copy link

@littledan littledan commented Nov 7, 2017

What do you think this should do?

@ajklein

This comment has been minimized.

Copy link
Owner Author

@ajklein ajklein commented Nov 27, 2017

@littledan I can't think of a reason that JSC's behavior is particularly bad, and it seems a lot easier to implement than what V8, SpiderMonkey, and the spec do today.

@syg

This comment has been minimized.

Copy link

@syg syg commented Nov 28, 2017

@ajklein I agree the current semantics is very odd and a pain to implement. Let's be specific: is the proposal that sloppy eval var bindings be allowed to escape to other parameter expression, or also the function body? I oppose letting dynamic var bindings escape to function body, which isn't going to make implementation any easier.

Yet another fix that is both simple to reason about and implement IMO is make all evals in parameter expression positions strict, regardless of the enclosing script's strictness. The current semantics is super weird in that bindings are allowed to escape the eval, but not the parameter expression position. This means you can access z in your example with a comma expression after eval.

@ajklein

This comment has been minimized.

Copy link
Owner Author

@ajklein ajklein commented Nov 28, 2017

@syg JSC apparently creates the var binding in the parameter scope, as adding a "var z;" to the function body causes the return value to be [1, 2, undefined]. I think that's the semantics I'd want.

@syg

This comment has been minimized.

Copy link

@syg syg commented Nov 28, 2017

@ajklein I still prefer all eval being strict, thus no ability to make new var bindings at all in parameter expressions. I think that aligns closer with the intent of the current semantics. Is there a V8 implementation preference against that? Seems simplest of all possible semantics to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment