Merge pull request #3406 from babel/fix-scope-info
Update scope info after block-scoping transform
This commit is contained in:
commit
b35013abe5
@ -3,3 +3,9 @@ export default class Foo {
|
|||||||
const baz = 0;
|
const baz = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function foo() {
|
||||||
|
async function bar() {
|
||||||
|
const baz = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,11 +1,68 @@
|
|||||||
export default class Foo {
|
"use strict";
|
||||||
bar() {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
return babelHelpers.asyncToGenerator(regeneratorRuntime.mark(function _callee() {
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||||
|
|
||||||
|
var foo = function () {
|
||||||
|
var ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee3() {
|
||||||
|
var bar = function () {
|
||||||
|
var ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee2() {
|
||||||
|
var baz;
|
||||||
|
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||||
|
while (1) {
|
||||||
|
switch (_context2.prev = _context2.next) {
|
||||||
|
case 0:
|
||||||
|
baz = {};
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
case "end":
|
||||||
|
return _context2.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, _callee2, this);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return function bar() {
|
||||||
|
return ref.apply(this, arguments);
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
return regeneratorRuntime.wrap(function _callee3$(_context3) {
|
||||||
|
while (1) {
|
||||||
|
switch (_context3.prev = _context3.next) {
|
||||||
|
case 0:
|
||||||
|
case "end":
|
||||||
|
return _context3.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, _callee3, this);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return function foo() {
|
||||||
|
return ref.apply(this, arguments);
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
|
|
||||||
|
var Foo = function () {
|
||||||
|
function Foo() {
|
||||||
|
_classCallCheck(this, Foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(Foo, [{
|
||||||
|
key: "bar",
|
||||||
|
value: function () {
|
||||||
|
var ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
|
||||||
var baz;
|
var baz;
|
||||||
return regeneratorRuntime.wrap(function _callee$(_context) {
|
return regeneratorRuntime.wrap(function _callee$(_context) {
|
||||||
while (1) switch (_context.prev = _context.next) {
|
while (1) {
|
||||||
|
switch (_context.prev = _context.next) {
|
||||||
case 0:
|
case 0:
|
||||||
baz = 0;
|
baz = 0;
|
||||||
|
|
||||||
@ -13,7 +70,19 @@ export default class Foo {
|
|||||||
case "end":
|
case "end":
|
||||||
return _context.stop();
|
return _context.stop();
|
||||||
}
|
}
|
||||||
}, _callee, _this);
|
|
||||||
}))();
|
|
||||||
}
|
}
|
||||||
|
}, _callee, this);
|
||||||
|
}));
|
||||||
|
|
||||||
|
function bar() {
|
||||||
|
return ref.apply(this, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bar;
|
||||||
|
}()
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return Foo;
|
||||||
|
}();
|
||||||
|
|
||||||
|
exports.default = Foo;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"plugins": ["external-helpers", "transform-async-to-generator", "transform-regenerator"]
|
"plugins": ["transform-async-to-generator"],
|
||||||
|
"presets": ["es2015"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,10 +88,6 @@ function convertBlockScopedToVar(path, parent, scope, moveBindingsToParent = fal
|
|||||||
// Move bindings from current block scope to function scope.
|
// Move bindings from current block scope to function scope.
|
||||||
if (moveBindingsToParent) {
|
if (moveBindingsToParent) {
|
||||||
const parentScope = scope.getFunctionParent();
|
const parentScope = scope.getFunctionParent();
|
||||||
if (parentScope === scope) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ids = path.getBindingIdentifiers();
|
const ids = path.getBindingIdentifiers();
|
||||||
for (let name in ids) {
|
for (let name in ids) {
|
||||||
scope.removeOwnBinding(name);
|
scope.removeOwnBinding(name);
|
||||||
@ -302,7 +298,6 @@ class BlockScoping {
|
|||||||
this.outsideLetReferences = Object.create(null);
|
this.outsideLetReferences = Object.create(null);
|
||||||
this.hasLetReferences = false;
|
this.hasLetReferences = false;
|
||||||
this.letReferences = Object.create(null);
|
this.letReferences = Object.create(null);
|
||||||
this.letReferencesDeclars = [];
|
|
||||||
this.body = [];
|
this.body = [];
|
||||||
|
|
||||||
if (loopPath) {
|
if (loopPath) {
|
||||||
@ -325,7 +320,10 @@ class BlockScoping {
|
|||||||
let needsClosure = this.getLetReferences();
|
let needsClosure = this.getLetReferences();
|
||||||
|
|
||||||
// this is a block within a `Function/Program` so we can safely leave it be
|
// this is a block within a `Function/Program` so we can safely leave it be
|
||||||
if (t.isFunction(this.parent) || t.isProgram(this.block)) return;
|
if (t.isFunction(this.parent) || t.isProgram(this.block)) {
|
||||||
|
this.updateScopeInfo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// we can skip everything
|
// we can skip everything
|
||||||
if (!this.hasLetReferences) return;
|
if (!this.hasLetReferences) return;
|
||||||
@ -336,18 +334,33 @@ class BlockScoping {
|
|||||||
this.remap();
|
this.remap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateScopeInfo();
|
||||||
|
|
||||||
if (this.loopLabel && !t.isLabeledStatement(this.loopParent)) {
|
if (this.loopLabel && !t.isLabeledStatement(this.loopParent)) {
|
||||||
return t.labeledStatement(this.loopLabel, this.loop);
|
return t.labeledStatement(this.loopLabel, this.loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateScopeInfo() {
|
||||||
|
let scope = this.scope;
|
||||||
|
let parentScope = scope.getFunctionParent();
|
||||||
|
let letRefs = this.letReferences;
|
||||||
|
|
||||||
|
for (let key in letRefs) {
|
||||||
|
let ref = letRefs[key];
|
||||||
|
const binding = scope.getBinding(ref.name);
|
||||||
|
if (!binding) continue;
|
||||||
|
if (binding.kind === "let" || binding.kind === "const") {
|
||||||
|
scope.removeOwnBinding(ref.name);
|
||||||
|
parentScope.registerBinding("var", binding.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
remap() {
|
remap() {
|
||||||
let hasRemaps = false;
|
let hasRemaps = false;
|
||||||
let letRefs = this.letReferences;
|
let letRefs = this.letReferences;
|
||||||
let scope = this.scope;
|
let scope = this.scope;
|
||||||
|
|
||||||
const parentScope = scope.getFunctionParent();
|
|
||||||
|
|
||||||
// alright, so since we aren't wrapping this block in a closure
|
// alright, so since we aren't wrapping this block in a closure
|
||||||
// we have to check if any of our let variables collide with
|
// we have to check if any of our let variables collide with
|
||||||
// those in upper scopes and then if they do, generate a uid
|
// those in upper scopes and then if they do, generate a uid
|
||||||
@ -370,18 +383,6 @@ class BlockScoping {
|
|||||||
uid: uid
|
uid: uid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove binding from block scope so it's moved to function scope.
|
|
||||||
if (parentScope !== scope) {
|
|
||||||
scope.removeOwnBinding(ref.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move bindings to parent scope.
|
|
||||||
if (parentScope !== scope) {
|
|
||||||
for (let declar of (this.letReferencesDeclars: Array<Object>)) {
|
|
||||||
parentScope.registerBinding("var", declar);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasRemaps) return;
|
if (!hasRemaps) return;
|
||||||
@ -535,7 +536,6 @@ class BlockScoping {
|
|||||||
let declarPath = this.blockPath.get("body")[i];
|
let declarPath = this.blockPath.get("body")[i];
|
||||||
if (isBlockScoped(declar)) {
|
if (isBlockScoped(declar)) {
|
||||||
convertBlockScopedToVar(declarPath, block, this.scope);
|
convertBlockScopedToVar(declarPath, block, this.scope);
|
||||||
this.letReferencesDeclars.push(declarPath);
|
|
||||||
}
|
}
|
||||||
declarators = declarators.concat(declar.declarations || declar);
|
declarators = declarators.concat(declar.declarations || declar);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,6 +71,9 @@ export default class Binding {
|
|||||||
|
|
||||||
reassign(path: Object) {
|
reassign(path: Object) {
|
||||||
this.constant = false;
|
this.constant = false;
|
||||||
|
if (this.constantViolations.indexOf(path) !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.constantViolations.push(path);
|
this.constantViolations.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user