commit c97696c224d718d96848df9e1577f337b45464be Author: Sebastian McKenzie Date: Sun Sep 28 23:39:22 2014 +1000 first commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..3f922a1077 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.js] +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..357a77091c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +node_modules +*.log +*.cache +/templates.json +coverage diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000000..f05b1f265d --- /dev/null +++ b/.jshintignore @@ -0,0 +1,2 @@ +node_modules +test diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000000..df9e13d7a0 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,22 @@ +{ + "esnext": true, + "indent": 2, + "maxlen": 80, + "freeze": true, + "camelcase": true, + "unused": true, + "eqnull": true, + "proto": true, + "newcap": true, + "supernew": true, + "noyield": true, + "evil": true, + "node": true, + "boss": true, + "expr": true, + "undef": true, + "loopfunc": true, + "white": true, + "maxparams": 5, + "maxdepth": 4 +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000000..cbf8a4e35d --- /dev/null +++ b/.npmignore @@ -0,0 +1,5 @@ +.DS_Store +node_modules +*.log +*.cache +lib/6to5/templates diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..d63ba09569 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 + - 0.10 + - 0.11 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..99ffaf89e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014 Sebastian McKenzie + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..a045827787 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +MOCHA_CMD = node_modules/mocha/bin/_mocha + +export NODE_ENV = test + +.PHONY: clean test test-cov test-travis publish + +clean: + rm -rf coverage templates.json + +test: + $(MOCHA_CMD) + +test-cov: + make clean + node node_modules/istanbul/lib/cli.js cover $(MOCHA_CMD) -- + +publish: + make clean + node bin/cache-templates + npm publish + make clean diff --git a/README.md b/README.md new file mode 100644 index 0000000000..781b7f2bcf --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +# 6to6 + +**6to5** turns ES6 code into vanilla ES5, so you can use ES6 features **today.** + +6to5 is: + + - Fast - [10x faster than Traceur](#comparison-to-traceur). + - Compact - maps directly to the equivalent ES5. + - Easy - with Browserify support, Node API, Connect Middleware and a CLI. + - Concise - we do not pollute any scope with unneccesary variables or functions declarations. + +## Features + +| Name | Implemented | +| -------------------------- | ----------- | +| Arrow functions | ✓ | +| Classes | ✓ | +| Default parameters | ✓ | +| Spread | ✓ | +| Block binding | ✓ | +| Property method assignment | ✓ | +| Rest parameters | ✓ | +| Template literals | ✓ | +| Modules | ✓ | +| Destructuring assignment | | +| Generators | | + +## Installation + + $ npm install -g 6to5 + +## Usage + +### CLI + +Compile the file `script.js` and output it to `script-compiled.js`. + + $ 6to5 script.js -o script-compiled.js + +Compile the entire `src` directory and output it to the `lib` directory. + + $ 6to5 src -d lib + +Compile the file `script.js` and output it to stdout. + + $ 6to5 script.js + +### Node + +```javascript +var to5 = require("6to5"); + +to5.transform("code();"); + +to5.transformFileSync("script.js"); + +to5.transformFile("script.js", function (err, data) { + +}); +``` + +##### Options + +```javascript +to5.transform("code();", { + // List of transformers to EXCLUDE + // See `features` for valid names. + blacklist: [], + + // List of transformers to ONLY use. + // See `features` for valid names. + whitelist: [], + + // Append source map and comment to bottom of returned output. + sourceMap: false, + + // Filename for use in errors etc. + filename: "unknown", + + // Format options + // See https://github.com/Constellation/escodegen/wiki/API for options. + format: {} +}); +``` + +#### Require hook + +All subsequent files required by node will be transformed into ES5 compatible +code. + +```javascript +require("6to5/register"); +``` + +#### Connect Middleware + +```javascript +var to5 = require("6to5"); + +app.use(6to5.middleware({ + transform: { + // options to use when transforming files + }, + src: "assets", + dest: "cache" +})); + +app.use(connect.static("cache")); +``` + +### Browserify + +#### CLI + + $ browserify script.js -t 6to5/browserify --outfile bundle.js + +#### Node + +```javascript +var to5 = require("6to5"); +browserify() + .transform(to5.browserify) + .require("script.js", { entry: true }) + .bundle({ debug: true }) + .pipe(fs.createWriteStream("bundle.js")); +``` + +## Caveats + +### Generators + +### Let + +## Comparison to Traceur diff --git a/bin/6to5 b/bin/6to5 new file mode 100755 index 0000000000..5092ac44cf --- /dev/null +++ b/bin/6to5 @@ -0,0 +1,134 @@ +#!/usr/bin/env node + +var commander = require("commander"); +var chokidar = require("chokidar"); +var readdir = require("fs-readdir-recursive"); +var mkdirp = require("mkdirp"); +var 6to5 = require("../lib/6to5/node"); +var path = require("path"); +var util = require("../lib/6to5/util"); +var fs = require("fs"); +var _ = require("lodash"); + +commander.option("-m, --source-maps", "Generate source maps alongside the compiled JavaScript files. Adds sourceMappingURL directives to the JavaScript as well."); +//commander.option("-w, --watch", "Watch, only works with --out-dir"); + +var list = function (val) { + return val ? val.split(",") : []; +}; + +commander.option("-w, --whitelist [whitelist]", "Whitelist", list); +commander.option("-b, --blacklist [blacklist]", "Blacklist", list); +commander.option("-o, --out-file [out]", "Compile all input files into a single file"); +commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory"); + +var pkg = require("../package.json"); +commander.version(pkg.version); +commander.usage("[options] "); +commander.parse(process.argv); + +// + +var errors = []; + +var filenames = commander.args; +if (!filenames.length) errors.push("no filenames input"); + +_.each(filenames, function (filename) { + if (!fs.existsSync(filename)) { + errors.push(filename + " doesn't exist"); + } +}); + +if (commander.outFile && commander.outDir) { + errors.push("cannot have --out-file and --out-dir"); +} + +if (errors.length) { + console.error(errors.join(". ")); + process.exit(2); +} + +// + +var readdirFilter = function (filename) { + return readdir(filename).filter(util.canCompile); +}; + +var mainOpts = { + blacklist: commander.blacklist, + whitelist: commander.whitelist, + sourceMap: commander.sourceMaps, + tolerant: commander.tolerant +}; + +var data = []; + +var compile = function (filename) { + var opts = _.clone(mainOpts); + opts.filename = filename; + + var file = fs.readFileSync(filename); + return 6to5.transform(file, opts); +}; + +if (commander.outDir) { + var write = function (src, relative) { + var data = compile(src); + + var dest = path.join(commander.outDir, relative); + + var up = path.normalize(dest + "/.."); + mkdirp.sync(up); + + fs.writeFileSync(dest, data); + + console.log(src + " -> " + dest); + }; + + var handle = function (filename) { + var stat = fs.statSync(filename); + + if (stat.isDirectory(filename)) { + var dirname = filename; + + _.each(readdirFilter(dirname), function (filename) { + write(path.join(dirname, filename), filename); + }); + } else { + write(filename, filename); + } + }; + + _.each(filenames, handle); +} else { + var data = []; + + var _filenames = filenames; + filenames = []; + + _.each(_filenames, function (filename) { + var stat = fs.statSync(filename); + if (stat.isDirectory()) { + var dirname = filename; + + _.each(readdirFilter(filename), function (filename) { + filenames.push(path.join(dirname, filename)); + }); + } else { + filenames.push(filename); + } + }); + + _.each(filenames, function (filename) { + data.push(compile(filename) + "\n"); + }); + + data = data.join(""); + + if (commander.outFile) { + fs.writeFileSync(commander.out, data); + } else { + console.log(data); + } +} diff --git a/bin/cache-templates b/bin/cache-templates new file mode 100755 index 0000000000..da349147e8 --- /dev/null +++ b/bin/cache-templates @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +var fs = require("fs"); +var templates = require("../lib/6to5/util").templates; +fs.writeFileSync("templates.json", JSON.stringify(templates)); diff --git a/browserify.js b/browserify.js new file mode 100644 index 0000000000..a4835f1cbb --- /dev/null +++ b/browserify.js @@ -0,0 +1 @@ +module.exports = require("./lib/6to5/browserify"); diff --git a/lib/6to5/browserify.js b/lib/6to5/browserify.js new file mode 100644 index 0000000000..9ed1f4b1f0 --- /dev/null +++ b/lib/6to5/browserify.js @@ -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; +}; diff --git a/lib/6to5/middleware.js b/lib/6to5/middleware.js new file mode 100644 index 0000000000..72998b61c8 --- /dev/null +++ b/lib/6to5/middleware.js @@ -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(); + } + }); + }); + }; +}; diff --git a/lib/6to5/node.js b/lib/6to5/node.js new file mode 100644 index 0000000000..4f6fdf9ea5 --- /dev/null +++ b/lib/6to5/node.js @@ -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); +}; diff --git a/lib/6to5/templates/arguments-slice-assign-arg.js b/lib/6to5/templates/arguments-slice-assign-arg.js new file mode 100644 index 0000000000..63fb4b7bd8 --- /dev/null +++ b/lib/6to5/templates/arguments-slice-assign-arg.js @@ -0,0 +1 @@ +var VARIABLE_NAME = Array.prototype.slice.call(arguments, SLICE_ARG); diff --git a/lib/6to5/templates/arguments-slice-assign.js b/lib/6to5/templates/arguments-slice-assign.js new file mode 100644 index 0000000000..c6c31475d1 --- /dev/null +++ b/lib/6to5/templates/arguments-slice-assign.js @@ -0,0 +1 @@ +var VARIABLE_NAME = Array.prototype.slice.call(arguments); diff --git a/lib/6to5/templates/arguments-slice.js b/lib/6to5/templates/arguments-slice.js new file mode 100644 index 0000000000..46653b4d59 --- /dev/null +++ b/lib/6to5/templates/arguments-slice.js @@ -0,0 +1 @@ +Array.prototype.slice.call(arguments); diff --git a/lib/6to5/templates/array-concat.js b/lib/6to5/templates/array-concat.js new file mode 100644 index 0000000000..0ee1aa04d8 --- /dev/null +++ b/lib/6to5/templates/array-concat.js @@ -0,0 +1 @@ +[].concat(ARGUMENT); diff --git a/lib/6to5/templates/class-method.js b/lib/6to5/templates/class-method.js new file mode 100644 index 0000000000..eed693f56a --- /dev/null +++ b/lib/6to5/templates/class-method.js @@ -0,0 +1 @@ +CLASS_NAME.prototype.METHOD_NAME = FUNCTION; diff --git a/lib/6to5/templates/class.js b/lib/6to5/templates/class.js new file mode 100644 index 0000000000..fc3c3ba01a --- /dev/null +++ b/lib/6to5/templates/class.js @@ -0,0 +1,7 @@ +var CLASS_NAME = (function () { + function CLASS_NAME() { + + } + + return CLASS_NAME; +})(); diff --git a/lib/6to5/templates/exports-alias-var.js b/lib/6to5/templates/exports-alias-var.js new file mode 100644 index 0000000000..fe27d9464c --- /dev/null +++ b/lib/6to5/templates/exports-alias-var.js @@ -0,0 +1,5 @@ +Object.defineProperty(exports, STRING_KEY, { + get: function () { + return KEY; + } +}); diff --git a/lib/6to5/templates/exports-assign.js b/lib/6to5/templates/exports-assign.js new file mode 100644 index 0000000000..c4c06b8a9a --- /dev/null +++ b/lib/6to5/templates/exports-assign.js @@ -0,0 +1 @@ +exports.KEY = VALUE; diff --git a/lib/6to5/templates/exports-default.js b/lib/6to5/templates/exports-default.js new file mode 100644 index 0000000000..4ce92a4fd1 --- /dev/null +++ b/lib/6to5/templates/exports-default.js @@ -0,0 +1 @@ +exports = module.exports = VALUE; diff --git a/lib/6to5/templates/exports-require-assign-key.js b/lib/6to5/templates/exports-require-assign-key.js new file mode 100644 index 0000000000..43de6ff6ff --- /dev/null +++ b/lib/6to5/templates/exports-require-assign-key.js @@ -0,0 +1 @@ +exports.VARIABLE_NAME = require(MODULE_NAME).KEY; diff --git a/lib/6to5/templates/exports-wildcard.js b/lib/6to5/templates/exports-wildcard.js new file mode 100644 index 0000000000..364ad8c20d --- /dev/null +++ b/lib/6to5/templates/exports-wildcard.js @@ -0,0 +1,5 @@ +(function (obj) { + for (var i in obj) { + exports[i] = obj[i]; + } +}(require(MODULE_NAME))); diff --git a/lib/6to5/templates/function-bind-this.js b/lib/6to5/templates/function-bind-this.js new file mode 100644 index 0000000000..b27ddb63aa --- /dev/null +++ b/lib/6to5/templates/function-bind-this.js @@ -0,0 +1 @@ +FUNCTION.bind(this); diff --git a/lib/6to5/templates/function-call-this.js b/lib/6to5/templates/function-call-this.js new file mode 100644 index 0000000000..720d64f373 --- /dev/null +++ b/lib/6to5/templates/function-call-this.js @@ -0,0 +1 @@ +FUNCTION.call(this); diff --git a/lib/6to5/templates/function-call.js b/lib/6to5/templates/function-call.js new file mode 100644 index 0000000000..13ba2f4b1a --- /dev/null +++ b/lib/6to5/templates/function-call.js @@ -0,0 +1 @@ +FUNCTION(); diff --git a/lib/6to5/templates/if-undefined-set-to.js b/lib/6to5/templates/if-undefined-set-to.js new file mode 100644 index 0000000000..c5ed82cdf9 --- /dev/null +++ b/lib/6to5/templates/if-undefined-set-to.js @@ -0,0 +1 @@ +if (VARIABLE === undefined) VARIABLE = DEFAULT; diff --git a/lib/6to5/templates/inherits.js b/lib/6to5/templates/inherits.js new file mode 100644 index 0000000000..343298086e --- /dev/null +++ b/lib/6to5/templates/inherits.js @@ -0,0 +1,8 @@ +CLASS_NAME.prototype = Object.create(SUPER_NAME.prototype, { + constructor: { + value: CLASS_NAME, + enumerable: false, + writable: true, + configurable: true + } +}); diff --git a/lib/6to5/templates/object-define-properties-closure.js b/lib/6to5/templates/object-define-properties-closure.js new file mode 100644 index 0000000000..c09c638d3f --- /dev/null +++ b/lib/6to5/templates/object-define-properties-closure.js @@ -0,0 +1,4 @@ +(function (obj) { + CONTENT; + return obj; +})(OBJECT); diff --git a/lib/6to5/templates/object-define-properties.js b/lib/6to5/templates/object-define-properties.js new file mode 100644 index 0000000000..55a569988f --- /dev/null +++ b/lib/6to5/templates/object-define-properties.js @@ -0,0 +1 @@ +Object.defineProperties(OBJECT, PROPS); diff --git a/lib/6to5/templates/prototype-identifier.js b/lib/6to5/templates/prototype-identifier.js new file mode 100644 index 0000000000..0bc116ef9a --- /dev/null +++ b/lib/6to5/templates/prototype-identifier.js @@ -0,0 +1 @@ +CLASS_NAME.prototype diff --git a/lib/6to5/templates/require-assign-key.js b/lib/6to5/templates/require-assign-key.js new file mode 100644 index 0000000000..07b0ef07fb --- /dev/null +++ b/lib/6to5/templates/require-assign-key.js @@ -0,0 +1 @@ +var VARIABLE_NAME = require(MODULE_NAME).KEY; diff --git a/lib/6to5/templates/require-assign.js b/lib/6to5/templates/require-assign.js new file mode 100644 index 0000000000..2b389fbfdf --- /dev/null +++ b/lib/6to5/templates/require-assign.js @@ -0,0 +1 @@ +var VARIABLE_NAME = require(MODULE_NAME); diff --git a/lib/6to5/transform.js b/lib/6to5/transform.js new file mode 100644 index 0000000000..79e9dcb3ff --- /dev/null +++ b/lib/6to5/transform.js @@ -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") +}; diff --git a/lib/6to5/transformers/arrow-functions.js b/lib/6to5/transformers/arrow-functions.js new file mode 100644 index 0000000000..6fbe989371 --- /dev/null +++ b/lib/6to5/transformers/arrow-functions.js @@ -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; + } +}; diff --git a/lib/6to5/transformers/block-binding.js b/lib/6to5/transformers/block-binding.js new file mode 100644 index 0000000000..fa894dc256 --- /dev/null +++ b/lib/6to5/transformers/block-binding.js @@ -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); +}; diff --git a/lib/6to5/transformers/classes.js b/lib/6to5/transformers/classes.js new file mode 100644 index 0000000000..1e5a4c374c --- /dev/null +++ b/lib/6to5/transformers/classes.js @@ -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)); +}; diff --git a/lib/6to5/transformers/default-parameters.js b/lib/6to5/transformers/default-parameters.js new file mode 100644 index 0000000000..aaf8bdc024 --- /dev/null +++ b/lib/6to5/transformers/default-parameters.js @@ -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 = []; +}; diff --git a/lib/6to5/transformers/destructuring-assignment.js b/lib/6to5/transformers/destructuring-assignment.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/6to5/transformers/generators.js b/lib/6to5/transformers/generators.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/6to5/transformers/modules.js b/lib/6to5/transformers/modules.js new file mode 100644 index 0000000000..63d37028e7 --- /dev/null +++ b/lib/6to5/transformers/modules.js @@ -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; +}; diff --git a/lib/6to5/transformers/property-method-assignment.js b/lib/6to5/transformers/property-method-assignment.js new file mode 100644 index 0000000000..90a1386d3d --- /dev/null +++ b/lib/6to5/transformers/property-method-assignment.js @@ -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 + }); +}; diff --git a/lib/6to5/transformers/rest-parameters.js b/lib/6to5/transformers/rest-parameters.js new file mode 100644 index 0000000000..71e15918b1 --- /dev/null +++ b/lib/6to5/transformers/rest-parameters.js @@ -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 + } + })); +}; diff --git a/lib/6to5/transformers/spread.js b/lib/6to5/transformers/spread.js new file mode 100644 index 0000000000..7ac9ec69bf --- /dev/null +++ b/lib/6to5/transformers/spread.js @@ -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); + } +}; diff --git a/lib/6to5/transformers/template-literals.js b/lib/6to5/transformers/template-literals.js new file mode 100644 index 0000000000..37e5feb75a --- /dev/null +++ b/lib/6to5/transformers/template-literals.js @@ -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]; + } +}; diff --git a/lib/6to5/traverse/index.js b/lib/6to5/traverse/index.js new file mode 100644 index 0000000000..7478df20d0 --- /dev/null +++ b/lib/6to5/traverse/index.js @@ -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; + }); +}; diff --git a/lib/6to5/traverse/visitor-keys.json b/lib/6to5/traverse/visitor-keys.json new file mode 100644 index 0000000000..85c0609647 --- /dev/null +++ b/lib/6to5/traverse/visitor-keys.json @@ -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"] +} diff --git a/lib/6to5/util.js b/lib/6to5/util.js new file mode 100644 index 0000000000..886f892bda --- /dev/null +++ b/lib/6to5/util.js @@ -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 + }); + }); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..6d19353580 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "6to5", + "description": "Turn ES6 code into vanilla ES5 with no runtime required", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "https://github.com/sebmck/6to5.git" + }, + "bugs": { + "url": "https://github.com/sebmck/6to5/issues" + }, + "preferGlobal": true, + "main": "lib/6to5/node.js", + "bin": { + "6to5": "./bin/6to5" + }, + "scripts": { + "test": "mocha" + }, + "dependencies": { + "chokidar": "^0.8.4", + "commander": "^2.3.0", + "escodegen": "https://github.com/Constellation/escodegen/tarball/master", + "esprima": "https://github.com/esnext/esprima/tarball/harmony-esnext", + "estraverse": "^1.5.1", + "fs-readdir-recursive": "0.0.2", + "lodash": "^2.4.1", + "mkdirp": "^0.5.0", + "through": "^2.3.4" + }, + "devDependencies": { + "istanbul": "0.3.2", + "mocha": "^1.21.4" + } +} diff --git a/register.js b/register.js new file mode 100644 index 0000000000..7d1809bbcd --- /dev/null +++ b/register.js @@ -0,0 +1 @@ +require("6to5").register(); diff --git a/test/api.js b/test/api.js new file mode 100644 index 0000000000..f2dc2291a1 --- /dev/null +++ b/test/api.js @@ -0,0 +1,7 @@ +suite("api", function () { + test("whitelist"); + + test("blacklist"); + + test("tolerant"); +}); diff --git a/test/classes.js b/test/classes.js new file mode 100644 index 0000000000..f5108437dd --- /dev/null +++ b/test/classes.js @@ -0,0 +1,51 @@ +var transform = require("../lib/6to5/transform"); +var assert = require("assert"); + +suite("classes", function () { + test("no calling super properties", function () { + assert.throws(function () { + transform.test([ + "class Test extends Foo {", + " constructor() {", + " super.test.whatever();", + " }", + "}" + ]); + }, /cannot access super properties/, "unexpected error"); + }); + + test("no accessing super properties", function () { + assert.throws(function () { + transform.test([ + "class Test extends Foo {", + " constructor() {", + " super.test.whatever;", + " }", + "}" + ]); + }, /cannot access super properties/, "unexpected error"); + }); + + test("accessing super without having one", function () { + assert.throws(function () { + transform.test([ + "class Test {", + " constructor() {", + " super();", + " }", + "}" + ]); + }, /cannot access super as this class has none/, "unexpected error"); + }); + + test("defining constructor as a mutator", function () { + assert.throws(function () { + transform.test([ + "class Test {", + " get constructor() {", + " }", + "}" + ]); + }, /unknown kind for constructor method/, "unexpected error"); + }); +}); diff --git a/test/errors.js b/test/errors.js new file mode 100644 index 0000000000..01db934db9 --- /dev/null +++ b/test/errors.js @@ -0,0 +1,3 @@ +suite("errors", function () { + +}); diff --git a/test/fixtures/arrow-functions/empty-arguments/actual.js b/test/fixtures/arrow-functions/empty-arguments/actual.js new file mode 100644 index 0000000000..3ca32cb574 --- /dev/null +++ b/test/fixtures/arrow-functions/empty-arguments/actual.js @@ -0,0 +1 @@ +var t = () => 5 + 5; diff --git a/test/fixtures/arrow-functions/empty-arguments/expected.js b/test/fixtures/arrow-functions/empty-arguments/expected.js new file mode 100644 index 0000000000..4f6faf9601 --- /dev/null +++ b/test/fixtures/arrow-functions/empty-arguments/expected.js @@ -0,0 +1,3 @@ +var t = function () { + return 5 + 5; +}; diff --git a/test/fixtures/arrow-functions/empty-block/actual.js b/test/fixtures/arrow-functions/empty-block/actual.js new file mode 100644 index 0000000000..6e1c768f7a --- /dev/null +++ b/test/fixtures/arrow-functions/empty-block/actual.js @@ -0,0 +1 @@ +var t = () => {}; diff --git a/test/fixtures/arrow-functions/empty-block/expected.js b/test/fixtures/arrow-functions/empty-block/expected.js new file mode 100644 index 0000000000..846044c23e --- /dev/null +++ b/test/fixtures/arrow-functions/empty-block/expected.js @@ -0,0 +1,2 @@ +var t = function () { +}; diff --git a/test/fixtures/arrow-functions/inside-call/actual.js b/test/fixtures/arrow-functions/inside-call/actual.js new file mode 100644 index 0000000000..81ea80f9f8 --- /dev/null +++ b/test/fixtures/arrow-functions/inside-call/actual.js @@ -0,0 +1 @@ +arr.map(i => i + 1); diff --git a/test/fixtures/arrow-functions/inside-call/expected.js b/test/fixtures/arrow-functions/inside-call/expected.js new file mode 100644 index 0000000000..61defa50d6 --- /dev/null +++ b/test/fixtures/arrow-functions/inside-call/expected.js @@ -0,0 +1,3 @@ +arr.map(function (i) { + return i + 1; +}); diff --git a/test/fixtures/arrow-functions/multiple-arguments/actual.js b/test/fixtures/arrow-functions/multiple-arguments/actual.js new file mode 100644 index 0000000000..2ac82f46df --- /dev/null +++ b/test/fixtures/arrow-functions/multiple-arguments/actual.js @@ -0,0 +1 @@ +var t = (i, x) => i * x; diff --git a/test/fixtures/arrow-functions/multiple-arguments/expected.js b/test/fixtures/arrow-functions/multiple-arguments/expected.js new file mode 100644 index 0000000000..8a79fc9fe8 --- /dev/null +++ b/test/fixtures/arrow-functions/multiple-arguments/expected.js @@ -0,0 +1,3 @@ +var t = function (i, x) { + return i * x; +}; diff --git a/test/fixtures/arrow-functions/paran-insertion/actual.js b/test/fixtures/arrow-functions/paran-insertion/actual.js new file mode 100644 index 0000000000..bcad1baee8 --- /dev/null +++ b/test/fixtures/arrow-functions/paran-insertion/actual.js @@ -0,0 +1 @@ +var t = i => i * 5; diff --git a/test/fixtures/arrow-functions/paran-insertion/expected.js b/test/fixtures/arrow-functions/paran-insertion/expected.js new file mode 100644 index 0000000000..689ec63907 --- /dev/null +++ b/test/fixtures/arrow-functions/paran-insertion/expected.js @@ -0,0 +1,3 @@ +var t = function (i) { + return i * 5; +}; diff --git a/test/fixtures/arrow-functions/single-argument/actual.js b/test/fixtures/arrow-functions/single-argument/actual.js new file mode 100644 index 0000000000..bbaa9e430a --- /dev/null +++ b/test/fixtures/arrow-functions/single-argument/actual.js @@ -0,0 +1 @@ +var t = (i) => i * 5; diff --git a/test/fixtures/arrow-functions/single-argument/expected.js b/test/fixtures/arrow-functions/single-argument/expected.js new file mode 100644 index 0000000000..689ec63907 --- /dev/null +++ b/test/fixtures/arrow-functions/single-argument/expected.js @@ -0,0 +1,3 @@ +var t = function (i) { + return i * 5; +}; diff --git a/test/fixtures/arrow-functions/this-usage/actual.js b/test/fixtures/arrow-functions/this-usage/actual.js new file mode 100644 index 0000000000..8e2573dd1f --- /dev/null +++ b/test/fixtures/arrow-functions/this-usage/actual.js @@ -0,0 +1 @@ +var t = x => this.x + x; diff --git a/test/fixtures/arrow-functions/this-usage/expected.js b/test/fixtures/arrow-functions/this-usage/expected.js new file mode 100644 index 0000000000..eda0cd71f4 --- /dev/null +++ b/test/fixtures/arrow-functions/this-usage/expected.js @@ -0,0 +1,3 @@ +var t = function (x) { + return this.x + x; +}.bind(this); diff --git a/test/fixtures/block-binding/block-multiple-let-inside/actual.js b/test/fixtures/block-binding/block-multiple-let-inside/actual.js new file mode 100644 index 0000000000..46448a3743 --- /dev/null +++ b/test/fixtures/block-binding/block-multiple-let-inside/actual.js @@ -0,0 +1,5 @@ +{ + let val = 1; + let multiplier = 5; + console.log(val * multiplier); +} diff --git a/test/fixtures/block-binding/block-multiple-let-inside/expected.js b/test/fixtures/block-binding/block-multiple-let-inside/expected.js new file mode 100644 index 0000000000..1edebe0070 --- /dev/null +++ b/test/fixtures/block-binding/block-multiple-let-inside/expected.js @@ -0,0 +1,7 @@ +{ + (function () { + var val = 1; + var multiplier = 5; + console.log(val * multiplier); + }()); +} diff --git a/test/fixtures/block-binding/block-single-let-inside/actual.js b/test/fixtures/block-binding/block-single-let-inside/actual.js new file mode 100644 index 0000000000..25951533e5 --- /dev/null +++ b/test/fixtures/block-binding/block-single-let-inside/actual.js @@ -0,0 +1,4 @@ +{ + let val = 1; + console.log(val * 2); +} diff --git a/test/fixtures/block-binding/block-single-let-inside/expected.js b/test/fixtures/block-binding/block-single-let-inside/expected.js new file mode 100644 index 0000000000..262b3401e1 --- /dev/null +++ b/test/fixtures/block-binding/block-single-let-inside/expected.js @@ -0,0 +1,6 @@ +{ + (function () { + var val = 1; + console.log(val * 2); + }()); +} diff --git a/test/fixtures/block-binding/closure-ignore-children/actual.js b/test/fixtures/block-binding/closure-ignore-children/actual.js new file mode 100644 index 0000000000..52b0faf62e --- /dev/null +++ b/test/fixtures/block-binding/closure-ignore-children/actual.js @@ -0,0 +1,4 @@ +(function () { + let i = 5; + console.log(i); +}()); diff --git a/test/fixtures/block-binding/closure-ignore-children/expected.js b/test/fixtures/block-binding/closure-ignore-children/expected.js new file mode 100644 index 0000000000..8070f8da35 --- /dev/null +++ b/test/fixtures/block-binding/closure-ignore-children/expected.js @@ -0,0 +1,4 @@ +(function () { + var i = 5; + console.log(i); +}()); diff --git a/test/fixtures/block-binding/for-block-wrap/actual.js b/test/fixtures/block-binding/for-block-wrap/actual.js new file mode 100644 index 0000000000..071195d953 --- /dev/null +++ b/test/fixtures/block-binding/for-block-wrap/actual.js @@ -0,0 +1,3 @@ +for (let i = 0; i < 9; i++) { + console.log(i); +} diff --git a/test/fixtures/block-binding/for-block-wrap/expected.js b/test/fixtures/block-binding/for-block-wrap/expected.js new file mode 100644 index 0000000000..142d1ea6dc --- /dev/null +++ b/test/fixtures/block-binding/for-block-wrap/expected.js @@ -0,0 +1,5 @@ +(function () { + for (var i = 0; i < 9; i++) { + console.log(i); + } +}()); diff --git a/test/fixtures/block-binding/for-in-block-wrap/actual.js b/test/fixtures/block-binding/for-in-block-wrap/actual.js new file mode 100644 index 0000000000..e746a86613 --- /dev/null +++ b/test/fixtures/block-binding/for-in-block-wrap/actual.js @@ -0,0 +1,5 @@ +var arr = [1, 2, 3]; +for (let i in arr) { + let val = arr[i]; + console.log(val * 2); +} diff --git a/test/fixtures/block-binding/for-in-block-wrap/expected.js b/test/fixtures/block-binding/for-in-block-wrap/expected.js new file mode 100644 index 0000000000..b86f42396d --- /dev/null +++ b/test/fixtures/block-binding/for-in-block-wrap/expected.js @@ -0,0 +1,13 @@ +var arr = [ + 1, + 2, + 3 +]; +(function () { + for (var i in arr) { + (function () { + var val = arr[i]; + console.log(val * 2); + }()); + } +}()); diff --git a/test/fixtures/block-binding/ignore-root/actual.js b/test/fixtures/block-binding/ignore-root/actual.js new file mode 100644 index 0000000000..b669f730d2 --- /dev/null +++ b/test/fixtures/block-binding/ignore-root/actual.js @@ -0,0 +1 @@ +let arr = [1, 2, 3]; diff --git a/test/fixtures/block-binding/ignore-root/expected.js b/test/fixtures/block-binding/ignore-root/expected.js new file mode 100644 index 0000000000..f17c6fc26d --- /dev/null +++ b/test/fixtures/block-binding/ignore-root/expected.js @@ -0,0 +1,5 @@ +var arr = [ + 1, + 2, + 3 +]; diff --git a/test/fixtures/block-binding/this-usage/actual.js b/test/fixtures/block-binding/this-usage/actual.js new file mode 100644 index 0000000000..11689687b0 --- /dev/null +++ b/test/fixtures/block-binding/this-usage/actual.js @@ -0,0 +1,5 @@ +var arr = [1, 2, 3]; +for (let i in arr) { + let val = arr[i]; + console.log(val * this.multiplier); +} diff --git a/test/fixtures/block-binding/this-usage/expected.js b/test/fixtures/block-binding/this-usage/expected.js new file mode 100644 index 0000000000..9b5a790d5a --- /dev/null +++ b/test/fixtures/block-binding/this-usage/expected.js @@ -0,0 +1,13 @@ +var arr = [ + 1, + 2, + 3 +]; +(function () { + for (var i in arr) { + (function () { + var val = arr[i]; + console.log(val * this.multiplier); + }.call(this)); + } +}.call(this)); diff --git a/test/fixtures/classes/accessing-super-class/actual.js b/test/fixtures/classes/accessing-super-class/actual.js new file mode 100644 index 0000000000..fee3fe2867 --- /dev/null +++ b/test/fixtures/classes/accessing-super-class/actual.js @@ -0,0 +1,8 @@ +class Test extends Foo { + constructor() { + woops.super.test(); + super(); + super.test(); + foob(super); + } +} diff --git a/test/fixtures/classes/accessing-super-class/expected.js b/test/fixtures/classes/accessing-super-class/expected.js new file mode 100644 index 0000000000..3ca726c4a5 --- /dev/null +++ b/test/fixtures/classes/accessing-super-class/expected.js @@ -0,0 +1,17 @@ +var Test = function (Foo) { + function Test() { + woops.super.test(); + Foo.call(this); + Foo.prototype.test.call(this); + foob(Foo); + } + Test.prototype = Object.create(Foo.prototype, { + constructor: { + value: Test, + enumerable: false, + writable: true, + configurable: true + } + }); + return Test; +}(Foo); diff --git a/test/fixtures/classes/constructor/actual.js b/test/fixtures/classes/constructor/actual.js new file mode 100644 index 0000000000..62670ab318 --- /dev/null +++ b/test/fixtures/classes/constructor/actual.js @@ -0,0 +1,5 @@ +class Test { + constructor() { + this.state = "test"; + } +} diff --git a/test/fixtures/classes/constructor/expected.js b/test/fixtures/classes/constructor/expected.js new file mode 100644 index 0000000000..718e067e61 --- /dev/null +++ b/test/fixtures/classes/constructor/expected.js @@ -0,0 +1,6 @@ +var Test = function () { + function Test() { + this.state = "test"; + } + return Test; +}(); diff --git a/test/fixtures/classes/instance-getter-and-setter/actual.js b/test/fixtures/classes/instance-getter-and-setter/actual.js new file mode 100644 index 0000000000..52503296ec --- /dev/null +++ b/test/fixtures/classes/instance-getter-and-setter/actual.js @@ -0,0 +1,8 @@ +class Test { + get test() { + return 5 + 5; + } + set test(val) { + this._test = val; + } +} diff --git a/test/fixtures/classes/instance-getter-and-setter/expected.js b/test/fixtures/classes/instance-getter-and-setter/expected.js new file mode 100644 index 0000000000..4ae42e0f88 --- /dev/null +++ b/test/fixtures/classes/instance-getter-and-setter/expected.js @@ -0,0 +1,15 @@ +var Test = function () { + function Test() { + } + Object.defineProperties(Test.prototype, { + test: { + get: function () { + return 5 + 5; + }, + set: function (val) { + this._test = val; + } + } + }); + return Test; +}(); diff --git a/test/fixtures/classes/instance-getter/actual.js b/test/fixtures/classes/instance-getter/actual.js new file mode 100644 index 0000000000..9eb0098289 --- /dev/null +++ b/test/fixtures/classes/instance-getter/actual.js @@ -0,0 +1,5 @@ +class Test { + get test() { + return 5 + 5; + } +} diff --git a/test/fixtures/classes/instance-getter/expected.js b/test/fixtures/classes/instance-getter/expected.js new file mode 100644 index 0000000000..0ff55736f6 --- /dev/null +++ b/test/fixtures/classes/instance-getter/expected.js @@ -0,0 +1,12 @@ +var Test = function () { + function Test() { + } + Object.defineProperties(Test.prototype, { + test: { + get: function () { + return 5 + 5; + } + } + }); + return Test; +}(); diff --git a/test/fixtures/classes/instance-method/actual.js b/test/fixtures/classes/instance-method/actual.js new file mode 100644 index 0000000000..2e89d3e4ec --- /dev/null +++ b/test/fixtures/classes/instance-method/actual.js @@ -0,0 +1,5 @@ +class Test { + test() { + return 5 + 5; + } +} diff --git a/test/fixtures/classes/instance-method/expected.js b/test/fixtures/classes/instance-method/expected.js new file mode 100644 index 0000000000..724b0683fb --- /dev/null +++ b/test/fixtures/classes/instance-method/expected.js @@ -0,0 +1,8 @@ +var Test = function () { + function Test() { + } + Test.prototype.test = function () { + return 5 + 5; + }; + return Test; +}(); diff --git a/test/fixtures/classes/instance-setter/actual.js b/test/fixtures/classes/instance-setter/actual.js new file mode 100644 index 0000000000..abaadb738e --- /dev/null +++ b/test/fixtures/classes/instance-setter/actual.js @@ -0,0 +1,5 @@ +class Test { + set test(val) { + this._test = val; + } +} diff --git a/test/fixtures/classes/instance-setter/expected.js b/test/fixtures/classes/instance-setter/expected.js new file mode 100644 index 0000000000..56432ac1a1 --- /dev/null +++ b/test/fixtures/classes/instance-setter/expected.js @@ -0,0 +1,12 @@ +var Test = function () { + function Test() { + } + Object.defineProperties(Test.prototype, { + test: { + set: function (val) { + this._test = val; + } + } + }); + return Test; +}(); diff --git a/test/fixtures/classes/plain-class/actual.js b/test/fixtures/classes/plain-class/actual.js new file mode 100644 index 0000000000..76edbc5989 --- /dev/null +++ b/test/fixtures/classes/plain-class/actual.js @@ -0,0 +1 @@ +class Test { } diff --git a/test/fixtures/classes/plain-class/expected.js b/test/fixtures/classes/plain-class/expected.js new file mode 100644 index 0000000000..8a1a129f99 --- /dev/null +++ b/test/fixtures/classes/plain-class/expected.js @@ -0,0 +1,5 @@ +var Test = function () { + function Test() { + } + return Test; +}(); diff --git a/test/fixtures/classes/super-class/actual.js b/test/fixtures/classes/super-class/actual.js new file mode 100644 index 0000000000..13a98b37be --- /dev/null +++ b/test/fixtures/classes/super-class/actual.js @@ -0,0 +1 @@ +class Test extends Foo { } diff --git a/test/fixtures/classes/super-class/expected.js b/test/fixtures/classes/super-class/expected.js new file mode 100644 index 0000000000..9f53df4270 --- /dev/null +++ b/test/fixtures/classes/super-class/expected.js @@ -0,0 +1,13 @@ +var Test = function (Foo) { + function Test() { + } + Test.prototype = Object.create(Foo.prototype, { + constructor: { + value: Test, + enumerable: false, + writable: true, + configurable: true + } + }); + return Test; +}(Foo); diff --git a/test/fixtures/comments/preserve-multi-line/actual.js b/test/fixtures/comments/preserve-multi-line/actual.js new file mode 100644 index 0000000000..08459da466 --- /dev/null +++ b/test/fixtures/comments/preserve-multi-line/actual.js @@ -0,0 +1,3 @@ +wow; +// um yeah lol +test.wow(); diff --git a/test/fixtures/comments/preserve-multi-line/expected.js b/test/fixtures/comments/preserve-multi-line/expected.js new file mode 100644 index 0000000000..08459da466 --- /dev/null +++ b/test/fixtures/comments/preserve-multi-line/expected.js @@ -0,0 +1,3 @@ +wow; +// um yeah lol +test.wow(); diff --git a/test/fixtures/comments/preserve-single-line/actual.js b/test/fixtures/comments/preserve-single-line/actual.js new file mode 100644 index 0000000000..07c91027c9 --- /dev/null +++ b/test/fixtures/comments/preserve-single-line/actual.js @@ -0,0 +1,5 @@ +wow; +/* + um yeah lol +*/ +test.wow(); diff --git a/test/fixtures/comments/preserve-single-line/expected.js b/test/fixtures/comments/preserve-single-line/expected.js new file mode 100644 index 0000000000..07c91027c9 --- /dev/null +++ b/test/fixtures/comments/preserve-single-line/expected.js @@ -0,0 +1,5 @@ +wow; +/* + um yeah lol +*/ +test.wow(); diff --git a/test/fixtures/default-parameters/multiple/actual.js b/test/fixtures/default-parameters/multiple/actual.js new file mode 100644 index 0000000000..98694446ff --- /dev/null +++ b/test/fixtures/default-parameters/multiple/actual.js @@ -0,0 +1,7 @@ +var t = function (t = "foo", f = 5) { + return t + " bar " + f; +}; + +var a = function (t, f = 5) { + return t + " bar " + f; +}; diff --git a/test/fixtures/default-parameters/multiple/expected.js b/test/fixtures/default-parameters/multiple/expected.js new file mode 100644 index 0000000000..9499e0d98b --- /dev/null +++ b/test/fixtures/default-parameters/multiple/expected.js @@ -0,0 +1,12 @@ +var t = function (t, f) { + if (f === undefined) + f = 5; + if (t === undefined) + t = "foo"; + return t + " bar " + f; +}; +var a = function (t, f) { + if (f === undefined) + f = 5; + return t + " bar " + f; +}; diff --git a/test/fixtures/default-parameters/single/actual.js b/test/fixtures/default-parameters/single/actual.js new file mode 100644 index 0000000000..7d89e2e035 --- /dev/null +++ b/test/fixtures/default-parameters/single/actual.js @@ -0,0 +1,3 @@ +var t = function (t = "foo") { + return t + " bar"; +}; diff --git a/test/fixtures/default-parameters/single/expected.js b/test/fixtures/default-parameters/single/expected.js new file mode 100644 index 0000000000..1e1dcd73e6 --- /dev/null +++ b/test/fixtures/default-parameters/single/expected.js @@ -0,0 +1,5 @@ +var t = function (t) { + if (t === undefined) + t = "foo"; + return t + " bar"; +}; diff --git a/test/fixtures/modules/export-as-from/actual.js b/test/fixtures/modules/export-as-from/actual.js new file mode 100644 index 0000000000..8187c99075 --- /dev/null +++ b/test/fixtures/modules/export-as-from/actual.js @@ -0,0 +1 @@ +export { encrypt as enc } from "crypto"; diff --git a/test/fixtures/modules/export-as-from/expected.js b/test/fixtures/modules/export-as-from/expected.js new file mode 100644 index 0000000000..4d590deb40 --- /dev/null +++ b/test/fixtures/modules/export-as-from/expected.js @@ -0,0 +1 @@ +exports.enc = require("crypto").encrypt; diff --git a/test/fixtures/modules/export-default/actual.js b/test/fixtures/modules/export-default/actual.js new file mode 100644 index 0000000000..907bb83258 --- /dev/null +++ b/test/fixtures/modules/export-default/actual.js @@ -0,0 +1,5 @@ +export default test; + +export default function (foo, bar) { + +}; diff --git a/test/fixtures/modules/export-default/expected.js b/test/fixtures/modules/export-default/expected.js new file mode 100644 index 0000000000..990160eb8f --- /dev/null +++ b/test/fixtures/modules/export-default/expected.js @@ -0,0 +1,5 @@ +exports = module.exports = test; + +exports = module.exports = function (foo, bar) { + +}; diff --git a/test/fixtures/modules/export-destructuring-from/actual.js b/test/fixtures/modules/export-destructuring-from/actual.js new file mode 100644 index 0000000000..626c3db849 --- /dev/null +++ b/test/fixtures/modules/export-destructuring-from/actual.js @@ -0,0 +1 @@ +export { foo, bar } from "crypto"; diff --git a/test/fixtures/modules/export-destructuring-from/expected.js b/test/fixtures/modules/export-destructuring-from/expected.js new file mode 100644 index 0000000000..dcbb54c5ec --- /dev/null +++ b/test/fixtures/modules/export-destructuring-from/expected.js @@ -0,0 +1,2 @@ +exports.foo = require("crypto").foo; +exports.bar = require("crypto").bar; diff --git a/test/fixtures/modules/export-function/actual.js b/test/fixtures/modules/export-function/actual.js new file mode 100644 index 0000000000..b2df74dbb9 --- /dev/null +++ b/test/fixtures/modules/export-function/actual.js @@ -0,0 +1,3 @@ +export function wow(foo, bar) { + +} diff --git a/test/fixtures/modules/export-function/expected.js b/test/fixtures/modules/export-function/expected.js new file mode 100644 index 0000000000..bdfe47b320 --- /dev/null +++ b/test/fixtures/modules/export-function/expected.js @@ -0,0 +1,3 @@ +exports.wow = function wow(foo, bar) { + +}; diff --git a/test/fixtures/modules/export-var/actual.js b/test/fixtures/modules/export-var/actual.js new file mode 100644 index 0000000000..8dc0527156 --- /dev/null +++ b/test/fixtures/modules/export-var/actual.js @@ -0,0 +1 @@ +export var foo = "test"; diff --git a/test/fixtures/modules/export-var/expected.js b/test/fixtures/modules/export-var/expected.js new file mode 100644 index 0000000000..7a19e48ebc --- /dev/null +++ b/test/fixtures/modules/export-var/expected.js @@ -0,0 +1,7 @@ +var foo = "test"; + +Object.defineProperty(exports, "foo", { + get: function () { + return foo; + } +}); diff --git a/test/fixtures/modules/export-wildcard-from/actual.js b/test/fixtures/modules/export-wildcard-from/actual.js new file mode 100644 index 0000000000..3fb52a2ef3 --- /dev/null +++ b/test/fixtures/modules/export-wildcard-from/actual.js @@ -0,0 +1 @@ +export * from "crypto"; diff --git a/test/fixtures/modules/export-wildcard-from/expected.js b/test/fixtures/modules/export-wildcard-from/expected.js new file mode 100644 index 0000000000..ff0e29a0be --- /dev/null +++ b/test/fixtures/modules/export-wildcard-from/expected.js @@ -0,0 +1,5 @@ +(function (obj) { + for (var i in obj) { + exports[i] = obj[i]; + } +}(require("crypto"))); diff --git a/test/fixtures/modules/import-as-from/actual.js b/test/fixtures/modules/import-as-from/actual.js new file mode 100644 index 0000000000..a897653534 --- /dev/null +++ b/test/fixtures/modules/import-as-from/actual.js @@ -0,0 +1 @@ +import { encrypt as enc } from "crypto"; diff --git a/test/fixtures/modules/import-as-from/expected.js b/test/fixtures/modules/import-as-from/expected.js new file mode 100644 index 0000000000..f7b0039b7d --- /dev/null +++ b/test/fixtures/modules/import-as-from/expected.js @@ -0,0 +1 @@ +var enc = require("crypto").encrypt; diff --git a/test/fixtures/modules/import-destructuring-from/actual.js b/test/fixtures/modules/import-destructuring-from/actual.js new file mode 100644 index 0000000000..03ce0acae7 --- /dev/null +++ b/test/fixtures/modules/import-destructuring-from/actual.js @@ -0,0 +1 @@ +import { encrypt, decrypt } from "crypto"; diff --git a/test/fixtures/modules/import-destructuring-from/expected.js b/test/fixtures/modules/import-destructuring-from/expected.js new file mode 100644 index 0000000000..4288d2f3af --- /dev/null +++ b/test/fixtures/modules/import-destructuring-from/expected.js @@ -0,0 +1,2 @@ +var encrypt = require("crypto").encrypt; +var decrypt = require("crypto").decrypt; diff --git a/test/fixtures/modules/import-from/actual.js b/test/fixtures/modules/import-from/actual.js new file mode 100644 index 0000000000..4913f920e0 --- /dev/null +++ b/test/fixtures/modules/import-from/actual.js @@ -0,0 +1 @@ +import $ from "jquery"; diff --git a/test/fixtures/modules/import-from/expected.js b/test/fixtures/modules/import-from/expected.js new file mode 100644 index 0000000000..706ca85314 --- /dev/null +++ b/test/fixtures/modules/import-from/expected.js @@ -0,0 +1 @@ +var $ = require("jquery"); diff --git a/test/fixtures/modules/module-form/actual.js b/test/fixtures/modules/module-form/actual.js new file mode 100644 index 0000000000..f9d99b90b5 --- /dev/null +++ b/test/fixtures/modules/module-form/actual.js @@ -0,0 +1 @@ +module crypto from "crypto"; diff --git a/test/fixtures/modules/module-form/expected.js b/test/fixtures/modules/module-form/expected.js new file mode 100644 index 0000000000..3ce9932615 --- /dev/null +++ b/test/fixtures/modules/module-form/expected.js @@ -0,0 +1 @@ +var crypto = require("crypto"); diff --git a/test/fixtures/property-methods-assignment/getter-and-setter/actual.js b/test/fixtures/property-methods-assignment/getter-and-setter/actual.js new file mode 100644 index 0000000000..5760e76545 --- /dev/null +++ b/test/fixtures/property-methods-assignment/getter-and-setter/actual.js @@ -0,0 +1,8 @@ +var obj = { + get foo() { + return 5 + 5; + }, + set foo(value) { + this._foo = value; + } +}; diff --git a/test/fixtures/property-methods-assignment/getter-and-setter/expected.js b/test/fixtures/property-methods-assignment/getter-and-setter/expected.js new file mode 100644 index 0000000000..d52c634e98 --- /dev/null +++ b/test/fixtures/property-methods-assignment/getter-and-setter/expected.js @@ -0,0 +1,13 @@ +var obj = function (obj) { + Object.defineProperties(obj, { + foo: { + get: function () { + return 5 + 5; + }, + set: function (value) { + this._foo = value; + } + } + }); + return obj; +}({}); diff --git a/test/fixtures/property-methods-assignment/getter/actual.js b/test/fixtures/property-methods-assignment/getter/actual.js new file mode 100644 index 0000000000..500b46807f --- /dev/null +++ b/test/fixtures/property-methods-assignment/getter/actual.js @@ -0,0 +1,5 @@ +var obj = { + get foo() { + return 5 + 5; + } +}; diff --git a/test/fixtures/property-methods-assignment/getter/expected.js b/test/fixtures/property-methods-assignment/getter/expected.js new file mode 100644 index 0000000000..7f6b975474 --- /dev/null +++ b/test/fixtures/property-methods-assignment/getter/expected.js @@ -0,0 +1,10 @@ +var obj = function (obj) { + Object.defineProperties(obj, { + foo: { + get: function () { + return 5 + 5; + } + } + }); + return obj; +}({}); diff --git a/test/fixtures/property-methods-assignment/method/actual.js b/test/fixtures/property-methods-assignment/method/actual.js new file mode 100644 index 0000000000..9114ccf44c --- /dev/null +++ b/test/fixtures/property-methods-assignment/method/actual.js @@ -0,0 +1,5 @@ +var obj = { + method() { + return 5 + 5; + } +}; diff --git a/test/fixtures/property-methods-assignment/method/expected.js b/test/fixtures/property-methods-assignment/method/expected.js new file mode 100644 index 0000000000..874b21c6b9 --- /dev/null +++ b/test/fixtures/property-methods-assignment/method/expected.js @@ -0,0 +1,5 @@ +var obj = { + method: function () { + return 5 + 5; + } +}; diff --git a/test/fixtures/property-methods-assignment/setter/actual.js b/test/fixtures/property-methods-assignment/setter/actual.js new file mode 100644 index 0000000000..b0b9f98a0e --- /dev/null +++ b/test/fixtures/property-methods-assignment/setter/actual.js @@ -0,0 +1,5 @@ +var obj = { + set foo(value) { + this._foo = value; + } +}; diff --git a/test/fixtures/property-methods-assignment/setter/expected.js b/test/fixtures/property-methods-assignment/setter/expected.js new file mode 100644 index 0000000000..2bed21387e --- /dev/null +++ b/test/fixtures/property-methods-assignment/setter/expected.js @@ -0,0 +1,10 @@ +var obj = function (obj) { + Object.defineProperties(obj, { + foo: { + set: function (value) { + this._foo = value; + } + } + }); + return obj; +}({}); diff --git a/test/fixtures/rest-parameters/multiple/actual.js b/test/fixtures/rest-parameters/multiple/actual.js new file mode 100644 index 0000000000..a017326b85 --- /dev/null +++ b/test/fixtures/rest-parameters/multiple/actual.js @@ -0,0 +1,3 @@ +var t = function (f, ...items) { + +}; diff --git a/test/fixtures/rest-parameters/multiple/expected.js b/test/fixtures/rest-parameters/multiple/expected.js new file mode 100644 index 0000000000..8e44bc14a9 --- /dev/null +++ b/test/fixtures/rest-parameters/multiple/expected.js @@ -0,0 +1,3 @@ +var t = function (f) { + var items = Array.prototype.slice.call(arguments, 1); +}; diff --git a/test/fixtures/rest-parameters/single/actual.js b/test/fixtures/rest-parameters/single/actual.js new file mode 100644 index 0000000000..e35cdfe517 --- /dev/null +++ b/test/fixtures/rest-parameters/single/actual.js @@ -0,0 +1,3 @@ +var t = function (...items) { + +}; diff --git a/test/fixtures/rest-parameters/single/expected.js b/test/fixtures/rest-parameters/single/expected.js new file mode 100644 index 0000000000..ea458a4b80 --- /dev/null +++ b/test/fixtures/rest-parameters/single/expected.js @@ -0,0 +1,3 @@ +var t = function () { + var items = Array.prototype.slice.call(arguments); +}; diff --git a/test/fixtures/source-maps/options.json b/test/fixtures/source-maps/options.json new file mode 100644 index 0000000000..a7aed2bcf8 --- /dev/null +++ b/test/fixtures/source-maps/options.json @@ -0,0 +1,3 @@ +{ + "sourceMap": true +} diff --git a/test/fixtures/spread/arguments/actual.js b/test/fixtures/spread/arguments/actual.js new file mode 100644 index 0000000000..a6fdb21bef --- /dev/null +++ b/test/fixtures/spread/arguments/actual.js @@ -0,0 +1,9 @@ +function foo() { + return bar("test", ...arguments); +} + +function bar(one, two, three) { + return [one, two, three]; +} + +foo("foo", "bar"); diff --git a/test/fixtures/spread/arguments/expected.js b/test/fixtures/spread/arguments/expected.js new file mode 100644 index 0000000000..6cf3de65ef --- /dev/null +++ b/test/fixtures/spread/arguments/expected.js @@ -0,0 +1,11 @@ +function foo() { + return bar.apply(null, ["test"].concat(Array.prototype.slice.call(arguments))); +} +function bar(one, two, three) { + return [ + one, + two, + three + ]; +} +foo("foo", "bar"); diff --git a/test/fixtures/spread/array-literals/actual.js b/test/fixtures/spread/array-literals/actual.js new file mode 100644 index 0000000000..5ebb80da66 --- /dev/null +++ b/test/fixtures/spread/array-literals/actual.js @@ -0,0 +1 @@ +var lyrics = ["head", "and", "toes", ...parts]; diff --git a/test/fixtures/spread/array-literals/expected.js b/test/fixtures/spread/array-literals/expected.js new file mode 100644 index 0000000000..19a3680890 --- /dev/null +++ b/test/fixtures/spread/array-literals/expected.js @@ -0,0 +1,5 @@ +var lyrics = [ + "head", + "and", + "toes" +].concat(parts); diff --git a/test/fixtures/spread/contexted-method-call-multiple-args/actual.js b/test/fixtures/spread/contexted-method-call-multiple-args/actual.js new file mode 100644 index 0000000000..112f046005 --- /dev/null +++ b/test/fixtures/spread/contexted-method-call-multiple-args/actual.js @@ -0,0 +1 @@ +foob.add(foo, bar, ...numbers); diff --git a/test/fixtures/spread/contexted-method-call-multiple-args/expected.js b/test/fixtures/spread/contexted-method-call-multiple-args/expected.js new file mode 100644 index 0000000000..eb6f7281d9 --- /dev/null +++ b/test/fixtures/spread/contexted-method-call-multiple-args/expected.js @@ -0,0 +1,4 @@ +foob.add.apply(foob, [ + foo, + bar +].concat(numbers)); diff --git a/test/fixtures/spread/contexted-method-call-single-arg/actual.js b/test/fixtures/spread/contexted-method-call-single-arg/actual.js new file mode 100644 index 0000000000..08a01b0c56 --- /dev/null +++ b/test/fixtures/spread/contexted-method-call-single-arg/actual.js @@ -0,0 +1 @@ +foob.add(...numbers); diff --git a/test/fixtures/spread/contexted-method-call-single-arg/expected.js b/test/fixtures/spread/contexted-method-call-single-arg/expected.js new file mode 100644 index 0000000000..2423ac1874 --- /dev/null +++ b/test/fixtures/spread/contexted-method-call-single-arg/expected.js @@ -0,0 +1 @@ +foob.add.apply(foob, numbers); diff --git a/test/fixtures/spread/method-call-multiple-args/actual.js b/test/fixtures/spread/method-call-multiple-args/actual.js new file mode 100644 index 0000000000..0a2421b7b4 --- /dev/null +++ b/test/fixtures/spread/method-call-multiple-args/actual.js @@ -0,0 +1 @@ +add(foo, bar, ...numbers); diff --git a/test/fixtures/spread/method-call-multiple-args/expected.js b/test/fixtures/spread/method-call-multiple-args/expected.js new file mode 100644 index 0000000000..732fa5edb1 --- /dev/null +++ b/test/fixtures/spread/method-call-multiple-args/expected.js @@ -0,0 +1,4 @@ +add.apply(null, [ + foo, + bar +].concat(numbers)); diff --git a/test/fixtures/spread/method-call-single-arg/actual.js b/test/fixtures/spread/method-call-single-arg/actual.js new file mode 100644 index 0000000000..a24aa1b09c --- /dev/null +++ b/test/fixtures/spread/method-call-single-arg/actual.js @@ -0,0 +1 @@ +add(...numbers); diff --git a/test/fixtures/spread/method-call-single-arg/expected.js b/test/fixtures/spread/method-call-single-arg/expected.js new file mode 100644 index 0000000000..d95f659560 --- /dev/null +++ b/test/fixtures/spread/method-call-single-arg/expected.js @@ -0,0 +1 @@ +add.apply(null, numbers); diff --git a/test/fixtures/template-literals/escape-quotes/actual.js b/test/fixtures/template-literals/escape-quotes/actual.js new file mode 100644 index 0000000000..22b5aa1a4c --- /dev/null +++ b/test/fixtures/template-literals/escape-quotes/actual.js @@ -0,0 +1 @@ +var t = `'${foo}' "${bar}"`; diff --git a/test/fixtures/template-literals/escape-quotes/expected.js b/test/fixtures/template-literals/escape-quotes/expected.js new file mode 100644 index 0000000000..67956e60ff --- /dev/null +++ b/test/fixtures/template-literals/escape-quotes/expected.js @@ -0,0 +1 @@ +var t = "'" + foo + "' \"" + bar + "\""; diff --git a/test/fixtures/template-literals/functions/actual.js b/test/fixtures/template-literals/functions/actual.js new file mode 100644 index 0000000000..6249f9ccd5 --- /dev/null +++ b/test/fixtures/template-literals/functions/actual.js @@ -0,0 +1 @@ +var foo = `test ${_.test(foo)} ${bar}`; diff --git a/test/fixtures/template-literals/functions/expected.js b/test/fixtures/template-literals/functions/expected.js new file mode 100644 index 0000000000..027f457d3c --- /dev/null +++ b/test/fixtures/template-literals/functions/expected.js @@ -0,0 +1 @@ +var foo = "test " + _.test(foo) + " " + bar; diff --git a/test/fixtures/template-literals/multiple/actual.js b/test/fixtures/template-literals/multiple/actual.js new file mode 100644 index 0000000000..606790184d --- /dev/null +++ b/test/fixtures/template-literals/multiple/actual.js @@ -0,0 +1 @@ +var foo = `test ${foo} ${bar}`; diff --git a/test/fixtures/template-literals/multiple/expected.js b/test/fixtures/template-literals/multiple/expected.js new file mode 100644 index 0000000000..cf7167ad71 --- /dev/null +++ b/test/fixtures/template-literals/multiple/expected.js @@ -0,0 +1 @@ +var foo = "test " + foo + " " + bar; diff --git a/test/fixtures/template-literals/none/actual.js b/test/fixtures/template-literals/none/actual.js new file mode 100644 index 0000000000..d979e5231f --- /dev/null +++ b/test/fixtures/template-literals/none/actual.js @@ -0,0 +1 @@ +var foo = `test`; diff --git a/test/fixtures/template-literals/none/expected.js b/test/fixtures/template-literals/none/expected.js new file mode 100644 index 0000000000..7768209432 --- /dev/null +++ b/test/fixtures/template-literals/none/expected.js @@ -0,0 +1 @@ +var foo = "test"; diff --git a/test/fixtures/template-literals/only/actual.js b/test/fixtures/template-literals/only/actual.js new file mode 100644 index 0000000000..1c4779e873 --- /dev/null +++ b/test/fixtures/template-literals/only/actual.js @@ -0,0 +1 @@ +var foo = `${test}`; diff --git a/test/fixtures/template-literals/only/expected.js b/test/fixtures/template-literals/only/expected.js new file mode 100644 index 0000000000..e7d47c4755 --- /dev/null +++ b/test/fixtures/template-literals/only/expected.js @@ -0,0 +1 @@ +var foo = "" + test; diff --git a/test/fixtures/template-literals/single/actual.js b/test/fixtures/template-literals/single/actual.js new file mode 100644 index 0000000000..25815c8456 --- /dev/null +++ b/test/fixtures/template-literals/single/actual.js @@ -0,0 +1 @@ +var foo = `test ${foo}`; diff --git a/test/fixtures/template-literals/single/expected.js b/test/fixtures/template-literals/single/expected.js new file mode 100644 index 0000000000..dae1e8ea59 --- /dev/null +++ b/test/fixtures/template-literals/single/expected.js @@ -0,0 +1 @@ +var foo = "test " + foo; diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000000..9edc04584e --- /dev/null +++ b/test/index.js @@ -0,0 +1,38 @@ +var transform = require("../lib/6to5/transform"); +var assert = require("assert"); +var fs = require("fs"); +var _ = require("lodash"); + +var humanise = function (val) { + return val.replace(/-/g, " "); +}; + +var fixturesDir = __dirname + "/fixtures"; + +_.each(fs.readdirSync(fixturesDir), function (suiteName) { + var suiteDir = fixturesDir + "/" + suiteName; + + var suiteOptsLoc = suiteDir + "/options.json"; + var suiteOpts = {}; + if (fs.existsSync(suiteOptsLoc)) suiteOpts = require(suiteOptsLoc); + + suite(humanise(suiteName), function () { + _.each(fs.readdirSync(suiteDir), function (taskName) { + var taskDir = suiteDir + "/" + taskName; + if (fs.statSync(taskDir).isFile()) return; + + test(humanise(taskName), function () { + var actualLoc = taskDir + "/actual.js"; + + var actual = fs.readFileSync(actualLoc, "utf8"); + var expect = fs.readFileSync(taskDir + "/expected.js", "utf8"); + + var taskOptsLoc = taskDir + "/options.json"; + var taskOpts = _.merge({ filename: actualLoc }, _.cloneDeep(suiteOpts)); + if (fs.existsSync(taskOptsLoc)) _.merge(taskOpts, require(taskOptsLoc)); + + transform.test(actual, expect, taskOpts); + }); + }); + }); +}); diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000000..78b498b1d3 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,3 @@ +--reporter dot +--ui tdd +--check-leaks