yank out more transformers and put them into plugins

This commit is contained in:
Sebastian McKenzie 2015-06-15 16:35:41 +01:00
parent 939c00d33c
commit 3247851019
11 changed files with 19 additions and 403 deletions

View File

@ -30,7 +30,16 @@
"dependencies": {
"acorn-jsx": "^1.0.0",
"ast-types": "~0.7.0",
"babel-plugin-undefined-to-void": "^1.1.0",
"babel-plugin-constant-folding": "^1.0.1",
"babel-plugin-dead-code-elimination": "^1.0.1",
"babel-plugin-eval": "^1.0.1",
"babel-plugin-inline-environment-variables": "^1.0.1",
"babel-plugin-member-expression-literals": "^1.0.1",
"babel-plugin-property-literals": "^1.0.1",
"babel-plugin-proto-to-assign": "^1.0.3",
"babel-plugin-remove-console": "^1.0.1",
"babel-plugin-remove-debugger": "^1.0.1",
"babel-plugin-undefined-to-void": "^1.1.6",
"bluebird": "^2.9.25",
"chalk": "^1.0.0",
"convert-source-map": "^1.1.0",

View File

@ -1,17 +1,17 @@
export default {
//- builtin-prepass
"minification.constantFolding": require("./minification/constant-folding"),
"minification.constantFolding": require("babel-plugin-constant-folding"),
//- builtin-pre
strict: require("./other/strict"),
eval: require("./other/eval"),
eval: require("babel-plugin-eval"),
_explode: require("./internal/explode"),
_validation: require("./internal/validation"),
_hoistDirectives: require("./internal/hoist-directives"),
"minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsole": require("./minification/remove-console"),
"utility.inlineEnvironmentVariables": require("./utility/inline-environment-variables"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
"minification.removeDebugger": require("babel-plugin-remove-debugger"),
"minification.removeConsole": require("babel-plugin-remove-console"),
"utility.inlineEnvironmentVariables": require("babel-plugin-inline-environment-variables"),
"minification.deadCodeElimination": require("babel-plugin-dead-code-elimination"),
_modules: require("./internal/modules"),
"spec.functionName": require("./spec/function-name"),
"es6.spec.templateLiterals": require("./es6/spec.template-literals"),
@ -49,7 +49,7 @@ export default {
"es6.spread": require("./es6/spread"),
"es6.parameters.default": require("./es6/parameters.default"),
"es7.exportExtensions": require("./es7/export-extensions"),
"spec.protoToAssign": require("./spec/proto-to-assign"),
"spec.protoToAssign": require("babel-plugin-proto-to-assign"),
"es7.doExpressions": require("./es7/do-expressions"),
"es6.spec.symbols": require("./es6/spec.symbols"),
"es7.functionBind": require("./es7/function-bind"),
@ -79,8 +79,8 @@ export default {
_shadowFunctions: require("./internal/shadow-functions"),
"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"),
"minification.memberExpressionLiterals": require("babel-plugin-member-expression-literals"),
"minification.propertyLiterals": require("babel-plugin-property-literals"),
_blockHoist: require("./internal/block-hoist"),
jscript: require("./other/jscript"),
flow: require("./other/flow"),

View File

@ -1,73 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-prepass",
experimental: true
};
export var visitor = {
AssignmentExpression() {
var left = this.get("left");
if (!left.isIdentifier()) return;
var binding = this.scope.getBinding(left.node.name);
if (!binding || binding.hasDeoptValue) return;
var evaluated = this.get("right").evaluate();
if (evaluated.confident) {
binding.setValue(evaluated.value);
} else {
binding.deoptValue();
}
},
IfStatement() {
var evaluated = this.get("test").evaluate();
if (!evaluated.confident) {
// todo: deopt binding values for constant violations inside
return this.skip();
}
if (evaluated.value) {
this.skipKey("alternate");
} else {
this.skipKey("consequent");
}
},
Scopable: {
enter() {
var funcScope = this.scope.getFunctionParent();
for (var name in this.scope.bindings) {
var binding = this.scope.bindings[name];
var deopt = false;
for (var path of (binding.constantViolations: Array)) {
var funcViolationScope = path.scope.getFunctionParent();
if (funcViolationScope !== funcScope) {
deopt = true;
break;
}
}
if (deopt) binding.deoptValue();
}
},
exit() {
for (var name in this.scope.bindings) {
var binding = this.scope.bindings[name];
binding.clearValue();
}
}
},
Expression: {
exit() {
var res = this.evaluate();
if (res.confident) return t.valueToNode(res.value);
}
}
};

View File

@ -1,154 +0,0 @@
import * as t from "../../../types";
function toStatements(node) {
if (t.isBlockStatement(node)) {
var hasBlockScoped = false;
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isBlockScoped(bodyNode)) hasBlockScoped = true;
}
if (!hasBlockScoped) {
return node.body;
}
}
return node;
}
export var metadata = {
optional: true,
group: "builtin-pre",
experimental: true
};
export var visitor = {
ReferencedIdentifier(node, parent, scope) {
var binding = scope.getBinding(node.name);
if (!binding || binding.references > 1 || !binding.constant) return;
if (binding.kind === "param" || binding.kind === "module") return;
var replacement = binding.path.node;
if (t.isVariableDeclarator(replacement)) {
replacement = replacement.init;
}
if (!replacement) return;
// ensure it's a "pure" type
if (!scope.isPure(replacement, true)) return;
if (t.isClass(replacement) || t.isFunction(replacement)) {
// don't change this if it's in a different scope, this can be bad
// for performance since it may be inside a loop or deeply nested in
// hot code
if (binding.path.scope.parent !== scope) return;
}
if (this.findParent((path) => path.node === replacement)) {
return;
}
t.toExpression(replacement);
scope.removeBinding(node.name);
binding.path.dangerouslyRemove();
return replacement;
},
"ClassDeclaration|FunctionDeclaration"(node, parent, scope) {
var binding = scope.getBinding(node.id.name);
if (binding && !binding.referenced) {
this.dangerouslyRemove();
}
},
VariableDeclarator(node, parent, scope) {
if (!t.isIdentifier(node.id) || !scope.isPure(node.init, true)) return;
visitor["ClassDeclaration|FunctionDeclaration"].apply(this, arguments);
},
ConditionalExpression(node) {
var evaluateTest = this.get("test").evaluateTruthy();
if (evaluateTest === true) {
return node.consequent;
} else if (evaluateTest === false) {
return node.alternate;
}
},
BlockStatement() {
var paths = this.get("body");
var purge = false;
for (var i = 0; i < paths.length; i++) {
let path = paths[i];
if (!purge && path.isCompletionStatement()) {
purge = true;
continue;
}
if (purge && !path.isFunctionDeclaration()) {
path.dangerouslyRemove();
}
}
},
IfStatement: {
exit(node) {
var consequent = node.consequent;
var alternate = node.alternate;
var test = node.test;
var evaluateTest = this.get("test").evaluateTruthy();
// we can check if a test will be truthy 100% and if so then we can inline
// the consequent and completely ignore the alternate
//
// if (true) { foo; } -> { foo; }
// if ("foo") { foo; } -> { foo; }
//
if (evaluateTest === true) {
return toStatements(consequent);
}
// we can check if a test will be falsy 100% and if so we can inline the
// alternate if there is one and completely remove the consequent
//
// if ("") { bar; } else { foo; } -> { foo; }
// if ("") { bar; } ->
//
if (evaluateTest === false) {
if (alternate) {
return toStatements(alternate);
} else {
return this.dangerouslyRemove();
}
}
// remove alternate blocks that are empty
//
// if (foo) { foo; } else {} -> if (foo) { foo; }
//
if (t.isBlockStatement(alternate) && !alternate.body.length) {
alternate = node.alternate = null;
}
// if the consequent block is empty turn alternate blocks into a consequent
// and flip the test
//
// if (foo) {} else { bar; } -> if (!foo) { bar; }
//
if (t.isBlockStatement(consequent) && !consequent.body.length && t.isBlockStatement(alternate) && alternate.body.length) {
node.consequent = node.alternate;
node.alternate = null;
node.test = t.unaryExpression("!", test, true);
}
}
}
};

View File

@ -1,19 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-trailing"
};
export var visitor = {
MemberExpression: {
exit(node) {
var prop = node.property;
if (node.computed && t.isLiteral(prop) && t.isValidIdentifier(prop.value)) {
// foo["bar"] => foo.bar
node.property = t.identifier(prop.value);
node.computed = false;
}
}
}
};

