Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a077c75c8c | ||
|
|
c0b03e8126 | ||
|
|
a3a4a7645c | ||
|
|
7bd1337ee8 | ||
|
|
c54f530b10 | ||
|
|
9d3a3a57f2 | ||
|
|
e1474c2f5f | ||
|
|
8a9a205122 | ||
|
|
885d65f9de | ||
|
|
43d1435c97 | ||
|
|
247c14c5ab | ||
|
|
0e2b12c134 | ||
|
|
59c5abe188 | ||
|
|
e1cc1dcb4b | ||
|
|
d091793077 | ||
|
|
e6baac1003 | ||
|
|
c41608edc3 | ||
|
|
3815913537 | ||
|
|
e5c18749f0 | ||
|
|
b7458f949c | ||
|
|
69302b314f | ||
|
|
0c57a00fdb | ||
|
|
3bec8b0311 |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,6 +1,19 @@
|
||||
# 1.12.20
|
||||
|
||||
* Append `sourceMappingURL` when using `bin/6to5` and output sourcemaps.
|
||||
|
||||
# 1.12.19
|
||||
|
||||
* Add `comments` option and `--remove-comments` flag. Thanks @[webpro](htps://github.com/webpro)!
|
||||
* Embed `regenerator`.
|
||||
|
||||
# 1.12.18
|
||||
|
||||
* Use `global` reference instead of `window`.
|
||||
|
||||
# 1.12.17
|
||||
|
||||
* Add `moduleName`, `sourceRoot` and `filenameRelative` options - thanks @darvelo!
|
||||
* Add `moduleName`, `sourceRoot` and `filenameRelative` options - thanks @[darvelo](https://github.com/darvelo)!
|
||||
* Traversal optimisations.
|
||||
|
||||
# 1.12.16
|
||||
|
||||
@@ -19,7 +19,9 @@ module.exports = function (commander, filenames, opts) {
|
||||
mkdirp.sync(up);
|
||||
|
||||
if (commander.sourceMaps) {
|
||||
fs.writeFileSync(dest + ".map", JSON.stringify(data.map));
|
||||
var mapLoc = dest + ".map";
|
||||
data.code = util.addSourceMappingUrl(data.code, mapLoc);
|
||||
fs.writeFileSync(mapLoc, JSON.stringify(data.map));
|
||||
}
|
||||
|
||||
fs.writeFileSync(dest, data.code);
|
||||
|
||||
@@ -56,7 +56,9 @@ module.exports = function (commander, filenames) {
|
||||
|
||||
if (commander.outFile) {
|
||||
if (commander.sourceMaps) {
|
||||
fs.writeFileSync(commander.outFile + ".map", JSON.stringify(result.map));
|
||||
var mapLoc = commander.outFile + ".map";
|
||||
result.code = util.addSourceMappingUrl(result.code, mapLoc);
|
||||
fs.writeFileSync(mapLoc, JSON.stringify(result.map));
|
||||
}
|
||||
|
||||
fs.writeFileSync(commander.outFile, result.code);
|
||||
|
||||
@@ -17,6 +17,7 @@ commander.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ON
|
||||
commander.option("-b, --blacklist [blacklist]", "Blacklist of transformers to NOT use", util.list);
|
||||
commander.option("-o, --out-file [out]", "Compile all input files into a single file");
|
||||
commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory");
|
||||
commander.option("-c, --remove-comments", "Remove comments from the compiled code", false);
|
||||
|
||||
commander.on("--help", function(){
|
||||
var outKeys = function (title, obj) {
|
||||
@@ -88,6 +89,7 @@ exports.opts = {
|
||||
blacklist: commander.blacklist,
|
||||
whitelist: commander.whitelist,
|
||||
sourceMap: commander.sourceMaps || commander.sourceMapsInline,
|
||||
comments: !commander.removeComments,
|
||||
runtime: commander.runtime,
|
||||
modules: commander.modules
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
var readdir = require("fs-readdir-recursive");
|
||||
var index = require("./index");
|
||||
var util = require("../../lib/6to5/util");
|
||||
var path = require("path");
|
||||
var to5 = require("../../lib/6to5");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
@@ -11,6 +12,10 @@ exports.readdirFilter = function (filename) {
|
||||
});
|
||||
};
|
||||
|
||||
exports.addSourceMappingUrl = function (code, loc) {
|
||||
return code + "\n//# sourceMappingURL=" + path.basename(loc);
|
||||
};
|
||||
|
||||
exports.transform = function (filename, code, opts) {
|
||||
opts = _.extend(opts || {}, index.opts);
|
||||
opts.filename = filename;
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
- [Brunch](https://github.com/es128/6to5-brunch)
|
||||
- [Duo](https://github.com/bdo-labs/duo6to5)
|
||||
- [Connect](https://github.com/6to5/6to5-connect)
|
||||
- [Gobble](https://github.com/gobblejs/gobble-6to5)
|
||||
- [Gulp](https://github.com/sindresorhus/gulp-6to5)
|
||||
- [Grunt](https://github.com/sindresorhus/grunt-6to5)
|
||||
- [Jade](https://github.com/Apoxx/jade-6to5)
|
||||
- [Jest](https://github.com/6to5/6to5-jest)
|
||||
- [JSXHint](https://github.com/STRML/JSXHint) (A wrapper around JSHint to allow linting of JSX files)
|
||||
- [Karma](https://github.com/shuhei/karma-6to5-preprocessor)
|
||||
- [Mocha](https://github.com/6to5/6to5-mocha)
|
||||
- [Rails](https://github.com/6to5/6to5-rails)
|
||||
- [Rails](https://github.com/josh/sprockets-es6) or via [browserify-rails](https://github.com/6to5/6to5-rails)
|
||||
- [webpack](https://github.com/Couto/6to5-loader)
|
||||
|
||||
@@ -124,7 +124,11 @@ to5.transformFile("filename.js", options, function (err, result) {
|
||||
// Optionally replace all 6to5 helper declarations with a referenece to this
|
||||
// variable. If set to `true` then the default namespace is used "to5Runtime".
|
||||
// Default: false
|
||||
runtime: true
|
||||
runtime: true,
|
||||
|
||||
// Output comments in generated output
|
||||
// Default: true
|
||||
comments: false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ transform.load = function (url, callback, opts, hold) {
|
||||
opts = opts || {};
|
||||
opts.filename = opts.filename || url;
|
||||
|
||||
var xhr = window.ActiveXObject ? new window.ActiveXObject("Microsoft.XMLHTTP") : new window.XMLHttpRequest();
|
||||
var xhr = global.ActiveXObject ? new global.ActiveXObject("Microsoft.XMLHTTP") : new global.XMLHttpRequest();
|
||||
xhr.open("GET", url, true);
|
||||
if ("overrideMimeType" in xhr) xhr.overrideMimeType("text/plain");
|
||||
|
||||
@@ -60,7 +60,7 @@ var runScripts = function () {
|
||||
}
|
||||
};
|
||||
|
||||
var _scripts = window.document.getElementsByTagName("script");
|
||||
var _scripts = global.document.getElementsByTagName("script");
|
||||
for (var i in _scripts) {
|
||||
var _script = _scripts[i];
|
||||
if (types.indexOf(_script.type) >= 0) scripts.push(_script);
|
||||
@@ -73,8 +73,8 @@ var runScripts = function () {
|
||||
exec();
|
||||
};
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("DOMContentLoaded", runScripts, false);
|
||||
} else {
|
||||
window.attachEvent("onload", runScripts);
|
||||
if (global.addEventListener) {
|
||||
global.addEventListener("DOMContentLoaded", runScripts, false);
|
||||
} else if (global.attachEvent) {
|
||||
global.attachEvent("onload", runScripts);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ File.normaliseOptions = function (opts) {
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
comments: true,
|
||||
filename: "unknown",
|
||||
modules: "common",
|
||||
runtime: false,
|
||||
|
||||
@@ -35,21 +35,17 @@ _.each(Buffer.prototype, function (fn, key) {
|
||||
});
|
||||
|
||||
CodeGenerator.normaliseOptions = function (opts) {
|
||||
opts = opts.format || {};
|
||||
|
||||
opts = _.merge({
|
||||
return _.merge({
|
||||
parentheses: true,
|
||||
semicolons: true,
|
||||
comments: true,
|
||||
comments: opts.comments == null || opts.comments,
|
||||
compact: false,
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
style: " ",
|
||||
base: 0
|
||||
}
|
||||
}, opts);
|
||||
|
||||
return opts;
|
||||
}, opts.format || {});
|
||||
};
|
||||
|
||||
CodeGenerator.generators = {
|
||||
|
||||
@@ -3,4 +3,4 @@ if (typeof Symbol === "undefined") {
|
||||
}
|
||||
|
||||
require("es6-shim");
|
||||
require("regenerator-6to5/runtime");
|
||||
require("./transformation/transformers/generators/runtime");
|
||||
|
||||
@@ -45,17 +45,17 @@ _.each({
|
||||
destructuring: require("./transformers/destructuring"),
|
||||
forOf: require("./transformers/for-of"),
|
||||
unicodeRegex: require("./transformers/unicode-regex"),
|
||||
react: require("./transformers/react"),
|
||||
|
||||
constants: require("./transformers/constants"),
|
||||
letScoping: require("./transformers/let-scoping"),
|
||||
|
||||
react: require("./transformers/react"),
|
||||
generators: require("./transformers/generators"),
|
||||
|
||||
_aliasFunctions: require("./transformers/_alias-functions"),
|
||||
_blockHoist: require("./transformers/_block-hoist"),
|
||||
_declarations: require("./transformers/_declarations"),
|
||||
_aliasFunctions: require("./transformers/_alias-functions"),
|
||||
|
||||
generators: require("./transformers/generators"),
|
||||
useStrict: require("./transformers/use-strict"),
|
||||
|
||||
_memberExpressionKeywords: require("./transformers/_member-expression-keywords"),
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
var regenerator = require("regenerator-6to5");
|
||||
|
||||
module.exports = regenerator.transform;
|
||||
1138
lib/6to5/transformation/transformers/generators/emit.js
Normal file
1138
lib/6to5/transformation/transformers/generators/emit.js
Normal file
File diff suppressed because it is too large
Load Diff
152
lib/6to5/transformation/transformers/generators/hoist.js
Normal file
152
lib/6to5/transformation/transformers/generators/hoist.js
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* 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");
|
||||
var types = require("ast-types");
|
||||
var n = types.namedTypes;
|
||||
var b = types.builders;
|
||||
var 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) {
|
||||
assert.ok(funPath instanceof types.NodePath);
|
||||
n.Function.assert(funPath.value);
|
||||
|
||||
var vars = {};
|
||||
|
||||
function varDeclToExpr(vdec, includeIdentifiers) {
|
||||
n.VariableDeclaration.assert(vdec);
|
||||
var exprs = [];
|
||||
|
||||
vdec.declarations.forEach(function(dec) {
|
||||
vars[dec.id.name] = dec.id;
|
||||
|
||||
if (dec.init) {
|
||||
exprs.push(b.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 b.sequenceExpression(exprs);
|
||||
}
|
||||
|
||||
types.visit(funPath.get("body"), {
|
||||
visitVariableDeclaration: function(path) {
|
||||
var expr = varDeclToExpr(path.value, false);
|
||||
if (expr === null) {
|
||||
path.replace();
|
||||
} else {
|
||||
// We don't need to traverse this expression any further because
|
||||
// there can't be any new declarations inside an expression.
|
||||
return b.expressionStatement(expr);
|
||||
}
|
||||
|
||||
// Since the original node has been either removed or replaced,
|
||||
// avoid traversing it any further.
|
||||
return false;
|
||||
},
|
||||
|
||||
visitForStatement: function(path) {
|
||||
var init = path.value.init;
|
||||
if (n.VariableDeclaration.check(init)) {
|
||||
path.get("init").replace(varDeclToExpr(init, false));
|
||||
}
|
||||
this.traverse(path);
|
||||
},
|
||||
|
||||
visitForInStatement: function(path) {
|
||||
var left = path.value.left;
|
||||
if (n.VariableDeclaration.check(left)) {
|
||||
path.get("left").replace(varDeclToExpr(left, true));
|
||||
}
|
||||
this.traverse(path);
|
||||
},
|
||||
|
||||
visitFunctionDeclaration: function(path) {
|
||||
var node = path.value;
|
||||
vars[node.id.name] = node.id;
|
||||
|
||||
var assignment = b.expressionStatement(
|
||||
b.assignmentExpression(
|
||||
"=",
|
||||
node.id,
|
||||
b.functionExpression(
|
||||
node.id,
|
||||
node.params,
|
||||
node.body,
|
||||
node.generator,
|
||||
node.expression
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (n.BlockStatement.check(path.parent.node)) {
|
||||
// Insert the assignment form before the first statement in the
|
||||
// enclosing block.
|
||||
path.parent.get("body").unshift(assignment);
|
||||
|
||||
// Remove the function declaration now that we've inserted the
|
||||
// equivalent assignment form at the beginning of the block.
|
||||
path.replace();
|
||||
|
||||
} 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.replace(assignment);
|
||||
}
|
||||
|
||||
// Don't hoist variables out of inner functions.
|
||||
return false;
|
||||
},
|
||||
|
||||
visitFunctionExpression: function() {
|
||||
// Don't descend into nested function expressions.
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
var paramNames = {};
|
||||
funPath.get("params").each(function(paramPath) {
|
||||
var param = paramPath.value;
|
||||
if (n.Identifier.check(param)) {
|
||||
paramNames[param.name] = param;
|
||||
} else {
|
||||
// Variables declared by destructuring parameter patterns will be
|
||||
// harmlessly re-declared.
|
||||
}
|
||||
});
|
||||
|
||||
var declarations = [];
|
||||
|
||||
Object.keys(vars).forEach(function(name) {
|
||||
if (!hasOwn.call(paramNames, name)) {
|
||||
declarations.push(b.variableDeclarator(vars[name], null));
|
||||
}
|
||||
});
|
||||
|
||||
if (declarations.length === 0) {
|
||||
return null; // Be sure to handle this case!
|
||||
}
|
||||
|
||||
return b.variableDeclaration("var", declarations);
|
||||
};
|
||||
1
lib/6to5/transformation/transformers/generators/index.js
Normal file
1
lib/6to5/transformation/transformers/generators/index.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("./visit").transform;
|
||||
179
lib/6to5/transformation/transformers/generators/leap.js
Normal file
179
lib/6to5/transformation/transformers/generators/leap.js
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* 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");
|
||||
var types = require("ast-types");
|
||||
var n = types.namedTypes;
|
||||
var inherits = require("util").inherits;
|
||||
|
||||
function Entry() {
|
||||
assert.ok(this instanceof Entry);
|
||||
}
|
||||
|
||||
function FunctionEntry(returnLoc) {
|
||||
Entry.call(this);
|
||||
|
||||
n.Literal.assert(returnLoc);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
returnLoc: { value: returnLoc }
|
||||
});
|
||||
}
|
||||
|
||||
inherits(FunctionEntry, Entry);
|
||||
exports.FunctionEntry = FunctionEntry;
|
||||
|
||||
function LoopEntry(breakLoc, continueLoc, label) {
|
||||
Entry.call(this);
|
||||
|
||||
n.Literal.assert(breakLoc);
|
||||
n.Literal.assert(continueLoc);
|
||||
|
||||
if (label) {
|
||||
n.Identifier.assert(label);
|
||||
} else {
|
||||
label = null;
|
||||
}
|
||||
|
||||
Object.defineProperties(this, {
|
||||
breakLoc: { value: breakLoc },
|
||||
continueLoc: { value: continueLoc },
|
||||
label: { value: label }
|
||||
});
|
||||
}
|
||||
|
||||
inherits(LoopEntry, Entry);
|
||||
exports.LoopEntry = LoopEntry;
|
||||
|
||||
function SwitchEntry(breakLoc) {
|
||||
Entry.call(this);
|
||||
|
||||
n.Literal.assert(breakLoc);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
breakLoc: { value: breakLoc }
|
||||
});
|
||||
}
|
||||
|
||||
inherits(SwitchEntry, Entry);
|
||||
exports.SwitchEntry = SwitchEntry;
|
||||
|
||||
function TryEntry(firstLoc, catchEntry, finallyEntry) {
|
||||
Entry.call(this);
|
||||
|
||||
n.Literal.assert(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);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
firstLoc: { value: firstLoc },
|
||||
catchEntry: { value: catchEntry },
|
||||
finallyEntry: { value: finallyEntry }
|
||||
});
|
||||
}
|
||||
|
||||
inherits(TryEntry, Entry);
|
||||
exports.TryEntry = TryEntry;
|
||||
|
||||
function CatchEntry(firstLoc, paramId) {
|
||||
Entry.call(this);
|
||||
|
||||
n.Literal.assert(firstLoc);
|
||||
n.Identifier.assert(paramId);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
firstLoc: { value: firstLoc },
|
||||
paramId: { value: paramId }
|
||||
});
|
||||
}
|
||||
|
||||
inherits(CatchEntry, Entry);
|
||||
exports.CatchEntry = CatchEntry;
|
||||
|
||||
function FinallyEntry(firstLoc) {
|
||||
Entry.call(this);
|
||||
|
||||
n.Literal.assert(firstLoc);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
firstLoc: { value: firstLoc }
|
||||
});
|
||||
}
|
||||
|
||||
inherits(FinallyEntry, Entry);
|
||||
exports.FinallyEntry = FinallyEntry;
|
||||
|
||||
function LeapManager(emitter) {
|
||||
assert.ok(this instanceof LeapManager);
|
||||
|
||||
var Emitter = require("./emit").Emitter;
|
||||
assert.ok(emitter instanceof Emitter);
|
||||
|
||||
Object.defineProperties(this, {
|
||||
emitter: { value: emitter },
|
||||
entryStack: {
|
||||
value: [new FunctionEntry(emitter.finalLoc)]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var 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 {
|
||||
var 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];
|
||||
if (loc) {
|
||||
if (label) {
|
||||
if (entry.label &&
|
||||
entry.label.name === label.name) {
|
||||
return loc;
|
||||
}
|
||||
} else {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
LMp.getBreakLoc = function(label) {
|
||||
return this._findLeapLocation("breakLoc", label);
|
||||
};
|
||||
|
||||
LMp.getContinueLoc = function(label) {
|
||||
return this._findLeapLocation("continueLoc", label);
|
||||
};
|
||||
100
lib/6to5/transformation/transformers/generators/meta.js
Normal file
100
lib/6to5/transformation/transformers/generators/meta.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 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");
|
||||
var types = require("ast-types");
|
||||
var m = require("private").makeAccessor();
|
||||
var isArray = types.builtInTypes.array;
|
||||
var n = types.namedTypes;
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
function makePredicate(propertyName, knownTypes) {
|
||||
function onlyChildren(node) {
|
||||
n.Node.assert(node);
|
||||
|
||||
// Assume no side effects until we find out otherwise.
|
||||
var result = false;
|
||||
|
||||
function check(child) {
|
||||
if (result) {
|
||||
// Do nothing.
|
||||
} else if (isArray.check(child)) {
|
||||
child.some(check);
|
||||
} else if (n.Node.check(child)) {
|
||||
assert.strictEqual(result, false);
|
||||
result = predicate(child);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
types.eachField(node, function(name, child) {
|
||||
check(child);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function predicate(node) {
|
||||
n.Node.assert(node);
|
||||
|
||||
var 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;
|
||||
}
|
||||
|
||||
var opaqueTypes = {
|
||||
FunctionExpression: true
|
||||
};
|
||||
|
||||
// These types potentially have side effects regardless of what side
|
||||
// effects their subexpressions have.
|
||||
var 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.
|
||||
var leapTypes = {
|
||||
YieldExpression: true,
|
||||
BreakStatement: true,
|
||||
ContinueStatement: true,
|
||||
ReturnStatement: true,
|
||||
ThrowStatement: true
|
||||
};
|
||||
|
||||
// All leap types are also side effect types.
|
||||
for (var type in leapTypes) {
|
||||
if (hasOwn.call(leapTypes, type)) {
|
||||
sideEffectTypes[type] = leapTypes[type];
|
||||
}
|
||||
}
|
||||
|
||||
exports.hasSideEffects = makePredicate("hasSideEffects", sideEffectTypes);
|
||||
exports.containsLeap = makePredicate("containsLeap", leapTypes);
|
||||
459
lib/6to5/transformation/transformers/generators/runtime.js
Normal file
459
lib/6to5/transformation/transformers/generators/runtime.js
Normal file
@@ -0,0 +1,459 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
if (typeof global.regeneratorRuntime === "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
var iteratorSymbol = typeof Symbol === "function" && Symbol.iterator || "@@iterator";
|
||||
var runtime = global.regeneratorRuntime = exports;
|
||||
|
||||
var wrap = runtime.wrap = function wrap(innerFn, outerFn, self, tryList) {
|
||||
return new Generator(innerFn, outerFn, self || null, tryList || []);
|
||||
};
|
||||
|
||||
var GenStateSuspendedStart = "suspendedStart";
|
||||
var GenStateSuspendedYield = "suspendedYield";
|
||||
var GenStateExecuting = "executing";
|
||||
var GenStateCompleted = "completed";
|
||||
|
||||
// Returning this object from the innerFn has the same effect as
|
||||
// breaking out of the dispatch switch statement.
|
||||
var ContinueSentinel = {};
|
||||
|
||||
// Dummy constructor that we use as the .constructor property for
|
||||
// functions that return Generator objects.
|
||||
var GF = function GeneratorFunction() {};
|
||||
var GFp = function GeneratorFunctionPrototype() {};
|
||||
var Gp = GFp.prototype = Generator.prototype;
|
||||
(GFp.constructor = GF).prototype =
|
||||
Gp.constructor = GFp;
|
||||
|
||||
// Ensure isGeneratorFunction works when Function#name not supported.
|
||||
var GFName = "GeneratorFunction";
|
||||
if (GF.name !== GFName) GF.name = GFName;
|
||||
if (GF.name !== GFName) throw new Error(GFName + " renamed?");
|
||||
|
||||
runtime.isGeneratorFunction = function(genFun) {
|
||||
var ctor = genFun && genFun.constructor;
|
||||
return ctor ? GF.name === ctor.name : false;
|
||||
};
|
||||
|
||||
runtime.mark = function(genFun) {
|
||||
genFun.__proto__ = GFp;
|
||||
genFun.prototype = Object.create(Gp);
|
||||
return genFun;
|
||||
};
|
||||
|
||||
runtime.async = function(innerFn, outerFn, self, tryList) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var generator = wrap(innerFn, outerFn, self, tryList);
|
||||
var callNext = step.bind(generator.next);
|
||||
var callThrow = step.bind(generator["throw"]);
|
||||
|
||||
function step(arg) {
|
||||
var info;
|
||||
var value;
|
||||
|
||||
try {
|
||||
info = this(arg);
|
||||
value = info.value;
|
||||
} catch (error) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
if (info.done) {
|
||||
resolve(value);
|
||||
} else {
|
||||
Promise.resolve(value).then(callNext, callThrow);
|
||||
}
|
||||
}
|
||||
|
||||
callNext();
|
||||
});
|
||||
};
|
||||
|
||||
function Generator(innerFn, outerFn, self, tryList) {
|
||||
var generator = outerFn ? Object.create(outerFn.prototype) : this;
|
||||
var context = new Context(tryList);
|
||||
var state = GenStateSuspendedStart;
|
||||
|
||||
function invoke(method, arg) {
|
||||
if (state === GenStateExecuting) {
|
||||
throw new Error("Generator is already running");
|
||||
}
|
||||
|
||||
if (state === GenStateCompleted) {
|
||||
throw new Error("Generator has already finished");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var delegate = context.delegate;
|
||||
var info;
|
||||
|
||||
if (delegate) {
|
||||
try {
|
||||
info = delegate.iterator[method](arg);
|
||||
|
||||
// Delegate generator ran and handled its own exceptions so
|
||||
// regardless of what the method was, we continue as if it is
|
||||
// "next" with an undefined arg.
|
||||
method = "next";
|
||||
arg = undefined;
|
||||
|
||||
} catch (uncaught) {
|
||||
context.delegate = null;
|
||||
|
||||
// Like returning generator.throw(uncaught), but without the
|
||||
// overhead of an extra function call.
|
||||
method = "throw";
|
||||
arg = uncaught;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info.done) {
|
||||
context[delegate.resultName] = info.value;
|
||||
context.next = delegate.nextLoc;
|
||||
} else {
|
||||
state = GenStateSuspendedYield;
|
||||
return info;
|
||||
}
|
||||
|
||||
context.delegate = null;
|
||||
}
|
||||
|
||||
if (method === "next") {
|
||||
if (state === GenStateSuspendedStart &&
|
||||
typeof arg !== "undefined") {
|
||||
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
|
||||
throw new TypeError(
|
||||
"attempt to send " + JSON.stringify(arg) + " to newborn generator"
|
||||
);
|
||||
}
|
||||
|
||||
if (state === GenStateSuspendedYield) {
|
||||
context.sent = arg;
|
||||
} else {
|
||||
delete context.sent;
|
||||
}
|
||||
|
||||
} else if (method === "throw") {
|
||||
if (state === GenStateSuspendedStart) {
|
||||
state = GenStateCompleted;
|
||||
throw arg;
|
||||
}
|
||||
|
||||
if (context.dispatchException(arg)) {
|
||||
// If the dispatched exception was caught by a catch block,
|
||||
// then let that catch block handle the exception normally.
|
||||
method = "next";
|
||||
arg = undefined;
|
||||
}
|
||||
|
||||
} else if (method === "return") {
|
||||
context.abrupt("return", arg);
|
||||
}
|
||||
|
||||
state = GenStateExecuting;
|
||||
|
||||
try {
|
||||
var value = innerFn.call(self, context);
|
||||
|
||||
// If an exception is thrown from innerFn, we leave state ===
|
||||
// GenStateExecuting and loop back for another invocation.
|
||||
state = context.done ? GenStateCompleted : GenStateSuspendedYield;
|
||||
|
||||
info = {
|
||||
value: value,
|
||||
done: context.done
|
||||
};
|
||||
|
||||
if (value === ContinueSentinel) {
|
||||
if (context.delegate && method === "next") {
|
||||
// Deliberately forget the last sent value so that we don't
|
||||
// accidentally pass it on to the delegate.
|
||||
arg = undefined;
|
||||
}
|
||||
} else {
|
||||
return info;
|
||||
}
|
||||
|
||||
} catch (thrown) {
|
||||
state = GenStateCompleted;
|
||||
|
||||
if (method === "next") {
|
||||
context.dispatchException(thrown);
|
||||
} else {
|
||||
arg = thrown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generator.next = invoke.bind(generator, "next");
|
||||
generator["throw"] = invoke.bind(generator, "throw");
|
||||
generator["return"] = invoke.bind(generator, "return");
|
||||
|
||||
return generator;
|
||||
}
|
||||
|
||||
Gp[iteratorSymbol] = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
Gp.toString = function() {
|
||||
return "[object Generator]";
|
||||
};
|
||||
|
||||
function pushTryEntry(triple) {
|
||||
var entry = { tryLoc: triple[0] };
|
||||
|
||||
if (1 in triple) {
|
||||
entry.catchLoc = triple[1];
|
||||
}
|
||||
|
||||
if (2 in triple) {
|
||||
entry.finallyLoc = triple[2];
|
||||
}
|
||||
|
||||
this.tryEntries.push(entry);
|
||||
}
|
||||
|
||||
function resetTryEntry(entry, i) {
|
||||
var record = entry.completion || {};
|
||||
record.type = i === 0 ? "normal" : "return";
|
||||
delete record.arg;
|
||||
entry.completion = record;
|
||||
}
|
||||
|
||||
function Context(tryList) {
|
||||
// The root entry object (effectively a try statement without a catch
|
||||
// or a finally block) gives us a place to store values thrown from
|
||||
// locations where there is no enclosing try statement.
|
||||
this.tryEntries = [{ tryLoc: "root" }];
|
||||
tryList.forEach(pushTryEntry, this);
|
||||
this.reset();
|
||||
}
|
||||
|
||||
runtime.keys = function(object) {
|
||||
var keys = [];
|
||||
for (var key in object) {
|
||||
keys.push(key);
|
||||
}
|
||||
keys.reverse();
|
||||
|
||||
// Rather than returning an object with a next method, we keep
|
||||
// things simple and return the next function itself.
|
||||
return function next() {
|
||||
while (keys.length) {
|
||||
var key = keys.pop();
|
||||
if (key in object) {
|
||||
next.value = key;
|
||||
next.done = false;
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
// To avoid creating an additional object, we just hang the .value
|
||||
// and .done properties off the next function object itself. This
|
||||
// also ensures that the minifier will not anonymize the function.
|
||||
next.done = true;
|
||||
return next;
|
||||
};
|
||||
};
|
||||
|
||||
function values(iterable) {
|
||||
var iterator = iterable;
|
||||
if (iteratorSymbol in iterable) {
|
||||
iterator = iterable[iteratorSymbol]();
|
||||
} else if (!isNaN(iterable.length)) {
|
||||
var i = -1;
|
||||
iterator = function next() {
|
||||
while (++i < iterable.length) {
|
||||
if (i in iterable) {
|
||||
next.value = iterable[i];
|
||||
next.done = false;
|
||||
return next;
|
||||
}
|
||||
}
|
||||
next.done = true;
|
||||
return next;
|
||||
};
|
||||
iterator.next = iterator;
|
||||
}
|
||||
return iterator;
|
||||
}
|
||||
runtime.values = values;
|
||||
|
||||
Context.prototype = {
|
||||
constructor: Context,
|
||||
|
||||
reset: function() {
|
||||
this.prev = 0;
|
||||
this.next = 0;
|
||||
this.sent = undefined;
|
||||
this.done = false;
|
||||
this.delegate = null;
|
||||
|
||||
this.tryEntries.forEach(resetTryEntry);
|
||||
|
||||
// Pre-initialize at least 20 temporary variables to enable hidden
|
||||
// class optimizations for simple generators.
|
||||
for (var tempIndex = 0, tempName;
|
||||
hasOwn.call(this, tempName = "t" + tempIndex) || tempIndex < 20;
|
||||
++tempIndex) {
|
||||
this[tempName] = null;
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
this.done = true;
|
||||
|
||||
var rootEntry = this.tryEntries[0];
|
||||
var rootRecord = rootEntry.completion;
|
||||
if (rootRecord.type === "throw") {
|
||||
throw rootRecord.arg;
|
||||
}
|
||||
|
||||
return this.rval;
|
||||
},
|
||||
|
||||
dispatchException: function(exception) {
|
||||
if (this.done) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
var context = this;
|
||||
function handle(loc, caught) {
|
||||
record.type = "throw";
|
||||
record.arg = exception;
|
||||
context.next = loc;
|
||||
return !!caught;
|
||||
}
|
||||
|
||||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||||
var entry = this.tryEntries[i];
|
||||
var record = entry.completion;
|
||||
|
||||
if (entry.tryLoc === "root") {
|
||||
// Exception thrown outside of any try block that could handle
|
||||
// it, so set the completion value of the entire function to
|
||||
// throw the exception.
|
||||
return handle("end");
|
||||
}
|
||||
|
||||
if (entry.tryLoc <= this.prev) {
|
||||
var hasCatch = hasOwn.call(entry, "catchLoc");
|
||||
var hasFinally = hasOwn.call(entry, "finallyLoc");
|
||||
|
||||
if (hasCatch && hasFinally) {
|
||||
if (this.prev < entry.catchLoc) {
|
||||
return handle(entry.catchLoc, true);
|
||||
} else if (this.prev < entry.finallyLoc) {
|
||||
return handle(entry.finallyLoc);
|
||||
}
|
||||
|
||||
} else if (hasCatch) {
|
||||
if (this.prev < entry.catchLoc) {
|
||||
return handle(entry.catchLoc, true);
|
||||
}
|
||||
|
||||
} else if (hasFinally) {
|
||||
if (this.prev < entry.finallyLoc) {
|
||||
return handle(entry.finallyLoc);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error("try statement without catch or finally");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_findFinallyEntry: function(finallyLoc) {
|
||||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||||
var entry = this.tryEntries[i];
|
||||
if (entry.tryLoc <= this.prev &&
|
||||
hasOwn.call(entry, "finallyLoc") && (
|
||||
entry.finallyLoc === finallyLoc ||
|
||||
this.prev < entry.finallyLoc)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
abrupt: function(type, arg) {
|
||||
var entry = this._findFinallyEntry();
|
||||
var record = entry ? entry.completion : {};
|
||||
|
||||
record.type = type;
|
||||
record.arg = arg;
|
||||
|
||||
if (entry) {
|
||||
this.next = entry.finallyLoc;
|
||||
} else {
|
||||
this.complete(record);
|
||||
}
|
||||
|
||||
return ContinueSentinel;
|
||||
},
|
||||
|
||||
complete: function(record) {
|
||||
if (record.type === "throw") {
|
||||
throw record.arg;
|
||||
}
|
||||
|
||||
if (record.type === "break" ||
|
||||
record.type === "continue") {
|
||||
this.next = record.arg;
|
||||
} else if (record.type === "return") {
|
||||
this.rval = record.arg;
|
||||
this.next = "end";
|
||||
}
|
||||
|
||||
return ContinueSentinel;
|
||||
},
|
||||
|
||||
finish: function(finallyLoc) {
|
||||
var entry = this._findFinallyEntry(finallyLoc);
|
||||
return this.complete(entry.completion);
|
||||
},
|
||||
|
||||
"catch": function(tryLoc) {
|
||||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||||
var entry = this.tryEntries[i];
|
||||
if (entry.tryLoc === tryLoc) {
|
||||
var record = entry.completion;
|
||||
var thrown;
|
||||
if (record.type === "throw") {
|
||||
thrown = record.arg;
|
||||
resetTryEntry(entry, i);
|
||||
}
|
||||
return thrown;
|
||||
}
|
||||
}
|
||||
|
||||
// The context.catch method must only be called with a location
|
||||
// argument that corresponds to a known catch block.
|
||||
throw new Error("illegal catch attempt");
|
||||
},
|
||||
|
||||
delegateYield: function(iterable, resultName, nextLoc) {
|
||||
this.delegate = {
|
||||
iterator: values(iterable),
|
||||
resultName: resultName,
|
||||
nextLoc: nextLoc
|
||||
};
|
||||
|
||||
return ContinueSentinel;
|
||||
}
|
||||
};
|
||||
37
lib/6to5/transformation/transformers/generators/util.js
Normal file
37
lib/6to5/transformation/transformers/generators/util.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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 b = require("ast-types").builders;
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
exports.defaults = function(obj) {
|
||||
var len = arguments.length;
|
||||
var extension;
|
||||
|
||||
for (var i = 1; i < len; ++i) {
|
||||
if ((extension = arguments[i])) {
|
||||
for (var key in extension) {
|
||||
if (hasOwn.call(extension, key) && !hasOwn.call(obj, key)) {
|
||||
obj[key] = extension[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
exports.runtimeProperty = function(name) {
|
||||
return b.memberExpression(
|
||||
b.identifier("regeneratorRuntime"),
|
||||
b.identifier(name),
|
||||
false
|
||||
);
|
||||
};
|
||||
222
lib/6to5/transformation/transformers/generators/visit.js
Normal file
222
lib/6to5/transformation/transformers/generators/visit.js
Normal file
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* 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 types = require("ast-types");
|
||||
var n = types.namedTypes;
|
||||
var b = types.builders;
|
||||
var hoist = require("./hoist").hoist;
|
||||
var Emitter = require("./emit").Emitter;
|
||||
var runtimeProperty = require("./util").runtimeProperty;
|
||||
var runtimeWrapMethod = runtimeProperty("wrap");
|
||||
var runtimeMarkMethod = runtimeProperty("mark");
|
||||
var runtimeAsyncMethod = runtimeProperty("async");
|
||||
|
||||
exports.transform = function transform(node) {
|
||||
return types.visit(node, visitor);
|
||||
};
|
||||
|
||||
var visitor = types.PathVisitor.fromMethodsObject({
|
||||
visitFunction: function(path) {
|
||||
// Calling this.traverse(path) first makes for a post-order traversal.
|
||||
this.traverse(path);
|
||||
|
||||
var node = path.value;
|
||||
|
||||
if (!node.generator && !node.async) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.generator = false;
|
||||
|
||||
if (node.expression) {
|
||||
// Transform expression lambdas into normal functions.
|
||||
node.expression = false;
|
||||
node.body = b.blockStatement([
|
||||
b.returnStatement(node.body)
|
||||
]);
|
||||
}
|
||||
|
||||
if (node.async) {
|
||||
awaitVisitor.visit(path.get("body"));
|
||||
}
|
||||
|
||||
var outerFnId = node.id || (
|
||||
node.id = path.scope.parent.declareTemporary("callee$")
|
||||
);
|
||||
|
||||
var innerFnId = b.identifier(node.id.name + "$");
|
||||
var contextId = path.scope.declareTemporary("context$");
|
||||
var vars = hoist(path);
|
||||
|
||||
var emitter = new Emitter(contextId);
|
||||
emitter.explode(path.get("body"));
|
||||
|
||||
var outerBody = [];
|
||||
|
||||
if (vars && vars.declarations.length > 0) {
|
||||
outerBody.push(vars);
|
||||
}
|
||||
|
||||
var wrapArgs = [
|
||||
emitter.getContextFunction(innerFnId),
|
||||
// Async functions don't care about the outer function because they
|
||||
// don't need it to be marked and don't inherit from its .prototype.
|
||||
node.async ? b.literal(null) : outerFnId,
|
||||
b.thisExpression()
|
||||
];
|
||||
|
||||
var tryEntryList = emitter.getTryEntryList();
|
||||
if (tryEntryList) {
|
||||
wrapArgs.push(tryEntryList);
|
||||
}
|
||||
|
||||
var wrapCall = b.callExpression(
|
||||
node.async ? runtimeAsyncMethod : runtimeWrapMethod,
|
||||
wrapArgs
|
||||
);
|
||||
|
||||
outerBody.push(b.returnStatement(wrapCall));
|
||||
node.body = b.blockStatement(outerBody);
|
||||
|
||||
if (node.async) {
|
||||
node.async = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (n.FunctionDeclaration.check(node)) {
|
||||
var pp = path.parent;
|
||||
|
||||
while (pp && !(n.BlockStatement.check(pp.value) ||
|
||||
n.Program.check(pp.value))) {
|
||||
pp = pp.parent;
|
||||
}
|
||||
|
||||
if (!pp) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Here we turn the FunctionDeclaration into a named
|
||||
// FunctionExpression that will be assigned to a variable of the
|
||||
// same name at the top of the enclosing block. This is important
|
||||
// for a very subtle reason: named function expressions can refer to
|
||||
// themselves by name without fear that the binding may change due
|
||||
// to code executing outside the function, whereas function
|
||||
// declarations are vulnerable to the following rebinding:
|
||||
//
|
||||
// function f() { return f }
|
||||
// var g = f;
|
||||
// f = "asdf";
|
||||
// g(); // "asdf"
|
||||
//
|
||||
// One way to prevent the problem illustrated above is to transform
|
||||
// the function declaration thus:
|
||||
//
|
||||
// var f = function f() { return f };
|
||||
// var g = f;
|
||||
// f = "asdf";
|
||||
// g(); // f
|
||||
// g()()()()(); // f
|
||||
//
|
||||
// In the code below, we transform generator function declarations
|
||||
// in the following way:
|
||||
//
|
||||
// gen().next(); // { value: gen, done: true }
|
||||
// function *gen() {
|
||||
// return gen;
|
||||
// }
|
||||
//
|
||||
// becomes something like
|
||||
//
|
||||
// var gen = runtime.mark(function *gen() {
|
||||
// return gen;
|
||||
// });
|
||||
// gen().next(); // { value: gen, done: true }
|
||||
//
|
||||
// which ensures that the generator body can always reliably refer
|
||||
// to gen by name.
|
||||
|
||||
// Remove the FunctionDeclaration so that we can add it back as a
|
||||
// FunctionExpression passed to runtime.mark.
|
||||
path.replace();
|
||||
|
||||
// Change the type of the function to be an expression instead of a
|
||||
// declaration. Note that all the other fields are the same.
|
||||
node.type = "FunctionExpression";
|
||||
|
||||
var varDecl = b.variableDeclaration("var", [
|
||||
b.variableDeclarator(
|
||||
node.id,
|
||||
b.callExpression(runtimeMarkMethod, [node])
|
||||
)
|
||||
]);
|
||||
|
||||
if (node.comments) {
|
||||
// Copy any comments preceding the function declaration to the
|
||||
// variable declaration, to avoid weird formatting consequences.
|
||||
varDecl.comments = node.comments;
|
||||
node.comments = null;
|
||||
}
|
||||
|
||||
var bodyPath = pp.get("body");
|
||||
var bodyLen = bodyPath.value.length;
|
||||
|
||||
for (var i = 0; i < bodyLen; ++i) {
|
||||
var firstStmtPath = bodyPath.get(i);
|
||||
if (!shouldNotHoistAbove(firstStmtPath)) {
|
||||
firstStmtPath.insertBefore(varDecl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bodyPath.push(varDecl);
|
||||
|
||||
} else {
|
||||
n.FunctionExpression.assert(node);
|
||||
return b.callExpression(runtimeMarkMethod, [node]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function shouldNotHoistAbove(stmtPath) {
|
||||
var value = stmtPath.value;
|
||||
n.Statement.assert(value);
|
||||
|
||||
// If the first statement is a "use strict" declaration, make sure to
|
||||
// insert hoisted declarations afterwards.
|
||||
if (n.ExpressionStatement.check(value) &&
|
||||
n.Literal.check(value.expression) &&
|
||||
value.expression.value === "use strict") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (n.VariableDeclaration.check(value)) {
|
||||
for (var i = 0; i < value.declarations.length; ++i) {
|
||||
var decl = value.declarations[i];
|
||||
if (n.CallExpression.check(decl.init) &&
|
||||
types.astNodesAreEquivalent(decl.init.callee,
|
||||
runtimeMarkMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var awaitVisitor = types.PathVisitor.fromMethodsObject({
|
||||
visitFunction: function() {
|
||||
return false; // Don't descend into nested function scopes.
|
||||
},
|
||||
|
||||
visitAwaitExpression: function(path) {
|
||||
// Convert await expressions to yield expressions.
|
||||
return b.yieldExpression(path.value.argument, false);
|
||||
}
|
||||
});
|
||||
@@ -128,6 +128,12 @@ LetScoping.prototype.run = function () {
|
||||
var call = t.callExpression(fn, params);
|
||||
var ret = t.identifier(this.file.generateUid("ret", this.scope));
|
||||
|
||||
var hasYield = traverse.hasType(fn.body, "YieldExpression", t.FUNCTION_TYPES);
|
||||
if (hasYield) {
|
||||
fn.generator = true;
|
||||
call = t.yieldExpression(call, true);
|
||||
}
|
||||
|
||||
this.build(ret, call);
|
||||
};
|
||||
|
||||
@@ -245,28 +251,34 @@ LetScoping.prototype.checkFor = function () {
|
||||
hasBreak: false,
|
||||
};
|
||||
|
||||
if (this.forParent) {
|
||||
traverse(this.block, function (node) {
|
||||
var replace;
|
||||
var forParent = this.forParent;
|
||||
|
||||
if (t.isFunction(node) || t.isFor(node)) {
|
||||
return false;
|
||||
} else if (t.isBreakStatement(node) && !node.label) {
|
||||
traverse(this.block, function (node) {
|
||||
var replace;
|
||||
|
||||
if (t.isFunction(node) || t.isFor(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (forParent && !node.label) {
|
||||
if (t.isBreakStatement(node)) {
|
||||
has.hasBreak = true;
|
||||
replace = t.returnStatement(t.literal("break"));
|
||||
} else if (t.isContinueStatement(node) && !node.label) {
|
||||
} else if (t.isContinueStatement(node)) {
|
||||
has.hasContinue = true;
|
||||
replace = t.returnStatement(t.literal("continue"));
|
||||
} else if (t.isReturnStatement(node)) {
|
||||
has.hasReturn = true;
|
||||
replace = t.returnStatement(t.objectExpression([
|
||||
t.property("init", t.identifier("v"), node.argument || t.identifier("undefined"))
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
if (replace) return t.inherits(replace, node);
|
||||
});
|
||||
}
|
||||
if (t.isReturnStatement(node)) {
|
||||
has.hasReturn = true;
|
||||
replace = t.returnStatement(t.objectExpression([
|
||||
t.property("init", t.identifier("v"), node.argument || t.identifier("undefined"))
|
||||
]));
|
||||
}
|
||||
|
||||
if (replace) return t.inherits(replace, node);
|
||||
});
|
||||
|
||||
return has;
|
||||
};
|
||||
|
||||
@@ -21,5 +21,6 @@
|
||||
"SequenceExpression": ["expressions"],
|
||||
"UnaryExpression": ["operator", "argument", "prefix"],
|
||||
"VariableDeclaration": ["kind", "declarations"],
|
||||
"VariableDeclarator": ["id", "init"]
|
||||
"VariableDeclarator": ["id", "init"],
|
||||
"YieldExpression": ["argument", "delegate"]
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "6to5",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "1.12.17",
|
||||
"version": "1.12.20",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://github.com/6to5/6to5",
|
||||
"repository": {
|
||||
@@ -44,12 +44,12 @@
|
||||
"es6-symbol": "0.1.1",
|
||||
"regexpu": "0.3.0",
|
||||
"source-map": "0.1.40",
|
||||
"regenerator-6to5": "https://github.com/6to5/regenerator-6to5/archive/a9c53518af063ffef410f826225f8ee250131932.tar.gz",
|
||||
"chokidar": "0.10.5",
|
||||
"source-map-support": "0.2.8",
|
||||
"esutils": "1.1.4",
|
||||
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/74d8e9bed20ba302d3504f53d0b1c649968959e1.tar.gz",
|
||||
"estraverse": "^1.7.0"
|
||||
"estraverse": "^1.7.0",
|
||||
"private": "^0.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "0.3.2",
|
||||
|
||||
33
test/_generator-helpers.js
Normal file
33
test/_generator-helpers.js
Normal file
@@ -0,0 +1,33 @@
|
||||
var assert = require("assert");
|
||||
|
||||
exports.check = function check(g, yields, returnValue) {
|
||||
for (var i = 0; i < yields.length; ++i) {
|
||||
var info = i > 0 ? g.next(i) : g.next();
|
||||
assert.deepEqual(info.value, yields[i]);
|
||||
assert.strictEqual(info.done, false);
|
||||
}
|
||||
|
||||
assert.deepEqual(
|
||||
i > 0 ? g.next(i) : g.next(),
|
||||
{ value: returnValue, done: true }
|
||||
);
|
||||
};
|
||||
|
||||
// A version of `throw` whose behavior can't be statically analyzed.
|
||||
// Useful for testing dynamic exception dispatching.
|
||||
exports.raise = function raise(argument) {
|
||||
throw argument;
|
||||
};
|
||||
|
||||
exports.assertAlreadyFinished = function assertAlreadyFinished(generator) {
|
||||
try {
|
||||
generator.next();
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(
|
||||
err.message,
|
||||
"Generator has already finished"
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
var Test = function Test() {};
|
||||
//# sourceMappingURL=bar.js.map
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
arr.map(function (x) {
|
||||
return x * MULTIPLIER;
|
||||
});
|
||||
//# sourceMappingURL=foo.js.map
|
||||
|
||||
@@ -6,3 +6,5 @@ var Test = function Test() {};
|
||||
arr.map(function (x) {
|
||||
return x * MULTIPLIER;
|
||||
});
|
||||
|
||||
//# sourceMappingURL=script3.js.map
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
arr.map(function (x) {
|
||||
return x * x;
|
||||
});
|
||||
|
||||
//# sourceMappingURL=test.js.map
|
||||
|
||||
7
test/fixtures/transformation/async/LICENSE
vendored
Normal file
7
test/fixtures/transformation/async/LICENSE
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
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.
|
||||
26
test/fixtures/transformation/async/dependent-promises-should-be-awaitable-out-of-order/exec.js
vendored
Normal file
26
test/fixtures/transformation/async/dependent-promises-should-be-awaitable-out-of-order/exec.js
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
async function outer(value) {
|
||||
var resolved = false;
|
||||
var p1 = new Promise(function(resolve) {
|
||||
setTimeout(function() {
|
||||
resolve(value + 1);
|
||||
resolved = true;
|
||||
}, 0);
|
||||
});
|
||||
|
||||
assert.strictEqual(resolved, false);
|
||||
|
||||
var v2 = await p1.then(function(value) {
|
||||
return value + 1;
|
||||
});
|
||||
|
||||
assert.strictEqual(resolved, true);
|
||||
|
||||
var v1 = await p1;
|
||||
|
||||
return [v1, v2];
|
||||
}
|
||||
|
||||
outer(1).then(function(pair) {
|
||||
assert.deepEqual(pair, [2, 3]);
|
||||
done();
|
||||
}).catch(done);
|
||||
@@ -0,0 +1,40 @@
|
||||
var markers = [];
|
||||
|
||||
async function innerMost(marker) {
|
||||
markers.push(marker);
|
||||
return await marker;
|
||||
}
|
||||
|
||||
async function inner(marker) {
|
||||
markers.push(marker);
|
||||
|
||||
assert.strictEqual(
|
||||
await innerMost(marker + 1),
|
||||
marker + 1
|
||||
);
|
||||
|
||||
markers.push(marker + 2);
|
||||
|
||||
assert.strictEqual(
|
||||
await innerMost(marker + 3),
|
||||
marker + 3
|
||||
);
|
||||
|
||||
markers.push(marker + 4);
|
||||
}
|
||||
|
||||
async function outer() {
|
||||
markers.push(0);
|
||||
await inner(1);
|
||||
markers.push(6);
|
||||
await inner(7);
|
||||
markers.push(12);
|
||||
}
|
||||
|
||||
outer().then(function() {
|
||||
var expected = [];
|
||||
for (var i = 0; i <= 12; ++i)
|
||||
expected.push(i);
|
||||
assert.deepEqual(markers, expected);
|
||||
done();
|
||||
}).catch(done);
|
||||
15
test/fixtures/transformation/async/no-await-async-function-should-return-a-Promise/exec.js
vendored
Normal file
15
test/fixtures/transformation/async/no-await-async-function-should-return-a-Promise/exec.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
var called = false;
|
||||
|
||||
async function noAwait(value) {
|
||||
called = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
var promise = noAwait("asdf");
|
||||
assert.strictEqual(called, true);
|
||||
|
||||
promise.then(function(value) {
|
||||
assert.strictEqual(called, true);
|
||||
assert.strictEqual(value, "asdf");
|
||||
done();
|
||||
}).catch(done);
|
||||
19
test/fixtures/transformation/async/one-await-async-function-should-finish-asynchronously/exec.js
vendored
Normal file
19
test/fixtures/transformation/async/one-await-async-function-should-finish-asynchronously/exec.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
var flag1 = false;
|
||||
var flag2 = false;
|
||||
|
||||
async function oneAwait(value) {
|
||||
flag1 = true;
|
||||
var result = await value;
|
||||
flag2 = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
3
test/fixtures/transformation/async/options.json
vendored
Normal file
3
test/fixtures/transformation/async/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"asyncExec": true
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
var error = new Error("rejected");
|
||||
|
||||
async function e(arg) {
|
||||
if (arg) {
|
||||
throw arg;
|
||||
}
|
||||
return "did not throw";
|
||||
}
|
||||
|
||||
async function f(arg) {
|
||||
return await e(arg);
|
||||
}
|
||||
|
||||
async function g(arg) {
|
||||
return await f(arg);
|
||||
}
|
||||
|
||||
async function h(arg) {
|
||||
return await Promise.all([
|
||||
g(arg),
|
||||
Promise.resolve("dummy")
|
||||
]);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -0,0 +1,21 @@
|
||||
var error = new Error("rejected");
|
||||
|
||||
async function f(arg) {
|
||||
try {
|
||||
return await arg;
|
||||
} catch (e) {
|
||||
assert.strictEqual(e, error);
|
||||
return "did throw";
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
7
test/fixtures/transformation/generators/LICENSE
vendored
Normal file
7
test/fixtures/transformation/generators/LICENSE
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
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.
|
||||
@@ -0,0 +1,24 @@
|
||||
function *gen() {
|
||||
var a$0 = 0, a$1 = 1;
|
||||
|
||||
let a = 3;
|
||||
|
||||
{
|
||||
let a = 1;
|
||||
yield a + a$0;
|
||||
}
|
||||
|
||||
{
|
||||
let a = 2;
|
||||
yield a - 1 + a$1;
|
||||
}
|
||||
|
||||
yield a;
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.deepEqual(g.next(), { value: 1, done: false });
|
||||
assert.deepEqual(g.next(), { value: 2, done: false });
|
||||
assert.deepEqual(g.next(), { value: 3, done: false });
|
||||
assert.deepEqual(g.next(), { value: void 0, done: true });
|
||||
@@ -0,0 +1,22 @@
|
||||
function *gen() {
|
||||
let arr = [];
|
||||
|
||||
for (let x = 0; x < 3; x++) {
|
||||
let y = x;
|
||||
arr.push(function() { return y; });
|
||||
}
|
||||
|
||||
{
|
||||
let x;
|
||||
while( x = arr.pop() ) {
|
||||
yield x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.equal(g.next().value(), 2);
|
||||
assert.equal(g.next().value(), 1);
|
||||
assert.equal(g.next().value(), 0);
|
||||
assert.deepEqual(g.next(), { value: void 0, done: true });
|
||||
@@ -0,0 +1,15 @@
|
||||
function *gen() {
|
||||
try {
|
||||
genHelpers.raise("e1");
|
||||
} catch (e) {
|
||||
yield e;
|
||||
try {
|
||||
genHelpers.raise("e2");
|
||||
} catch (e) {
|
||||
yield e;
|
||||
}
|
||||
yield e;
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(gen(), ["e1", "e2", "e1"]);
|
||||
@@ -0,0 +1,22 @@
|
||||
function *gen(x) {
|
||||
var y = x + 1;
|
||||
try {
|
||||
throw x + 2;
|
||||
} catch (x) {
|
||||
yield x;
|
||||
x += 1;
|
||||
yield x;
|
||||
}
|
||||
yield x;
|
||||
try {
|
||||
throw x + 3;
|
||||
} catch (y) {
|
||||
yield y;
|
||||
y *= 2;
|
||||
yield y;
|
||||
}
|
||||
yield y;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(1), [3, 4, 1, 4, 8, 2]);
|
||||
genHelpers.check(gen(2), [4, 5, 2, 5, 10, 3]);
|
||||
@@ -0,0 +1,32 @@
|
||||
function *gen(x) {
|
||||
try {
|
||||
throw x;
|
||||
} catch (x) {
|
||||
yield x;
|
||||
|
||||
yield (function(x) {
|
||||
return x += 1;
|
||||
}(x + 1));
|
||||
|
||||
yield (function() {
|
||||
var x = arguments[0];
|
||||
return x * 2;
|
||||
}(x + 2));
|
||||
|
||||
yield (function() {
|
||||
function notCalled(x) {
|
||||
throw x;
|
||||
}
|
||||
|
||||
x >>= 1;
|
||||
return x;
|
||||
}());
|
||||
|
||||
yield x -= 1;
|
||||
}
|
||||
|
||||
yield x;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(10), [10, 12, 24, 5, 4, 10]);
|
||||
genHelpers.check(gen(11), [11, 13, 26, 5, 4, 11]);
|
||||
42
test/fixtures/transformation/generators/collatz-generator/exec.js
vendored
Normal file
42
test/fixtures/transformation/generators/collatz-generator/exec.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
function *gen(n) {
|
||||
var count = 0;
|
||||
|
||||
yield n;
|
||||
|
||||
while (n !== 1) {
|
||||
count += 1;
|
||||
|
||||
if (n % 2) {
|
||||
yield n = n * 3 + 1;
|
||||
} else {
|
||||
yield n >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
function collatz(n) {
|
||||
var result = [n];
|
||||
|
||||
while (n !== 1) {
|
||||
if (n % 2) {
|
||||
n *= 3;
|
||||
n += 1;
|
||||
} else {
|
||||
n >>= 1;
|
||||
}
|
||||
|
||||
result.push(n);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var seven = collatz(7);
|
||||
var fiftyTwo = seven.slice(seven.indexOf(52));
|
||||
var eightyTwo = collatz(82);
|
||||
|
||||
genHelpers.check(gen(7), seven, 16);
|
||||
genHelpers.check(gen(52), fiftyTwo, 11);
|
||||
genHelpers.check(gen(82), eightyTwo, 110);
|
||||
11
test/fixtures/transformation/generators/completed-generator/exec.js
vendored
Normal file
11
test/fixtures/transformation/generators/completed-generator/exec.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
function *gen() {
|
||||
return "ALL DONE";
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.deepEqual(g.next(), {
|
||||
value: "ALL DONE", done: true
|
||||
});
|
||||
|
||||
genHelpers.assertAlreadyFinished(g);
|
||||
@@ -0,0 +1,27 @@
|
||||
var error = new Error("thrown");
|
||||
|
||||
function *outer(n) {
|
||||
try {
|
||||
yield 0;
|
||||
yield* inner(n);
|
||||
yield 1;
|
||||
} catch (err) {
|
||||
yield err.message;
|
||||
}
|
||||
yield 4;
|
||||
}
|
||||
|
||||
function *inner(n) {
|
||||
while (n --> 0) {
|
||||
try {
|
||||
if (n === 3) {
|
||||
genHelpers.raise(error);
|
||||
}
|
||||
} finally {
|
||||
yield n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(outer(3), [0, 2, 1, 0, 1, 4]);
|
||||
genHelpers.check(outer(5), [0, 4, 3, "thrown", 4]);
|
||||
@@ -0,0 +1,10 @@
|
||||
function *gen(condition) {
|
||||
if (condition) {
|
||||
yield 0;
|
||||
yield* gen(false);
|
||||
yield 1;
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(gen(true), [0, 1]);
|
||||
genHelpers.check(gen(false), []);
|
||||
12
test/fixtures/transformation/generators/delegated-yield-should-delegate-correctly/exec.js
vendored
Normal file
12
test/fixtures/transformation/generators/delegated-yield-should-delegate-correctly/exec.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
function *gen(condition) {
|
||||
yield 0;
|
||||
if (condition) {
|
||||
yield 1;
|
||||
yield* gen(false);
|
||||
yield 2;
|
||||
}
|
||||
yield 3;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(true), [0, 1, 0, 3, 2, 3]);
|
||||
genHelpers.check(gen(false), [0, 3]);
|
||||
@@ -0,0 +1,37 @@
|
||||
var count = 0;
|
||||
|
||||
function *gen() {
|
||||
yield* inner();
|
||||
try {
|
||||
yield* inner();
|
||||
} catch (err) {
|
||||
// pass
|
||||
}
|
||||
return yield* inner();
|
||||
}
|
||||
|
||||
function *inner() {
|
||||
return yield count++;
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.deepEqual(g.next(), {
|
||||
value: 0,
|
||||
done: false
|
||||
});
|
||||
|
||||
assert.deepEqual(g.next(), {
|
||||
value: 1,
|
||||
done: false
|
||||
});
|
||||
|
||||
assert.deepEqual(g.throw(new Error("lol")), {
|
||||
value: 2,
|
||||
done: false,
|
||||
});
|
||||
|
||||
assert.deepEqual(g.next("sent"), {
|
||||
value: "sent",
|
||||
done: true
|
||||
});
|
||||
15
test/fixtures/transformation/generators/delegated-yield-should-pass-sent-values-through/exec.js
vendored
Normal file
15
test/fixtures/transformation/generators/delegated-yield-should-pass-sent-values-through/exec.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
function *outer(n) {
|
||||
yield* inner(n << 1);
|
||||
yield "zxcv";
|
||||
}
|
||||
|
||||
function *inner(n) {
|
||||
return yield yield yield n;
|
||||
}
|
||||
|
||||
var g = outer(3);
|
||||
assert.deepEqual(g.next(), { value: 6, done: false });
|
||||
assert.deepEqual(g.next(1), { value: 1, done: false });
|
||||
assert.deepEqual(g.next(2), { value: 2, done: false });
|
||||
assert.deepEqual(g.next(4), { value: "zxcv", done: false });
|
||||
assert.deepEqual(g.next(5), { value: void 0, done: true });
|
||||
18
test/fixtures/transformation/generators/delegated-yield-should-support-deeper-nesting/exec.js
vendored
Normal file
18
test/fixtures/transformation/generators/delegated-yield-should-support-deeper-nesting/exec.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
function *outer(n) {
|
||||
yield n;
|
||||
yield* middle(n - 1, inner(n + 10));
|
||||
yield n + 1;
|
||||
}
|
||||
|
||||
function *middle(n, plusTen) {
|
||||
yield n;
|
||||
yield* inner(n - 1);
|
||||
yield n + 1;
|
||||
yield* plusTen;
|
||||
}
|
||||
|
||||
function *inner(n) {
|
||||
yield n;
|
||||
}
|
||||
|
||||
genHelpers.check(outer(5), [5, 4, 3, 5, 15, 6]);
|
||||
@@ -0,0 +1,11 @@
|
||||
function *gen() {
|
||||
yield 0;
|
||||
yield* [
|
||||
yield "one",
|
||||
yield "two",
|
||||
yield "three"
|
||||
];
|
||||
yield 5;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(), [0, "one", "two", "three", 2, 3, 4, 5]);
|
||||
20
test/fixtures/transformation/generators/dynamic-exception-should-be-dispatched-correctly/exec.js
vendored
Normal file
20
test/fixtures/transformation/generators/dynamic-exception-should-be-dispatched-correctly/exec.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
function *gen(x, fname) {
|
||||
try {
|
||||
return fns[fname](x);
|
||||
} catch (thrown) {
|
||||
yield thrown;
|
||||
}
|
||||
}
|
||||
|
||||
var fns = {
|
||||
f: function(x) {
|
||||
throw x;
|
||||
},
|
||||
|
||||
g: function(x) {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
genHelpers.check(gen("asdf", "f"), ["asdf"]);
|
||||
genHelpers.check(gen("asdf", "g"), [], "asdf");
|
||||
@@ -0,0 +1,16 @@
|
||||
function *gen(x) {
|
||||
while (x) {
|
||||
// empty while loop
|
||||
}
|
||||
|
||||
do {
|
||||
// empty do-while loop
|
||||
} while (x);
|
||||
|
||||
return gen.toString();
|
||||
}
|
||||
|
||||
var info = gen(false).next();
|
||||
assert.strictEqual(info.done, true);
|
||||
assert.ok(/do \{/.test(info.value));
|
||||
assert.ok(/while \(/.test(info.value));
|
||||
@@ -0,0 +1,19 @@
|
||||
function *gen(obj) {
|
||||
var count = 0;
|
||||
for (var key in (yield "why not", obj)) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (key === "skip") {
|
||||
break;
|
||||
}
|
||||
count += 1;
|
||||
yield [key, obj[key]];
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
genHelpers.check(
|
||||
gen({ a: 1, b: 2, skip: 3, c: 4 }),
|
||||
["why not", ["a", 1], ["b", 2]],
|
||||
2
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
function *gen() {
|
||||
var count = 0;
|
||||
var obj = {foo: 1, bar: 2};
|
||||
for (var key in obj) {
|
||||
assert(obj.hasOwnProperty(key), key + " must be own property");
|
||||
yield [key, obj[key]];
|
||||
delete obj.bar;
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(), [["foo", 1]], 1);
|
||||
@@ -0,0 +1,26 @@
|
||||
function a(sent) {
|
||||
assert.strictEqual(sent, 1);
|
||||
a.called = true;
|
||||
}
|
||||
|
||||
function b(sent) {
|
||||
assert.strictEqual(sent, 2);
|
||||
b.called = true;
|
||||
return { callee: b };
|
||||
}
|
||||
|
||||
function *gen() {
|
||||
assert.ok(!a.called);
|
||||
assert.ok(!b.called);
|
||||
for (var key in a(yield 0), b(yield 1)) {
|
||||
assert.ok(a.called);
|
||||
assert.ok(b.called);
|
||||
assert.strictEqual(yield key, 3);
|
||||
}
|
||||
|
||||
for (var key in a(1), { foo: "foo", bar: "bar" }) {
|
||||
yield key;
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(gen(), [0, 1, "callee", "foo", "bar"]);
|
||||
@@ -0,0 +1,12 @@
|
||||
function *gen() {
|
||||
var count = 0;
|
||||
var obj = {foo: 1, bar: 2};
|
||||
for (var key in obj) {
|
||||
assert(obj.hasOwnProperty(key), key + " must be own property");
|
||||
yield [key, obj[key]];
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(), [["foo", 1], ["bar", 2]], 2);
|
||||
@@ -0,0 +1,16 @@
|
||||
function *gen() {
|
||||
var count = 0;
|
||||
function Foo() {
|
||||
this.baz = 1
|
||||
}
|
||||
Foo.prototype.bar = 2;
|
||||
|
||||
var foo = new Foo();
|
||||
for (var key in foo) {
|
||||
yield [key, foo[key]];
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
genHelpers.check(gen(), [["baz", 1], ["bar", 2]], 2);
|
||||
@@ -0,0 +1,7 @@
|
||||
// https://github.com/facebook/regenerator/issues/103
|
||||
function *range() {
|
||||
for (var i = 0; false; ) {
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(range(), []);
|
||||
5
test/fixtures/transformation/generators/for-of-loops-should-work-for-Arrays/exec.js
vendored
Normal file
5
test/fixtures/transformation/generators/for-of-loops-should-work-for-Arrays/exec.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
var sum = 0;
|
||||
for (var x of [1, 2].concat(3)) {
|
||||
sum += x;
|
||||
}
|
||||
assert.strictEqual(sum, 6);
|
||||
10
test/fixtures/transformation/generators/for-of-loops-should-work-for-generators/exec.js
vendored
Normal file
10
test/fixtures/transformation/generators/for-of-loops-should-work-for-generators/exec.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
function *range(n) {
|
||||
for (var i = 0; i < n; ++i) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
var value, values = [];
|
||||
for (value of range(3))
|
||||
values.push(value);
|
||||
assert.deepEqual(values, [0, 1, 2]);
|
||||
45
test/fixtures/transformation/generators/for-of-loops-should-work-inside-of-generators/exec.js
vendored
Normal file
45
test/fixtures/transformation/generators/for-of-loops-should-work-inside-of-generators/exec.js
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
function *yieldPermutations(list) {
|
||||
if (list.length < 2) {
|
||||
yield list;
|
||||
return 1;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var first = list.slice(0, 1);
|
||||
var genRest = yieldPermutations(list.slice(1));
|
||||
|
||||
for (var perm of genRest) {
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
var prefix = perm.slice(0, i);
|
||||
var suffix = perm.slice(i);
|
||||
yield prefix.concat(first, suffix);
|
||||
}
|
||||
|
||||
count += i;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
for (var perm of yieldPermutations([])) {
|
||||
assert.deepEqual(perm, []);
|
||||
++count;
|
||||
}
|
||||
assert.strictEqual(count, 1);
|
||||
|
||||
genHelpers.check(yieldPermutations([1]), [[1]], 1);
|
||||
|
||||
genHelpers.check(yieldPermutations([2, 1]), [
|
||||
[2, 1],
|
||||
[1, 2]
|
||||
], 2);
|
||||
|
||||
genHelpers.check(yieldPermutations([1,3,2]), [
|
||||
[1, 3, 2],
|
||||
[3, 1, 2],
|
||||
[3, 2, 1],
|
||||
[1, 2, 3],
|
||||
[2, 1, 3],
|
||||
[2, 3, 1]
|
||||
], 6);
|
||||
@@ -1,20 +0,0 @@
|
||||
function *range(max, step) {
|
||||
var count = 0;
|
||||
step = step || 1;
|
||||
|
||||
for (var i = 0; i < max; i += step) {
|
||||
count++;
|
||||
yield i;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
var gen = range(20, 3);
|
||||
var values = [];
|
||||
|
||||
for (var value of gen) {
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
assert.deepEqual(values, [0, 3, 6, 9, 12, 15, 18]);
|
||||
@@ -0,0 +1,32 @@
|
||||
function *gen(n) {
|
||||
yield increment(n);
|
||||
|
||||
function increment(x) {
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
if (n % 2) {
|
||||
yield halve(decrement(n));
|
||||
|
||||
function halve(x) {
|
||||
return x >> 1;
|
||||
}
|
||||
|
||||
function decrement(x) {
|
||||
return x - 1;
|
||||
}
|
||||
} else {
|
||||
// The behavior of function declarations nested inside conditional
|
||||
// blocks is notoriously underspecified, and in V8 it appears the
|
||||
// halve function is still defined when we take this branch, so
|
||||
// "undefine" it for consistency with regenerator semantics.
|
||||
halve = void 0;
|
||||
}
|
||||
|
||||
yield typeof halve;
|
||||
|
||||
yield increment(increment(n));
|
||||
}
|
||||
|
||||
genHelpers.check(gen(3), [4, 1, "function", 5]);
|
||||
genHelpers.check(gen(4), [5, "undefined", 6]);
|
||||
@@ -0,0 +1,15 @@
|
||||
function *outer(n) {
|
||||
yield 0;
|
||||
assert.ok(regeneratorRuntime.isGeneratorFunction(inner));
|
||||
return yield* inner(n);
|
||||
|
||||
// Note that this function declaration comes after everything else
|
||||
// in the outer function, but needs to be fully available above.
|
||||
function *inner(n) {
|
||||
yield n - 1;
|
||||
yield n;
|
||||
return yield n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(outer(2), [0, 1, 2, 3], 4);
|
||||
@@ -0,0 +1,6 @@
|
||||
genHelpers.check(function *(x, y) {
|
||||
yield x;
|
||||
yield y;
|
||||
yield x + y;
|
||||
return x * y;
|
||||
}(3, 7), [3, 7, 10], 21);
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
var GeneratorFunctionPrototype = f.__proto__;
|
||||
var GeneratorFunction = GeneratorFunctionPrototype.constructor;
|
||||
|
||||
assert.strictEqual(GeneratorFunction.name, 'GeneratorFunction');
|
||||
assert.strictEqual(GeneratorFunction.prototype,
|
||||
GeneratorFunctionPrototype);
|
||||
assert.strictEqual(GeneratorFunctionPrototype.prototype.constructor,
|
||||
GeneratorFunctionPrototype);
|
||||
assert.strictEqual(GeneratorFunctionPrototype.prototype,
|
||||
f.prototype.__proto__);
|
||||
assert.strictEqual(GeneratorFunctionPrototype.__proto__,
|
||||
Function.prototype);
|
||||
assert.strictEqual(GeneratorFunctionPrototype.name,
|
||||
"GeneratorFunctionPrototype");
|
||||
|
||||
assert.strictEqual(typeof f2, "function");
|
||||
assert.strictEqual(f2.constructor, GeneratorFunction);
|
||||
assert.ok(f2 instanceof GeneratorFunction);
|
||||
assert.strictEqual(f2.name, "f2");
|
||||
|
||||
var g = f();
|
||||
assert.ok(g instanceof f);
|
||||
assert.strictEqual(g.__proto__, f.prototype);
|
||||
|
||||
assert.deepEqual([], Object.getOwnPropertyNames(f.prototype));
|
||||
// assert.deepEqual([], Object.getOwnPropertyNames(g));
|
||||
|
||||
f.prototype.x = 42;
|
||||
|
||||
var g2 = f();
|
||||
assert.strictEqual(g2.x, 42);
|
||||
|
||||
var g3 = new f();
|
||||
assert.strictEqual(g3.x, 42);
|
||||
|
||||
function* f2() {
|
||||
yield 1;
|
||||
}
|
||||
|
||||
assert.strictEqual(f.__proto__, f2.__proto__);
|
||||
assert.strictEqual(f.hasOwnProperty('constructor'), false);
|
||||
assert.strictEqual(f.__proto__.constructor.name, 'GeneratorFunction');
|
||||
|
||||
// Intentionally at the end to test hoisting.
|
||||
function* f() {
|
||||
yield this;
|
||||
}
|
||||
|
||||
function* f() {
|
||||
yield 1;
|
||||
}
|
||||
|
||||
var f2 = f;
|
||||
f = 42;
|
||||
var g = f2();
|
||||
|
||||
assert.deepEqual(g.next(), { value: 1, done: false });
|
||||
assert.deepEqual(g.next(), { value: void 0, done: true });
|
||||
assert.ok(g instanceof f2);
|
||||
@@ -0,0 +1,18 @@
|
||||
function *gen(x) {
|
||||
try {
|
||||
(yield x).next(x);
|
||||
} catch (err) {
|
||||
yield err;
|
||||
}
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
var g = gen(3);
|
||||
assert.deepEqual(g.next(), { value: 3, done: false });
|
||||
var complaint = g.next(g); // Sending the generator to itself.
|
||||
assert.ok(complaint.value instanceof Error);
|
||||
assert.strictEqual(
|
||||
complaint.value.message,
|
||||
"Generator is already running"
|
||||
);
|
||||
assert.deepEqual(g.next(), { value: 4, done: true });
|
||||
@@ -0,0 +1,22 @@
|
||||
var executedFinally = false;
|
||||
|
||||
function *gen() {
|
||||
try {
|
||||
yield 0;
|
||||
} catch (err) {
|
||||
assert.ok(false, "should not have executed the catch handler");
|
||||
} finally {
|
||||
executedFinally = true;
|
||||
}
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
assert.deepEqual(g.next(), { value: 0, done: false });
|
||||
|
||||
assert.deepEqual(g.return("argument"), {
|
||||
value: "argument",
|
||||
done: true
|
||||
});
|
||||
|
||||
assert.strictEqual(executedFinally, true);
|
||||
genHelpers.assertAlreadyFinished(g);
|
||||
@@ -0,0 +1,12 @@
|
||||
function *gen() {
|
||||
yield 0;
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.deepEqual(g.return("argument"), {
|
||||
value: "argument",
|
||||
done: true
|
||||
});
|
||||
|
||||
genHelpers.assertAlreadyFinished(g);
|
||||
16
test/fixtures/transformation/generators/generator-throw-method-should-complete-generator/exec.js
vendored
Normal file
16
test/fixtures/transformation/generators/generator-throw-method-should-complete-generator/exec.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
function *gen(x) {
|
||||
yield 2;
|
||||
throw 1;
|
||||
}
|
||||
|
||||
var u = gen();
|
||||
|
||||
u.next();
|
||||
|
||||
try {
|
||||
u.throw(2);
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, 2);
|
||||
}
|
||||
|
||||
genHelpers.assertAlreadyFinished(u);
|
||||
@@ -0,0 +1,16 @@
|
||||
var began = false;
|
||||
|
||||
function *gen() {
|
||||
began = true;
|
||||
yield 1;
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
var exception = new Error("unhandled exception");
|
||||
try {
|
||||
g.throw(exception);
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, exception);
|
||||
assert.strictEqual(began, false);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
function *outer() {
|
||||
try {
|
||||
yield* inner();
|
||||
} catch (err) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function *inner() {
|
||||
try {
|
||||
yield void 0;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var g = outer();
|
||||
g.next();
|
||||
assert.equal(g.throw(new Error('foo')).value, 1);
|
||||
@@ -0,0 +1,16 @@
|
||||
function *outer() {
|
||||
try {
|
||||
yield* inner();
|
||||
} catch (err) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function *inner() {
|
||||
yield void 0;
|
||||
}
|
||||
|
||||
var g = outer();
|
||||
g.next();
|
||||
assert.equal(g.throw(new Error('foo')).value, -1);
|
||||
@@ -0,0 +1,14 @@
|
||||
function *gen() {
|
||||
yield 1;
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
assert.deepEqual(g.next(), { value: 1, done: false });
|
||||
|
||||
var exception = new Error("unhandled exception");
|
||||
try {
|
||||
g.throw(exception);
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, exception);
|
||||
}
|
||||
41
test/fixtures/transformation/generators/infinite-sequence-generator/exec.js
vendored
Normal file
41
test/fixtures/transformation/generators/infinite-sequence-generator/exec.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
function *gen(start, step) {
|
||||
step = step || 1;
|
||||
while (true) {
|
||||
yield start;
|
||||
start += step;
|
||||
}
|
||||
}
|
||||
|
||||
function *limit(g, stop) {
|
||||
while (true) {
|
||||
var info = g.next();
|
||||
if (info.done) {
|
||||
return;
|
||||
} else if (info.value < stop) {
|
||||
yield info.value;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// should generate a lot of plausible values
|
||||
var g = gen(10, 2);
|
||||
|
||||
assert.deepEqual(g.next(), { value: 10, done: false });
|
||||
assert.deepEqual(g.next(), { value: 12, done: false });
|
||||
assert.deepEqual(g.next(), { value: 14, done: false });
|
||||
assert.deepEqual(g.next(), { value: 16, done: false });
|
||||
|
||||
var sum = 10 + 12 + 14 + 16;
|
||||
|
||||
for (var n = 0; n < 1000; ++n) {
|
||||
var info = g.next();
|
||||
sum += info.value;
|
||||
assert.strictEqual(info.done, false);
|
||||
}
|
||||
|
||||
assert.strictEqual(sum, 1017052);
|
||||
|
||||
// should allow limiting
|
||||
genHelpers.check(limit(gen(10, 3), 20), [10, 13, 16, 19]);
|
||||
@@ -0,0 +1,19 @@
|
||||
// Do the assertions up here to make sure the generator function is
|
||||
// marked at the beginning of the block the function is declared in.
|
||||
assert.strictEqual(
|
||||
regeneratorRuntime.isGeneratorFunction(genFun),
|
||||
true
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
regeneratorRuntime.isGeneratorFunction(normalFun),
|
||||
false
|
||||
);
|
||||
|
||||
function normalFun() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function *genFun() {
|
||||
yield 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
assert.strictEqual(
|
||||
regeneratorRuntime.isGeneratorFunction(function *genFun() {
|
||||
yield 0;
|
||||
}),
|
||||
true
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
regeneratorRuntime.isGeneratorFunction(function normalFun() {
|
||||
return 0;
|
||||
}),
|
||||
false
|
||||
);
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
var e1 = "first";
|
||||
var e2 = "second";
|
||||
var e3 = "third";
|
||||
var e4 = "fourth";
|
||||
|
||||
function *gen(n, which) {
|
||||
try {
|
||||
yield 0;
|
||||
genHelpers.raise(e1);
|
||||
|
||||
} finally {
|
||||
yield 1;
|
||||
|
||||
loop:
|
||||
for (var i = 0; i < n; ++i) {
|
||||
yield i;
|
||||
|
||||
try {
|
||||
genHelpers.raise(e2);
|
||||
} finally {
|
||||
yield 2;
|
||||
|
||||
try {
|
||||
genHelpers.raise(e3);
|
||||
} finally {
|
||||
yield 3;
|
||||
|
||||
try {
|
||||
genHelpers.raise(e4);
|
||||
} finally {
|
||||
yield 4;
|
||||
|
||||
if (which === "break") {
|
||||
yield "breaking";
|
||||
break loop;
|
||||
}
|
||||
|
||||
if (which === "continue") {
|
||||
yield "continuing";
|
||||
continue loop;
|
||||
}
|
||||
|
||||
yield 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield 6;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
genHelpers.check(gen(1, "break"), [
|
||||
0, 1, 0, 2, 3, 4, "breaking", 6
|
||||
]);
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, e1);
|
||||
}
|
||||
|
||||
try {
|
||||
genHelpers.check(gen(3, "continue"), [
|
||||
0, 1, 0, 2, 3, 4, "continuing",
|
||||
1, 2, 3, 4, "continuing",
|
||||
2, 2, 3, 4, "continuing",
|
||||
6 // Loop finished naturally.
|
||||
]);
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, e1);
|
||||
}
|
||||
|
||||
try {
|
||||
genHelpers.check(gen(3, "neither"), [
|
||||
0, 1, 0, 2, 3, 4, 5
|
||||
]);
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, e4);
|
||||
}
|
||||
41
test/fixtures/transformation/generators/nested-finally-blocks/exec.js
vendored
Normal file
41
test/fixtures/transformation/generators/nested-finally-blocks/exec.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
function *usingThrow() {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
throw "thrown";
|
||||
} finally {
|
||||
yield 1;
|
||||
}
|
||||
} catch (thrown) {
|
||||
yield thrown;
|
||||
} finally {
|
||||
yield 2;
|
||||
}
|
||||
} finally {
|
||||
yield 3;
|
||||
}
|
||||
}
|
||||
|
||||
function *usingRaise() {
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
genHelpers.raise("thrown");
|
||||
} finally {
|
||||
yield 1;
|
||||
}
|
||||
} catch (thrown) {
|
||||
yield thrown;
|
||||
} finally {
|
||||
yield 2;
|
||||
}
|
||||
} finally {
|
||||
yield 3;
|
||||
}
|
||||
}
|
||||
|
||||
// should statically execute in order
|
||||
genHelpers.check(usingThrow(), [1, "thrown", 2, 3]);
|
||||
|
||||
// should dynamically execute in order
|
||||
genHelpers.check(usingRaise(), [1, "thrown", 2, 3]);
|
||||
@@ -0,0 +1,18 @@
|
||||
function *gen() {
|
||||
try {
|
||||
nonExistent;
|
||||
} catch (e) {
|
||||
yield function* () {
|
||||
yield e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var genFun2 = gen().next().value;
|
||||
assert.ok(regeneratorRuntime.isGeneratorFunction(genFun2));
|
||||
var gen2 = genFun2();
|
||||
var res = gen2.next();
|
||||
assert.ok(res.value instanceof ReferenceError);
|
||||
// Note that we don't do strict equality over the message because it varies
|
||||
// across browsers (if we ever want to run tests in browsers).
|
||||
assert.ok(res.value.message.match(/nonExistent/));
|
||||
@@ -0,0 +1,22 @@
|
||||
function A(first, second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
function *gen() {
|
||||
return yield new (yield 0)(yield 1, yield 2);
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.deepEqual(g.next(), { value: 0, done: false });
|
||||
assert.deepEqual(g.next(A), { value: 1, done: false });
|
||||
assert.deepEqual(g.next("asdf"), { value: 2, done: false });
|
||||
|
||||
var info = g.next("zxcv");
|
||||
assert.strictEqual(info.done, false);
|
||||
assert.ok(info.value instanceof A);
|
||||
assert.strictEqual(info.value.first, "asdf");
|
||||
assert.strictEqual(info.value.second, "zxcv");
|
||||
|
||||
assert.deepEqual(g.next("qwer"), { value: "qwer", done: true });
|
||||
@@ -0,0 +1,40 @@
|
||||
function *range(n) {
|
||||
for (var i = 0; i < n; ++i) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
function *chain(a, b) {
|
||||
yield* a;
|
||||
yield* b;
|
||||
}
|
||||
|
||||
genHelpers.check(chain(range(3), range(5)), [0, 1, 2, 0, 1, 2, 3, 4]);
|
||||
|
||||
function *y3(x) {
|
||||
return yield yield yield x;
|
||||
}
|
||||
|
||||
function *y5(x) {
|
||||
return yield yield yield yield yield x;
|
||||
}
|
||||
|
||||
genHelpers.check(
|
||||
chain(y3("foo"), y5("bar")),
|
||||
["foo", 1, 2, "bar", 4, 5, 6, 7]
|
||||
);
|
||||
|
||||
var g3 = y3("three");
|
||||
assert.deepEqual(g3.next(), {
|
||||
value: "three",
|
||||
done: false
|
||||
});
|
||||
|
||||
var g5 = y5("five");
|
||||
assert.deepEqual(g5.next(), {
|
||||
value: "five",
|
||||
done: false
|
||||
});
|
||||
|
||||
var undef; // A little easier to read than void 0.
|
||||
genHelpers.check(chain(g3, g5), [undef, 1, undef, 3, 4, 5]);
|
||||
@@ -0,0 +1,29 @@
|
||||
function *inner() {
|
||||
return [yield 1, yield 2];
|
||||
}
|
||||
|
||||
function *outer(delegate) {
|
||||
return yield* delegate;
|
||||
}
|
||||
|
||||
var n = inner();
|
||||
|
||||
assert.deepEqual(n.next(), {
|
||||
value: 1,
|
||||
done: false
|
||||
});
|
||||
|
||||
var g = outer(n);
|
||||
|
||||
// I would really like to be able to pass 3 to g.next here, but V8
|
||||
// ignores values sent to newborn generators, and SpiderMonkey throws
|
||||
// a TypeError.
|
||||
assert.deepEqual(g.next(), {
|
||||
value: 2,
|
||||
done: false
|
||||
});
|
||||
|
||||
assert.deepEqual(g.next(4), {
|
||||
value: [void 0, 4],
|
||||
done: true
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
var markers = [];
|
||||
|
||||
function *inner() {
|
||||
markers.push(0);
|
||||
var sent1 = yield 1;
|
||||
markers.push(2);
|
||||
var sent2 = yield 2;
|
||||
markers.push(3);
|
||||
return [sent1, sent2];
|
||||
}
|
||||
|
||||
function wrapper(delegate) {
|
||||
var gen = (function*() {
|
||||
// This yield is the "initial yield" whose argument we ignore.
|
||||
var sent = yield "ignored", info;
|
||||
|
||||
markers.push(1);
|
||||
|
||||
while (!(info = delegate.next(sent)).done) {
|
||||
sent = yield info.value;
|
||||
}
|
||||
|
||||
markers.push(4);
|
||||
|
||||
return info.value;
|
||||
})();
|
||||
|
||||
// Ensure that gen is not newborn and that the next invocation of
|
||||
// gen.next(value) can send value to the initial yield expression.
|
||||
gen.next();
|
||||
|
||||
return gen;
|
||||
}
|
||||
|
||||
var n = inner();
|
||||
|
||||
assert.deepEqual(n.next(), {
|
||||
value: 1,
|
||||
done: false
|
||||
});
|
||||
|
||||
var g = wrapper(n);
|
||||
|
||||
// Unlike in the previous spec, it's fine to pass 3 to g.next here,
|
||||
// because g is not newborn, because g.next was already called once
|
||||
// before g was returned from the wrapper function.
|
||||
assert.deepEqual(g.next(3), {
|
||||
value: 2,
|
||||
done: false
|
||||
});
|
||||
|
||||
assert.deepEqual(g.next(4), {
|
||||
value: [3, 4],
|
||||
done: true
|
||||
});
|
||||
|
||||
// Ensure we encountered the marker points in the expected order.
|
||||
assert.deepEqual(markers, [0, 1, 2, 3, 4]);
|
||||
@@ -0,0 +1,9 @@
|
||||
function *gen(a, b) {
|
||||
yield {
|
||||
a: a - (yield a),
|
||||
b: yield b
|
||||
};
|
||||
}
|
||||
|
||||
genHelpers.check(gen(1, 2), [1, 2, { a: 0, b: 2 }]);
|
||||
genHelpers.check(gen(4, 2), [4, 2, { a: 3, b: 2 }]);
|
||||
@@ -0,0 +1,17 @@
|
||||
function *gen(fn) {
|
||||
return {
|
||||
a: yield "a",
|
||||
b: yield "b",
|
||||
c: fn(yield "c", yield "d"),
|
||||
d: [yield "e", yield "f"]
|
||||
};
|
||||
}
|
||||
|
||||
genHelpers.check(gen(function sum(x, y) {
|
||||
return x + y;
|
||||
}), ["a", "b", "c", "d", "e", "f"], {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3 + 4,
|
||||
d: [5, 6]
|
||||
});
|
||||
9
test/fixtures/transformation/generators/range-generator/exec.js
vendored
Normal file
9
test/fixtures/transformation/generators/range-generator/exec.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
function *range(n) {
|
||||
for (var i = 0; i < n; ++i) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(range(0), []);
|
||||
|
||||
genHelpers.check(range(5), [0, 1, 2, 3, 4]);
|
||||
5
test/fixtures/transformation/generators/should-support-multiple-yields-in-expression/exec.js
vendored
Normal file
5
test/fixtures/transformation/generators/should-support-multiple-yields-in-expression/exec.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
function *gen() { return (yield 0) + (yield 0); }
|
||||
var itr = gen();
|
||||
itr.next();
|
||||
itr.next(1);
|
||||
assert.equal(itr.next(2).value, 3);
|
||||
6
test/fixtures/transformation/generators/should-yield-only-its-first-argument/exec.js
vendored
Normal file
6
test/fixtures/transformation/generators/should-yield-only-its-first-argument/exec.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
function *gen(x) {
|
||||
yield x;
|
||||
}
|
||||
|
||||
genHelpers.check(gen("oyez"), ["oyez"]);
|
||||
genHelpers.check(gen("foo", "bar"), ["foo"]);
|
||||
@@ -1,19 +0,0 @@
|
||||
function *range(max, step) {
|
||||
var count = 0;
|
||||
step = step || 1;
|
||||
|
||||
for (var i = 0; i < max; i += step) {
|
||||
count++;
|
||||
yield i;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
var gen = range(20, 3), info;
|
||||
|
||||
while (!(info = gen.next()).done) {
|
||||
info.value;
|
||||
}
|
||||
|
||||
assert(info.value, 7);
|
||||
@@ -0,0 +1,11 @@
|
||||
function *gen(a) {
|
||||
switch (yield a) {
|
||||
case (yield "x") - a:
|
||||
return "first case";
|
||||
case (yield "y") - a:
|
||||
return "second case";
|
||||
}
|
||||
}
|
||||
|
||||
genHelpers.check(gen(1), [1, "x"], "first case");
|
||||
genHelpers.check(gen(2), [2, "x", "y"], "second case");
|
||||
@@ -0,0 +1,7 @@
|
||||
function *gen(obj) {
|
||||
yield obj.arguments;
|
||||
obj.arguments = "oyez";
|
||||
yield obj;
|
||||
}
|
||||
|
||||
genHelpers.check(gen({ arguments: 42 }), [42, { arguments: "oyez" }]);
|
||||
@@ -0,0 +1,12 @@
|
||||
function *sum() {
|
||||
var result = 0;
|
||||
|
||||
for (var i = 0; i < arguments.length; ++i) {
|
||||
yield result += arguments[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
genHelpers.check(sum(1, 2, 3), [1, 3, 6], 6);
|
||||
genHelpers.check(sum(9, -5, 3, 0, 2), [9, 4, 7, 7, 9], 9);
|
||||
13
test/fixtures/transformation/generators/throw-should-complete-generator/exec.js
vendored
Normal file
13
test/fixtures/transformation/generators/throw-should-complete-generator/exec.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
function *gen(x) {
|
||||
throw 1;
|
||||
}
|
||||
|
||||
var u = gen();
|
||||
|
||||
try {
|
||||
u.next();
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, 1);
|
||||
}
|
||||
|
||||
genHelpers.assertAlreadyFinished(u);
|
||||
42
test/fixtures/transformation/generators/try-catch-finally-generator/exec.js
vendored
Normal file
42
test/fixtures/transformation/generators/try-catch-finally-generator/exec.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
function *usingThrow() {
|
||||
yield 0;
|
||||
try {
|
||||
try {
|
||||
yield 1;
|
||||
throw 2;
|
||||
yield 3;
|
||||
} catch (x) {
|
||||
throw yield x;
|
||||
} finally {
|
||||
yield 5;
|
||||
}
|
||||
} catch (thrown) {
|
||||
yield thrown;
|
||||
}
|
||||
yield 6;
|
||||
}
|
||||
|
||||
function *usingRaise() {
|
||||
yield 0;
|
||||
try {
|
||||
try {
|
||||
yield 1;
|
||||
genHelpers.raise(2);
|
||||
yield 3;
|
||||
} catch (x) {
|
||||
throw yield x;
|
||||
} finally {
|
||||
yield 5;
|
||||
}
|
||||
} catch (thrown) {
|
||||
yield thrown;
|
||||
}
|
||||
yield 6;
|
||||
}
|
||||
|
||||
// should statically catch and then finalize
|
||||
genHelpers.check(usingThrow(), [0, 1, 2, 5, 3, 6]);
|
||||
|
||||
// should dynamically catch and then finalize
|
||||
genHelpers.check(usingRaise(), [0, 1, 2, 5, 3, 6]);
|
||||
33
test/fixtures/transformation/generators/try-catch-generator/exec.js
vendored
Normal file
33
test/fixtures/transformation/generators/try-catch-generator/exec.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
function *usingThrow(x) {
|
||||
yield 0;
|
||||
try {
|
||||
yield 1;
|
||||
if (x % 2 === 0)
|
||||
throw 2;
|
||||
yield x;
|
||||
} catch (x) {
|
||||
yield x;
|
||||
}
|
||||
yield 3;
|
||||
}
|
||||
|
||||
function *usingRaise(x) {
|
||||
yield 0;
|
||||
try {
|
||||
yield 1;
|
||||
if (x % 2 === 0)
|
||||
genHelpers.raise(2);
|
||||
yield x;
|
||||
} catch (x) {
|
||||
yield x;
|
||||
}
|
||||
yield 3;
|
||||
}
|
||||
|
||||
// should catch static exceptions properly
|
||||
genHelpers.check(usingThrow(4), [0, 1, 2, 3]);
|
||||
genHelpers.check(usingThrow(5), [0, 1, 5, 3]);
|
||||
|
||||
// should catch dynamic exceptions properly
|
||||
genHelpers.check(usingRaise(4), [0, 1, 2, 3]);
|
||||
genHelpers.check(usingRaise(5), [0, 1, 5, 3]);
|
||||
114
test/fixtures/transformation/generators/try-finally-generator/exec.js
vendored
Normal file
114
test/fixtures/transformation/generators/try-finally-generator/exec.js
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
function *usingThrow(condition) {
|
||||
yield 0;
|
||||
try {
|
||||
yield 1;
|
||||
throw 2;
|
||||
yield 3;
|
||||
} finally {
|
||||
if (condition) {
|
||||
yield 4;
|
||||
return 5;
|
||||
}
|
||||
yield 6;
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
function *usingRaise(condition) {
|
||||
yield 0;
|
||||
try {
|
||||
yield 1;
|
||||
genHelpers.raise(2);
|
||||
yield 3;
|
||||
} finally {
|
||||
if (condition) {
|
||||
yield 4;
|
||||
return 5;
|
||||
}
|
||||
yield 6;
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
// should execute finally blocks statically
|
||||
genHelpers.check(usingThrow(true), [0, 1, 4], 5);
|
||||
genHelpers.check(usingThrow(false), [0, 1, 6], 7);
|
||||
|
||||
// should execute finally blocks dynamically
|
||||
genHelpers.check(usingRaise(true), [0, 1, 4], 5);
|
||||
genHelpers.check(usingRaise(false), [0, 1, 6], 7);
|
||||
|
||||
// should execute finally blocks before throwing
|
||||
var uncaughtError = new Error("uncaught");
|
||||
|
||||
function *uncaught(condition) {
|
||||
try {
|
||||
yield 0;
|
||||
if (condition) {
|
||||
yield 1;
|
||||
genHelpers.raise(uncaughtError);
|
||||
}
|
||||
yield 2;
|
||||
} finally {
|
||||
yield 3;
|
||||
}
|
||||
yield 4;
|
||||
}
|
||||
|
||||
genHelpers.check(uncaught(false), [0, 2, 3, 4]);
|
||||
|
||||
var u = uncaught(true);
|
||||
|
||||
assert.deepEqual(u.next(), { value: 0, done: false });
|
||||
assert.deepEqual(u.next(), { value: 1, done: false });
|
||||
assert.deepEqual(u.next(), { value: 3, done: false });
|
||||
|
||||
try {
|
||||
u.next();
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, uncaughtError);
|
||||
}
|
||||
|
||||
// should throw correct error when finally contains catch
|
||||
var right = new Error("right");
|
||||
var wrong = new Error("wrong");
|
||||
|
||||
function *gen() {
|
||||
try {
|
||||
yield 0;
|
||||
genHelpers.raise(right);
|
||||
} finally {
|
||||
yield 1;
|
||||
try {
|
||||
genHelpers.raise(wrong);
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, wrong);
|
||||
yield 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var g = gen();
|
||||
|
||||
assert.deepEqual(g.next(), {
|
||||
value: 0,
|
||||
done: false
|
||||
});
|
||||
|
||||
assert.deepEqual(g.next(), {
|
||||
value: 1,
|
||||
done: false
|
||||
});
|
||||
|
||||
assert.deepEqual(g.next(), {
|
||||
value: 2,
|
||||
done: false
|
||||
});
|
||||
|
||||
try {
|
||||
g.next();
|
||||
assert.ok(false, "should have thrown an exception");
|
||||
} catch (err) {
|
||||
assert.strictEqual(err, right);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
function getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// This is almost certainly the global object, but there's a chance it
|
||||
// might be null or undefined (in strict mode).
|
||||
var unqualifiedThis = getThis();
|
||||
|
||||
function *invoke() {
|
||||
// It seems like a bug in the ES6 spec that we have to yield an
|
||||
// argument instead of just calling (yield)().
|
||||
return (yield "dummy")();
|
||||
}
|
||||
|
||||
var g = invoke();
|
||||
var info = g.next();
|
||||
|
||||
assert.deepEqual(info, { value: "dummy", done: false });
|
||||
|
||||
info = g.next(getThis);
|
||||
|
||||
// Avoid using assert.strictEqual when the arguments might equal the
|
||||
// global object, since JSON.stringify chokes on circular structures.
|
||||
assert.ok(info.value === unqualifiedThis);
|
||||
|
||||
assert.strictEqual(info.done, true);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user