From c97696c224d718d96848df9e1577f337b45464be Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 28 Sep 2014 23:39:22 +1000 Subject: [PATCH] first commit --- .editorconfig | 11 ++ .gitignore | 6 + .jshintignore | 2 + .jshintrc | 22 +++ .npmignore | 5 + .travis.yml | 5 + LICENSE | 22 +++ Makefile | 21 ++ README.md | 134 +++++++++++++ bin/6to5 | 134 +++++++++++++ bin/cache-templates | 5 + browserify.js | 1 + lib/6to5/browserify.js | 19 ++ lib/6to5/middleware.js | 66 +++++++ lib/6to5/node.js | 45 +++++ .../templates/arguments-slice-assign-arg.js | 1 + lib/6to5/templates/arguments-slice-assign.js | 1 + lib/6to5/templates/arguments-slice.js | 1 + lib/6to5/templates/array-concat.js | 1 + lib/6to5/templates/class-method.js | 1 + lib/6to5/templates/class.js | 7 + lib/6to5/templates/exports-alias-var.js | 5 + lib/6to5/templates/exports-assign.js | 1 + lib/6to5/templates/exports-default.js | 1 + .../templates/exports-require-assign-key.js | 1 + lib/6to5/templates/exports-wildcard.js | 5 + lib/6to5/templates/function-bind-this.js | 1 + lib/6to5/templates/function-call-this.js | 1 + lib/6to5/templates/function-call.js | 1 + lib/6to5/templates/if-undefined-set-to.js | 1 + lib/6to5/templates/inherits.js | 8 + .../object-define-properties-closure.js | 4 + .../templates/object-define-properties.js | 1 + lib/6to5/templates/prototype-identifier.js | 1 + lib/6to5/templates/require-assign-key.js | 1 + lib/6to5/templates/require-assign.js | 1 + lib/6to5/transform.js | 107 ++++++++++ lib/6to5/transformers/arrow-functions.js | 27 +++ lib/6to5/transformers/block-binding.js | 59 ++++++ lib/6to5/transformers/classes.js | 132 +++++++++++++ lib/6to5/transformers/default-parameters.js | 17 ++ .../transformers/destructuring-assignment.js | 0 lib/6to5/transformers/generators.js | 0 lib/6to5/transformers/modules.js | 85 ++++++++ .../property-method-assignment.js | 32 +++ lib/6to5/transformers/rest-parameters.js | 19 ++ lib/6to5/transformers/spread.js | 64 ++++++ lib/6to5/transformers/template-literals.js | 40 ++++ lib/6to5/traverse/index.js | 68 +++++++ lib/6to5/traverse/visitor-keys.json | 46 +++++ lib/6to5/util.js | 182 ++++++++++++++++++ package.json | 35 ++++ register.js | 1 + test/api.js | 7 + test/classes.js | 51 +++++ test/errors.js | 3 + .../arrow-functions/empty-arguments/actual.js | 1 + .../empty-arguments/expected.js | 3 + .../arrow-functions/empty-block/actual.js | 1 + .../arrow-functions/empty-block/expected.js | 2 + .../arrow-functions/inside-call/actual.js | 1 + .../arrow-functions/inside-call/expected.js | 3 + .../multiple-arguments/actual.js | 1 + .../multiple-arguments/expected.js | 3 + .../arrow-functions/paran-insertion/actual.js | 1 + .../paran-insertion/expected.js | 3 + .../arrow-functions/single-argument/actual.js | 1 + .../single-argument/expected.js | 3 + .../arrow-functions/this-usage/actual.js | 1 + .../arrow-functions/this-usage/expected.js | 3 + .../block-multiple-let-inside/actual.js | 5 + .../block-multiple-let-inside/expected.js | 7 + .../block-single-let-inside/actual.js | 4 + .../block-single-let-inside/expected.js | 6 + .../closure-ignore-children/actual.js | 4 + .../closure-ignore-children/expected.js | 4 + .../block-binding/for-block-wrap/actual.js | 3 + .../block-binding/for-block-wrap/expected.js | 5 + .../block-binding/for-in-block-wrap/actual.js | 5 + .../for-in-block-wrap/expected.js | 13 ++ .../block-binding/ignore-root/actual.js | 1 + .../block-binding/ignore-root/expected.js | 5 + .../block-binding/this-usage/actual.js | 5 + .../block-binding/this-usage/expected.js | 13 ++ .../classes/accessing-super-class/actual.js | 8 + .../classes/accessing-super-class/expected.js | 17 ++ test/fixtures/classes/constructor/actual.js | 5 + test/fixtures/classes/constructor/expected.js | 6 + .../instance-getter-and-setter/actual.js | 8 + .../instance-getter-and-setter/expected.js | 15 ++ .../classes/instance-getter/actual.js | 5 + .../classes/instance-getter/expected.js | 12 ++ .../classes/instance-method/actual.js | 5 + .../classes/instance-method/expected.js | 8 + .../classes/instance-setter/actual.js | 5 + .../classes/instance-setter/expected.js | 12 ++ test/fixtures/classes/plain-class/actual.js | 1 + test/fixtures/classes/plain-class/expected.js | 5 + test/fixtures/classes/super-class/actual.js | 1 + test/fixtures/classes/super-class/expected.js | 13 ++ .../comments/preserve-multi-line/actual.js | 3 + .../comments/preserve-multi-line/expected.js | 3 + .../comments/preserve-single-line/actual.js | 5 + .../comments/preserve-single-line/expected.js | 5 + .../default-parameters/multiple/actual.js | 7 + .../default-parameters/multiple/expected.js | 12 ++ .../default-parameters/single/actual.js | 3 + .../default-parameters/single/expected.js | 5 + .../fixtures/modules/export-as-from/actual.js | 1 + .../modules/export-as-from/expected.js | 1 + .../fixtures/modules/export-default/actual.js | 5 + .../modules/export-default/expected.js | 5 + .../export-destructuring-from/actual.js | 1 + .../export-destructuring-from/expected.js | 2 + .../modules/export-function/actual.js | 3 + .../modules/export-function/expected.js | 3 + test/fixtures/modules/export-var/actual.js | 1 + test/fixtures/modules/export-var/expected.js | 7 + .../modules/export-wildcard-from/actual.js | 1 + .../modules/export-wildcard-from/expected.js | 5 + .../fixtures/modules/import-as-from/actual.js | 1 + .../modules/import-as-from/expected.js | 1 + .../import-destructuring-from/actual.js | 1 + .../import-destructuring-from/expected.js | 2 + test/fixtures/modules/import-from/actual.js | 1 + test/fixtures/modules/import-from/expected.js | 1 + test/fixtures/modules/module-form/actual.js | 1 + test/fixtures/modules/module-form/expected.js | 1 + .../getter-and-setter/actual.js | 8 + .../getter-and-setter/expected.js | 13 ++ .../getter/actual.js | 5 + .../getter/expected.js | 10 + .../method/actual.js | 5 + .../method/expected.js | 5 + .../setter/actual.js | 5 + .../setter/expected.js | 10 + .../rest-parameters/multiple/actual.js | 3 + .../rest-parameters/multiple/expected.js | 3 + .../fixtures/rest-parameters/single/actual.js | 3 + .../rest-parameters/single/expected.js | 3 + test/fixtures/source-maps/options.json | 3 + test/fixtures/spread/arguments/actual.js | 9 + test/fixtures/spread/arguments/expected.js | 11 ++ test/fixtures/spread/array-literals/actual.js | 1 + .../spread/array-literals/expected.js | 5 + .../actual.js | 1 + .../expected.js | 4 + .../actual.js | 1 + .../expected.js | 1 + .../method-call-multiple-args/actual.js | 1 + .../method-call-multiple-args/expected.js | 4 + .../spread/method-call-single-arg/actual.js | 1 + .../spread/method-call-single-arg/expected.js | 1 + .../template-literals/escape-quotes/actual.js | 1 + .../escape-quotes/expected.js | 1 + .../template-literals/functions/actual.js | 1 + .../template-literals/functions/expected.js | 1 + .../template-literals/multiple/actual.js | 1 + .../template-literals/multiple/expected.js | 1 + .../fixtures/template-literals/none/actual.js | 1 + .../template-literals/none/expected.js | 1 + .../fixtures/template-literals/only/actual.js | 1 + .../template-literals/only/expected.js | 1 + .../template-literals/single/actual.js | 1 + .../template-literals/single/expected.js | 1 + test/index.js | 38 ++++ test/mocha.opts | 3 + 167 files changed, 2007 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .jshintignore create mode 100644 .jshintrc create mode 100644 .npmignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100755 bin/6to5 create mode 100755 bin/cache-templates create mode 100644 browserify.js create mode 100644 lib/6to5/browserify.js create mode 100644 lib/6to5/middleware.js create mode 100644 lib/6to5/node.js create mode 100644 lib/6to5/templates/arguments-slice-assign-arg.js create mode 100644 lib/6to5/templates/arguments-slice-assign.js create mode 100644 lib/6to5/templates/arguments-slice.js create mode 100644 lib/6to5/templates/array-concat.js create mode 100644 lib/6to5/templates/class-method.js create mode 100644 lib/6to5/templates/class.js create mode 100644 lib/6to5/templates/exports-alias-var.js create mode 100644 lib/6to5/templates/exports-assign.js create mode 100644 lib/6to5/templates/exports-default.js create mode 100644 lib/6to5/templates/exports-require-assign-key.js create mode 100644 lib/6to5/templates/exports-wildcard.js create mode 100644 lib/6to5/templates/function-bind-this.js create mode 100644 lib/6to5/templates/function-call-this.js create mode 100644 lib/6to5/templates/function-call.js create mode 100644 lib/6to5/templates/if-undefined-set-to.js create mode 100644 lib/6to5/templates/inherits.js create mode 100644 lib/6to5/templates/object-define-properties-closure.js create mode 100644 lib/6to5/templates/object-define-properties.js create mode 100644 lib/6to5/templates/prototype-identifier.js create mode 100644 lib/6to5/templates/require-assign-key.js create mode 100644 lib/6to5/templates/require-assign.js create mode 100644 lib/6to5/transform.js create mode 100644 lib/6to5/transformers/arrow-functions.js create mode 100644 lib/6to5/transformers/block-binding.js create mode 100644 lib/6to5/transformers/classes.js create mode 100644 lib/6to5/transformers/default-parameters.js create mode 100644 lib/6to5/transformers/destructuring-assignment.js create mode 100644 lib/6to5/transformers/generators.js create mode 100644 lib/6to5/transformers/modules.js create mode 100644 lib/6to5/transformers/property-method-assignment.js create mode 100644 lib/6to5/transformers/rest-parameters.js create mode 100644 lib/6to5/transformers/spread.js create mode 100644 lib/6to5/transformers/template-literals.js create mode 100644 lib/6to5/traverse/index.js create mode 100644 lib/6to5/traverse/visitor-keys.json create mode 100644 lib/6to5/util.js create mode 100644 package.json create mode 100644 register.js create mode 100644 test/api.js create mode 100644 test/classes.js create mode 100644 test/errors.js create mode 100644 test/fixtures/arrow-functions/empty-arguments/actual.js create mode 100644 test/fixtures/arrow-functions/empty-arguments/expected.js create mode 100644 test/fixtures/arrow-functions/empty-block/actual.js create mode 100644 test/fixtures/arrow-functions/empty-block/expected.js create mode 100644 test/fixtures/arrow-functions/inside-call/actual.js create mode 100644 test/fixtures/arrow-functions/inside-call/expected.js create mode 100644 test/fixtures/arrow-functions/multiple-arguments/actual.js create mode 100644 test/fixtures/arrow-functions/multiple-arguments/expected.js create mode 100644 test/fixtures/arrow-functions/paran-insertion/actual.js create mode 100644 test/fixtures/arrow-functions/paran-insertion/expected.js create mode 100644 test/fixtures/arrow-functions/single-argument/actual.js create mode 100644 test/fixtures/arrow-functions/single-argument/expected.js create mode 100644 test/fixtures/arrow-functions/this-usage/actual.js create mode 100644 test/fixtures/arrow-functions/this-usage/expected.js create mode 100644 test/fixtures/block-binding/block-multiple-let-inside/actual.js create mode 100644 test/fixtures/block-binding/block-multiple-let-inside/expected.js create mode 100644 test/fixtures/block-binding/block-single-let-inside/actual.js create mode 100644 test/fixtures/block-binding/block-single-let-inside/expected.js create mode 100644 test/fixtures/block-binding/closure-ignore-children/actual.js create mode 100644 test/fixtures/block-binding/closure-ignore-children/expected.js create mode 100644 test/fixtures/block-binding/for-block-wrap/actual.js create mode 100644 test/fixtures/block-binding/for-block-wrap/expected.js create mode 100644 test/fixtures/block-binding/for-in-block-wrap/actual.js create mode 100644 test/fixtures/block-binding/for-in-block-wrap/expected.js create mode 100644 test/fixtures/block-binding/ignore-root/actual.js create mode 100644 test/fixtures/block-binding/ignore-root/expected.js create mode 100644 test/fixtures/block-binding/this-usage/actual.js create mode 100644 test/fixtures/block-binding/this-usage/expected.js create mode 100644 test/fixtures/classes/accessing-super-class/actual.js create mode 100644 test/fixtures/classes/accessing-super-class/expected.js create mode 100644 test/fixtures/classes/constructor/actual.js create mode 100644 test/fixtures/classes/constructor/expected.js create mode 100644 test/fixtures/classes/instance-getter-and-setter/actual.js create mode 100644 test/fixtures/classes/instance-getter-and-setter/expected.js create mode 100644 test/fixtures/classes/instance-getter/actual.js create mode 100644 test/fixtures/classes/instance-getter/expected.js create mode 100644 test/fixtures/classes/instance-method/actual.js create mode 100644 test/fixtures/classes/instance-method/expected.js create mode 100644 test/fixtures/classes/instance-setter/actual.js create mode 100644 test/fixtures/classes/instance-setter/expected.js create mode 100644 test/fixtures/classes/plain-class/actual.js create mode 100644 test/fixtures/classes/plain-class/expected.js create mode 100644 test/fixtures/classes/super-class/actual.js create mode 100644 test/fixtures/classes/super-class/expected.js create mode 100644 test/fixtures/comments/preserve-multi-line/actual.js create mode 100644 test/fixtures/comments/preserve-multi-line/expected.js create mode 100644 test/fixtures/comments/preserve-single-line/actual.js create mode 100644 test/fixtures/comments/preserve-single-line/expected.js create mode 100644 test/fixtures/default-parameters/multiple/actual.js create mode 100644 test/fixtures/default-parameters/multiple/expected.js create mode 100644 test/fixtures/default-parameters/single/actual.js create mode 100644 test/fixtures/default-parameters/single/expected.js create mode 100644 test/fixtures/modules/export-as-from/actual.js create mode 100644 test/fixtures/modules/export-as-from/expected.js create mode 100644 test/fixtures/modules/export-default/actual.js create mode 100644 test/fixtures/modules/export-default/expected.js create mode 100644 test/fixtures/modules/export-destructuring-from/actual.js create mode 100644 test/fixtures/modules/export-destructuring-from/expected.js create mode 100644 test/fixtures/modules/export-function/actual.js create mode 100644 test/fixtures/modules/export-function/expected.js create mode 100644 test/fixtures/modules/export-var/actual.js create mode 100644 test/fixtures/modules/export-var/expected.js create mode 100644 test/fixtures/modules/export-wildcard-from/actual.js create mode 100644 test/fixtures/modules/export-wildcard-from/expected.js create mode 100644 test/fixtures/modules/import-as-from/actual.js create mode 100644 test/fixtures/modules/import-as-from/expected.js create mode 100644 test/fixtures/modules/import-destructuring-from/actual.js create mode 100644 test/fixtures/modules/import-destructuring-from/expected.js create mode 100644 test/fixtures/modules/import-from/actual.js create mode 100644 test/fixtures/modules/import-from/expected.js create mode 100644 test/fixtures/modules/module-form/actual.js create mode 100644 test/fixtures/modules/module-form/expected.js create mode 100644 test/fixtures/property-methods-assignment/getter-and-setter/actual.js create mode 100644 test/fixtures/property-methods-assignment/getter-and-setter/expected.js create mode 100644 test/fixtures/property-methods-assignment/getter/actual.js create mode 100644 test/fixtures/property-methods-assignment/getter/expected.js create mode 100644 test/fixtures/property-methods-assignment/method/actual.js create mode 100644 test/fixtures/property-methods-assignment/method/expected.js create mode 100644 test/fixtures/property-methods-assignment/setter/actual.js create mode 100644 test/fixtures/property-methods-assignment/setter/expected.js create mode 100644 test/fixtures/rest-parameters/multiple/actual.js create mode 100644 test/fixtures/rest-parameters/multiple/expected.js create mode 100644 test/fixtures/rest-parameters/single/actual.js create mode 100644 test/fixtures/rest-parameters/single/expected.js create mode 100644 test/fixtures/source-maps/options.json create mode 100644 test/fixtures/spread/arguments/actual.js create mode 100644 test/fixtures/spread/arguments/expected.js create mode 100644 test/fixtures/spread/array-literals/actual.js create mode 100644 test/fixtures/spread/array-literals/expected.js create mode 100644 test/fixtures/spread/contexted-method-call-multiple-args/actual.js create mode 100644 test/fixtures/spread/contexted-method-call-multiple-args/expected.js create mode 100644 test/fixtures/spread/contexted-method-call-single-arg/actual.js create mode 100644 test/fixtures/spread/contexted-method-call-single-arg/expected.js create mode 100644 test/fixtures/spread/method-call-multiple-args/actual.js create mode 100644 test/fixtures/spread/method-call-multiple-args/expected.js create mode 100644 test/fixtures/spread/method-call-single-arg/actual.js create mode 100644 test/fixtures/spread/method-call-single-arg/expected.js create mode 100644 test/fixtures/template-literals/escape-quotes/actual.js create mode 100644 test/fixtures/template-literals/escape-quotes/expected.js create mode 100644 test/fixtures/template-literals/functions/actual.js create mode 100644 test/fixtures/template-literals/functions/expected.js create mode 100644 test/fixtures/template-literals/multiple/actual.js create mode 100644 test/fixtures/template-literals/multiple/expected.js create mode 100644 test/fixtures/template-literals/none/actual.js create mode 100644 test/fixtures/template-literals/none/expected.js create mode 100644 test/fixtures/template-literals/only/actual.js create mode 100644 test/fixtures/template-literals/only/expected.js create mode 100644 test/fixtures/template-literals/single/actual.js create mode 100644 test/fixtures/template-literals/single/expected.js create mode 100644 test/index.js create mode 100644 test/mocha.opts 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