|
|
|
'use strict';
|
|
|
|
|
|
|
|
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; }; }(); /*
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
|
value: true
|
|
|
|
});
|
|
|
|
|
|
|
|
var _es6WeakMap = require('es6-weak-map');
|
|
|
|
|
|
|
|
var _es6WeakMap2 = _interopRequireDefault(_es6WeakMap);
|
|
|
|
|
|
|
|
var _scope = require('./scope');
|
|
|
|
|
|
|
|
var _scope2 = _interopRequireDefault(_scope);
|
|
|
|
|
|
|
|
var _assert = require('assert');
|
|
|
|
|
|
|
|
var _assert2 = _interopRequireDefault(_assert);
|
|
|
|
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class ScopeManager
|
|
|
|
*/
|
|
|
|
|
|
|
|
var ScopeManager = function () {
|
|
|
|
function ScopeManager(options) {
|
|
|
|
_classCallCheck(this, ScopeManager);
|
|
|
|
|
|
|
|
this.scopes = [];
|
|
|
|
this.globalScope = null;
|
|
|
|
this.__nodeToScope = new _es6WeakMap2.default();
|
|
|
|
this.__currentScope = null;
|
|
|
|
this.__options = options;
|
|
|
|
this.__declaredVariables = new _es6WeakMap2.default();
|
|
|
|
}
|
|
|
|
|
|
|
|
_createClass(ScopeManager, [{
|
|
|
|
key: '__useDirective',
|
|
|
|
value: function __useDirective() {
|
|
|
|
return this.__options.directive;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__isOptimistic',
|
|
|
|
value: function __isOptimistic() {
|
|
|
|
return this.__options.optimistic;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__ignoreEval',
|
|
|
|
value: function __ignoreEval() {
|
|
|
|
return this.__options.ignoreEval;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__isNodejsScope',
|
|
|
|
value: function __isNodejsScope() {
|
|
|
|
return this.__options.nodejsScope;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'isModule',
|
|
|
|
value: function isModule() {
|
|
|
|
return this.__options.sourceType === 'module';
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'isImpliedStrict',
|
|
|
|
value: function isImpliedStrict() {
|
|
|
|
return this.__options.impliedStrict;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'isStrictModeSupported',
|
|
|
|
value: function isStrictModeSupported() {
|
|
|
|
return this.__options.ecmaVersion >= 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns appropriate scope for this node.
|
|
|
|
|
|
|
|
}, {
|
|
|
|
key: '__get',
|
|
|
|
value: function __get(node) {
|
|
|
|
return this.__nodeToScope.get(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
}, {
|
|
|
|
key: 'getDeclaredVariables',
|
|
|
|
value: function getDeclaredVariables(node) {
|
|
|
|
return this.__declaredVariables.get(node) || [];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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?}
|
|
|
|
*/
|
|
|
|
|
|
|
|
}, {
|
|
|
|
key: 'acquire',
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* acquire all scopes from node.
|
|
|
|
* @method ScopeManager#acquireAll
|
|
|
|
* @param {Esprima.Node} node - node for the acquired scope.
|
|
|
|
* @return {Scope[]?}
|
|
|
|
*/
|
|
|
|
|
|
|
|
}, {
|
|
|
|
key: 'acquireAll',
|
|
|
|
value: function acquireAll(node) {
|
|
|
|
return this.__get(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
}, {
|
|
|
|
key: 'release',
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: 'attach',
|
|
|
|
value: function attach() {}
|
|
|
|
}, {
|
|
|
|
key: 'detach',
|
|
|
|
value: function detach() {}
|
|
|
|
}, {
|
|
|
|
key: '__nestScope',
|
|
|
|
value: function __nestScope(scope) {
|
|
|
|
if (scope instanceof _scope.GlobalScope) {
|
|
|
|
(0, _assert2.default)(this.__currentScope === null);
|
|
|
|
this.globalScope = scope;
|
|
|
|
}
|
|
|
|
this.__currentScope = scope;
|
|
|
|
return scope;
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestGlobalScope',
|
|
|
|
value: function __nestGlobalScope(node) {
|
|
|
|
return this.__nestScope(new _scope.GlobalScope(this, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestBlockScope',
|
|
|
|
value: function __nestBlockScope(node, isMethodDefinition) {
|
|
|
|
return this.__nestScope(new _scope.BlockScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestFunctionScope',
|
|
|
|
value: function __nestFunctionScope(node, isMethodDefinition) {
|
|
|
|
return this.__nestScope(new _scope.FunctionScope(this, this.__currentScope, node, isMethodDefinition));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestForScope',
|
|
|
|
value: function __nestForScope(node) {
|
|
|
|
return this.__nestScope(new _scope.ForScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestCatchScope',
|
|
|
|
value: function __nestCatchScope(node) {
|
|
|
|
return this.__nestScope(new _scope.CatchScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestWithScope',
|
|
|
|
value: function __nestWithScope(node) {
|
|
|
|
return this.__nestScope(new _scope.WithScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestClassScope',
|
|
|
|
value: function __nestClassScope(node) {
|
|
|
|
return this.__nestScope(new _scope.ClassScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestSwitchScope',
|
|
|
|
value: function __nestSwitchScope(node) {
|
|
|
|
return this.__nestScope(new _scope.SwitchScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestModuleScope',
|
|
|
|
value: function __nestModuleScope(node) {
|
|
|
|
return this.__nestScope(new _scope.ModuleScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestTDZScope',
|
|
|
|
value: function __nestTDZScope(node) {
|
|
|
|
return this.__nestScope(new _scope.TDZScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__nestFunctionExpressionNameScope',
|
|
|
|
value: function __nestFunctionExpressionNameScope(node) {
|
|
|
|
return this.__nestScope(new _scope.FunctionExpressionNameScope(this, this.__currentScope, node));
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
key: '__isES6',
|
|
|
|
value: function __isES6() {
|
|
|
|
return this.__options.ecmaVersion >= 6;
|
|
|
|
}
|
|
|
|
}]);
|
|
|
|
|
|
|
|
return ScopeManager;
|
|
|
|
}();
|
|
|
|
|
|
|
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
|
|
|
|
|
|
|
exports.default = ScopeManager;
|
|
|
|
//# sourceMappingURL=data:application/json;base64,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
|