i made the javascripts faster with a transformer prepass to check what transformers actually have to be ran
This commit is contained in:
@@ -9,6 +9,7 @@ var transform = require("./transformation");
|
||||
var generate = require("./generation");
|
||||
var defaults = require("lodash/object/defaults");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var traverse = require("./traverse");
|
||||
var clone = require("./helpers/clone");
|
||||
var Scope = require("./traverse/scope");
|
||||
var util = require("./util");
|
||||
@@ -352,6 +353,8 @@ File.prototype.transform = function (ast) {
|
||||
modFormatter.init();
|
||||
}
|
||||
|
||||
this.checkNode(ast);
|
||||
|
||||
var astRun = function (key) {
|
||||
each(self.transformerStack, function (pass) {
|
||||
pass.astRun(key);
|
||||
@@ -367,6 +370,30 @@ File.prototype.transform = function (ast) {
|
||||
astRun("exit");
|
||||
};
|
||||
|
||||
var checkTransformerVisitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
state.check(node, scope);
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype.checkNode = function (node, scope) {
|
||||
var self = this;
|
||||
scope = scope || this.scope;
|
||||
|
||||
var check = function (node, scope) {
|
||||
each(self.transformerStack, function (pass) {
|
||||
if (pass.shouldRun) return;
|
||||
pass.checkNode(node, scope);
|
||||
});
|
||||
};
|
||||
|
||||
check(node, scope);
|
||||
|
||||
traverse(node, checkTransformerVisitor, scope, {
|
||||
check: check
|
||||
});
|
||||
};
|
||||
|
||||
File.prototype.generate = function () {
|
||||
var opts = this.opts;
|
||||
var ast = this.ast;
|
||||
|
||||
@@ -94,8 +94,10 @@ exports.Literal = function (node) {
|
||||
});
|
||||
|
||||
this.push(val);
|
||||
} else if (type === "boolean" || type === "number") {
|
||||
this.push(JSON.stringify(val));
|
||||
} else if (type === "number") {
|
||||
this.push(val + "");
|
||||
} else if (type === "boolean" ) {
|
||||
this.push(val ? "true" : "false");
|
||||
} else if (node.regex) {
|
||||
this.push("/" + node.regex.pattern + "/" + node.regex.flags);
|
||||
} else if (val === null) {
|
||||
|
||||
@@ -11,11 +11,14 @@ var contains = require("lodash/collection/contains");
|
||||
|
||||
function TransformerPass(file, transformer) {
|
||||
this.transformer = transformer;
|
||||
this.shouldRun = !transformer.check;
|
||||
this.handlers = transformer.handlers;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
TransformerPass.prototype.astRun = function (key) {
|
||||
if (!this.shouldRun) return;
|
||||
|
||||
var handlers = this.handlers;
|
||||
var file = this.file;
|
||||
|
||||
@@ -29,23 +32,39 @@ TransformerPass.prototype.canRun = function () {
|
||||
|
||||
var opts = this.file.opts;
|
||||
var key = transformer.key;
|
||||
|
||||
// internal
|
||||
if (key[0] === "_") return true;
|
||||
|
||||
// blacklist
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && contains(blacklist, key)) return false;
|
||||
|
||||
// whitelist
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist.length && !contains(whitelist, key)) return false;
|
||||
|
||||
// optional
|
||||
if (transformer.optional && !contains(opts.optional, key)) return false;
|
||||
|
||||
// experimental
|
||||
if (transformer.experimental && !opts.experimental) return false;
|
||||
|
||||
// playground
|
||||
if (transformer.playground && !opts.playground) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
TransformerPass.prototype.checkNode = function (node) {
|
||||
var check = this.transformer.check;
|
||||
if (check) {
|
||||
return this.shouldRun = check(node);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var transformVisitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
var fns = state.handlers[node.type];
|
||||
@@ -61,6 +80,8 @@ var transformVisitor = {
|
||||
};
|
||||
|
||||
TransformerPass.prototype.transform = function () {
|
||||
if (!this.shouldRun) return;
|
||||
|
||||
var file = this.file;
|
||||
|
||||
util.debug(file.opts.filename + ": Running transformer " + this.transformer.key);
|
||||
|
||||
@@ -16,13 +16,16 @@ var each = require("lodash/collection/each");
|
||||
|
||||
function Transformer(key, transformer, opts) {
|
||||
this.manipulateOptions = transformer.manipulateOptions;
|
||||
this.experimental = !!transformer.experimental;
|
||||
this.playground = !!transformer.playground;
|
||||
this.secondPass = !!transformer.secondPass;
|
||||
this.optional = !!transformer.optional;
|
||||
this.handlers = this.normalize(transformer);
|
||||
this.opts = opts || {};
|
||||
this.key = key;
|
||||
this.check = transformer.check;
|
||||
|
||||
this.experimental = !!transformer.experimental;
|
||||
this.playground = !!transformer.playground;
|
||||
this.secondPass = !!transformer.secondPass;
|
||||
this.optional = !!transformer.optional;
|
||||
|
||||
this.handlers = this.normalize(transformer);
|
||||
this.opts = opts || {};
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
Transformer.prototype.normalize = function (transformer) {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
var defineMap = require("../../helpers/define-map");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isProperty(node) && (node.kind === "get" || node.kind === "set");
|
||||
};
|
||||
|
||||
exports.ObjectExpression = function (node) {
|
||||
var mutatorMap = {};
|
||||
var hasAny = false;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isArrowFunctionExpression;
|
||||
|
||||
exports.ArrowFunctionExpression = function (node) {
|
||||
t.ensureBlock(node);
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ var t = require("../../../types");
|
||||
var values = require("lodash/object/values");
|
||||
var extend = require("lodash/object/extend");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const");
|
||||
};
|
||||
|
||||
var isLet = function (node, parent) {
|
||||
if (!t.isVariableDeclaration(node)) return false;
|
||||
if (node._let) return true;
|
||||
|
||||
@@ -6,6 +6,8 @@ var defineMap = require("../../helpers/define-map");
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isClass;
|
||||
|
||||
exports.ClassDeclaration = function (node, parent, scope, context, file) {
|
||||
return new Class(node, file, scope, true).run();
|
||||
};
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
var traverse = require("../../../traverse");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isVariableDeclaration(node, { kind: "const" });
|
||||
};
|
||||
|
||||
var visitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isPattern;
|
||||
|
||||
var buildVariableAssign = function (opts, id, init) {
|
||||
var op = opts.operator;
|
||||
if (t.isMemberExpression(id)) op = "=";
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isForOfStatement;
|
||||
|
||||
exports.ForOfStatement = function (node, parent, scope, context, file) {
|
||||
var callback = spec;
|
||||
if (file.isLoose("es6.forOf")) callback = loose;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = require("../internal/modules").check;
|
||||
|
||||
exports.ImportDeclaration = function (node, parent, scope, context, file) {
|
||||
var nodes = [];
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ var traverse = require("../../../traverse");
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isFunction(node) && hasDefaults(node);
|
||||
};
|
||||
|
||||
var hasDefaults = function (node) {
|
||||
for (var i = 0; i < node.params.length; i++) {
|
||||
if (t.isAssignmentPattern(node.params[i])) return true;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isRestElement;
|
||||
|
||||
var hasRest = function (node) {
|
||||
return t.isRestElement(node.params[node.params.length - 1]);
|
||||
};
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isProperty(node) && node.computed;
|
||||
};
|
||||
|
||||
exports.ObjectExpression = function (node, parent, scope, context, file) {
|
||||
var hasComputed = false;
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ var nameMethod = require("../../helpers/name-method");
|
||||
var t = require("../../../types");
|
||||
var clone = require("lodash/lang/clone");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isProperty(node) && (node.method || node.shorthand);
|
||||
};
|
||||
|
||||
exports.Property = function (node, parent, scope, context, file) {
|
||||
if (node.method) {
|
||||
node.method = false;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isSpreadElement;
|
||||
|
||||
var getSpreadLiteral = function (spread, file) {
|
||||
return file.toArray(spread.argument);
|
||||
|
||||
@@ -6,6 +6,10 @@ var buildBinaryExpression = function (left, right) {
|
||||
return t.binaryExpression("+", left, right);
|
||||
};
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isTemplateLiteral(node) || t.isTaggedTemplateExpression(node);
|
||||
};
|
||||
|
||||
exports.TaggedTemplateExpression = function (node, parent, scope, context, file) {
|
||||
var args = [];
|
||||
var quasi = node.quasi;
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
var rewritePattern = require("regexpu/rewrite-pattern");
|
||||
var pull = require("lodash/array/pull");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isLiteral(node) && node.regex && node.regex.flags.indexOf("u") >= 0;
|
||||
};
|
||||
|
||||
exports.Literal = function (node) {
|
||||
var regex = node.regex;
|
||||
|
||||
@@ -15,6 +15,10 @@ var resolveModuleSource = function (node, parent, scope, context, file) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isImportDeclaration(node) || t.isExportDeclaration(node);
|
||||
};
|
||||
|
||||
exports.ImportDeclaration = resolveModuleSource;
|
||||
|
||||
exports.ExportDeclaration = function (node, parent, scope) {
|
||||
|
||||
@@ -10,6 +10,12 @@ var esutils = require("esutils");
|
||||
var react = require("../../helpers/react");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = 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" && t.isReferenced(node, parent)) {
|
||||
return t.thisExpression();
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
var regenerator = require("regenerator-6to5");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isFunction(node) && (node.async || node.generator);
|
||||
};
|
||||
|
||||
exports.ast = {
|
||||
before: function (ast, file) {
|
||||
|
||||
@@ -23,6 +23,7 @@ exports.Property =
|
||||
exports.MethodDefinition = function (node, parent, scope, context, file) {
|
||||
if (node.kind !== "memo") return;
|
||||
node.kind = "get";
|
||||
file.checkNode(node, scope);
|
||||
|
||||
var value = node.value;
|
||||
t.ensureBlock(value);
|
||||
|
||||
@@ -10,11 +10,12 @@ var contains = require("lodash/collection/contains");
|
||||
var flatten = require("lodash/array/flatten");
|
||||
var compact = require("lodash/array/compact");
|
||||
|
||||
function TraversalContext() {
|
||||
function TraversalContext(scope) {
|
||||
this.shouldFlatten = false;
|
||||
this.shouldRemove = false;
|
||||
this.shouldSkip = false;
|
||||
this.shouldStop = false;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
TraversalContext.prototype.flatten = function () {
|
||||
@@ -44,20 +45,31 @@ TraversalContext.prototype.reset = function () {
|
||||
TraversalContext.prototype.maybeRemove = function (obj, key) {
|
||||
if (this.shouldRemove) {
|
||||
obj[key] = null;
|
||||
this.shouldFlatten = true;
|
||||
this.flatten();
|
||||
}
|
||||
};
|
||||
|
||||
function replaceNode(obj, key, node, result) {
|
||||
var isArray = Array.isArray(result);
|
||||
TraversalContext.prototype.replaceNode = function (obj, key, node, replacement, scope) {
|
||||
var isArray = Array.isArray(replacement);
|
||||
|
||||
// inherit comments from original node to the first replacement node
|
||||
var inheritTo = result;
|
||||
if (isArray) inheritTo = result[0];
|
||||
var inheritTo = replacement;
|
||||
if (isArray) inheritTo = replacement[0];
|
||||
if (inheritTo) t.inheritsComments(inheritTo, node);
|
||||
|
||||
// replace the node
|
||||
obj[key] = result;
|
||||
obj[key] = replacement;
|
||||
|
||||
var file = this.scope && this.scope.file;
|
||||
if (file) {
|
||||
if (isArray) {
|
||||
for (var i = 0; i < replacement.length; i++) {
|
||||
file.checkNode(replacement[i], scope);
|
||||
}
|
||||
} else {
|
||||
file.checkNode(replacement, scope);
|
||||
}
|
||||
}
|
||||
|
||||
// we're replacing a statement or block node with an array of statements so we better
|
||||
// ensure that it's a block
|
||||
@@ -66,39 +78,16 @@ function replaceNode(obj, key, node, result) {
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
return true;
|
||||
this.flatten();
|
||||
}
|
||||
}
|
||||
|
||||
TraversalContext.prototype.enterNode = function (obj, key, node, enter, parent, scope, state) {
|
||||
var result = enter(node, parent, scope, this, state);
|
||||
var flatten = false;
|
||||
|
||||
if (result) {
|
||||
flatten = replaceNode(obj, key, node, result);
|
||||
node = result;
|
||||
|
||||
if (flatten) {
|
||||
this.shouldFlatten = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.maybeRemove(obj, key);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
TraversalContext.prototype.exitNode = function (obj, key, node, exit, parent, scope, state) {
|
||||
var result = exit(node, parent, scope, this, state);
|
||||
var flatten = false;
|
||||
TraversalContext.prototype.call = function (fn, obj, key, node, parent, scope, state) {
|
||||
var replacement = fn(node, parent, scope, this, state);
|
||||
|
||||
if (result) {
|
||||
flatten = replaceNode(obj, key, node, result);
|
||||
node = result;
|
||||
|
||||
if (flatten) {
|
||||
this.shouldFlatten = true;
|
||||
}
|
||||
if (replacement) {
|
||||
this.replaceNode(obj, key, node, replacement, scope);
|
||||
node = replacement;
|
||||
}
|
||||
|
||||
this.maybeRemove(obj, key);
|
||||
@@ -122,7 +111,7 @@ TraversalContext.prototype.visitNode = function (obj, key, opts, scope, parent,
|
||||
ourScope = new Scope(node, parent, scope);
|
||||
}
|
||||
|
||||
node = this.enterNode(obj, key, node, opts.enter, parent, ourScope, state);
|
||||
node = this.call(opts.enter, obj, key, node, parent, ourScope, state);
|
||||
|
||||
if (this.shouldSkip) {
|
||||
return this.shouldStop;
|
||||
@@ -136,7 +125,7 @@ TraversalContext.prototype.visitNode = function (obj, key, opts, scope, parent,
|
||||
}
|
||||
} else {
|
||||
traverseNode(node, opts, ourScope, state);
|
||||
this.exitNode(obj, key, node, opts.exit, parent, ourScope, state);
|
||||
this.call(opts.exit, obj, key, node, parent, ourScope, state);
|
||||
}
|
||||
|
||||
return this.shouldStop;
|
||||
@@ -174,7 +163,7 @@ function traverseNode(node, opts, scope, state) {
|
||||
var keys = t.VISITOR_KEYS[node.type];
|
||||
if (!keys) return;
|
||||
|
||||
var context = new TraversalContext();
|
||||
var context = new TraversalContext(scope);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (context.visit(node, keys[i], opts, scope, state)) {
|
||||
return;
|
||||
|
||||
@@ -35,6 +35,18 @@ function Scope(block, parentBlock, parent, file) {
|
||||
|
||||
Scope.defaultDeclarations = flatten([globals.builtin, globals.browser, globals.node].map(Object.keys));
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {Object} opts
|
||||
* @param [state]
|
||||
*/
|
||||
|
||||
Scope.prototype.traverse = function (node, opts, state) {
|
||||
traverse(node, opts, this, state);
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
|
||||
@@ -44,28 +44,39 @@
|
||||
"ArrayPattern": ["Pattern"],
|
||||
"AssignmentPattern": ["Pattern"],
|
||||
|
||||
"Property": ["UserWhitespacable"],
|
||||
"Property": ["UserWhitespacable"],
|
||||
"JSXElement": ["UserWhitespacable", "Expression"],
|
||||
|
||||
"ArrayExpression": ["Expression"],
|
||||
"AssignmentExpression": ["Expression"],
|
||||
"AwaitExpression": ["Expression"],
|
||||
"BindFunctionExpression": ["Expression"],
|
||||
"BindMemberExpression": ["Expression"],
|
||||
"CallExpression": ["Expression"],
|
||||
"ComprehensionExpression": ["Expression", "Scope"],
|
||||
"ConditionalExpression": ["Expression"],
|
||||
"Identifier": ["Expression"],
|
||||
"Literal": ["Expression"],
|
||||
"MemberExpression": ["Expression"],
|
||||
"NewExpression": ["Expression"],
|
||||
"ObjectExpression": ["Expression"],
|
||||
"SequenceExpression": ["Expression"],
|
||||
"TaggedTemplateExpression": ["Expression"],
|
||||
"ThisExpression": ["Expression"],
|
||||
"UpdateExpression": ["Expression"],
|
||||
"ArrayExpression": ["Expression"],
|
||||
"AssignmentExpression": ["Expression"],
|
||||
"AwaitExpression": ["Expression"],
|
||||
"BindFunctionExpression": ["Expression"],
|
||||
"BindMemberExpression": ["Expression"],
|
||||
"CallExpression": ["Expression"],
|
||||
"ComprehensionExpression": ["Expression", "Scope"],
|
||||
"ConditionalExpression": ["Expression"],
|
||||
"Identifier": ["Expression"],
|
||||
"Literal": ["Expression"],
|
||||
"MemberExpression": ["Expression"],
|
||||
"NewExpression": ["Expression"],
|
||||
"ObjectExpression": ["Expression"],
|
||||
"SequenceExpression": ["Expression"],
|
||||
"TaggedTemplateExpression": ["Expression"],
|
||||
"ThisExpression": ["Expression"],
|
||||
"UpdateExpression": ["Expression"],
|
||||
"VirtualPropertyExpression": ["Expression"],
|
||||
"JSXEmptyExpression": ["Expression"],
|
||||
"JSXMemberExpression": ["Expression"],
|
||||
"YieldExpression": ["Expression"]
|
||||
"JSXEmptyExpression": ["Expression"],
|
||||
"JSXMemberExpression": ["Expression"],
|
||||
"YieldExpression": ["Expression"],
|
||||
|
||||
"JSXAttribute": ["JSX"],
|
||||
"JSXClosingElement": ["JSX"],
|
||||
"JSXElement": ["JSX"],
|
||||
"JSXEmptyExpression": ["JSX"],
|
||||
"JSXExpressionContainer": ["JSX"],
|
||||
"JSXIdentifier": ["JSX"],
|
||||
"JSXMemberExpression": ["JSX"],
|
||||
"JSXNamespacedName": ["JSX"],
|
||||
"JSXOpeningElement": ["JSX"],
|
||||
"JSXSpreadAttribute": ["JSX"]
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ exports.parse = function (opts, code, callback) {
|
||||
|
||||
var ast = acorn.parse(code, {
|
||||
allowImportExportEverywhere: opts.allowImportExportEverywhere,
|
||||
allowReturnOutsideFunction: true,
|
||||
allowReturnOutsideFunction: !opts._anal,
|
||||
ecmaVersion: opts.experimental ? 7 : 6,
|
||||
playground: opts.playground,
|
||||
strictMode: opts.strictMode,
|
||||
|
||||
Reference in New Issue
Block a user