start migration of core from nodes to paths
This commit is contained in:
parent
41a8257005
commit
c906bd3edc
@ -464,7 +464,7 @@ export default class File {
|
|||||||
this.scope = this.path.scope;
|
this.scope = this.path.scope;
|
||||||
this.ast = ast;
|
this.ast = ast;
|
||||||
|
|
||||||
traverse(ast, {
|
this.path.traverse({
|
||||||
enter(node, parent, scope) {
|
enter(node, parent, scope) {
|
||||||
if (this.isScope()) {
|
if (this.isScope()) {
|
||||||
for (var key in scope.bindings) {
|
for (var key in scope.bindings) {
|
||||||
@ -472,7 +472,7 @@ export default class File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, this.scope);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
transform(ast) {
|
transform(ast) {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export default function (exports, opts) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.JSXNamespacedName = function (node, parent, scope, file) {
|
exports.JSXNamespacedName = function (node, parent, scope, file) {
|
||||||
throw file.errorWithNode(node, messages.get("JSXNamespacedTags"));
|
throw this.errorWithNode(messages.get("JSXNamespacedTags"));
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.JSXMemberExpression = {
|
exports.JSXMemberExpression = {
|
||||||
|
|||||||
@ -219,7 +219,7 @@ export default class ReplaceSupers {
|
|||||||
var thisReference;
|
var thisReference;
|
||||||
|
|
||||||
if (isIllegalBareSuper(node, parent)) {
|
if (isIllegalBareSuper(node, parent)) {
|
||||||
throw this.file.errorWithNode(node, messages.get("classesIllegalBareSuper"));
|
throw this.errorWithNode(messages.get("classesIllegalBareSuper"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isCallExpression(node)) {
|
if (t.isCallExpression(node)) {
|
||||||
|
|||||||
@ -45,7 +45,7 @@ var importsVisitor = {
|
|||||||
ImportDeclaration: {
|
ImportDeclaration: {
|
||||||
enter(node, parent, scope, formatter) {
|
enter(node, parent, scope, formatter) {
|
||||||
formatter.hasLocalImports = true;
|
formatter.hasLocalImports = true;
|
||||||
extend(formatter.localImports, t.getBindingIdentifiers(node));
|
extend(formatter.localImports, this.getBindingIdentifiers());
|
||||||
formatter.bumpImportOccurences(node);
|
formatter.bumpImportOccurences(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,11 +54,11 @@ var importsVisitor = {
|
|||||||
var exportsVisitor = {
|
var exportsVisitor = {
|
||||||
ExportDeclaration: {
|
ExportDeclaration: {
|
||||||
enter(node, parent, scope, formatter) {
|
enter(node, parent, scope, formatter) {
|
||||||
var declar = node.declaration;
|
var declar = this.get("declaration");
|
||||||
formatter.hasLocalImports = true;
|
formatter.hasLocalImports = true;
|
||||||
|
|
||||||
if (declar && t.isStatement(declar)) {
|
if (declar.isStatement()) {
|
||||||
extend(formatter.localExports, t.getBindingIdentifiers(declar));
|
extend(formatter.localExports, declar.getBindingIdentifiers());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.default) {
|
if (!node.default) {
|
||||||
@ -105,16 +105,16 @@ export default class DefaultFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLocalExports() {
|
getLocalExports() {
|
||||||
this.file.scope.traverse(this.file.ast, exportsVisitor, this);
|
this.file.path.traverse(exportsVisitor, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLocalImports() {
|
getLocalImports() {
|
||||||
this.file.scope.traverse(this.file.ast, importsVisitor, this);
|
this.file.path.traverse(importsVisitor, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
remapAssignments() {
|
remapAssignments() {
|
||||||
if (this.hasLocalImports) {
|
if (this.hasLocalImports) {
|
||||||
this.file.scope.traverse(this.file.ast, remapVisitor, this);
|
this.file.path.traverse(remapVisitor, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import includes from "lodash/collection/includes";
|
import includes from "lodash/collection/includes";
|
||||||
|
import traverse from "../traversal";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for traversing over the provided `File`s
|
* This class is responsible for traversing over the provided `File`s
|
||||||
@ -59,7 +60,7 @@ export default class TransformerPass {
|
|||||||
|
|
||||||
file.log.debug(`Running transformer ${this.transformer.key}`);
|
file.log.debug(`Running transformer ${this.transformer.key}`);
|
||||||
|
|
||||||
file.scope.traverse(file.ast, this.handlers, file);
|
traverse(file.ast, this.handlers, file.scope, file);
|
||||||
|
|
||||||
this.ran = true;
|
this.ran = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export function BlockStatement(node, parent, scope, file) {
|
|||||||
var letRefs = node._letReferences;
|
var letRefs = node._letReferences;
|
||||||
if (!letRefs) return;
|
if (!letRefs) return;
|
||||||
|
|
||||||
scope.traverse(node, visitor, {
|
this.traverse(visitor, {
|
||||||
letRefs: letRefs,
|
letRefs: letRefs,
|
||||||
file: file
|
file: file
|
||||||
});
|
});
|
||||||
|
|||||||
@ -111,7 +111,7 @@ function traverseReplace(node, parent, scope, remaps) {
|
|||||||
var letReferenceBlockVisitor = {
|
var letReferenceBlockVisitor = {
|
||||||
enter(node, parent, scope, state) {
|
enter(node, parent, scope, state) {
|
||||||
if (this.isFunction()) {
|
if (this.isFunction()) {
|
||||||
scope.traverse(node, letReferenceFunctionVisitor, state);
|
this.traverse(letReferenceFunctionVisitor, state);
|
||||||
return this.skip();
|
return this.skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ var loopVisitor = {
|
|||||||
|
|
||||||
if (this.isLoop()) {
|
if (this.isLoop()) {
|
||||||
state.ignoreLabeless = true;
|
state.ignoreLabeless = true;
|
||||||
scope.traverse(node, loopVisitor, state);
|
this.traverse(loopVisitor, state);
|
||||||
state.ignoreLabeless = false;
|
state.ignoreLabeless = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export function ClassDeclaration(node, parent, scope, file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ClassExpression(node, parent, scope, file) {
|
export function ClassExpression(node, parent, scope, file) {
|
||||||
return new ClassTransformer(node, parent, scope, file).run();
|
return new ClassTransformer(this, file).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
var verifyConstructorVisitor = traverse.explode({
|
var verifyConstructorVisitor = traverse.explode({
|
||||||
@ -37,7 +37,7 @@ var verifyConstructorVisitor = traverse.explode({
|
|||||||
state.hasBareSuper = true;
|
state.hasBareSuper = true;
|
||||||
|
|
||||||
if (!state.hasSuper) {
|
if (!state.hasSuper) {
|
||||||
throw state.file.errorWithNode(node, "super call is only allowed in derived constructor");
|
throw this.errorWithNode("super call is only allowed in derived constructor");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ var verifyConstructorVisitor = traverse.explode({
|
|||||||
ThisExpression: {
|
ThisExpression: {
|
||||||
enter(node, parent, scope, state) {
|
enter(node, parent, scope, state) {
|
||||||
if (state.hasSuper && !state.hasBareSuper) {
|
if (state.hasSuper && !state.hasBareSuper) {
|
||||||
throw state.file.errorWithNode(node, "'this' is not allowed before super()");
|
throw this.errorWithNode("'this' is not allowed before super()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,10 +58,11 @@ class ClassTransformer {
|
|||||||
* Description
|
* Description
|
||||||
*/
|
*/
|
||||||
|
|
||||||
constructor(node: Object, parent: Object, scope: Scope, file: File) {
|
constructor(path: TraversalPath, file: File) {
|
||||||
this.parent = parent;
|
this.parent = path.parent;
|
||||||
this.scope = scope;
|
this.scope = path.scope;
|
||||||
this.node = node;
|
this.node = path.node;
|
||||||
|
this.path = path;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
this.hasInstanceMutators = false;
|
this.hasInstanceMutators = false;
|
||||||
@ -71,11 +72,11 @@ class ClassTransformer {
|
|||||||
this.staticMutatorMap = {};
|
this.staticMutatorMap = {};
|
||||||
|
|
||||||
this.hasConstructor = false;
|
this.hasConstructor = false;
|
||||||
this.className = node.id;
|
this.className = this.node.id;
|
||||||
this.classRef = node.id || scope.generateUidIdentifier("class");
|
this.classRef = this.node.id || this.scope.generateUidIdentifier("class");
|
||||||
|
|
||||||
this.superName = node.superClass || t.identifier("Function");
|
this.superName = this.node.superClass || t.identifier("Function");
|
||||||
this.hasSuper = !!node.superClass;
|
this.hasSuper = !!this.node.superClass;
|
||||||
|
|
||||||
this.isLoose = file.isLoose("es6.classes");
|
this.isLoose = file.isLoose("es6.classes");
|
||||||
}
|
}
|
||||||
@ -174,11 +175,13 @@ class ClassTransformer {
|
|||||||
var classBody = this.node.body.body;
|
var classBody = this.node.body.body;
|
||||||
var body = this.body;
|
var body = this.body;
|
||||||
|
|
||||||
|
var classBodyPaths = this.path.get("body").get("body");
|
||||||
|
|
||||||
for (var i = 0; i < classBody.length; i++) {
|
for (var i = 0; i < classBody.length; i++) {
|
||||||
var node = classBody[i];
|
var node = classBody[i];
|
||||||
if (t.isMethodDefinition(node)) {
|
if (t.isMethodDefinition(node)) {
|
||||||
var isConstructor = (!node.computed && t.isIdentifier(node.key, { name: "constructor" })) || t.isLiteral(node.key, { value: "constructor" });
|
var isConstructor = (!node.computed && t.isIdentifier(node.key, { name: "constructor" })) || t.isLiteral(node.key, { value: "constructor" });
|
||||||
if (isConstructor) this.verifyConstructor(node);
|
if (isConstructor) this.verifyConstructor(classBodyPaths[i]);
|
||||||
|
|
||||||
var replaceSupers = new ReplaceSupers({
|
var replaceSupers = new ReplaceSupers({
|
||||||
methodNode: node,
|
methodNode: node,
|
||||||
@ -206,7 +209,7 @@ class ClassTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we have no constructor, we have a super, and the super doesn't appear to be falsy
|
// we have no constructor, we have a super, and the super doesn't appear to be falsy
|
||||||
if (!this.hasConstructor && this.hasSuper && t.evaluateTruthy(superName, this.scope) !== false) {
|
if (!this.hasConstructor && this.hasSuper) { // todo: t.evaluateTruthy(superName, this.scope) !== false
|
||||||
var helperName = "class-super-constructor-call";
|
var helperName = "class-super-constructor-call";
|
||||||
if (this.isLoose) helperName += "-loose";
|
if (this.isLoose) helperName += "-loose";
|
||||||
constructor.body.body.push(util.template(helperName, {
|
constructor.body.body.push(util.template(helperName, {
|
||||||
@ -249,17 +252,17 @@ class ClassTransformer {
|
|||||||
* Description
|
* Description
|
||||||
*/
|
*/
|
||||||
|
|
||||||
verifyConstructor(node: Object) {
|
verifyConstructor(path: TraversalPath) {
|
||||||
var state = {
|
var state = {
|
||||||
hasBareSuper: false,
|
hasBareSuper: false,
|
||||||
hasSuper: this.hasSuper,
|
hasSuper: this.hasSuper,
|
||||||
file: this.file
|
file: this.file
|
||||||
};
|
};
|
||||||
|
|
||||||
traverse(node, verifyConstructorVisitor, this.scope, state);
|
path.traverse(verifyConstructorVisitor, state);
|
||||||
|
|
||||||
if (!state.hasBareSuper && this.hasSuper) {
|
if (!state.hasBareSuper && this.hasSuper) {
|
||||||
throw this.file.errorWithNode(node, "Derived constructor must call super()");
|
throw path.errorWithNode("Derived constructor must call super()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ var visitor = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Scopable(node, parent, scope, file) {
|
export function Scopable(node, parent, scope, file) {
|
||||||
scope.traverse(node, visitor, {
|
this.traverse(visitor, {
|
||||||
constants: scope.getAllBindingsOfKind("const"),
|
constants: scope.getAllBindingsOfKind("const"),
|
||||||
file: file
|
file: file
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,12 +5,10 @@ import * as t from "../../../types";
|
|||||||
export var check = t.isForOfStatement;
|
export var check = t.isForOfStatement;
|
||||||
|
|
||||||
export function ForOfStatement(node, parent, scope, file) {
|
export function ForOfStatement(node, parent, scope, file) {
|
||||||
if (this.get("right").isTypeGeneric("Array")) {
|
if (this.get("right").isArrayExpression()) {
|
||||||
return array(node, scope, file);
|
return _ForOfStatementArray.call(this, node, scope, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
var callback = spec;
|
var callback = spec;
|
||||||
if (file.isLoose("es6.forOf")) callback = loose;
|
if (file.isLoose("es6.forOf")) callback = loose;
|
||||||
|
|
||||||
@ -42,7 +40,7 @@ export function ForOfStatement(node, parent, scope, file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var array = function (node, scope, file) {
|
export function _ForOfStatementArray(node, scope, file) {
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
var right = node.right;
|
var right = node.right;
|
||||||
|
|
||||||
@ -78,7 +76,7 @@ var array = function (node, scope, file) {
|
|||||||
nodes.push(loop);
|
nodes.push(loop);
|
||||||
|
|
||||||
return nodes;
|
return nodes;
|
||||||
};
|
}
|
||||||
|
|
||||||
var loose = function (node, parent, scope, file) {
|
var loose = function (node, parent, scope, file) {
|
||||||
var left = node.left;
|
var left = node.left;
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function ImportDeclaration(node, parent, scope, file) {
|
|||||||
|
|
||||||
export function ExportDeclaration(node, parent, scope, file) {
|
export function ExportDeclaration(node, parent, scope, file) {
|
||||||
// flow type
|
// flow type
|
||||||
if (t.isTypeAlias(node.declaration)) return;
|
if (this.get("declaration").isTypeAlias()) return;
|
||||||
|
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
var i;
|
var i;
|
||||||
|
|||||||
@ -49,41 +49,42 @@ exports.Function = function (node, parent, scope, file) {
|
|||||||
body.push(defNode);
|
body.push(defNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var i = 0; i < node.params.length; i++) {
|
var params = this.get("params");
|
||||||
var param = node.params[i];
|
for (var i = 0; i < params.length; i++) {
|
||||||
|
var param = params[i];
|
||||||
|
|
||||||
if (!t.isAssignmentPattern(param)) {
|
if (!param.isAssignmentPattern()) {
|
||||||
if (!t.isRestElement(param)) {
|
if (!param.isRestElement()) {
|
||||||
lastNonDefaultParam = i + 1;
|
lastNonDefaultParam = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!t.isIdentifier(param)) {
|
if (!param.isIdentifier()) {
|
||||||
scope.traverse(param, iifeVisitor, state);
|
param.traverse(iifeVisitor, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.transformers["es6.blockScopingTDZ"].canRun() && t.isIdentifier(param)) {
|
if (file.transformers["es6.blockScopingTDZ"].canRun() && param.isIdentifier()) {
|
||||||
pushDefNode(param, t.identifier("undefined"), i);
|
pushDefNode(param.node, t.identifier("undefined"), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var left = param.left;
|
var left = param.get("left");
|
||||||
var right = param.right;
|
var right = param.get("right");
|
||||||
|
|
||||||
var placeholder = scope.generateUidIdentifier("x");
|
var placeholder = scope.generateUidIdentifier("x");
|
||||||
placeholder._isDefaultPlaceholder = true;
|
placeholder._isDefaultPlaceholder = true;
|
||||||
node.params[i] = placeholder;
|
node.params[i] = placeholder;
|
||||||
|
|
||||||
if (!state.iife) {
|
if (!state.iife) {
|
||||||
if (t.isIdentifier(right) && scope.hasOwnBinding(right.name)) {
|
if (right.isIdentifier() && scope.hasOwnBinding(right.node.name)) {
|
||||||
state.iife = true;
|
state.iife = true;
|
||||||
} else {
|
} else {
|
||||||
scope.traverse(right, iifeVisitor, state);
|
right.traverse(iifeVisitor, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pushDefNode(left, right, i);
|
pushDefNode(left.node, right.node, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to cut off all trailing default parameters
|
// we need to cut off all trailing default parameters
|
||||||
|
|||||||
@ -15,7 +15,7 @@ var memberExpressionOptimisationVisitor = {
|
|||||||
// to the wrong function
|
// to the wrong function
|
||||||
if (this.isFunctionDeclaration() || this.isFunctionExpression()) {
|
if (this.isFunctionDeclaration() || this.isFunctionExpression()) {
|
||||||
state.noOptimise = true;
|
state.noOptimise = true;
|
||||||
scope.traverse(node, memberExpressionOptimisationVisitor, state);
|
this.traverse(memberExpressionOptimisationVisitor, state);
|
||||||
state.noOptimise = false;
|
state.noOptimise = false;
|
||||||
return this.skip();
|
return this.skip();
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ exports.Function = function (node, parent, scope, file) {
|
|||||||
name: rest.name
|
name: rest.name
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.traverse(node, memberExpressionOptimisationVisitor, state);
|
this.traverse(memberExpressionOptimisationVisitor, state);
|
||||||
|
|
||||||
// we only have shorthands and there's no other references
|
// we only have shorthands and there's no other references
|
||||||
if (state.canOptimise && state.candidates.length) {
|
if (state.canOptimise && state.candidates.length) {
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export function CallExpression(node, parent, scope) {
|
|||||||
|
|
||||||
var callee = node.callee;
|
var callee = node.callee;
|
||||||
|
|
||||||
if (t.isMemberExpression(callee)) {
|
if (this.get("callee").isMemberExpression()) {
|
||||||
var temp = scope.generateTempBasedOnNode(callee.object);
|
var temp = scope.generateTempBasedOnNode(callee.object);
|
||||||
if (temp) {
|
if (temp) {
|
||||||
callee.object = t.assignmentExpression("=", temp, callee.object);
|
callee.object = t.assignmentExpression("=", temp, callee.object);
|
||||||
@ -101,7 +101,7 @@ export function NewExpression(node, parent, scope, file) {
|
|||||||
var args = node.arguments;
|
var args = node.arguments;
|
||||||
if (!hasSpread(args)) return;
|
if (!hasSpread(args)) return;
|
||||||
|
|
||||||
var nativeType = t.isIdentifier(node.callee) && includes(t.NATIVE_TYPE_NAMES, node.callee.name);
|
var nativeType = this.get("callee").isIdentifier() && includes(t.NATIVE_TYPE_NAMES, node.callee.name);
|
||||||
|
|
||||||
var nodes = build(args, scope);
|
var nodes = build(args, scope);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export function UnaryExpression(node, parent, scope, file) {
|
|||||||
|
|
||||||
if (node.operator === "typeof") {
|
if (node.operator === "typeof") {
|
||||||
var call = t.callExpression(file.addHelper("typeof"), [node.argument]);
|
var call = t.callExpression(file.addHelper("typeof"), [node.argument]);
|
||||||
if (t.isIdentifier(node.argument)) {
|
if (this.get("argument").isIdentifier()) {
|
||||||
var undefLiteral = t.literal("undefined");
|
var undefLiteral = t.literal("undefined");
|
||||||
return t.conditionalExpression(
|
return t.conditionalExpression(
|
||||||
t.binaryExpression("===", t.unaryExpression("typeof", node.argument), undefLiteral),
|
t.binaryExpression("===", t.unaryExpression("typeof", node.argument), undefLiteral),
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import map from "lodash/collection/map";
|
|||||||
import * as t from "../../../types";
|
import * as t from "../../../types";
|
||||||
|
|
||||||
exports.Function = function (node, parent, scope, file) {
|
exports.Function = function (node, parent, scope, file) {
|
||||||
var tailCall = new TailCallTransformer(node, scope, file);
|
var tailCall = new TailCallTransformer(this, scope, file);
|
||||||
tailCall.run();
|
tailCall.run();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,11 +18,11 @@ function returnBlock(expr) {
|
|||||||
var firstPass = {
|
var firstPass = {
|
||||||
enter(node, parent, scope, state) {
|
enter(node, parent, scope, state) {
|
||||||
if (this.isIfStatement()) {
|
if (this.isIfStatement()) {
|
||||||
if (t.isReturnStatement(node.alternate)) {
|
if (this.get("alternate").isReturnStatement()) {
|
||||||
t.ensureBlock(node, "alternate");
|
t.ensureBlock(node, "alternate");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isReturnStatement(node.consequent)) {
|
if (this.get("consequent").isReturnStatement()) {
|
||||||
t.ensureBlock(node, "consequent");
|
t.ensureBlock(node, "consequent");
|
||||||
}
|
}
|
||||||
} else if (this.isReturnStatement()) {
|
} else if (this.isReturnStatement()) {
|
||||||
@ -85,17 +85,18 @@ var thirdPass = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class TailCallTransformer {
|
class TailCallTransformer {
|
||||||
constructor(node, scope, file) {
|
constructor(path, scope, file) {
|
||||||
this.hasTailRecursion = false;
|
this.hasTailRecursion = false;
|
||||||
this.needsArguments = false;
|
this.needsArguments = false;
|
||||||
this.setsArguments = false;
|
this.setsArguments = false;
|
||||||
this.needsThis = false;
|
this.needsThis = false;
|
||||||
this.ownerId = node.id;
|
this.ownerId = path.node.id;
|
||||||
this.vars = [];
|
this.vars = [];
|
||||||
|
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
|
this.path = path;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.node = node;
|
this.node = path.node;
|
||||||
}
|
}
|
||||||
|
|
||||||
getArgumentsId() {
|
getArgumentsId() {
|
||||||
@ -156,7 +157,7 @@ class TailCallTransformer {
|
|||||||
if (!ownerId) return;
|
if (!ownerId) return;
|
||||||
|
|
||||||
// traverse the function and look for tail recursion
|
// traverse the function and look for tail recursion
|
||||||
scope.traverse(node, firstPass, this);
|
this.path.traverse(firstPass, this);
|
||||||
|
|
||||||
if (!this.hasTailRecursion) return;
|
if (!this.hasTailRecursion) return;
|
||||||
|
|
||||||
@ -167,10 +168,10 @@ class TailCallTransformer {
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
scope.traverse(node, secondPass, this);
|
this.path.traverse(secondPass, this);
|
||||||
|
|
||||||
if (!this.needsThis || !this.needsArguments) {
|
if (!this.needsThis || !this.needsArguments) {
|
||||||
scope.traverse(node, thirdPass, this);
|
this.path.traverse(thirdPass, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = t.ensureBlock(node).body;
|
var body = t.ensureBlock(node).body;
|
||||||
|
|||||||
@ -44,6 +44,7 @@ export default {
|
|||||||
// needs to be before `_aliasFunction` due to define property closure
|
// needs to be before `_aliasFunction` due to define property closure
|
||||||
"es6.properties.computed": require("./es6/properties.computed"),
|
"es6.properties.computed": require("./es6/properties.computed"),
|
||||||
|
|
||||||
|
"optimisation.es6.forOf": require("./optimisation/flow.for-of"),
|
||||||
"es6.forOf": require("./es6/for-of"),
|
"es6.forOf": require("./es6/for-of"),
|
||||||
|
|
||||||
"es6.regex.sticky": require("./es6/regex.sticky"),
|
"es6.regex.sticky": require("./es6/regex.sticky"),
|
||||||
|
|||||||
@ -34,13 +34,13 @@ var functionVisitor = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// traverse all child nodes of this function and find `arguments` and `this`
|
// traverse all child nodes of this function and find `arguments` and `this`
|
||||||
scope.traverse(node, functionChildrenVisitor, state);
|
this.traverse(functionChildrenVisitor, state);
|
||||||
|
|
||||||
return this.skip();
|
return this.skip();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var go = function (getBody, node, scope) {
|
function aliasFunction(getBody, path, scope) {
|
||||||
var argumentsId;
|
var argumentsId;
|
||||||
var thisId;
|
var thisId;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ var go = function (getBody, node, scope) {
|
|||||||
|
|
||||||
// traverse the function and find all alias functions so we can alias
|
// traverse the function and find all alias functions so we can alias
|
||||||
// `arguments` and `this` if necessary
|
// `arguments` and `this` if necessary
|
||||||
scope.traverse(node, functionVisitor, state);
|
path.traverse(functionVisitor, state);
|
||||||
|
|
||||||
var body;
|
var body;
|
||||||
|
|
||||||
@ -77,16 +77,16 @@ var go = function (getBody, node, scope) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Program(node, parent, scope) {
|
export function Program(node, parent, scope) {
|
||||||
go(function () {
|
aliasFunction(function () {
|
||||||
return node.body;
|
return node.body;
|
||||||
}, node, scope);
|
}, this, scope);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FunctionDeclaration(node, parent, scope) {
|
export function FunctionDeclaration(node, parent, scope) {
|
||||||
go(function () {
|
aliasFunction(function () {
|
||||||
t.ensureBlock(node);
|
t.ensureBlock(node);
|
||||||
return node.body.body;
|
return node.body.body;
|
||||||
}, node, scope);
|
}, this, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { FunctionDeclaration as FunctionExpression };
|
export { FunctionDeclaration as FunctionExpression };
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export function ExportDeclaration(node, parent, scope) {
|
|||||||
} else if (t.isVariableDeclaration(declar)) {
|
} else if (t.isVariableDeclaration(declar)) {
|
||||||
// export var foo = "bar";
|
// export var foo = "bar";
|
||||||
var specifiers = [];
|
var specifiers = [];
|
||||||
var bindings = t.getBindingIdentifiers(declar);
|
var bindings = this.get("declaration").getBindingIdentifiers();
|
||||||
for (var key in bindings) {
|
for (var key in bindings) {
|
||||||
var id = bindings[key];
|
var id = bindings[key];
|
||||||
specifiers.push(t.exportSpecifier(id, id));
|
specifiers.push(t.exportSpecifier(id, id));
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { _ForOfStatementArray } from "../es6/for-of";
|
||||||
|
import * as t from "../../../types";
|
||||||
|
|
||||||
|
export var check = t.isForOfStatement;
|
||||||
|
export var optional = true;
|
||||||
|
|
||||||
|
export function ForOfStatement(node, parent, scope, file) {
|
||||||
|
if (this.get("right").isTypeGeneric("Array")) {
|
||||||
|
return _ForOfStatementArray.call(this, node, scope, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,5 +29,5 @@ export function ImportDeclaration(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ExportDeclaration(node) {
|
export function ExportDeclaration(node) {
|
||||||
if (t.isTypeAlias(node.declaration)) this.remove();
|
if (this.get("declaration").isTypeAlias()) this.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import core from "core-js/library";
|
|||||||
import has from "lodash/object/has";
|
import has from "lodash/object/has";
|
||||||
import * as t from "../../../types";
|
import * as t from "../../../types";
|
||||||
|
|
||||||
var isSymboliterator = t.buildMatchMemberExpression("Symbol.iterator");
|
var isSymbolIterator = t.buildMatchMemberExpression("Symbol.iterator");
|
||||||
|
|
||||||
var coreHas = function (node) {
|
var coreHas = function (node) {
|
||||||
return node.name !== "_" && has(core, node.name);
|
return node.name !== "_" && has(core, node.name);
|
||||||
@ -47,7 +47,7 @@ var astVisitor = {
|
|||||||
if (!callee.computed) return false;
|
if (!callee.computed) return false;
|
||||||
|
|
||||||
prop = callee.property;
|
prop = callee.property;
|
||||||
if (!isSymboliterator(prop)) return false;
|
if (!isSymbolIterator(prop)) return false;
|
||||||
|
|
||||||
return util.template("corejs-iterator", {
|
return util.template("corejs-iterator", {
|
||||||
CORE_ID: file.get("coreIdentifier"),
|
CORE_ID: file.get("coreIdentifier"),
|
||||||
@ -59,7 +59,7 @@ var astVisitor = {
|
|||||||
if (node.operator !== "in") return;
|
if (node.operator !== "in") return;
|
||||||
|
|
||||||
var left = node.left;
|
var left = node.left;
|
||||||
if (!isSymboliterator(left)) return;
|
if (!isSymbolIterator(left)) return;
|
||||||
|
|
||||||
return util.template("corejs-is-iterator", {
|
return util.template("corejs-is-iterator", {
|
||||||
CORE_ID: file.get("coreIdentifier"),
|
CORE_ID: file.get("coreIdentifier"),
|
||||||
@ -76,7 +76,7 @@ export function manipulateOptions(opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Program(node, parent, scope, file) {
|
export function Program(node, parent, scope, file) {
|
||||||
scope.traverse(node, astVisitor, file);
|
this.traverse(astVisitor, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pre(file) {
|
export function pre(file) {
|
||||||
|
|||||||
@ -20,8 +20,7 @@ export function MethodDefinition(node, parent, scope, file) {
|
|||||||
if (node.kind !== "memo") return;
|
if (node.kind !== "memo") return;
|
||||||
node.kind = "get";
|
node.kind = "get";
|
||||||
|
|
||||||
var value = node.value;
|
t.ensureBlock(node.value);
|
||||||
t.ensureBlock(value);
|
|
||||||
|
|
||||||
var key = node.key;
|
var key = node.key;
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ export function MethodDefinition(node, parent, scope, file) {
|
|||||||
file: file
|
file: file
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.traverse(value, visitor, state);
|
this.get("value").traverse(visitor, state);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ function toStatements(node) {
|
|||||||
export var optional = true;
|
export var optional = true;
|
||||||
|
|
||||||
export function ConditionalExpression(node, parent, scope) {
|
export function ConditionalExpression(node, parent, scope) {
|
||||||
var evaluateTest = t.evaluateTruthy(node.test, scope);
|
var evaluateTest = this.get("test").evaluateTruthy();
|
||||||
if (evaluateTest === true) {
|
if (evaluateTest === true) {
|
||||||
return node.consequent;
|
return node.consequent;
|
||||||
} else if (evaluateTest === false) {
|
} else if (evaluateTest === false) {
|
||||||
@ -32,9 +32,8 @@ export var IfStatement = {
|
|||||||
exit(node, parent, scope) {
|
exit(node, parent, scope) {
|
||||||
var consequent = node.consequent;
|
var consequent = node.consequent;
|
||||||
var alternate = node.alternate;
|
var alternate = node.alternate;
|
||||||
var test = node.test;
|
|
||||||
|
|
||||||
var evaluateTest = t.evaluateTruthy(test, scope);
|
var evaluateTest = this.get("test").evaluateTruthy();
|
||||||
|
|
||||||
// we can check if a test will be truthy 100% and if so then we can inline
|
// we can check if a test will be truthy 100% and if so then we can inline
|
||||||
// the consequent and completely ignore the alternate
|
// the consequent and completely ignore the alternate
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import * as t from "../../../types";
|
|||||||
export var optional = true;
|
export var optional = true;
|
||||||
|
|
||||||
export function Expression(node, parent, scope) {
|
export function Expression(node, parent, scope) {
|
||||||
var res = t.evaluate(node, scope);
|
var res = this.evaluate();
|
||||||
if (res.confident) return t.valueToNode(res.value);
|
if (res.confident) return t.valueToNode(res.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
import * as t from "../../../types";
|
import * as t from "../../../types";
|
||||||
|
|
||||||
var isConsole = t.buildMatchMemberExpression("console", true);
|
|
||||||
|
|
||||||
export var optional = true;
|
export var optional = true;
|
||||||
|
|
||||||
export function CallExpression(node, parent) {
|
export function CallExpression(node, parent) {
|
||||||
if (isConsole(node.callee)) {
|
if (this.get("callee").matchesPattern("console", true)) {
|
||||||
if (t.isExpressionStatement(parent)) {
|
if (t.isExpressionStatement(parent)) {
|
||||||
this.parentPath.remove();
|
this.parentPath.remove();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ function check(source, file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function CallExpression(node, parent, scope, file) {
|
export function CallExpression(node, parent, scope, file) {
|
||||||
if (t.isIdentifier(node.callee, { name: "require" }) && node.arguments.length === 1) {
|
if (this.get("callee").isIdentifier({ name: "require" }) && node.arguments.length === 1) {
|
||||||
check(node.arguments[0], file);
|
check(node.arguments[0], file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,30 +58,6 @@ export default class Binding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Description
|
|
||||||
*/
|
|
||||||
|
|
||||||
getValueIfImmutable() {
|
|
||||||
// can't guarantee this value is the same
|
|
||||||
if (this.reassigned) return;
|
|
||||||
|
|
||||||
var node = this.path.node;
|
|
||||||
if (t.isVariableDeclarator(node)) {
|
|
||||||
if (t.isIdentifier(node.id)) {
|
|
||||||
node = node.init;
|
|
||||||
} else {
|
|
||||||
// otherwise it's probably a destructuring like:
|
|
||||||
// var { foo } = "foo";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.isImmutable(node)) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description
|
* Description
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
module.exports = traverse;
|
|
||||||
|
|
||||||
import TraversalContext from "./context";
|
import TraversalContext from "./context";
|
||||||
import includes from "lodash/collection/includes";
|
import includes from "lodash/collection/includes";
|
||||||
import * as t from "../types";
|
import * as t from "../types";
|
||||||
|
|
||||||
function traverse(parent, opts, scope, state) {
|
export default function traverse(parent, opts, scope, state, parentPath) {
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
|
|
||||||
if (!opts.noScope && !scope) {
|
if (!opts.noScope && !scope) {
|
||||||
@ -20,10 +18,10 @@ function traverse(parent, opts, scope, state) {
|
|||||||
// array of nodes
|
// array of nodes
|
||||||
if (Array.isArray(parent)) {
|
if (Array.isArray(parent)) {
|
||||||
for (var i = 0; i < parent.length; i++) {
|
for (var i = 0; i < parent.length; i++) {
|
||||||
traverse.node(parent[i], opts, scope, state);
|
traverse.node(parent[i], opts, scope, state, parentPath);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
traverse.node(parent, opts, scope, state);
|
traverse.node(parent, opts, scope, state, parentPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import * as t from "./index";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk the input `node` and statically evaluate if it's truthy.
|
* Walk the input `node` and statically evaluate if it's truthy.
|
||||||
*
|
*
|
||||||
@ -18,15 +16,15 @@ import * as t from "./index";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function evaluateTruthy(node: Object, scope: Scope): boolean {
|
export function evaluateTruthy(): boolean {
|
||||||
var res = evaluate(node, scope);
|
var res = this.evaluate();
|
||||||
if (res.confident) return !!res.value;
|
if (res.confident) return !!res.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk the input `node` and statically evaluate it.
|
* Walk the input `node` and statically evaluate it.
|
||||||
*
|
*
|
||||||
* Returns an pbject in the form `{ confident, value }`. `confident` indicates
|
* Returns an object in the form `{ confident, value }`. `confident` indicates
|
||||||
* whether or not we had to drop out of evaluating the expression because of
|
* whether or not we had to drop out of evaluating the expression because of
|
||||||
* hitting an unknown node that we couldn't confidently find the value of.
|
* hitting an unknown node that we couldn't confidently find the value of.
|
||||||
*
|
*
|
||||||
@ -38,24 +36,27 @@ export function evaluateTruthy(node: Object, scope: Scope): boolean {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function evaluate(node: Object, scope: Scope): { confident: boolean; value: any } {
|
export function evaluate(): { confident: boolean; value: any } {
|
||||||
var confident = true;
|
var confident = true;
|
||||||
|
|
||||||
var value = evaluate(node);
|
var value = evaluate(this);
|
||||||
if (!confident) value = undefined;
|
if (!confident) value = undefined;
|
||||||
return {
|
return {
|
||||||
confident: confident,
|
confident: confident,
|
||||||
value: value
|
value: value
|
||||||
};
|
};
|
||||||
|
|
||||||
function evaluate(node) {
|
function evaluate(path) {
|
||||||
if (!confident) return;
|
if (!confident) return;
|
||||||
|
|
||||||
if (t.isSequenceExpression(node)) {
|
var node = path.node;
|
||||||
return evaluate(node.expressions[node.expressions.length - 1]);
|
|
||||||
|
if (path.isSequenceExpression()) {
|
||||||
|
var exprs = path.get("expressions");
|
||||||
|
return evaluate(exprs[exprs.length - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isLiteral(node)) {
|
if (path.isLiteral()) {
|
||||||
if (node.regex && node.value === null) {
|
if (node.regex && node.value === null) {
|
||||||
// we have a regex and we can't represent it natively
|
// we have a regex and we can't represent it natively
|
||||||
} else {
|
} else {
|
||||||
@ -63,24 +64,29 @@ export function evaluate(node: Object, scope: Scope): { confident: boolean; valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isConditionalExpression(node)) {
|
if (path.isConditionalExpression()) {
|
||||||
if (evaluate(node.test)) {
|
if (evaluate(path.get("test"))) {
|
||||||
return evaluate(node.consequent);
|
return evaluate(path.get("consequent"));
|
||||||
} else {
|
} else {
|
||||||
return evaluate(node.alternate);
|
return evaluate(path.get("alternate"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isIdentifier(node)) {
|
if (path.isIdentifier({ name: "undefined" })) {
|
||||||
if (node.name === "undefined") {
|
return undefined;
|
||||||
return undefined;
|
}
|
||||||
|
|
||||||
|
if (path.isIdentifier() || path.isMemberExpression()) {
|
||||||
|
path = path.resolve();
|
||||||
|
if (path) {
|
||||||
|
return evaluate(path);
|
||||||
} else {
|
} else {
|
||||||
return evaluate(scope.getImmutableBindingValue(node.name));
|
return confident = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isUnaryExpression(node, { prefix: true })) {
|
if (path.isUnaryExpression({ prefix: true })) {
|
||||||
var arg = evaluate(node.argument);
|
var arg = evaluate(path.get("argument"));
|
||||||
switch (node.operator) {
|
switch (node.operator) {
|
||||||
case "void": return undefined;
|
case "void": return undefined;
|
||||||
case "!": return !arg;
|
case "!": return !arg;
|
||||||
@ -89,13 +95,13 @@ export function evaluate(node: Object, scope: Scope): { confident: boolean; valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isArrayExpression(node) || t.isObjectExpression(node)) {
|
if (path.isArrayExpression() || path.isObjectExpression()) {
|
||||||
// we could evaluate these but it's probably impractical and not very useful
|
// we could evaluate these but it's probably impractical and not very useful
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isLogicalExpression(node)) {
|
if (path.isLogicalExpression()) {
|
||||||
let left = evaluate(node.left);
|
let left = evaluate(path.get("left"));
|
||||||
let right = evaluate(node.right);
|
let right = evaluate(path.get("right"));
|
||||||
|
|
||||||
switch (node.operator) {
|
switch (node.operator) {
|
||||||
case "||": return left || right;
|
case "||": return left || right;
|
||||||
@ -103,9 +109,9 @@ export function evaluate(node: Object, scope: Scope): { confident: boolean; valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isBinaryExpression(node)) {
|
if (path.isBinaryExpression()) {
|
||||||
let left = evaluate(node.left);
|
let left = evaluate(path.get("left"));
|
||||||
let right = evaluate(node.right);
|
let right = evaluate(path.get("right"));
|
||||||
|
|
||||||
switch (node.operator) {
|
switch (node.operator) {
|
||||||
case "-": return left - right;
|
case "-": return left - right;
|
||||||
@ -2,10 +2,11 @@ import isBoolean from "lodash/lang/isBoolean";
|
|||||||
import isNumber from "lodash/lang/isNumber";
|
import isNumber from "lodash/lang/isNumber";
|
||||||
import isRegExp from "lodash/lang/isRegExp";
|
import isRegExp from "lodash/lang/isRegExp";
|
||||||
import isString from "lodash/lang/isString";
|
import isString from "lodash/lang/isString";
|
||||||
import traverse from "./index";
|
import traverse from "../index";
|
||||||
import includes from "lodash/collection/includes";
|
import includes from "lodash/collection/includes";
|
||||||
import Scope from "./scope";
|
import assign from "lodash/object/assign";
|
||||||
import * as t from "../types";
|
import Scope from "../scope";
|
||||||
|
import * as t from "../../types";
|
||||||
|
|
||||||
export default class TraversalPath {
|
export default class TraversalPath {
|
||||||
constructor(parent, container) {
|
constructor(parent, container) {
|
||||||
@ -112,6 +113,13 @@ export default class TraversalPath {
|
|||||||
this._refresh(node, [node]);
|
this._refresh(node, [node]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorWithNode(msg, Error = SyntaxError) {
|
||||||
|
var loc = this.node.loc.start;
|
||||||
|
var err = new Error(`Line ${loc.line}: ${msg}`);
|
||||||
|
err.loc = loc;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
get node() {
|
get node() {
|
||||||
return this.container[this.key];
|
return this.container[this.key];
|
||||||
}
|
}
|
||||||
@ -133,9 +141,6 @@ export default class TraversalPath {
|
|||||||
// potentially create new scope
|
// potentially create new scope
|
||||||
this.setScope();
|
this.setScope();
|
||||||
|
|
||||||
// refresh scope with new/removed bindings
|
|
||||||
this._refresh(oldNode, replacements);
|
|
||||||
|
|
||||||
var file = this.scope && this.scope.file;
|
var file = this.scope && this.scope.file;
|
||||||
if (file) {
|
if (file) {
|
||||||
for (var i = 0; i < replacements.length; i++) {
|
for (var i = 0; i < replacements.length; i++) {
|
||||||
@ -170,12 +175,12 @@ export default class TraversalPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isBlacklisted() {
|
isBlacklisted(): boolean {
|
||||||
var blacklist = this.opts.blacklist;
|
var blacklist = this.opts.blacklist;
|
||||||
return blacklist && blacklist.indexOf(this.node.type) > -1;
|
return blacklist && blacklist.indexOf(this.node.type) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
visit() {
|
visit(): boolean {
|
||||||
if (this.isBlacklisted()) return false;
|
if (this.isBlacklisted()) return false;
|
||||||
|
|
||||||
this.call("enter");
|
this.call("enter");
|
||||||
@ -215,11 +220,22 @@ export default class TraversalPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has(key) {
|
has(key): boolean {
|
||||||
return !!this.node[key];
|
return !!this.node[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
getTypeAnnotation(): Object {
|
is(key): boolean {
|
||||||
|
return this.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
isnt(key): boolean {
|
||||||
|
return !this.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTypeAnnotation(): {
|
||||||
|
inferred: boolean;
|
||||||
|
annotation: ?Object;
|
||||||
|
} {
|
||||||
if (this.typeInfo) {
|
if (this.typeInfo) {
|
||||||
return this.typeInfo;
|
return this.typeInfo;
|
||||||
}
|
}
|
||||||
@ -246,10 +262,15 @@ export default class TraversalPath {
|
|||||||
|
|
||||||
resolve(): ?TraversalPath {
|
resolve(): ?TraversalPath {
|
||||||
if (this.isVariableDeclarator()) {
|
if (this.isVariableDeclarator()) {
|
||||||
return this.get("init").resolve();
|
if (this.get("id").isIdentifier()) {
|
||||||
|
return this.get("init").resolve();
|
||||||
|
} else {
|
||||||
|
// otherwise it's a request for a destructuring declarator and i'm not
|
||||||
|
// ready to resolve those just yet
|
||||||
|
}
|
||||||
} else if (this.isIdentifier()) {
|
} else if (this.isIdentifier()) {
|
||||||
var binding = this.scope.getBinding(this.node.name);
|
var binding = this.scope.getBinding(this.node.name);
|
||||||
if (!binding) return;
|
if (!binding || binding.reassigned) return;
|
||||||
|
|
||||||
if (binding.path === this) {
|
if (binding.path === this) {
|
||||||
return this;
|
return this;
|
||||||
@ -270,27 +291,44 @@ export default class TraversalPath {
|
|||||||
if (!prop.isProperty()) continue;
|
if (!prop.isProperty()) continue;
|
||||||
|
|
||||||
var key = prop.get("key");
|
var key = prop.get("key");
|
||||||
if (key.isIdentifier({ name: targetName }) || key.isLiteral({ value: targetName })) {
|
|
||||||
return prop.get("value");
|
// { foo: obj }
|
||||||
}
|
var match = prop.isnt("computed") && key.isIdentifier({ name: targetName });
|
||||||
|
|
||||||
|
// { "foo": "obj" } or { ["foo"]: "obj" }
|
||||||
|
match ||= key.isLiteral({ value: targetName });
|
||||||
|
|
||||||
|
if (match) return prop.get("value");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inferType(path: TraversalPath) {
|
inferType(path: TraversalPath): ?Object {
|
||||||
path = path.resolve();
|
path = path.resolve();
|
||||||
if (!path) return;
|
if (!path) return;
|
||||||
|
|
||||||
if (path.isRestElement() || path.isArrayExpression()) {
|
if (path.isRestElement() || path.parentPath.isRestElement() || path.isArrayExpression()) {
|
||||||
return t.genericTypeAnnotation(t.identifier("Array"));
|
return t.genericTypeAnnotation(t.identifier("Array"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.parentPath.isTypeCastExpression()) {
|
||||||
|
return path.parentPath.node.typeAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.isTypeCastExpression()) {
|
||||||
|
return path.node.typeAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
if (path.isObjectExpression()) {
|
if (path.isObjectExpression()) {
|
||||||
return t.genericTypeAnnotation(t.identifier("Object"));
|
return t.genericTypeAnnotation(t.identifier("Object"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.isFunction()) {
|
||||||
|
return t.identifier("Function");
|
||||||
|
}
|
||||||
|
|
||||||
if (path.isLiteral()) {
|
if (path.isLiteral()) {
|
||||||
var value = path.node.value;
|
var value = path.node.value;
|
||||||
if (isString(value)) return t.stringTypeAnnotation();
|
if (isString(value)) return t.stringTypeAnnotation();
|
||||||
@ -304,39 +342,44 @@ export default class TraversalPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isScope() {
|
isScope(): boolean {
|
||||||
return t.isScope(this.node, this.parent);
|
return t.isScope(this.node, this.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
isReferencedIdentifier(opts) {
|
isReferencedIdentifier(opts): boolean {
|
||||||
return t.isReferencedIdentifier(this.node, this.parent, opts);
|
return t.isReferencedIdentifier(this.node, this.parent, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
isReferenced() {
|
isReferenced(): boolean {
|
||||||
return t.isReferenced(this.node, this.parent);
|
return t.isReferenced(this.node, this.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
isBlockScoped() {
|
isBlockScoped(): boolean {
|
||||||
return t.isBlockScoped(this.node);
|
return t.isBlockScoped(this.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
isVar() {
|
isVar(): boolean {
|
||||||
return t.isVar(this.node);
|
return t.isVar(this.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
isScope() {
|
isScope(): boolean {
|
||||||
return t.isScope(this.node, this.parent);
|
return t.isScope(this.node, this.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
isTypeGeneric(genericName: string, hasTypeParameters?): boolean {
|
isTypeGeneric(genericName: string, opts = {}): boolean {
|
||||||
var type = this.getTypeAnnotation().annotation;
|
var typeInfo = this.getTypeAnnotation();
|
||||||
|
var type = typeInfo.annotation;
|
||||||
if (!type) return false;
|
if (!type) return false;
|
||||||
|
|
||||||
|
if (type.inferred && opts.inference === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!t.isGenericTypeAnnotation(type) || !t.isIdentifier(type.id, { name: genericName })) {
|
if (!t.isGenericTypeAnnotation(type) || !t.isIdentifier(type.id, { name: genericName })) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasTypeParameters && !type.typeParameters) {
|
if (opts.requireTypeParameters && !type.typeParameters) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,10 +391,64 @@ export default class TraversalPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
traverse(opts, state) {
|
traverse(opts, state) {
|
||||||
traverse(this.node, opts, this.scope, state);
|
traverse(this.node, opts, this.scope, state, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match the current node if it matches the provided `pattern`.
|
||||||
|
*
|
||||||
|
* For example, given the match `React.createClass` it would match the
|
||||||
|
* parsed nodes of `React.createClass` and `React["createClass"]`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
matchesPattern(pattern: string, allowPartial?: boolean): boolean {
|
||||||
|
var parts = pattern.split(".");
|
||||||
|
|
||||||
|
// not a member expression
|
||||||
|
if (!this.isMemberExpression()) return false;
|
||||||
|
|
||||||
|
var search = [this.node];
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
while (search.length) {
|
||||||
|
var node = search.shift();
|
||||||
|
|
||||||
|
if (allowPartial && i === parts.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.isIdentifier(node)) {
|
||||||
|
// this part doesn't match
|
||||||
|
if (parts[i] !== node.name) return false;
|
||||||
|
} else if (t.isLiteral(node)) {
|
||||||
|
// this part doesn't match
|
||||||
|
if (parts[i] !== node.value) return false;
|
||||||
|
} else if (t.isMemberExpression(node)) {
|
||||||
|
if (node.computed && !t.isLiteral(node.property)) {
|
||||||
|
// we can't deal with this
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
search.push(node.object);
|
||||||
|
search.push(node.property);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we can't deal with this
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// too many parts
|
||||||
|
if (++i > parts.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assign(TraversalPath.prototype, require("./evaluation"));
|
||||||
|
|
||||||
for (var i = 0; i < t.TYPES.length; i++) {
|
for (var i = 0; i < t.TYPES.length; i++) {
|
||||||
let type = t.TYPES[i];
|
let type = t.TYPES[i];
|
||||||
let typeKey = `is${type}`;
|
let typeKey = `is${type}`;
|
||||||
@ -75,7 +75,7 @@ export default class Scope {
|
|||||||
if (cached) {
|
if (cached) {
|
||||||
return cached;
|
return cached;
|
||||||
} else {
|
} else {
|
||||||
path.setData("scope", this);
|
//path.setData("scope", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
@ -245,7 +245,7 @@ export default class Scope {
|
|||||||
if (t.isReferencedIdentifier(node, parent) && node.name === oldName) {
|
if (t.isReferencedIdentifier(node, parent) && node.name === oldName) {
|
||||||
node.name = newName;
|
node.name = newName;
|
||||||
} else if (t.isDeclaration(node)) {
|
} else if (t.isDeclaration(node)) {
|
||||||
var ids = t.getBindingIdentifiers(node);
|
var ids = this.getBindingIdentifiers();
|
||||||
for (var name in ids) {
|
for (var name in ids) {
|
||||||
if (name === oldName) ids[name].name = newName;
|
if (name === oldName) ids[name].name = newName;
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ export default class Scope {
|
|||||||
|
|
||||||
if (t.isIdentifier(node)) {
|
if (t.isIdentifier(node)) {
|
||||||
var binding = this.getBinding(node.name);
|
var binding = this.getBinding(node.name);
|
||||||
if (binding && binding.isTypeGeneric("Array")) return node;
|
if (binding && binding.isTypeGeneric("Array", { inference: false })) return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isArrayExpression(node)) {
|
if (t.isArrayExpression(node)) {
|
||||||
@ -613,26 +613,6 @@ export default class Scope {
|
|||||||
return binding && binding.identifier;
|
return binding && binding.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Description
|
|
||||||
*/
|
|
||||||
|
|
||||||
getOwnImmutableBindingValue(name: string) {
|
|
||||||
return this._immutableBindingInfoToValue(this.getOwnBindingInfo(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description
|
|
||||||
*/
|
|
||||||
|
|
||||||
getImmutableBindingValue(name: string) {
|
|
||||||
return this._immutableBindingInfoToValue(this.getBinding(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
_immutableBindingInfoToValue(binding) {
|
|
||||||
if (binding) return binding.getValueIfImmutable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description
|
* Description
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -297,7 +297,6 @@ toFastProperties(t);
|
|||||||
toFastProperties(t.VISITOR_KEYS);
|
toFastProperties(t.VISITOR_KEYS);
|
||||||
|
|
||||||
exports.__esModule = true;
|
exports.__esModule = true;
|
||||||
assign(t, require("./evaluators"));
|
|
||||||
assign(t, require("./retrievers"));
|
assign(t, require("./retrievers"));
|
||||||
assign(t, require("./validators"));
|
assign(t, require("./validators"));
|
||||||
assign(t, require("./converters"));
|
assign(t, require("./converters"));
|
||||||
|
|||||||
@ -93,7 +93,7 @@
|
|||||||
"TypeofTypeAnnotation": ["argument"],
|
"TypeofTypeAnnotation": ["argument"],
|
||||||
"TypeAlias": ["id", "typeParameters", "right"],
|
"TypeAlias": ["id", "typeParameters", "right"],
|
||||||
"TypeAnnotation": ["typeAnnotation"],
|
"TypeAnnotation": ["typeAnnotation"],
|
||||||
"TypeCastExpression": ["expression"],
|
"TypeCastExpression": ["expression", "typeAnnotation"],
|
||||||
"TypeParameterDeclaration": ["params"],
|
"TypeParameterDeclaration": ["params"],
|
||||||
"TypeParameterInstantiation": ["params"],
|
"TypeParameterInstantiation": ["params"],
|
||||||
"ObjectTypeAnnotation": ["key", "value"],
|
"ObjectTypeAnnotation": ["key", "value"],
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
var arr = [for (i of [1, 2, 3]) i * i];
|
var arr = [for (i of nums) i * i];
|
||||||
|
|||||||
@ -7,7 +7,7 @@ var arr = (function () {
|
|||||||
var _iteratorError = undefined;
|
var _iteratorError = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (var _iterator = [1, 2, 3][Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
for (var _iterator = nums[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||||
var i = _step.value;
|
var i = _step.value;
|
||||||
|
|
||||||
_arr.push(i * i);
|
_arr.push(i * i);
|
||||||
@ -28,4 +28,4 @@ var arr = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return _arr;
|
return _arr;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
function add() {
|
function add() {
|
||||||
return [for (i of [1, 2, 3]) i * this.multiplier];
|
return [for (i of nums) i * this.multiplier];
|
||||||
}
|
}
|
||||||
|
|
||||||
add.call({ multiplier: 5 });
|
add.call({ multiplier: 5 });
|
||||||
|
|||||||
@ -10,7 +10,7 @@ function add() {
|
|||||||
var _iteratorError = undefined;
|
var _iteratorError = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (var _iterator = [1, 2, 3][Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
for (var _iterator = nums[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||||
var i = _step.value;
|
var i = _step.value;
|
||||||
|
|
||||||
_ref.push(i * _this.multiplier);
|
_ref.push(i * _this.multiplier);
|
||||||
@ -34,4 +34,4 @@ function add() {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
add.call({ multiplier: 5 });
|
add.call({ multiplier: 5 });
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user