|
|
|
"use strict";
|
|
|
|
|
|
|
|
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
|
|
|
|
|
|
|
|
var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
|
|
|
|
|
|
|
|
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
var WeakMap = _interopRequire(require("es6-weak-map"));
|
|
|
|
|
|
|
|
var _scope = require("./scope");
|
|
|
|
|
|
|
|
var Scope = _interopRequire(_scope);
|
|
|
|
|
|
|
|
var assert = _interopRequire(require("assert"));
|
|
|
|
|
|
|
|
var GlobalScope = _scope.GlobalScope;
|
|
|
|
var CatchScope = _scope.CatchScope;
|
|
|
|
var WithScope = _scope.WithScope;
|
|
|
|
var ModuleScope = _scope.ModuleScope;
|
|
|
|
var ClassScope = _scope.ClassScope;
|
|
|
|
var SwitchScope = _scope.SwitchScope;
|
|
|
|
var FunctionScope = _scope.FunctionScope;
|
|
|
|
var ForScope = _scope.ForScope;
|
|
|
|
var TDZScope = _scope.TDZScope;
|
|
|
|
var FunctionExpressionNameScope = _scope.FunctionExpressionNameScope;
|
|
|
|
var BlockScope = _scope.BlockScope;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class ScopeManager
|
|
|
|
*/
|
|
|
|
|
|
|
|
var ScopeManager = (function () {
|
|
|
|
function ScopeManager(options) {
|
|
|
|
_classCallCheck(this, ScopeManager);
|
|
|
|
|
|
|
|
this.scopes = [];
|
|
|
|
this.globalScope = null;
|
|
|
|
this.__nodeToScope = new WeakMap();
|
|
|
|
this.__currentScope = null;
|
|
|
|
this.__options = options;
|
|
|
|
this.__declaredVariables = new WeakMap();
|
|
|
|
}
|
|
|
|
|
|
|
|
_createClass(ScopeManager, {
|
|
|
|
__useDirective: {
|
|
|
|
value: function __useDirective() {
|
|
|
|
return this.__options.directive;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__isOptimistic: {
|
|
|
|
value: function __isOptimistic() {
|
|
|
|
return this.__options.optimistic;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__ignoreEval: {
|
|
|
|
value: function __ignoreEval() {
|
|
|
|
return this.__options.ignoreEval;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__isNodejsScope: {
|
|
|
|
value: function __isNodejsScope() {
|
|
|
|
return this.__options.nodejsScope;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
isModule: {
|
|
|
|
value: function isModule() {
|
|
|
|
return this.__options.sourceType === "module";
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__get: {
|
|
|
|
|
|
|
|
// Returns appropriate scope for this node.
|
|
|
|
|
|
|
|
value: function __get(node) {
|
|
|
|
return this.__nodeToScope.get(node);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
getDeclaredVariables: {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get variables that are declared by the node.
|
|
|
|
*
|
|
|
|
* "are declared by the node" means the node is same as `Variable.defs[].node` or `Variable.defs[].parent`.
|
|
|
|
* If the node declares nothing, this method returns an empty array.
|
|
|
|
* CAUTION: This API is experimental. See https://github.com/estools/escope/pull/69 for more details.
|
|
|
|
*
|
|
|
|
* @param {Esprima.Node} node - a node to get.
|
|
|
|
* @returns {Variable[]} variables that declared by the node.
|
|
|
|
*/
|
|
|
|
|
|
|
|
value: function getDeclaredVariables(node) {
|
|
|
|
return this.__declaredVariables.get(node) || [];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
acquire: {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* acquire scope from node.
|
|
|
|
* @method ScopeManager#acquire
|
|
|
|
* @param {Esprima.Node} node - node for the acquired scope.
|
|
|
|
* @param {boolean=} inner - look up the most inner scope, default value is false.
|
|
|
|
* @return {Scope?}
|
|
|
|
*/
|
|
|
|
|
|
|
|
value: function acquire(node, inner) {
|
|
|
|
var scopes, scope, i, iz;
|
|
|
|
|
|
|
|
function predicate(scope) {
|
|
|
|
if (scope.type === "function" && scope.functionExpressionScope) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (scope.type === "TDZ") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
scopes = this.__get(node);
|
|
|
|
if (!scopes || scopes.length === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Heuristic selection from all scopes.
|
|
|
|
// If you would like to get all scopes, please use ScopeManager#acquireAll.
|
|
|
|
if (scopes.length === 1) {
|
|
|
|
return scopes[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inner) {
|
|
|
|
for (i = scopes.length - 1; i >= 0; --i) {
|
|
|
|
scope = scopes[i];
|
|
|
|
if (predicate(scope)) {
|
|
|
|
return scope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0, iz = scopes.length; i < iz; ++i) {
|
|
|
|
scope = scopes[i];
|
|
|
|
if (predicate(scope)) {
|
|
|
|
return scope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
acquireAll: {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* acquire all scopes from node.
|
|
|
|
* @method ScopeManager#acquireAll
|
|
|
|
* @param {Esprima.Node} node - node for the acquired scope.
|
|
|
|
* @return {Scope[]?}
|
|
|
|
*/
|
|
|
|
|
|
|
|
value: function acquireAll(node) {
|
|
|
|
return this.__get(node);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
release: {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* release the node.
|
|
|
|
* @method ScopeManager#release
|
|
|
|
* @param {Esprima.Node} node - releasing node.
|
|
|
|
* @param {boolean=} inner - look up the most inner scope, default value is false.
|
|
|
|
* @return {Scope?} upper scope for the node.
|
|
|
|
*/
|
|
|
|
|
|
|
|
value: function release(node, inner) {
|
|
|
|
var scopes, scope;
|
|
|
|
scopes = this.__get(node);
|
|
|
|
if (scopes && scopes.length) {
|
|
|
|
scope = scopes[0].upper;
|
|
|
|
if (!scope) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return this.acquire(scope.block, inner);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
attach: {
|
|
|
|
value: function attach() {}
|
|
|
|
},
|
|
|
|
detach: {
|
|
|
|
value: function detach() {}
|
|
|
|
},
|
|
|
|
__nestScope: {
|
|
|
|
value: function __nestScope(scope) {
|
|
|
|
if (scope instanceof GlobalScope) {
|
|
|
|
assert(this.__currentScope === null);
|
|
|
|
this.globalScope = scope;
|
|
|
|
}
|
|
|
|
this.__currentScope = scope;
|
|
|
|
return scope;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestGlobalScope: {
|
|
|
|
value: function __nestGlobalScope(node) {
|
|
|
|
return this.__nestScope(new GlobalScope(this, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestBlockScope: {
|
|
|
|
value: function __nestBlockScope(node, isMethodDefinition) {
|
|
|
|
return this.__nestScope(new BlockScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestFunctionScope: {
|
|
|
|
value: function __nestFunctionScope(node, isMethodDefinition) {
|
|
|
|
return this.__nestScope(new FunctionScope(this, this.__currentScope, node, isMethodDefinition));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestForScope: {
|
|
|
|
value: function __nestForScope(node) {
|
|
|
|
return this.__nestScope(new ForScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestCatchScope: {
|
|
|
|
value: function __nestCatchScope(node) {
|
|
|
|
return this.__nestScope(new CatchScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestWithScope: {
|
|
|
|
value: function __nestWithScope(node) {
|
|
|
|
return this.__nestScope(new WithScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestClassScope: {
|
|
|
|
value: function __nestClassScope(node) {
|
|
|
|
return this.__nestScope(new ClassScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestSwitchScope: {
|
|
|
|
value: function __nestSwitchScope(node) {
|
|
|
|
return this.__nestScope(new SwitchScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestModuleScope: {
|
|
|
|
value: function __nestModuleScope(node) {
|
|
|
|
return this.__nestScope(new ModuleScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestTDZScope: {
|
|
|
|
value: function __nestTDZScope(node) {
|
|
|
|
return this.__nestScope(new TDZScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__nestFunctionExpressionNameScope: {
|
|
|
|
value: function __nestFunctionExpressionNameScope(node) {
|
|
|
|
return this.__nestScope(new FunctionExpressionNameScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__isES6: {
|
|
|
|
value: function __isES6() {
|
|
|
|
return this.__options.ecmaVersion >= 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return ScopeManager;
|
|
|
|
})();
|
|
|
|
|
|
|
|
module.exports = ScopeManager;
|
|
|
|
|
|
|
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
|
|
|
//# sourceMappingURL=data:application/json;base64,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
|