Scoping of non-strict direct evals in ComputedPropertyNames in parameters
Great catch!
now ecmascript#4419
On Jul 8, 2015, at 12:25 PM, Kevin Gibbons wrote:
In the final ECMAScript 2015 spec, each function for which ContainsExpression of that function's [[FormalParameters]] internal slot is true has a scope object for its parameters. Additionally, these functions have a separate scope object under this one for each parameter that has an initializer. See 14.1.18 for the production "FormalParameter : BindingElement". The last sentence of this section states
The new Environment Record created in step 6 is only used if the BindElement’s Initializer contains a direct eval.
This is shown to be incorrect (aside from the "BindElement" typo) with the following program.
var x = "outer"; function f({ [eval('var x="inner"; "a";')]: y } = null) { console.log(x); } f({a: "z"});
Because the presence of an initializer causes a new scope to be created, in which the entire BindingElement is evaluated, this should print "outer". Therefore, the scope is used any time there is a direct eval in BindingElement.
The intent, per the last sentence of 14.1.18 and bug 3383, is that direct evals in the parameter list cannot introduce new variables in the function's parameters scope mentioned earlier. However, non-strict direct evals can also occur in computed property names in parameters which do not have initializers
var x = "outer"; function f({ [eval("var x='inner'; 'a';")]: y }) { console.log(x); } f({a: "z"});
Because the separate scope is not created if no initializer is present, this should print "inner".
Introducing an initializer, even an initializer which is just a simple value, causes a separate scope to be created. This is non-intuitive, and appears to be unintentional.
An oversight, I forget about the possibility of computer property name expressions in a parameter position.
There are multiple ways that this behavior can be fixed
Create a new scope for each parameter, unconditionally
Yes, this fix reflects what we intended.
Define code in computed property names as strict code
The erroneous sentence at the end of section 14.1.18 may be fixed by replacing it with "The new Environment Record created in step 6 is only used if the BindElement contains a direct eval.".
and it should probably be tagged as a NOTE
In the final ECMAScript 2015 spec, each function for which ContainsExpression of that function's [[FormalParameters]] internal slot is true has a scope object for its parameters. Additionally, these functions have a separate scope object under this one for each parameter that has an initializer. See 14.1.18 for the production "FormalParameter : BindingElement". The last sentence of this section states
The new Environment Record www.ecma-international.org/ecma-262/6.0/index.html#sec-environment-records
created in step 6 is only used if the BindElement’s Initializer contains a direct eval.
This is shown to be incorrect (aside from the "BindElement" typo) with the following program.
var x = "outer";
function f({ [eval('var x="inner"; "a";')]: y } = null) {
console.log(x);
}
f({a: "z"});
Because the presence of an initializer causes a new scope to be created, in which the entire BindingElement is evaluated, this should print "outer". Therefore, the scope is used any time there is a direct eval in BindingElement.
The intent, per the last sentence of 14.1.18 and bug 3383 ecmascript#3383, is that direct evals in
the parameter list cannot introduce new variables in the function's parameters scope mentioned earlier. However, non-strict direct evals can also occur in computed property names in parameters which do not have initializers
var x = "outer";
function f({ [eval("var x='inner'; 'a';")]: y }) {
console.log(x);
}
f({a: "z"});
Because the separate scope is not created if no initializer is present, this should print "inner".
Introducing an initializer, even an initializer which is just a simple value, causes a separate scope to be created. This is non-intuitive, and appears to be unintentional.
There are multiple ways that this behavior can be fixed
Create a new scope for each parameter, unconditionally 2.
Create a new scope for parameters for which ContainsExpression is true, instead of just those that have an initializer 3.
Define code in computed property names as strict code
The erroneous sentence at the end of section 14.1.18 may be fixed by replacing it with "The new Environment Record created in step 6 is only used if the BindElement contains a direct eval.".