diff --git a/packages/babel-plugin-transform-block-scoping/src/index.js b/packages/babel-plugin-transform-block-scoping/src/index.js index cf2b8f550c..0a674c27b1 100644 --- a/packages/babel-plugin-transform-block-scoping/src/index.js +++ b/packages/babel-plugin-transform-block-scoping/src/index.js @@ -338,6 +338,18 @@ const loopVisitor = { }, }; +function isStrict(path) { + return !!path.find(({ node }) => { + if (t.isProgram(node)) { + if (node.sourceType === "module") return true; + } else if (!t.isBlockStatement(node)) return false; + + return node.directives.some( + directive => directive.value.value === "use strict", + ); + }); +} + class BlockScoping { constructor( loopPath?: NodePath, @@ -486,7 +498,10 @@ class BlockScoping { const parentBinding = scope.parent.getOwnBinding(key); if ( binding.kind === "hoisted" && - (!parentBinding || isVar(parentBinding.path.parent)) + !binding.path.node.async && + !binding.path.node.generator && + (!parentBinding || isVar(parentBinding.path.parent)) && + !isStrict(binding.path.parentPath) ) { continue; } diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async-generator/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async-generator/input.js new file mode 100644 index 0000000000..1597234a17 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async-generator/input.js @@ -0,0 +1,16 @@ +// NOTE: When compiling async generators, +// we run the async-generator-functions transform +// as soon as in Program:enter, so when the block-scoping plugin +// runs it has already been transpiled to a plain function. +// The functions is thus visible to the outer scope. +// This is a bug. + +if (true) { + async function* run() { + return true; + } +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async-generator/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async-generator/output.js new file mode 100644 index 0000000000..2d59fb4262 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async-generator/output.js @@ -0,0 +1,15 @@ +// NOTE: When compiling async generators, +// we run the async-generator-functions transform +// as soon as in Program:enter, so when the block-scoping plugin +// runs it has already been transpiled to a plain function. +// The functions is thus visible to the outer scope. +// This is a bug. +if (true) { + var _run = async function* () { + return true; + }; +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/input.js new file mode 100644 index 0000000000..76a4c593f0 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/input.js @@ -0,0 +1,9 @@ +if (true) { + async function run() { + return true; + } +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/options.json new file mode 100644 index 0000000000..f596954c3d --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "transform-block-scoping", + "transform-block-scoped-functions", + "transform-async-to-generator" + ] +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/output.js new file mode 100644 index 0000000000..f9fe43527b --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/output.js @@ -0,0 +1,19 @@ +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } + +function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } + +if (true) { + var _run = /*#__PURE__*/function () { + var _ref = _asyncToGenerator(function* () { + return true; + }); + + return function _run() { + return _ref.apply(this, arguments); + }; + }(); +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/input.js new file mode 100644 index 0000000000..3586bf70c5 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/input.js @@ -0,0 +1,9 @@ +if (true) { + function* run() { + return true; + } +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/options.json b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/options.json new file mode 100644 index 0000000000..e0e4407ab4 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "transform-block-scoping", + "transform-block-scoped-functions", + "transform-regenerator" + ] +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/output.js new file mode 100644 index 0000000000..dc656985c2 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-generator/output.js @@ -0,0 +1,20 @@ +if (true) { + var _run = /*#__PURE__*/regeneratorRuntime.mark(function _callee() { + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + return _context.abrupt("return", true); + + case 1: + case "end": + return _context.stop(); + } + } + }, _callee); + }); +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-module/input.mjs b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-module/input.mjs new file mode 100644 index 0000000000..19d0ca04b0 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-module/input.mjs @@ -0,0 +1,9 @@ +if (true) { + function run() { + return true; + } +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-module/output.mjs b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-module/output.mjs new file mode 100644 index 0000000000..de9b198518 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-module/output.mjs @@ -0,0 +1,9 @@ +if (true) { + var _run = function () { + return true; + }; +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/input.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/input.js new file mode 100644 index 0000000000..26283df207 --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/input.js @@ -0,0 +1,11 @@ +"use strict"; + +if (true) { + function run() { + return true; + } +} + +function test() { + return run(); +} diff --git a/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/output.js b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/output.js new file mode 100644 index 0000000000..59d945fd0c --- /dev/null +++ b/packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/output.js @@ -0,0 +1,11 @@ +"use strict"; + +if (true) { + var _run = function () { + return true; + }; +} + +function test() { + return run(); +}