clean up scope API
This commit is contained in:
@@ -407,7 +407,7 @@ File.prototype.generateUid = function (name, scope) {
|
||||
do {
|
||||
uid = this._generateUid(name, i);
|
||||
i++;
|
||||
} while (scope.has(uid));
|
||||
} while (scope.hasReference(uid));
|
||||
return uid;
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ var t = require("../../types");
|
||||
var getObjRef = function (node, nodes, file, scope) {
|
||||
var ref;
|
||||
if (t.isIdentifier(node)) {
|
||||
if (scope.has(node.name, true)) {
|
||||
if (scope.hasBinding(node.name)) {
|
||||
// this variable is declared in scope so we can be 100% sure
|
||||
// that evaluating it multiple times wont trigger a getter
|
||||
// or something else
|
||||
@@ -18,7 +18,7 @@ var getObjRef = function (node, nodes, file, scope) {
|
||||
} else if (t.isMemberExpression(node)) {
|
||||
ref = node.object;
|
||||
|
||||
if (t.isIdentifier(ref) && scope.has(ref.name)) {
|
||||
if (t.isIdentifier(ref) && scope.hasReference(ref.name)) {
|
||||
// the object reference that we need to save is locally declared
|
||||
// so as per the previous comment we can be 100% sure evaluating
|
||||
// it multiple times will be safe
|
||||
|
||||
@@ -14,7 +14,7 @@ var visitor = {
|
||||
|
||||
// check that we don't have a local variable declared as that removes the need
|
||||
// for the wrapper
|
||||
var localDeclar = scope.get(state.id, true);
|
||||
var localDeclar = scope.getBinding(state.id);
|
||||
if (localDeclar !== state.outerDeclar) return;
|
||||
|
||||
state.selfReference = true;
|
||||
@@ -32,7 +32,7 @@ exports.property = function (node, file, scope) {
|
||||
var state = {
|
||||
id: id,
|
||||
selfReference: false,
|
||||
outerDeclar: scope.get(id, true),
|
||||
outerDeclar: scope.getBinding(id),
|
||||
};
|
||||
|
||||
traverse(node, visitor, scope, state);
|
||||
|
||||
@@ -147,7 +147,7 @@ DefaultFormatter.prototype.remapExportAssignment = function (node) {
|
||||
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
|
||||
var localExports = this.localExports;
|
||||
var name = node.name;
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBinding(name);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getModuleName = function () {
|
||||
|
||||
@@ -11,7 +11,7 @@ var visitor = {
|
||||
if (!declared) return;
|
||||
|
||||
// declared node is different in this scope
|
||||
if (scope.get(node.name, true) !== declared) return;
|
||||
if (scope.getBinding(node.name) !== declared) return;
|
||||
|
||||
var declaredLoc = declared.loc;
|
||||
var referenceLoc = node.loc;
|
||||
|
||||
@@ -110,7 +110,7 @@ function replace(node, parent, scope, context, remaps) {
|
||||
var remap = remaps[node.name];
|
||||
if (!remap) return;
|
||||
|
||||
var own = scope.get(node.name, true);
|
||||
var own = scope.getBinding(node.name);
|
||||
if (own === remap.node) {
|
||||
node.name = remap.uid;
|
||||
} else {
|
||||
@@ -149,7 +149,7 @@ BlockScoping.prototype.remap = function () {
|
||||
// this is the defining identifier of a declaration
|
||||
var ref = letRefs[key];
|
||||
|
||||
if (scope.parentHas(key)) {
|
||||
if (scope.parentHasReference(key)) {
|
||||
var uid = scope.generateUidIdentifier(ref.name).name;
|
||||
ref.name = uid;
|
||||
|
||||
@@ -227,7 +227,7 @@ var letReferenceFunctionVisitor = {
|
||||
|
||||
// this scope has a variable with the same name so it couldn't belong
|
||||
// to our let scope
|
||||
if (scope.hasOwn(node.name, true)) return;
|
||||
if (scope.hasOwnBinding(node.name)) return;
|
||||
|
||||
// not a part of our scope
|
||||
if (!state.letReferences[node.name]) return;
|
||||
|
||||
@@ -21,7 +21,7 @@ var visitor = {
|
||||
// constant so we can just ignore it
|
||||
if (id === constant) continue;
|
||||
|
||||
var localBinding = scope.get(key, true);
|
||||
var localBinding = scope.getBinding(key);
|
||||
if (localBinding !== constant) continue;
|
||||
|
||||
throw state.file.errorWithNode(id, key + " is read-only");
|
||||
|
||||
@@ -13,7 +13,7 @@ var hasDefaults = function (node) {
|
||||
|
||||
var iifeVisitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
if (t.isReferencedIdentifier(node, parent) && state.scope.hasOwn(node.name)) {
|
||||
if (t.isReferencedIdentifier(node, parent) && state.scope.hasOwnReference(node.name)) {
|
||||
state.iife = true;
|
||||
context.stop();
|
||||
}
|
||||
@@ -48,7 +48,7 @@ exports.Function = function (node, parent, scope) {
|
||||
node.params[i] = scope.generateUidIdentifier("x");
|
||||
|
||||
if (!state.iife) {
|
||||
if (t.isIdentifier(right) && scope.hasOwn(right.name)) {
|
||||
if (t.isIdentifier(right) && scope.hasOwnReference(right.name)) {
|
||||
state.iife = true;
|
||||
} else {
|
||||
traverse(right, iifeVisitor, scope, state);
|
||||
|
||||
@@ -35,7 +35,7 @@ var astVisitor = {
|
||||
context.skip();
|
||||
return t.prependToMemberExpression(node, file.get("coreIdentifier"));
|
||||
}
|
||||
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && contains(ALIASABLE_CONSTRUCTORS, node.name) && !scope.get(node.name, true)) {
|
||||
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && contains(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBinding(node.name)) {
|
||||
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
|
||||
return t.memberExpression(file.get("coreIdentifier"), node);
|
||||
} else if (t.isCallExpression(node)) {
|
||||
|
||||
@@ -7,19 +7,19 @@ exports.optional = true;
|
||||
|
||||
exports.Identifier = function (node, parent, scope, context, file) {
|
||||
if (!t.isReferenced(node, parent)) return;
|
||||
if (scope.has(node.name, true)) return;
|
||||
if (scope.hasBinding(node.name)) return;
|
||||
|
||||
var msg = "Reference to undeclared variable";
|
||||
|
||||
// get the closest declaration to offer as a suggestion
|
||||
// the variable name may have just been mistyped
|
||||
|
||||
var declarations = scope.getAllDeclarations();
|
||||
var bindings = scope.getAllBindings();
|
||||
|
||||
var closest;
|
||||
var shortest = -1;
|
||||
|
||||
for (var name in declarations) {
|
||||
for (var name in bindings) {
|
||||
var distance = levenshtein(node.name, name);
|
||||
if (distance <= 0 || distance > 3) continue;
|
||||
if (distance <= shortest) continue;
|
||||
|
||||
@@ -14,7 +14,7 @@ var has = require("lodash/object/has");
|
||||
var t = require("../types");
|
||||
|
||||
/**
|
||||
* This searches the current "scope" and collects all references/declarations
|
||||
* This searches the current "scope" and collects all references/bindings
|
||||
* within.
|
||||
*
|
||||
* @param {Node} block
|
||||
@@ -31,8 +31,9 @@ function Scope(block, parentBlock, parent, file) {
|
||||
this.block = block;
|
||||
|
||||
var info = this.getInfo();
|
||||
this.references = info.references;
|
||||
this.declarations = info.declarations;
|
||||
|
||||
this.references = info.references;
|
||||
this.bindings = info.bindings;
|
||||
this.declarationKinds = info.declarationKinds;
|
||||
}
|
||||
|
||||
@@ -113,7 +114,7 @@ Scope.prototype.generateUidBasedOnNode = function (parent) {
|
||||
*/
|
||||
|
||||
Scope.prototype.generateTempBasedOnNode = function (node) {
|
||||
if (t.isIdentifier(node) && this.has(node.name, true)) {
|
||||
if (t.isIdentifier(node) && this.hasBinding(node.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -154,7 +155,7 @@ var functionVariableVisitor = {
|
||||
|
||||
var programReferenceVisitor = {
|
||||
enter: function (node, parent, scope, context, add) {
|
||||
if (t.isReferencedIdentifier(node, parent) && !scope.has(node.name)) {
|
||||
if (t.isReferencedIdentifier(node, parent) && !scope.hasReference(node.name)) {
|
||||
add(node, true);
|
||||
}
|
||||
}
|
||||
@@ -177,8 +178,10 @@ Scope.prototype.getInfo = function () {
|
||||
if (block._scopeInfo) return block._scopeInfo;
|
||||
|
||||
var info = block._scopeInfo = {};
|
||||
var references = info.references = object();
|
||||
var declarations = info.declarations = object();
|
||||
|
||||
var bindings = info.bindings = object();
|
||||
var references = info.references = object();
|
||||
var types = info.types = object();
|
||||
var declarationKinds = info.declarationKinds = {
|
||||
"var": object(),
|
||||
"let": object(),
|
||||
@@ -197,7 +200,7 @@ Scope.prototype.getInfo = function () {
|
||||
}
|
||||
}
|
||||
|
||||
extend(declarations, ids);
|
||||
extend(bindings, ids);
|
||||
|
||||
var kinds = declarationKinds[node.kind];
|
||||
if (kinds) extend(kinds, ids);
|
||||
@@ -312,7 +315,7 @@ Scope.prototype.addDeclarationToFunctionScope = function (kind, node) {
|
||||
var scope = this.getFunctionParent();
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
|
||||
extend(scope.declarations, ids);
|
||||
extend(scope.bindings, ids);
|
||||
extend(scope.references, ids);
|
||||
|
||||
// this ignores the duplicate declaration logic specified in `getInfo`
|
||||
@@ -334,17 +337,17 @@ Scope.prototype.getFunctionParent = function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Walks the scope tree and gathers **all** declarations.
|
||||
* Walks the scope tree and gathers **all** bindings.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Scope.prototype.getAllDeclarations = function () {
|
||||
Scope.prototype.getAllBindings = function () {
|
||||
var ids = object();
|
||||
|
||||
var scope = this;
|
||||
do {
|
||||
defaults(ids, scope.declarations);
|
||||
defaults(ids, scope.bindings);
|
||||
scope = scope.parent;
|
||||
} while (scope);
|
||||
|
||||
@@ -377,8 +380,8 @@ Scope.prototype.getAllDeclarationsOfKind = function (kind) {
|
||||
* @param {Boolean} [decl]
|
||||
*/
|
||||
|
||||
Scope.prototype.get = function (id, decl) {
|
||||
return id && (this.getOwn(id, decl) || this.parentGet(id, decl));
|
||||
Scope.prototype.getReference = function (id, decl) {
|
||||
return id && (this.getOwnReference(id, decl) || this.parentGetReference(id, decl));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -388,9 +391,9 @@ Scope.prototype.get = function (id, decl) {
|
||||
* @param {Boolean} [decl]
|
||||
*/
|
||||
|
||||
Scope.prototype.getOwn = function (id, decl) {
|
||||
Scope.prototype.getOwnReference = function (id, decl) {
|
||||
var refs = this.references;
|
||||
if (decl) refs = this.declarations;
|
||||
if (decl) refs = this.bindings;
|
||||
return has(refs, id) && refs[id];
|
||||
};
|
||||
|
||||
@@ -401,8 +404,8 @@ Scope.prototype.getOwn = function (id, decl) {
|
||||
* @param {Boolean} [decl]
|
||||
*/
|
||||
|
||||
Scope.prototype.parentGet = function (id, decl) {
|
||||
return this.parent && this.parent.get(id, decl);
|
||||
Scope.prototype.parentGetReference = function (id, decl) {
|
||||
return this.parent && this.parent.getReference(id, decl);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -413,10 +416,10 @@ Scope.prototype.parentGet = function (id, decl) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Scope.prototype.has = function (id, decl) {
|
||||
Scope.prototype.hasReference = function (id, decl) {
|
||||
if (!id) return false;
|
||||
if (this.hasOwn(id, decl)) return true;
|
||||
if (this.parentHas(id, decl)) return true;
|
||||
if (this.hasOwnReference(id, decl)) return true;
|
||||
if (this.parentHasReference(id, decl)) return true;
|
||||
if (contains(Scope.defaultDeclarations, id)) return true;
|
||||
return false;
|
||||
};
|
||||
@@ -429,8 +432,8 @@ Scope.prototype.has = function (id, decl) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Scope.prototype.hasOwn = function (id, decl) {
|
||||
return !!this.getOwn(id, decl);
|
||||
Scope.prototype.hasOwnReference = function (id, decl) {
|
||||
return !!this.getOwnReference(id, decl);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -441,6 +444,30 @@ Scope.prototype.hasOwn = function (id, decl) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Scope.prototype.parentHas = function (id, decl) {
|
||||
return this.parent && this.parent.has(id, decl);
|
||||
Scope.prototype.parentHasReference = function (id, decl) {
|
||||
return this.parent && this.parent.hasReference(id, decl);
|
||||
};
|
||||
|
||||
Scope.prototype.getBinding = function (id) {
|
||||
return this.getReference(id, true);
|
||||
};
|
||||
|
||||
Scope.prototype.hasBinding = function (id) {
|
||||
return this.hasReference(id, true);
|
||||
};
|
||||
|
||||
Scope.prototype.getOwnBinding = function (id) {
|
||||
return this.getOwnReference(id, true);
|
||||
};
|
||||
|
||||
Scope.prototype.hasOwnBinding = function (id) {
|
||||
return this.hasOwnReference(id, true);
|
||||
};
|
||||
|
||||
Scope.prototype.parentGetBinding = function (id) {
|
||||
return this.parentGetReference(id, true);
|
||||
};
|
||||
|
||||
Scope.prototype.parentHasBinding = function (id) {
|
||||
return this.parentHasReference(id, true);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user