merge internal transformers into single traversal pass
This commit is contained in:
@@ -4,6 +4,7 @@ import moduleFormatters from "../modules";
|
||||
import PluginManager from "./plugin-manager";
|
||||
import shebangRegex from "shebang-regex";
|
||||
import TraversalPath from "../../traversal/path";
|
||||
import Transformer from "../transformer";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import isAbsolute from "path-is-absolute";
|
||||
import resolveRc from "../../tools/resolve-rc";
|
||||
@@ -26,19 +27,6 @@ import path from "path";
|
||||
import each from "lodash/collection/each";
|
||||
import * as t from "../../types";
|
||||
|
||||
var checkTransformerVisitor = {
|
||||
exit(node, parent, scope, state) {
|
||||
checkPath(state.stack, this);
|
||||
}
|
||||
};
|
||||
|
||||
function checkPath(stack, path) {
|
||||
each(stack, function (pass) {
|
||||
if (pass.shouldRun || pass.ran) return;
|
||||
pass.checkPath(path);
|
||||
});
|
||||
}
|
||||
|
||||
export default class File {
|
||||
constructor(opts = {}, pipeline) {
|
||||
this.dynamicImportTypes = {};
|
||||
@@ -234,7 +222,46 @@ export default class File {
|
||||
stack = beforePlugins.concat(stack, afterPlugins);
|
||||
|
||||
// register
|
||||
this.transformerStack = stack.concat(secondaryStack);
|
||||
this.transformerStack = this.mergeStack(stack.concat(secondaryStack));
|
||||
|
||||
|
||||
}
|
||||
|
||||
mergeStack(_stack) {
|
||||
var stack = [];
|
||||
var ignore = [];
|
||||
|
||||
for (let pass of (_stack: Array)) {
|
||||
// been merged
|
||||
if (ignore.indexOf(pass) >= 0) continue;
|
||||
|
||||
var category = pass.transformer.metadata.category;
|
||||
|
||||
// can't merge
|
||||
if (!pass.canTransform() || !category) {
|
||||
stack.push(pass);
|
||||
continue;
|
||||
}
|
||||
|
||||
var mergeStack = [];
|
||||
for (let pass of (_stack: Array)) {
|
||||
if (pass.transformer.metadata.category === category) {
|
||||
mergeStack.push(pass);
|
||||
ignore.push(pass);
|
||||
}
|
||||
}
|
||||
|
||||
var visitors = [];
|
||||
for (let pass of (mergeStack: Array)) {
|
||||
visitors.push(pass.handlers);
|
||||
}
|
||||
var visitor = traverse.visitors.merge(visitors);
|
||||
var mergeTransformer = new Transformer(category, visitor);
|
||||
//console.log(mergeTransformer);
|
||||
stack.push(mergeTransformer.buildPass(this));
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
set(key: string, val): any {
|
||||
@@ -357,23 +384,6 @@ export default class File {
|
||||
return err;
|
||||
}
|
||||
|
||||
checkPath(path) {
|
||||
if (Array.isArray(path)) {
|
||||
for (var i = 0; i < path.length; i++) {
|
||||
this.checkPath(path[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var stack = this.transformerStack;
|
||||
|
||||
checkPath(stack, path);
|
||||
|
||||
path.traverse(checkTransformerVisitor, {
|
||||
stack: stack
|
||||
});
|
||||
}
|
||||
|
||||
mergeSourceMap(map: Object) {
|
||||
var opts = this.opts;
|
||||
|
||||
@@ -461,10 +471,6 @@ export default class File {
|
||||
this._addAst(ast);
|
||||
this.log.debug("End set AST");
|
||||
|
||||
this.log.debug("Start prepass");
|
||||
this.checkPath(this.path);
|
||||
this.log.debug("End prepass");
|
||||
|
||||
this.log.debug("Start module formatter init");
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canTransform()) {
|
||||
|
||||
@@ -10,10 +10,6 @@ export default function (exports, opts) {
|
||||
return t.assignmentExpression("=", left, right);
|
||||
};
|
||||
|
||||
exports.shouldVisit = function (node) {
|
||||
return node.operator && (node.operator === opts.operator || node.operator === opts.operator + "=");
|
||||
};
|
||||
|
||||
exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
// hit the `AssignmentExpression` one below
|
||||
if (this.isCompletionRecord()) return;
|
||||
|
||||
@@ -10,12 +10,6 @@ import * as react from "./react";
|
||||
import * as t from "../../types";
|
||||
|
||||
export default function (exports, opts) {
|
||||
exports.shouldVisit = function (node) {
|
||||
if (t.isJSX(node)) return true;
|
||||
if (react.isCreateClass(node)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
exports.JSXIdentifier = function (node, parent) {
|
||||
if (node.name === "this" && this.isReferenced()) {
|
||||
return t.thisExpression();
|
||||
|
||||
@@ -5,6 +5,13 @@ var pipeline = new Pipeline;
|
||||
//
|
||||
|
||||
import transformers from "./transformers";
|
||||
|
||||
for (var key in transformers) {
|
||||
var transformer = transformers[key];
|
||||
var metadata = transformer.metadata = transformer.metadata || {};
|
||||
metadata.category = metadata.category || "builtin";
|
||||
}
|
||||
|
||||
pipeline.addTransformers(transformers);
|
||||
|
||||
//
|
||||
|
||||
@@ -8,27 +8,18 @@ import traverse from "../traversal";
|
||||
|
||||
export default class TransformerPass {
|
||||
constructor(file: File, transformer: Transformer) {
|
||||
this.shouldTransform = !transformer.shouldVisit;
|
||||
this.transformer = transformer;
|
||||
this.handlers = transformer.handlers;
|
||||
this.skipKey = transformer.skipKey;
|
||||
this.file = file;
|
||||
this.ran = false;
|
||||
this.transformer = transformer;
|
||||
this.handlers = transformer.handlers;
|
||||
this.skipKey = transformer.skipKey;
|
||||
this.file = file;
|
||||
this.ran = false;
|
||||
}
|
||||
|
||||
canTransform(): boolean {
|
||||
return this.file.pipeline.canTransform(this.transformer, this.file.opts);
|
||||
}
|
||||
|
||||
checkPath(path: TraversalPath): boolean {
|
||||
if (this.shouldTransform || this.ran) return;
|
||||
|
||||
this.shouldTransform = this.transformer.shouldVisit(path.node);
|
||||
}
|
||||
|
||||
transform() {
|
||||
if (!this.shouldTransform) return;
|
||||
|
||||
var file = this.file;
|
||||
|
||||
file.log.debug(`Start transformer ${this.transformer.key}`);
|
||||
|
||||
@@ -25,7 +25,6 @@ export default class Transformer {
|
||||
};
|
||||
|
||||
this.manipulateOptions = take("manipulateOptions");
|
||||
this.shouldVisit = take("shouldVisit");
|
||||
this.metadata = take("metadata") || {};
|
||||
this.parser = take("parser");
|
||||
this.post = take("post");
|
||||
@@ -41,18 +40,6 @@ export default class Transformer {
|
||||
|
||||
this.handlers = this.normalize(transformer);
|
||||
this.key = transformerKey;
|
||||
|
||||
//
|
||||
|
||||
if (!this.shouldVisit && !this.handlers.enter && !this.handlers.exit) {
|
||||
var types = Object.keys(this.handlers);
|
||||
this.shouldVisit = function (node) {
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
if (node.type === types[i]) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
normalize(transformer: Object): Object {
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
import * as defineMap from "../../helpers/define-map";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isProperty(node) && (node.kind === "get" || node.kind === "set");
|
||||
}
|
||||
export var ObjectExpression = {
|
||||
exit(node, parent, scope, file) {
|
||||
var mutatorMap = {};
|
||||
var hasAny = false;
|
||||
|
||||
export function ObjectExpression(node, parent, scope, file) {
|
||||
var mutatorMap = {};
|
||||
var hasAny = false;
|
||||
node.properties = node.properties.filter(function (prop) {
|
||||
if (prop.kind === "get" || prop.kind === "set") {
|
||||
hasAny = true;
|
||||
defineMap.push(mutatorMap, prop, prop.kind, file);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
node.properties = node.properties.filter(function (prop) {
|
||||
if (prop.kind === "get" || prop.kind === "set") {
|
||||
hasAny = true;
|
||||
defineMap.push(mutatorMap, prop, prop.kind, file);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!hasAny) return;
|
||||
|
||||
if (!hasAny) return;
|
||||
|
||||
return t.callExpression(
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")),
|
||||
[node, defineMap.toDefineObject(mutatorMap)]
|
||||
);
|
||||
}
|
||||
return t.callExpression(
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")),
|
||||
[node, defineMap.toDefineObject(mutatorMap)]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var shouldVisit = t.isArrowFunctionExpression;
|
||||
|
||||
export function ArrowFunctionExpression(node) {
|
||||
t.ensureBlock(node);
|
||||
|
||||
|
||||
@@ -37,10 +37,6 @@ function standardizeLets(declars) {
|
||||
}
|
||||
}
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const");
|
||||
}
|
||||
|
||||
export function VariableDeclaration(node, parent, scope, file) {
|
||||
if (!isLet(node, parent)) return;
|
||||
|
||||
|
||||
@@ -11,17 +11,17 @@ import * as t from "../../../types";
|
||||
|
||||
const PROPERTY_COLLISION_METHOD_NAME = "__initializeProperties";
|
||||
|
||||
export var shouldVisit = t.isClass;
|
||||
|
||||
export function ClassDeclaration(node, parent, scope, file) {
|
||||
return t.variableDeclaration("let", [
|
||||
t.variableDeclarator(node.id, t.toExpression(node))
|
||||
]);
|
||||
}
|
||||
|
||||
export function ClassExpression(node, parent, scope, file) {
|
||||
return new ClassTransformer(this, file).run();
|
||||
}
|
||||
export var ClassExpression = {
|
||||
exit(node, parent, scope, file) {
|
||||
return new ClassTransformer(this, file).run();
|
||||
}
|
||||
};
|
||||
|
||||
var collectPropertyReferencesVisitor = {
|
||||
Identifier: {
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isVariableDeclaration(node, { kind: "const" }) || t.isImportDeclaration(node);
|
||||
}
|
||||
|
||||
var visitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (this.isAssignmentExpression() || this.isUpdateExpression()) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var shouldVisit = t.isPattern;
|
||||
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
var left = node.left;
|
||||
|
||||
@@ -83,7 +81,6 @@ exports.Function = function (node, parent, scope, file) {
|
||||
|
||||
var block = node.body;
|
||||
block.body = nodes.concat(block.body);
|
||||
this.checkSelf();
|
||||
};
|
||||
|
||||
export function CatchClause(node, parent, scope, file) {
|
||||
@@ -104,8 +101,6 @@ export function CatchClause(node, parent, scope, file) {
|
||||
destructuring.init(pattern, ref);
|
||||
|
||||
node.body.body = nodes.concat(node.body.body);
|
||||
|
||||
this.checkSelf();
|
||||
}
|
||||
|
||||
export function ExpressionStatement(node, parent, scope, file) {
|
||||
|
||||
@@ -2,8 +2,6 @@ import * as messages from "../../../messages";
|
||||
import * as util from "../../../util";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var shouldVisit = t.isForOfStatement;
|
||||
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
if (this.get("right").isArrayExpression()) {
|
||||
return _ForOfStatementArray.call(this, node, scope, file);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export { shouldVisit } from "../internal/modules";
|
||||
|
||||
function keepBlockHoist(node, nodes) {
|
||||
if (node._blockHoist) {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import ReplaceSupers from "../../helpers/replace-supers";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var shouldVisit = t.isSuper;
|
||||
|
||||
function Property(path, node, scope, getObjectRef, file) {
|
||||
if (!node.method) return;
|
||||
|
||||
|
||||
@@ -3,10 +3,6 @@ import * as util from "../../../util";
|
||||
import traverse from "../../../traversal";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isFunction(node) && hasDefaults(node);
|
||||
}
|
||||
|
||||
var hasDefaults = function (node) {
|
||||
for (var i = 0; i < node.params.length; i++) {
|
||||
if (!t.isIdentifier(node.params[i])) return true;
|
||||
@@ -96,6 +92,4 @@ exports.Function = function (node, parent, scope, file) {
|
||||
} else {
|
||||
node.body.body = body.concat(node.body.body);
|
||||
}
|
||||
|
||||
this.checkSelf();
|
||||
};
|
||||
|
||||
@@ -2,8 +2,6 @@ import isNumber from "lodash/lang/isNumber";
|
||||
import * as util from "../../../util";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var shouldVisit = t.isRestElement;
|
||||
|
||||
var memberExpressionOptimisationVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
// check if this scope has a local binding that will shadow the rest parameter
|
||||
@@ -96,7 +94,6 @@ exports.Function = function (node, parent, scope, file) {
|
||||
candidate.replaceWith(argsId);
|
||||
optimizeMemberExpression(candidate.parent, node.params.length);
|
||||
}
|
||||
this.checkSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -138,5 +135,4 @@ exports.Function = function (node, parent, scope, file) {
|
||||
});
|
||||
loop._blockHoist = node.params.length + 1;
|
||||
node.body.body.unshift(loop);
|
||||
this.checkSelf();
|
||||
};
|
||||
|
||||
@@ -63,42 +63,40 @@ function spec(node, body, objId, initProps, file) {
|
||||
}
|
||||
}
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isProperty(node) && node.computed;
|
||||
}
|
||||
export var ObjectExpression = {
|
||||
exit(node, parent, scope, file) {
|
||||
var hasComputed = false;
|
||||
|
||||
export function ObjectExpression(node, parent, scope, file) {
|
||||
var hasComputed = false;
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
|
||||
if (hasComputed) break;
|
||||
}
|
||||
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
|
||||
if (hasComputed) break;
|
||||
if (!hasComputed) return;
|
||||
|
||||
var initProps = [];
|
||||
var objId = scope.generateUidBasedOnNode(parent);
|
||||
|
||||
//
|
||||
|
||||
var body = [];
|
||||
|
||||
//
|
||||
|
||||
var callback = spec;
|
||||
if (file.isLoose("es6.properties.computed")) callback = loose;
|
||||
|
||||
var result = callback(node, body, objId, initProps, file);
|
||||
if (result) return result;
|
||||
|
||||
//
|
||||
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(objId, t.objectExpression(initProps))
|
||||
]));
|
||||
|
||||
body.push(t.expressionStatement(objId));
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
if (!hasComputed) return;
|
||||
|
||||
var initProps = [];
|
||||
var objId = scope.generateUidBasedOnNode(parent);
|
||||
|
||||
//
|
||||
|
||||
var body = [];
|
||||
|
||||
//
|
||||
|
||||
var callback = spec;
|
||||
if (file.isLoose("es6.properties.computed")) callback = loose;
|
||||
|
||||
var result = callback(node, body, objId, initProps, file);
|
||||
if (result) return result;
|
||||
|
||||
//
|
||||
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(objId, t.objectExpression(initProps))
|
||||
]));
|
||||
|
||||
body.push(t.expressionStatement(objId));
|
||||
|
||||
return body;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isProperty(node) && (node.method || node.shorthand);
|
||||
}
|
||||
|
||||
export function Property(node) {
|
||||
if (node.method) {
|
||||
node.method = false;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import * as regex from "../../helpers/regex";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return regex.is(node, "y");
|
||||
}
|
||||
|
||||
export function Literal(node) {
|
||||
if (!regex.is(node, "y")) return;
|
||||
return t.newExpression(t.identifier("RegExp"), [
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import rewritePattern from "regexpu/rewrite-pattern";
|
||||
import * as regex from "../../helpers/regex";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return regex.is(node, "u");
|
||||
}
|
||||
|
||||
export function Literal(node) {
|
||||
if (!regex.is(node, "u")) return;
|
||||
node.regex.pattern = rewritePattern(node.regex.pattern, node.regex.flags);
|
||||
|
||||
@@ -44,8 +44,6 @@ function build(props, scope) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
export var shouldVisit = t.isSpreadElement;
|
||||
|
||||
export function ArrayExpression(node, parent, scope) {
|
||||
var elements = node.elements;
|
||||
if (!hasSpread(elements)) return;
|
||||
|
||||
@@ -4,10 +4,6 @@ var buildBinaryExpression = function (left, right) {
|
||||
return t.binaryExpression("+", left, right);
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isTemplateLiteral(node) || t.isTaggedTemplateExpression(node);
|
||||
}
|
||||
|
||||
export function TaggedTemplateExpression(node, parent, scope, file) {
|
||||
var quasi = node.quasi;
|
||||
var args = [];
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function shouldVisit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
export var metadata = {
|
||||
stage: 0
|
||||
};
|
||||
|
||||
export function shouldVisit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@ export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return !!node.decorators;
|
||||
}
|
||||
|
||||
export function ObjectExpression(node, parent, scope, file) {
|
||||
var hasDecorators = false;
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
|
||||
@@ -5,8 +5,6 @@ export var metadata = {
|
||||
stage: 0
|
||||
};
|
||||
|
||||
export var shouldVisit = t.isDoExpression;
|
||||
|
||||
export function DoExpression(node) {
|
||||
var body = node.body.body;
|
||||
if (body.length) {
|
||||
|
||||
@@ -6,10 +6,6 @@ export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isExportDefaultSpecifier(node) || t.isExportNamespaceSpecifier(node);
|
||||
}
|
||||
|
||||
function build(node, nodes, scope) {
|
||||
var first = node.specifiers[0];
|
||||
if (!t.isExportNamespaceSpecifier(first) && !t.isExportDefaultSpecifier(first)) return;
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
export var metadata = {
|
||||
stage: 1
|
||||
};
|
||||
|
||||
export function shouldVisit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,124 +1,66 @@
|
||||
export default {
|
||||
"utility.removeDebugger": require("./utility/remove-debugger"),
|
||||
"utility.removeConsole": require("./utility/remove-console"),
|
||||
|
||||
"utility.inlineEnvironmentVariables": require("./utility/inline-environment-variables"),
|
||||
"utility.inlineExpressions": require("./utility/inline-expressions"),
|
||||
|
||||
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
|
||||
|
||||
_modules: require("./internal/modules"),
|
||||
|
||||
"es7.classProperties": require("./es7/class-properties"),
|
||||
"es7.trailingFunctionCommas": require("./es7/trailing-function-commas"),
|
||||
"es7.asyncFunctions": require("./es7/async-functions"),
|
||||
"es7.decorators": require("./es7/decorators"),
|
||||
|
||||
strict: require("./other/strict"),
|
||||
|
||||
_validation: require("./internal/validation"),
|
||||
|
||||
"validation.undeclaredVariableCheck": require("./validation/undeclared-variable-check"),
|
||||
"validation.react": require("./validation/react"),
|
||||
|
||||
// this goes at the start so we only transform the original user code
|
||||
"spec.functionName": require("./spec/function-name"),
|
||||
|
||||
// needs to be before `_shadowFunctions`
|
||||
"es6.arrowFunctions": require("./es6/arrow-functions"),
|
||||
|
||||
"spec.blockScopedFunctions": require("./spec/block-scoped-functions"),
|
||||
|
||||
"optimisation.react.constantElements": require("./optimisation/react.constant-elements"),
|
||||
"optimisation.react.inlineElements": require("./optimisation/react.inline-elements"),
|
||||
reactCompat: require("./other/react-compat"),
|
||||
react: require("./other/react"),
|
||||
|
||||
// needs to be before `regenerator` due to generator comprehensions
|
||||
// needs to be before `_shadowFunctions`
|
||||
"es7.comprehensions": require("./es7/comprehensions"),
|
||||
|
||||
"es6.classes": require("./es6/classes"),
|
||||
|
||||
asyncToGenerator: require("./other/async-to-generator"),
|
||||
bluebirdCoroutines: require("./other/bluebird-coroutines"),
|
||||
|
||||
"es6.objectSuper": require("./es6/object-super"),
|
||||
"es7.objectRestSpread": require("./es7/object-rest-spread"),
|
||||
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
|
||||
|
||||
"es6.spec.templateLiterals": require("./es6/spec.template-literals"),
|
||||
"es6.templateLiterals": require("./es6/template-literals"),
|
||||
|
||||
"es5.properties.mutators": require("./es5/properties.mutators"),
|
||||
"es6.properties.shorthand": require("./es6/properties.shorthand"),
|
||||
|
||||
// needs to be before `_shadowFunctions` due to define property closure
|
||||
"es6.properties.computed": require("./es6/properties.computed"),
|
||||
|
||||
"optimisation.flow.forOf": require("./optimisation/flow.for-of"),
|
||||
"es6.forOf": require("./es6/for-of"),
|
||||
|
||||
"es6.regex.sticky": require("./es6/regex.sticky"),
|
||||
"es6.regex.unicode": require("./es6/regex.unicode"),
|
||||
|
||||
"es6.constants": require("./es6/constants"),
|
||||
|
||||
// needs to be before `es6.parameters.default` as default parameters will destroy the rest param
|
||||
"es6.parameters.rest": require("./es6/parameters.rest"),
|
||||
|
||||
// needs to be after `es6.parameters.rest` as we use `toArray` and avoid turning an already known array into one
|
||||
"es6.spread": require("./es6/spread"),
|
||||
|
||||
// needs to be before `es6.blockScoping` as default parameters have a TDZ
|
||||
"es6.parameters.default": require("./es6/parameters.default"),
|
||||
|
||||
// needs to be before `es6.blockScoping` as let variables may be produced
|
||||
"es6.destructuring": require("./es6/destructuring"),
|
||||
|
||||
// needs to be before `_shadowFunctions` due to block scopes sometimes being wrapped in a
|
||||
// closure
|
||||
"es6.blockScoping": require("./es6/block-scoping"),
|
||||
|
||||
// needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks
|
||||
"es6.spec.blockScoping": require("./es6/spec.block-scoping"),
|
||||
|
||||
// needs to be after `es6.parameters.*` and `es6.blockScoping` due to needing pure
|
||||
// identifiers in parameters and variable declarators
|
||||
"es6.tailCall": require("./es6/tail-call"),
|
||||
|
||||
regenerator: require("./other/regenerator"),
|
||||
|
||||
// needs to be after `regenerator` due to needing `regeneratorRuntime` references
|
||||
// needs to be after `es6.forOf` due to needing `Symbol.iterator` references
|
||||
// needs to be before `es6.modules` due to dynamic imports
|
||||
runtime: require("./other/runtime"),
|
||||
|
||||
// needs to be before `_blockHoist` due to function hoisting etc
|
||||
runtime: require("./other/runtime"),
|
||||
"es7.exportExtensions": require("./es7/export-extensions"),
|
||||
"es6.modules": require("./es6/modules"),
|
||||
|
||||
_blockHoist: require("./internal/block-hoist"),
|
||||
|
||||
"spec.protoToAssign": require("./spec/proto-to-assign"),
|
||||
|
||||
_shadowFunctions: require("./internal/shadow-functions"),
|
||||
|
||||
"es7.doExpressions": require("./es7/do-expressions"),
|
||||
|
||||
"es6.spec.symbols": require("./es6/spec.symbols"),
|
||||
ludicrous: require("./other/ludicrous"),
|
||||
"spec.undefinedToVoid": require("./spec/undefined-to-void"),
|
||||
|
||||
_strict: require("./internal/strict"),
|
||||
_moduleFormatter: require("./internal/module-formatter"),
|
||||
|
||||
"es3.propertyLiterals": require("./es3/property-literals"),
|
||||
"es3.memberExpressionLiterals": require("./es3/member-expression-literals"),
|
||||
|
||||
"minification.memberExpressionLiterals": require("./minification/member-expression-literals"),
|
||||
"minification.propertyLiterals": require("./minification/property-literals"),
|
||||
|
||||
jscript: require("./other/jscript"),
|
||||
flow: require("./other/flow")
|
||||
flow: require("./other/flow"),
|
||||
_hoistDirectives: require("./internal/hoist-directives"),
|
||||
_blockHoist: require("./internal/block-hoist")
|
||||
};
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var BlockStatement = {
|
||||
exit(node) {
|
||||
for (var i = 0; i < node.body.length; i++) {
|
||||
var bodyNode = node.body[i];
|
||||
if (t.isExpressionStatement(bodyNode) && t.isLiteral(bodyNode.expression)) {
|
||||
bodyNode._blockHoist = Infinity;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export { BlockStatement as Program };
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as strict from "../../helpers/strict";
|
||||
|
||||
export function Program(program, parent, scope, file) {
|
||||
this.stop();
|
||||
|
||||
strict.wrap(program, function () {
|
||||
program.body = file.dynamicImports.concat(program.body);
|
||||
});
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isImportDeclaration(node) || t.isExportDeclaration(node);
|
||||
}
|
||||
|
||||
export function ImportDeclaration(node, parent, scope, file) {
|
||||
if (node.source) {
|
||||
node.source.value = file.resolveModuleSource(node.source.value);
|
||||
|
||||
@@ -82,21 +82,24 @@ function aliasFunction(getBody, path, scope) {
|
||||
}
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return true;
|
||||
}
|
||||
// todo: on all `this` and `arguments`, walk UP the tree instead of
|
||||
// crawling the entire function tree
|
||||
|
||||
export function Program(node, parent, scope) {
|
||||
aliasFunction(function () {
|
||||
return node.body;
|
||||
}, this, scope);
|
||||
export var Program = {
|
||||
exit(node, parent, scope) {
|
||||
aliasFunction(function () {
|
||||
return node.body;
|
||||
}, this, scope);
|
||||
}
|
||||
};
|
||||
|
||||
export function FunctionDeclaration(node, parent, scope) {
|
||||
aliasFunction(function () {
|
||||
t.ensureBlock(node);
|
||||
return node.body.body;
|
||||
}, this, scope);
|
||||
}
|
||||
export var FunctionDeclaration = {
|
||||
exit(node, parent, scope) {
|
||||
aliasFunction(function () {
|
||||
t.ensureBlock(node);
|
||||
return node.body.body;
|
||||
}, this, scope);
|
||||
}
|
||||
};
|
||||
|
||||
export { FunctionDeclaration as FunctionExpression };
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function Program(program, parent, scope, file) {
|
||||
if (file.transformers.strict.canTransform()) {
|
||||
var directive = file.get("existingStrictDirective");
|
||||
|
||||
if (!directive) {
|
||||
directive = t.expressionStatement(t.literal("use strict"));
|
||||
var first = program.body[0];
|
||||
if (first) {
|
||||
directive.leadingComments = first.leadingComments;
|
||||
first.leadingComments = [];
|
||||
}
|
||||
}
|
||||
|
||||
this.unshiftContainer("body", [directive]);
|
||||
}
|
||||
this.stop();
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var metadata = {
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
var left = node.left;
|
||||
if (t.isVariableDeclaration(left)) {
|
||||
@@ -43,16 +39,3 @@ export function Property(node, parent, scope, file) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function BlockStatement(node) {
|
||||
for (var i = 0; i < node.body.length; i++) {
|
||||
var bodyNode = node.body[i];
|
||||
if (t.isExpressionStatement(bodyNode) && t.isLiteral(bodyNode.expression)) {
|
||||
bodyNode._blockHoist = Infinity;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { BlockStatement as Program };
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { _ForOfStatementArray } from "../es6/for-of";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var shouldVisit = t.isForOfStatement;
|
||||
export var metadata = {
|
||||
optional: true
|
||||
};
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return node.isType || node.optional || node.implements || node.typeAnnotation || t.isFlow(node);
|
||||
}
|
||||
|
||||
export function Flow(node) {
|
||||
this.remove();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import regenerator from "regenerator";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isFunction(node) && (node.async || node.generator);
|
||||
}
|
||||
|
||||
export var Program = {
|
||||
enter(ast) {
|
||||
exit(ast) {
|
||||
regenerator.transform(ast);
|
||||
this.stop();
|
||||
this.checkSelf();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,22 +1,33 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export function Program(program, parent, scope, file) {
|
||||
var first = program.body[0];
|
||||
if (t.isExpressionStatement(first) && t.isLiteral(first.expression, { value: "use strict" })) {
|
||||
file.set("existingStrictDirective", program.body.shift());
|
||||
const THIS_BREAK_KEYS = ["FunctionExpression", "FunctionDeclaration", "ClassExpression", "ClassDeclaration"];
|
||||
|
||||
export var Program = {
|
||||
enter(program, parent, scope, file) {
|
||||
var first = program.body[0];
|
||||
|
||||
var directive;
|
||||
if (t.isExpressionStatement(first) && t.isLiteral(first.expression, { value: "use strict" })) {
|
||||
directive = first;
|
||||
} else {
|
||||
directive = t.expressionStatement(t.literal("use strict"));
|
||||
this.unshiftContainer("body", directive);
|
||||
if (first) {
|
||||
directive.leadingComments = first.leadingComments;
|
||||
first.leadingComments = [];
|
||||
}
|
||||
}
|
||||
directive._blockHoist = Infinity;
|
||||
}
|
||||
}
|
||||
|
||||
export function FunctionExpression() {
|
||||
this.skip();
|
||||
}
|
||||
|
||||
export { FunctionExpression as FunctionDeclaration };
|
||||
export { FunctionExpression as Class };
|
||||
|
||||
export function ThisExpression() {
|
||||
return t.identifier("undefined");
|
||||
if (!this.findParent(function (node) {
|
||||
return !node.shadow && THIS_BREAK_KEYS.indexOf(node.type) >= 0;
|
||||
})) {
|
||||
return t.identifier("undefined");
|
||||
}
|
||||
}
|
||||
|
||||
export function CallExpression(node, parent, scope, file) {
|
||||
|
||||
@@ -23,21 +23,6 @@ function statementList(key, path, file) {
|
||||
}
|
||||
}
|
||||
|
||||
export function shouldVisit(node) {
|
||||
var body;
|
||||
if (node.type === "SwitchCase") {
|
||||
body = node.consequent;
|
||||
} else if (node.type === "BlockStatement") {
|
||||
body = node.body;
|
||||
}
|
||||
if (body) {
|
||||
for (var i = 0; i < body.length; i++) {
|
||||
if (body[i].type === "FunctionDeclaration") return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function BlockStatement(node, parent, scope, file) {
|
||||
if ((t.isFunction(parent) && parent.body === node) || t.isExportDeclaration(parent)) {
|
||||
return;
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import * as messages from "../../../messages";
|
||||
import * as t from "../../../types";
|
||||
|
||||
export var metadata = {
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
export function shouldVisit(node) {
|
||||
return t.isModuleDeclaration(node) || (t.isCallExpression(node) && t.isIdentifier(node.callee, { name: "require" }));
|
||||
}
|
||||
|
||||
// check if the input Literal `source` is an alternate casing of "react"
|
||||
function check(source, file) {
|
||||
if (t.isLiteral(source)) {
|
||||
|
||||
@@ -2,8 +2,7 @@ import levenshtein from "leven";
|
||||
import * as messages from "../../../messages";
|
||||
|
||||
export var metadata = {
|
||||
optional: true,
|
||||
readOnly: true
|
||||
optional: true
|
||||
};
|
||||
|
||||
export function Identifier(node, parent, scope, file) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import TraversalContext from "./context";
|
||||
import { explode, verify } from "./visitors";
|
||||
import * as visitors from "./visitors";
|
||||
import * as messages from "../messages";
|
||||
import includes from "lodash/collection/includes";
|
||||
import * as t from "../types";
|
||||
@@ -14,7 +14,7 @@ export default function traverse(parent, opts, scope, state, parentPath) {
|
||||
}
|
||||
|
||||
if (!opts) opts = {};
|
||||
verify(opts);
|
||||
visitors.verify(opts);
|
||||
|
||||
// array of nodes
|
||||
if (Array.isArray(parent)) {
|
||||
@@ -26,8 +26,9 @@ export default function traverse(parent, opts, scope, state, parentPath) {
|
||||
}
|
||||
}
|
||||
|
||||
traverse.verify = verify;
|
||||
traverse.explode = explode;
|
||||
traverse.visitors = visitors;
|
||||
traverse.verify = visitors.verify;
|
||||
traverse.explode = visitors.explode;
|
||||
|
||||
traverse.node = function (node, opts, scope, state, parentPath) {
|
||||
var keys = t.VISITOR_KEYS[node.type];
|
||||
|
||||
@@ -107,12 +107,43 @@ export default class TraversalPath {
|
||||
return ancestry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
inType(types) {
|
||||
if (!Array.isArray(types)) types = [types];
|
||||
|
||||
var path = this;
|
||||
while (path) {
|
||||
for (var type of (types: Array)) {
|
||||
if (path.node.type === type) return true;
|
||||
}
|
||||
path = path.parentPath;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
findParent(callback) {
|
||||
var path = this;
|
||||
while (path) {
|
||||
if (callback(path.node)) return path.node;
|
||||
path = path.parentPath;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
queueNode(path) {
|
||||
if (this.context) {
|
||||
if (this.context && this.context.queue) {
|
||||
this.context.queue.push(path);
|
||||
}
|
||||
}
|
||||
@@ -136,7 +167,6 @@ export default class TraversalPath {
|
||||
} else if (this.isStatementOrBlock()) {
|
||||
if (this.node) nodes.push(this.node);
|
||||
this.container[this.key] = t.blockStatement(nodes);
|
||||
this.checkSelf();
|
||||
} else {
|
||||
throw new Error("We don't know what to do with this node type. We were previously a Statement but we can't fit in here?");
|
||||
}
|
||||
@@ -163,8 +193,6 @@ export default class TraversalPath {
|
||||
paths.push(TraversalPath.get(this, null, node, this.container, to));
|
||||
}
|
||||
}
|
||||
|
||||
this.checkPaths(paths);
|
||||
}
|
||||
|
||||
_containerInsertBefore(nodes) {
|
||||
@@ -234,7 +262,6 @@ export default class TraversalPath {
|
||||
} else if (this.isStatementOrBlock()) {
|
||||
if (this.node) nodes.unshift(this.node);
|
||||
this.container[this.key] = t.blockStatement(nodes);
|
||||
this.checkSelf();
|
||||
} else {
|
||||
throw new Error("We don't know what to do with this node type. We were previously a Statement but we can't fit in here?");
|
||||
}
|
||||
@@ -528,7 +555,7 @@ export default class TraversalPath {
|
||||
}
|
||||
|
||||
if (this.node === replacement) {
|
||||
return this.checkSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
// normalise inserting an entire AST
|
||||
@@ -572,26 +599,6 @@ export default class TraversalPath {
|
||||
|
||||
// potentially create new scope
|
||||
this.setScope();
|
||||
|
||||
this.checkSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
checkSelf() {
|
||||
this.checkPaths(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
checkPaths(paths) {
|
||||
var scope = this.scope;
|
||||
var file = scope && scope.file;
|
||||
if (file) file.checkPath(paths);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,9 +698,13 @@ export default class TraversalPath {
|
||||
|
||||
// call the function with the params (node, parent, scope, state)
|
||||
var replacement = fn.call(this, node, this.parent, this.scope, this.state);
|
||||
if (replacement) this.replaceWith(replacement, true);
|
||||
if (replacement) {
|
||||
this.replaceWith(replacement, true);
|
||||
this.queueNode(this);
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.shouldStop) break;
|
||||
if (this.shouldStop || this.removed) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ export function explode(visitor, mergeConflicts) {
|
||||
if (wrapper.type) {
|
||||
// merge the visitor if necessary or just put it back in
|
||||
if (visitor[wrapper.type]) {
|
||||
merge(visitor[wrapper.type], fns);
|
||||
mergePair(visitor[wrapper.type], fns);
|
||||
} else {
|
||||
visitor[wrapper.type] = fns;
|
||||
}
|
||||
} else {
|
||||
merge(visitor, fns);
|
||||
mergePair(visitor, fns);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ export function explode(visitor, mergeConflicts) {
|
||||
var existing = visitor[alias];
|
||||
if (existing) {
|
||||
if (mergeConflicts) {
|
||||
merge(existing, fns);
|
||||
mergePair(existing, fns);
|
||||
}
|
||||
} else {
|
||||
visitor[alias] = fns;
|
||||
@@ -105,6 +105,19 @@ export function verify(visitor) {
|
||||
visitor._verified = true;
|
||||
}
|
||||
|
||||
export function merge(visitors) {
|
||||
var rootVisitor = {};
|
||||
|
||||
for (var visitor of (visitors: Array)) {
|
||||
for (var type in visitor) {
|
||||
var nodeVisitor = rootVisitor[type] = rootVisitor[type] || {};
|
||||
mergePair(nodeVisitor, visitor[type]);
|
||||
}
|
||||
}
|
||||
|
||||
return rootVisitor;
|
||||
}
|
||||
|
||||
function ensureEntranceObjects(obj) {
|
||||
for (let key in obj) {
|
||||
if (shouldIgnoreKey(key)) continue;
|
||||
@@ -135,7 +148,7 @@ function addSelector(visitor, selector, fns) {
|
||||
};
|
||||
}
|
||||
|
||||
merge(visitor, fns);
|
||||
mergePair(visitor, fns);
|
||||
}
|
||||
|
||||
function wrapCheck(wrapper, fn) {
|
||||
@@ -159,7 +172,7 @@ function shouldIgnoreKey(key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function merge(dest, src) {
|
||||
function mergePair(dest, src) {
|
||||
for (var key in src) {
|
||||
dest[key] = (dest[key] || []).concat(src[key]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user