clean up babel-plugin-transform-regenerator
This commit is contained in:
parent
f047a593df
commit
6fa85e6f5b
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,5 @@ dist
|
|||||||
/packages/babel-runtime/helpers/*.js
|
/packages/babel-runtime/helpers/*.js
|
||||||
/packages/babel-runtime/regenerator/*.js
|
/packages/babel-runtime/regenerator/*.js
|
||||||
/packages/*/lib
|
/packages/*/lib
|
||||||
!/packages/babel-plugin-transform-regenerator/lib
|
|
||||||
_babel.github.io
|
_babel.github.io
|
||||||
/tests/.browser-build.js
|
/tests/.browser-build.js
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
var vm = require("vm");
|
|
||||||
var fs = require("fs");
|
|
||||||
|
|
||||||
var loc = __dirname + "/../dist/browser.js";
|
|
||||||
|
|
||||||
suite("browser", function () {
|
|
||||||
test("sanity check", function () {
|
|
||||||
if (fs.existsSync(loc)) {
|
|
||||||
require(loc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
npm-debug.log
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
test/mocha.js
|
|
||||||
test/mocha.css
|
|
||||||
|
|
||||||
test/tests.es5.js
|
|
||||||
test/async.es5.js
|
|
||||||
test/tests.browser.js
|
|
||||||
|
|
||||||
.idea
|
|
||||||
@ -1,805 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2014, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
|
||||||
* additional grant of patent rights can be found in the PATENTS file in
|
|
||||||
* the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assert = require("assert");
|
|
||||||
|
|
||||||
describe("async functions and await expressions", function () {
|
|
||||||
Promise = require("promise");
|
|
||||||
|
|
||||||
describe("regeneratorRuntime", function () {
|
|
||||||
it("should be defined globally", function () {
|
|
||||||
var global = Function("return this")();
|
|
||||||
assert.ok("regeneratorRuntime" in global);
|
|
||||||
assert.strictEqual(global.regeneratorRuntime, regeneratorRuntime);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should have a .wrap method", function () {
|
|
||||||
assert.strictEqual(typeof regeneratorRuntime.wrap, "function");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Promise", function () {
|
|
||||||
it("should be defined globally", function () {
|
|
||||||
var global = Function("return this")();
|
|
||||||
assert.ok("Promise" in global);
|
|
||||||
assert.strictEqual(global.Promise, Promise);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be a function", function () {
|
|
||||||
assert.strictEqual(typeof Promise, "function");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("no-await async function", function () {
|
|
||||||
it("should return a Promise", function (done) {
|
|
||||||
var called = false;
|
|
||||||
|
|
||||||
function noAwait(value) {
|
|
||||||
return regeneratorRuntime.async(function noAwait$(_context) {
|
|
||||||
while (1) switch (_context.prev = _context.next) {
|
|
||||||
case 0:
|
|
||||||
called = true;
|
|
||||||
return _context.abrupt("return", value);
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
case "end":
|
|
||||||
return _context.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var promise = noAwait("asdf");
|
|
||||||
assert.strictEqual(called, true);
|
|
||||||
|
|
||||||
promise.then(function (value) {
|
|
||||||
assert.strictEqual(called, true);
|
|
||||||
assert.strictEqual(value, "asdf");
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("one-await async function", function () {
|
|
||||||
it("should finish asynchronously", function (done) {
|
|
||||||
var flag1 = false;
|
|
||||||
var flag2 = false;
|
|
||||||
|
|
||||||
function oneAwait(value) {
|
|
||||||
var result;
|
|
||||||
return regeneratorRuntime.async(function oneAwait$(_context2) {
|
|
||||||
while (1) switch (_context2.prev = _context2.next) {
|
|
||||||
case 0:
|
|
||||||
flag1 = true;
|
|
||||||
_context2.next = 3;
|
|
||||||
return regeneratorRuntime.awrap(value);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
result = _context2.sent;
|
|
||||||
|
|
||||||
flag2 = true;
|
|
||||||
return _context2.abrupt("return", result);
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
case "end":
|
|
||||||
return _context2.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var promise = oneAwait("asdf");
|
|
||||||
assert.strictEqual(flag1, true);
|
|
||||||
assert.strictEqual(flag2, false);
|
|
||||||
|
|
||||||
promise.then(function (value) {
|
|
||||||
assert.strictEqual(flag2, true);
|
|
||||||
assert.strictEqual(value, "asdf");
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("nested async function calls", function () {
|
|
||||||
it("should evaluate in the right order", function (done) {
|
|
||||||
var markers = [];
|
|
||||||
|
|
||||||
function innerMost(marker) {
|
|
||||||
return regeneratorRuntime.async(function innerMost$(_context3) {
|
|
||||||
while (1) switch (_context3.prev = _context3.next) {
|
|
||||||
case 0:
|
|
||||||
markers.push(marker);
|
|
||||||
_context3.next = 3;
|
|
||||||
return regeneratorRuntime.awrap(marker);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
return _context3.abrupt("return", _context3.sent);
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
case "end":
|
|
||||||
return _context3.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
function inner(marker) {
|
|
||||||
return regeneratorRuntime.async(function inner$(_context4) {
|
|
||||||
while (1) switch (_context4.prev = _context4.next) {
|
|
||||||
case 0:
|
|
||||||
markers.push(marker);
|
|
||||||
|
|
||||||
_context4.t0 = assert;
|
|
||||||
_context4.next = 4;
|
|
||||||
return regeneratorRuntime.awrap(innerMost(marker + 1));
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
_context4.t1 = _context4.sent;
|
|
||||||
_context4.t2 = marker + 1;
|
|
||||||
|
|
||||||
_context4.t0.strictEqual.call(_context4.t0, _context4.t1, _context4.t2);
|
|
||||||
|
|
||||||
markers.push(marker + 2);
|
|
||||||
|
|
||||||
_context4.t3 = assert;
|
|
||||||
_context4.next = 11;
|
|
||||||
return regeneratorRuntime.awrap(innerMost(marker + 3));
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
_context4.t4 = _context4.sent;
|
|
||||||
_context4.t5 = marker + 3;
|
|
||||||
|
|
||||||
_context4.t3.strictEqual.call(_context4.t3, _context4.t4, _context4.t5);
|
|
||||||
|
|
||||||
markers.push(marker + 4);
|
|
||||||
|
|
||||||
case 15:
|
|
||||||
case "end":
|
|
||||||
return _context4.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
function outer() {
|
|
||||||
return regeneratorRuntime.async(function outer$(_context5) {
|
|
||||||
while (1) switch (_context5.prev = _context5.next) {
|
|
||||||
case 0:
|
|
||||||
markers.push(0);
|
|
||||||
_context5.next = 3;
|
|
||||||
return regeneratorRuntime.awrap(inner(1));
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
markers.push(6);
|
|
||||||
_context5.next = 6;
|
|
||||||
return regeneratorRuntime.awrap(inner(7));
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
markers.push(12);
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
case "end":
|
|
||||||
return _context5.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
outer().then(function () {
|
|
||||||
var expected = [];
|
|
||||||
for (var i = 0; i <= 12; ++i) expected.push(i);
|
|
||||||
assert.deepEqual(markers, expected);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("dependent promises", function () {
|
|
||||||
it("should be awaitable out of order", function (done) {
|
|
||||||
function outer(value) {
|
|
||||||
var resolved, p1, v2, v1;
|
|
||||||
return regeneratorRuntime.async(function outer$(_context6) {
|
|
||||||
while (1) switch (_context6.prev = _context6.next) {
|
|
||||||
case 0:
|
|
||||||
resolved = false;
|
|
||||||
p1 = new Promise(function (resolve) {
|
|
||||||
setTimeout(function () {
|
|
||||||
resolve(value + 1);
|
|
||||||
resolved = true;
|
|
||||||
}, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.strictEqual(resolved, false);
|
|
||||||
|
|
||||||
_context6.next = 5;
|
|
||||||
return regeneratorRuntime.awrap(p1.then(function (value) {
|
|
||||||
return value + 1;
|
|
||||||
}));
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
v2 = _context6.sent;
|
|
||||||
|
|
||||||
assert.strictEqual(resolved, true);
|
|
||||||
|
|
||||||
_context6.next = 9;
|
|
||||||
return regeneratorRuntime.awrap(p1);
|
|
||||||
|
|
||||||
case 9:
|
|
||||||
v1 = _context6.sent;
|
|
||||||
return _context6.abrupt("return", [v1, v2]);
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
case "end":
|
|
||||||
return _context6.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
outer(1).then(function (pair) {
|
|
||||||
assert.deepEqual(pair, [2, 3]);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("rejected promises", function () {
|
|
||||||
it("should cause await expressions to throw", function (done) {
|
|
||||||
var error = new Error("rejected");
|
|
||||||
|
|
||||||
function f(arg) {
|
|
||||||
return regeneratorRuntime.async(function f$(_context7) {
|
|
||||||
while (1) switch (_context7.prev = _context7.next) {
|
|
||||||
case 0:
|
|
||||||
_context7.prev = 0;
|
|
||||||
_context7.next = 3;
|
|
||||||
return regeneratorRuntime.awrap(arg);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
return _context7.abrupt("return", _context7.sent);
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
_context7.prev = 6;
|
|
||||||
_context7.t0 = _context7["catch"](0);
|
|
||||||
|
|
||||||
assert.strictEqual(_context7.t0, error);
|
|
||||||
return _context7.abrupt("return", "did throw");
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
case "end":
|
|
||||||
return _context7.stop();
|
|
||||||
}
|
|
||||||
}, null, this, [[0, 6]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all([f(Promise.reject(error)), f(Promise.resolve("did not throw"))]).then(function (results) {
|
|
||||||
assert.deepEqual(results, ["did throw", "did not throw"]);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be returned by exceptional async functions", function (done) {
|
|
||||||
var error = new Error("rejected");
|
|
||||||
|
|
||||||
function e(arg) {
|
|
||||||
return regeneratorRuntime.async(function e$(_context8) {
|
|
||||||
while (1) switch (_context8.prev = _context8.next) {
|
|
||||||
case 0:
|
|
||||||
if (!arg) {
|
|
||||||
_context8.next = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw arg;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return _context8.abrupt("return", "did not throw");
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
case "end":
|
|
||||||
return _context8.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
function f(arg) {
|
|
||||||
return regeneratorRuntime.async(function f$(_context9) {
|
|
||||||
while (1) switch (_context9.prev = _context9.next) {
|
|
||||||
case 0:
|
|
||||||
_context9.next = 2;
|
|
||||||
return regeneratorRuntime.awrap(e(arg));
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return _context9.abrupt("return", _context9.sent);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
case "end":
|
|
||||||
return _context9.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
function g(arg) {
|
|
||||||
return regeneratorRuntime.async(function g$(_context10) {
|
|
||||||
while (1) switch (_context10.prev = _context10.next) {
|
|
||||||
case 0:
|
|
||||||
_context10.next = 2;
|
|
||||||
return regeneratorRuntime.awrap(f(arg));
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return _context10.abrupt("return", _context10.sent);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
case "end":
|
|
||||||
return _context10.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
function h(arg) {
|
|
||||||
return regeneratorRuntime.async(function h$(_context11) {
|
|
||||||
while (1) switch (_context11.prev = _context11.next) {
|
|
||||||
case 0:
|
|
||||||
_context11.next = 2;
|
|
||||||
return regeneratorRuntime.awrap(Promise.all([g(arg), Promise.resolve("dummy")]));
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return _context11.abrupt("return", _context11.sent);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
case "end":
|
|
||||||
return _context11.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all([h(error).then(function () {
|
|
||||||
done(new Error("should not have resolved"));
|
|
||||||
}, function (e) {
|
|
||||||
assert.strictEqual(e, error);
|
|
||||||
return "ok1";
|
|
||||||
}), h(null).then(function (result) {
|
|
||||||
assert.deepEqual(result, ["did not throw", "dummy"]);
|
|
||||||
return "ok2";
|
|
||||||
})]).then(function (results) {
|
|
||||||
assert.deepEqual(results, ["ok1", "ok2"]);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should propagate failure when returned", function () {
|
|
||||||
var rejection = new Error("rejection");
|
|
||||||
|
|
||||||
function f() {
|
|
||||||
return regeneratorRuntime.async(function f$(_context12) {
|
|
||||||
while (1) switch (_context12.prev = _context12.next) {
|
|
||||||
case 0:
|
|
||||||
return _context12.abrupt("return", new Promise(function (resolve, reject) {
|
|
||||||
reject(rejection);
|
|
||||||
}));
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
case "end":
|
|
||||||
return _context12.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return f().then(function (result) {
|
|
||||||
assert.ok(false, "should have been rejected");
|
|
||||||
}, function (error) {
|
|
||||||
assert.strictEqual(error, rejection);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("async function expressions", function () {
|
|
||||||
it("should be allowed", function (done) {
|
|
||||||
(function _callee(arg) {
|
|
||||||
return regeneratorRuntime.async(function _callee$(_context13) {
|
|
||||||
while (1) switch (_context13.prev = _context13.next) {
|
|
||||||
case 0:
|
|
||||||
_context13.next = 2;
|
|
||||||
return regeneratorRuntime.awrap(arg);
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return _context13.abrupt("return", _context13.sent);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
case "end":
|
|
||||||
return _context13.stop();
|
|
||||||
}
|
|
||||||
}, null, this);
|
|
||||||
})(Promise.resolve(1234)).then(function (value) {
|
|
||||||
assert.strictEqual(value, 1234);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("async generator functions", function () {
|
|
||||||
it("should return a working AsyncIterator", function () {
|
|
||||||
var _marked = [gen].map(regeneratorRuntime.mark);
|
|
||||||
|
|
||||||
var markers = [];
|
|
||||||
|
|
||||||
function gen(arg) {
|
|
||||||
var sent, result;
|
|
||||||
return regeneratorRuntime.async(function gen$(_context14) {
|
|
||||||
while (1) switch (_context14.prev = _context14.next) {
|
|
||||||
case 0:
|
|
||||||
markers.push(0);
|
|
||||||
_context14.next = 3;
|
|
||||||
return arg;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
sent = _context14.sent;
|
|
||||||
|
|
||||||
markers.push(1);
|
|
||||||
_context14.next = 7;
|
|
||||||
return regeneratorRuntime.awrap(sent);
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
result = _context14.sent;
|
|
||||||
|
|
||||||
markers.push(2);
|
|
||||||
_context14.t0 = assert;
|
|
||||||
_context14.t1 = regeneratorRuntime;
|
|
||||||
_context14.next = 13;
|
|
||||||
return "second";
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
_context14.t2 = _context14.sent;
|
|
||||||
_context14.next = 16;
|
|
||||||
return _context14.t1.awrap.call(_context14.t1, _context14.t2);
|
|
||||||
|
|
||||||
case 16:
|
|
||||||
_context14.t3 = _context14.sent;
|
|
||||||
|
|
||||||
_context14.t0.strictEqual.call(_context14.t0, _context14.t3, "sent after second");
|
|
||||||
|
|
||||||
markers.push(3);
|
|
||||||
return _context14.abrupt("return", result);
|
|
||||||
|
|
||||||
case 20:
|
|
||||||
case "end":
|
|
||||||
return _context14.stop();
|
|
||||||
}
|
|
||||||
}, _marked[0], this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var iter = gen("initial argument");
|
|
||||||
assert.deepEqual(markers, []);
|
|
||||||
|
|
||||||
var firstPromise = iter.next();
|
|
||||||
assert.deepEqual(markers, [0]);
|
|
||||||
|
|
||||||
return firstPromise.then(function (firstResult) {
|
|
||||||
assert.deepEqual(firstResult, {
|
|
||||||
value: "initial argument",
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepEqual(markers, [0]);
|
|
||||||
|
|
||||||
return iter.next(new Promise(function (resolve) {
|
|
||||||
setTimeout(resolve, 100);
|
|
||||||
}).then(function () {
|
|
||||||
assert.deepEqual(markers, [0, 1]);
|
|
||||||
return "will become final result";
|
|
||||||
}));
|
|
||||||
}).then(function (secondResult) {
|
|
||||||
assert.deepEqual(secondResult, {
|
|
||||||
value: "second",
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepEqual(markers, [0, 1, 2]);
|
|
||||||
|
|
||||||
return iter.next("sent after second");
|
|
||||||
}).then(function (finalResult) {
|
|
||||||
assert.deepEqual(markers, [0, 1, 2, 3]);
|
|
||||||
assert.deepEqual(finalResult, {
|
|
||||||
value: "will become final result",
|
|
||||||
done: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should keep results in order", function () {
|
|
||||||
var _marked2 = [range].map(regeneratorRuntime.mark);
|
|
||||||
|
|
||||||
function range(limit) {
|
|
||||||
var before, after, i;
|
|
||||||
return regeneratorRuntime.async(function range$(_context15) {
|
|
||||||
while (1) switch (_context15.prev = _context15.next) {
|
|
||||||
case 0:
|
|
||||||
before = [];
|
|
||||||
after = [];
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
if (!(i < limit)) {
|
|
||||||
_context15.next = 11;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
before.push(i);
|
|
||||||
_context15.next = 7;
|
|
||||||
return i;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
after.push(i);
|
|
||||||
|
|
||||||
case 8:
|
|
||||||
++i;
|
|
||||||
_context15.next = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
assert.deepEqual(before, after);
|
|
||||||
return _context15.abrupt("return", before);
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
case "end":
|
|
||||||
return _context15.stop();
|
|
||||||
}
|
|
||||||
}, _marked2[0], this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var limit = 10;
|
|
||||||
var iter = range(limit);
|
|
||||||
var promises = [];
|
|
||||||
var results = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < limit; ++i) {
|
|
||||||
var promise = iter.next();
|
|
||||||
promises.push(promise);
|
|
||||||
|
|
||||||
promise.then(function (result) {
|
|
||||||
assert.strictEqual(result.done, false);
|
|
||||||
results.push(result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.deepEqual(results, []);
|
|
||||||
|
|
||||||
return Promise.all(promises).then(function (promiseResults) {
|
|
||||||
assert.deepEqual(results, promiseResults);
|
|
||||||
|
|
||||||
return iter.next();
|
|
||||||
}).then(function (finalResult) {
|
|
||||||
assert.deepEqual(results.map(function (result) {
|
|
||||||
return result.value;
|
|
||||||
}), finalResult.value);
|
|
||||||
|
|
||||||
assert.strictEqual(finalResult.done, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be able to handle many awaits", function () {
|
|
||||||
var _marked3 = [gen].map(regeneratorRuntime.mark);
|
|
||||||
|
|
||||||
var awaitCount = 0;
|
|
||||||
|
|
||||||
function countAwait(i) {
|
|
||||||
return Promise.resolve(i).then(function () {
|
|
||||||
++awaitCount;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function gen(limit) {
|
|
||||||
var i;
|
|
||||||
return regeneratorRuntime.async(function gen$(_context16) {
|
|
||||||
while (1) switch (_context16.prev = _context16.next) {
|
|
||||||
case 0:
|
|
||||||
_context16.next = 2;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(0));
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
_context16.next = 4;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
_context16.next = 6;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(2));
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
_context16.next = 8;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(3));
|
|
||||||
|
|
||||||
case 8:
|
|
||||||
_context16.next = 10;
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
_context16.next = 12;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(5));
|
|
||||||
|
|
||||||
case 12:
|
|
||||||
_context16.next = 14;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(6));
|
|
||||||
|
|
||||||
case 14:
|
|
||||||
_context16.next = 16;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(7));
|
|
||||||
|
|
||||||
case 16:
|
|
||||||
_context16.next = 18;
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
case 18:
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
case 19:
|
|
||||||
if (!(i < limit)) {
|
|
||||||
_context16.next = 25;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_context16.next = 22;
|
|
||||||
return regeneratorRuntime.awrap(countAwait(i));
|
|
||||||
|
|
||||||
case 22:
|
|
||||||
++i;
|
|
||||||
_context16.next = 19;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 25:
|
|
||||||
return _context16.abrupt("return", "done");
|
|
||||||
|
|
||||||
case 26:
|
|
||||||
case "end":
|
|
||||||
return _context16.stop();
|
|
||||||
}
|
|
||||||
}, _marked3[0], this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var iter = gen(100);
|
|
||||||
|
|
||||||
return iter.next().then(function (result) {
|
|
||||||
assert.strictEqual(awaitCount, 1);
|
|
||||||
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: 1,
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
|
|
||||||
return iter.next();
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.strictEqual(awaitCount, 3);
|
|
||||||
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: 4,
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
|
|
||||||
return iter.next();
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.strictEqual(awaitCount, 6);
|
|
||||||
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: 8,
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
|
|
||||||
return iter.next();
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.strictEqual(awaitCount, 6 + 100);
|
|
||||||
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: "done",
|
|
||||||
done: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return iter.next();
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: void 0,
|
|
||||||
done: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should not propagate exceptions between iterations", function () {
|
|
||||||
var _marked4 = [gen].map(regeneratorRuntime.mark);
|
|
||||||
|
|
||||||
function gen() {
|
|
||||||
return regeneratorRuntime.async(function gen$(_context17) {
|
|
||||||
while (1) switch (_context17.prev = _context17.next) {
|
|
||||||
case 0:
|
|
||||||
_context17.next = 2;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
_context17.next = 4;
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
case "end":
|
|
||||||
return _context17.stop();
|
|
||||||
}
|
|
||||||
}, _marked4[0], this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var iter = gen();
|
|
||||||
|
|
||||||
return iter.next().then(function (result) {
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: 1,
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
|
|
||||||
return iter.throw(new Error("thrown from first yield"));
|
|
||||||
}).then(function () {
|
|
||||||
throw new Error("should have thrown");
|
|
||||||
}, function (error) {
|
|
||||||
assert.strictEqual(error.message, "thrown from first yield");
|
|
||||||
return iter.next();
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: void 0,
|
|
||||||
done: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should allow yielding a rejected Promise", function () {
|
|
||||||
var _marked5 = [gen].map(regeneratorRuntime.mark);
|
|
||||||
|
|
||||||
var yielded = new Error("yielded rejection");
|
|
||||||
var returned = new Error("returned rejection");
|
|
||||||
|
|
||||||
function gen() {
|
|
||||||
return regeneratorRuntime.async(function gen$(_context18) {
|
|
||||||
while (1) switch (_context18.prev = _context18.next) {
|
|
||||||
case 0:
|
|
||||||
_context18.t0 = assert;
|
|
||||||
_context18.next = 3;
|
|
||||||
return Promise.reject(yielded);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
_context18.t1 = _context18.sent;
|
|
||||||
|
|
||||||
_context18.t0.strictEqual.call(_context18.t0, _context18.t1, "first sent");
|
|
||||||
|
|
||||||
_context18.t2 = assert;
|
|
||||||
_context18.next = 8;
|
|
||||||
return "middle";
|
|
||||||
|
|
||||||
case 8:
|
|
||||||
_context18.t3 = _context18.sent;
|
|
||||||
|
|
||||||
_context18.t2.strictEqual.call(_context18.t2, _context18.t3, "second sent");
|
|
||||||
|
|
||||||
return _context18.abrupt("return", Promise.reject(returned));
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
case "end":
|
|
||||||
return _context18.stop();
|
|
||||||
}
|
|
||||||
}, _marked5[0], this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var iter = gen();
|
|
||||||
|
|
||||||
return iter.next().then(function (result) {
|
|
||||||
assert.ok(false, "should have yielded a rejected Promise");
|
|
||||||
}, function (error) {
|
|
||||||
assert.strictEqual(error, yielded);
|
|
||||||
return iter.next("first sent");
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.deepEqual(result, {
|
|
||||||
value: "middle",
|
|
||||||
done: false
|
|
||||||
});
|
|
||||||
return iter.next("second sent");
|
|
||||||
}).then(function (result) {
|
|
||||||
assert.ok(false, "should have returned a rejected Promise");
|
|
||||||
}, function (error) {
|
|
||||||
assert.strictEqual(error, returned);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Mocha</title>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<link rel="stylesheet" href="mocha.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="mocha"></div>
|
|
||||||
<script src="mocha.js"></script>
|
|
||||||
<script>mocha.setup('bdd')</script>
|
|
||||||
<script src="tests.browser.js"></script>
|
|
||||||
<script>
|
|
||||||
mocha.run();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
function asdf() {
|
|
||||||
return "no generators or a-s-y-n-c functions to see here";
|
|
||||||
}
|
|
||||||
@ -1,154 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2014, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
|
||||||
* additional grant of patent rights can be found in the PATENTS file in
|
|
||||||
* the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var fs = require("fs");
|
|
||||||
var path = require("path");
|
|
||||||
var semver = require("semver");
|
|
||||||
var spawn = require("child_process").spawn;
|
|
||||||
var regenerator = require("../main");
|
|
||||||
var mochaDir = path.dirname(require.resolve("mocha"));
|
|
||||||
|
|
||||||
function convert(es6File, es5File, callback) {
|
|
||||||
fs.readFile(es6File, "utf-8", function(err, es6) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFile(es5File, regenerator.compile(es6).code, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function bundle(es5Files, browserFile, callback) {
|
|
||||||
var bundle = require("browserify")();
|
|
||||||
es5Files.forEach(bundle.add, bundle);
|
|
||||||
bundle.bundle(function(err, src) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
fs.writeFile(browserFile, src, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var queue = [];
|
|
||||||
function enqueue(cmd, args, quiet) {
|
|
||||||
queue.push({
|
|
||||||
cmd: cmd,
|
|
||||||
args: args || [],
|
|
||||||
quiet: !!quiet
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function flush() {
|
|
||||||
var entry = queue.shift();
|
|
||||||
if (entry) {
|
|
||||||
var cmd = entry.cmd;
|
|
||||||
if (typeof cmd === "function") {
|
|
||||||
cmd.apply(null, entry.args.concat(asyncCallback));
|
|
||||||
} else {
|
|
||||||
spawn(cmd, entry.args, {
|
|
||||||
stdio: [
|
|
||||||
process.stdin,
|
|
||||||
entry.quiet ? "ignore" : process.stdout,
|
|
||||||
process.stderr
|
|
||||||
]
|
|
||||||
}).on("exit", asyncCallback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function asyncCallback(err) {
|
|
||||||
if (err) {
|
|
||||||
console.error("process exited abnormally:", err);
|
|
||||||
process.exit(typeof err === "number" ? err : -1);
|
|
||||||
} else {
|
|
||||||
process.nextTick(flush);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeMochaCopyFunction(fileName) {
|
|
||||||
return function copy(callback) {
|
|
||||||
var src = path.join(mochaDir, fileName);
|
|
||||||
var dst = path.join(__dirname, fileName);
|
|
||||||
fs.unlink(dst, function() {
|
|
||||||
fs.symlink(src, dst, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.gte(process.version, "0.11.2")) {
|
|
||||||
enqueue("mocha", [
|
|
||||||
"--harmony",
|
|
||||||
"--reporter", "spec",
|
|
||||||
"--require", "./runtime",
|
|
||||||
"./test/tests.es6.js"
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
enqueue(convert, [
|
|
||||||
"./test/tests.es6.js",
|
|
||||||
"./test/tests.es5.js"
|
|
||||||
]);
|
|
||||||
|
|
||||||
enqueue(convert, [
|
|
||||||
"./test/async.es6.js",
|
|
||||||
"./test/async.es5.js"
|
|
||||||
]);
|
|
||||||
|
|
||||||
enqueue(makeMochaCopyFunction("mocha.js"));
|
|
||||||
enqueue(makeMochaCopyFunction("mocha.css"));
|
|
||||||
|
|
||||||
// uglify-js does not work properly due to Node 0.11.7 bug.
|
|
||||||
// (https://github.com/joyent/node/issues/6235)
|
|
||||||
if (!semver.eq(process.version, "0.11.7")) {
|
|
||||||
try {
|
|
||||||
require.resolve("browserify"); // Throws if missing.
|
|
||||||
enqueue(bundle, [
|
|
||||||
["./runtime.js",
|
|
||||||
"./test/tests.es5.js",
|
|
||||||
"./test/async.es5.js"],
|
|
||||||
"./test/tests.browser.js"
|
|
||||||
]);
|
|
||||||
} catch (ignored) {
|
|
||||||
console.error("browserify not installed; skipping bundle step");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enqueue("mocha", [
|
|
||||||
"--reporter", "spec",
|
|
||||||
"--require", "./runtime",
|
|
||||||
"./test/tests.es5.js",
|
|
||||||
"./test/async.es5.js",
|
|
||||||
"./test/tests.transform.js"
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Run command-line tool with available options to make sure it works.
|
|
||||||
|
|
||||||
enqueue("./bin/regenerator", [
|
|
||||||
"./test/async.es5.js"
|
|
||||||
], true);
|
|
||||||
|
|
||||||
enqueue("./bin/regenerator", [
|
|
||||||
"--include-runtime",
|
|
||||||
"./test/async.es5.js"
|
|
||||||
], true);
|
|
||||||
|
|
||||||
// Make sure we run the command-line tool on a file that does not need any
|
|
||||||
// transformation, too.
|
|
||||||
|
|
||||||
enqueue("./bin/regenerator", [
|
|
||||||
"./test/nothing-to-transform.js"
|
|
||||||
], true);
|
|
||||||
|
|
||||||
enqueue("./bin/regenerator", [
|
|
||||||
"--include-runtime",
|
|
||||||
"./test/nothing-to-transform.js"
|
|
||||||
], true);
|
|
||||||
|
|
||||||
flush();
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,47 +0,0 @@
|
|||||||
var regenerator = require("..");
|
|
||||||
var babylon = require("babylon");
|
|
||||||
var assert = require("assert");
|
|
||||||
var babel = require("babel-core");
|
|
||||||
var t = require("babel-types");
|
|
||||||
|
|
||||||
describe("_blockHoist nodes", function() {
|
|
||||||
it("should be hoisted to the outer body", function() {
|
|
||||||
var foo;
|
|
||||||
var names = [];
|
|
||||||
var ast = babylon.parse([
|
|
||||||
"function *foo(doNotHoistMe, hoistMe) {",
|
|
||||||
" var sent = yield doNotHoistMe();",
|
|
||||||
" hoistMe();",
|
|
||||||
" names.push(sent);",
|
|
||||||
" return 123;",
|
|
||||||
"}"
|
|
||||||
].join("\n"));
|
|
||||||
|
|
||||||
var hoistMeStmt = ast.program.body[0].body.body[1];
|
|
||||||
t.assertExpressionStatement(hoistMeStmt);
|
|
||||||
t.assertCallExpression(hoistMeStmt.expression);
|
|
||||||
t.assertIdentifier(hoistMeStmt.expression.callee);
|
|
||||||
assert.strictEqual(hoistMeStmt.expression.callee.name, "hoistMe");
|
|
||||||
|
|
||||||
hoistMeStmt._blockHoist = 1;
|
|
||||||
|
|
||||||
eval(babel.transformFromAst(ast, null, { plugins: [regenerator] }).code);
|
|
||||||
|
|
||||||
assert.strictEqual(typeof foo, "function");
|
|
||||||
assert.ok(regeneratorRuntime.isGeneratorFunction(foo));
|
|
||||||
assert.strictEqual(names.length, 0);
|
|
||||||
|
|
||||||
var g = foo(function doNotHoistMe() {
|
|
||||||
names.push("doNotHoistMe");
|
|
||||||
return "yielded";
|
|
||||||
}, function hoistMe() {
|
|
||||||
names.push("hoistMe");
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepEqual(names, ["hoistMe"]);
|
|
||||||
assert.deepEqual(g.next(), { value: "yielded", done: false });
|
|
||||||
assert.deepEqual(names, ["hoistMe", "doNotHoistMe"]);
|
|
||||||
assert.deepEqual(g.next("oyez"), { value: 123, done: true });
|
|
||||||
assert.deepEqual(names, ["hoistMe", "doNotHoistMe", "oyez"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "4.0"
|
|
||||||
- "iojs"
|
|
||||||
- "0.12"
|
|
||||||
- "0.11"
|
|
||||||
- "0.10"
|
|
||||||
- "0.8"
|
|
||||||
before_install:
|
|
||||||
- npm install -g npm@1.4.28
|
|
||||||
sudo: false
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
# Contributing to Regenerator
|
|
||||||
|
|
||||||
Regenerator uses GitHub as its sole source of truth. Everything happens
|
|
||||||
here. Facebook employees who contribute to Regenerator are expected to do
|
|
||||||
so in the same way as everyone else. In other words, this document applies
|
|
||||||
equally to all contributors.
|
|
||||||
|
|
||||||
### `master` is unsafe
|
|
||||||
|
|
||||||
We will do our best to keep `master` in good shape, with tests passing at
|
|
||||||
all times. But in order to move fast, we will make API changes that your
|
|
||||||
application might not be compatible with. We will do our best to
|
|
||||||
communicate these changes and always version appropriately so you can lock
|
|
||||||
into a specific version if need be.
|
|
||||||
|
|
||||||
### Pull Requests
|
|
||||||
|
|
||||||
In case you've never submitted a pull request (PR) via GitHub before,
|
|
||||||
please read [this short
|
|
||||||
tutorial](https://help.github.com/articles/creating-a-pull-request). If
|
|
||||||
you've submitted a PR before, there should be nothing surprising about our
|
|
||||||
procedures for Regenerator.
|
|
||||||
|
|
||||||
*Before* submitting a pull request, please make sure the following is done…
|
|
||||||
|
|
||||||
1. Fork the repo and create your branch from `master`.
|
|
||||||
2. If you've added code that should be tested, add tests!
|
|
||||||
3. Ensure the test suite passes (`npm test`).
|
|
||||||
4. If you haven't already, complete the CLA.
|
|
||||||
5. Submit a pull request via GitHub.
|
|
||||||
6. Check that Travis CI tests pass (pull request turns green).
|
|
||||||
|
|
||||||
### Contributor License Agreement ("CLA")
|
|
||||||
|
|
||||||
In order to accept your pull request, we need you to submit a CLA. You
|
|
||||||
only need to do this once, so if you've done this for another Facebook
|
|
||||||
open source project, you're good to go. If you are submitting a pull
|
|
||||||
request for the first time, just let us know that you have completed the
|
|
||||||
CLA and we can cross-check with your GitHub username.
|
|
||||||
|
|
||||||
Complete your CLA here: <https://code.facebook.com/cla>
|
|
||||||
|
|
||||||
## Bugs
|
|
||||||
|
|
||||||
### Where to Find Known Issues
|
|
||||||
|
|
||||||
We will be using GitHub Issues for all bugs. Before filing a new issue,
|
|
||||||
please try to make sure your problem doesn't already exist. If you think
|
|
||||||
your issue is more general than one that already exists, our preference is
|
|
||||||
still to modify the original issue to reflect the underlying problem more
|
|
||||||
faithfully.
|
|
||||||
|
|
||||||
### Reporting New Issues
|
|
||||||
|
|
||||||
The best way to get a bug fixed is to provide a reduced test case, and the
|
|
||||||
easiest way to reduce a testcase is to edit it in [the
|
|
||||||
sandbox](http://facebook.github.io/regenerator/) until you're satisfied
|
|
||||||
and then click the "report a bug" link (the new issue will be populated
|
|
||||||
automatically with your code).
|
|
||||||
|
|
||||||
### Security Bugs
|
|
||||||
|
|
||||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for
|
|
||||||
the safe disclosure of security bugs. With that in mind, please do not
|
|
||||||
file public issues and go through the process outlined on that page.
|
|
||||||
|
|
||||||
## Coding Style
|
|
||||||
|
|
||||||
* Use semicolons;
|
|
||||||
* Commas last,
|
|
||||||
* 2 spaces for indentation (no tabs).
|
|
||||||
* Prefer `"` over `'`
|
|
||||||
* 80 character line length
|
|
||||||
* Match surrounding coding style.
|
|
||||||
* Less code is better code.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
By contributing to Regenerator, you agree that your contributions will be
|
|
||||||
licensed under the [BSD License](LICENSE).
|
|
||||||
@ -1,74 +1 @@
|
|||||||
regenerator [](https://travis-ci.org/facebook/regenerator)
|
# babel-plugin-transform-regenerator
|
||||||
===
|
|
||||||
|
|
||||||
This package implements a fully-functional source transformation that
|
|
||||||
takes the proposed syntax for generators/`yield` from future versions of
|
|
||||||
JS ([ECMAScript6 or ES6](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts), experimentally implemented in Node.js v0.11) and
|
|
||||||
spits out efficient JS-of-today (ES5) that behaves the same way.
|
|
||||||
|
|
||||||
A small runtime library (less than 1KB compressed) is required to provide the
|
|
||||||
`wrapGenerator` function. You can install it either as a CommonJS module
|
|
||||||
or as a standalone .js file, whichever you prefer.
|
|
||||||
|
|
||||||
Installation
|
|
||||||
---
|
|
||||||
|
|
||||||
From NPM:
|
|
||||||
```sh
|
|
||||||
npm install -g regenerator
|
|
||||||
```
|
|
||||||
|
|
||||||
From GitHub:
|
|
||||||
```sh
|
|
||||||
cd path/to/node_modules
|
|
||||||
git clone git://github.com/facebook/regenerator.git
|
|
||||||
cd regenerator
|
|
||||||
npm install .
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
Usage
|
|
||||||
---
|
|
||||||
|
|
||||||
You have several options for using this module.
|
|
||||||
|
|
||||||
Simplest usage:
|
|
||||||
```sh
|
|
||||||
regenerator es6.js > es5.js # Just the transform.
|
|
||||||
regenerator --include-runtime es6.js > es5.js # Add the runtime too.
|
|
||||||
regenerator src lib # Transform every .js file in src and output to lib.
|
|
||||||
```
|
|
||||||
|
|
||||||
Programmatic usage:
|
|
||||||
```js
|
|
||||||
var es5Source = require("regenerator").compile(es6Source).code;
|
|
||||||
var es5SourceWithRuntime = require("regenerator").compile(es6Source, {
|
|
||||||
includeRuntime: true
|
|
||||||
}).code;
|
|
||||||
```
|
|
||||||
|
|
||||||
Babel plugin:
|
|
||||||
```js
|
|
||||||
var babel = require("babel-core");
|
|
||||||
var code = babel.transform(es6Source, {
|
|
||||||
plugins: [require("generator")]
|
|
||||||
}).code;
|
|
||||||
```
|
|
||||||
|
|
||||||
How can you get involved?
|
|
||||||
---
|
|
||||||
|
|
||||||
The easiest way to get involved is to look for buggy examples using [the
|
|
||||||
sandbox](http://facebook.github.io/regenerator/), and when you find
|
|
||||||
something strange just click the "report a bug" link (the new issue form
|
|
||||||
will be populated automatically with the problematic code).
|
|
||||||
|
|
||||||
Alternatively, you can
|
|
||||||
[fork](https://github.com/facebook/regenerator/fork) the repository,
|
|
||||||
create some failing tests cases in [test/tests.es6.js](test/tests.es6.js),
|
|
||||||
and send pull requests for me to fix.
|
|
||||||
|
|
||||||
If you're feeling especially brave, you are more than welcome to dive into
|
|
||||||
the transformer code and fix the bug(s) yourself, but I must warn you that
|
|
||||||
the code could really benefit from [better implementation
|
|
||||||
comments](https://github.com/facebook/regenerator/issues/7).
|
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
// -*- mode: js -*-
|
|
||||||
|
|
||||||
var compile = require("../main").compile;
|
|
||||||
|
|
||||||
require("commoner").version(
|
|
||||||
require("../package.json").version
|
|
||||||
).resolve(function(id) {
|
|
||||||
return this.readModuleP(id);
|
|
||||||
}).option(
|
|
||||||
"-r, --include-runtime",
|
|
||||||
"Prepend the runtime to the output."
|
|
||||||
).process(function(id, source) {
|
|
||||||
return compile(source, {
|
|
||||||
includeRuntime: this.options.includeRuntime
|
|
||||||
}).code;
|
|
||||||
});
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -8,16 +8,23 @@
|
|||||||
* the same directory.
|
* the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var traverse = require("babel-traverse");
|
"use strict";
|
||||||
var assert = require("assert");
|
|
||||||
var t = require("babel-types");
|
var _Object$keys = require("babel-runtime/core-js/object/keys")["default"];
|
||||||
|
|
||||||
|
var _interopRequireWildcard = require("babel-runtime/helpers/interop-require-wildcard")["default"];
|
||||||
|
|
||||||
|
var _babelTypes = require("babel-types");
|
||||||
|
|
||||||
|
var t = _interopRequireWildcard(_babelTypes);
|
||||||
|
|
||||||
var hasOwn = Object.prototype.hasOwnProperty;
|
var hasOwn = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
// The hoist function takes a FunctionExpression or FunctionDeclaration
|
// The hoist function takes a FunctionExpression or FunctionDeclaration
|
||||||
// and replaces any Declaration nodes in its body with assignments, then
|
// and replaces any Declaration nodes in its body with assignments, then
|
||||||
// returns a VariableDeclaration containing just the names of the removed
|
// returns a VariableDeclaration containing just the names of the removed
|
||||||
// declarations.
|
// declarations.
|
||||||
exports.hoist = function(funPath) {
|
exports.hoist = function (funPath) {
|
||||||
t.assertFunction(funPath.node);
|
t.assertFunction(funPath.node);
|
||||||
|
|
||||||
var vars = {};
|
var vars = {};
|
||||||
@ -27,30 +34,26 @@ exports.hoist = function(funPath) {
|
|||||||
// TODO assert.equal(vdec.kind, "var");
|
// TODO assert.equal(vdec.kind, "var");
|
||||||
var exprs = [];
|
var exprs = [];
|
||||||
|
|
||||||
vdec.declarations.forEach(function(dec) {
|
vdec.declarations.forEach(function (dec) {
|
||||||
vars[dec.id.name] = dec.id;
|
vars[dec.id.name] = dec.id;
|
||||||
|
|
||||||
if (dec.init) {
|
if (dec.init) {
|
||||||
exprs.push(t.assignmentExpression(
|
exprs.push(t.assignmentExpression("=", dec.id, dec.init));
|
||||||
"=", dec.id, dec.init
|
|
||||||
));
|
|
||||||
} else if (includeIdentifiers) {
|
} else if (includeIdentifiers) {
|
||||||
exprs.push(dec.id);
|
exprs.push(dec.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (exprs.length === 0)
|
if (exprs.length === 0) return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
if (exprs.length === 1)
|
if (exprs.length === 1) return exprs[0];
|
||||||
return exprs[0];
|
|
||||||
|
|
||||||
return t.sequenceExpression(exprs);
|
return t.sequenceExpression(exprs);
|
||||||
}
|
}
|
||||||
|
|
||||||
funPath.get("body").traverse({
|
funPath.get("body").traverse({
|
||||||
VariableDeclaration: {
|
VariableDeclaration: {
|
||||||
exit: function(path) {
|
exit: function exit(path) {
|
||||||
var expr = varDeclToExpr(path.node, false);
|
var expr = varDeclToExpr(path.node, false);
|
||||||
if (expr === null) {
|
if (expr === null) {
|
||||||
path.remove();
|
path.remove();
|
||||||
@ -66,38 +69,25 @@ exports.hoist = function(funPath) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ForStatement: function(path) {
|
ForStatement: function ForStatement(path) {
|
||||||
var init = path.node.init;
|
var init = path.node.init;
|
||||||
if (t.isVariableDeclaration(init)) {
|
if (t.isVariableDeclaration(init)) {
|
||||||
path.get("init").replaceWith(varDeclToExpr(init, false));
|
path.get("init").replaceWith(varDeclToExpr(init, false));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ForXStatement: function(path) {
|
ForXStatement: function ForXStatement(path) {
|
||||||
var left = path.get("left");
|
var left = path.get("left");
|
||||||
if (left.isVariableDeclaration()) {
|
if (left.isVariableDeclaration()) {
|
||||||
left.replaceWith(varDeclToExpr(left.node, true));
|
left.replaceWith(varDeclToExpr(left.node, true));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
FunctionDeclaration: function(path) {
|
FunctionDeclaration: function FunctionDeclaration(path) {
|
||||||
var node = path.node;
|
var node = path.node;
|
||||||
vars[node.id.name] = node.id;
|
vars[node.id.name] = node.id;
|
||||||
|
|
||||||
var parentNode = path.parent.node;
|
var assignment = t.expressionStatement(t.assignmentExpression("=", node.id, t.functionExpression(node.id, node.params, node.body, node.generator, node.expression)));
|
||||||
var assignment = t.expressionStatement(
|
|
||||||
t.assignmentExpression(
|
|
||||||
"=",
|
|
||||||
node.id,
|
|
||||||
t.functionExpression(
|
|
||||||
node.id,
|
|
||||||
node.params,
|
|
||||||
node.body,
|
|
||||||
node.generator,
|
|
||||||
node.expression
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (path.parentPath.isBlockStatement()) {
|
if (path.parentPath.isBlockStatement()) {
|
||||||
// Insert the assignment form before the first statement in the
|
// Insert the assignment form before the first statement in the
|
||||||
@ -118,14 +108,14 @@ exports.hoist = function(funPath) {
|
|||||||
path.skip();
|
path.skip();
|
||||||
},
|
},
|
||||||
|
|
||||||
FunctionExpression: function(path) {
|
FunctionExpression: function FunctionExpression(path) {
|
||||||
// Don't descend into nested function expressions.
|
// Don't descend into nested function expressions.
|
||||||
path.skip();
|
path.skip();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var paramNames = {};
|
var paramNames = {};
|
||||||
funPath.get("params").forEach(function(paramPath) {
|
funPath.get("params").forEach(function (paramPath) {
|
||||||
var param = paramPath.node;
|
var param = paramPath.node;
|
||||||
if (t.isIdentifier(param)) {
|
if (t.isIdentifier(param)) {
|
||||||
paramNames[param.name] = param;
|
paramNames[param.name] = param;
|
||||||
@ -137,7 +127,7 @@ exports.hoist = function(funPath) {
|
|||||||
|
|
||||||
var declarations = [];
|
var declarations = [];
|
||||||
|
|
||||||
Object.keys(vars).forEach(function(name) {
|
_Object$keys(vars).forEach(function (name) {
|
||||||
if (!hasOwn.call(paramNames, name)) {
|
if (!hasOwn.call(paramNames, name)) {
|
||||||
declarations.push(t.variableDeclarator(vars[name], null));
|
declarations.push(t.variableDeclarator(vars[name], null));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,13 +8,24 @@
|
|||||||
* the same directory.
|
* the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var assert = require("assert");
|
"use strict";
|
||||||
var t = require("babel-types");
|
|
||||||
var inherits = require("util").inherits;
|
var _interopRequireDefault = require("babel-runtime/helpers/interop-require-default")["default"];
|
||||||
var hasOwn = Object.prototype.hasOwnProperty;
|
|
||||||
|
var _interopRequireWildcard = require("babel-runtime/helpers/interop-require-wildcard")["default"];
|
||||||
|
|
||||||
|
var _assert = require("assert");
|
||||||
|
|
||||||
|
var _assert2 = _interopRequireDefault(_assert);
|
||||||
|
|
||||||
|
var _babelTypes = require("babel-types");
|
||||||
|
|
||||||
|
var t = _interopRequireWildcard(_babelTypes);
|
||||||
|
|
||||||
|
var _util = require("util");
|
||||||
|
|
||||||
function Entry() {
|
function Entry() {
|
||||||
assert.ok(this instanceof Entry);
|
_assert2["default"].ok(this instanceof Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
function FunctionEntry(returnLoc) {
|
function FunctionEntry(returnLoc) {
|
||||||
@ -23,7 +34,7 @@ function FunctionEntry(returnLoc) {
|
|||||||
this.returnLoc = returnLoc;
|
this.returnLoc = returnLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(FunctionEntry, Entry);
|
_util.inherits(FunctionEntry, Entry);
|
||||||
exports.FunctionEntry = FunctionEntry;
|
exports.FunctionEntry = FunctionEntry;
|
||||||
|
|
||||||
function LoopEntry(breakLoc, continueLoc, label) {
|
function LoopEntry(breakLoc, continueLoc, label) {
|
||||||
@ -43,7 +54,7 @@ function LoopEntry(breakLoc, continueLoc, label) {
|
|||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(LoopEntry, Entry);
|
_util.inherits(LoopEntry, Entry);
|
||||||
exports.LoopEntry = LoopEntry;
|
exports.LoopEntry = LoopEntry;
|
||||||
|
|
||||||
function SwitchEntry(breakLoc) {
|
function SwitchEntry(breakLoc) {
|
||||||
@ -52,7 +63,7 @@ function SwitchEntry(breakLoc) {
|
|||||||
this.breakLoc = breakLoc;
|
this.breakLoc = breakLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(SwitchEntry, Entry);
|
_util.inherits(SwitchEntry, Entry);
|
||||||
exports.SwitchEntry = SwitchEntry;
|
exports.SwitchEntry = SwitchEntry;
|
||||||
|
|
||||||
function TryEntry(firstLoc, catchEntry, finallyEntry) {
|
function TryEntry(firstLoc, catchEntry, finallyEntry) {
|
||||||
@ -61,26 +72,26 @@ function TryEntry(firstLoc, catchEntry, finallyEntry) {
|
|||||||
t.assertLiteral(firstLoc);
|
t.assertLiteral(firstLoc);
|
||||||
|
|
||||||
if (catchEntry) {
|
if (catchEntry) {
|
||||||
assert.ok(catchEntry instanceof CatchEntry);
|
_assert2["default"].ok(catchEntry instanceof CatchEntry);
|
||||||
} else {
|
} else {
|
||||||
catchEntry = null;
|
catchEntry = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finallyEntry) {
|
if (finallyEntry) {
|
||||||
assert.ok(finallyEntry instanceof FinallyEntry);
|
_assert2["default"].ok(finallyEntry instanceof FinallyEntry);
|
||||||
} else {
|
} else {
|
||||||
finallyEntry = null;
|
finallyEntry = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to have one or the other (or both).
|
// Have to have one or the other (or both).
|
||||||
assert.ok(catchEntry || finallyEntry);
|
_assert2["default"].ok(catchEntry || finallyEntry);
|
||||||
|
|
||||||
this.firstLoc = firstLoc;
|
this.firstLoc = firstLoc;
|
||||||
this.catchEntry = catchEntry;
|
this.catchEntry = catchEntry;
|
||||||
this.finallyEntry = finallyEntry;
|
this.finallyEntry = finallyEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(TryEntry, Entry);
|
_util.inherits(TryEntry, Entry);
|
||||||
exports.TryEntry = TryEntry;
|
exports.TryEntry = TryEntry;
|
||||||
|
|
||||||
function CatchEntry(firstLoc, paramId) {
|
function CatchEntry(firstLoc, paramId) {
|
||||||
@ -93,7 +104,7 @@ function CatchEntry(firstLoc, paramId) {
|
|||||||
this.paramId = paramId;
|
this.paramId = paramId;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(CatchEntry, Entry);
|
_util.inherits(CatchEntry, Entry);
|
||||||
exports.CatchEntry = CatchEntry;
|
exports.CatchEntry = CatchEntry;
|
||||||
|
|
||||||
function FinallyEntry(firstLoc, afterLoc) {
|
function FinallyEntry(firstLoc, afterLoc) {
|
||||||
@ -104,7 +115,7 @@ function FinallyEntry(firstLoc, afterLoc) {
|
|||||||
this.afterLoc = afterLoc;
|
this.afterLoc = afterLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(FinallyEntry, Entry);
|
_util.inherits(FinallyEntry, Entry);
|
||||||
exports.FinallyEntry = FinallyEntry;
|
exports.FinallyEntry = FinallyEntry;
|
||||||
|
|
||||||
function LabeledEntry(breakLoc, label) {
|
function LabeledEntry(breakLoc, label) {
|
||||||
@ -117,14 +128,14 @@ function LabeledEntry(breakLoc, label) {
|
|||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(LabeledEntry, Entry);
|
_util.inherits(LabeledEntry, Entry);
|
||||||
exports.LabeledEntry = LabeledEntry;
|
exports.LabeledEntry = LabeledEntry;
|
||||||
|
|
||||||
function LeapManager(emitter) {
|
function LeapManager(emitter) {
|
||||||
assert.ok(this instanceof LeapManager);
|
_assert2["default"].ok(this instanceof LeapManager);
|
||||||
|
|
||||||
var Emitter = require("./emit").Emitter;
|
var Emitter = require("./emit").Emitter;
|
||||||
assert.ok(emitter instanceof Emitter);
|
_assert2["default"].ok(emitter instanceof Emitter);
|
||||||
|
|
||||||
this.emitter = emitter;
|
this.emitter = emitter;
|
||||||
this.entryStack = [new FunctionEntry(emitter.finalLoc)];
|
this.entryStack = [new FunctionEntry(emitter.finalLoc)];
|
||||||
@ -133,25 +144,24 @@ function LeapManager(emitter) {
|
|||||||
var LMp = LeapManager.prototype;
|
var LMp = LeapManager.prototype;
|
||||||
exports.LeapManager = LeapManager;
|
exports.LeapManager = LeapManager;
|
||||||
|
|
||||||
LMp.withEntry = function(entry, callback) {
|
LMp.withEntry = function (entry, callback) {
|
||||||
assert.ok(entry instanceof Entry);
|
_assert2["default"].ok(entry instanceof Entry);
|
||||||
this.entryStack.push(entry);
|
this.entryStack.push(entry);
|
||||||
try {
|
try {
|
||||||
callback.call(this.emitter);
|
callback.call(this.emitter);
|
||||||
} finally {
|
} finally {
|
||||||
var popped = this.entryStack.pop();
|
var popped = this.entryStack.pop();
|
||||||
assert.strictEqual(popped, entry);
|
_assert2["default"].strictEqual(popped, entry);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LMp._findLeapLocation = function(property, label) {
|
LMp._findLeapLocation = function (property, label) {
|
||||||
for (var i = this.entryStack.length - 1; i >= 0; --i) {
|
for (var i = this.entryStack.length - 1; i >= 0; --i) {
|
||||||
var entry = this.entryStack[i];
|
var entry = this.entryStack[i];
|
||||||
var loc = entry[property];
|
var loc = entry[property];
|
||||||
if (loc) {
|
if (loc) {
|
||||||
if (label) {
|
if (label) {
|
||||||
if (entry.label &&
|
if (entry.label && entry.label.name === label.name) {
|
||||||
entry.label.name === label.name) {
|
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
} else if (entry instanceof LabeledEntry) {
|
} else if (entry instanceof LabeledEntry) {
|
||||||
@ -166,10 +176,10 @@ LMp._findLeapLocation = function(property, label) {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
LMp.getBreakLoc = function(label) {
|
LMp.getBreakLoc = function (label) {
|
||||||
return this._findLeapLocation("breakLoc", label);
|
return this._findLeapLocation("breakLoc", label);
|
||||||
};
|
};
|
||||||
|
|
||||||
LMp.getContinueLoc = function(label) {
|
LMp.getContinueLoc = function (label) {
|
||||||
return this._findLeapLocation("continueLoc", label);
|
return this._findLeapLocation("continueLoc", label);
|
||||||
};
|
};
|
||||||
@ -8,9 +8,22 @@
|
|||||||
* the same directory.
|
* the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var assert = require("assert");
|
"use strict";
|
||||||
|
|
||||||
|
var _interopRequireDefault = require("babel-runtime/helpers/interop-require-default")["default"];
|
||||||
|
|
||||||
|
var _interopRequireWildcard = require("babel-runtime/helpers/interop-require-wildcard")["default"];
|
||||||
|
|
||||||
|
var _assert = require("assert");
|
||||||
|
|
||||||
|
var _assert2 = _interopRequireDefault(_assert);
|
||||||
|
|
||||||
|
var _babelTypes = require("babel-types");
|
||||||
|
|
||||||
|
var t = _interopRequireWildcard(_babelTypes);
|
||||||
|
|
||||||
var m = require("private").makeAccessor();
|
var m = require("private").makeAccessor();
|
||||||
var t = require("babel-types");
|
|
||||||
var hasOwn = Object.prototype.hasOwnProperty;
|
var hasOwn = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
function makePredicate(propertyName, knownTypes) {
|
function makePredicate(propertyName, knownTypes) {
|
||||||
@ -26,7 +39,7 @@ function makePredicate(propertyName, knownTypes) {
|
|||||||
} else if (Array.isArray(child)) {
|
} else if (Array.isArray(child)) {
|
||||||
child.some(check);
|
child.some(check);
|
||||||
} else if (t.isNode(child)) {
|
} else if (t.isNode(child)) {
|
||||||
assert.strictEqual(result, false);
|
_assert2["default"].strictEqual(result, false);
|
||||||
result = predicate(child);
|
result = predicate(child);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -48,16 +61,13 @@ function makePredicate(propertyName, knownTypes) {
|
|||||||
t.assertNode(node);
|
t.assertNode(node);
|
||||||
|
|
||||||
var meta = m(node);
|
var meta = m(node);
|
||||||
if (hasOwn.call(meta, propertyName))
|
if (hasOwn.call(meta, propertyName)) return meta[propertyName];
|
||||||
return meta[propertyName];
|
|
||||||
|
|
||||||
// Certain types are "opaque," which means they have no side
|
// Certain types are "opaque," which means they have no side
|
||||||
// effects or leaps and we don't care about their subexpressions.
|
// effects or leaps and we don't care about their subexpressions.
|
||||||
if (hasOwn.call(opaqueTypes, node.type))
|
if (hasOwn.call(opaqueTypes, node.type)) return meta[propertyName] = false;
|
||||||
return meta[propertyName] = false;
|
|
||||||
|
|
||||||
if (hasOwn.call(knownTypes, node.type))
|
if (hasOwn.call(knownTypes, node.type)) return meta[propertyName] = true;
|
||||||
return meta[propertyName] = true;
|
|
||||||
|
|
||||||
return meta[propertyName] = onlyChildren(node);
|
return meta[propertyName] = onlyChildren(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,16 +8,22 @@
|
|||||||
* the same directory.
|
* the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var t = require("babel-types");
|
"use strict";
|
||||||
|
|
||||||
exports.runtimeProperty = function(name) {
|
var _interopRequireWildcard = require("babel-runtime/helpers/interop-require-wildcard")["default"];
|
||||||
return t.memberExpression(
|
|
||||||
t.identifier("regeneratorRuntime"),
|
|
||||||
t.identifier(name),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.isReference = function(path) {
|
exports.__esModule = true;
|
||||||
|
exports.runtimeProperty = runtimeProperty;
|
||||||
|
exports.isReference = isReference;
|
||||||
|
|
||||||
|
var _babelTypes = require("babel-types");
|
||||||
|
|
||||||
|
var t = _interopRequireWildcard(_babelTypes);
|
||||||
|
|
||||||
|
function runtimeProperty(name) {
|
||||||
|
return t.memberExpression(t.identifier("regeneratorRuntime"), t.identifier(name), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isReference(path) {
|
||||||
return path.isReferenced() || path.parentPath.isAssignmentExpression({ left: path.node });
|
return path.isReferenced() || path.parentPath.isAssignmentExpression({ left: path.node });
|
||||||
};
|
}
|
||||||
@ -8,20 +8,33 @@
|
|||||||
* the same directory.
|
* the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var traverse = require("babel-traverse");
|
"use strict";
|
||||||
var babylon = require("babylon");
|
|
||||||
var assert = require("assert");
|
var _interopRequireDefault = require("babel-runtime/helpers/interop-require-default")["default"];
|
||||||
var fs = require("fs");
|
|
||||||
var t = require("babel-types");
|
var _interopRequireWildcard = require("babel-runtime/helpers/interop-require-wildcard")["default"];
|
||||||
var hoist = require("./hoist").hoist;
|
|
||||||
var Emitter = require("./emit").Emitter;
|
var _assert = require("assert");
|
||||||
var util = require("./util");
|
|
||||||
var runtimeProperty = util.runtimeProperty;
|
var _assert2 = _interopRequireDefault(_assert);
|
||||||
|
|
||||||
|
var _babelTypes = require("babel-types");
|
||||||
|
|
||||||
|
var t = _interopRequireWildcard(_babelTypes);
|
||||||
|
|
||||||
|
var _hoist = require("./hoist");
|
||||||
|
|
||||||
|
var _emit = require("./emit");
|
||||||
|
|
||||||
|
var _util = require("./util");
|
||||||
|
|
||||||
|
var util = _interopRequireWildcard(_util);
|
||||||
|
|
||||||
var getMarkInfo = require("private").makeAccessor();
|
var getMarkInfo = require("private").makeAccessor();
|
||||||
|
|
||||||
exports.visitor = {
|
exports.visitor = {
|
||||||
Function: {
|
Function: {
|
||||||
exit: function(path, state) {
|
exit: function exit(path, state) {
|
||||||
var node = path.node;
|
var node = path.node;
|
||||||
|
|
||||||
if (node.generator) {
|
if (node.generator) {
|
||||||
@ -43,9 +56,7 @@ exports.visitor = {
|
|||||||
if (node.expression) {
|
if (node.expression) {
|
||||||
// Transform expression lambdas into normal functions.
|
// Transform expression lambdas into normal functions.
|
||||||
node.expression = false;
|
node.expression = false;
|
||||||
node.body = t.blockStatement([
|
node.body = t.blockStatement([t.returnStatement(node.body)]);
|
||||||
t.returnStatement(node.body)
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.async) {
|
if (node.async) {
|
||||||
@ -56,7 +67,7 @@ exports.visitor = {
|
|||||||
var outerBody = [];
|
var outerBody = [];
|
||||||
var innerBody = [];
|
var innerBody = [];
|
||||||
|
|
||||||
bodyBlockPath.get("body").forEach(function(childPath) {
|
bodyBlockPath.get("body").forEach(function (childPath) {
|
||||||
var node = childPath.node;
|
var node = childPath.node;
|
||||||
if (node && node._blockHoist != null) {
|
if (node && node._blockHoist != null) {
|
||||||
outerBody.push(node);
|
outerBody.push(node);
|
||||||
@ -82,41 +93,33 @@ exports.visitor = {
|
|||||||
|
|
||||||
// Turn all declarations into vars, and replace the original
|
// Turn all declarations into vars, and replace the original
|
||||||
// declarations with equivalent assignment expressions.
|
// declarations with equivalent assignment expressions.
|
||||||
var vars = hoist(path);
|
var vars = _hoist.hoist(path);
|
||||||
|
|
||||||
var didRenameArguments = renameArguments(path, argsId);
|
var didRenameArguments = renameArguments(path, argsId);
|
||||||
if (didRenameArguments) {
|
if (didRenameArguments) {
|
||||||
vars = vars || t.variableDeclaration("var", []);
|
vars = vars || t.variableDeclaration("var", []);
|
||||||
vars.declarations.push(t.variableDeclarator(
|
vars.declarations.push(t.variableDeclarator(argsId, t.identifier("arguments")));
|
||||||
argsId, t.identifier("arguments")
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var emitter = new Emitter(contextId);
|
var emitter = new _emit.Emitter(contextId);
|
||||||
emitter.explode(path.get("body"));
|
emitter.explode(path.get("body"));
|
||||||
|
|
||||||
if (vars && vars.declarations.length > 0) {
|
if (vars && vars.declarations.length > 0) {
|
||||||
outerBody.push(vars);
|
outerBody.push(vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
var wrapArgs = [
|
var wrapArgs = [emitter.getContextFunction(innerFnId),
|
||||||
emitter.getContextFunction(innerFnId),
|
|
||||||
// Async functions that are not generators don't care about the
|
// Async functions that are not generators don't care about the
|
||||||
// outer function because they don't need it to be marked and don't
|
// outer function because they don't need it to be marked and don't
|
||||||
// inherit from its .prototype.
|
// inherit from its .prototype.
|
||||||
node.generator ? outerFnExpr : t.nullLiteral(),
|
node.generator ? outerFnExpr : t.nullLiteral(), t.thisExpression()];
|
||||||
t.thisExpression()
|
|
||||||
];
|
|
||||||
|
|
||||||
var tryLocsList = emitter.getTryLocsList();
|
var tryLocsList = emitter.getTryLocsList();
|
||||||
if (tryLocsList) {
|
if (tryLocsList) {
|
||||||
wrapArgs.push(tryLocsList);
|
wrapArgs.push(tryLocsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
var wrapCall = t.callExpression(
|
var wrapCall = t.callExpression(util.runtimeProperty(node.async ? "async" : "wrap"), wrapArgs);
|
||||||
runtimeProperty(node.async ? "async" : "wrap"),
|
|
||||||
wrapArgs
|
|
||||||
);
|
|
||||||
|
|
||||||
outerBody.push(t.returnStatement(wrapCall));
|
outerBody.push(t.returnStatement(wrapCall));
|
||||||
node.body = t.blockStatement(outerBody);
|
node.body = t.blockStatement(outerBody);
|
||||||
@ -130,9 +133,8 @@ exports.visitor = {
|
|||||||
node.async = false;
|
node.async = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wasGeneratorFunction &&
|
if (wasGeneratorFunction && t.isExpression(node)) {
|
||||||
t.isExpression(node)) {
|
path.replaceWith(t.callExpression(util.runtimeProperty("mark"), [node]));
|
||||||
path.replaceWith(t.callExpression(runtimeProperty("mark"), [node]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,40 +166,22 @@ function getOuterFnExpr(funPath) {
|
|||||||
var index = funDeclIdArray.elements.length;
|
var index = funDeclIdArray.elements.length;
|
||||||
funDeclIdArray.elements.push(node.id);
|
funDeclIdArray.elements.push(node.id);
|
||||||
|
|
||||||
return t.memberExpression(
|
return t.memberExpression(markedArray, t.numericLiteral(index), true);
|
||||||
markedArray,
|
|
||||||
t.numericLiteral(index),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.id || (
|
return node.id || (node.id = funPath.scope.parent.generateUidIdentifier("callee"));
|
||||||
node.id = funPath.scope.parent.generateUidIdentifier("callee")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRuntimeMarkDecl(blockPath) {
|
function getRuntimeMarkDecl(blockPath) {
|
||||||
var block = blockPath.node;
|
var block = blockPath.node;
|
||||||
assert.ok(Array.isArray(block.body));
|
_assert2["default"].ok(Array.isArray(block.body));
|
||||||
|
|
||||||
var info = getMarkInfo(block);
|
var info = getMarkInfo(block);
|
||||||
if (info.decl) {
|
if (info.decl) {
|
||||||
return info.decl;
|
return info.decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.decl = t.variableDeclaration("var", [
|
info.decl = t.variableDeclaration("var", [t.variableDeclarator(blockPath.scope.generateUidIdentifier("marked"), t.callExpression(t.memberExpression(t.arrayExpression([]), t.identifier("map"), false), [util.runtimeProperty("mark")]))]);
|
||||||
t.variableDeclarator(
|
|
||||||
blockPath.scope.generateUidIdentifier("marked"),
|
|
||||||
t.callExpression(
|
|
||||||
t.memberExpression(
|
|
||||||
t.arrayExpression([]),
|
|
||||||
t.identifier("map"),
|
|
||||||
false
|
|
||||||
),
|
|
||||||
[runtimeProperty("mark")]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
|
|
||||||
blockPath.unshiftContainer("body", info.decl);
|
blockPath.unshiftContainer("body", info.decl);
|
||||||
|
|
||||||
@ -220,11 +204,11 @@ function renameArguments(funcPath, argsId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var argumentsVisitor = {
|
var argumentsVisitor = {
|
||||||
"FunctionExpression|FunctionDeclaration": function(path) {
|
"FunctionExpression|FunctionDeclaration": function FunctionExpressionFunctionDeclaration(path) {
|
||||||
path.skip();
|
path.skip();
|
||||||
},
|
},
|
||||||
|
|
||||||
Identifier: function(path, state) {
|
Identifier: function Identifier(path, state) {
|
||||||
if (path.node.name === "arguments" && util.isReference(path)) {
|
if (path.node.name === "arguments" && util.isReference(path)) {
|
||||||
path.replaceWith(state.argsId);
|
path.replaceWith(state.argsId);
|
||||||
state.didRenameArguments = true;
|
state.didRenameArguments = true;
|
||||||
@ -233,23 +217,17 @@ var argumentsVisitor = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var awaitVisitor = {
|
var awaitVisitor = {
|
||||||
Function: function(path) {
|
Function: function Function(path) {
|
||||||
path.skip(); // Don't descend into nested function scopes.
|
path.skip(); // Don't descend into nested function scopes.
|
||||||
},
|
},
|
||||||
|
|
||||||
AwaitExpression: function(path) {
|
AwaitExpression: function AwaitExpression(path) {
|
||||||
// Convert await and await* expressions to yield expressions.
|
// Convert await and await* expressions to yield expressions.
|
||||||
var argument = path.node.argument;
|
var argument = path.node.argument;
|
||||||
|
|
||||||
// Transforming `await x` to `yield regeneratorRuntime.awrap(x)`
|
// Transforming `await x` to `yield regeneratorRuntime.awrap(x)`
|
||||||
// causes the argument to be wrapped in such a way that the runtime
|
// causes the argument to be wrapped in such a way that the runtime
|
||||||
// can distinguish between awaited and merely yielded values.
|
// can distinguish between awaited and merely yielded values.
|
||||||
path.replaceWith(t.yieldExpression(
|
path.replaceWith(t.yieldExpression(t.callExpression(util.runtimeProperty("awrap"), [argument]), false));
|
||||||
t.callExpression(
|
|
||||||
runtimeProperty("awrap"),
|
|
||||||
[argument]
|
|
||||||
),
|
|
||||||
false
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2014, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
|
||||||
* additional grant of patent rights can be found in the PATENTS file in
|
|
||||||
* the same directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var asyncFunctionSyntax = require("babel-plugin-syntax-async-functions");
|
|
||||||
var blockScopingPlugin = require("babel-plugin-transform-es2015-block-scoping");
|
|
||||||
var forOfPlugin = require("babel-plugin-transform-es2015-for-of");
|
|
||||||
var babel = require("babel-core");
|
|
||||||
|
|
||||||
var regenerator = module.exports = function() {
|
|
||||||
return require("./lib/visit");
|
|
||||||
};
|
|
||||||
|
|
||||||
regenerator.compile = function(code, opts) {
|
|
||||||
// todo: includeRuntime
|
|
||||||
return babel.transform(code, buildBabelOptions(opts));
|
|
||||||
};
|
|
||||||
|
|
||||||
regenerator.transform = function (ast, opts) {
|
|
||||||
return babel.transformFromAst(ast, null, buildBabelOptions(opts));
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildBabelOptions(opts) {
|
|
||||||
return {
|
|
||||||
plugins: [regenerator, blockScopingPlugin, asyncFunctionSyntax, forOfPlugin],
|
|
||||||
sourceType: "script"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,32 +1,10 @@
|
|||||||
{
|
{
|
||||||
"author": "Ben Newman <bn@cs.stanford.edu>",
|
|
||||||
"name": "babel-plugin-transform-regenerator",
|
"name": "babel-plugin-transform-regenerator",
|
||||||
"description": "Source transformer enabling ECMAScript 6 generator functions (yield) in JavaScript-of-today (ES5)",
|
"author": "Ben Newman <bn@cs.stanford.edu>",
|
||||||
"keywords": [
|
"description": "",
|
||||||
"generator",
|
|
||||||
"yield",
|
|
||||||
"coroutine",
|
|
||||||
"rewriting",
|
|
||||||
"transformation",
|
|
||||||
"syntax",
|
|
||||||
"codegen",
|
|
||||||
"rewriting",
|
|
||||||
"refactoring",
|
|
||||||
"transpiler",
|
|
||||||
"desugaring",
|
|
||||||
"ES6"
|
|
||||||
],
|
|
||||||
"version": "6.0.18",
|
"version": "6.0.18",
|
||||||
"homepage": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-regenerator",
|
"homepage": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-regenerator",
|
||||||
"repository": {
|
"main": "lib/index.js",
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/facebook/regenerator.git"
|
|
||||||
},
|
|
||||||
"main": "main.js",
|
|
||||||
"bin": "bin/regenerator",
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test/run.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commoner": "~0.10.3",
|
"commoner": "~0.10.3",
|
||||||
"babel-plugin-transform-es2015-block-scoping": "^6.0.18",
|
"babel-plugin-transform-es2015-block-scoping": "^6.0.18",
|
||||||
@ -39,13 +17,5 @@
|
|||||||
"private": "~0.1.5",
|
"private": "~0.1.5",
|
||||||
"through": "~2.3.8"
|
"through": "~2.3.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"license": "BSD"
|
||||||
"mocha": "~2.3.3",
|
|
||||||
"promise": "~7.0.4",
|
|
||||||
"semver": "~5.0.3"
|
|
||||||
},
|
|
||||||
"license": "BSD",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
1181
packages/babel-plugin-transform-regenerator/src/emit.js
Normal file
1181
packages/babel-plugin-transform-regenerator/src/emit.js
Normal file
File diff suppressed because it is too large
Load Diff
148
packages/babel-plugin-transform-regenerator/src/hoist.js
Normal file
148
packages/babel-plugin-transform-regenerator/src/hoist.js
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
||||||
|
* additional grant of patent rights can be found in the PATENTS file in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as t from "babel-types";
|
||||||
|
let hasOwn = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
|
// The hoist function takes a FunctionExpression or FunctionDeclaration
|
||||||
|
// and replaces any Declaration nodes in its body with assignments, then
|
||||||
|
// returns a VariableDeclaration containing just the names of the removed
|
||||||
|
// declarations.
|
||||||
|
exports.hoist = function(funPath) {
|
||||||
|
t.assertFunction(funPath.node);
|
||||||
|
|
||||||
|
let vars = {};
|
||||||
|
|
||||||
|
function varDeclToExpr(vdec, includeIdentifiers) {
|
||||||
|
t.assertVariableDeclaration(vdec);
|
||||||
|
// TODO assert.equal(vdec.kind, "var");
|
||||||
|
let exprs = [];
|
||||||
|
|
||||||
|
vdec.declarations.forEach(function(dec) {
|
||||||
|
vars[dec.id.name] = dec.id;
|
||||||
|
|
||||||
|
if (dec.init) {
|
||||||
|
exprs.push(t.assignmentExpression(
|
||||||
|
"=", dec.id, dec.init
|
||||||
|
));
|
||||||
|
} else if (includeIdentifiers) {
|
||||||
|
exprs.push(dec.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (exprs.length === 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (exprs.length === 1)
|
||||||
|
return exprs[0];
|
||||||
|
|
||||||
|
return t.sequenceExpression(exprs);
|
||||||
|
}
|
||||||
|
|
||||||
|
funPath.get("body").traverse({
|
||||||
|
VariableDeclaration: {
|
||||||
|
exit: function(path) {
|
||||||
|
let expr = varDeclToExpr(path.node, false);
|
||||||
|
if (expr === null) {
|
||||||
|
path.remove();
|
||||||
|
} else {
|
||||||
|
// We don't need to traverse this expression any further because
|
||||||
|
// there can't be any new declarations inside an expression.
|
||||||
|
path.replaceWith(t.expressionStatement(expr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the original node has been either removed or replaced,
|
||||||
|
// avoid traversing it any further.
|
||||||
|
path.skip();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ForStatement: function(path) {
|
||||||
|
let init = path.node.init;
|
||||||
|
if (t.isVariableDeclaration(init)) {
|
||||||
|
path.get("init").replaceWith(varDeclToExpr(init, false));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ForXStatement: function(path) {
|
||||||
|
let left = path.get("left");
|
||||||
|
if (left.isVariableDeclaration()) {
|
||||||
|
left.replaceWith(varDeclToExpr(left.node, true));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
FunctionDeclaration: function(path) {
|
||||||
|
let node = path.node;
|
||||||
|
vars[node.id.name] = node.id;
|
||||||
|
|
||||||
|
let assignment = t.expressionStatement(
|
||||||
|
t.assignmentExpression(
|
||||||
|
"=",
|
||||||
|
node.id,
|
||||||
|
t.functionExpression(
|
||||||
|
node.id,
|
||||||
|
node.params,
|
||||||
|
node.body,
|
||||||
|
node.generator,
|
||||||
|
node.expression
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (path.parentPath.isBlockStatement()) {
|
||||||
|
// Insert the assignment form before the first statement in the
|
||||||
|
// enclosing block.
|
||||||
|
path.parentPath.unshiftContainer("body", assignment);
|
||||||
|
|
||||||
|
// Remove the function declaration now that we've inserted the
|
||||||
|
// equivalent assignment form at the beginning of the block.
|
||||||
|
path.remove();
|
||||||
|
} else {
|
||||||
|
// If the parent node is not a block statement, then we can just
|
||||||
|
// replace the declaration with the equivalent assignment form
|
||||||
|
// without worrying about hoisting it.
|
||||||
|
path.replaceWith(assignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't hoist variables out of inner functions.
|
||||||
|
path.skip();
|
||||||
|
},
|
||||||
|
|
||||||
|
FunctionExpression: function(path) {
|
||||||
|
// Don't descend into nested function expressions.
|
||||||
|
path.skip();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let paramNames = {};
|
||||||
|
funPath.get("params").forEach(function(paramPath) {
|
||||||
|
let param = paramPath.node;
|
||||||
|
if (t.isIdentifier(param)) {
|
||||||
|
paramNames[param.name] = param;
|
||||||
|
} else {
|
||||||
|
// Variables declared by destructuring parameter patterns will be
|
||||||
|
// harmlessly re-declared.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let declarations = [];
|
||||||
|
|
||||||
|
Object.keys(vars).forEach(function(name) {
|
||||||
|
if (!hasOwn.call(paramNames, name)) {
|
||||||
|
declarations.push(t.variableDeclarator(vars[name], null));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (declarations.length === 0) {
|
||||||
|
return null; // Be sure to handle this case!
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.variableDeclaration("var", declarations);
|
||||||
|
};
|
||||||
13
packages/babel-plugin-transform-regenerator/src/index.js
Normal file
13
packages/babel-plugin-transform-regenerator/src/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
||||||
|
* additional grant of patent rights can be found in the PATENTS file in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return require("./visit");
|
||||||
|
}
|
||||||
174
packages/babel-plugin-transform-regenerator/src/leap.js
Normal file
174
packages/babel-plugin-transform-regenerator/src/leap.js
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
||||||
|
* additional grant of patent rights can be found in the PATENTS file in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from "assert";
|
||||||
|
import * as t from "babel-types";
|
||||||
|
import { inherits } from "util";
|
||||||
|
|
||||||
|
function Entry() {
|
||||||
|
assert.ok(this instanceof Entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FunctionEntry(returnLoc) {
|
||||||
|
Entry.call(this);
|
||||||
|
t.assertLiteral(returnLoc);
|
||||||
|
this.returnLoc = returnLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(FunctionEntry, Entry);
|
||||||
|
exports.FunctionEntry = FunctionEntry;
|
||||||
|
|
||||||
|
function LoopEntry(breakLoc, continueLoc, label) {
|
||||||
|
Entry.call(this);
|
||||||
|
|
||||||
|
t.assertLiteral(breakLoc);
|
||||||
|
t.assertLiteral(continueLoc);
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
t.assertIdentifier(label);
|
||||||
|
} else {
|
||||||
|
label = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.breakLoc = breakLoc;
|
||||||
|
this.continueLoc = continueLoc;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(LoopEntry, Entry);
|
||||||
|
exports.LoopEntry = LoopEntry;
|
||||||
|
|
||||||
|
function SwitchEntry(breakLoc) {
|
||||||
|
Entry.call(this);
|
||||||
|
t.assertLiteral(breakLoc);
|
||||||
|
this.breakLoc = breakLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(SwitchEntry, Entry);
|
||||||
|
exports.SwitchEntry = SwitchEntry;
|
||||||
|
|
||||||
|
function TryEntry(firstLoc, catchEntry, finallyEntry) {
|
||||||
|
Entry.call(this);
|
||||||
|
|
||||||
|
t.assertLiteral(firstLoc);
|
||||||
|
|
||||||
|
if (catchEntry) {
|
||||||
|
assert.ok(catchEntry instanceof CatchEntry);
|
||||||
|
} else {
|
||||||
|
catchEntry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finallyEntry) {
|
||||||
|
assert.ok(finallyEntry instanceof FinallyEntry);
|
||||||
|
} else {
|
||||||
|
finallyEntry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Have to have one or the other (or both).
|
||||||
|
assert.ok(catchEntry || finallyEntry);
|
||||||
|
|
||||||
|
this.firstLoc = firstLoc;
|
||||||
|
this.catchEntry = catchEntry;
|
||||||
|
this.finallyEntry = finallyEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(TryEntry, Entry);
|
||||||
|
exports.TryEntry = TryEntry;
|
||||||
|
|
||||||
|
function CatchEntry(firstLoc, paramId) {
|
||||||
|
Entry.call(this);
|
||||||
|
|
||||||
|
t.assertLiteral(firstLoc);
|
||||||
|
t.assertIdentifier(paramId);
|
||||||
|
|
||||||
|
this.firstLoc = firstLoc;
|
||||||
|
this.paramId = paramId;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(CatchEntry, Entry);
|
||||||
|
exports.CatchEntry = CatchEntry;
|
||||||
|
|
||||||
|
function FinallyEntry(firstLoc, afterLoc) {
|
||||||
|
Entry.call(this);
|
||||||
|
t.assertLiteral(firstLoc);
|
||||||
|
t.assertLiteral(afterLoc);
|
||||||
|
this.firstLoc = firstLoc;
|
||||||
|
this.afterLoc = afterLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(FinallyEntry, Entry);
|
||||||
|
exports.FinallyEntry = FinallyEntry;
|
||||||
|
|
||||||
|
function LabeledEntry(breakLoc, label) {
|
||||||
|
Entry.call(this);
|
||||||
|
|
||||||
|
t.assertLiteral(breakLoc);
|
||||||
|
t.assertIdentifier(label);
|
||||||
|
|
||||||
|
this.breakLoc = breakLoc;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(LabeledEntry, Entry);
|
||||||
|
exports.LabeledEntry = LabeledEntry;
|
||||||
|
|
||||||
|
function LeapManager(emitter) {
|
||||||
|
assert.ok(this instanceof LeapManager);
|
||||||
|
|
||||||
|
let Emitter = require("./emit").Emitter;
|
||||||
|
assert.ok(emitter instanceof Emitter);
|
||||||
|
|
||||||
|
this.emitter = emitter;
|
||||||
|
this.entryStack = [new FunctionEntry(emitter.finalLoc)];
|
||||||
|
}
|
||||||
|
|
||||||
|
let LMp = LeapManager.prototype;
|
||||||
|
exports.LeapManager = LeapManager;
|
||||||
|
|
||||||
|
LMp.withEntry = function(entry, callback) {
|
||||||
|
assert.ok(entry instanceof Entry);
|
||||||
|
this.entryStack.push(entry);
|
||||||
|
try {
|
||||||
|
callback.call(this.emitter);
|
||||||
|
} finally {
|
||||||
|
let popped = this.entryStack.pop();
|
||||||
|
assert.strictEqual(popped, entry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LMp._findLeapLocation = function(property, label) {
|
||||||
|
for (let i = this.entryStack.length - 1; i >= 0; --i) {
|
||||||
|
let entry = this.entryStack[i];
|
||||||
|
let loc = entry[property];
|
||||||
|
if (loc) {
|
||||||
|
if (label) {
|
||||||
|
if (entry.label &&
|
||||||
|
entry.label.name === label.name) {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
} else if (entry instanceof LabeledEntry) {
|
||||||
|
// Ignore LabeledEntry entries unless we are actually breaking to
|
||||||
|
// a label.
|
||||||
|
} else {
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
LMp.getBreakLoc = function(label) {
|
||||||
|
return this._findLeapLocation("breakLoc", label);
|
||||||
|
};
|
||||||
|
|
||||||
|
LMp.getContinueLoc = function(label) {
|
||||||
|
return this._findLeapLocation("continueLoc", label);
|
||||||
|
};
|
||||||
103
packages/babel-plugin-transform-regenerator/src/meta.js
Normal file
103
packages/babel-plugin-transform-regenerator/src/meta.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
||||||
|
* additional grant of patent rights can be found in the PATENTS file in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from "assert";
|
||||||
|
let m = require("private").makeAccessor();
|
||||||
|
import * as t from "babel-types";
|
||||||
|
let hasOwn = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
|
function makePredicate(propertyName, knownTypes) {
|
||||||
|
function onlyChildren(node) {
|
||||||
|
t.assertNode(node);
|
||||||
|
|
||||||
|
// Assume no side effects until we find out otherwise.
|
||||||
|
let result = false;
|
||||||
|
|
||||||
|
function check(child) {
|
||||||
|
if (result) {
|
||||||
|
// Do nothing.
|
||||||
|
} else if (Array.isArray(child)) {
|
||||||
|
child.some(check);
|
||||||
|
} else if (t.isNode(child)) {
|
||||||
|
assert.strictEqual(result, false);
|
||||||
|
result = predicate(child);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys = t.VISITOR_KEYS[node.type];
|
||||||
|
if (keys) {
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
let key = keys[i];
|
||||||
|
let child = node[key];
|
||||||
|
check(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function predicate(node) {
|
||||||
|
t.assertNode(node);
|
||||||
|
|
||||||
|
let meta = m(node);
|
||||||
|
if (hasOwn.call(meta, propertyName))
|
||||||
|
return meta[propertyName];
|
||||||
|
|
||||||
|
// Certain types are "opaque," which means they have no side
|
||||||
|
// effects or leaps and we don't care about their subexpressions.
|
||||||
|
if (hasOwn.call(opaqueTypes, node.type))
|
||||||
|
return meta[propertyName] = false;
|
||||||
|
|
||||||
|
if (hasOwn.call(knownTypes, node.type))
|
||||||
|
return meta[propertyName] = true;
|
||||||
|
|
||||||
|
return meta[propertyName] = onlyChildren(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate.onlyChildren = onlyChildren;
|
||||||
|
|
||||||
|
return predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
let opaqueTypes = {
|
||||||
|
FunctionExpression: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// These types potentially have side effects regardless of what side
|
||||||
|
// effects their subexpressions have.
|
||||||
|
let sideEffectTypes = {
|
||||||
|
CallExpression: true, // Anything could happen!
|
||||||
|
ForInStatement: true, // Modifies the key variable.
|
||||||
|
UnaryExpression: true, // Think delete.
|
||||||
|
BinaryExpression: true, // Might invoke .toString() or .valueOf().
|
||||||
|
AssignmentExpression: true, // Side-effecting by definition.
|
||||||
|
UpdateExpression: true, // Updates are essentially assignments.
|
||||||
|
NewExpression: true // Similar to CallExpression.
|
||||||
|
};
|
||||||
|
|
||||||
|
// These types are the direct cause of all leaps in control flow.
|
||||||
|
let leapTypes = {
|
||||||
|
YieldExpression: true,
|
||||||
|
BreakStatement: true,
|
||||||
|
ContinueStatement: true,
|
||||||
|
ReturnStatement: true,
|
||||||
|
ThrowStatement: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// All leap types are also side effect types.
|
||||||
|
for (let type in leapTypes) {
|
||||||
|
if (hasOwn.call(leapTypes, type)) {
|
||||||
|
sideEffectTypes[type] = leapTypes[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.hasSideEffects = makePredicate("hasSideEffects", sideEffectTypes);
|
||||||
|
exports.containsLeap = makePredicate("containsLeap", leapTypes);
|
||||||
23
packages/babel-plugin-transform-regenerator/src/util.js
Normal file
23
packages/babel-plugin-transform-regenerator/src/util.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
||||||
|
* additional grant of patent rights can be found in the PATENTS file in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as t from "babel-types";
|
||||||
|
|
||||||
|
export function runtimeProperty(name) {
|
||||||
|
return t.memberExpression(
|
||||||
|
t.identifier("regeneratorRuntime"),
|
||||||
|
t.identifier(name),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isReference(path) {
|
||||||
|
return path.isReferenced() || path.parentPath.isAssignmentExpression({ left: path.node });
|
||||||
|
}
|
||||||
252
packages/babel-plugin-transform-regenerator/src/visit.js
Normal file
252
packages/babel-plugin-transform-regenerator/src/visit.js
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
|
||||||
|
* additional grant of patent rights can be found in the PATENTS file in
|
||||||
|
* the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from "assert";
|
||||||
|
import * as t from "babel-types";
|
||||||
|
import { hoist } from "./hoist";
|
||||||
|
import { Emitter } from "./emit";
|
||||||
|
import * as util from "./util";
|
||||||
|
|
||||||
|
let getMarkInfo = require("private").makeAccessor();
|
||||||
|
|
||||||
|
exports.visitor = {
|
||||||
|
Function: {
|
||||||
|
exit: function(path, state) {
|
||||||
|
let node = path.node;
|
||||||
|
|
||||||
|
if (node.generator) {
|
||||||
|
if (node.async) {
|
||||||
|
// Async generator
|
||||||
|
if (state.opts.asyncGenerators === false) return;
|
||||||
|
} else {
|
||||||
|
// Plain generator
|
||||||
|
if (state.opts.generators === false) return;
|
||||||
|
}
|
||||||
|
} else if (node.async) {
|
||||||
|
// Async function
|
||||||
|
if (state.opts.async === false) return;
|
||||||
|
} else {
|
||||||
|
// Not a generator or async function.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.expression) {
|
||||||
|
// Transform expression lambdas into normal functions.
|
||||||
|
node.expression = false;
|
||||||
|
node.body = t.blockStatement([
|
||||||
|
t.returnStatement(node.body)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.async) {
|
||||||
|
path.get("body").traverse(awaitVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bodyBlockPath = path.get("body");
|
||||||
|
let outerBody = [];
|
||||||
|
let innerBody = [];
|
||||||
|
|
||||||
|
bodyBlockPath.get("body").forEach(function(childPath) {
|
||||||
|
let node = childPath.node;
|
||||||
|
if (node && node._blockHoist != null) {
|
||||||
|
outerBody.push(node);
|
||||||
|
} else {
|
||||||
|
innerBody.push(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (outerBody.length > 0) {
|
||||||
|
// Only replace the inner body if we actually hoisted any statements
|
||||||
|
// to the outer body.
|
||||||
|
bodyBlockPath.node.body = innerBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
let outerFnExpr = getOuterFnExpr(path);
|
||||||
|
// Note that getOuterFnExpr has the side-effect of ensuring that the
|
||||||
|
// function has a name (so node.id will always be an Identifier), even
|
||||||
|
// if a temporary name has to be synthesized.
|
||||||
|
t.assertIdentifier(node.id);
|
||||||
|
let innerFnId = t.identifier(node.id.name + "$");
|
||||||
|
let contextId = path.scope.generateUidIdentifier("context");
|
||||||
|
let argsId = path.scope.generateUidIdentifier("args");
|
||||||
|
|
||||||
|
// Turn all declarations into vars, and replace the original
|
||||||
|
// declarations with equivalent assignment expressions.
|
||||||
|
let vars = hoist(path);
|
||||||
|
|
||||||
|
let didRenameArguments = renameArguments(path, argsId);
|
||||||
|
if (didRenameArguments) {
|
||||||
|
vars = vars || t.variableDeclaration("var", []);
|
||||||
|
vars.declarations.push(t.variableDeclarator(
|
||||||
|
argsId, t.identifier("arguments")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let emitter = new Emitter(contextId);
|
||||||
|
emitter.explode(path.get("body"));
|
||||||
|
|
||||||
|
if (vars && vars.declarations.length > 0) {
|
||||||
|
outerBody.push(vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapArgs = [
|
||||||
|
emitter.getContextFunction(innerFnId),
|
||||||
|
// Async functions that are not generators don't care about the
|
||||||
|
// outer function because they don't need it to be marked and don't
|
||||||
|
// inherit from its .prototype.
|
||||||
|
node.generator ? outerFnExpr : t.nullLiteral(),
|
||||||
|
t.thisExpression()
|
||||||
|
];
|
||||||
|
|
||||||
|
let tryLocsList = emitter.getTryLocsList();
|
||||||
|
if (tryLocsList) {
|
||||||
|
wrapArgs.push(tryLocsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapCall = t.callExpression(
|
||||||
|
util.runtimeProperty(node.async ? "async" : "wrap"),
|
||||||
|
wrapArgs
|
||||||
|
);
|
||||||
|
|
||||||
|
outerBody.push(t.returnStatement(wrapCall));
|
||||||
|
node.body = t.blockStatement(outerBody);
|
||||||
|
|
||||||
|
let wasGeneratorFunction = node.generator;
|
||||||
|
if (wasGeneratorFunction) {
|
||||||
|
node.generator = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.async) {
|
||||||
|
node.async = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasGeneratorFunction &&
|
||||||
|
t.isExpression(node)) {
|
||||||
|
path.replaceWith(t.callExpression(util.runtimeProperty("mark"), [node]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Given a NodePath for a Function, return an Expression node that can be
|
||||||
|
// used to refer reliably to the function object from inside the function.
|
||||||
|
// This expression is essentially a replacement for arguments.callee, with
|
||||||
|
// the key advantage that it works in strict mode.
|
||||||
|
function getOuterFnExpr(funPath) {
|
||||||
|
let node = funPath.node;
|
||||||
|
t.assertFunction(node);
|
||||||
|
|
||||||
|
if (node.generator && // Non-generator functions don't need to be marked.
|
||||||
|
t.isFunctionDeclaration(node)) {
|
||||||
|
let pp = funPath.findParent(function (path) {
|
||||||
|
return path.isProgram() || path.isBlockStatement();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pp) {
|
||||||
|
return node.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
let markDecl = getRuntimeMarkDecl(pp);
|
||||||
|
let markedArray = markDecl.declarations[0].id;
|
||||||
|
let funDeclIdArray = markDecl.declarations[0].init.callee.object;
|
||||||
|
t.assertArrayExpression(funDeclIdArray);
|
||||||
|
|
||||||
|
let index = funDeclIdArray.elements.length;
|
||||||
|
funDeclIdArray.elements.push(node.id);
|
||||||
|
|
||||||
|
return t.memberExpression(
|
||||||
|
markedArray,
|
||||||
|
t.numericLiteral(index),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.id || (
|
||||||
|
node.id = funPath.scope.parent.generateUidIdentifier("callee")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuntimeMarkDecl(blockPath) {
|
||||||
|
let block = blockPath.node;
|
||||||
|
assert.ok(Array.isArray(block.body));
|
||||||
|
|
||||||
|
let info = getMarkInfo(block);
|
||||||
|
if (info.decl) {
|
||||||
|
return info.decl;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.decl = t.variableDeclaration("var", [
|
||||||
|
t.variableDeclarator(
|
||||||
|
blockPath.scope.generateUidIdentifier("marked"),
|
||||||
|
t.callExpression(
|
||||||
|
t.memberExpression(
|
||||||
|
t.arrayExpression([]),
|
||||||
|
t.identifier("map"),
|
||||||
|
false
|
||||||
|
),
|
||||||
|
[util.runtimeProperty("mark")]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
blockPath.unshiftContainer("body", info.decl);
|
||||||
|
|
||||||
|
return info.decl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameArguments(funcPath, argsId) {
|
||||||
|
let state = {
|
||||||
|
didRenameArguments: false,
|
||||||
|
argsId: argsId
|
||||||
|
};
|
||||||
|
|
||||||
|
funcPath.traverse(argumentsVisitor, state);
|
||||||
|
|
||||||
|
// If the traversal replaced any arguments references, then we need to
|
||||||
|
// alias the outer function's arguments binding (be it the implicit
|
||||||
|
// arguments object or some other parameter or variable) to the variable
|
||||||
|
// named by argsId.
|
||||||
|
return state.didRenameArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
let argumentsVisitor = {
|
||||||
|
"FunctionExpression|FunctionDeclaration": function(path) {
|
||||||
|
path.skip();
|
||||||
|
},
|
||||||
|
|
||||||
|
Identifier: function(path, state) {
|
||||||
|
if (path.node.name === "arguments" && util.isReference(path)) {
|
||||||
|
path.replaceWith(state.argsId);
|
||||||
|
state.didRenameArguments = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let awaitVisitor = {
|
||||||
|
Function: function(path) {
|
||||||
|
path.skip(); // Don't descend into nested function scopes.
|
||||||
|
},
|
||||||
|
|
||||||
|
AwaitExpression: function(path) {
|
||||||
|
// Convert await and await* expressions to yield expressions.
|
||||||
|
let argument = path.node.argument;
|
||||||
|
|
||||||
|
// Transforming `await x` to `yield regeneratorRuntime.awrap(x)`
|
||||||
|
// causes the argument to be wrapped in such a way that the runtime
|
||||||
|
// can distinguish between awaited and merely yielded values.
|
||||||
|
path.replaceWith(t.yieldExpression(
|
||||||
|
t.callExpression(
|
||||||
|
util.runtimeProperty("awrap"),
|
||||||
|
[argument]
|
||||||
|
),
|
||||||
|
false
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user