From 73b8daf370397f03197d20eae3147ad0830cd539 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 14 Oct 2014 10:11:51 +1100 Subject: [PATCH] add generators support via regenerator --- README.md | 17 +++++++++------- lib/6to5/file.js | 1 + lib/6to5/polyfill.js | 1 + lib/6to5/transform.js | 3 ++- lib/6to5/transformer.js | 19 +++++++++++++----- lib/6to5/transformers/generators.js | 3 +++ package.json | 3 ++- test/browser.html | 1 + .../syntax/generators/for-of/actual.js | 20 +++++++++++++++++++ test/fixtures/syntax/generators/options.json | 3 +++ .../syntax/generators/simple/actual.js | 19 ++++++++++++++++++ test/mocha.opts | 1 + 12 files changed, 77 insertions(+), 14 deletions(-) create mode 100644 test/fixtures/syntax/generators/for-of/actual.js create mode 100644 test/fixtures/syntax/generators/options.json create mode 100644 test/fixtures/syntax/generators/simple/actual.js diff --git a/README.md b/README.md index 8738a60a6d..0ea827fb60 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ - **Readable** - formatting is retained if possible so your generated code is as similar as possible. - **Extensible** - with a large range of [plugins](#plugins) and **browser support**. - **Lossless** - **source map support** so you can debug your compiled code with ease. - - **Compact** - maps directly to the equivalent ES5 with **no runtime**. + - **Compact** - maps directly to the equivalent ES5 with **no runtime**[\*](#generators). ## Installation @@ -55,6 +55,7 @@ It's as easy as: - [Default parameters](FEATURES.md#default-parameters) - [Destructuring](FEATURES.md#destructuring) - [For-of](FEATURES.md#for-of) + - [Generators](FEATURES.md#generators) via [regenerator](https://github.com/facebook/regenerator) - [Let scoping](FEATURES.md#let-scoping) - [Modules](FEATURES.md#modules) - [Numeric literals](FEATURES.md#numeric-literals) @@ -65,10 +66,6 @@ It's as easy as: - [Template literals](FEATURES.md#template-literals) - [Unicode Regex](FEATURES.md#unicode-regex) -To be implemented: - - - [Generators](FEATURES.md#generators) - ## Usage ### Plugins @@ -249,7 +246,8 @@ A polyfill is included with 6to5 code that can be included in node like so: require("6to5/polyfill"); ``` -This is simply a wrapper around the +This is simply a wrapper around the regenerator +[runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) and the [es6-shim](https://github.com/paulmillr/es6-shim) and [es6-symbol](https://github.com/medikoo/es6-symbol) polyfills. @@ -276,6 +274,11 @@ If you're inheriting from a class then static properties are inherited from it via [\_\_proto\_\_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto), this is widely supported but you may run into problems with much older browsers. +### Generators + +The [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) +and an [ES6 polyfill](#polyfill) are required in order for generators to work. + ## Differences ### Philosophy @@ -346,7 +349,7 @@ better suited if you'd like a full ES6 environment with polyfills and all. | Default parameters | ✓ | ✓ | ✓ | ✓ | ✓ | | | Destructuring | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | For-of | ✓ | ✓ | ✓ | ✓ | ✓ | | -| Generators | | ✓ | ✓ | | | | +| Generators | ✓ | ✓ | ✓ | | | | | Let scoping | ✓ | ✓ | | | ✓ | | | Modules | ✓ | ✓ | | ✓ | | | | Property method assignment | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | diff --git a/lib/6to5/file.js b/lib/6to5/file.js index bcb67ff6db..b940682797 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -91,6 +91,7 @@ File.prototype.transform = function (ast) { var result = util.generate(ast, opts); if (this.shebang) { + // add back shebang result.code = this.shebang + result.code; } diff --git a/lib/6to5/polyfill.js b/lib/6to5/polyfill.js index 1b9ee87bcd..64c1a40fe2 100644 --- a/lib/6to5/polyfill.js +++ b/lib/6to5/polyfill.js @@ -1,2 +1,3 @@ require("es6-symbol/implement"); require("es6-shim"); +global.regeneratorRuntime = require("regenerator/runtime"); diff --git a/lib/6to5/transform.js b/lib/6to5/transform.js index 5a7798f35d..4106dc6dcd 100644 --- a/lib/6to5/transform.js +++ b/lib/6to5/transform.js @@ -30,6 +30,7 @@ transform.test = function (task, assert) { actualCode = recast.prettyPrint(actualAst).code; if (exec) { + require("./polyfill"); var fn = new Function("assert", actualCode); fn(assert); } @@ -79,12 +80,12 @@ transform.transformers = { templateLiterals: require("./transformers/template-literals"), propertyMethodAssignment: require("./transformers/property-method-assignment"), defaultParameters: require("./transformers/default-parameters"), - generators: require("./transformers/generators"), letScoping: require("./transformers/let-scoping"), restParameters: require("./transformers/rest-parameters"), destructuring: require("./transformers/destructuring"), forOf: require("./transformers/for-of"), unicodeRegex: require("./transformers/unicode-regex"), + generators: require("./transformers/generators"), _aliasFunctions: require("./transformers/_alias-functions") }; diff --git a/lib/6to5/transformer.js b/lib/6to5/transformer.js index 3ec3652374..ab165bcb40 100644 --- a/lib/6to5/transformer.js +++ b/lib/6to5/transformer.js @@ -9,10 +9,14 @@ function Transformer(key, transformer) { } Transformer.normalise = function (transformer) { - _.each(transformer, function (fns, type) { - if (_.isFunction(fns)) fns = { enter: fns }; - transformer[type] = fns; - }); + if (_.isFunction(transformer)) { + transformer = { ast: transformer }; + } else { + _.each(transformer, function (fns, type) { + if (_.isFunction(fns)) fns = { enter: fns }; + transformer[type] = fns; + }); + } return transformer; }; @@ -20,6 +24,11 @@ Transformer.prototype.transform = function (file) { if (!this.canRun(file)) return; var transformer = this.transformer; + var ast = file.ast; + + if (transformer.ast) { + transformer.ast(ast); + } var build = function (exit) { return function (node, parent) { @@ -43,7 +52,7 @@ Transformer.prototype.transform = function (file) { }; }; - traverse(file.ast, { + traverse(ast, { enter: build(), exit: build(true) }); diff --git a/lib/6to5/transformers/generators.js b/lib/6to5/transformers/generators.js index e69de29bb2..20dc6620e1 100644 --- a/lib/6to5/transformers/generators.js +++ b/lib/6to5/transformers/generators.js @@ -0,0 +1,3 @@ +var regenerator = require("regenerator"); + +module.exports = regenerator.transform; diff --git a/package.json b/package.json index 01614747f0..a25af8298b 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "es6-symbol": "0.1.1", "regexpu": "0.3.0", "recast": "0.8.0", - "source-map": "0.1.40" + "source-map": "0.1.40", + "regenerator": "0.6.7" }, "devDependencies": { "es6-transpiler": "0.7.17", diff --git a/test/browser.html b/test/browser.html index fc6320b9a5..8ee85790c4 100644 --- a/test/browser.html +++ b/test/browser.html @@ -13,6 +13,7 @@ diff --git a/test/fixtures/syntax/generators/for-of/actual.js b/test/fixtures/syntax/generators/for-of/actual.js new file mode 100644 index 0000000000..9b13528d62 --- /dev/null +++ b/test/fixtures/syntax/generators/for-of/actual.js @@ -0,0 +1,20 @@ +function *range(max, step) { + var count = 0; + step = step || 1; + + for (var i = 0; i < max; i += step) { + count++; + yield i; + } + + return count; +} + +var gen = range(20, 3); +var values = []; + +for (var value of gen) { + values.push(value); +} + +assert.deepEqual(values, [0, 3, 6, 9, 12, 15, 18]); diff --git a/test/fixtures/syntax/generators/options.json b/test/fixtures/syntax/generators/options.json new file mode 100644 index 0000000000..37997efa87 --- /dev/null +++ b/test/fixtures/syntax/generators/options.json @@ -0,0 +1,3 @@ +{ + "exec": true +} diff --git a/test/fixtures/syntax/generators/simple/actual.js b/test/fixtures/syntax/generators/simple/actual.js new file mode 100644 index 0000000000..6f86130c52 --- /dev/null +++ b/test/fixtures/syntax/generators/simple/actual.js @@ -0,0 +1,19 @@ +function *range(max, step) { + var count = 0; + step = step || 1; + + for (var i = 0; i < max; i += step) { + count++; + yield i; + } + + return count; +} + +var gen = range(20, 3), info; + +while (!(info = gen.next()).done) { + info.value; +} + +assert(info.value, 7); diff --git a/test/mocha.opts b/test/mocha.opts index 78b498b1d3..51c30180df 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,3 +1,4 @@ --reporter dot --ui tdd --check-leaks +--globals regeneratorRuntime