From 0188556b361401e4991952c2700a267adcc527dd Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 17 Oct 2014 21:19:51 +1100 Subject: [PATCH] forbid function declarations that reference block scoped variables --- lib/6to5/transformers/let-scoping.js | 19 ++++++------------- .../no-nested-function-declarations/actual.js | 7 +++++++ .../options.json | 3 +++ 3 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 test/fixtures/syntax/let-scoping/no-nested-function-declarations/actual.js create mode 100644 test/fixtures/syntax/let-scoping/no-nested-function-declarations/options.json diff --git a/lib/6to5/transformers/let-scoping.js b/lib/6to5/transformers/let-scoping.js index 7345cdd7a7..cd7a00efdc 100644 --- a/lib/6to5/transformers/let-scoping.js +++ b/lib/6to5/transformers/let-scoping.js @@ -26,8 +26,10 @@ exports.VariableDeclaration = function (node, parent, file) { if (util.isReferenced(node, parent)) return id; }; + var isProgram = parent.type === "Program"; + var replace = function (node, parent) { - if (_.contains(traverse.FUNCTION_TYPES, node.type)) { + if (!isProgram && _.contains(traverse.FUNCTION_TYPES, node.type)) { var letReferences = []; traverse(node, function (node, parent) { @@ -37,21 +39,12 @@ exports.VariableDeclaration = function (node, parent, file) { }); if (letReferences.length) { - var callNode = function () { + if (node.type === "FunctionDeclaration") { + throw new Error("`FunctionDeclaration`s that use `let` and `constant` references aren't allowed outside of the root scope"); + } else { return b.callExpression(b.functionExpression(null, letReferences, b.blockStatement([ b.returnStatement(node) ])), letReferences); - }; - - if (node.type === "FunctionDeclaration") { - util.ensureExpressionType(node); - var declar = b.variableDeclaration("var", [ - b.variableDeclarator(node.id, callNode()) - ]); - declar._blockHoist = true; - return declar; - } else { - return callNode(); } } else { return false; diff --git a/test/fixtures/syntax/let-scoping/no-nested-function-declarations/actual.js b/test/fixtures/syntax/let-scoping/no-nested-function-declarations/actual.js new file mode 100644 index 0000000000..dc5a13878d --- /dev/null +++ b/test/fixtures/syntax/let-scoping/no-nested-function-declarations/actual.js @@ -0,0 +1,7 @@ +var numbers = [1, 2, 3]; + +for (let i in numbers) { + function foo() { + return i; + } +} diff --git a/test/fixtures/syntax/let-scoping/no-nested-function-declarations/options.json b/test/fixtures/syntax/let-scoping/no-nested-function-declarations/options.json new file mode 100644 index 0000000000..ddd3d8df0f --- /dev/null +++ b/test/fixtures/syntax/let-scoping/no-nested-function-declarations/options.json @@ -0,0 +1,3 @@ +{ + "throws": "`FunctionDeclaration`s that use `let` and `constant` references aren't allowed outside of the root scope" +}