View File

@ -1,19 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-trailing"
};
export var visitor = {
Property: {
exit(node) {
var key = node.key;
if (t.isLiteral(key) && t.isValidIdentifier(key.value)) {
// "foo": "bar" -> foo: "bar"
node.key = t.identifier(key.value);
node.computed = false;
}
}
}
};

View File

@ -1,12 +0,0 @@
export var metadata = {
optional: true,
group: "builtin-pre"
};
export var visitor = {
CallExpression() {
if (this.get("callee").matchesPattern("console", true)) {
this.dangerouslyRemove();
}
}
};

View File

@ -1,10 +0,0 @@
export var metadata = {
optional: true,
group: "builtin-pre"
};
export var visitor = {
DebuggerStatement() {
this.dangerouslyRemove();
}
};

View File

@ -1,23 +0,0 @@
import traverse from "../../../traversal";
import parse from "../../../helpers/parse";
export var metadata = {
group: "builtin-pre",
optional: true
};
export var visitor = {
CallExpression(node) {
if (this.get("callee").isIdentifier({ name: "eval" }) && node.arguments.length === 1) {
var evaluate = this.get("arguments")[0].evaluate();
if (!evaluate.confident) return;
var code = evaluate.value;
if (typeof code !== "string") return;
var ast = parse(code);
traverse.removeProperties(ast);
return ast.program;
}
}
};

