Fix annex B block function hoisting semantics (#12512)
This commit is contained in:
parent
70fa1b3d49
commit
bfb51362c7
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
if (true) {
|
||||
async function run() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
return run();
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
"transform-block-scoping",
|
||||
"transform-block-scoped-functions",
|
||||
"transform-async-to-generator"
|
||||
]
|
||||
}
|
||||
19
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/output.js
vendored
Normal file
19
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-async/output.js
vendored
Normal file
@ -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();
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
if (true) {
|
||||
function* run() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
return run();
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
"transform-block-scoping",
|
||||
"transform-block-scoped-functions",
|
||||
"transform-regenerator"
|
||||
]
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
if (true) {
|
||||
function run() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
return run();
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
if (true) {
|
||||
var _run = function () {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function test() {
|
||||
return run();
|
||||
}
|
||||
11
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/input.js
vendored
Normal file
11
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/input.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
if (true) {
|
||||
function run() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function test() {
|
||||
return run();
|
||||
}
|
||||
11
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/output.js
vendored
Normal file
11
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10046-strict/output.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
if (true) {
|
||||
var _run = function () {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function test() {
|
||||
return run();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user