diff --git a/README.md b/README.md index 220188bc15..688e73ab13 100644 --- a/README.md +++ b/README.md @@ -151,11 +151,7 @@ to5.transformFile("filename.js", options, function (err, result) { sourceMap: false, // Filename for use in errors etc. - filename: "unknown", - - // Format options - // See https://github.com/Constellation/escodegen/wiki/API for options. - format: {} + filename: "unknown" } ``` diff --git a/bin/generate-browser-test b/bin/generate-browser-test index 6a27d5b2cc..6075930537 100755 --- a/bin/generate-browser-test +++ b/bin/generate-browser-test @@ -1,5 +1,6 @@ #!/usr/bin/env node var helper = require("../test/_helper"); +var util = require("../test/_helper"); -console.log("(" + helper.run + ")(" + JSON.stringify(helper.getTests(), null, " ") + ", to5, proclaim)"); +console.log("(" + helper.run + ")(" + util.formatJSON(helper.getTests()) + ", to5, proclaim)"); diff --git a/lib/6to5/transform.js b/lib/6to5/transform.js index 79bbe6b70e..e5fdbd717e 100644 --- a/lib/6to5/transform.js +++ b/lib/6to5/transform.js @@ -1,5 +1,6 @@ var traverse = require("./traverse"); var assert = require("assert"); +var recast = require("recast"); var path = require("path"); var util = require("./util"); var _ = require("lodash"); @@ -51,28 +52,13 @@ transform._run = function (code, tree, opts) { transform._runTransformer(transformer, tree, opts, generateUid); }); - var genOpts = { - file: path.basename(opts.filename), - format: opts.format - }; + var result = util.generate(tree, opts); - if (opts.sourceMap) { - genOpts.sourceMap = genOpts.file; - genOpts.sourceContent = code; - genOpts.sourceMapWithCode = true; + if (opts.sourceMap === "inline") { + result.code += "\n" + util.sourceMapToComment(result.map); } - var result = util.generate(tree, genOpts); - - if (opts.sourceMap) { - if (opts.sourceMap === "inline") { - result.code += "\n" + util.sourceMapToComment(result.map); - } - - return result; - } else { - return { code: result, map: null }; - } + return result; }; transform._runTransformer = function (transformer, tree, opts, generateUid) { @@ -86,20 +72,32 @@ transform._runTransformer = function (transformer, tree, opts, generateUid) { }); }; -transform.test = function (actual, expect, opts) { - opts = opts || {}; - _.defaults(opts, { filename: "test" }); +transform.test = function (task, assert) { + var actual = task.actual; + var expect = task.expect; + var opts = task.options; + + opts.filename = actual.filename; var actualCode = actual.code.trim(); - var transformedCode = transform(actualCode, opts).code; + + var transformedResult = transform(actualCode, opts); + var transformedCode = transformedResult.code; + var actualAst = util.parse(actual.filename, transformedCode); - actualCode = util.generate(actualAst); + var actualResult = recast.prettyPrint(actualAst); + actualCode = actualResult.code; var expectCode = expect.code.trim(); var expectAst = util.parse(expect.filename, expectCode); - expectCode = util.generate(expectAst); + var expectResult = recast.prettyPrint(expectAst); + expectCode = expectResult.code; assert.equal(actualCode, expectCode); + + if (opts.sourceMap && task.sourceMap) { + assert.deepEqual(util.formatJSON(transformedResult.map), util.formatJSON(task.sourceMap)); + } }; transform.transformers = { diff --git a/lib/6to5/traverse/visitor-keys.json b/lib/6to5/traverse/visitor-keys.json index 924b011c60..901163db09 100644 --- a/lib/6to5/traverse/visitor-keys.json +++ b/lib/6to5/traverse/visitor-keys.json @@ -3,6 +3,7 @@ "ArrayPattern": ["elements"], "ArrowFunctionExpression": ["params", "defaults", "rest", "body"], "AssignmentExpression": ["left", "right"], + "AwaitExpression": ["argument"], "BinaryExpression": ["left", "right"], "BlockStatement": ["body"], "BreakStatement": ["label"], @@ -23,6 +24,7 @@ "ExportBatchSpecifier": [], "ExportSpecifier": ["id", "name"], "ExpressionStatement": ["expression"], + "File": ["program"], "ForInStatement": ["left", "right", "body"], "ForOfStatement": ["left", "right", "body"], "ForStatement": ["init", "test", "update", "body"], @@ -70,6 +72,5 @@ "VoidTypeAnnotation": [], "WhileStatement": ["test", "body"], "WithStatement": ["object", "body"], - "YieldExpression": ["argument"], - "AwaitExpression": ["argument"] + "YieldExpression": ["argument"] } diff --git a/lib/6to5/util.js b/lib/6to5/util.js index 7103f1c1c2..db07bfb01a 100644 --- a/lib/6to5/util.js +++ b/lib/6to5/util.js @@ -1,46 +1,12 @@ var estraverse = require("estraverse"); -var escodegen = require("escodegen"); var traverse = require("./traverse"); var esprima = require("esprima-fb"); +var recast = require("recast"); var path = require("path"); var fs = require("fs"); var _ = require("lodash"); var b = require("ast-types").builders; -_.each(esprima.Syntax, function (name) { - estraverse.VisitorKeys[name] = estraverse.VisitorKeys[name] || []; -}); - -exports.parse = function (filename, code, callback, opts) { - try { - var ast = esprima.parse(code, _.extend(opts || {}, { - comment: true, - source: filename, - tokens: true, - range: true, - loc: true - })); - - estraverse.attachComments(ast, ast.comments, ast.tokens); - - if (callback) { - return callback(ast); - } else { - return ast; - } - } catch (err) { - if (!err._6to5) { - err._6to5 = true; - err.message = filename + ": " + err.message; - if (err.lineNumber) { - var frame = exports.codeFrame(code, err.lineNumber, err.column); - err.message = err.message + frame; - } - } - throw err; - } -}; - exports.ensureBlock = function (node) { var block = node.body; if (block.type === "BlockStatement") return; @@ -52,19 +18,8 @@ exports.isPattern = function (node) { return node.type === "ArrayPattern" || node.type === "ObjectPattern"; }; -exports.generate = function (ast, opts) { - opts = opts || {}; - - opts = _.merge({ - comment: true, - format: { - indent: { - style: " " - } - } - }, opts); - - return escodegen.generate(ast, opts); +exports.formatJSON = function (obj) { + return JSON.stringify(obj, null, " "); }; exports.removeProperties = function (tree) { @@ -138,6 +93,7 @@ exports.buildDefineProperties = function (mutatorMap, keyNode) { var propNode = b.property("init", b.identifier(key), mapNode); _.each(map, function (methodNode, type) { + methodNode = _.clone(methodNode); if (methodNode.type === "MethodDefinition") methodNode = methodNode.value; mapNode.properties.push(b.property("init", b.identifier(type), methodNode)); }); @@ -212,6 +168,39 @@ exports.repeat = function (width, cha) { return new Array(width + 1).join(cha); }; +exports.generate = function (ast, opts) { + var printOpts = {}; + if (opts.sourceMap) { + printOpts.sourceMapName = path.basename(opts.filename); + } + + return recast.print(ast, printOpts); +}; + +exports.parse = function (filename, code, callback, opts) { + try { + var ast = recast.parse(code, { + sourceFileName: path.basename(filename) + }); + + if (callback) { + return callback(ast); + } else { + return ast; + } + } catch (err) { + if (!err._6to5) { + err._6to5 = true; + err.message = filename + ": " + err.message; + if (err.lineNumber) { + var frame = exports.codeFrame(code, err.lineNumber, err.column); + err.message = err.message + frame; + } + } + throw err; + } +}; + try { exports.templates = require("../../templates.json"); } catch (err) { @@ -221,7 +210,9 @@ try { var templatesLoc = __dirname + "/templates"; if (!fs.existsSync(templatesLoc)) { - throw new Error("no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/sebmck/6to5/issues"); + throw new Error("no templates directory - this is most likely the result" + + " of a broken `npm publish`. Please report to " + + "https://github.com/sebmck/6to5/issues"); } _.each(fs.readdirSync(templatesLoc), function (name) { @@ -231,6 +222,6 @@ try { exports.templates[key] = exports.removeProperties(exports.parse(loc, code, null, { tolerant: true - })); + }).program); }); } diff --git a/package.json b/package.json index ea18667415..8328aff2bf 100644 --- a/package.json +++ b/package.json @@ -39,15 +39,13 @@ "dependencies": { "ast-types": "0.5.0", "commander": "2.3.0", - "escodegen": "https://github.com/Constellation/escodegen/archive/624550d0d6edf812a661902c6908dedff66005a7.tar.gz", - "esprima-fb": "7001.1.0-dev-harmony-fb", - "estraverse": "1.5.1", "fs-readdir-recursive": "0.0.2", "lodash": "2.4.1", "mkdirp": "0.5.0", "es6-shim": "^0.18.0", "es6-symbol": "^0.1.1", - "regexpu": "^0.2.2" + "regexpu": "^0.2.2", + "recast": "^0.8.0" }, "devDependencies": { "es6-transpiler": "0.7.17", diff --git a/test/_helper.js b/test/_helper.js index 702ba63986..1fdecca05e 100644 --- a/test/_helper.js +++ b/test/_helper.js @@ -20,8 +20,9 @@ exports.run = function (suites, transform, assert) { suite(testSuite.title, function () { _.each(testSuite.tests, function (task) { test(task.title, function () { + var run = function () { - transform.test(task.actual, task.expect, task.options); + transform.test(task, assert); }; var throwMsg = task.options.throws; @@ -70,7 +71,8 @@ exports.getTests = function () { var taskOpts = _.merge({ filename: actualLoc }, _.cloneDeep(suite.options)); if (fs.existsSync(taskOptsLoc)) _.merge(taskOpts, require(taskOptsLoc)); - suite.tests.push({ + + var test = { title: humanise(taskName), options: taskOpts, actual: { @@ -81,7 +83,15 @@ exports.getTests = function () { code: readFile(expectLoc), filename: expectLoc } - }); + }; + + suite.tests.push(test); + + var sourceMapLoc = taskDir + "/source-map.json"; + if (fs.existsSync(sourceMapLoc)) { + test.options.sourceMap = true; + test.sourceMap = require(sourceMapLoc); + } }); });