first commit
This commit is contained in:
19
lib/6to5/browserify.js
Normal file
19
lib/6to5/browserify.js
Normal file
@@ -0,0 +1,19 @@
|
||||
var transform = require("./transform");
|
||||
var through = require("through");
|
||||
|
||||
module.exports = function (filename) {
|
||||
var data = "";
|
||||
|
||||
var write = function (buf) {
|
||||
data += buf;
|
||||
};
|
||||
|
||||
var end = function () {
|
||||
var out = transform(data, { filename: filename });
|
||||
stream.queue(out);
|
||||
stream.queue(null);
|
||||
};
|
||||
|
||||
var stream = through(write, end);
|
||||
return stream;
|
||||
};
|
||||
66
lib/6to5/middleware.js
Normal file
66
lib/6to5/middleware.js
Normal file
@@ -0,0 +1,66 @@
|
||||
var util = require("./util");
|
||||
var path = require("path");
|
||||
var api = require("./node");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
|
||||
module.exports = function (opts) {
|
||||
opts = _.defaults(opts || {}, {
|
||||
src: "assets",
|
||||
dest: "cache"
|
||||
});
|
||||
|
||||
var cache = {};
|
||||
|
||||
return function (req, res, next) {
|
||||
var url = req.url;
|
||||
if (!util.canCompile(url)) return next();
|
||||
|
||||
var dest = path.join(opts.dest, url);
|
||||
var src = path.join(opts.src, url);
|
||||
|
||||
var write = function (transformed) {
|
||||
fs.writeFile(dest, transformed, function (err) {
|
||||
if (err) {
|
||||
next(err);
|
||||
} else {
|
||||
cache[url] = Date.now();
|
||||
next();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var compile = function () {
|
||||
var transformOpts = _.clone(opts.transform || {});
|
||||
|
||||
api.transformFile(opts.dest, transformOpts, function (err, transformed) {
|
||||
if (err) return next(err);
|
||||
write(transformed);
|
||||
});
|
||||
};
|
||||
|
||||
var destExists = function () {
|
||||
fs.stat(dest, function (err, stat) {
|
||||
if (err) return next(err);
|
||||
|
||||
if (cache[url] < +stat.mtime) {
|
||||
compile();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
fs.exists(src, function (exists) {
|
||||
if (!exists) return next();
|
||||
|
||||
fs.exists(dest, function (exists) {
|
||||
if (exists && cache[dest]) {
|
||||
destExists();
|
||||
} else {
|
||||
compile();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
45
lib/6to5/node.js
Normal file
45
lib/6to5/node.js
Normal file
@@ -0,0 +1,45 @@
|
||||
var transform = require("./transform");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.browserify = require("./browserify");
|
||||
exports.middleware = require("./middleware");
|
||||
|
||||
exports.register = function () {
|
||||
require.extensions[".js"] = function (m, filename) {
|
||||
m._compile(exports.transformFileSync(filename, {
|
||||
sourceMap: true
|
||||
}), filename);
|
||||
};
|
||||
};
|
||||
|
||||
exports.transform = transform;
|
||||
|
||||
exports.transformFile = function (filename, opts, callback) {
|
||||
if (_.isFunction(opts)) {
|
||||
callback = opts;
|
||||
opts = {};
|
||||
}
|
||||
|
||||
opts.filename = filename;
|
||||
|
||||
fs.readFile(filename, function (err, raw) {
|
||||
if (err) return callback(err);
|
||||
|
||||
var code;
|
||||
|
||||
try {
|
||||
code = transform(raw, opts);
|
||||
} catch (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
callback(null, code);
|
||||
});
|
||||
};
|
||||
|
||||
exports.transformFileSync = function (filename, opts) {
|
||||
opts = opts || {};
|
||||
opts.filename = filename;
|
||||
return transform(fs.readFileSync(filename), opts);
|
||||
};
|
||||
1
lib/6to5/templates/arguments-slice-assign-arg.js
Normal file
1
lib/6to5/templates/arguments-slice-assign-arg.js
Normal file
@@ -0,0 +1 @@
|
||||
var VARIABLE_NAME = Array.prototype.slice.call(arguments, SLICE_ARG);
|
||||
1
lib/6to5/templates/arguments-slice-assign.js
Normal file
1
lib/6to5/templates/arguments-slice-assign.js
Normal file
@@ -0,0 +1 @@
|
||||
var VARIABLE_NAME = Array.prototype.slice.call(arguments);
|
||||
1
lib/6to5/templates/arguments-slice.js
Normal file
1
lib/6to5/templates/arguments-slice.js
Normal file
@@ -0,0 +1 @@
|
||||
Array.prototype.slice.call(arguments);
|
||||
1
lib/6to5/templates/array-concat.js
Normal file
1
lib/6to5/templates/array-concat.js
Normal file
@@ -0,0 +1 @@
|
||||
[].concat(ARGUMENT);
|
||||
1
lib/6to5/templates/class-method.js
Normal file
1
lib/6to5/templates/class-method.js
Normal file
@@ -0,0 +1 @@
|
||||
CLASS_NAME.prototype.METHOD_NAME = FUNCTION;
|
||||
7
lib/6to5/templates/class.js
Normal file
7
lib/6to5/templates/class.js
Normal file
@@ -0,0 +1,7 @@
|
||||
var CLASS_NAME = (function () {
|
||||
function CLASS_NAME() {
|
||||
|
||||
}
|
||||
|
||||
return CLASS_NAME;
|
||||
})();
|
||||
5
lib/6to5/templates/exports-alias-var.js
Normal file
5
lib/6to5/templates/exports-alias-var.js
Normal file
@@ -0,0 +1,5 @@
|
||||
Object.defineProperty(exports, STRING_KEY, {
|
||||
get: function () {
|
||||
return KEY;
|
||||
}
|
||||
});
|
||||
1
lib/6to5/templates/exports-assign.js
Normal file
1
lib/6to5/templates/exports-assign.js
Normal file
@@ -0,0 +1 @@
|
||||
exports.KEY = VALUE;
|
||||
1
lib/6to5/templates/exports-default.js
Normal file
1
lib/6to5/templates/exports-default.js
Normal file
@@ -0,0 +1 @@
|
||||
exports = module.exports = VALUE;
|
||||
1
lib/6to5/templates/exports-require-assign-key.js
Normal file
1
lib/6to5/templates/exports-require-assign-key.js
Normal file
@@ -0,0 +1 @@
|
||||
exports.VARIABLE_NAME = require(MODULE_NAME).KEY;
|
||||
5
lib/6to5/templates/exports-wildcard.js
Normal file
5
lib/6to5/templates/exports-wildcard.js
Normal file
@@ -0,0 +1,5 @@
|
||||
(function (obj) {
|
||||
for (var i in obj) {
|
||||
exports[i] = obj[i];
|
||||
}
|
||||
}(require(MODULE_NAME)));
|
||||
1
lib/6to5/templates/function-bind-this.js
Normal file
1
lib/6to5/templates/function-bind-this.js
Normal file
@@ -0,0 +1 @@
|
||||
FUNCTION.bind(this);
|
||||
1
lib/6to5/templates/function-call-this.js
Normal file
1
lib/6to5/templates/function-call-this.js
Normal file
@@ -0,0 +1 @@
|
||||
FUNCTION.call(this);
|
||||
1
lib/6to5/templates/function-call.js
Normal file
1
lib/6to5/templates/function-call.js
Normal file
@@ -0,0 +1 @@
|
||||
FUNCTION();
|
||||
1
lib/6to5/templates/if-undefined-set-to.js
Normal file
1
lib/6to5/templates/if-undefined-set-to.js
Normal file
@@ -0,0 +1 @@
|
||||
if (VARIABLE === undefined) VARIABLE = DEFAULT;
|
||||
8
lib/6to5/templates/inherits.js
Normal file
8
lib/6to5/templates/inherits.js
Normal file
@@ -0,0 +1,8 @@
|
||||
CLASS_NAME.prototype = Object.create(SUPER_NAME.prototype, {
|
||||
constructor: {
|
||||
value: CLASS_NAME,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
4
lib/6to5/templates/object-define-properties-closure.js
Normal file
4
lib/6to5/templates/object-define-properties-closure.js
Normal file
@@ -0,0 +1,4 @@
|
||||
(function (obj) {
|
||||
CONTENT;
|
||||
return obj;
|
||||
})(OBJECT);
|
||||
1
lib/6to5/templates/object-define-properties.js
Normal file
1
lib/6to5/templates/object-define-properties.js
Normal file
@@ -0,0 +1 @@
|
||||
Object.defineProperties(OBJECT, PROPS);
|
||||
1
lib/6to5/templates/prototype-identifier.js
vendored
Normal file
1
lib/6to5/templates/prototype-identifier.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
CLASS_NAME.prototype
|
||||
1
lib/6to5/templates/require-assign-key.js
Normal file
1
lib/6to5/templates/require-assign-key.js
Normal file
@@ -0,0 +1 @@
|
||||
var VARIABLE_NAME = require(MODULE_NAME).KEY;
|
||||
1
lib/6to5/templates/require-assign.js
Normal file
1
lib/6to5/templates/require-assign.js
Normal file
@@ -0,0 +1 @@
|
||||
var VARIABLE_NAME = require(MODULE_NAME);
|
||||
107
lib/6to5/transform.js
Normal file
107
lib/6to5/transform.js
Normal file
@@ -0,0 +1,107 @@
|
||||
var escodegen = require("escodegen");
|
||||
var traverse = require("./traverse");
|
||||
var assert = require("assert");
|
||||
var util = require("./util");
|
||||
var _ = require("lodash");
|
||||
|
||||
var transform = module.exports = function (code, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
_.defaults(opts, {
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
filename: "unknown",
|
||||
format: {}
|
||||
});
|
||||
|
||||
try {
|
||||
var tree = util.parse(code);
|
||||
} catch (err) {
|
||||
err.message = opts.filename + ": " + err.message;
|
||||
throw err;
|
||||
}
|
||||
|
||||
traverse.replace(tree, function (node) {
|
||||
if (node.type === "EmptyStatement") {
|
||||
return traverse.Delete;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(transform.transformers, function (transformer, name) {
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && _.contains(blacklist, name)) return;
|
||||
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist.length && !_.contains(whitelist, name)) return;
|
||||
|
||||
transform._runTransformer(transformer, tree, opts);
|
||||
});
|
||||
|
||||
var genOpts = {
|
||||
comment: true,
|
||||
format: _.merge(opts.format, {
|
||||
indent: {
|
||||
style: " "
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
if (opts.sourceMap) {
|
||||
genOpts.sourceMap = true;
|
||||
genOpts.sourceContent = code;
|
||||
genOpts.sourceMapWithCode = true;
|
||||
}
|
||||
|
||||
var result = escodegen.generate(tree, genOpts);
|
||||
|
||||
if (genOpts.sourceMapWithCode) {
|
||||
return result.code + "\n" + util.sourceMapToComment(result.map) + "\n";
|
||||
} else {
|
||||
return result + "\n";
|
||||
}
|
||||
};
|
||||
|
||||
transform._runTransformer = function (transformer, tree, opts) {
|
||||
if (transformer.Program) transformer.Program(tree, opts);
|
||||
|
||||
traverse.replace(tree, function (node, parent) {
|
||||
var fn = transformer[node.type] || transformer.all;
|
||||
if (!fn) return;
|
||||
|
||||
return fn(node, parent, opts);
|
||||
});
|
||||
};
|
||||
|
||||
transform.test = function (actual, expect, opts) {
|
||||
expect = [].concat(expect).join("\n");
|
||||
actual = [].concat(actual).join("\n");
|
||||
|
||||
opts = opts || {};
|
||||
_.defaults(opts, { filename: "test" });
|
||||
|
||||
actual = util.parse(transform(actual, opts));
|
||||
expect = util.parse(expect);
|
||||
|
||||
try {
|
||||
assert.deepEqual(actual, expect);
|
||||
} catch (err) {
|
||||
actual = escodegen.generate(actual);
|
||||
expect = escodegen.generate(expect);
|
||||
assert.equal(actual, expect);
|
||||
}
|
||||
};
|
||||
|
||||
transform.transformers = {
|
||||
arrowFunctions: require("./transformers/arrow-functions"),
|
||||
classes: require("./transformers/classes"),
|
||||
spread: require("./transformers/spread"),
|
||||
templateLiterals: require("./transformers/template-literals"),
|
||||
propertyMethodAssignment: require("./transformers/property-method-assignment"),
|
||||
defaultParameters: require("./transformers/default-parameters"),
|
||||
destructuringAssignment: require("./transformers/destructuring-assignment"),
|
||||
generators: require("./transformers/generators"),
|
||||
blockBinding: require("./transformers/block-binding"),
|
||||
modules: require("./transformers/modules"),
|
||||
restParameters: require("./transformers/rest-parameters")
|
||||
};
|
||||
27
lib/6to5/transformers/arrow-functions.js
Normal file
27
lib/6to5/transformers/arrow-functions.js
Normal file
@@ -0,0 +1,27 @@
|
||||
var traverse = require("../traverse");
|
||||
var util = require("../util");
|
||||
|
||||
exports.ArrowFunctionExpression = function (node) {
|
||||
var body = node.body;
|
||||
if (body.type !== "BlockStatement") {
|
||||
body = {
|
||||
type: "BlockStatement",
|
||||
body: [{
|
||||
type: "ReturnStatement",
|
||||
argument: body
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
node.expression = false;
|
||||
node.body = body;
|
||||
node.type = "FunctionExpression";
|
||||
|
||||
if (traverse.hasType(node, "ThisExpression")) {
|
||||
return util.template("function-bind-this", {
|
||||
FUNCTION: node
|
||||
});
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
};
|
||||
59
lib/6to5/transformers/block-binding.js
Normal file
59
lib/6to5/transformers/block-binding.js
Normal file
@@ -0,0 +1,59 @@
|
||||
var transform = require("../transform");
|
||||
var traverse = require("../traverse");
|
||||
var util = require("../util");
|
||||
var _ = require("lodash");
|
||||
|
||||
var isLet = function (node) {
|
||||
if (node.type === "VariableDeclaration" && node.kind === "let") {
|
||||
node.kind = "var";
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
exports.Program = function (node) {
|
||||
_.each(node.body, isLet);
|
||||
};
|
||||
|
||||
exports.BlockStatement = function (node, parent) {
|
||||
var hasLet = false;
|
||||
|
||||
_.each(node.body, function (bodyNode) {
|
||||
if (isLet(bodyNode)) hasLet = true;
|
||||
});
|
||||
|
||||
if (!hasLet) return;
|
||||
|
||||
// ignore if we're direct children of a closure already
|
||||
if (parent.type === "FunctionExpression") return;
|
||||
|
||||
node.body = [buildNode(node.body)];
|
||||
};
|
||||
|
||||
exports.ForInStatement = function (node) {
|
||||
if (isLet(node.left)) return buildNode(node);
|
||||
};
|
||||
|
||||
exports.ForStatement = function (node) {
|
||||
if (isLet(node.init)) return buildNode(node);
|
||||
};
|
||||
|
||||
var buildNode = function (node) {
|
||||
var func = {
|
||||
type: "FunctionExpression",
|
||||
params: [],
|
||||
defaults: [],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [].concat(node)
|
||||
}
|
||||
};
|
||||
|
||||
var templateName = "function-call";
|
||||
if (traverse.hasType(node, "ThisExpression")) {
|
||||
templateName = "function-call-this";
|
||||
}
|
||||
|
||||
return util.template(templateName, {
|
||||
FUNCTION: func
|
||||
}, true);
|
||||
};
|
||||
132
lib/6to5/transformers/classes.js
Normal file
132
lib/6to5/transformers/classes.js
Normal file
@@ -0,0 +1,132 @@
|
||||
var traverse = require("../traverse");
|
||||
var util = require("../util");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.ClassDeclaration = function (node, parent, opts) {
|
||||
var superName = node.superClass;
|
||||
var className = node.id;
|
||||
|
||||
var root = util.template("class", {
|
||||
CLASS_NAME: className
|
||||
}, true);
|
||||
|
||||
var container = root.declarations[0].init;
|
||||
var block = container.callee.body;
|
||||
var body = block.body;
|
||||
|
||||
var returnStatement = body.pop();
|
||||
|
||||
if (superName) {
|
||||
body.push(util.template("inherits", {
|
||||
SUPER_NAME: superName,
|
||||
CLASS_NAME: className
|
||||
}, true));
|
||||
|
||||
container.arguments.push(superName);
|
||||
container.callee.params.push(superName);
|
||||
}
|
||||
|
||||
buildClassBody(body, className, superName, node);
|
||||
|
||||
body.push(returnStatement);
|
||||
|
||||
return root;
|
||||
};
|
||||
|
||||
var buildClassBody = function (body, className, superName, node) {
|
||||
var mutatorMap = {};
|
||||
|
||||
var classBody = node.body.body;
|
||||
_.each(classBody, function (bodyNode) {
|
||||
if (bodyNode.type !== "MethodDefinition") return;
|
||||
|
||||
var methodName = bodyNode.key.name;
|
||||
var method = bodyNode.value;
|
||||
|
||||
replaceInstanceSuperReferences(superName, method);
|
||||
|
||||
if (methodName === "constructor") {
|
||||
if (bodyNode.kind === "") {
|
||||
addConstructor(body[0], method);
|
||||
} else {
|
||||
throw new Error("unknown kind for constructor method");
|
||||
}
|
||||
} else {
|
||||
if (bodyNode.kind === "") {
|
||||
addInstanceMethod(body, className, methodName, method);
|
||||
} else {
|
||||
util.pushMutatorMap(mutatorMap, methodName, bodyNode.kind, bodyNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!_.isEmpty(mutatorMap)) {
|
||||
var protoId = util.template("prototype-identifier", {
|
||||
CLASS_NAME: className
|
||||
});
|
||||
|
||||
body.push(util.buildDefineProperties(mutatorMap, protoId));
|
||||
}
|
||||
};
|
||||
|
||||
var superIdentifier = function (superName, node, parent) {
|
||||
if (parent.property === node) return;
|
||||
if (!superName) return;
|
||||
|
||||
node.name = superName.name;
|
||||
|
||||
// super(); -> ClassName.call(this);
|
||||
if (parent.type === "CallExpression" && parent.callee === node) {
|
||||
node.name += ".call";
|
||||
parent.arguments.unshift({
|
||||
type: "ThisExpression"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var replaceInstanceSuperReferences = function (superName, method) {
|
||||
traverse(method, function (node, parent) {
|
||||
if (node.type === "Identifier" && node.name === "super") {
|
||||
superIdentifier(superName, node, parent);
|
||||
} else if (node.type === "MemberExpression") {
|
||||
// no accessing of super properties
|
||||
|
||||
var obj = node.object;
|
||||
|
||||
if (parent.object === node && obj.type === "Identifier" && obj.name === "super") {
|
||||
throw new Error("cannot access super properties");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (node.type === "CallExpression") {
|
||||
var callee = node.callee;
|
||||
if (callee.type !== "MemberExpression") return;
|
||||
if (callee.object.name !== "super") return;
|
||||
|
||||
callee.property.name = "prototype." + callee.property.name + ".call";
|
||||
node.arguments.unshift({
|
||||
type: "ThisExpression"
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!superName) {
|
||||
throw new Error("cannot access super as this class has none");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var addConstructor = function (construct, method) {
|
||||
construct.defaults = method.defaults;
|
||||
construct.params = method.params;
|
||||
construct.body = method.body;
|
||||
};
|
||||
|
||||
var addInstanceMethod = function (body, className, methodName, method) {
|
||||
body.push(util.template("class-method", {
|
||||
METHOD_NAME: methodName,
|
||||
CLASS_NAME: className,
|
||||
FUNCTION: method
|
||||
}, true));
|
||||
};
|
||||
17
lib/6to5/transformers/default-parameters.js
Normal file
17
lib/6to5/transformers/default-parameters.js
Normal file
@@ -0,0 +1,17 @@
|
||||
var util = require("../util");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.FunctionExpression = function (node) {
|
||||
_.each(node.defaults, function (def, i) {
|
||||
if (!def) return;
|
||||
|
||||
var param = node.params[i];
|
||||
|
||||
node.body.body.unshift(util.template("if-undefined-set-to", {
|
||||
VARIABLE: param,
|
||||
DEFAULT: def
|
||||
}, true));
|
||||
});
|
||||
|
||||
node.defaults = [];
|
||||
};
|
||||
0
lib/6to5/transformers/destructuring-assignment.js
Normal file
0
lib/6to5/transformers/destructuring-assignment.js
Normal file
0
lib/6to5/transformers/generators.js
Normal file
0
lib/6to5/transformers/generators.js
Normal file
85
lib/6to5/transformers/modules.js
Normal file
85
lib/6to5/transformers/modules.js
Normal file
@@ -0,0 +1,85 @@
|
||||
var util = require("../util");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.ImportDeclaration = function (node) {
|
||||
var nodes = [];
|
||||
|
||||
_.each(node.specifiers, function (specifier) {
|
||||
var variableName = specifier.name || specifier.id;
|
||||
|
||||
var key = specifier.id.name;
|
||||
|
||||
var templateName = "require-assign";
|
||||
if (node.kind !== "default") templateName += "-key";
|
||||
|
||||
nodes.push(util.template(templateName, {
|
||||
VARIABLE_NAME: variableName.name,
|
||||
MODULE_NAME: node.source,
|
||||
KEY: key
|
||||
}));
|
||||
});
|
||||
|
||||
return nodes;
|
||||
};
|
||||
|
||||
exports.ModuleDeclaration = function (node) {
|
||||
return util.template("require-assign", {
|
||||
VARIABLE_NAME: node.id,
|
||||
MODULE_NAME: node.source
|
||||
});
|
||||
};
|
||||
|
||||
exports.ExportDeclaration = function (node) {
|
||||
var nodes = [];
|
||||
|
||||
_.each(node.specifiers, function (specifier) {
|
||||
var variableName = specifier.name || specifier.id;
|
||||
|
||||
if (specifier.type === "ExportBatchSpecifier") {
|
||||
nodes.push(util.template("exports-wildcard", {
|
||||
MODULE_NAME: node.source
|
||||
}, true));
|
||||
} else {
|
||||
nodes.push(util.template("exports-require-assign-key", {
|
||||
VARIABLE_NAME: variableName.name,
|
||||
MODULE_NAME: node.source,
|
||||
KEY: specifier.id.name
|
||||
}, true));
|
||||
}
|
||||
});
|
||||
|
||||
var declar = node.declaration;
|
||||
|
||||
if (declar) {
|
||||
if (node.default) {
|
||||
nodes.push(util.template("exports-default", {
|
||||
VALUE: declar
|
||||
}, true));
|
||||
} else {
|
||||
if (declar.type === "VariableDeclaration") {
|
||||
nodes.push(declar);
|
||||
|
||||
_.each(declar.declarations, function (declar) {
|
||||
nodes.push(util.template("exports-alias-var", {
|
||||
STRING_KEY: {
|
||||
type: "Literal",
|
||||
value: declar.id.name
|
||||
},
|
||||
KEY: declar.id
|
||||
}, true));
|
||||
});
|
||||
} else if (declar.type === "FunctionDeclaration") {
|
||||
declar.type = "FunctionExpression";
|
||||
|
||||
nodes.push(util.template("exports-assign", {
|
||||
KEY: declar.id,
|
||||
VALUE: declar
|
||||
}, true));
|
||||
} else {
|
||||
throw new Error("unsupported export declaration type " + declar.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
};
|
||||
32
lib/6to5/transformers/property-method-assignment.js
Normal file
32
lib/6to5/transformers/property-method-assignment.js
Normal file
@@ -0,0 +1,32 @@
|
||||
var util = require("../util");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.Property = function (node) {
|
||||
if (node.method) node.method = false;
|
||||
};
|
||||
|
||||
exports.ObjectExpression = function (node) {
|
||||
//if (node.ignorePropertyMethods) return;
|
||||
//node.ignorePropertyMethods = true;
|
||||
|
||||
var mutatorMap = {};
|
||||
|
||||
node.properties = node.properties.filter(function (prop) {
|
||||
if (prop.kind === "get" || prop.kind === "set") {
|
||||
util.pushMutatorMap(mutatorMap, prop.key.name, prop.kind, prop.value);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (_.isEmpty(mutatorMap)) return;
|
||||
|
||||
return util.template("object-define-properties-closure", {
|
||||
OBJECT: node,
|
||||
CONTENT: util.buildDefineProperties(mutatorMap, {
|
||||
type: "Identifier",
|
||||
name: "obj"
|
||||
}).expression
|
||||
});
|
||||
};
|
||||
19
lib/6to5/transformers/rest-parameters.js
Normal file
19
lib/6to5/transformers/rest-parameters.js
Normal file
@@ -0,0 +1,19 @@
|
||||
var util = require("../util");
|
||||
|
||||
exports.FunctionExpression = function (node, parent) {
|
||||
if (!node.rest) return;
|
||||
|
||||
var rest = node.rest;
|
||||
delete node.rest;
|
||||
|
||||
var templateName = "arguments-slice-assign";
|
||||
if (node.params.length) templateName += "-arg";
|
||||
|
||||
node.body.body.unshift(util.template(templateName, {
|
||||
VARIABLE_NAME: rest,
|
||||
SLICE_ARG: {
|
||||
type: "Literal",
|
||||
value: node.params.length
|
||||
}
|
||||
}));
|
||||
};
|
||||
64
lib/6to5/transformers/spread.js
Normal file
64
lib/6to5/transformers/spread.js
Normal file
@@ -0,0 +1,64 @@
|
||||
var util = require("../util");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.ArrayExpression = function (node, parent) {
|
||||
//if (node.ignoreSpread) return;
|
||||
|
||||
var elements = node.elements;
|
||||
if (!elements.length) return;
|
||||
|
||||
var spread = elements.pop();
|
||||
if (spread.type !== "SpreadElement") {
|
||||
elements.push(spread);
|
||||
return;
|
||||
}
|
||||
|
||||
var concat = util.template("array-concat", {
|
||||
ARGUMENT: spread.argument
|
||||
});
|
||||
|
||||
concat.callee.object.elements = elements;
|
||||
|
||||
return concat;
|
||||
};
|
||||
|
||||
exports.CallExpression = function (node, parent) {
|
||||
var args = node.arguments;
|
||||
|
||||
if (args.length && _.last(args).type === "SpreadElement") {
|
||||
var spread = args.pop();
|
||||
|
||||
var spreadLiteral = spread.argument;
|
||||
|
||||
var contextLiteral = {
|
||||
type: "Literal",
|
||||
value: null
|
||||
};
|
||||
|
||||
node.arguments = [];
|
||||
|
||||
if (args.length) {
|
||||
if (spreadLiteral.name === "arguments") {
|
||||
spreadLiteral = util.template("arguments-slice");
|
||||
}
|
||||
|
||||
var concat = util.template("array-concat");
|
||||
concat.arguments = [spreadLiteral];
|
||||
concat.callee.object.elements = args;
|
||||
node.arguments.push(concat);
|
||||
} else {
|
||||
node.arguments.push(spreadLiteral);
|
||||
}
|
||||
|
||||
var callee = node.callee;
|
||||
|
||||
if (callee.type === "MemberExpression") {
|
||||
contextLiteral = callee.object;
|
||||
callee.property.name += ".apply";
|
||||
} else {
|
||||
node.callee.name += ".apply";
|
||||
}
|
||||
|
||||
node.arguments.unshift(contextLiteral);
|
||||
}
|
||||
};
|
||||
40
lib/6to5/transformers/template-literals.js
Normal file
40
lib/6to5/transformers/template-literals.js
Normal file
@@ -0,0 +1,40 @@
|
||||
var _ = require("lodash");
|
||||
|
||||
var buildBinaryExpression = function (left, right) {
|
||||
return {
|
||||
type: "BinaryExpression",
|
||||
operator: "+",
|
||||
left: left,
|
||||
right: right
|
||||
};
|
||||
};
|
||||
|
||||
exports.TemplateLiteral = function (node) {
|
||||
var nodes = [];
|
||||
|
||||
_.each(node.quasis, function (elem) {
|
||||
nodes.push({
|
||||
type: "Literal",
|
||||
value: elem.value.raw
|
||||
});
|
||||
|
||||
var expr = node.expressions.shift();
|
||||
if (expr) nodes.push(expr);
|
||||
});
|
||||
|
||||
if (nodes.length > 1) {
|
||||
// remove redundant '' at the end of the expression
|
||||
var last = _.last(nodes);
|
||||
if (last.type === "Literal" && last.value === "") nodes.pop();
|
||||
|
||||
var root = buildBinaryExpression(nodes.shift(), nodes.shift());
|
||||
|
||||
_.each(nodes, function (node) {
|
||||
root = buildBinaryExpression(root, node);
|
||||
});
|
||||
|
||||
return root;
|
||||
} else {
|
||||
return nodes[0];
|
||||
}
|
||||
};
|
||||
68
lib/6to5/traverse/index.js
Normal file
68
lib/6to5/traverse/index.js
Normal file
@@ -0,0 +1,68 @@
|
||||
var VISITOR_KEYS = require("./visitor-keys");
|
||||
var _ = require("lodash");
|
||||
|
||||
var traverse = module.exports = function (parent, callback) {
|
||||
if (_.isArray(parent)) {
|
||||
_.each(parent, function (node) {
|
||||
traverse(node, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var keys = VISITOR_KEYS[parent.type] || [];
|
||||
|
||||
_.each(keys, function (key) {
|
||||
var nodes = parent[key];
|
||||
if (!nodes) return;
|
||||
|
||||
var handle = function (obj, key) {
|
||||
if (!obj[key]) return;
|
||||
|
||||
// strict references in case the callback modified/replaced the node
|
||||
|
||||
var result = callback(obj[key], parent, obj, key);
|
||||
if (result === false) return;
|
||||
|
||||
traverse(obj[key], callback);
|
||||
};
|
||||
|
||||
if (_.isArray(nodes)) {
|
||||
_.each(nodes, function (node, i) {
|
||||
handle(nodes, i);
|
||||
});
|
||||
parent[key] = _.flatten(nodes).filter(function (node) {
|
||||
return node !== traverse.Delete;
|
||||
});
|
||||
} else {
|
||||
handle(parent, key);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
traverse.Delete = {};
|
||||
|
||||
traverse.hasType = function (tree, type) {
|
||||
var has = false;
|
||||
|
||||
if (_.isArray(tree)) {
|
||||
return !!_.find(tree, function (node) {
|
||||
return traverse.hasType(node, type);
|
||||
});
|
||||
} else {
|
||||
traverse(tree, function (node) {
|
||||
if (node.type === type) {
|
||||
has = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return has;
|
||||
};
|
||||
|
||||
traverse.replace = function (node, callback) {
|
||||
traverse(node, function (node, parent, obj, key) {
|
||||
var result = callback(node, parent);
|
||||
if (result != null) obj[key] = result;
|
||||
});
|
||||
};
|
||||
46
lib/6to5/traverse/visitor-keys.json
Normal file
46
lib/6to5/traverse/visitor-keys.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"AssignmentExpression": ["left", "right"],
|
||||
"ArrayExpression": ["elements"],
|
||||
"ArrayPattern": ["elements"],
|
||||
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
|
||||
"BlockStatement": ["body"],
|
||||
"BinaryExpression": ["left", "right"],
|
||||
"BreakStatement": ["label"],
|
||||
"CallExpression": ["callee", "arguments"],
|
||||
"CatchClause": ["param", "body"],
|
||||
"ClassBody": ["body"],
|
||||
"ClassDeclaration": ["id", "body", "superClass"],
|
||||
"ClassExpression": ["id", "body", "superClass"],
|
||||
"ConditionalExpression": ["test", "consequent", "alternate"],
|
||||
"ContinueStatement": ["label"],
|
||||
"DoWhileStatement": ["body", "test"],
|
||||
"ExpressionStatement": ["expression"],
|
||||
"ForStatement": ["init", "test", "update", "body"],
|
||||
"ForInStatement": ["left", "right", "body"],
|
||||
"ForOfStatement": ["left", "right", "body"],
|
||||
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body"],
|
||||
"FunctionExpression": ["id", "params", "defaults", "rest", "body"],
|
||||
"IfStatement": ["test", "consequent", "alternate"],
|
||||
"LabeledStatement": ["label", "body"],
|
||||
"LogicalExpression": ["left", "right"],
|
||||
"MemberExpression": ["object", "property"],
|
||||
"MethodDefinition": ["key", "value"],
|
||||
"NewExpression": ["callee", "arguments"],
|
||||
"ObjectExpression": ["properties"],
|
||||
"ObjectPattern": ["properties"],
|
||||
"Program": ["body"],
|
||||
"Property": ["key", "value"],
|
||||
"ReturnStatement": ["argument"],
|
||||
"SequenceExpression": ["expressions"],
|
||||
"SwitchStatement": ["discriminant", "cases"],
|
||||
"SwitchCase": ["test", "consequent"],
|
||||
"ThrowStatement": ["argument"],
|
||||
"TryStatement": ["block", "handlers", "handler", "guardedHandlers", "finalizer"],
|
||||
"UnaryExpression": ["argument"],
|
||||
"UpdateExpression": ["argument"],
|
||||
"VariableDeclaration": ["declarations"],
|
||||
"VariableDeclarator": ["id", "init"],
|
||||
"WhileStatement": ["test", "body"],
|
||||
"WithStatement": ["object", "body"],
|
||||
"YieldExpression": ["argument"]
|
||||
}
|
||||
182
lib/6to5/util.js
Normal file
182
lib/6to5/util.js
Normal file
@@ -0,0 +1,182 @@
|
||||
var estraverse = require("estraverse");
|
||||
var traverse = require("./traverse");
|
||||
var esprima = require("esprima");
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.parse = function (code, opts) {
|
||||
opts = _.defaults(opts || {}, {
|
||||
comment: true,
|
||||
range: true,
|
||||
loc: true
|
||||
});
|
||||
|
||||
code = [].concat(code).join("");
|
||||
|
||||
try {
|
||||
var tree = esprima.parse(code);
|
||||
|
||||
if (tree.tokens && tree.comments) {
|
||||
estraverse.attachComments(tree, tree.comments, tree.tokens);
|
||||
}
|
||||
|
||||
return tree;
|
||||
} catch (err) {
|
||||
if (err.lineNumber) {
|
||||
err.message = err.message + exports.codeFrame(code, err.lineNumber, err.column);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
exports.canCompile = function (filename) {
|
||||
return path.extname(filename) === ".js";
|
||||
};
|
||||
|
||||
exports.sourceMapToComment = function (map) {
|
||||
var json = JSON.stringify(map);
|
||||
var base64 = new Buffer(json).toString("base64");
|
||||
return "//# sourceMappingURL=data:application/json;base64," + base64;
|
||||
};
|
||||
|
||||
exports.pushMutatorMap = function (mutatorMap, key, kind, method) {
|
||||
var map = mutatorMap[key] = mutatorMap[key] || {};
|
||||
if (map[kind]) {
|
||||
throw new Error("a " + kind + " already exists for this property");
|
||||
} else {
|
||||
map[kind] = method;
|
||||
}
|
||||
};
|
||||
|
||||
exports.buildDefineProperties = function (mutatorMap, keyNode) {
|
||||
var objExpr = {
|
||||
type: "ObjectExpression",
|
||||
properties: []
|
||||
};
|
||||
|
||||
_.each(mutatorMap, function (map, key) {
|
||||
var mapNode = {
|
||||
type: "ObjectExpression",
|
||||
properties: []
|
||||
};
|
||||
|
||||
var propNode = {
|
||||
type: "Property",
|
||||
key: {
|
||||
type: "Identifier",
|
||||
name: key
|
||||
},
|
||||
value: mapNode,
|
||||
kind: "init"
|
||||
};
|
||||
|
||||
_.each(map, function (methodNode, type) {
|
||||
if (methodNode.type === "MethodDefinition") methodNode = methodNode.value;
|
||||
mapNode.properties.push({
|
||||
type: "Property",
|
||||
key: {
|
||||
type: "Identifier",
|
||||
name: type
|
||||
},
|
||||
value: methodNode,
|
||||
kind: "init"
|
||||
});
|
||||
});
|
||||
|
||||
objExpr.properties.push(propNode);
|
||||
});
|
||||
|
||||
return exports.template("object-define-properties", {
|
||||
OBJECT: keyNode,
|
||||
PROPS: objExpr
|
||||
}, true);
|
||||
};
|
||||
|
||||
exports.template = function (name, nodes, keepExpression) {
|
||||
var template = _.cloneDeep(exports.templates[name]);
|
||||
|
||||
if (!_.isEmpty(nodes)) {
|
||||
traverse.replace(template, function (node) {
|
||||
if (node.type === "Identifier" && _.has(nodes, node.name)) {
|
||||
var newNode = nodes[node.name];
|
||||
if (_.isString(newNode)) {
|
||||
node.name = newNode;
|
||||
} else {
|
||||
return newNode;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var normaliseNode = function (node) {
|
||||
if (!keepExpression && node.type === "ExpressionStatement") {
|
||||
return node.expression;
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
var body = template.body;
|
||||
|
||||
if (body.length <= 1) {
|
||||
return normaliseNode(body[0]);
|
||||
} else {
|
||||
return body.map(normaliseNode);
|
||||
}
|
||||
};
|
||||
|
||||
exports.codeFrame = function (lines, lineNumber, colNumber) {
|
||||
if (!lineNumber) return "";
|
||||
|
||||
colNumber = Math.max(colNumber, 0);
|
||||
|
||||
lines = lines.split("\n");
|
||||
var start = Math.max(lineNumber - 3, 0);
|
||||
var end = Math.min(lines.length, lineNumber + 3);
|
||||
var width = (end + "").length;
|
||||
|
||||
return "\n" + lines.slice(start, end).map(function (line, i) {
|
||||
var curr = i + start + 1;
|
||||
|
||||
var gutter = curr === lineNumber ? "> " : " ";
|
||||
|
||||
var sep = curr + exports.repeat(width + 1);
|
||||
gutter += sep + "| ";
|
||||
|
||||
var str = gutter + line;
|
||||
|
||||
if (colNumber && curr === lineNumber) {
|
||||
str += "\n";
|
||||
str += exports.repeat(gutter.length - 2);
|
||||
str += "|" + exports.repeat(colNumber) + "^";
|
||||
}
|
||||
|
||||
return str;
|
||||
}).join("\n");
|
||||
};
|
||||
|
||||
exports.repeat = function (width, cha) {
|
||||
cha = cha || " ";
|
||||
return Array(width + 1).join(cha);
|
||||
};
|
||||
|
||||
var templatesCacheLoc = __dirname + "/../../templates.json";
|
||||
|
||||
if (fs.existsSync(templatesCacheLoc)) {
|
||||
exports.templates = require(templatesCacheLoc);
|
||||
} else {
|
||||
exports.templates = {};
|
||||
|
||||
var templatesLoc = __dirname + "/templates";
|
||||
|
||||
_.each(fs.readdirSync(templatesLoc), function (name) {
|
||||
var key = path.basename(name, path.extname(name));
|
||||
|
||||
var code = fs.readFileSync(templatesLoc + "/" + name, "utf8");
|
||||
exports.templates[key] = exports.parse(code, {
|
||||
range: false,
|
||||
loc: false
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user