From 5739cbd3e36f7bf885153bff17ecddc507b84421 Mon Sep 17 00:00:00 2001 From: lye Date: Thu, 20 Dec 2018 18:42:12 -0800 Subject: [PATCH] Hoisting fixes (#2606) When hoisting a var, use UNKNOWN_EXPRESSION as the initializer instead of the actual one. This prevents the initializer from being used during the optimization step when it hasn't yet been assigned at runtime. --- src/ast/scopes/BlockScope.ts | 8 +++++++- .../samples/hoisted-variable-case-stmt/_config.js | 3 +++ .../hoisted-variable-case-stmt/_expected.js | 8 ++++++++ .../samples/hoisted-variable-case-stmt/main.js | 8 ++++++++ .../samples/hoisted-variable-if-stmt/_config.js | 4 ++++ .../samples/hoisted-variable-if-stmt/_expected.js | 15 +++++++++++++++ .../form/samples/hoisted-variable-if-stmt/main.js | 15 +++++++++++++++ 7 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/form/samples/hoisted-variable-case-stmt/_config.js create mode 100644 test/form/samples/hoisted-variable-case-stmt/_expected.js create mode 100644 test/form/samples/hoisted-variable-case-stmt/main.js create mode 100644 test/form/samples/hoisted-variable-if-stmt/_config.js create mode 100644 test/form/samples/hoisted-variable-if-stmt/_expected.js create mode 100644 test/form/samples/hoisted-variable-if-stmt/main.js diff --git a/src/ast/scopes/BlockScope.ts b/src/ast/scopes/BlockScope.ts index 838e6a2b7d8..fca384856c0 100644 --- a/src/ast/scopes/BlockScope.ts +++ b/src/ast/scopes/BlockScope.ts @@ -1,6 +1,7 @@ import { AstContext } from '../../Module'; import Identifier from '../nodes/Identifier'; import { ExpressionEntity } from '../nodes/shared/Expression'; +import { UNKNOWN_EXPRESSION } from '../values'; import LocalVariable from '../variables/LocalVariable'; import Scope from './Scope'; @@ -14,7 +15,12 @@ export default class BlockScope extends Scope { isHoisted: boolean = false ) { if (isHoisted) { - return this.parent.addDeclaration(identifier, context, init, true) as LocalVariable; + return this.parent.addDeclaration( + identifier, + context, + UNKNOWN_EXPRESSION, + true + ) as LocalVariable; } else { return super.addDeclaration(identifier, context, init, false) as LocalVariable; } diff --git a/test/form/samples/hoisted-variable-case-stmt/_config.js b/test/form/samples/hoisted-variable-case-stmt/_config.js new file mode 100644 index 00000000000..f4ec792209e --- /dev/null +++ b/test/form/samples/hoisted-variable-case-stmt/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'Properly handles a variable hoisted from within a fallthrough switch case' +}; diff --git a/test/form/samples/hoisted-variable-case-stmt/_expected.js b/test/form/samples/hoisted-variable-case-stmt/_expected.js new file mode 100644 index 00000000000..872b496dacf --- /dev/null +++ b/test/form/samples/hoisted-variable-case-stmt/_expected.js @@ -0,0 +1,8 @@ +switch (someGlobal) { + case 1: + var hoisted = true; + case 2: + if (hoisted) { + throw "failed"; + } +} diff --git a/test/form/samples/hoisted-variable-case-stmt/main.js b/test/form/samples/hoisted-variable-case-stmt/main.js new file mode 100644 index 00000000000..872b496dacf --- /dev/null +++ b/test/form/samples/hoisted-variable-case-stmt/main.js @@ -0,0 +1,8 @@ +switch (someGlobal) { + case 1: + var hoisted = true; + case 2: + if (hoisted) { + throw "failed"; + } +} diff --git a/test/form/samples/hoisted-variable-if-stmt/_config.js b/test/form/samples/hoisted-variable-if-stmt/_config.js new file mode 100644 index 00000000000..c6e376a856b --- /dev/null +++ b/test/form/samples/hoisted-variable-if-stmt/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: + 'Properly renders branches which refer to hoisted variables from other lexical scopes' +}; diff --git a/test/form/samples/hoisted-variable-if-stmt/_expected.js b/test/form/samples/hoisted-variable-if-stmt/_expected.js new file mode 100644 index 00000000000..a7ac1cf18f7 --- /dev/null +++ b/test/form/samples/hoisted-variable-if-stmt/_expected.js @@ -0,0 +1,15 @@ +if (false) { + var foo; +} + +if (foo) { + console.log("nope"); +} + +{ + var bar = true; +} + +if (bar) { + console.log("ok"); +} diff --git a/test/form/samples/hoisted-variable-if-stmt/main.js b/test/form/samples/hoisted-variable-if-stmt/main.js new file mode 100644 index 00000000000..8f57f22a1cc --- /dev/null +++ b/test/form/samples/hoisted-variable-if-stmt/main.js @@ -0,0 +1,15 @@ +if (false) { + var foo = true; +} + +if (foo) { + console.log("nope"); +} + +if (true) { + var bar = true; +} + +if (bar) { + console.log("ok"); +}