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 tokens = [];
var ast = acorn.parse(code, { var ast = acorn.parse(code, {
allowImportExportEverywhere: opts.allowImportExportEverywhere, allowImportExportEverywhere: opts.looseModules,
allowReturnOutsideFunction: !opts._anal, allowReturnOutsideFunction: opts.looseModules,
ecmaVersion: opts.experimental ? 7 : 6, transformers: opts.transformers,
playground: opts.playground, ecmaVersion: 6,
strictMode: opts.strictMode, strictMode: opts.strictMode,
onComment: comments, onComment: comments,
locations: true, locations: true,

View File

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

View File

@ -19,6 +19,12 @@
}, },
"react": {
"description": "",
"type": "boolean",
"default": false
},
"highlightErrors": { "highlightErrors": {
"description": "ANSI syntax highlight error messages", "description": "ANSI syntax highlight error messages",
"type": "boolean", "type": "boolean",
@ -42,13 +48,6 @@
"default": false "default": false
}, },
"playground": {
"description": "Enable all playground transformers",
"shorthand": "p",
"type": "boolean",
"default": false
},
"blacklist": { "blacklist": {
"type": "transformerList", "type": "transformerList",
"description": "Blacklist of transformers to NOT use", "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.shouldRun = !transformer.check;
this.handlers = transformer.handlers; this.handlers = transformer.handlers;
this.file = file; this.file = file;
this.ran = false;
this.canRun = this._canRun();
this.ran = false;
} }
canRun(): boolean { _canRun(): boolean {
var transformer = this.transformer; var transformer = this.transformer;
var opts = this.file.opts; var opts = this.file.opts;
@ -32,14 +34,14 @@ export default class TransformerPass {
var whitelist = opts.whitelist; var whitelist = opts.whitelist;
if (whitelist.length) return includes(whitelist, key); if (whitelist.length) return includes(whitelist, key);
// experimental // react
if (transformer.experimental && opts.experimental) return true; if (transformer.metadata.react && opts.react) return true;
// playground // experimental
if (transformer.playground && opts.playground) return true; if (transformer.metadata.experimental && opts.experimental) return true;
// optional // optional
if (transformer.optional && !includes(opts.optional, key)) return false; if (transformer.metadata.optional && !includes(opts.optional, key)) return false;
return true; return true;
} }

View File

@ -23,15 +23,11 @@ export default class Transformer {
}; };
this.manipulateOptions = take("manipulateOptions"); this.manipulateOptions = take("manipulateOptions");
this.metadata = take("metadata") || {};
this.check = take("check"); this.check = take("check");
this.post = take("post"); this.post = take("post");
this.pre = take("pre"); 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.handlers = this.normalize(transformer);
this.opts ||= {}; this.opts ||= {};
this.key = transformerKey; 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) { export function BlockStatement(node, parent, scope, file) {
var letRefs = node._letReferences; var letRefs = node._letReferences;

View File

@ -44,7 +44,7 @@ export function check(node) {
export function VariableDeclaration(node, parent, scope, file) { export function VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent)) return; if (!isLet(node, parent)) return;
if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun()) { if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun) {
var nodes = [node]; var nodes = [node];
for (var i = 0; i < node.declarations.length; i++) { 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); 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); pushDefNode(param.node, t.identifier("undefined"), i);
} }

View File

@ -1,6 +1,8 @@
import * as t from "../../../types"; import * as t from "../../../types";
export var optional = true; export var metadata = {
optional: true
};
export function UnaryExpression(node, parent, scope, file) { export function UnaryExpression(node, parent, scope, file) {
this.skip(); 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 util from "../../../util";
import * as t from "../../../types"; import * as t from "../../../types";
export var experimental = true; export var metadata = {
export var optional = true; experimental: true,
optional: true
};
export function ComprehensionExpression(node, parent, scope, file) { export function ComprehensionExpression(node, parent, scope, file) {
var callback = array; var callback = array;

View File

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

View File

@ -2,8 +2,11 @@
import * as t from "../../../types"; import * as t from "../../../types";
export var experimental = true; export var metadata = {
export var optional = true; experimental: true,
optional: true,
react: true
};
export function manipulateOptions(opts) { export function manipulateOptions(opts) {
if (opts.whitelist.length) opts.whitelist.push("es6.destructuring"); 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.sticky": require("./es6/regex.sticky"),
"es6.regex.unicode": require("./es6/regex.unicode"), "es6.regex.unicode": require("./es6/regex.unicode"),
"es7.abstractReferences": require("./es7/abstract-references"),
"es6.constants": require("./es6/constants"), "es6.constants": require("./es6/constants"),

View File

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

View File

@ -5,7 +5,7 @@ export function Program(program, parent, scope, file) {
program.body = file.dynamicImports.concat(program.body); 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) { if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program); file.moduleFormatter.transform(program);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,6 +3,10 @@ import * as t from "../../../types";
var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/; var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/;
export var metadata = {
react: true
};
export function Program(node, parent, scope, file) { export function Program(node, parent, scope, file) {
var id = "React.createElement"; 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) { export function manipulateOptions(opts) {
if (opts.whitelist.length) opts.whitelist.push("es6.modules"); 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])); return t.expressionStatement(t.callExpression(file.addHelper("defaults"), [ref, expr.right]));
} }
export var secondPass = true; export var metadata = {
export var optional = true; secondPass: true,
optional: true
};
export function AssignmentExpression(node, parent, scope, file) { export function AssignmentExpression(node, parent, scope, file) {
if (!isProtoAssignmentExpression(node)) return; if (!isProtoAssignmentExpression(node)) return;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -78,7 +78,7 @@ var templateVisitor = {
return nodes[node.name]; 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 { 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); ast = traverse.removeProperties(ast);
return 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, "experimental": true,
"whitelist": ["flow"], "whitelist": ["flow"],
"noCheckAst": true "noCheckAst": true

View File

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

View File

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