Merge branch 'development'

Conflicts:
	package.json
This commit is contained in:
Sebastian McKenzie
2015-11-09 18:20:23 -08:00
31 changed files with 246 additions and 6784 deletions

View File

@@ -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);
}
});
});

View File

@@ -124,7 +124,8 @@ export default function (
suite(name + "/" + testSuite.title, function () {
for (let task of testSuite.tests) {
if (_.contains(suiteOpts.ignoreTasks, task.title) || _.contains(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)) continue;
if (_.contains(suiteOpts.ignoreTasks, task.title) ||
_.contains(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)) continue;
test(task.title, !task.disabled && function () {
function runTask() {

View File

@@ -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

View File

@@ -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);
});
});
});

View File

@@ -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>

View File

@@ -1,3 +0,0 @@
function asdf() {
return "no generators or a-s-y-n-c functions to see here";
}

View File

@@ -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

View File

@@ -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"]);
});
});

View File

@@ -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

View File

@@ -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).

View File

@@ -1,74 +1 @@
regenerator [![Build Status](https://travis-ci.org/facebook/regenerator.png?branch=master)](https://travis-ci.org/facebook/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).
# babel-plugin-transform-regenerator

View File

@@ -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;
});

View File

@@ -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"
};
}

View File

@@ -1,51 +1,22 @@
{
"author": "Ben Newman <bn@cs.stanford.edu>",
"name": "babel-plugin-transform-regenerator",
"description": "Source transformer enabling ECMAScript 6 generator functions (yield) in JavaScript-of-today (ES5)",
"keywords": [
"generator",
"yield",
"coroutine",
"rewriting",
"transformation",
"syntax",
"codegen",
"rewriting",
"refactoring",
"transpiler",
"desugaring",
"ES6"
],
"author": "Ben Newman <bn@cs.stanford.edu>",
"description": "",
"version": "6.0.18",
"homepage": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-regenerator",
"repository": {
"type": "git",
"url": "git://github.com/facebook/regenerator.git"
},
"main": "main.js",
"bin": "bin/regenerator",
"scripts": {
"test": "node test/run.js"
},
"main": "lib/index.js",
"dependencies": {
"commoner": "~0.10.3",
"babel-plugin-transform-es2015-block-scoping": "^6.0.18",
"babel-plugin-syntax-async-functions": "^6.0.14",
"babel-plugin-transform-es2015-for-of": "^6.0.14",
"babel-core": "^6.0.18",
"babel-runtime": "^5.0.0",
"babel-traverse": "^6.0.18",
"babel-types": "^6.0.18",
"babylon": "^6.0.18",
"private": "~0.1.5",
"through": "~2.3.8"
},
"devDependencies": {
"mocha": "~2.3.3",
"promise": "~7.0.4",
"semver": "~5.0.3"
},
"license": "BSD",
"engines": {
"node": ">= 0.6"
}
"license": "BSD"
}

View File

