From f8f2fa7ad4fc206cfcbdee89874041b7af2ba688 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 11 Aug 2017 21:27:08 -0400 Subject: [PATCH] init for loop scopes correctly --- src/ast/nodes/ForOfStatement.js | 2 +- src/ast/nodes/ForStatement.js | 8 ++++++-- .../samples/for-in-loop-head-dependencies/_config.js | 3 +++ .../samples/for-in-loop-head-dependencies/main.js | 12 ++++++++++++ .../samples/for-loop-head-dependencies/_config.js | 2 +- .../samples/for-loop-head-dependencies/main.js | 8 ++++---- .../samples/for-of-loop-head-dependencies/_config.js | 3 +++ .../samples/for-of-loop-head-dependencies/main.js | 12 ++++++++++++ 8 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 test/function/samples/for-in-loop-head-dependencies/_config.js create mode 100644 test/function/samples/for-in-loop-head-dependencies/main.js create mode 100644 test/function/samples/for-of-loop-head-dependencies/_config.js create mode 100644 test/function/samples/for-of-loop-head-dependencies/main.js diff --git a/src/ast/nodes/ForOfStatement.js b/src/ast/nodes/ForOfStatement.js index 8c745b7103a..cffde3abf0d 100644 --- a/src/ast/nodes/ForOfStatement.js +++ b/src/ast/nodes/ForOfStatement.js @@ -6,7 +6,7 @@ import { UNKNOWN } from '../values.js'; export default class ForOfStatement extends Statement { initialiseChildren () { this.left.initialise( this.scope ); - this.right.initialise( this.scope ); + this.right.initialise( this.scope.parent ); this.body.initialiseAndReplaceScope ? this.body.initialiseAndReplaceScope( this.scope ) : this.body.initialise( this.scope ); diff --git a/src/ast/nodes/ForStatement.js b/src/ast/nodes/ForStatement.js index 94132dfa65d..92cd59c470f 100644 --- a/src/ast/nodes/ForStatement.js +++ b/src/ast/nodes/ForStatement.js @@ -6,9 +6,13 @@ export default class ForStatement extends Statement { if ( this.init ) this.init.initialise( this.scope ); if ( this.test ) this.test.initialise( this.scope ); if ( this.update ) this.update.initialise( this.scope ); - this.body.initialiseAndReplaceScope ? - this.body.initialiseAndReplaceScope( this.scope ) : + + if ( this.body.type === 'BlockStatement' ) { + this.body.initialiseScope( this.scope ); + this.body.initialiseChildren(); + } else { this.body.initialise( this.scope ); + } } initialiseScope ( parentScope ) { diff --git a/test/function/samples/for-in-loop-head-dependencies/_config.js b/test/function/samples/for-in-loop-head-dependencies/_config.js new file mode 100644 index 00000000000..50f9834fbab --- /dev/null +++ b/test/function/samples/for-in-loop-head-dependencies/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'uses parent scope for right-hand-side in for-in statement (#1480)' +}; \ No newline at end of file diff --git a/test/function/samples/for-in-loop-head-dependencies/main.js b/test/function/samples/for-in-loop-head-dependencies/main.js new file mode 100644 index 00000000000..d51c8b5bcab --- /dev/null +++ b/test/function/samples/for-in-loop-head-dependencies/main.js @@ -0,0 +1,12 @@ +function foo() { + return ['x']; +} + +const result = []; + +for (let i in foo()) { + const foo = i; + result.push(foo); +} + +assert.deepEqual(result, [0]); \ No newline at end of file diff --git a/test/function/samples/for-loop-head-dependencies/_config.js b/test/function/samples/for-loop-head-dependencies/_config.js index 50f9834fbab..0caf9dc5ffd 100644 --- a/test/function/samples/for-loop-head-dependencies/_config.js +++ b/test/function/samples/for-loop-head-dependencies/_config.js @@ -1,3 +1,3 @@ module.exports = { - description: 'uses parent scope for right-hand-side in for-in statement (#1480)' + description: 'uses correct scope in for statement (#1538)' }; \ No newline at end of file diff --git a/test/function/samples/for-loop-head-dependencies/main.js b/test/function/samples/for-loop-head-dependencies/main.js index d51c8b5bcab..158029a6755 100644 --- a/test/function/samples/for-loop-head-dependencies/main.js +++ b/test/function/samples/for-loop-head-dependencies/main.js @@ -1,12 +1,12 @@ function foo() { - return ['x']; + return ['x', 'y']; } const result = []; -for (let i in foo()) { - const foo = i; +for (let a = foo(), i = 0; i < a.length; ++i) { + const foo = a[i]; result.push(foo); } -assert.deepEqual(result, [0]); \ No newline at end of file +assert.deepEqual(result, ['x', 'y']); \ No newline at end of file diff --git a/test/function/samples/for-of-loop-head-dependencies/_config.js b/test/function/samples/for-of-loop-head-dependencies/_config.js new file mode 100644 index 00000000000..65eba21dd3a --- /dev/null +++ b/test/function/samples/for-of-loop-head-dependencies/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'uses parent scope for right-hand-side in for-of statement (#1539)' +}; \ No newline at end of file diff --git a/test/function/samples/for-of-loop-head-dependencies/main.js b/test/function/samples/for-of-loop-head-dependencies/main.js new file mode 100644 index 00000000000..dd40202a9e4 --- /dev/null +++ b/test/function/samples/for-of-loop-head-dependencies/main.js @@ -0,0 +1,12 @@ +function foo() { + return ['x', 'y']; +} + +const result = []; + +for (const i of foo()) { + const foo = i; + result.push(i); +} + +assert.deepEqual(result, ['x', 'y']); \ No newline at end of file