123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- "use strict";;
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- var types_1 = __importDefault(require("./types"));
- var hasOwn = Object.prototype.hasOwnProperty;
- function scopePlugin(fork) {
- var types = fork.use(types_1.default);
- var Type = types.Type;
- var namedTypes = types.namedTypes;
- var Node = namedTypes.Node;
- var Expression = namedTypes.Expression;
- var isArray = types.builtInTypes.array;
- var b = types.builders;
- var Scope = function Scope(path, parentScope) {
- if (!(this instanceof Scope)) {
- throw new Error("Scope constructor cannot be invoked without 'new'");
- }
- ScopeType.assert(path.value);
- var depth;
- if (parentScope) {
- if (!(parentScope instanceof Scope)) {
- throw new Error("");
- }
- depth = parentScope.depth + 1;
- }
- else {
- parentScope = null;
- depth = 0;
- }
- Object.defineProperties(this, {
- path: { value: path },
- node: { value: path.value },
- isGlobal: { value: !parentScope, enumerable: true },
- depth: { value: depth },
- parent: { value: parentScope },
- bindings: { value: {} },
- types: { value: {} },
- });
- };
- var scopeTypes = [
- // Program nodes introduce global scopes.
- namedTypes.Program,
- // Function is the supertype of FunctionExpression,
- // FunctionDeclaration, ArrowExpression, etc.
- namedTypes.Function,
- // In case you didn't know, the caught parameter shadows any variable
- // of the same name in an outer scope.
- namedTypes.CatchClause
- ];
- var ScopeType = Type.or.apply(Type, scopeTypes);
- Scope.isEstablishedBy = function (node) {
- return ScopeType.check(node);
- };
- var Sp = Scope.prototype;
- // Will be overridden after an instance lazily calls scanScope.
- Sp.didScan = false;
- Sp.declares = function (name) {
- this.scan();
- return hasOwn.call(this.bindings, name);
- };
- Sp.declaresType = function (name) {
- this.scan();
- return hasOwn.call(this.types, name);
- };
- Sp.declareTemporary = function (prefix) {
- if (prefix) {
- if (!/^[a-z$_]/i.test(prefix)) {
- throw new Error("");
- }
- }
- else {
- prefix = "t$";
- }
- // Include this.depth in the name to make sure the name does not
- // collide with any variables in nested/enclosing scopes.
- prefix += this.depth.toString(36) + "$";
- this.scan();
- var index = 0;
- while (this.declares(prefix + index)) {
- ++index;
- }
- var name = prefix + index;
- return this.bindings[name] = types.builders.identifier(name);
- };
- Sp.injectTemporary = function (identifier, init) {
- identifier || (identifier = this.declareTemporary());
- var bodyPath = this.path.get("body");
- if (namedTypes.BlockStatement.check(bodyPath.value)) {
- bodyPath = bodyPath.get("body");
- }
- bodyPath.unshift(b.variableDeclaration("var", [b.variableDeclarator(identifier, init || null)]));
- return identifier;
- };
- Sp.scan = function (force) {
- if (force || !this.didScan) {
- for (var name in this.bindings) {
- // Empty out this.bindings, just in cases.
- delete this.bindings[name];
- }
- scanScope(this.path, this.bindings, this.types);
- this.didScan = true;
- }
- };
- Sp.getBindings = function () {
- this.scan();
- return this.bindings;
- };
- Sp.getTypes = function () {
- this.scan();
- return this.types;
- };
- function scanScope(path, bindings, scopeTypes) {
- var node = path.value;
- ScopeType.assert(node);
- if (namedTypes.CatchClause.check(node)) {
- // A catch clause establishes a new scope but the only variable
- // bound in that scope is the catch parameter. Any other
- // declarations create bindings in the outer scope.
- addPattern(path.get("param"), bindings);
- }
- else {
- recursiveScanScope(path, bindings, scopeTypes);
- }
- }
- function recursiveScanScope(path, bindings, scopeTypes) {
- var node = path.value;
- if (path.parent &&
- namedTypes.FunctionExpression.check(path.parent.node) &&
- path.parent.node.id) {
- addPattern(path.parent.get("id"), bindings);
- }
- if (!node) {
- // None of the remaining cases matter if node is falsy.
- }
- else if (isArray.check(node)) {
- path.each(function (childPath) {
- recursiveScanChild(childPath, bindings, scopeTypes);
- });
- }
- else if (namedTypes.Function.check(node)) {
- path.get("params").each(function (paramPath) {
- addPattern(paramPath, bindings);
- });
- recursiveScanChild(path.get("body"), bindings, scopeTypes);
- }
- else if ((namedTypes.TypeAlias && namedTypes.TypeAlias.check(node)) ||
- (namedTypes.InterfaceDeclaration && namedTypes.InterfaceDeclaration.check(node)) ||
- (namedTypes.TSTypeAliasDeclaration && namedTypes.TSTypeAliasDeclaration.check(node)) ||
- (namedTypes.TSInterfaceDeclaration && namedTypes.TSInterfaceDeclaration.check(node))) {
- addTypePattern(path.get("id"), scopeTypes);
- }
- else if (namedTypes.VariableDeclarator.check(node)) {
- addPattern(path.get("id"), bindings);
- recursiveScanChild(path.get("init"), bindings, scopeTypes);
- }
- else if (node.type === "ImportSpecifier" ||
- node.type === "ImportNamespaceSpecifier" ||
- node.type === "ImportDefaultSpecifier") {
- addPattern(
- // Esprima used to use the .name field to refer to the local
- // binding identifier for ImportSpecifier nodes, but .id for
- // ImportNamespaceSpecifier and ImportDefaultSpecifier nodes.
- // ESTree/Acorn/ESpree use .local for all three node types.
- path.get(node.local ? "local" :
- node.name ? "name" : "id"), bindings);
- }
- else if (Node.check(node) && !Expression.check(node)) {
- types.eachField(node, function (name, child) {
- var childPath = path.get(name);
- if (!pathHasValue(childPath, child)) {
- throw new Error("");
- }
- recursiveScanChild(childPath, bindings, scopeTypes);
- });
- }
- }
- function pathHasValue(path, value) {
- if (path.value === value) {
- return true;
- }
- // Empty arrays are probably produced by defaults.emptyArray, in which
- // case is makes sense to regard them as equivalent, if not ===.
- if (Array.isArray(path.value) &&
- path.value.length === 0 &&
- Array.isArray(value) &&
- value.length === 0) {
- return true;
- }
- return false;
- }
- function recursiveScanChild(path, bindings, scopeTypes) {
- var node = path.value;
- if (!node || Expression.check(node)) {
- // Ignore falsy values and Expressions.
- }
- else if (namedTypes.FunctionDeclaration.check(node) &&
- node.id !== null) {
- addPattern(path.get("id"), bindings);
- }
- else if (namedTypes.ClassDeclaration &&
- namedTypes.ClassDeclaration.check(node)) {
- addPattern(path.get("id"), bindings);
- }
- else if (ScopeType.check(node)) {
- if (namedTypes.CatchClause.check(node) &&
- // TODO Broaden this to accept any pattern.
- namedTypes.Identifier.check(node.param)) {
- var catchParamName = node.param.name;
- var hadBinding = hasOwn.call(bindings, catchParamName);
- // Any declarations that occur inside the catch body that do
- // not have the same name as the catch parameter should count
- // as bindings in the outer scope.
- recursiveScanScope(path.get("body"), bindings, scopeTypes);
- // If a new binding matching the catch parameter name was
- // created while scanning the catch body, ignore it because it
- // actually refers to the catch parameter and not the outer
- // scope that we're currently scanning.
- if (!hadBinding) {
- delete bindings[catchParamName];
- }
- }
- }
- else {
- recursiveScanScope(path, bindings, scopeTypes);
- }
- }
- function addPattern(patternPath, bindings) {
- var pattern = patternPath.value;
- namedTypes.Pattern.assert(pattern);
- if (namedTypes.Identifier.check(pattern)) {
- if (hasOwn.call(bindings, pattern.name)) {
- bindings[pattern.name].push(patternPath);
- }
- else {
- bindings[pattern.name] = [patternPath];
- }
- }
- else if (namedTypes.AssignmentPattern &&
- namedTypes.AssignmentPattern.check(pattern)) {
- addPattern(patternPath.get('left'), bindings);
- }
- else if (namedTypes.ObjectPattern &&
- namedTypes.ObjectPattern.check(pattern)) {
- patternPath.get('properties').each(function (propertyPath) {
- var property = propertyPath.value;
- if (namedTypes.Pattern.check(property)) {
- addPattern(propertyPath, bindings);
- }
- else if (namedTypes.Property.check(property)) {
- addPattern(propertyPath.get('value'), bindings);
- }
- else if (namedTypes.SpreadProperty &&
- namedTypes.SpreadProperty.check(property)) {
- addPattern(propertyPath.get('argument'), bindings);
- }
- });
- }
- else if (namedTypes.ArrayPattern &&
- namedTypes.ArrayPattern.check(pattern)) {
- patternPath.get('elements').each(function (elementPath) {
- var element = elementPath.value;
- if (namedTypes.Pattern.check(element)) {
- addPattern(elementPath, bindings);
- }
- else if (namedTypes.SpreadElement &&
- namedTypes.SpreadElement.check(element)) {
- addPattern(elementPath.get("argument"), bindings);
- }
- });
- }
- else if (namedTypes.PropertyPattern &&
- namedTypes.PropertyPattern.check(pattern)) {
- addPattern(patternPath.get('pattern'), bindings);
- }
- else if ((namedTypes.SpreadElementPattern &&
- namedTypes.SpreadElementPattern.check(pattern)) ||
- (namedTypes.SpreadPropertyPattern &&
- namedTypes.SpreadPropertyPattern.check(pattern))) {
- addPattern(patternPath.get('argument'), bindings);
- }
- }
- function addTypePattern(patternPath, types) {
- var pattern = patternPath.value;
- namedTypes.Pattern.assert(pattern);
- if (namedTypes.Identifier.check(pattern)) {
- if (hasOwn.call(types, pattern.name)) {
- types[pattern.name].push(patternPath);
- }
- else {
- types[pattern.name] = [patternPath];
- }
- }
- }
- Sp.lookup = function (name) {
- for (var scope = this; scope; scope = scope.parent)
- if (scope.declares(name))
- break;
- return scope;
- };
- Sp.lookupType = function (name) {
- for (var scope = this; scope; scope = scope.parent)
- if (scope.declaresType(name))
- break;
- return scope;
- };
- Sp.getGlobalScope = function () {
- var scope = this;
- while (!scope.isGlobal)
- scope = scope.parent;
- return scope;
- };
- return Scope;
- }
- exports.default = scopePlugin;
- module.exports = exports["default"];
|