From 925b1f7600c2b678c02f07399f443d3a8a0ecb27 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 2 Jan 2015 01:31:14 +1100 Subject: [PATCH] add optional asyncToGenerator transformer - closes #321 --- lib/6to5/file.js | 9 +++- lib/6to5/runtime-generator.js | 4 ++ .../templates/async-to-generator.js | 37 ++++++++++++++++ lib/6to5/transformation/transform.js | 1 + .../optional-async-to-generator.js | 15 +++++++ .../optional-bluebird-coroutines.js | 10 +++-- .../basic/actual.js | 3 ++ .../basic/expected.js | 42 +++++++++++++++++++ .../optional-async-to-generator/options.json | 3 ++ 9 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 lib/6to5/transformation/templates/async-to-generator.js create mode 100644 lib/6to5/transformation/transformers/optional-async-to-generator.js create mode 100644 test/fixtures/transformation/optional-async-to-generator/basic/actual.js create mode 100644 test/fixtures/transformation/optional-async-to-generator/basic/expected.js create mode 100644 test/fixtures/transformation/optional-async-to-generator/options.json diff --git a/lib/6to5/file.js b/lib/6to5/file.js index 7eda4531d5..57937a47df 100644 --- a/lib/6to5/file.js +++ b/lib/6to5/file.js @@ -27,7 +27,12 @@ File.declarations = [ "object-without-properties", "has-own", "slice", - "define-property" + "define-property", + "async-to-generator" +]; + +File.excludeDeclarationsFromRuntime = [ + "async-to-generator" ]; File.normaliseOptions = function (opts) { @@ -166,7 +171,7 @@ File.prototype.addDeclaration = function (name) { var ref; var runtimeNamespace = this.opts.runtime; - if (runtimeNamespace) { + if (runtimeNamespace && !_.contains(File.excludeDeclarationsFromRuntime, name)) { name = t.identifier(t.toIdentifier(name)); return t.memberExpression(t.identifier(runtimeNamespace), name); } else { diff --git a/lib/6to5/runtime-generator.js b/lib/6to5/runtime-generator.js index c431bc96dc..59ad533466 100644 --- a/lib/6to5/runtime-generator.js +++ b/lib/6to5/runtime-generator.js @@ -19,6 +19,10 @@ module.exports = function (namespace) { ])); _.each(File.declarations, function (name) { + if (_.contains(File.excludeDeclarationsFromRuntime, name)) { + return false; + } + var key = t.identifier(t.toIdentifier(name)); body.push(t.expressionStatement( t.assignmentExpression("=", t.memberExpression(namespace, key), util.template(name)) diff --git a/lib/6to5/transformation/templates/async-to-generator.js b/lib/6to5/transformation/templates/async-to-generator.js new file mode 100644 index 0000000000..aeacb62f04 --- /dev/null +++ b/lib/6to5/transformation/templates/async-to-generator.js @@ -0,0 +1,37 @@ +(function (fn) { + return function () { + var gen = fn.apply(this, arguments); + + return new Promise(function (resolve, reject) { + function step(getNext) { + var next; + + try { + next = getNext(); + } catch(e) { + reject(e); + return; + } + + if (next.done) { + resolve(next.value); + return; + } + + Promise.resolve(next.value).then(function (v) { + step(function () { + return gen.next(v); + }); + }, function (e) { + step(function () { + return gen["throw"](e); + }); + }); + } + + step(function () { + return gen.next(); + }); + }); + } +}) diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index d7c44d377d..f68d61de71 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -49,6 +49,7 @@ _.each({ memoizationOperator: require("./transformers/playground-memoization-operator"), objectGetterMemoization: require("./transformers/playground-object-getter-memoization"), + asyncToGenerator: require("./transformers/optional-async-to-generator"), bluebirdCoroutines: require("./transformers/optional-bluebird-coroutines"), react: require("./transformers/react"), diff --git a/lib/6to5/transformation/transformers/optional-async-to-generator.js b/lib/6to5/transformation/transformers/optional-async-to-generator.js new file mode 100644 index 0000000000..370cf08d02 --- /dev/null +++ b/lib/6to5/transformation/transformers/optional-async-to-generator.js @@ -0,0 +1,15 @@ +var bluebirdCoroutines = require("./optional-bluebird-coroutines"); +var traverse = require("../../traverse"); +var t = require("../../types"); + +exports.optional = true; + +exports.manipulateOptions = bluebirdCoroutines.manipulateOptions; + +exports.Function = function (node, parent, file) { + if (!node.async || node.generator) return; + + bluebirdCoroutines._Function(node); + + return t.callExpression(file.addDeclaration("async-to-generator"), [node]); +}; diff --git a/lib/6to5/transformation/transformers/optional-bluebird-coroutines.js b/lib/6to5/transformation/transformers/optional-bluebird-coroutines.js index a08a27e121..2bb993dffd 100644 --- a/lib/6to5/transformation/transformers/optional-bluebird-coroutines.js +++ b/lib/6to5/transformation/transformers/optional-bluebird-coroutines.js @@ -8,9 +8,7 @@ exports.manipulateOptions = function (opts) { exports.optional = true; -exports.Function = function (node, parent, file) { - if (!node.async || node.generator) return; - +exports._Function = function (node) { node.async = false; node.generator = true; @@ -23,6 +21,12 @@ exports.Function = function (node, parent, file) { } } }); +}; + +exports.Function = function (node, parent, file) { + if (!node.async || node.generator) return; + + exports._Function(node); var id = t.identifier("Bluebird"); file.addImport(id, "bluebird"); diff --git a/test/fixtures/transformation/optional-async-to-generator/basic/actual.js b/test/fixtures/transformation/optional-async-to-generator/basic/actual.js new file mode 100644 index 0000000000..363ec6d007 --- /dev/null +++ b/test/fixtures/transformation/optional-async-to-generator/basic/actual.js @@ -0,0 +1,3 @@ +var foo = async function () { + var wat = await bar(); +}; diff --git a/test/fixtures/transformation/optional-async-to-generator/basic/expected.js b/test/fixtures/transformation/optional-async-to-generator/basic/expected.js new file mode 100644 index 0000000000..faf8868b28 --- /dev/null +++ b/test/fixtures/transformation/optional-async-to-generator/basic/expected.js @@ -0,0 +1,42 @@ +"use strict"; + +var _asyncToGenerator = function (fn) { + return function () { + var gen = fn.apply(this, arguments); + + return new Promise(function (resolve, reject) { + function step(getNext) { + var next; + try { + next = getNext(); + } catch (e) { + reject(e); + + return; + } + if (next.done) { + resolve(next.value); + + return; + } + Promise.resolve(next.value).then(function (v) { + step(function () { + return gen.next(v); + }); + }, function (e) { + step(function () { + return gen["throw"](e); + }); + }); + } + + step(function () { + return gen.next(); + }); + }); + }; +}; + +var foo = _asyncToGenerator(function* () { + var wat = yield bar(); +}); diff --git a/test/fixtures/transformation/optional-async-to-generator/options.json b/test/fixtures/transformation/optional-async-to-generator/options.json new file mode 100644 index 0000000000..d8694ba41c --- /dev/null +++ b/test/fixtures/transformation/optional-async-to-generator/options.json @@ -0,0 +1,3 @@ +{ + "optional": ["asyncToGenerator"] +}