640 lines
77 KiB
JavaScript
640 lines
77 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
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 _estraverse = require('estraverse');
|
||
|
|
||
|
var _esrecurse = require('esrecurse');
|
||
|
|
||
|
var _esrecurse2 = _interopRequireDefault(_esrecurse);
|
||
|
|
||
|
var _reference = require('./reference');
|
||
|
|
||
|
var _reference2 = _interopRequireDefault(_reference);
|
||
|
|
||
|
var _variable = require('./variable');
|
||
|
|
||
|
var _variable2 = _interopRequireDefault(_variable);
|
||
|
|
||
|
var _patternVisitor = require('./pattern-visitor');
|
||
|
|
||
|
var _patternVisitor2 = _interopRequireDefault(_patternVisitor);
|
||
|
|
||
|
var _definition = require('./definition');
|
||
|
|
||
|
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"); } }
|
||
|
|
||
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||
|
|
||
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
|
||
|
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.
|
||
|
*/
|
||
|
|
||
|
|
||
|
function traverseIdentifierInPattern(options, rootPattern, referencer, callback) {
|
||
|
// Call the callback at left hand identifier nodes, and Collect right hand nodes.
|
||
|
var visitor = new _patternVisitor2.default(options, rootPattern, callback);
|
||
|
visitor.visit(rootPattern);
|
||
|
|
||
|
// Process the right hand nodes recursively.
|
||
|
if (referencer != null) {
|
||
|
visitor.rightHandNodes.forEach(referencer.visit, referencer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Importing ImportDeclaration.
|
||
|
// http://people.mozilla.org/~jorendorff/es6-draft.html#sec-moduledeclarationinstantiation
|
||
|
// https://github.com/estree/estree/blob/master/es6.md#importdeclaration
|
||
|
// FIXME: Now, we don't create module environment, because the context is
|
||
|
// implementation dependent.
|
||
|
|
||
|
var Importer = function (_esrecurse$Visitor) {
|
||
|
_inherits(Importer, _esrecurse$Visitor);
|
||
|
|
||
|
function Importer(declaration, referencer) {
|
||
|
_classCallCheck(this, Importer);
|
||
|
|
||
|
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Importer).call(this, null, referencer.options));
|
||
|
|
||
|
_this.declaration = declaration;
|
||
|
_this.referencer = referencer;
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
_createClass(Importer, [{
|
||
|
key: 'visitImport',
|
||
|
value: function visitImport(id, specifier) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
this.referencer.visitPattern(id, function (pattern) {
|
||
|
_this2.referencer.currentScope().__define(pattern, new _definition.Definition(_variable2.default.ImportBinding, pattern, specifier, _this2.declaration, null, null));
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ImportNamespaceSpecifier',
|
||
|
value: function ImportNamespaceSpecifier(node) {
|
||
|
var local = node.local || node.id;
|
||
|
if (local) {
|
||
|
this.visitImport(local, node);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ImportDefaultSpecifier',
|
||
|
value: function ImportDefaultSpecifier(node) {
|
||
|
var local = node.local || node.id;
|
||
|
this.visitImport(local, node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ImportSpecifier',
|
||
|
value: function ImportSpecifier(node) {
|
||
|
var local = node.local || node.id;
|
||
|
if (node.name) {
|
||
|
this.visitImport(node.name, node);
|
||
|
} else {
|
||
|
this.visitImport(local, node);
|
||
|
}
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return Importer;
|
||
|
}(_esrecurse2.default.Visitor);
|
||
|
|
||
|
// Referencing variables and creating bindings.
|
||
|
|
||
|
|
||
|
var Referencer = function (_esrecurse$Visitor2) {
|
||
|
_inherits(Referencer, _esrecurse$Visitor2);
|
||
|
|
||
|
function Referencer(options, scopeManager) {
|
||
|
_classCallCheck(this, Referencer);
|
||
|
|
||
|
var _this3 = _possibleConstructorReturn(this, Object.getPrototypeOf(Referencer).call(this, null, options));
|
||
|
|
||
|
_this3.options = options;
|
||
|
_this3.scopeManager = scopeManager;
|
||
|
_this3.parent = null;
|
||
|
_this3.isInnerMethodDefinition = false;
|
||
|
return _this3;
|
||
|
}
|
||
|
|
||
|
_createClass(Referencer, [{
|
||
|
key: 'currentScope',
|
||
|
value: function currentScope() {
|
||
|
return this.scopeManager.__currentScope;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'close',
|
||
|
value: function close(node) {
|
||
|
while (this.currentScope() && node === this.currentScope().block) {
|
||
|
this.scopeManager.__currentScope = this.currentScope().__close(this.scopeManager);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'pushInnerMethodDefinition',
|
||
|
value: function pushInnerMethodDefinition(isInnerMethodDefinition) {
|
||
|
var previous = this.isInnerMethodDefinition;
|
||
|
this.isInnerMethodDefinition = isInnerMethodDefinition;
|
||
|
return previous;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'popInnerMethodDefinition',
|
||
|
value: function popInnerMethodDefinition(isInnerMethodDefinition) {
|
||
|
this.isInnerMethodDefinition = isInnerMethodDefinition;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'materializeTDZScope',
|
||
|
value: function materializeTDZScope(node, iterationNode) {
|
||
|
// http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-forin-div-ofexpressionevaluation-abstract-operation
|
||
|
// TDZ scope hides the declaration's names.
|
||
|
this.scopeManager.__nestTDZScope(node, iterationNode);
|
||
|
this.visitVariableDeclaration(this.currentScope(), _variable2.default.TDZ, iterationNode.left, 0, true);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'materializeIterationScope',
|
||
|
value: function materializeIterationScope(node) {
|
||
|
var _this4 = this;
|
||
|
|
||
|
// Generate iteration scope for upper ForIn/ForOf Statements.
|
||
|
var letOrConstDecl;
|
||
|
this.scopeManager.__nestForScope(node);
|
||
|
letOrConstDecl = node.left;
|
||
|
this.visitVariableDeclaration(this.currentScope(), _variable2.default.Variable, letOrConstDecl, 0);
|
||
|
this.visitPattern(letOrConstDecl.declarations[0].id, function (pattern) {
|
||
|
_this4.currentScope().__referencing(pattern, _reference2.default.WRITE, node.right, null, true, true);
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'referencingDefaultValue',
|
||
|
value: function referencingDefaultValue(pattern, assignments, maybeImplicitGlobal, init) {
|
||
|
var scope = this.currentScope();
|
||
|
assignments.forEach(function (assignment) {
|
||
|
scope.__referencing(pattern, _reference2.default.WRITE, assignment.right, maybeImplicitGlobal, pattern !== assignment.left, init);
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitPattern',
|
||
|
value: function visitPattern(node, options, callback) {
|
||
|
if (typeof options === 'function') {
|
||
|
callback = options;
|
||
|
options = { processRightHandNodes: false };
|
||
|
}
|
||
|
traverseIdentifierInPattern(this.options, node, options.processRightHandNodes ? this : null, callback);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitFunction',
|
||
|
value: function visitFunction(node) {
|
||
|
var _this5 = this;
|
||
|
|
||
|
var i, iz;
|
||
|
// FunctionDeclaration name is defined in upper scope
|
||
|
// NOTE: Not referring variableScope. It is intended.
|
||
|
// Since
|
||
|
// in ES5, FunctionDeclaration should be in FunctionBody.
|
||
|
// in ES6, FunctionDeclaration should be block scoped.
|
||
|
if (node.type === _estraverse.Syntax.FunctionDeclaration) {
|
||
|
// id is defined in upper scope
|
||
|
this.currentScope().__define(node.id, new _definition.Definition(_variable2.default.FunctionName, node.id, node, null, null, null));
|
||
|
}
|
||
|
|
||
|
// FunctionExpression with name creates its special scope;
|
||
|
// FunctionExpressionNameScope.
|
||
|
if (node.type === _estraverse.Syntax.FunctionExpression && node.id) {
|
||
|
this.scopeManager.__nestFunctionExpressionNameScope(node);
|
||
|
}
|
||
|
|
||
|
// Consider this function is in the MethodDefinition.
|
||
|
this.scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition);
|
||
|
|
||
|
// Process parameter declarations.
|
||
|
for (i = 0, iz = node.params.length; i < iz; ++i) {
|
||
|
this.visitPattern(node.params[i], { processRightHandNodes: true }, function (pattern, info) {
|
||
|
_this5.currentScope().__define(pattern, new _definition.ParameterDefinition(pattern, node, i, info.rest));
|
||
|
|
||
|
_this5.referencingDefaultValue(pattern, info.assignments, null, true);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// if there's a rest argument, add that
|
||
|
if (node.rest) {
|
||
|
this.visitPattern({
|
||
|
type: 'RestElement',
|
||
|
argument: node.rest
|
||
|
}, function (pattern) {
|
||
|
_this5.currentScope().__define(pattern, new _definition.ParameterDefinition(pattern, node, node.params.length, true));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Skip BlockStatement to prevent creating BlockStatement scope.
|
||
|
if (node.body.type === _estraverse.Syntax.BlockStatement) {
|
||
|
this.visitChildren(node.body);
|
||
|
} else {
|
||
|
this.visit(node.body);
|
||
|
}
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitClass',
|
||
|
value: function visitClass(node) {
|
||
|
if (node.type === _estraverse.Syntax.ClassDeclaration) {
|
||
|
this.currentScope().__define(node.id, new _definition.Definition(_variable2.default.ClassName, node.id, node, null, null, null));
|
||
|
}
|
||
|
|
||
|
// FIXME: Maybe consider TDZ.
|
||
|
this.visit(node.superClass);
|
||
|
|
||
|
this.scopeManager.__nestClassScope(node);
|
||
|
|
||
|
if (node.id) {
|
||
|
this.currentScope().__define(node.id, new _definition.Definition(_variable2.default.ClassName, node.id, node));
|
||
|
}
|
||
|
this.visit(node.body);
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitProperty',
|
||
|
value: function visitProperty(node) {
|
||
|
var previous, isMethodDefinition;
|
||
|
if (node.computed) {
|
||
|
this.visit(node.key);
|
||
|
}
|
||
|
|
||
|
isMethodDefinition = node.type === _estraverse.Syntax.MethodDefinition;
|
||
|
if (isMethodDefinition) {
|
||
|
previous = this.pushInnerMethodDefinition(true);
|
||
|
}
|
||
|
this.visit(node.value);
|
||
|
if (isMethodDefinition) {
|
||
|
this.popInnerMethodDefinition(previous);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitForIn',
|
||
|
value: function visitForIn(node) {
|
||
|
var _this6 = this;
|
||
|
|
||
|
if (node.left.type === _estraverse.Syntax.VariableDeclaration && node.left.kind !== 'var') {
|
||
|
this.materializeTDZScope(node.right, node);
|
||
|
this.visit(node.right);
|
||
|
this.close(node.right);
|
||
|
|
||
|
this.materializeIterationScope(node);
|
||
|
this.visit(node.body);
|
||
|
this.close(node);
|
||
|
} else {
|
||
|
if (node.left.type === _estraverse.Syntax.VariableDeclaration) {
|
||
|
this.visit(node.left);
|
||
|
this.visitPattern(node.left.declarations[0].id, function (pattern) {
|
||
|
_this6.currentScope().__referencing(pattern, _reference2.default.WRITE, node.right, null, true, true);
|
||
|
});
|
||
|
} else {
|
||
|
this.visitPattern(node.left, { processRightHandNodes: true }, function (pattern, info) {
|
||
|
var maybeImplicitGlobal = null;
|
||
|
if (!_this6.currentScope().isStrict) {
|
||
|
maybeImplicitGlobal = {
|
||
|
pattern: pattern,
|
||
|
node: node
|
||
|
};
|
||
|
}
|
||
|
_this6.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
|
||
|
_this6.currentScope().__referencing(pattern, _reference2.default.WRITE, node.right, maybeImplicitGlobal, true, false);
|
||
|
});
|
||
|
}
|
||
|
this.visit(node.right);
|
||
|
this.visit(node.body);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitVariableDeclaration',
|
||
|
value: function visitVariableDeclaration(variableTargetScope, type, node, index, fromTDZ) {
|
||
|
var _this7 = this;
|
||
|
|
||
|
// If this was called to initialize a TDZ scope, this needs to make definitions, but doesn't make references.
|
||
|
var decl, init;
|
||
|
|
||
|
decl = node.declarations[index];
|
||
|
init = decl.init;
|
||
|
this.visitPattern(decl.id, { processRightHandNodes: !fromTDZ }, function (pattern, info) {
|
||
|
variableTargetScope.__define(pattern, new _definition.Definition(type, pattern, decl, node, index, node.kind));
|
||
|
|
||
|
if (!fromTDZ) {
|
||
|
_this7.referencingDefaultValue(pattern, info.assignments, null, true);
|
||
|
}
|
||
|
if (init) {
|
||
|
_this7.currentScope().__referencing(pattern, _reference2.default.WRITE, init, null, !info.topLevel, true);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'AssignmentExpression',
|
||
|
value: function AssignmentExpression(node) {
|
||
|
var _this8 = this;
|
||
|
|
||
|
if (_patternVisitor2.default.isPattern(node.left)) {
|
||
|
if (node.operator === '=') {
|
||
|
this.visitPattern(node.left, { processRightHandNodes: true }, function (pattern, info) {
|
||
|
var maybeImplicitGlobal = null;
|
||
|
if (!_this8.currentScope().isStrict) {
|
||
|
maybeImplicitGlobal = {
|
||
|
pattern: pattern,
|
||
|
node: node
|
||
|
};
|
||
|
}
|
||
|
_this8.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
|
||
|
_this8.currentScope().__referencing(pattern, _reference2.default.WRITE, node.right, maybeImplicitGlobal, !info.topLevel, false);
|
||
|
});
|
||
|
} else {
|
||
|
this.currentScope().__referencing(node.left, _reference2.default.RW, node.right);
|
||
|
}
|
||
|
} else {
|
||
|
this.visit(node.left);
|
||
|
}
|
||
|
this.visit(node.right);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'CatchClause',
|
||
|
value: function CatchClause(node) {
|
||
|
var _this9 = this;
|
||
|
|
||
|
this.scopeManager.__nestCatchScope(node);
|
||
|
|
||
|
this.visitPattern(node.param, { processRightHandNodes: true }, function (pattern, info) {
|
||
|
_this9.currentScope().__define(pattern, new _definition.Definition(_variable2.default.CatchClause, node.param, node, null, null, null));
|
||
|
_this9.referencingDefaultValue(pattern, info.assignments, null, true);
|
||
|
});
|
||
|
this.visit(node.body);
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'Program',
|
||
|
value: function Program(node) {
|
||
|
this.scopeManager.__nestGlobalScope(node);
|
||
|
|
||
|
if (this.scopeManager.__isNodejsScope()) {
|
||
|
// Force strictness of GlobalScope to false when using node.js scope.
|
||
|
this.currentScope().isStrict = false;
|
||
|
this.scopeManager.__nestFunctionScope(node, false);
|
||
|
}
|
||
|
|
||
|
if (this.scopeManager.__isES6() && this.scopeManager.isModule()) {
|
||
|
this.scopeManager.__nestModuleScope(node);
|
||
|
}
|
||
|
|
||
|
if (this.scopeManager.isStrictModeSupported() && this.scopeManager.isImpliedStrict()) {
|
||
|
this.currentScope().isStrict = true;
|
||
|
}
|
||
|
|
||
|
this.visitChildren(node);
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'Identifier',
|
||
|
value: function Identifier(node) {
|
||
|
this.currentScope().__referencing(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'UpdateExpression',
|
||
|
value: function UpdateExpression(node) {
|
||
|
if (_patternVisitor2.default.isPattern(node.argument)) {
|
||
|
this.currentScope().__referencing(node.argument, _reference2.default.RW, null);
|
||
|
} else {
|
||
|
this.visitChildren(node);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'MemberExpression',
|
||
|
value: function MemberExpression(node) {
|
||
|
this.visit(node.object);
|
||
|
if (node.computed) {
|
||
|
this.visit(node.property);
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'Property',
|
||
|
value: function Property(node) {
|
||
|
this.visitProperty(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'MethodDefinition',
|
||
|
value: function MethodDefinition(node) {
|
||
|
this.visitProperty(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'BreakStatement',
|
||
|
value: function BreakStatement() {}
|
||
|
}, {
|
||
|
key: 'ContinueStatement',
|
||
|
value: function ContinueStatement() {}
|
||
|
}, {
|
||
|
key: 'LabeledStatement',
|
||
|
value: function LabeledStatement(node) {
|
||
|
this.visit(node.body);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ForStatement',
|
||
|
value: function ForStatement(node) {
|
||
|
// Create ForStatement declaration.
|
||
|
// NOTE: In ES6, ForStatement dynamically generates
|
||
|
// per iteration environment. However, escope is
|
||
|
// a static analyzer, we only generate one scope for ForStatement.
|
||
|
if (node.init && node.init.type === _estraverse.Syntax.VariableDeclaration && node.init.kind !== 'var') {
|
||
|
this.scopeManager.__nestForScope(node);
|
||
|
}
|
||
|
|
||
|
this.visitChildren(node);
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ClassExpression',
|
||
|
value: function ClassExpression(node) {
|
||
|
this.visitClass(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ClassDeclaration',
|
||
|
value: function ClassDeclaration(node) {
|
||
|
this.visitClass(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'CallExpression',
|
||
|
value: function CallExpression(node) {
|
||
|
// Check this is direct call to eval
|
||
|
if (!this.scopeManager.__ignoreEval() && node.callee.type === _estraverse.Syntax.Identifier && node.callee.name === 'eval') {
|
||
|
// NOTE: This should be `variableScope`. Since direct eval call always creates Lexical environment and
|
||
|
// let / const should be enclosed into it. Only VariableDeclaration affects on the caller's environment.
|
||
|
this.currentScope().variableScope.__detectEval();
|
||
|
}
|
||
|
this.visitChildren(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'BlockStatement',
|
||
|
value: function BlockStatement(node) {
|
||
|
if (this.scopeManager.__isES6()) {
|
||
|
this.scopeManager.__nestBlockScope(node);
|
||
|
}
|
||
|
|
||
|
this.visitChildren(node);
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ThisExpression',
|
||
|
value: function ThisExpression() {
|
||
|
this.currentScope().variableScope.__detectThis();
|
||
|
}
|
||
|
}, {
|
||
|
key: 'WithStatement',
|
||
|
value: function WithStatement(node) {
|
||
|
this.visit(node.object);
|
||
|
// Then nest scope for WithStatement.
|
||
|
this.scopeManager.__nestWithScope(node);
|
||
|
|
||
|
this.visit(node.body);
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'VariableDeclaration',
|
||
|
value: function VariableDeclaration(node) {
|
||
|
var variableTargetScope, i, iz, decl;
|
||
|
variableTargetScope = node.kind === 'var' ? this.currentScope().variableScope : this.currentScope();
|
||
|
for (i = 0, iz = node.declarations.length; i < iz; ++i) {
|
||
|
decl = node.declarations[i];
|
||
|
this.visitVariableDeclaration(variableTargetScope, _variable2.default.Variable, node, i);
|
||
|
if (decl.init) {
|
||
|
this.visit(decl.init);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// sec 13.11.8
|
||
|
|
||
|
}, {
|
||
|
key: 'SwitchStatement',
|
||
|
value: function SwitchStatement(node) {
|
||
|
var i, iz;
|
||
|
|
||
|
this.visit(node.discriminant);
|
||
|
|
||
|
if (this.scopeManager.__isES6()) {
|
||
|
this.scopeManager.__nestSwitchScope(node);
|
||
|
}
|
||
|
|
||
|
for (i = 0, iz = node.cases.length; i < iz; ++i) {
|
||
|
this.visit(node.cases[i]);
|
||
|
}
|
||
|
|
||
|
this.close(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'FunctionDeclaration',
|
||
|
value: function FunctionDeclaration(node) {
|
||
|
this.visitFunction(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'FunctionExpression',
|
||
|
value: function FunctionExpression(node) {
|
||
|
this.visitFunction(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ForOfStatement',
|
||
|
value: function ForOfStatement(node) {
|
||
|
this.visitForIn(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ForInStatement',
|
||
|
value: function ForInStatement(node) {
|
||
|
this.visitForIn(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ArrowFunctionExpression',
|
||
|
value: function ArrowFunctionExpression(node) {
|
||
|
this.visitFunction(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ImportDeclaration',
|
||
|
value: function ImportDeclaration(node) {
|
||
|
var importer;
|
||
|
|
||
|
(0, _assert2.default)(this.scopeManager.__isES6() && this.scopeManager.isModule(), 'ImportDeclaration should appear when the mode is ES6 and in the module context.');
|
||
|
|
||
|
importer = new Importer(node, this);
|
||
|
importer.visit(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'visitExportDeclaration',
|
||
|
value: function visitExportDeclaration(node) {
|
||
|
if (node.source) {
|
||
|
return;
|
||
|
}
|
||
|
if (node.declaration) {
|
||
|
this.visit(node.declaration);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.visitChildren(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ExportDeclaration',
|
||
|
value: function ExportDeclaration(node) {
|
||
|
this.visitExportDeclaration(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ExportNamedDeclaration',
|
||
|
value: function ExportNamedDeclaration(node) {
|
||
|
this.visitExportDeclaration(node);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'ExportSpecifier',
|
||
|
value: function ExportSpecifier(node) {
|
||
|
var local = node.id || node.local;
|
||
|
this.visit(local);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'MetaProperty',
|
||
|
value: function MetaProperty() {
|
||
|
// do nothing.
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return Referencer;
|
||
|
}(_esrecurse2.default.Visitor);
|
||
|
|
||
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
||
|
|
||
|
|
||
|
exports.default = Referencer;
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInJlZmVyZW5jZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUF1QkE7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxTQUFTLDJCQUFULENBQXFDLE9BQXJDLEVBQThDLFdBQTlDLEVBQTJELFVBQTNELEVBQXVFLFFBQXZFLEVBQWlGOztBQUU3RSxRQUFJLFVBQVUsNkJBQW1CLE9BQW5CLEVBQTRCLFdBQTVCLEVBQXlDLFFBQXpDLENBQVYsQ0FGeUU7QUFHN0UsWUFBUSxLQUFSLENBQWMsV0FBZDs7O0FBSDZFLFFBTXpFLGNBQWMsSUFBZCxFQUFvQjtBQUNwQixnQkFBUSxjQUFSLENBQXVCLE9BQXZCLENBQStCLFdBQVcsS0FBWCxFQUFrQixVQUFqRCxFQURvQjtLQUF4QjtDQU5KOzs7Ozs7OztJQWlCTTs7O0FBQ0YsYUFERSxRQUNGLENBQVksV0FBWixFQUF5QixVQUF6QixFQUFxQzs4QkFEbkMsVUFDbUM7OzJFQURuQyxxQkFFUSxNQUFNLFdBQVcsT0FBWCxHQURxQjs7QUFFakMsY0FBSyxXQUFMLEdBQW1CLFdBQW5CLENBRmlDO0FBR2pDLGNBQUssVUFBTCxHQUFrQixVQUFsQixDQUhpQzs7S0FBckM7O2lCQURFOztvQ0FPVSxJQUFJLFdBQVc7OztBQUN2QixpQkFBSyxVQUFMLENBQWdCLFlBQWhCLENBQTZCLEVBQTdCLEVBQWlDLFVBQUMsT0FBRCxFQUFhO0FBQzFDLHVCQUFLLFVBQUwsQ0FBZ0IsWUFBaEIsR0FBK0IsUUFBL0IsQ0FBd0MsT0FBeEMsRUFDSSwyQkFDSSxtQkFBUyxhQUFULEVBQ0EsT0FGSixFQUdJLFNBSEosRUFJSSxPQUFLLFdBQUwsRUFDQSxJQUxKLEVBTUksSUFOSixDQURKLEVBRDBDO2FBQWIsQ0FBakMsQ0FEdUI7Ozs7aURBY0YsTUFBTTtBQUMzQixnQkFBSSxRQUFTLEtBQUssS0FBTCxJQUFjLEtBQUssRUFBTCxDQURBO0FBRTNCLGdCQUFJLEtBQUosRUFBVztBQUNQLHFCQUFLLFdBQUwsQ0FBaUIsS0FBakIsRUFBd0IsSUFBeEIsRUFETzthQUFYOzs7OytDQUttQixNQUFNO0FBQ3pCLGdCQUFJLFFBQVMsS0FBSyxLQUFMLElBQWMsS0FBSyxFQUFMLENBREY7QUFFekIsaUJBQUssV0FBTCxDQUFpQixLQUFqQixFQUF3QixJQUF4QixFQUZ5Qjs7Ozt3Q0FLYixNQUFNO0FBQ2xCLGdCQUFJLFFBQVMsS0FBSyxLQUFMLElBQWMsS0FBSyxFQUFMLENBRFQ7QUFFbEIsZ0JBQUksS0FBSyxJQUFMLEVBQVc7QUFDWCxxQkFBSyxXQUFMLENBQWlCLEtBQUssSUFBTCxFQUFXLElBQTVCLEVBRFc7YUFBZixNQUVPO0FBQ0gscUJBQUssV0FBTCxDQUFpQixLQUFqQixFQUF3QixJQUF4QixFQURHO2FBRlA7Ozs7V0FuQ0Y7RUFBaUIsb0JBQVUsT0FBVjs7Ozs7SUE0Q0Y7OztBQUNqQixhQURpQixVQUNqQixDQUFZLE9BQVosRUFBcUIsWUFBckIsRUFBbUM7OEJBRGxCLFlBQ2tCOzs0RUFEbEIsdUJBRVAsTUFBTSxVQURtQjs7QUFFL0IsZUFBSyxPQUFMLEdBQWUsT0FBZixDQUYrQjtBQUcvQixlQUFLLFlBQUwsR0FBb0IsWUFBcEIsQ0FIK0I7QUFJL0IsZUFBSyxNQUFMLEdBQWMsSUFBZCxDQUorQjtBQUsvQixlQUFLLHVCQUFMLEdBQStCLEtBQS9CLENBTCtCOztLQUFuQzs7aUJBRGlCOzt1Q0FTRjtBQUNYLG1CQUFPLEtBQUssWUFBTCxDQUFrQixjQUFsQixDQURJOzs7OzhCQUlULE1BQU07QUFDUixtQkFBTyxLQUFLLFlBQUwsTUFBdUIsU0FBUyxLQUFLLFlBQUwsR0FBb0IsS0FBcEIsRUFBMkI7QUFDOUQscUJBQUssWUFBTCxDQUFrQixjQUFsQixHQUFtQyxLQUFLLFlBQUwsR0FBb0IsT0FBcEIsQ0FBNEIsS0FBSyxZQUFMLENBQS9ELENBRDhEO2FBQWxFOzs7O2tEQUtzQix5QkFBeUI7QUFDL0MsZ0JBQUksV0FBVyxLQUFLLHVCQUFMLENBRGdDO0FBRS9DLGlCQUFLLHVCQUFMLEdBQStCLHVCQUEvQixDQUYrQztBQUcvQyxtQkFBTyxRQUFQLENBSCtDOzs7O2lEQU0xQix5QkFBeUI7QUFDOUMsaUJBQUssdUJBQUwsR0FBK0IsdUJBQS9CLENBRDhDOzs7OzRDQUk5QixNQUFNLGVBQWU7OztBQUdyQyxpQkFBSyxZQUFMLENBQWtCLGNBQWxCLENBQWlDLElBQWpDLEVBQXVDLGFBQXZDLEVBSHFDO0FBSXJDLGlCQUFLLHdCQUFMLENBQThCLEtBQUssWUFBTCxFQUE5QixFQUFtRCxtQkFBUyxHQUFULEVBQWMsY0FBYyxJQUFkLEVBQW9CLENBQXJGLEVBQXdGLElBQXhGLEVBSnFDOzs7O2tEQU9mLE1BQU07Ozs7QUFFNUIsZ0JBQUksY0FBSixDQUY0QjtBQUc1QixpQkFBSyxZQUFMLENBQWtCLGNBQWxCLENBQWlDLElBQWpDLEVBSDRCO0FBSTVCLDZCQUFpQixLQUFLLElBQUwsQ0FKVztBQUs1QixpQkFBSyx3QkFBTCxDQUE4QixLQUFLLFlBQUwsRUFBOUIsRUFBbUQsbUJBQVMsUUFBVCxFQUFtQixjQUF0RSxFQUFzRixDQUF0RixFQUw0QjtBQU01QixpQkFBSyxZQUFMLENBQWtCLGVBQWUsWUFBZixDQUE0QixDQUE1QixFQUErQixFQUEvQixFQUFtQyxVQUFDLE9BQUQsRUFBYTtBQUM5RCx1QkFBSyxZQUFMLEdBQW9CLGFBQXBCLENBQWtDLE9BQWxDLEVBQTJDLG9CQUFVLEtBQVYsRUFBaUIsS0FBSyxLQUFMLEVBQVksSUFBeEUsRUFBOEUsSUFBOUUsRUFBb0YsSUFBcEYsRUFEOEQ7YUFBYixDQUFyRCxDQU40Qjs7OztnREFXUixTQUFTLGFBQWEscUJBQXFCLE1BQU07QUFDckUsZ0JBQU0sUUFBUSxLQUFLLFlBQUwsRUFBUixDQUQrRDtBQUVyRSx3QkFBWSxPQUFaLENBQW9CLHNCQUFjO0FBQzlCLHNCQUFNLGFBQU4sQ0FDSSxPQURKLEVBRUksb0JBQVUsS0FBVixFQUNBLFdBQVcsS0FBWCxFQUNBLG1CQUpKLEVBS0ksWUFBWSxXQUFXLElBQVgsRUFDWixJQU5KLEVBRDhCO2FBQWQsQ0FBcEIsQ0FGcUU7Ozs7cUNBYTVELE1BQU0sU0FBUyxVQUFVO0FBQ2xDLGdCQUFJLE9BQU8sT0FBUCxLQUFtQixVQUFuQixFQUErQjtBQUMvQiwyQkFBVyxPQUFYLENBRCtCO0FBRS9CLDBCQUFVLEVBQUMsdUJBQXVCLEtBQXZCLEVBQVgsQ0FGK0I7YUFBbkM7QUFJQSx3Q0FDSSxLQUFLLE9BQUwsRUFDQSxJQUZKLEVBR0ksUUFBUSxxQkFBUixHQUFnQyxJQUFoQyxHQUF1QyxJQUF2QyxFQUNBLFFBSkosRUFMa0M7Ozs7c0NBWXhCLE1BQU07OztBQUNoQixnQkFBSSxDQUFKLEVBQU8sRUFBUDs7Ozs7O0FBRGdCLGdCQU9aLEtBQ
|