@@ -8,14 +8,13 @@
* the same directory.
*/
var traverse = require("babel-traverse");
var assert = require("assert");
var t = require("babel-types");
var leap = require("./leap");
var meta = require("./meta");
var util = require("./util");
var runtimeProperty = util.runtimeProperty;
var hasOwn = Object.prototype.hasOwnProperty;
import assert from "assert";
import * as t from "babel-types";
import * as leap from "./leap";
import * as meta from "./meta";
import * as util from "./util";
let hasOwn = Object.prototype.hasOwnProperty;
function Emitter(contextId) {
assert.ok(this instanceof Emitter);
@@ -24,41 +23,34 @@ function Emitter(contextId) {
// Used to generate unique temporary names.
this.nextTempId = 0;
Object.defineProperties(this, {
// In order to make sure the context object does not collide with
// anything in the local scope, we might have to rename it, so we
// refer to it symbolically instead of just assuming that it will be
// called "context".
contextId: { value: contextId },
// In order to make sure the context object does not collide with
// anything in the local scope, we might have to rename it, so we
// refer to it symbolically instead of just assuming that it will be
// called "context".
this.contextId = contextId;
// An append-only list of Statements that grows each time this.emit is
// called.
listing: { value: [] },
// An append-only list of Statements that grows each time this.emit is
// called.
this.listing = [];
// A sparse array whose keys correspond to locations in this.listing
// that have been marked as branch/jump targets.
marked: { value: [true] },
// A sparse array whose keys correspond to locations in this.listing
// that have been marked as branch/jump targets.
this.marked = [true];
// The last location will be marked when this.getDispatchLoop is
// called.
finalLoc: { value: loc() },
// The last location will be marked when this.getDispatchLoop is
// called.
this.finalLoc = loc();
// A list of all leap.TryEntry statements emitted.
tryEntries: { value: [] }
});
// A list of all leap.TryEntry statements emitted.
this.tryEntries = [];
// The .leapManager property needs to be defined by a separate
// defineProperties call so that .finalLoc will be visible to the
// leap.LeapManager constructor.
Object.defineProperties(this, {
// Each time we evaluate the body of a loop, we tell this.leapManager
// to enter a nested loop context that determines the meaning of break
// and continue statements therein.
leapManager: { value: new leap.LeapManager(this) }
});
// Each time we evaluate the body of a loop, we tell this.leapManager
// to enter a nested loop context that determines the meaning of break
// and continue statements therein.
this.leapManager = new leap.LeapManager(this);
}
var Ep = Emitter.prototype;
let Ep = Emitter.prototype;
exports.Emitter = Emitter;
// Offsets into this.listing that could be used as targets for branches or
@@ -74,7 +66,7 @@ function loc() {
// Statement emitted.
Ep.mark = function(loc) {
t.assertLiteral(loc);
var index = this.listing.length;
let index = this.listing.length;
if (loc.value === -1) {
loc.value = index;
} else {
@@ -87,8 +79,10 @@ Ep.mark = function(loc) {
};
Ep.emit = function(node) {
if (t.isExpression(node))
if (t.isExpression(node)) {
node = t.expressionStatement(node);
}
t.assertStatement(node);
this.listing.push(node);
};
@@ -137,7 +131,7 @@ Ep.setReturnValue = function(valuePath) {
Ep.clearPendingException = function(tryLoc, assignee) {
t.assertLiteral(tryLoc);
var catchCall = t.callExpression(
let catchCall = t.callExpression(
this.contextProperty("catch", true),
[tryLoc]
);
@@ -175,7 +169,7 @@ Ep.jumpIfNot = function(test, toLoc) {
t.assertExpression(test);
t.assertLiteral(toLoc);
var negatedTest;
let negatedTest;
if (t.isUnaryExpression(test) &&
test.operator === "!") {
// Avoid double negation.
@@ -224,13 +218,13 @@ Ep.getContextFunction = function(id) {
// Each marked location in this.listing will correspond to one generated
// case statement.
Ep.getDispatchLoop = function() {
var self = this;
var cases = [];
var current;
let self = this;
let cases = [];
let current;
// If we encounter a break, continue, or return statement in a switch
// case, we can skip the rest of the statements until the next case.
var alreadyEnded = false;
let alreadyEnded = false;
self.listing.forEach(function(stmt, i) {
if (self.marked.hasOwnProperty(i)) {
@@ -286,18 +280,18 @@ Ep.getTryLocsList = function() {
return null;
}
var lastLocValue = 0;
let lastLocValue = 0;
return t.arrayExpression(
this.tryEntries.map(function(tryEntry) {
var thisLocValue = tryEntry.firstLoc.value;
let thisLocValue = tryEntry.firstLoc.value;
assert.ok(thisLocValue >= lastLocValue, "try entries out of order");
lastLocValue = thisLocValue;
var ce = tryEntry.catchEntry;
var fe = tryEntry.finallyEntry;
let ce = tryEntry.catchEntry;
let fe = tryEntry.finallyEntry;
var locs = [
let locs = [
tryEntry.firstLoc,
// The null here makes a hole in the array.
ce ? ce.firstLoc : null
@@ -321,8 +315,8 @@ Ep.getTryLocsList = function() {
// No destructive modification of AST nodes.
Ep.explode = function(path, ignoreResult) {
var node = path.node;
var self = this;
let node = path.node;
let self = this;
t.assertNode(node);
@@ -368,8 +362,9 @@ function getDeclError(node) {
}
Ep.explodeStatement = function(path, labelId) {
var stmt = path.node;
var self = this;
let stmt = path.node;
let self = this;
let before, after, head;
t.assertStatement(stmt);
@@ -404,7 +399,7 @@ Ep.explodeStatement = function(path, labelId) {
break;
case "LabeledStatement":
var after = loc();
after = loc();
// Did you know you can break from any labeled block statement or
// control structure? Well, you can! Note: when a labeled loop is
@@ -438,8 +433,8 @@ Ep.explodeStatement = function(path, labelId) {
break;
case "WhileStatement":
var before = loc();
var after = loc();
before = loc();
after = loc();
self.mark(before);
self.jumpIfNot(self.explodeExpression(path.get("test")), after);
@@ -453,9 +448,9 @@ Ep.explodeStatement = function(path, labelId) {
break;
case "DoWhileStatement":
var first = loc();
var test = loc();
var after = loc();
let first = loc();
let test = loc();
after = loc();
self.mark(first);
self.leapManager.withEntry(
@@ -469,9 +464,9 @@ Ep.explodeStatement = function(path, labelId) {
break;
case "ForStatement":
var head = loc();
var update = loc();
var after = loc();
head = loc();
let update = loc();
after = loc();
if (stmt.init) {
// We pass true here to indicate that if stmt.init is an expression
@@ -510,21 +505,21 @@ Ep.explodeStatement = function(path, labelId) {
return self.explodeExpression(path.get("expression"));
case "ForInStatement":
var head = loc();
var after = loc();
head = loc();
after = loc();
var keyIterNextFn = self.makeTempVar();
let keyIterNextFn = self.makeTempVar();
self.emitAssign(
keyIterNextFn,
t.callExpression(
runtimeProperty("keys"),
util.runtimeProperty("keys"),
[self.explodeExpression(path.get("right"))]
)
);
self.mark(head);
var keyInfoTmpVar = self.makeTempVar();
let keyInfoTmpVar = self.makeTempVar();
self.jumpIf(
t.memberExpression(
t.assignmentExpression(
@@ -577,21 +572,21 @@ Ep.explodeStatement = function(path, labelId) {
case "SwitchStatement":
// Always save the discriminant into a temporary variable in case the
// test expressions overwrite values like context.sent.
var disc = self.emitAssign(
let disc = self.emitAssign(
self.makeTempVar(),
self.explodeExpression(path.get("discriminant"))
);
var after = loc();
var defaultLoc = loc();
var condition = defaultLoc;
var caseLocs = [];
after = loc();
let defaultLoc = loc();
let condition = defaultLoc;
let caseLocs = [];
// If there are no cases, .cases might be undefined.
var cases = stmt.cases || [];
let cases = stmt.cases || [];
for (var i = cases.length - 1; i >= 0; --i) {
var c = cases[i];
for (let i = cases.length - 1; i >= 0; --i) {
let c = cases[i];
t.assertSwitchCase(c);
if (c.test) {
@@ -605,7 +600,7 @@ Ep.explodeStatement = function(path, labelId) {
}
}
var discriminant = path.get("discriminant");
let discriminant = path.get("discriminant");
discriminant.replaceWith(condition);
self.jump(self.explodeExpression(discriminant));
@@ -613,9 +608,7 @@ Ep.explodeStatement = function(path, labelId) {
new leap.SwitchEntry(after),
function() {
path.get("cases").forEach(function(casePath) {
var c = casePath.node;
var i = casePath.key;
let i = casePath.key;
self.mark(caseLocs[i]);
casePath.get("consequent").forEach(function (path) {
@@ -634,8 +627,8 @@ Ep.explodeStatement = function(path, labelId) {
break;
case "IfStatement":
var elseLoc = stmt.alternate && loc();
var after = loc();
let elseLoc = stmt.alternate && loc();
after = loc();
self.jumpIfNot(
self.explodeExpression(path.get("test")),
@@ -663,25 +656,24 @@ Ep.explodeStatement = function(path, labelId) {
break;
case "WithStatement":
throw new Error(
node.type + " not supported in generator functions.");
throw new Error("WithStatement not supported in generator functions.");
case "TryStatement":
var after = loc();
after = loc();
var handler = stmt.handler;
let handler = stmt.handler;
var catchLoc = handler && loc();
var catchEntry = catchLoc && new leap.CatchEntry(
let catchLoc = handler && loc();
let catchEntry = catchLoc && new leap.CatchEntry(
catchLoc,
handler.param
);
var finallyLoc = stmt.finalizer && loc();
var finallyEntry = finallyLoc &&
let finallyLoc = stmt.finalizer && loc();
let finallyEntry = finallyLoc &&
new leap.FinallyEntry(finallyLoc, after);
var tryEntry = new leap.TryEntry(
let tryEntry = new leap.TryEntry(
self.getUnmarkedCurrentLoc(),
catchEntry,
finallyEntry
@@ -708,14 +700,10 @@ Ep.explodeStatement = function(path, labelId) {
self.updateContextPrevLoc(self.mark(catchLoc));
var bodyPath = path.get("handler.body");
var safeParam = self.makeTempVar();
let bodyPath = path.get("handler.body");
let safeParam = self.makeTempVar();
self.clearPendingException(tryEntry.firstLoc, safeParam);
var catchScope = bodyPath.scope;
// TODO: t.assertCatchClause(catchScope.block);
// TODO: assert.strictEqual(catchScope.lookup(catchParamName), catchScope);
bodyPath.traverse(catchParamVisitor, {
safeParam: safeParam,
catchParamName: handler.param.name
@@ -758,7 +746,7 @@ Ep.explodeStatement = function(path, labelId) {
}
};
var catchParamVisitor = {
let catchParamVisitor = {
Identifier: function(path, state) {
if (path.node.name === state.catchParamName && util.isReference(path)) {
path.replaceWith(state.safeParam);
@@ -788,7 +776,7 @@ Ep.emitAbruptCompletion = function(record) {
"normal completions are not abrupt"
);
var abruptArgs = [t.stringLiteral(record.type)];
let abruptArgs = [t.stringLiteral(record.type)];
if (record.type === "break" ||
record.type === "continue") {
@@ -813,7 +801,7 @@ Ep.emitAbruptCompletion = function(record) {
};
function isValidCompletion(record) {
var type = record.type;
let type = record.type;
if (type === "normal") {
return !hasOwn.call(record, "target");
@@ -882,15 +870,16 @@ Ep.updateContextPrevLoc = function(loc) {
};
Ep.explodeExpression = function(path, ignoreResult) {
var expr = path.node;
let expr = path.node;
if (expr) {
t.assertExpression(expr);
} else {
return expr;
}
var self = this;
var result; // Used optionally by several cases below.
let self = this;
let result; // Used optionally by several cases below.
let after;
function finish(expr) {
t.assertExpression(expr);
@@ -911,7 +900,7 @@ Ep.explodeExpression = function(path, ignoreResult) {
// break statement), then any sibling subexpressions will almost
// certainly have to be exploded in order to maintain the order of their
// side effects relative to the leaping child(ren).
var hasLeapingChildren = meta.containsLeap.onlyChildren(expr);
let hasLeapingChildren = meta.containsLeap.onlyChildren(expr);
// In order to save the rest of explodeExpression from a combinatorial
// trainwreck of special cases, explodeViaTempVar is responsible for
@@ -929,7 +918,7 @@ Ep.explodeExpression = function(path, ignoreResult) {
"be assigned to a temporary variable?"
);
var result = self.explodeExpression(childPath, ignoreChildResult);
let result = self.explodeExpression(childPath, ignoreChildResult);
if (ignoreChildResult) {
// Side effects already emitted above.
@@ -970,13 +959,13 @@ Ep.explodeExpression = function(path, ignoreResult) {
));
case "CallExpression":
var calleePath = path.get("callee");
var argsPath = path.get("arguments");
let calleePath = path.get("callee");
let argsPath = path.get("arguments");
var newCallee;
var newArgs = [];
let newCallee;
let newArgs = [];
var hasLeapingArgs = false;
let hasLeapingArgs = false;
argsPath.forEach(function(argPath) {
hasLeapingArgs = hasLeapingArgs ||
meta.containsLeap(argPath.node);
@@ -990,14 +979,14 @@ Ep.explodeExpression = function(path, ignoreResult) {
// expression, then we must be careful that the object of the
// member expression still gets bound to `this` for the call.
var newObject = explodeViaTempVar(
let newObject = explodeViaTempVar(
// Assign the exploded callee.object expression to a temporary
// variable so that we can use it twice without reevaluating it.
self.makeTempVar(),
calleePath.get("object")
);
var newProperty = calleePath.node.computed
let newProperty = calleePath.node.computed
? explodeViaTempVar(null, calleePath.get("property"))
: calleePath.node.property;
@@ -1030,7 +1019,7 @@ Ep.explodeExpression = function(path, ignoreResult) {
// will receive the object of the MemberExpression as its `this`
// object.
newCallee = t.sequenceExpression([
t.numericLiteral(0),
t.numbericLiteral(0),
newCallee
]);
}
@@ -1076,7 +1065,7 @@ Ep.explodeExpression = function(path, ignoreResult) {
));
case "SequenceExpression":
var lastIndex = expr.expressions.length - 1;
let lastIndex = expr.expressions.length - 1;
path.get("expressions").forEach(function(exprPath) {
if (exprPath.key === lastIndex) {
@@ -1089,13 +1078,13 @@ Ep.explodeExpression = function(path, ignoreResult) {
return result;
case "LogicalExpression":
var after = loc();
after = loc();
if (!ignoreResult) {
result = self.makeTempVar();
}
var left = explodeViaTempVar(result, path.get("left"));
let left = explodeViaTempVar(result, path.get("left"));
if (expr.operator === "&&") {
self.jumpIfNot(left, after);
@@ -1111,9 +1100,9 @@ Ep.explodeExpression = function(path, ignoreResult) {
return result;
case "ConditionalExpression":
var elseLoc = loc();
var after = loc();
var test = self.explodeExpression(path.get("test"));
let elseLoc = loc();
after = loc();
let test = self.explodeExpression(path.get("test"));
self.jumpIfNot(test, elseLoc);
@@ -1162,11 +1151,11 @@ Ep.explodeExpression = function(path, ignoreResult) {
));
case "YieldExpression":
var after = loc();
var arg = expr.argument && self.explodeExpression(path.get("argument"));
after = loc();
let arg = expr.argument && self.explodeExpression(path.get("argument"));
if (arg && expr.delegate) {
var result = self.makeTempVar();
let result = self.makeTempVar();
self.emit(t.returnStatement(t.callExpression(
self.contextProperty("delegateYield"), [

View File

@@ -8,10 +8,8 @@
* the same directory.
*/
var traverse = require("babel-traverse");
var assert = require("assert");
var t = require("babel-types");
var hasOwn = Object.prototype.hasOwnProperty;
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
@@ -20,12 +18,12 @@ var hasOwn = Object.prototype.hasOwnProperty;
exports.hoist = function(funPath) {
t.assertFunction(funPath.node);
var vars = {};
let vars = {};
function varDeclToExpr(vdec, includeIdentifiers) {
t.assertVariableDeclaration(vdec);
// TODO assert.equal(vdec.kind, "var");
var exprs = [];
let exprs = [];
vdec.declarations.forEach(function(dec) {
vars[dec.id.name] = dec.id;
@@ -51,7 +49,7 @@ exports.hoist = function(funPath) {
funPath.get("body").traverse({
VariableDeclaration: {
exit: function(path) {
var expr = varDeclToExpr(path.node, false);
let expr = varDeclToExpr(path.node, false);
if (expr === null) {
path.remove();
} else {
@@ -67,25 +65,24 @@ exports.hoist = function(funPath) {
},
ForStatement: function(path) {
var init = path.node.init;
let init = path.node.init;
if (t.isVariableDeclaration(init)) {
path.get("init").replaceWith(varDeclToExpr(init, false));
}
},
ForXStatement: function(path) {
var left = path.get("left");
let left = path.get("left");
if (left.isVariableDeclaration()) {
left.replaceWith(varDeclToExpr(left.node, true));
}
},
FunctionDeclaration: function(path) {
var node = path.node;
let node = path.node;
vars[node.id.name] = node.id;
var parentNode = path.parent.node;
var assignment = t.expressionStatement(
let assignment = t.expressionStatement(
t.assignmentExpression(
"=",
node.id,
@@ -124,9 +121,9 @@ exports.hoist = function(funPath) {
}
});
var paramNames = {};
let paramNames = {};
funPath.get("params").forEach(function(paramPath) {
var param = paramPath.node;
let param = paramPath.node;
if (t.isIdentifier(param)) {
paramNames[param.name] = param;
} else {
@@ -135,7 +132,7 @@ exports.hoist = function(funPath) {
}
});
var declarations = [];
let declarations = [];
Object.keys(vars).forEach(function(name) {
if (!hasOwn.call(paramNames, name)) {

View 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");
}

View File

@@ -8,10 +8,9 @@
* the same directory.
*/
var assert = require("assert");
var t = require("babel-types");
var inherits = require("util").inherits;
var hasOwn = Object.prototype.hasOwnProperty;
import assert from "assert";
import * as t from "babel-types";
import { inherits } from "util";
function Entry() {
assert.ok(this instanceof Entry);
@@ -123,14 +122,14 @@ exports.LabeledEntry = LabeledEntry;
function LeapManager(emitter) {
assert.ok(this instanceof LeapManager);
var Emitter = require("./emit").Emitter;
let Emitter = require("./emit").Emitter;
assert.ok(emitter instanceof Emitter);
this.emitter = emitter;
this.entryStack = [new FunctionEntry(emitter.finalLoc)];
}
var LMp = LeapManager.prototype;
let LMp = LeapManager.prototype;
exports.LeapManager = LeapManager;
LMp.withEntry = function(entry, callback) {
@@ -139,15 +138,15 @@ LMp.withEntry = function(entry, callback) {
try {
callback.call(this.emitter);
} finally {
var popped = this.entryStack.pop();
let popped = this.entryStack.pop();
assert.strictEqual(popped, entry);
}
};
LMp._findLeapLocation = function(property, label) {
for (var i = this.entryStack.length - 1; i >= 0; --i) {
var entry = this.entryStack[i];
var loc = entry[property];
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 &&

View File

@@ -8,17 +8,17 @@
* the same directory.
*/
var assert = require("assert");
var m = require("private").makeAccessor();
var t = require("babel-types");
var hasOwn = Object.prototype.hasOwnProperty;
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.
var result = false;
let result = false;
function check(child) {
if (result) {
@@ -32,11 +32,11 @@ function makePredicate(propertyName, knownTypes) {
return result;
}
var keys = t.VISITOR_KEYS[node.type];
let keys = t.VISITOR_KEYS[node.type];
if (keys) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var child = node[key];
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
let child = node[key];
check(child);
}
}
@@ -47,7 +47,7 @@ function makePredicate(propertyName, knownTypes) {
function predicate(node) {
t.assertNode(node);
var meta = m(node);
let meta = m(node);
if (hasOwn.call(meta, propertyName))
return meta[propertyName];
@@ -67,13 +67,13 @@ function makePredicate(propertyName, knownTypes) {
return predicate;
}
var opaqueTypes = {
let opaqueTypes = {
FunctionExpression: true
};
// These types potentially have side effects regardless of what side
// effects their subexpressions have.
var sideEffectTypes = {
let sideEffectTypes = {
CallExpression: true, // Anything could happen!
ForInStatement: true, // Modifies the key variable.
UnaryExpression: true, // Think delete.
@@ -84,7 +84,7 @@ var sideEffectTypes = {
};
// These types are the direct cause of all leaps in control flow.
var leapTypes = {
let leapTypes = {
YieldExpression: true,
BreakStatement: true,
ContinueStatement: true,
@@ -93,7 +93,7 @@ var leapTypes = {
};
// All leap types are also side effect types.
for (var type in leapTypes) {
for (let type in leapTypes) {
if (hasOwn.call(leapTypes, type)) {
sideEffectTypes[type] = leapTypes[type];
}

View File

@@ -8,16 +8,16 @@
* the same directory.
*/
var t = require("babel-types");
import * as t from "babel-types";
exports.runtimeProperty = function(name) {
export function runtimeProperty(name) {
return t.memberExpression(
t.identifier("regeneratorRuntime"),
t.identifier(name),
false
);
};
}
exports.isReference = function(path) {
export function isReference(path) {
return path.isReferenced() || path.parentPath.isAssignmentExpression({ left: path.node });
};
}

View File

@@ -8,21 +8,18 @@
* the same directory.
*/
var traverse = require("babel-traverse");
var babylon = require("babylon");
var assert = require("assert");
var fs = require("fs");
var t = require("babel-types");
var hoist = require("./hoist").hoist;
var Emitter = require("./emit").Emitter;
var util = require("./util");
var runtimeProperty = util.runtimeProperty;
var getMarkInfo = require("private").makeAccessor();
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) {
var node = path.node;
let node = path.node;
if (node.generator) {
if (node.async) {
@@ -52,12 +49,12 @@ exports.visitor = {
path.get("body").traverse(awaitVisitor);
}
var bodyBlockPath = path.get("body");
var outerBody = [];
var innerBody = [];
let bodyBlockPath = path.get("body");
let outerBody = [];
let innerBody = [];
bodyBlockPath.get("body").forEach(function(childPath) {
var node = childPath.node;
let node = childPath.node;
if (node && node._blockHoist != null) {
outerBody.push(node);
} else {
@@ -71,20 +68,20 @@ exports.visitor = {
bodyBlockPath.node.body = innerBody;
}
var outerFnExpr = getOuterFnExpr(path);
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);
var innerFnId = t.identifier(node.id.name + "$");
var contextId = path.scope.generateUidIdentifier("context");
var argsId = path.scope.generateUidIdentifier("args");
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.
var vars = hoist(path);
let vars = hoist(path);
var didRenameArguments = renameArguments(path, argsId);
let didRenameArguments = renameArguments(path, argsId);
if (didRenameArguments) {
vars = vars || t.variableDeclaration("var", []);
vars.declarations.push(t.variableDeclarator(
@@ -92,14 +89,14 @@ exports.visitor = {
));
}
var emitter = new Emitter(contextId);
let emitter = new Emitter(contextId);
emitter.explode(path.get("body"));
if (vars && vars.declarations.length > 0) {
outerBody.push(vars);
}
var wrapArgs = [
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
@@ -108,20 +105,20 @@ exports.visitor = {
t.thisExpression()
];
var tryLocsList = emitter.getTryLocsList();
let tryLocsList = emitter.getTryLocsList();
if (tryLocsList) {
wrapArgs.push(tryLocsList);
}
var wrapCall = t.callExpression(
runtimeProperty(node.async ? "async" : "wrap"),
let wrapCall = t.callExpression(
util.runtimeProperty(node.async ? "async" : "wrap"),
wrapArgs
);
outerBody.push(t.returnStatement(wrapCall));
node.body = t.blockStatement(outerBody);
var wasGeneratorFunction = node.generator;
let wasGeneratorFunction = node.generator;
if (wasGeneratorFunction) {
node.generator = false;
}
@@ -132,7 +129,7 @@ exports.visitor = {
if (wasGeneratorFunction &&
t.isExpression(node)) {
path.replaceWith(t.callExpression(runtimeProperty("mark"), [node]));
path.replaceWith(t.callExpression(util.runtimeProperty("mark"), [node]));
}
}
}
@@ -143,12 +140,12 @@ exports.visitor = {
// This expression is essentially a replacement for arguments.callee, with
// the key advantage that it works in strict mode.
function getOuterFnExpr(funPath) {
var node = funPath.node;
let node = funPath.node;
t.assertFunction(node);
if (node.generator && // Non-generator functions don't need to be marked.
t.isFunctionDeclaration(node)) {
var pp = funPath.findParent(function (path) {
let pp = funPath.findParent(function (path) {
return path.isProgram() || path.isBlockStatement();
});
@@ -156,12 +153,12 @@ function getOuterFnExpr(funPath) {
return node.id;
}
var markDecl = getRuntimeMarkDecl(pp);
var markedArray = markDecl.declarations[0].id;
var funDeclIdArray = markDecl.declarations[0].init.callee.object;
let markDecl = getRuntimeMarkDecl(pp);
let markedArray = markDecl.declarations[0].id;
let funDeclIdArray = markDecl.declarations[0].init.callee.object;
t.assertArrayExpression(funDeclIdArray);
var index = funDeclIdArray.elements.length;
let index = funDeclIdArray.elements.length;
funDeclIdArray.elements.push(node.id);
return t.memberExpression(
@@ -177,10 +174,10 @@ function getOuterFnExpr(funPath) {
}
function getRuntimeMarkDecl(blockPath) {
var block = blockPath.node;
let block = blockPath.node;
assert.ok(Array.isArray(block.body));
var info = getMarkInfo(block);
let info = getMarkInfo(block);
if (info.decl) {
return info.decl;
}
@@ -194,7 +191,7 @@ function getRuntimeMarkDecl(blockPath) {
t.identifier("map"),
false
),
[runtimeProperty("mark")]
[util.runtimeProperty("mark")]
)
)
]);
@@ -205,7 +202,7 @@ function getRuntimeMarkDecl(blockPath) {
}
function renameArguments(funcPath, argsId) {
var state = {
let state = {
didRenameArguments: false,
argsId: argsId
};
@@ -219,7 +216,7 @@ function renameArguments(funcPath, argsId) {
return state.didRenameArguments;
}
var argumentsVisitor = {
let argumentsVisitor = {
"FunctionExpression|FunctionDeclaration": function(path) {
path.skip();
},
@@ -232,21 +229,21 @@ var argumentsVisitor = {
}
};
var awaitVisitor = {
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.
var argument = path.node.argument;
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(
runtimeProperty("awrap"),
util.runtimeProperty("awrap"),
[argument]
),
false

View File

@@ -24,6 +24,8 @@ export default function ({ types: t }) {
visitor: {
ReferencedIdentifier(path, state) {
if (state.opts.regenerator === false) return;
let { node, parent, scope } = path;
if (node.name === "regeneratorRuntime") {
@@ -43,8 +45,9 @@ export default function ({ types: t }) {
));
},
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
CallExpression(path, state) {
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
if (state.opts.polyfill === false) return;
// we can't compile this
if (path.node.arguments.length) return;
@@ -64,8 +67,9 @@ export default function ({ types: t }) {
));
},
// Symbol.iterator in arr -> core.$for.isIterable(arr)
BinaryExpression(path, state) {
// Symbol.iterator in arr -> core.$for.isIterable(arr)
if (state.opts.polyfill === false) return;
if (path.node.operator !== "in") return;
if (!path.get("left").matchesPattern("Symbol.iterator")) return;
@@ -80,12 +84,12 @@ export default function ({ types: t }) {
));
},
// Array.from -> _core.Array.from
MemberExpression: {
enter(path, state) {
if (state.opts.polyfill === false) return;
if (!path.isReferenced()) return;
// Array.from -> _core.Array.from
let { node } = path;
let obj = node.object;
let prop = node.property;
@@ -114,6 +118,7 @@ export default function ({ types: t }) {
},
exit(path, state) {
if (state.opts.polyfill === false) return;
if (!path.isReferenced()) return;
let { node } = path;