-
-
Save ajklein/b947351835cc77ad0040db9a55813f51 to your computer and use it in GitHub Desktop.
// 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 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.
@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
.
@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.
@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.
What do you think this should do?