From 183d9570f91af50b1ae269707775e369dbcd608b Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Thu, 18 Aug 2016 01:23:09 +0200 Subject: [PATCH] Fix bug where redeclaration of var doesn't deopt (#3559) * Fix bug where redeclaration of var doesn't deopt. (Close T7470) * [evaluate] Add tests for cases - let/const/different scopes --- .../babel-traverse/src/path/evaluation.js | 5 +++ packages/babel-traverse/test/evaluation.js | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/packages/babel-traverse/src/path/evaluation.js b/packages/babel-traverse/src/path/evaluation.js index 5e89b1a2dd..6dcc3f747f 100644 --- a/packages/babel-traverse/src/path/evaluation.js +++ b/packages/babel-traverse/src/path/evaluation.js @@ -168,6 +168,11 @@ export function evaluate(): { confident: boolean; value: any } { if (path.isReferencedIdentifier()) { let binding = path.scope.getBinding(node.name); + + if (binding && binding.constantViolations.length > 0) { + return deopt(binding.path); + } + if (binding && binding.hasValue) { return binding.value; } else { diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index be0d5c0f1b..84db801024 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -51,4 +51,39 @@ suite("evaluation", function () { true ); }); + + test("should deopt when var is redeclared in the same scope", function () { + assert.strictEqual( + getPath("var x = 2; var y = x + 2; { var x = 3 }").get("body.1.declarations.0.init").evaluate().confident, + false + ); + }); + + test("it should not deopt vars in different scope", function () { + const input = "var a = 5; function x() { var a = 5; var b = a + 1; } var b = a + 2"; + assert.strictEqual( + getPath(input).get("body.1.body.body.1.declarations.0.init").evaluate().value, + 6 + ); + assert.strictEqual( + getPath(input).get("body.2.declarations.0.init").evaluate().value, + 7 + ); + }); + + test("it should not deopt let/const inside blocks", function () { + assert.strictEqual( + getPath("let x = 5; { let x = 1; } let y = x + 5").get("body.2.declarations.0.init").evaluate().value, + 10 + ); + const constExample = "const d = true; if (d && true || false) { const d = false; d && 5; }"; + assert.strictEqual( + getPath(constExample).get("body.1.test").evaluate().value, + true + ); + assert.strictEqual( + getPath(constExample).get("body.1.consequent.body.1").evaluate().value, + false + ); + }); });