consolidate transformer metadata, remove abstract references, make react transformer optional

This commit is contained in:
Sebastian McKenzie 2015-03-16 19:26:50 +11:00
parent b495370740
commit 4d965b0f46
48 changed files with 117 additions and 255 deletions

View File

@ -9,10 +9,10 @@ export default function (opts, code, callback) {
var tokens = [];
var ast = acorn.parse(code, {
allowImportExportEverywhere: opts.allowImportExportEverywhere,
allowReturnOutsideFunction: !opts._anal,
ecmaVersion: opts.experimental ? 7 : 6,
playground: opts.playground,
allowImportExportEverywhere: opts.looseModules,
allowReturnOutsideFunction: opts.looseModules,
transformers: opts.transformers,
ecmaVersion: 6,
strictMode: opts.strictMode,
onComment: comments,
locations: true,

View File

@ -181,10 +181,10 @@ export default class File {
each(transform.transformers, function (transformer, key) {
var pass = transformers[key] = transformer.buildPass(file);
if (pass.canRun(file)) {
if (pass.canRun) {
stack.push(pass);
if (transformer.secondPass) {
if (transformer.metadata.secondPass) {
secondaryStack.push(pass);
}
@ -274,7 +274,7 @@ export default class File {
this.dynamicImported.push(declar);
if (noDefault) this.dynamicImportedNoDefault.push(declar);
if (this.transformers["es6.modules"].canRun()) {
if (this.transformers["es6.modules"].canRun) {
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);
} else {
this.dynamicImports.push(declar);
@ -380,8 +380,19 @@ export default class File {
var opts = this.opts;
opts.allowImportExportEverywhere = this.isLoose("es6.modules");
opts.strictMode = this.transformers.strict.canRun();
//
var parseOpts = {};
var transformers = parseOpts.transformers = {};
for (var key in this.transformers) {
transformers[key] = this.transformers[key].canRun;
}
parseOpts.looseModules = this.isLoose("es6.modules");
parseOpts.strictMode = this.transformers.strict.canRun;
//
return parse(opts, code, (tree) => {
this.transform(tree);
@ -413,7 +424,7 @@ export default class File {
this.lastStatements = t.getLastStatements(ast.program);
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
if (modFormatter.init && this.transformers["es6.modules"].canRun()) {
if (modFormatter.init && this.transformers["es6.modules"].canRun) {
modFormatter.init();
}

View File

@ -19,6 +19,12 @@
},
"react": {
"description": "",
"type": "boolean",
"default": false
},
"highlightErrors": {
"description": "ANSI syntax highlight error messages",
"type": "boolean",
@ -42,13 +48,6 @@
"default": false
},
"playground": {
"description": "Enable all playground transformers",
"shorthand": "p",
"type": "boolean",
"default": false
},
"blacklist": {
"type": "transformerList",
"description": "Blacklist of transformers to NOT use",

View File

@ -1,3 +1,4 @@
{
"blacklist": ["useStrict", "es6.blockScoping", "regenerator"]
"blacklist": ["useStrict", "es6.blockScoping", "regenerator"],
"loose": ["es6.modules"]
}

View File

@ -12,10 +12,12 @@ export default class TransformerPass {
this.shouldRun = !transformer.check;
this.handlers = transformer.handlers;
this.file = file;
this.ran = false;
this.canRun = this._canRun();
this.ran = false;
}
canRun(): boolean {
_canRun(): boolean {
var transformer = this.transformer;
var opts = this.file.opts;
@ -32,14 +34,14 @@ export default class TransformerPass {
var whitelist = opts.whitelist;
if (whitelist.length) return includes(whitelist, key);
// experimental
if (transformer.experimental && opts.experimental) return true;
// react
if (transformer.metadata.react && opts.react) return true;
// playground
if (transformer.playground && opts.playground) return true;
// experimental
if (transformer.metadata.experimental && opts.experimental) return true;
// optional
if (transformer.optional && !includes(opts.optional, key)) return false;
if (transformer.metadata.optional && !includes(opts.optional, key)) return false;
return true;
}

View File

@ -23,15 +23,11 @@ export default class Transformer {
};
this.manipulateOptions = take("manipulateOptions");
this.metadata = take("metadata") || {};
this.check = take("check");
this.post = take("post");
this.pre = take("pre");
this.experimental = !!take("experimental");
this.playground = !!take("playground");
this.secondPass = !!take("secondPass");
this.optional = !!take("optional");
this.handlers = this.normalize(transformer);
this.opts ||= {};
this.key = transformerKey;

View File

@ -26,7 +26,9 @@ var visitor = {
}
};
export var optional = true;
export var metadata = {
optional: true
};
export function BlockStatement(node, parent, scope, file) {
var letRefs = node._letReferences;

View File

@ -44,7 +44,7 @@ export function check(node) {
export function VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent)) return;
if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun()) {
if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun) {
var nodes = [node];
for (var i = 0; i < node.declarations.length; i++) {

View File

@ -62,7 +62,7 @@ exports.Function = function (node, parent, scope, file) {
param.traverse(iifeVisitor, state);
}
if (file.transformers["es6.blockScopingTDZ"].canRun() && param.isIdentifier()) {
if (file.transformers["es6.blockScopingTDZ"].canRun && param.isIdentifier()) {
pushDefNode(param.node, t.identifier("undefined"), i);
}

View File

@ -1,6 +1,8 @@
import * as t from "../../../types";
export var optional = true;
export var metadata = {
optional: true
};
export function UnaryExpression(node, parent, scope, file) {
this.skip();

View File

@ -1,112 +0,0 @@
// https://github.com/zenparsing/es-abstract-refs
import * as util from "../../../util";
import * as t from "../../../types";
export var experimental = true;
export var optional = true;
var container = function (parent, call, ret, file) {
if (t.isExpressionStatement(parent) && !file.isConsequenceExpressionStatement(parent)) {
// we don't need to worry about return values
return call;
} else {
var exprs = [];
if (t.isSequenceExpression(call)) {
exprs = call.expressions;
} else {
exprs.push(call);
}
exprs.push(ret);
return t.sequenceExpression(exprs);
}
};
export function AssignmentExpression(node, parent, scope, file) {
var left = node.left;
if (!t.isVirtualPropertyExpression(left)) return;
var value = node.right;
var temp;
// we need to return `node.right`
if (!t.isExpressionStatement(parent)) {
temp = scope.generateTempBasedOnNode(node.right);
if (temp) value = temp;
}
if (node.operator !== "=") {
value = t.binaryExpression(
node.operator[0],
util.template("abstract-expression-get", {
PROPERTY: node.property,
OBJECT: node.object
}),
value
);
}
var call = util.template("abstract-expression-set", {
PROPERTY: left.property,
OBJECT: left.object,
VALUE: value
});
if (temp) {
call = t.sequenceExpression([
t.assignmentExpression("=", temp, node.right),
call
]);
}
return container(parent, call, value, file);
}
export function UnaryExpression(node, parent, scope, file) {
var arg = node.argument;
if (!t.isVirtualPropertyExpression(arg)) return;
if (node.operator !== "delete") return;
var call = util.template("abstract-expression-delete", {
PROPERTY: arg.property,
OBJECT: arg.object
});
return container(parent, call, t.literal(true), file);
}
export function CallExpression(node, parent, scope) {
var callee = node.callee;
if (!t.isVirtualPropertyExpression(callee)) return;
var temp = scope.generateTempBasedOnNode(callee.object);
var call = util.template("abstract-expression-call", {
PROPERTY: callee.property,
OBJECT: temp || callee.object
});
call.arguments = call.arguments.concat(node.arguments);
if (temp) {
return t.sequenceExpression([
t.assignmentExpression("=", temp, callee.object),
call
]);
} else {
return call;
}
}
export function VirtualPropertyExpression(node) {
return util.template("abstract-expression-get", {
PROPERTY: node.property,
OBJECT: node.object
});
}
export function PrivateDeclaration(node) {
return t.variableDeclaration("const", node.declarations.map(function (id) {
return t.variableDeclarator(id, t.newExpression(t.identifier("WeakMap"), []));
}));
}

View File

@ -3,8 +3,10 @@ import traverse from "../../../traversal";
import * as util from "../../../util";
import * as t from "../../../types";
export var experimental = true;
export var optional = true;
export var metadata = {
experimental: true,
optional: true
};
export function ComprehensionExpression(node, parent, scope, file) {
var callback = array;

View File

@ -3,8 +3,9 @@
import build from "../../helpers/build-binary-assignment-operator-transformer";
import * as t from "../../../types";
export var experimental = true;
export var optional = true;
export var metadata = {
optional: true
};
var MATH_POW = t.memberExpression(t.identifier("Math"), t.identifier("pow"));

View File

@ -2,8 +2,11 @@
import * as t from "../../../types";
export var experimental = true;
export var optional = true;
export var metadata = {
experimental: true,
optional: true,
react: true
};
export function manipulateOptions(opts) {
if (opts.whitelist.length) opts.whitelist.push("es6.destructuring");

View File

@ -44,7 +44,6 @@ export default {
"es6.regex.sticky": require("./es6/regex.sticky"),
"es6.regex.unicode": require("./es6/regex.unicode"),
"es7.abstractReferences": require("./es7/abstract-references"),
"es6.constants": require("./es6/constants"),

View File

@ -1,7 +1,9 @@
import * as strict from "../../helpers/strict";
import * as t from "../../../types";
export var secondPass = true;
export var metadata = {
secondPass: true
};
export function BlockStatement(node, parent, scope, file) {
if (!node._declarations) return;

View File

@ -5,7 +5,7 @@ export function Program(program, parent, scope, file) {
program.body = file.dynamicImports.concat(program.body);
});
if (!file.transformers["es6.modules"].canRun()) return;
if (!file.transformers["es6.modules"].canRun) return;
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program);

View File

@ -1,7 +1,7 @@
import * as t from "../../../types";
export function Program(program, parent, scope, file) {
if (file.transformers.strict.canRun()) {
if (file.transformers.strict.canRun) {
var directive = file.get("existingStrictDirective");
if (!directive) {

View File

@ -2,7 +2,9 @@ import remapAsyncToGenerator from "../../helpers/remap-async-to-generator";
export { manipulateOptions } from "./bluebird-coroutines";
export var optional = true;
export var metadata = {
optional: true
};
exports.Function = function (node, parent, scope, file) {
if (!node.async || node.generator) return;

View File

@ -6,7 +6,9 @@ export function manipulateOptions(opts) {
opts.blacklist.push("regenerator");
}
export var optional = true;
export var metadata = {
optional: true
};
exports.Function = function (node, parent, scope, file) {
if (!node.async || node.generator) return;

View File

@ -1,5 +1,9 @@
import * as t from "../../../types";
export var metadata = {
react: true
};
export function Flow(node) {
this.remove();
}

View File

@ -5,7 +5,10 @@ export function manipulateOptions(opts) {
opts.blacklist.push("react");
}
export var optional = true;
export var metadata = {
optional: true,
react: true
};
require("../../helpers/build-react-transformer")(exports, {
pre(state) {

View File

@ -3,6 +3,10 @@ import * as t from "../../../types";
var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/;
export var metadata = {
react: true
};
export function Program(node, parent, scope, file) {
var id = "React.createElement";

View File

@ -69,7 +69,10 @@ var astVisitor = {
}
};
export var optional = true;
export var metadata = {
optional: true,
react: true
};
export function manipulateOptions(opts) {
if (opts.whitelist.length) opts.whitelist.push("es6.modules");

View File

@ -14,8 +14,10 @@ function buildDefaultsCallExpression(expr, ref, file) {
return t.expressionStatement(t.callExpression(file.addHelper("defaults"), [ref, expr.right]));
}
export var secondPass = true;
export var optional = true;
export var metadata = {
secondPass: true,
optional: true
};
export function AssignmentExpression(node, parent, scope, file) {
if (!isProtoAssignmentExpression(node)) return;

View File

@ -1,6 +1,9 @@
import * as t from "../../../types";
export var optional = true;
export var metadata = {
optional: true,
react: true
};
export function Identifier(node, parent) {
if (node.name === "undefined" && this.isReferenced()) {

View File

@ -17,7 +17,9 @@ function toStatements(node) {
return node;
}
export var optional = true;
export var metadata = {
optional: true
};
export function ConditionalExpression(node, parent, scope) {
var evaluateTest = this.get("test").evaluateTruthy();

View File

@ -1,6 +1,8 @@
import * as t from "../../../types";
export var optional = true;
export var metadata = {
optional: true
};
var match = t.buildMatchMemberExpression("process.env");

View File

@ -1,6 +1,8 @@
import * as t from "../../../types";
export var optional = true;
export var metadata = {
optional: true
};
export function Expression(node, parent, scope) {
var res = this.evaluate();

View File

@ -1,6 +1,8 @@
import * as t from "../../../types";
export var optional = true;
export var metadata = {
optional: true
};
export function CallExpression(node, parent) {
if (this.get("callee").matchesPattern("console", true)) {

View File

@ -1,6 +1,8 @@
import * as t from "../../../types";
export var optional = true;
export var metadata = {
optional: true
};
export function ExpressionStatement(node) {
if (this.get("expression").isIdentifier({ name: "debugger" })) {

View File

@ -1,7 +1,9 @@
import levenshtein from "leven";
import * as messages from "../../../messages";
export var optional = true;
export var metadata = {
optional: true
};
export function Identifier(node, parent, scope, file) {
if (!this.isReferenced()) return;

View File

@ -78,7 +78,7 @@ var templateVisitor = {
return nodes[node.name];
}
}
}
};
//
@ -109,7 +109,7 @@ export function template(name: string, nodes?: Array<Object>, keepExpression?: b
}
export function parseTemplate(loc: string, code: string): Object {
var ast = parse({ filename: loc }, code).program;
var ast = parse({ filename: loc, looseModules: true }, code).program;
ast = traverse.removeProperties(ast);
return ast;
}

View File

@ -1,6 +0,0 @@
foo::bar();
foo::bar("arg");
var test = "test";
test::bar();
test::bar("arg");

View File

@ -1,10 +0,0 @@
"use strict";
var _foo, _foo2;
_foo = foo, bar[Symbol.referenceGet](_foo).call(_foo);
_foo2 = foo, bar[Symbol.referenceGet](_foo2).call(_foo2, "arg");
var test = "test";
bar[Symbol.referenceGet](test).call(test);
bar[Symbol.referenceGet](test).call(test, "arg");

View File

@ -1,3 +0,0 @@
delete foo::bar;
if (delete foo::bar) {}

View File

@ -1,5 +0,0 @@
"use strict";
bar[Symbol.referenceDelete](foo);
if ((bar[Symbol.referenceDelete](foo), true)) {}

View File

@ -1 +0,0 @@
foo::bar;

View File

@ -1,3 +0,0 @@
"use strict";
bar[Symbol.referenceGet](foo);

View File

@ -1,3 +0,0 @@
{
"experimental": true
}

View File

@ -1,12 +0,0 @@
private A;
private B, C;
class D {
private E;
private F, G;
}
var H = class {
private I;
private J, K;
};

View File

@ -1,30 +0,0 @@
"use strict";
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
var A = new WeakMap();
var B = new WeakMap(),
C = new WeakMap();
var D = (function () {
var F = new WeakMap(),
G = new WeakMap();
var E = new WeakMap();
function D() {
_classCallCheck(this, D);
}
return D;
})();
var H = (function () {
var _class = function H() {
_classCallCheck(this, _class);
};
var J = new WeakMap(),
K = new WeakMap();
var I = new WeakMap();
return _class;
})();

View File

@ -1,3 +0,0 @@
var baz = "foo";
foo::bar = baz;
if (foo::bar = baz) {}

View File

@ -1,5 +0,0 @@
"use strict";
var baz = "foo";
bar[Symbol.referenceSet](foo, baz);
if ((bar[Symbol.referenceSet](foo, baz), baz)) {}

View File

@ -1,3 +0,0 @@
{
"experimental": true
}

View File

@ -1,4 +1,5 @@
{
"react": true,
"experimental": true,
"whitelist": ["flow"],
"noCheckAst": true

View File

@ -1,4 +1,5 @@
{
"react": true,
"blacklist": "strict",
"optional": "reactCompat"
}

View File

@ -1,3 +1,4 @@
{
"react": true,
"blacklist": ["strict"]
}