Add (and fix) failing test of function parameter bindings in a catch block (#4880)

* Add failing test of function parameter bindings in a catch block.

This test can be run in isolation via the following command:

  TEST_GREP='block-scoping.*function in catch' make test-only

This test fails because BlockScoping#getLetReferences accidentally
considers the parameters of the function declaration as let bindings in
the catch scope. When the name of the catch parameter is the same as one
of the function's parameter names, the function declaration will be
unnecessarily wrapped to isolate its parameters from the outer scope.

While the extra wrapping may not seem harmful in this case, this behavior
is a symptom of a deeper problem that causes very subtle bugs in transform
code involving catch parameters and function declarations. This test case
was just the simplest example I could find to demonstrate the problem.

I have a proposed fix for this problem that I will push as soon as the
tests fail for this commit.

* Make BlockScoping#getLetReferences ignore function parameters.
This commit is contained in:
Ben Newman 2016-12-08 10:16:48 -05:00 committed by Henry Zhu
parent 44fe114939
commit 26b4e0909e
3 changed files with 19 additions and 1 deletions

View File

@ -524,7 +524,11 @@ class BlockScoping {
// //
for (let i = 0; i < declarators.length; i++) { for (let i = 0; i < declarators.length; i++) {
let declar = declarators[i]; let declar = declarators[i];
let keys = t.getBindingIdentifiers(declar); // Passing true as the third argument causes t.getBindingIdentifiers
// to return only the *outer* binding identifiers of this
// declaration, rather than (for example) mistakenly including the
// parameters of a function declaration. Fixes #4880.
let keys = t.getBindingIdentifiers(declar, false, true);
extend(this.letReferences, keys); extend(this.letReferences, keys);
this.hasLetReferences = true; this.hasLetReferences = true;
} }

View File

@ -0,0 +1,7 @@
try {
foo();
} catch (x) {
function harmless(x) {
return x;
}
}

View File

@ -0,0 +1,7 @@
try {
foo();
} catch (x) {
var harmless = function (x) {
return x;
};
}