View File

@ -1,64 +0,0 @@
import * as t from "../../../types";
import pull from "lodash/array/pull";
function isProtoKey(node) {
return t.isLiteral(t.toComputedKey(node, node.key), { value: "__proto__" });
}
function isProtoAssignmentExpression(node) {
var left = node.left;
return t.isMemberExpression(left) && t.isLiteral(t.toComputedKey(left, left.property), { value: "__proto__" });
}
function buildDefaultsCallExpression(expr, ref, file) {
return t.expressionStatement(t.callExpression(file.addHelper("defaults"), [ref, expr.right]));
}
export var metadata = {
secondPass: true,
optional: true
};
export var visitor = {
AssignmentExpression(node, parent, scope, file) {
if (!isProtoAssignmentExpression(node)) return;
var nodes = [];
var left = node.left.object;
var temp = scope.maybeGenerateMemoised(left);
nodes.push(t.expressionStatement(t.assignmentExpression("=", temp, left)));
nodes.push(buildDefaultsCallExpression(node, temp, file));
if (temp) nodes.push(temp);
return nodes;
},
ExpressionStatement(node, parent, scope, file) {
var expr = node.expression;
if (!t.isAssignmentExpression(expr, { operator: "=" })) return;
if (isProtoAssignmentExpression(expr)) {
return buildDefaultsCallExpression(expr, expr.left.object, file);
}
},
ObjectExpression(node, parent, scope, file) {
var proto;
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
if (isProtoKey(prop)) {
proto = prop.value;
pull(node.properties, prop);
}
}
if (proto) {
var args = [t.objectExpression([]), proto];
if (node.properties.length) args.push(node);
return t.callExpression(file.addHelper("extends"), args);
}
}
};

View File

@ -1,19 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-pre"
};
var match = t.buildMatchMemberExpression("process.env");
export var visitor = {
MemberExpression(node) {
if (match(node.object)) {
var key = this.toComputedKey();
if (t.isLiteral(key)) {
return t.valueToNode(process.env[key.value]);
}
}
}
};