Compare commits
272 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34335018e9 | ||
|
|
136bddab33 | ||
|
|
b2951c5462 | ||
|
|
07de6f5f4a | ||
|
|
99ea00ca18 | ||
|
|
ab5c6a38eb | ||
|
|
52cee84625 | ||
|
|
ba5992621d | ||
|
|
cdae98f653 | ||
|
|
81434bb557 | ||
|
|
3af0fc6fb7 | ||
|
|
3f60062ab6 | ||
|
|
76499bb26e | ||
|
|
44f2f701e1 | ||
|
|
032bc0af5e | ||
|
|
0e822a7e54 | ||
|
|
51e521f0e0 | ||
|
|
e5ce69d6af | ||
|
|
e3b8fa93e2 | ||
|
|
f4ce3a23ad | ||
|
|
39f4696ac7 | ||
|
|
4a9918ec6b | ||
|
|
c87e14f6a9 | ||
|
|
680771c81b | ||
|
|
cad3f63723 | ||
|
|
eceda64528 | ||
|
|
b8ec87e058 | ||
|
|
04bd023787 | ||
|
|
f1759dc419 | ||
|
|
2985f1b40b | ||
|
|
14d1b6701e | ||
|
|
eb3cc9ff07 | ||
|
|
b97a2bd61d | ||
|
|
49e7e3b998 | ||
|
|
11ac6ff084 | ||
|
|
54e7e495ac | ||
|
|
fafdb1a18a | ||
|
|
b599e2c794 | ||
|
|
7f57d3d6a2 | ||
|
|
a2b0ee6809 | ||
|
|
83e8c4bddd | ||
|
|
57aca3c77f | ||
|
|
f80527832c | ||
|
|
2ecceaac45 | ||
|
|
32f8f9e663 | ||
|
|
3447204d97 | ||
|
|
c500532469 | ||
|
|
3396cc84f1 | ||
|
|
1de4893a69 | ||
|
|
abba930f36 | ||
|
|
c84097cf57 | ||
|
|
790b81938c | ||
|
|
187bbca731 | ||
|
|
4ccc12b04d | ||
|
|
9a5f97d85b | ||
|
|
4ed77e136b | ||
|
|
0339d21c33 | ||
|
|
4502aee988 | ||
|
|
55150853b4 | ||
|
|
b9da4f988c | ||
|
|
bf0ca10253 | ||
|
|
fcc4734a1f | ||
|
|
d1c5c773fa | ||
|
|
01ce38c5ac | ||
|
|
cc6d440f0e | ||
|
|
2b21f4b571 | ||
|
|
24d9833170 | ||
|
|
20f21987de | ||
|
|
fad0be8a45 | ||
|
|
02c42b94f5 | ||
|
|
4808689795 | ||
|
|
6231dceb1c | ||
|
|
1753afa782 | ||
|
|
4097da09bd | ||
|
|
c7965df42d | ||
|
|
1027f8a5a4 | ||
|
|
cbd6be30bf | ||
|
|
7e299470fd | ||
|
|
c794c2aede | ||
|
|
1a58087460 | ||
|
|
44f6fc67f8 | ||
|
|
e4a3d222d6 | ||
|
|
5a96c2e015 | ||
|
|
43390c0d1f | ||
|
|
d166656149 | ||
|
|
acc4d289e4 | ||
|
|
717e6df407 | ||
|
|
286404c6f2 | ||
|
|
f191fd7883 | ||
|
|
74f36cfaa0 | ||
|
|
71aed8b269 | ||
|
|
9e6b0b45b3 | ||
|
|
7bbb3725d4 | ||
|
|
1210c92405 | ||
|
|
714ca9fbc8 | ||
|
|
60713f0e5f | ||
|
|
f1f5f8bb27 | ||
|
|
a69f095720 | ||
|
|
d50d4972a7 | ||
|
|
bd91bbee71 | ||
|
|
8b46cce466 | ||
|
|
defa9108bd | ||
|
|
6b1d9b49b7 | ||
|
|
4e333cf357 | ||
|
|
ddcd7ab28d | ||
|
|
4b8a4492ba | ||
|
|
4256a9960c | ||
|
|
ecb695c30c | ||
|
|
db97f665ed | ||
|
|
931b68dc5d | ||
|
|
b5feaf7c2f | ||
|
|
d82683f598 | ||
|
|
6772f5a74f | ||
|
|
a90f133918 | ||
|
|
71ad511322 | ||
|
|
ff6677a4b7 | ||
|
|
ac5e0ad392 | ||
|
|
0a25618c34 | ||
|
|
984c048591 | ||
|
|
5867e24886 | ||
|
|
02d7cdc701 | ||
|
|
d3b3febfeb | ||
|
|
7fccf98c10 | ||
|
|
4a1c393bdb | ||
|
|
afaf3fb0c0 | ||
|
|
2152ae9b17 | ||
|
|
b8f5693b5e | ||
|
|
638143700b | ||
|
|
aa7eb9c1c9 | ||
|
|
27ca532896 | ||
|
|
913fbdbd87 | ||
|
|
fb39df71eb | ||
|
|
102a566b1d | ||
|
|
b924e3deb5 | ||
|
|
ef21724a9c | ||
|
|
fdad51b53b | ||
|
|
df0e4f6431 | ||
|
|
a37f2093bc | ||
|
|
32b32329b2 | ||
|
|
d4379d52a7 | ||
|
|
5c5d811647 | ||
|
|
8feb17dd23 | ||
|
|
55b3f84a2f | ||
|
|
50dee1a754 | ||
|
|
f80f860bbc | ||
|
|
7fc2fe41af | ||
|
|
a884a26402 | ||
|
|
81ec1e1f42 | ||
|
|
1a27970376 | ||
|
|
6822c854d4 | ||
|
|
8f4c4be821 | ||
|
|
5fca095149 | ||
|
|
34599a21cb | ||
|
|
d9d84c60b5 | ||
|
|
221d78d2e2 | ||
|
|
fa46f60655 | ||
|
|
03ce52fb7c | ||
|
|
0df0c696a9 | ||
|
|
21b7f4120e | ||
|
|
f43a3dec4b | ||
|
|
cacee5c625 | ||
|
|
553c90ae75 | ||
|
|
bc3502d695 | ||
|
|
6ae03a5dce | ||
|
|
9895711bf4 | ||
|
|
d2724554cc | ||
|
|
8db466c698 | ||
|
|
68ef2d545e | ||
|
|
861b9e68d3 | ||
|
|
a0eb108cd4 | ||
|
|
756aef6adc | ||
|
|
7b74c1c8ec | ||
|
|
8e115ef3ed | ||
|
|
b9a6cf35b7 | ||
|
|
2e22de71b4 | ||
|
|
a077c75c8c | ||
|
|
c0b03e8126 | ||
|
|
a3a4a7645c | ||
|
|
7bd1337ee8 | ||
|
|
c54f530b10 | ||
|
|
9d3a3a57f2 | ||
|
|
e1474c2f5f | ||
|
|
8a9a205122 | ||
|
|
885d65f9de | ||
|
|
43d1435c97 | ||
|
|
247c14c5ab | ||
|
|
0e2b12c134 | ||
|
|
59c5abe188 | ||
|
|
e1cc1dcb4b | ||
|
|
d091793077 | ||
|
|
e6baac1003 | ||
|
|
c41608edc3 | ||
|
|
3815913537 | ||
|
|
e5c18749f0 | ||
|
|
b7458f949c | ||
|
|
69302b314f | ||
|
|
0c57a00fdb | ||
|
|
3bec8b0311 | ||
|
|
6a88e05362 | ||
|
|
e3bd2dff8d | ||
|
|
ef82171254 | ||
|
|
00d94fd810 | ||
|
|
d929d3c5eb | ||
|
|
5c1ee86b97 | ||
|
|
5409691a3a | ||
|
|
24964ac454 | ||
|
|
faa81ab85b | ||
|
|
d4bc082bb9 | ||
|
|
3777af6bbd | ||
|
|
1f258e9e9c | ||
|
|
50333c879c | ||
|
|
105e6ac379 | ||
|
|
dadab64e39 | ||
|
|
2b82f2bcc2 | ||
|
|
f1183505b1 | ||
|
|
fa3b24e5b4 | ||
|
|
5789447068 | ||
|
|
f1f7321590 | ||
|
|
9ff4df6dae | ||
|
|
0dbb24c922 | ||
|
|
a027d2b9cf | ||
|
|
e290990371 | ||
|
|
d0a2bd170e | ||
|
|
69db46f96b | ||
|
|
27ba4b2bba | ||
|
|
b337c1ab06 | ||
|
|
a1895b4bb4 | ||
|
|
00483917f0 | ||
|
|
d09bafaf8c | ||
|
|
a7ef02c781 | ||
|
|
94cd45c269 | ||
|
|
424bab97d0 | ||
|
|
a1bdd804e2 | ||
|
|
10c051890b | ||
|
|
ac49d0a335 | ||
|
|
b56f1800e5 | ||
|
|
49ef92c586 | ||
|
|
542fe89123 | ||
|
|
5b118c0c3f | ||
|
|
8503916799 | ||
|
|
206c828a56 | ||
|
|
7a261a1db1 | ||
|
|
c9d9a085f1 | ||
|
|
6d1953d9c3 | ||
|
|
92621d71c7 | ||
|
|
dc01731c25 | ||
|
|
9fb8a80f60 | ||
|
|
85c2de57e4 | ||
|
|
58fac2e2be | ||
|
|
682806f1ca | ||
|
|
47c6f74251 | ||
|
|
37f360c72d | ||
|
|
e5a8c95b62 | ||
|
|
921d459f13 | ||
|
|
58898932e6 | ||
|
|
c7b45116c4 | ||
|
|
32ddd638ba | ||
|
|
0eb3cda2d4 | ||
|
|
2acb24d43d | ||
|
|
fdd1451d53 | ||
|
|
43e2f121a6 | ||
|
|
297e55ba63 | ||
|
|
38396dadd5 | ||
|
|
f75f045026 | ||
|
|
740193b1e2 | ||
|
|
b9fe1475c2 | ||
|
|
6065220f9b | ||
|
|
715884662e | ||
|
|
11780c28ff | ||
|
|
215c2da7cb | ||
|
|
c7c41d6548 | ||
|
|
695571b435 |
@@ -1,3 +0,0 @@
|
||||
java_script:
|
||||
enabled: true
|
||||
config_file: .jshintrc
|
||||
144
CHANGELOG.md
144
CHANGELOG.md
@@ -1,3 +1,147 @@
|
||||
# 1.13.12
|
||||
|
||||
* Ignore `XJSEmptyExpression`s in `react` transformer output.
|
||||
|
||||
# 1.13.11
|
||||
|
||||
* Fix `util.regexify` on falsy values.
|
||||
* Fix `_aliasFunction` with rest parameters.
|
||||
* Export as `module.exports` instead of `exports.default` if there are no other `ExportDeclaration`s in `commonInterop` module formatter.
|
||||
* Add `system` module formatter. Thanks [@douglasduteil](https://github.com/douglasduteil).
|
||||
|
||||
# 1.13.10
|
||||
|
||||
* Add support for `AssignmentExpression` destructuring outside of `ExpressionStatement`.
|
||||
|
||||
# 1.13.9
|
||||
|
||||
* Fix `VirtualPropertyExpression` visitor keys.
|
||||
|
||||
# 1.13.8
|
||||
|
||||
* Only use a single reference in abstract references.
|
||||
|
||||
# 1.13.7
|
||||
|
||||
* Upgrade `acorn-6to5`.
|
||||
* Add experimental exponentiation operator support.
|
||||
|
||||
# 1.13.6
|
||||
|
||||
* Fix experimental object spread/rest helper.
|
||||
|
||||
# 1.13.5
|
||||
|
||||
* Upgrade `acorn-6to5`.
|
||||
* Add experimental support for object spread/rest.
|
||||
* Change `arguments` to array to an additional helper method.
|
||||
|
||||
# 1.13.4
|
||||
|
||||
* Fix single spread element returning itself.
|
||||
|
||||
# 1.13.3
|
||||
|
||||
* Upgrade `acorn-6to5`.
|
||||
* Add experimental support for abstract references.
|
||||
|
||||
# 1.13.2
|
||||
|
||||
* Optimise `Array.from` usage by adding a helper method.
|
||||
* Upgrade `acorn-6to5`.
|
||||
|
||||
# 1.13.1
|
||||
|
||||
* Fix constructor spread optimisation. Thanks [@zloirock](https://github.com/zloirock).
|
||||
|
||||
# 1.13.0
|
||||
|
||||
* Put experimental ES7 features behind a flag `--experimental` and `experimental` option.
|
||||
* Constructor spread performance increase. Thanks [@RReverser](https://github.com/RReverser).
|
||||
* Use `self` instead of `window` in the optional 6to5 runtime. Thanks [@RReverser](https://github.com/RReverser).
|
||||
|
||||
# 1.12.26
|
||||
|
||||
* Support computed property destructuring.
|
||||
|
||||
# 1.12.25
|
||||
|
||||
* Update `acorn-6to5`, `ast-types`, `es6-shim`, `chokidar`, `estraverse` and `private`.
|
||||
|
||||
# 1.12.24
|
||||
|
||||
* Collect references that haven't been declared in scope.
|
||||
|
||||
# 1.12.23
|
||||
|
||||
* Fix generator function export hoisting.
|
||||
|
||||
# 1.12.22
|
||||
|
||||
* Update `fs-readdir-recursive` and `chokidar`.
|
||||
* Support array destructuring on iterables.
|
||||
* Make amd module id optional. Thanks [@webpro](https://github.com/webpro).
|
||||
|
||||
# 1.12.21
|
||||
|
||||
* Fix unneccesary let scoping replacement.
|
||||
* Add `commonInterop` module formatter. Thanks [@Naddiseo](https://github.com/Naddiseo).
|
||||
* Fix `return` outside of function body bug. Thanks [@brentburg](https://github.com/brentburg).
|
||||
* Add more flexible option types.
|
||||
|
||||
# 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](https://github.com/darvelo).
|
||||
* Traversal optimisations.
|
||||
|
||||
# 1.12.16
|
||||
|
||||
* Fix comments not being retained from `MethodDefinition` in classes.
|
||||
* Add temporal dead zone in default parameters.
|
||||
|
||||
# 1.12.15
|
||||
|
||||
* Update `acorn-6to5`.
|
||||
|
||||
# 1.12.14
|
||||
|
||||
* Fix duplicate let scoping in functions.
|
||||
* Make JSX whitespace more React-compliant.
|
||||
* Add `_memberExpressionKeywords` transformer that turns keyword identifiers to computed literals.
|
||||
* Upgrade `regenerator-6to5`.
|
||||
|
||||
# 1.12.13
|
||||
|
||||
* Support duplicate constants within different block scopes.
|
||||
* Fix for-head duplication testing and replacement.
|
||||
* Support `raw` property on tagged template literals.
|
||||
|
||||
# 1.12.12
|
||||
|
||||
* Make scope tracker more reliable to handle all edgecases.
|
||||
|
||||
# 1.12.11
|
||||
|
||||
* Block scope classes.
|
||||
* Fix generation of integer `Literal`s in `MemberExpression`.
|
||||
|
||||
# 1.12.10
|
||||
|
||||
* Fix let scoping var hoisting.
|
||||
|
||||
# 1.12.9
|
||||
|
||||
* Escape unicode characters when generating string `Literal`s.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/6to5/6to5">
|
||||
<img alt="Travis Status" src="http://img.shields.io/travis/6to5/6to5.svg?branch=master&style=flat&label=travis">
|
||||
<img alt="Travis Status" src="http://img.shields.io/travis/6to5/6to5/master.svg?style=flat&label=travis">
|
||||
</a>
|
||||
|
||||
<a href="https://ci.appveyor.com/project/sebmck/6to5">
|
||||
@@ -26,4 +26,5 @@
|
||||
|
||||
**6to5** turns ES6+ code into vanilla ES5, so you can use next generation features **today.**
|
||||
|
||||
For more information view the [documentation](https://6to5.github.io).
|
||||
For more information view the [documentation](https://6to5.github.io). For
|
||||
support visit the [gitter room](https://gitter.im/6to5/6to5).
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -11,12 +11,15 @@ commander.option("-s, --source-maps", "Save source map alongside the compiled co
|
||||
commander.option("-f, --filename [filename]", "Filename to use when reading from stdin - this will be used in source-maps, errors etc [stdin]", "stdin");
|
||||
commander.option("-w, --watch", "Recompile files on changes");
|
||||
commander.option("-r, --runtime", "Replace 6to5 declarations with references to a runtime");
|
||||
commander.option("-e, --experimental", "Enable experimental support for proposed ES7 features");
|
||||
|
||||
commander.option("-m, --modules [modules]", "Module formatter type to use [common]", "common");
|
||||
commander.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ONLY use", util.list);
|
||||
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.option("-a, --amd-module-ids", "Insert module id in AMD modules", false);
|
||||
|
||||
commander.on("--help", function(){
|
||||
var outKeys = function (title, obj) {
|
||||
@@ -85,9 +88,12 @@ if (errors.length) {
|
||||
|
||||
exports.opts = {
|
||||
sourceMapName: commander.outFile,
|
||||
amdModuleIds: commander.amdModuleIds,
|
||||
experimental: commander.experimental,
|
||||
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;
|
||||
|
||||
@@ -8,10 +8,11 @@ var util = require("../lib/6to5/util");
|
||||
var vm = require("vm");
|
||||
var _ = require("lodash");
|
||||
|
||||
commander.option("-e, --eval [script]", "evaluate script");
|
||||
commander.option("-p, --print", "evaluate script and print result");
|
||||
commander.option("-i, --ignore [regex]", "ignore all files that match this regex when using the require hook");
|
||||
commander.option("-x, --extensions [extensions]", "list of extensions to hook into [.es6,.js]", util.list);
|
||||
commander.option("-e, --eval [script]", "Evaluate script");
|
||||
commander.option("-p, --print", "Evaluate script and print result");
|
||||
commander.option("-i, --ignore [regex]", "Ignore all files that match this regex when using the require hook");
|
||||
commander.option("-x, --extensions [extensions]", "List of extensions to hook into [.es6,.js]");
|
||||
commander.option("-r, --experimental", "Enable experimental support for proposed ES7 features");
|
||||
|
||||
var pkg = require("../package.json");
|
||||
commander.version(pkg.version);
|
||||
@@ -20,22 +21,20 @@ commander.parse(process.argv);
|
||||
|
||||
//
|
||||
|
||||
var registerOpts = {};
|
||||
|
||||
if (commander.ignore) {
|
||||
registerOpts.ignoreRegex = new RegExp(commander.ignore);
|
||||
}
|
||||
|
||||
if (commander.extensions && commander.extensions.length) {
|
||||
registerOpts.extensions = commander.extensions;
|
||||
}
|
||||
|
||||
to5.register(registerOpts);
|
||||
to5.register({
|
||||
experimental: commander.experimental,
|
||||
extensions: commander.extensions,
|
||||
ignore: commander.ignore
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
var _eval = function (code, filename) {
|
||||
code = to5.transform(code, { filename: filename, blacklist: ["useStrict"] }).code;
|
||||
code = to5.transform(code, {
|
||||
filename: filename,
|
||||
blacklist: ["useStrict"],
|
||||
experimental: commander.experimental
|
||||
}).code;
|
||||
return vm.runInThisContext(code, filename);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
# Caveats
|
||||
|
||||
## Async/Generators
|
||||
In order for certain features to work they require certain polyfills. You can
|
||||
satisfy **all** 6to5 feature requirements by using the included
|
||||
[polyfill](polyfill.md). You may alternatively selectively include what you need:
|
||||
|
||||
The [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js)
|
||||
and an [ES6 polyfill](polyfill.md) are required in order for generators to work.
|
||||
| Feature | Requirements |
|
||||
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Abstract References | [experimental](usage.md#experimental), `Symbol` |
|
||||
| Array destructuring | `Array.isArray`, `Array.from` |
|
||||
| Async functions, Generators | [experimental](usage.md#experimental), [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) |
|
||||
| Comprehensions | [experimental](usage.md#experimental), `Array.isArray`, `Array.from` |
|
||||
| For Of | `Symbol`, `prototype[Symbol.iterator]` |
|
||||
| Object spread/rest | [experimental](usage.md#experimental), `Object.assign` |
|
||||
| Spread | `Array.isArray`, `Array.from` |
|
||||
|
||||
## Classes
|
||||
|
||||
@@ -30,14 +39,3 @@ class Bar extends Foo {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## For-of
|
||||
|
||||
A polyfill is required for for-of functionality that implements `Symbol` and
|
||||
adds `prototype[Symbol.iterator]` behaviour to built-ins. Using the polyfills
|
||||
specified in [polyfill](polyfill.md) suffices.
|
||||
|
||||
## Spread
|
||||
|
||||
An [ES6 polyfill](polyfill.md) is required in order for spread to work. More
|
||||
specifically a polyfill for `Array.from`.
|
||||
|
||||
@@ -56,37 +56,47 @@ better suited if you'd like a full ES6 environment with polyfills and all.
|
||||
|
||||
## Comparison to other transpilers
|
||||
|
||||
| | 6to5 | Traceur | esnext | es6now | es6-transpiler | jstransform |
|
||||
| ---------------------------- | ---- | ------- | ------ | ------ | -------------- | ----------- |
|
||||
| No runtime | ✓ | | | | ✓ | ✓ |
|
||||
| Source maps | ✓ | ✓ | ✓ | | ✓ | ✓ |
|
||||
| No compiler global pollution | ✓ | | ✓ | | ✓ | ✓ |
|
||||
| Browser support | ✓ | ✓ | ✓ | | | |
|
||||
| Array comprehension | ✓ | ✓ | | | ✓ | |
|
||||
| Arrow functions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Async functions | ✓ | ✓ | ✓ | | | |
|
||||
| Classes | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Computed property names | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Constants | ✓ | ✓ | | | ✓ | |
|
||||
| Default parameters | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Destructuring | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| For-of | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Generators | ✓ | ✓ | ✓ | | | |
|
||||
| Generator comprehension | ✓ | ✓ | | | | |
|
||||
| Let scoping | ✓ | ✓ | | | ✓ | |
|
||||
| Modules | ✓ | ✓ | | ✓ | | |
|
||||
| Property method assignment | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Property name shorthand | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Rest parameters | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Spread | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Template literals | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Unicode regex | ✓ | ✓ | | | ✓ | |
|
||||
### Features
|
||||
|
||||
| | 6to5 | Traceur | es6-transpiler | esnext | es6now | jstransform |
|
||||
| ---------------------------- | ---- | ------- | -------------- | ------ | ------ | ----------- |
|
||||
| Source maps | ✓ | ✓ | ✓ | ✓ | | ✓ |
|
||||
| No compiler global pollution | ✓ | | ✓ | ✓ | | ✓ |
|
||||
| Optional runtime | ✓ | | ✓ | | | ✓ |
|
||||
| Browser support | ✓ | ✓ | | ✓ | | |
|
||||
|
||||
### Language Support
|
||||
|
||||
| | 6to5 | Traceur | es6-transpiler | esnext | es6now | jstransform |
|
||||
| ---------------------------- | ----- | ------- | -------------- | ------ | ------ | ----------- |
|
||||
| Abstract references | ✓ | | | | | |
|
||||
| Array comprehension | ✓ | ✓ | ✓ | | | |
|
||||
| Arrow functions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Async functions | ✓ | ✓ | | ✓ | | |
|
||||
| Classes | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Computed property names | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Constants | ✓ | ✓ | ✓ | | | |
|
||||
| Default parameters | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Destructuring | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Exponentiation operator | ✓ | ✓ | | | | |
|
||||
| For-of | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Generators | ✓ | ✓ | | ✓ | | |
|
||||
| Generator comprehension | ✓ | ✓ | | | | |
|
||||
| Let scoping | ✓ | ✓ | ✓ | | | |
|
||||
| Modules | ✓ | ✓ | | | ✓ | |
|
||||
| Object rest/spread | ✓ | | | | | ✓ |
|
||||
| Property method assignment | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Property name shorthand | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Rest parameters | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Spread | ✓ | ✓ | ✓ | ✓ | ✓ | |
|
||||
| Template literals | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| Unicode regex | ✓ | ✓ | ✓ | | | |
|
||||
|
||||
### [Traceur](https://github.com/google/traceur-compiler)
|
||||
|
||||
Traceur requires quite a bulky runtime (~75KB) and produces quite verbose code.
|
||||
While this can be trimmed down by selectively building the runtime, it's an
|
||||
unneccesary step when a runtime can be eliminated entirely.
|
||||
unneccesary step when a large runtime can be eliminated entirely.
|
||||
|
||||
### [es6now](https://github.com/zenparsing/es6now)
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
# Features
|
||||
|
||||
## Array comprehension
|
||||
## Abstract references ([experimental](usage.md#experimental)) ([spec](https://github.com/zenparsing/es-abstract-refs))
|
||||
|
||||
```javascript
|
||||
foo::bar;
|
||||
foo::bar = baz;
|
||||
delete foo::bar;
|
||||
```
|
||||
|
||||
## Array comprehensions ([experimental](usage.md#experimental))
|
||||
|
||||
```javascript
|
||||
var results = [for (c of customers) if (c.city == "Seattle") { name: c.name, age: c.age }]
|
||||
@@ -31,7 +39,7 @@ var bob = {
|
||||
};
|
||||
```
|
||||
|
||||
## Async functions
|
||||
## Async functions ([experimental](usage.md#experimental)) ([spec](https://github.com/lukehoban/ecmascript-asyncawait))
|
||||
|
||||
```javascript
|
||||
async function chainAnimationsAsync(elem, animations) {
|
||||
@@ -122,6 +130,15 @@ var [a] = [];
|
||||
a === undefined;
|
||||
```
|
||||
|
||||
## Exponentiation operator ([experimental](usage.md#experimental)) ([spec](https://github.com/rwaldron/exponentiation-operator))
|
||||
|
||||
```javascript
|
||||
var a = 2;
|
||||
a **= 2;
|
||||
|
||||
var squared = 2 ** 2;
|
||||
```
|
||||
|
||||
## For-of
|
||||
|
||||
```javascript
|
||||
@@ -133,11 +150,31 @@ for (var i of [1, 2, 3]) {
|
||||
## Generators
|
||||
|
||||
```javascript
|
||||
function* fibonacci() {
|
||||
var pre = 0, cur = 1;
|
||||
for (;;) {
|
||||
var temp = pre;
|
||||
pre = cur;
|
||||
cur += temp;
|
||||
yield cur;
|
||||
}
|
||||
}
|
||||
|
||||
for (var n of fibonacci()) {
|
||||
// truncate the sequence at 1000
|
||||
if (n > 1000) break;
|
||||
console.log(n);
|
||||
}
|
||||
```
|
||||
|
||||
## Generator comprehension
|
||||
## Generator comprehensions ([experimental](usage.md#experimental))
|
||||
|
||||
```javascript
|
||||
var nums = [1, 2, 3, 4, 5, 6];
|
||||
var multiples = (for (i of nums) if (i % 2) i * i);
|
||||
assert.equal(multiples.next().value, 1);
|
||||
assert.equal(multiples.next().value, 9);
|
||||
assert.equal(multiples.next().value, 25);
|
||||
```
|
||||
|
||||
## Let scoping
|
||||
@@ -151,6 +188,17 @@ for (let i in arr) {
|
||||
## Modules
|
||||
|
||||
```javascript
|
||||
import "foo";
|
||||
import foo from "foo";
|
||||
import * as foo from "foo";
|
||||
import {bar} from "foo";
|
||||
import {foo as bar} from "foo";
|
||||
|
||||
export { test };
|
||||
export var test = 5;
|
||||
export function test() {}
|
||||
|
||||
export default test;
|
||||
```
|
||||
|
||||
## Numeric literals
|
||||
@@ -160,6 +208,13 @@ for (let i in arr) {
|
||||
0o767 === 503; // true
|
||||
```
|
||||
|
||||
## Object spread/rest ([experimental](usage.md#experimental)) ([spec](https://github.com/sebmarkbage/ecmascript-rest-spread))
|
||||
|
||||
```javascript
|
||||
var n = { x, y, ...z };
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
```
|
||||
|
||||
## Property method assignment
|
||||
|
||||
```javascript
|
||||
@@ -213,7 +268,6 @@ var x = 5;
|
||||
var y = 10;
|
||||
console.log(`${x} + ${y} = ${x + y}`); // "5 + 10 = 15"
|
||||
```
|
||||
|
||||
## Unicode regex
|
||||
|
||||
```javascript
|
||||
|
||||
13
doc/index.md
13
doc/index.md
@@ -3,7 +3,7 @@
|
||||
- **Readable** - formatting is retained if possible so your generated code is as similar as possible.
|
||||
- **Extensible** - with a large range of [plugins](plugins.md) and **browser support**.
|
||||
- **Lossless** - **source map support** so you can debug your compiled code with ease.
|
||||
- **Compact** - maps directly to the equivalent ES5 with **no runtime**[\*](caveats.md#generators).
|
||||
- **Compact** - maps directly to the equivalent ES5 with **no runtime**[\*](caveats.md).
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -31,20 +31,23 @@ And it doesn't end here! To see all the ways you can use 6to5, check out the
|
||||
|
||||
## [Features](features.md)
|
||||
|
||||
- [Array comprehension](features.md#array-comprehension)
|
||||
- [Async functions](features.md#async-functions) via [regenerator](https://github.com/facebook/regenerator)
|
||||
- [Abstract references](features.md#abstract-references) ([experimental](usage.md#experimental))
|
||||
- [Array comprehension](features.md#array-comprehension) ([experimental](usage.md#experimental))
|
||||
- [Async functions](features.md#async-functions) ([experimental](usage.md#experimental))
|
||||
- [Arrow functions](features.md#arrow-functions)
|
||||
- [Classes](features.md#classes)
|
||||
- [Computed property names](features.md#computed-property-names)
|
||||
- [Constants](features.md#constants)
|
||||
- [Default parameters](features.md#default-parameters)
|
||||
- [Destructuring](features.md#destructuring)
|
||||
- [Exponentiation operator](features.md#exponentiation-operator) ([experimental](usage.md#experimental))
|
||||
- [For-of](features.md#for-of)
|
||||
- [Generators](features.md#generators) via [regenerator](https://github.com/facebook/regenerator)
|
||||
- [Generator comprehension](features.md#generator-comprehension)
|
||||
- [Generators](features.md#generators)
|
||||
- [Generator comprehension](features.md#generator-comprehension) ([experimental](usage.md#experimental))
|
||||
- [Let scoping](features.md#let-scoping)
|
||||
- [Modules](features.md#modules)
|
||||
- [Numeric literals](features.md#numeric-literals)
|
||||
- [Object Rest/Spread](features.md#object-rest-spread) ([experimental](usage.md#experimental))
|
||||
- [Property method assignment](features.md#property-method-assignment)
|
||||
- [Property name shorthand](features.md#property-name-shorthand)
|
||||
- [React/JSX](react.md)
|
||||
|
||||
112
doc/modules.md
112
doc/modules.md
@@ -15,6 +15,13 @@ to5.transform('import "foo";', { modules: "common" });
|
||||
|
||||
## Formats
|
||||
|
||||
* [AMD](#amd)
|
||||
* [Common (Default)](#common-default)
|
||||
* [Common](#common)
|
||||
* [Ignore](#ignore)
|
||||
* [System](#system)
|
||||
* [UMD](#umd)
|
||||
|
||||
### Common (Default)
|
||||
|
||||
**In**
|
||||
@@ -51,6 +58,69 @@ var test = 5; exports.test = test;
|
||||
exports.default = test;
|
||||
```
|
||||
|
||||
### Common interop
|
||||
|
||||
**In**
|
||||
|
||||
```javascript
|
||||
import "foo";
|
||||
|
||||
import foo from "foo";
|
||||
import * as foo from "foo";
|
||||
|
||||
import {bar} from "foo";
|
||||
import {foo as bar} from "foo";
|
||||
|
||||
export {test};
|
||||
export var test = 5;
|
||||
|
||||
export default test;
|
||||
```
|
||||
|
||||
**Out**
|
||||
|
||||
```javascript
|
||||
var _interopRequire = function (obj) {
|
||||
return obj && (obj["default"] || obj);
|
||||
};
|
||||
|
||||
require("foo");
|
||||
|
||||
var foo = _interopRequire(require("foo"));
|
||||
var foo = require("foo");
|
||||
|
||||
var bar = require("foo").bar;
|
||||
var bar = require("foo").foo;
|
||||
|
||||
exports.test = test;
|
||||
var test = exports.test = 5;
|
||||
|
||||
exports["default"] = test;
|
||||
```
|
||||
|
||||
#### module.exports behaviour
|
||||
|
||||
If there exist no other non-default `export`s then `default exports` are
|
||||
exported as `module.exports` instead of `exports.default`.
|
||||
|
||||
**In**
|
||||
|
||||
```javascript
|
||||
export default function foo() {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
**Out**
|
||||
|
||||
```javascript
|
||||
module.exports = foo;
|
||||
|
||||
function foo() {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### AMD
|
||||
|
||||
**In**
|
||||
@@ -77,6 +147,12 @@ define(["exports", "foo"], function (exports, _foo) {
|
||||
});
|
||||
```
|
||||
|
||||
You can optionally specify to include the module id (using the `--amd-module-id` argument):
|
||||
|
||||
```javascript
|
||||
define("filename", ["exports", "foo"], function (exports, _foo) {})
|
||||
```
|
||||
|
||||
### UMD
|
||||
|
||||
**In**
|
||||
@@ -111,7 +187,6 @@ export function bar() {
|
||||
|
||||
### Ignore
|
||||
|
||||
|
||||
**In**
|
||||
|
||||
```javascript
|
||||
@@ -130,6 +205,41 @@ function bar() {
|
||||
}
|
||||
```
|
||||
|
||||
### System
|
||||
|
||||
**In**
|
||||
|
||||
```javascript
|
||||
import foo from "foo";
|
||||
|
||||
export function bar() {
|
||||
return foo("foobar");
|
||||
}
|
||||
```
|
||||
|
||||
**Out**
|
||||
|
||||
```javascript
|
||||
System.register("bar", ["foo"], function (_export) {
|
||||
"use strict";
|
||||
|
||||
var __moduleName = "bar";
|
||||
|
||||
var foo;
|
||||
function bar() {
|
||||
return foo("foobar");
|
||||
}
|
||||
return {
|
||||
setters: [function (m) {
|
||||
foo = m.default;
|
||||
}],
|
||||
execute: function () {
|
||||
_export("bar", bar);
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
## Custom
|
||||
|
||||
You can alternatively specify module names instead of one of the built-in types.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -5,13 +5,23 @@
|
||||
[es6-shim](https://github.com/paulmillr/es6-shim) and
|
||||
[es6-symbol](https://github.com/medikoo/es6-symbol) polyfills.
|
||||
|
||||
## Node
|
||||
This will emulate a full ES6 environment. This polyfill is automatically loaded
|
||||
when using [6to5-node](usage.md#node).
|
||||
|
||||
## Usage
|
||||
|
||||
### Node
|
||||
|
||||
You need to include the polyfill require at the top the **entry point** to your
|
||||
application.
|
||||
|
||||
```javascript
|
||||
require("6to5/polyfill");
|
||||
```
|
||||
|
||||
## Browser
|
||||
### Browser
|
||||
|
||||
Available from the `browser-polyfill.js` file within the 6to5 directory of an
|
||||
npm release.
|
||||
npm release. This needs to be included **before** all your compiled 6to5 code.
|
||||
You can either prepend it to your compiled code or include it in a `<script>`
|
||||
before it.
|
||||
|
||||
41
doc/usage.md
41
doc/usage.md
@@ -83,6 +83,10 @@ to5.transformFile("filename.js", options, function (err, result) {
|
||||
// Default: "unknown"
|
||||
filename: "filename",
|
||||
|
||||
// Filename relative to `sourceRoot`
|
||||
// Default: `filename` option.
|
||||
filenameRelative: "",
|
||||
|
||||
// List of transformers to EXCLUDE.
|
||||
// Run `6to5 --help` to see a full list of transformers.
|
||||
blacklist: [],
|
||||
@@ -103,17 +107,39 @@ to5.transformFile("filename.js", options, function (err, result) {
|
||||
sourceMap: true,
|
||||
|
||||
// Set `file` on returned source map.
|
||||
// Default: `filename` option.
|
||||
// Default: `filenameRelative` option.
|
||||
sourceMapName: "filename",
|
||||
|
||||
// Set `sources[0]` on returned source map.
|
||||
// Default: `filename` option.
|
||||
// Default: `filenameRelative` option.
|
||||
sourceFileName: "filename",
|
||||
|
||||
// The root from which all sources are relative
|
||||
// Default: `moduleRoot` option.
|
||||
sourceRoot: "assets/scripts",
|
||||
|
||||
// Optional prefix for the AMD module formatter that will be prepend to the
|
||||
// filename on module definitions
|
||||
// Default: `sourceRoot` option.
|
||||
moduleRoot: "my-app",
|
||||
|
||||
// If truthy, insert an explicit id for each defined AMD module.
|
||||
// By default, AMD modules are anonymous.
|
||||
// Default: false
|
||||
amdModuleIds: true,
|
||||
|
||||
// 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,
|
||||
|
||||
// Enable support for experimental ES7 features
|
||||
// Default: false
|
||||
experimental: true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -159,3 +185,12 @@ require("6to5/register")({
|
||||
extensions: [".js", ".es6"]
|
||||
});
|
||||
```
|
||||
|
||||
## Experimental
|
||||
|
||||
6to5 also has experimental support for ES7 proposals. You can enable this with
|
||||
the `experimental: true` option when using the [Node API](#node) or
|
||||
`--experimental` when using the [CLI](#cli).
|
||||
|
||||
**WARNING:** These proposals are subject to change so use with
|
||||
**extreme caution**.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -10,36 +10,59 @@ var t = require("./types");
|
||||
var _ = require("lodash");
|
||||
|
||||
function File(opts) {
|
||||
this.opts = File.normaliseOptions(opts);
|
||||
this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
|
||||
this.declarations = {};
|
||||
this.uids = {};
|
||||
this.ast = {};
|
||||
this.opts = File.normaliseOptions(opts);
|
||||
this.uids = {};
|
||||
this.ast = {};
|
||||
}
|
||||
|
||||
File.declarations = ["extends", "class-props", "slice", "apply-constructor"];
|
||||
File.declarations = [
|
||||
"extends",
|
||||
"class-props",
|
||||
"apply-constructor",
|
||||
"tagged-template-literal",
|
||||
"interop-require",
|
||||
"to-array",
|
||||
"arguments-to-array",
|
||||
"object-spread"
|
||||
];
|
||||
|
||||
File.normaliseOptions = function (opts) {
|
||||
opts = _.cloneDeep(opts || {});
|
||||
|
||||
_.defaults(opts, {
|
||||
whitespace: true,
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
filename: "unknown",
|
||||
modules: "common",
|
||||
runtime: false,
|
||||
code: true
|
||||
experimental: false,
|
||||
whitespace: true,
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
comments: true,
|
||||
filename: "unknown",
|
||||
modules: "common",
|
||||
runtime: false,
|
||||
code: true
|
||||
});
|
||||
|
||||
// normalise windows path separators to unix
|
||||
opts.filename = opts.filename.replace(/\\/g, "/");
|
||||
|
||||
opts.blacklist = util.arrayify(opts.blacklist);
|
||||
opts.whitelist = util.arrayify(opts.whitelist);
|
||||
|
||||
_.defaults(opts, {
|
||||
sourceFileName: opts.filename,
|
||||
sourceMapName: opts.filename
|
||||
moduleRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
_.defaults(opts, {
|
||||
sourceRoot: opts.moduleRoot
|
||||
});
|
||||
|
||||
_.defaults(opts, {
|
||||
filenameRelative: opts.filename
|
||||
});
|
||||
|
||||
_.defaults(opts, {
|
||||
sourceFileName: opts.filenameRelative,
|
||||
sourceMapName: opts.filenameRelative
|
||||
});
|
||||
|
||||
if (opts.runtime === true) {
|
||||
@@ -52,8 +75,21 @@ File.normaliseOptions = function (opts) {
|
||||
return opts;
|
||||
};
|
||||
|
||||
File.prototype.toArray = function (node) {
|
||||
if (t.isArrayExpression(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
var templateName = "to-array";
|
||||
if (t.isIdentifier(node) && node.name === "arguments") {
|
||||
templateName = "arguments-to-array";
|
||||
}
|
||||
|
||||
return t.callExpression(this.addDeclaration(templateName), [node]);
|
||||
};
|
||||
|
||||
File.prototype.getModuleFormatter = function (type) {
|
||||
var ModuleFormatter = transform.moduleFormatters[type];
|
||||
var ModuleFormatter = _.isFunction(type) ? type : transform.moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolve(type);
|
||||
@@ -84,8 +120,10 @@ File.prototype.addDeclaration = function (name) {
|
||||
throw new ReferenceError("unknown declaration " + name);
|
||||
}
|
||||
|
||||
var declar = this.declarations[name];
|
||||
if (declar) return declar.uid;
|
||||
var program = this.ast.program;
|
||||
|
||||
var declar = program._declarations && program._declarations[name];
|
||||
if (declar) return declar.id;
|
||||
|
||||
var ref;
|
||||
var runtimeNamespace = this.opts.runtime;
|
||||
@@ -96,11 +134,8 @@ File.prototype.addDeclaration = function (name) {
|
||||
ref = util.template(name);
|
||||
}
|
||||
|
||||
var uid = t.identifier(this.generateUid(name));
|
||||
this.declarations[name] = {
|
||||
uid: uid,
|
||||
node: ref
|
||||
};
|
||||
var uid = this.generateUidIdentifier(name);
|
||||
this.scope.push(name, uid, ref);
|
||||
return uid;
|
||||
};
|
||||
|
||||
@@ -130,7 +165,8 @@ File.prototype.parse = function (code) {
|
||||
|
||||
File.prototype.transform = function (ast) {
|
||||
this.ast = ast;
|
||||
this.scope = new Scope(null, ast.program);
|
||||
this.scope = new Scope(ast.program);
|
||||
this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
|
||||
var self = this;
|
||||
|
||||
@@ -179,6 +215,10 @@ File.prototype.generateUid = function (name, scope) {
|
||||
return uid;
|
||||
};
|
||||
|
||||
File.prototype.generateUidIdentifier = function (name, scope) {
|
||||
return t.identifier(this.generateUid(name, scope));
|
||||
};
|
||||
|
||||
File.prototype._generateUid = function (name) {
|
||||
var uids = this.uids;
|
||||
var i = uids[name] || 1;
|
||||
|
||||
@@ -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 = {
|
||||
@@ -169,6 +165,8 @@ CodeGenerator.prototype.print = function (node, parent, opts) {
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.printJoin = function (print, nodes, opts) {
|
||||
if (!nodes || !nodes.length) return;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
var self = this;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var t = require("../../types");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.UnaryExpression = function (node, print) {
|
||||
var hasSpace = /[a-z]$/.test(node.operator);
|
||||
@@ -105,6 +106,11 @@ exports.MemberExpression = function (node, print) {
|
||||
print(node.property);
|
||||
this.push("]");
|
||||
} else {
|
||||
// 5..toFixed(2);
|
||||
if (t.isLiteral(node.object) && util.isInteger(node.object.value)) {
|
||||
this.push(".");
|
||||
}
|
||||
|
||||
this.push(".");
|
||||
print(node.property);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,18 @@ exports.Identifier = function (node) {
|
||||
this.push(node.name);
|
||||
};
|
||||
|
||||
exports.SpreadElement = function (node, print) {
|
||||
exports.SpreadElement =
|
||||
exports.SpreadProperty = function (node, print) {
|
||||
this.push("...");
|
||||
print(node.argument);
|
||||
};
|
||||
|
||||
exports.VirtualPropertyExpression = function (node, print) {
|
||||
print(node.object);
|
||||
this.push("::");
|
||||
print(node.property);
|
||||
};
|
||||
|
||||
exports.ObjectExpression =
|
||||
exports.ObjectPattern = function (node, print) {
|
||||
var props = node.properties;
|
||||
@@ -78,7 +85,7 @@ exports.Literal = function (node) {
|
||||
val = JSON.stringify(val);
|
||||
|
||||
// escape unicode characters
|
||||
val = val.replace(/[\u007f-\uffff]/g, function(c) {
|
||||
val = val.replace(/[\u007f-\uffff]/g, function (c) {
|
||||
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ module.exports = Node;
|
||||
|
||||
var whitespace = require("./whitespace");
|
||||
var parens = require("./parentheses");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
var find = function (obj, node, parent) {
|
||||
var result;
|
||||
@@ -24,15 +24,7 @@ function Node(node, parent) {
|
||||
}
|
||||
|
||||
Node.prototype.isUserWhitespacable = function () {
|
||||
var parent = this.parent;
|
||||
var node = this.node;
|
||||
|
||||
if (t.isUserWhitespacable(node) ||
|
||||
t.isSequenceExpression(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return t.isUserWhitespacable(this.node);
|
||||
};
|
||||
|
||||
Node.prototype.needsWhitespace = function (type) {
|
||||
|
||||
@@ -9,6 +9,10 @@ exports.before = {
|
||||
}
|
||||
},
|
||||
|
||||
SpreadProperty: function (node, parent) {
|
||||
return exports.before.nodes.Property(node, parent);
|
||||
},
|
||||
|
||||
SwitchCase: function (node, parent) {
|
||||
if (parent.cases[0] === node) {
|
||||
return 1;
|
||||
|
||||
@@ -9,7 +9,8 @@ function SourceMap(position, opts, code) {
|
||||
|
||||
if (opts.sourceMap) {
|
||||
this.map = new sourceMap.SourceMapGenerator({
|
||||
file: opts.sourceMapName
|
||||
file: opts.sourceMapName,
|
||||
sourceRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
this.map.setSourceContent(opts.sourceFileName, code);
|
||||
|
||||
@@ -17,6 +17,9 @@ exports.polyfill = function () {
|
||||
|
||||
exports.canCompile = util.canCompile;
|
||||
|
||||
// do not use this - this is for use by official maintained 6to5 plugins
|
||||
exports._util = util;
|
||||
|
||||
exports.transform = transform;
|
||||
|
||||
exports.transformFile = function (filename, opts, callback) {
|
||||
|
||||
@@ -3,6 +3,7 @@ var _ = require("lodash");
|
||||
|
||||
var types = require("ast-types");
|
||||
var def = types.Type.def;
|
||||
var or = types.Type.or;
|
||||
|
||||
// Program wrapper
|
||||
def("File")
|
||||
@@ -16,12 +17,19 @@ def("ParenthesizedExpression")
|
||||
.build("expression")
|
||||
.field("expression", def("Expression"));
|
||||
|
||||
// Same as ImportNamespaceSpecifier but `id` is `name`
|
||||
// Acorn - Same as ImportNamespaceSpecifier but `id` is `name`
|
||||
def("ImportBatchSpecifier")
|
||||
.bases("Specifier")
|
||||
.build("name")
|
||||
.field("name", def("Identifier"));
|
||||
|
||||
// Abstract references
|
||||
def("VirtualPropertyExpression")
|
||||
.bases("Expression")
|
||||
.build("object", "property")
|
||||
.field("object", def("Expression"))
|
||||
.field("property", or(def("Identifier"), def("Expression")));
|
||||
|
||||
types.finalize();
|
||||
|
||||
var estraverse = require("estraverse");
|
||||
|
||||
@@ -1,6 +1,37 @@
|
||||
/* jshint newcap: false */
|
||||
|
||||
var ensureSymbol = function (key) {
|
||||
Symbol[key] = Symbol[key] || Symbol();
|
||||
};
|
||||
|
||||
var ensureProto = function (Constructor, key, val) {
|
||||
var proto = Constructor.prototype;
|
||||
proto[key] = proto[key] || val;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
if (typeof Symbol === "undefined") {
|
||||
require("es6-symbol/implement");
|
||||
}
|
||||
|
||||
require("es6-shim");
|
||||
require("regenerator-6to5/runtime");
|
||||
require("./transformation/transformers/es6-generators/runtime");
|
||||
|
||||
// Abstract references
|
||||
|
||||
ensureSymbol("referenceGet");
|
||||
ensureSymbol("referenceSet");
|
||||
ensureSymbol("referenceDelete");
|
||||
|
||||
ensureProto(Function, Symbol.referenceGet, function () { return this; });
|
||||
|
||||
ensureProto(Map, Symbol.referenceGet, Map.prototype.get);
|
||||
ensureProto(Map, Symbol.referenceSet, Map.prototype.set);
|
||||
ensureProto(Map, Symbol.referenceDelete, Map.prototype.delete);
|
||||
|
||||
if (global.WeakMap) {
|
||||
ensureProto(WeakMap, Symbol.referenceGet, WeakMap.prototype.get);
|
||||
ensureProto(WeakMap, Symbol.referenceSet, WeakMap.prototype.set);
|
||||
ensureProto(WeakMap, Symbol.referenceDelete, WeakMap.prototype.delete);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require("./polyfill");
|
||||
|
||||
var sourceMapSupport = require("source-map-support");
|
||||
var util = require("./util");
|
||||
var to5 = require("./index");
|
||||
var _ = require("lodash");
|
||||
|
||||
@@ -56,23 +57,25 @@ blacklistTest("unicodeRegex", function () { new RegExp("foo", "u"); });
|
||||
|
||||
//
|
||||
|
||||
var ignoreRegex = /node_modules/;
|
||||
var transformOpts = {};
|
||||
var ignoreRegex = /node_modules/;
|
||||
var onlyRegex;
|
||||
var whitelist = [];
|
||||
var exts = {};
|
||||
var maps = {};
|
||||
var old = require.extensions[".js"];
|
||||
var whitelist = [];
|
||||
var exts = {};
|
||||
var maps = {};
|
||||
var old = require.extensions[".js"];
|
||||
|
||||
var loader = function (m, filename) {
|
||||
if ((ignoreRegex && ignoreRegex.test(filename)) || (onlyRegex && !onlyRegex.test(filename))) {
|
||||
return old.apply(this, arguments);
|
||||
}
|
||||
|
||||
var result = to5.transformFileSync(filename, {
|
||||
var result = to5.transformFileSync(filename, _.extend({
|
||||
whitelist: whitelist,
|
||||
blacklist: blacklist,
|
||||
sourceMap: true
|
||||
});
|
||||
sourceMap: true,
|
||||
modules: "commonInterop"
|
||||
}, transformOpts));
|
||||
|
||||
maps[filename] = result.map;
|
||||
|
||||
@@ -100,11 +103,10 @@ module.exports = function (opts) {
|
||||
if (_.isRegExp(opts)) opts = { ignore: opts };
|
||||
if (opts.ignoreRegex != null) opts.ignore = opts.ignoreRegex;
|
||||
|
||||
if (opts.only != null) onlyRegex = opts.only;
|
||||
if (opts.ignore != null) ignoreRegex = opts.ignore;
|
||||
if (opts.only != null) onlyRegex = util.regexify(opts.only);
|
||||
if (opts.ignore != null) ignoreRegex = util.regexify(opts.ignore);
|
||||
|
||||
if (opts.extensions) hookExtensions(opts.extensions);
|
||||
if (opts.extensions) hookExtensions(util.arrayify(opts.extensions));
|
||||
|
||||
if (opts.blacklist) blacklist = opts.blacklist;
|
||||
if (opts.whitelist) whitelist = opts.whitelist;
|
||||
_.extend(transformOpts, opts);
|
||||
};
|
||||
|
||||
@@ -5,18 +5,16 @@ var t = require("./types");
|
||||
var _ = require("lodash");
|
||||
|
||||
module.exports = function (namespace) {
|
||||
namespace = t.identifier(namespace || "to5Runtime");
|
||||
namespace = t.identifier(t.toIdentifier(namespace || "to5Runtime"));
|
||||
|
||||
var body = [];
|
||||
var container = t.functionExpression(null, [], t.blockStatement(body));
|
||||
var tree = t.program([t.expressionStatement(t.callExpression(container, []))]);
|
||||
|
||||
body.push(util.template("self-global", true));
|
||||
var container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
|
||||
var tree = t.program([t.expressionStatement(t.callExpression(container, [util.template("self-global")]))]);
|
||||
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
namespace,
|
||||
t.assignmentExpression("=", t.memberExpression(t.identifier("self"), namespace), t.objectExpression([]))
|
||||
t.assignmentExpression("=", t.memberExpression(t.identifier("global"), namespace), t.objectExpression([]))
|
||||
)
|
||||
]));
|
||||
|
||||
|
||||
1
lib/6to5/templates/abstract-expression-call.js
Normal file
1
lib/6to5/templates/abstract-expression-call.js
Normal file
@@ -0,0 +1 @@
|
||||
PROPERTY[Symbol.referenceGet](OBJECT).call(OBJECT)
|
||||
1
lib/6to5/templates/abstract-expression-delete.js
Normal file
1
lib/6to5/templates/abstract-expression-delete.js
Normal file
@@ -0,0 +1 @@
|
||||
PROPERTY[Symbol.referenceDelete](OBJECT)
|
||||
1
lib/6to5/templates/abstract-expression-get.js
Normal file
1
lib/6to5/templates/abstract-expression-get.js
Normal file
@@ -0,0 +1 @@
|
||||
PROPERTY[Symbol.referenceGet](OBJECT)
|
||||
1
lib/6to5/templates/abstract-expression-set.js
Normal file
1
lib/6to5/templates/abstract-expression-set.js
Normal file
@@ -0,0 +1 @@
|
||||
PROPERTY[Symbol.referenceSet](OBJECT, VALUE)
|
||||
@@ -1,5 +1,5 @@
|
||||
(function (Constructor, args) {
|
||||
var bindArgs = [null].concat(args);
|
||||
var Factory = Constructor.bind.apply(Constructor, bindArgs);
|
||||
return new Factory;
|
||||
var instance = Object.create(Constructor.prototype);
|
||||
var result = Constructor.apply(instance, args);
|
||||
return result != null && (typeof result == "object" || typeof result == "function") ? result : instance;
|
||||
});
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
var VARIABLE_NAME = SLICE_KEY.call(arguments, SLICE_ARG);
|
||||
@@ -1 +0,0 @@
|
||||
var VARIABLE_NAME = SLICE_KEY.call(arguments);
|
||||
@@ -1 +0,0 @@
|
||||
SLICE_KEY.call(arguments);
|
||||
7
lib/6to5/templates/arguments-to-array.js
Normal file
7
lib/6to5/templates/arguments-to-array.js
Normal file
@@ -0,0 +1,7 @@
|
||||
(function (args) {
|
||||
var target = new Array(args.length);
|
||||
for (var i = 0; i< args.length; i++) {
|
||||
target[i] = args[i];
|
||||
}
|
||||
return target;
|
||||
})
|
||||
1
lib/6to5/templates/array-from.js
Normal file
1
lib/6to5/templates/array-from.js
Normal file
@@ -0,0 +1 @@
|
||||
Array.from(VALUE);
|
||||
1
lib/6to5/templates/exports-default-module.js
Normal file
1
lib/6to5/templates/exports-default-module.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = VALUE;
|
||||
3
lib/6to5/templates/interop-require.js
Normal file
3
lib/6to5/templates/interop-require.js
Normal file
@@ -0,0 +1,3 @@
|
||||
(function (obj) {
|
||||
return obj && (obj["default"] || obj);
|
||||
})
|
||||
9
lib/6to5/templates/object-spread.js
Normal file
9
lib/6to5/templates/object-spread.js
Normal file
@@ -0,0 +1,9 @@
|
||||
(function (obj, keys) {
|
||||
var target = {};
|
||||
for (var i in obj) {
|
||||
if (keys.indexOf(i) >= 0) continue;
|
||||
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
|
||||
target[i] = obj[i];
|
||||
}
|
||||
return target;
|
||||
})
|
||||
1
lib/6to5/templates/register.js
Normal file
1
lib/6to5/templates/register.js
Normal file
@@ -0,0 +1 @@
|
||||
System.register(MODULE_NAME, MODULE_DEPENDENCIES, MODULE_BODY);
|
||||
@@ -1 +1 @@
|
||||
var self = typeof global === "undefined" ? window : global;
|
||||
typeof global === "undefined" ? self : global
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Array.prototype.slice;
|
||||
4
lib/6to5/templates/tagged-template-literal.js
Normal file
4
lib/6to5/templates/tagged-template-literal.js
Normal file
@@ -0,0 +1,4 @@
|
||||
(function (strings, raw) {
|
||||
return Object.defineProperties(strings, { raw: { value: raw } });
|
||||
});
|
||||
|
||||
3
lib/6to5/templates/to-array.js
Normal file
3
lib/6to5/templates/to-array.js
Normal file
@@ -0,0 +1,3 @@
|
||||
(function (arr) {
|
||||
return Array.isArray(arr) ? arr : Array.from(arr);
|
||||
});
|
||||
@@ -30,11 +30,24 @@ AMDFormatter.prototype.transform = function (ast) {
|
||||
params.unshift(t.identifier("exports"));
|
||||
|
||||
var container = t.functionExpression(null, params, t.blockStatement(body));
|
||||
var call = t.callExpression(t.identifier("define"), [names, container]);
|
||||
|
||||
var defineArgs = [names, container];
|
||||
var moduleName = this.getModuleName();
|
||||
if (moduleName) defineArgs.unshift(t.literal(moduleName));
|
||||
|
||||
var call = t.callExpression(t.identifier("define"), defineArgs);
|
||||
|
||||
program.body = [t.expressionStatement(call)];
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.getModuleName = function () {
|
||||
if (this.file.opts.amdModuleIds) {
|
||||
return CommonJSFormatter.prototype.getModuleName.apply(this, arguments);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
AMDFormatter.prototype._push = function (node) {
|
||||
var id = node.source.value;
|
||||
var ids = this.ids;
|
||||
@@ -42,7 +55,7 @@ AMDFormatter.prototype._push = function (node) {
|
||||
if (ids[id]) {
|
||||
return ids[id];
|
||||
} else {
|
||||
return this.ids[id] = t.identifier(this.file.generateUid(id));
|
||||
return this.ids[id] = this.file.generateUidIdentifier(id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
53
lib/6to5/transformation/modules/common-interop.js
Normal file
53
lib/6to5/transformation/modules/common-interop.js
Normal file
@@ -0,0 +1,53 @@
|
||||
module.exports = CommonJSInteropFormatter;
|
||||
|
||||
var CommonJSFormatter = require("./common");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
|
||||
function CommonJSInteropFormatter() {
|
||||
this.has = false;
|
||||
CommonJSFormatter.apply(this, arguments);
|
||||
}
|
||||
|
||||
util.inherits(CommonJSInteropFormatter, CommonJSFormatter);
|
||||
|
||||
CommonJSInteropFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
var variableName = t.getSpecifierName(specifier);
|
||||
|
||||
// import foo from "foo";
|
||||
if (specifier.default) {
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(variableName,
|
||||
t.callExpression(this.file.addDeclaration("interop-require"), [util.template("require", {
|
||||
MODULE_NAME: node.source.raw
|
||||
})])
|
||||
)
|
||||
]));
|
||||
} else {
|
||||
CommonJSFormatter.prototype.importSpecifier.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
CommonJSInteropFormatter.prototype.export = function (node, nodes) {
|
||||
if (node.default && !this.has) {
|
||||
var declar = node.declaration;
|
||||
|
||||
// module.exports = VALUE;
|
||||
var assign = util.template("exports-default-module", {
|
||||
VALUE: this._pushStatement(declar, nodes)
|
||||
}, true);
|
||||
|
||||
// hoist to the top if this default is a function
|
||||
nodes.push(this._hoistExport(declar, assign));
|
||||
return;
|
||||
} else {
|
||||
this.has = true;
|
||||
}
|
||||
|
||||
CommonJSFormatter.prototype.export.apply(this, arguments);
|
||||
};
|
||||
|
||||
CommonJSInteropFormatter.prototype.exportSpecifier = function () {
|
||||
this.has = true;
|
||||
CommonJSFormatter.prototype.exportSpecifier.apply(this, arguments);
|
||||
};
|
||||
@@ -7,6 +7,33 @@ function CommonJSFormatter(file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
CommonJSFormatter.prototype.getModuleName = function () {
|
||||
var opts = this.file.opts;
|
||||
var filenameRelative = opts.filenameRelative;
|
||||
var moduleName = "";
|
||||
|
||||
if (opts.moduleRoot) {
|
||||
moduleName = opts.moduleRoot + "/";
|
||||
}
|
||||
|
||||
if (!opts.filenameRelative) {
|
||||
return moduleName + opts.filename.replace(/^\//, "");
|
||||
}
|
||||
|
||||
if (opts.sourceRoot) {
|
||||
// remove sourceRoot from filename
|
||||
var sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
|
||||
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
|
||||
}
|
||||
|
||||
// remove extension
|
||||
filenameRelative = filenameRelative.replace(/\.(.*?)$/, "");
|
||||
|
||||
moduleName += filenameRelative;
|
||||
|
||||
return moduleName;
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.import = function (node, nodes) {
|
||||
// import "foo";
|
||||
nodes.push(util.template("require", {
|
||||
@@ -38,23 +65,32 @@ CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes)
|
||||
}));
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype._hoistExport = function (declar, assign) {
|
||||
if (t.isFunctionDeclaration(declar)) {
|
||||
assign._blockHoist = true;
|
||||
}
|
||||
|
||||
return assign;
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype._pushStatement = function (ref, nodes) {
|
||||
if (t.isClass(ref) || t.isFunction(ref)) {
|
||||
if (ref.id) {
|
||||
nodes.push(t.toStatement(ref));
|
||||
ref = ref.id;
|
||||
}
|
||||
}
|
||||
return ref;
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.export = function (node, nodes) {
|
||||
var declar = node.declaration;
|
||||
|
||||
if (node.default) {
|
||||
var ref = declar;
|
||||
|
||||
if (t.isClass(ref) || t.isFunction(ref)) {
|
||||
if (ref.id) {
|
||||
nodes.push(t.toStatement(ref));
|
||||
ref = ref.id;
|
||||
}
|
||||
}
|
||||
|
||||
nodes.push(util.template("exports-default", {
|
||||
//inherits: node,
|
||||
|
||||
VALUE: ref
|
||||
VALUE: this._pushStatement(declar, nodes)
|
||||
}, true));
|
||||
} else {
|
||||
var assign;
|
||||
@@ -83,9 +119,7 @@ CommonJSFormatter.prototype.export = function (node, nodes) {
|
||||
nodes.push(t.toStatement(declar));
|
||||
nodes.push(assign);
|
||||
|
||||
if (t.isFunctionDeclaration(declar)) {
|
||||
assign._blockHoist = true;
|
||||
}
|
||||
this._hoistExport(declar, assign);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -126,7 +160,7 @@ CommonJSFormatter.prototype._exportSpecifier = function (getRef, specifier, node
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
|
||||
return this._exportSpecifier(function () {
|
||||
this._exportSpecifier(function () {
|
||||
return t.callExpression(t.identifier("require"), [node.source]);
|
||||
}, specifier, node, nodes);
|
||||
};
|
||||
|
||||
202
lib/6to5/transformation/modules/system.js
Normal file
202
lib/6to5/transformation/modules/system.js
Normal file
@@ -0,0 +1,202 @@
|
||||
module.exports = SystemFormatter;
|
||||
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
var SETTER_MODULE_NAMESPACE = t.identifier("m");
|
||||
var DEFAULT_IDENTIFIER = t.identifier("default");
|
||||
var NULL_SETTER = t.literal(null);
|
||||
|
||||
function SystemFormatter(file) {
|
||||
this.exportedStatements = [];
|
||||
this.importedModule = {};
|
||||
|
||||
this.exportIdentifier = file.generateUidIdentifier("export");
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
SystemFormatter.prototype.transform = function (ast) {
|
||||
var program = ast.program;
|
||||
var body = program.body;
|
||||
|
||||
// extract the module name
|
||||
var moduleName = this.file.opts.filename
|
||||
.replace(/^.*\//, "").replace(/\..*$/, "");
|
||||
|
||||
// build an array of module names
|
||||
var dependencies = Object.keys(this.importedModule).map(t.literal);
|
||||
|
||||
// generate the __moduleName variable
|
||||
var moduleNameVariableNode = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
t.identifier("__moduleName"),
|
||||
t.literal(moduleName)
|
||||
)
|
||||
]);
|
||||
body.splice(1, 0, moduleNameVariableNode);
|
||||
|
||||
// generate an array of import variables
|
||||
|
||||
var declaredSetters = _(this.importedModule)
|
||||
.map()
|
||||
.flatten()
|
||||
.pluck("variableName")
|
||||
.pluck("name")
|
||||
.uniq()
|
||||
.map(t.identifier)
|
||||
.map(function (name) {
|
||||
return t.variableDeclarator(name);
|
||||
})
|
||||
.value();
|
||||
|
||||
if (declaredSetters.length) {
|
||||
body.splice(2, 0, t.variableDeclaration("var", declaredSetters));
|
||||
}
|
||||
|
||||
// generate the execute function expression
|
||||
var executeFunctionExpression = t.functionExpression(
|
||||
null, [], t.blockStatement(this.exportedStatements)
|
||||
);
|
||||
|
||||
// generate the execute function expression
|
||||
var settersArrayExpression = t.arrayExpression(this._buildSetters());
|
||||
|
||||
// generate the return statement
|
||||
var moduleReturnStatement = t.returnStatement(t.objectExpression([
|
||||
t.property("init", t.identifier("setters"), settersArrayExpression),
|
||||
t.property("init", t.identifier("execute"), executeFunctionExpression)
|
||||
]));
|
||||
body.push(moduleReturnStatement);
|
||||
|
||||
// runner
|
||||
var runner = util.template("register", {
|
||||
MODULE_NAME: t.literal(moduleName),
|
||||
MODULE_DEPENDENCIES: t.arrayExpression(dependencies),
|
||||
MODULE_BODY: t.functionExpression(
|
||||
null,
|
||||
[this.exportIdentifier],
|
||||
t.blockStatement(body)
|
||||
)
|
||||
});
|
||||
|
||||
program.body = [t.expressionStatement(runner)];
|
||||
};
|
||||
|
||||
SystemFormatter.prototype._buildSetters = function () {
|
||||
// generate setters array expression elements
|
||||
return _.map(this.importedModule, function (specs) {
|
||||
if (!specs.length) {
|
||||
return NULL_SETTER;
|
||||
}
|
||||
|
||||
var expressionStatements = _.map(specs, function (spec) {
|
||||
var right = SETTER_MODULE_NAMESPACE;
|
||||
if (!spec.isBatch) {
|
||||
right = t.memberExpression(right, spec.key);
|
||||
}
|
||||
|
||||
return t.expressionStatement(
|
||||
t.assignmentExpression("=", spec.variableName, right
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return t.functionExpression(
|
||||
null, [SETTER_MODULE_NAMESPACE], t.blockStatement(expressionStatements)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.import = function (node) {
|
||||
var MODULE_NAME = node.source.value;
|
||||
this.importedModule[MODULE_NAME] = this.importedModule[MODULE_NAME] || [];
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.importSpecifier = function (specifier, node) {
|
||||
var variableName = t.getSpecifierName(specifier);
|
||||
|
||||
// import foo from "foo";
|
||||
if (specifier.default) {
|
||||
specifier.id = DEFAULT_IDENTIFIER;
|
||||
}
|
||||
|
||||
var MODULE_NAME = node.source.value;
|
||||
|
||||
this.importedModule[MODULE_NAME] = this.importedModule[MODULE_NAME] || [];
|
||||
|
||||
this.importedModule[MODULE_NAME].push({
|
||||
variableName: variableName,
|
||||
isBatch: specifier.type === "ImportBatchSpecifier",
|
||||
key: specifier.id
|
||||
});
|
||||
};
|
||||
|
||||
SystemFormatter.prototype._export = function (name, identifier) {
|
||||
this.exportedStatements.push(t.expressionStatement(
|
||||
t.callExpression(this.exportIdentifier, [t.literal(name), identifier])
|
||||
));
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.export = function (node, nodes) {
|
||||
var declar = node.declaration;
|
||||
var variableName, identifier;
|
||||
|
||||
if (node.default) {
|
||||
// export default foo
|
||||
variableName = DEFAULT_IDENTIFIER.name;
|
||||
if (t.isClass(declar) || t.isFunction(declar)) {
|
||||
if (!declar.id) {
|
||||
declar.id = this.file.generateUidIdentifier("anonymous");
|
||||
}
|
||||
|
||||
nodes.push(t.toStatement(declar));
|
||||
declar = declar.id;
|
||||
}
|
||||
|
||||
identifier = declar;
|
||||
} else if (t.isVariableDeclaration(declar)) {
|
||||
// export var foo
|
||||
variableName = declar.declarations[0].id.name;
|
||||
identifier = declar.declarations[0].id;
|
||||
|
||||
nodes.push(declar);
|
||||
} else {
|
||||
// export function foo () {}
|
||||
variableName = declar.id.name;
|
||||
identifier = declar.id;
|
||||
|
||||
nodes.push(declar);
|
||||
}
|
||||
|
||||
this._export(variableName, identifier);
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.exportSpecifier = function (specifier, node) {
|
||||
var variableName = t.getSpecifierName(specifier);
|
||||
|
||||
if (node.source) {
|
||||
if (t.isExportBatchSpecifier(specifier)) {
|
||||
// export * from "foo";
|
||||
var exportIdentifier = t.identifier("exports");
|
||||
this.exportedStatements.push(
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(exportIdentifier, this.exportIdentifier)
|
||||
])
|
||||
);
|
||||
|
||||
this.exportedStatements.push(util.template("exports-wildcard", {
|
||||
OBJECT: t.identifier(node.source.value)
|
||||
}, true));
|
||||
} else {
|
||||
// export { foo } from "test";
|
||||
this._export(variableName.name, t.memberExpression(
|
||||
t.identifier(node.source.value),
|
||||
specifier.id
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// export { foo };
|
||||
this._export(variableName.name, specifier.id);
|
||||
}
|
||||
};
|
||||
@@ -5,9 +5,8 @@ var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
function UMDFormatter(file) {
|
||||
this.file = file;
|
||||
this.ids = {};
|
||||
function UMDFormatter() {
|
||||
AMDFormatter.apply(this, arguments);
|
||||
}
|
||||
|
||||
util.inherits(UMDFormatter, AMDFormatter);
|
||||
@@ -32,8 +31,12 @@ UMDFormatter.prototype.transform = function (ast) {
|
||||
|
||||
// runner
|
||||
|
||||
var defineArgs = [t.arrayExpression([t.literal("exports")].concat(names))];
|
||||
var moduleName = this.getModuleName();
|
||||
if (moduleName) defineArgs.unshift(t.literal(moduleName));
|
||||
|
||||
var runner = util.template("umd-runner-body", {
|
||||
AMD_ARGUMENTS: t.arrayExpression([t.literal("exports")].concat(names)),
|
||||
AMD_ARGUMENTS: defineArgs,
|
||||
|
||||
COMMON_ARGUMENTS: names.map(function (name) {
|
||||
return t.callExpression(t.identifier("require"), [name]);
|
||||
|
||||
@@ -20,44 +20,51 @@ transform._ensureTransformerNames = function (type, keys) {
|
||||
transform.transformers = {};
|
||||
|
||||
transform.moduleFormatters = {
|
||||
common: require("./modules/common"),
|
||||
ignore: require("./modules/ignore"),
|
||||
amd: require("./modules/amd"),
|
||||
umd: require("./modules/umd")
|
||||
common: require("./modules/common"),
|
||||
commonInterop: require("./modules/common-interop"),
|
||||
system: require("./modules/system"),
|
||||
ignore: require("./modules/ignore"),
|
||||
amd: require("./modules/amd"),
|
||||
umd: require("./modules/umd")
|
||||
};
|
||||
|
||||
_.each({
|
||||
modules: require("./transformers/modules"),
|
||||
propertyNameShorthand: require("./transformers/property-name-shorthand"),
|
||||
constants: require("./transformers/constants"),
|
||||
arrayComprehension: require("./transformers/array-comprehension"),
|
||||
generatorComprehension: require("./transformers/generator-comprehension"),
|
||||
arrowFunctions: require("./transformers/arrow-functions"),
|
||||
classes: require("./transformers/classes"),
|
||||
modules: require("./transformers/es6-modules"),
|
||||
propertyNameShorthand: require("./transformers/es6-property-name-shorthand"),
|
||||
arrayComprehension: require("./transformers/es7-array-comprehension"),
|
||||
generatorComprehension: require("./transformers/es7-generator-comprehension"),
|
||||
arrowFunctions: require("./transformers/es6-arrow-functions"),
|
||||
classes: require("./transformers/es6-classes"),
|
||||
|
||||
_propertyLiterals: require("./transformers/_property-literals"),
|
||||
computedPropertyNames: require("./transformers/computed-property-names"),
|
||||
_propertyLiterals: require("./transformers/_property-literals"),
|
||||
computedPropertyNames: require("./transformers/es6-computed-property-names"),
|
||||
|
||||
spread: require("./transformers/spread"),
|
||||
templateLiterals: require("./transformers/template-literals"),
|
||||
propertyMethodAssignment: require("./transformers/property-method-assignment"),
|
||||
defaultParameters: require("./transformers/default-parameters"),
|
||||
restParameters: require("./transformers/rest-parameters"),
|
||||
destructuring: require("./transformers/destructuring"),
|
||||
letScoping: require("./transformers/let-scoping"),
|
||||
forOf: require("./transformers/for-of"),
|
||||
unicodeRegex: require("./transformers/unicode-regex"),
|
||||
objectSpread: require("./transformers/es7-object-spread"),
|
||||
exponentiationOperator: require("./transformers/es7-exponentiation-operator"),
|
||||
spread: require("./transformers/es6-spread"),
|
||||
templateLiterals: require("./transformers/es6-template-literals"),
|
||||
propertyMethodAssignment: require("./transformers/es5-property-method-assignment"),
|
||||
defaultParameters: require("./transformers/es6-default-parameters"),
|
||||
restParameters: require("./transformers/es6-rest-parameters"),
|
||||
destructuring: require("./transformers/es6-destructuring"),
|
||||
forOf: require("./transformers/es6-for-of"),
|
||||
unicodeRegex: require("./transformers/es6-unicode-regex"),
|
||||
abstractReferences: require("./transformers/es7-abstract-references"),
|
||||
react: require("./transformers/react"),
|
||||
|
||||
react: require("./transformers/react"),
|
||||
constants: require("./transformers/es6-constants"),
|
||||
letScoping: require("./transformers/es6-let-scoping"),
|
||||
|
||||
_aliasFunctions: require("./transformers/_alias-functions"),
|
||||
_blockHoist: require("./transformers/_block-hoist"),
|
||||
_declarations: require("./transformers/_declarations"),
|
||||
generators: require("./transformers/es6-generators"),
|
||||
|
||||
generators: require("./transformers/generators"),
|
||||
useStrict: require("./transformers/use-strict"),
|
||||
_blockHoist: require("./transformers/_block-hoist"),
|
||||
_declarations: require("./transformers/_declarations"),
|
||||
_aliasFunctions: require("./transformers/_alias-functions"),
|
||||
|
||||
_moduleFormatter: require("./transformers/_module-formatter")
|
||||
useStrict: require("./transformers/use-strict"),
|
||||
|
||||
_memberExpressionKeywords: require("./transformers/_member-expression-keywords"),
|
||||
_moduleFormatter: require("./transformers/_module-formatter")
|
||||
}, function (transformer, key) {
|
||||
transform.transformers[key] = new Transformer(key, transformer);
|
||||
});
|
||||
|
||||
@@ -6,11 +6,11 @@ var go = function (getBody, node, file, scope) {
|
||||
var thisId;
|
||||
|
||||
var getArgumentsId = function () {
|
||||
return argumentsId = argumentsId || t.identifier(file.generateUid("arguments", scope));
|
||||
return argumentsId = argumentsId || file.generateUidIdentifier("arguments", scope);
|
||||
};
|
||||
|
||||
var getThisId = function () {
|
||||
return thisId = thisId || t.identifier(file.generateUid("this", scope));
|
||||
return thisId = thisId || file.generateUidIdentifier("this", scope);
|
||||
};
|
||||
|
||||
// traverse the function and find all alias functions so we can alias
|
||||
@@ -31,7 +31,7 @@ var go = function (getBody, node, file, scope) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node._ignoreAliasFunctions) return;
|
||||
if (node._ignoreAliasFunctions) return false;
|
||||
|
||||
var getId;
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
module.exports = function (ast, file) {
|
||||
var body = ast.program.body;
|
||||
|
||||
_.each(file.declarations, function (declar) {
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(declar.uid, declar.node)
|
||||
exports.BlockStatement =
|
||||
exports.Program = function (node) {
|
||||
_.each(node._declarations, function (declar) {
|
||||
node.body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(declar.id, declar.init)
|
||||
]));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
var esutils = require("esutils");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.MemberExpression = function (node) {
|
||||
var prop = node.property;
|
||||
if (t.isIdentifier(prop) && esutils.keyword.isKeywordES6(prop.name, true)) {
|
||||
node.property = t.literal(prop.name);
|
||||
node.computed = true;
|
||||
}
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
var traverse = require("../../traverse");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.Program =
|
||||
exports.BlockStatement =
|
||||
exports.ForInStatement =
|
||||
exports.ForOfStatement =
|
||||
exports.ForStatement = function (node, parent, file) {
|
||||
var constants = [];
|
||||
|
||||
var check = function (node, names) {
|
||||
_.each(names, function (name) {
|
||||
if (constants.indexOf(name) >= 0) {
|
||||
throw file.errorWithNode(node, name + " is read-only");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var getIds = function (node) {
|
||||
return t.getIds(node, false, ["MemberExpression"]);
|
||||
};
|
||||
|
||||
_.each(node.body, function (child) {
|
||||
if (child && t.isVariableDeclaration(child, { kind: "const" })) {
|
||||
_.each(child.declarations, function (declar) {
|
||||
_.each(getIds(declar), function (name) {
|
||||
check(declar, [name]);
|
||||
constants.push(name);
|
||||
});
|
||||
|
||||
declar._ignoreConstant = true;
|
||||
});
|
||||
|
||||
child._ignoreConstant = true;
|
||||
child.kind = "let";
|
||||
}
|
||||
});
|
||||
|
||||
if (!constants.length) return;
|
||||
|
||||
traverse(node, function (child) {
|
||||
if (child._ignoreConstant) return;
|
||||
|
||||
if (t.isVariableDeclarator(child) || t.isDeclaration(child) || t.isAssignmentExpression(child)) {
|
||||
check(child, getIds(child));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.Function = function (node) {
|
||||
if (!node.defaults || !node.defaults.length) return;
|
||||
t.ensureBlock(node);
|
||||
|
||||
_.each(node.defaults, function (def, i) {
|
||||
if (!def) return;
|
||||
|
||||
var param = node.params[i];
|
||||
|
||||
node.body.body.unshift(util.template("if-undefined-set-to", {
|
||||
VARIABLE: param,
|
||||
DEFAULT: def
|
||||
}, true));
|
||||
});
|
||||
|
||||
node.defaults = [];
|
||||
};
|
||||
@@ -4,7 +4,7 @@ var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.ClassDeclaration = function (node, parent, file, scope) {
|
||||
return t.variableDeclaration("var", [
|
||||
return t.variableDeclaration("let", [
|
||||
t.variableDeclarator(node.id, new Class(node, file, scope).run())
|
||||
]);
|
||||
};
|
||||
@@ -36,7 +36,7 @@ function Class(node, file, scope) {
|
||||
this.instanceMutatorMap = {};
|
||||
this.staticMutatorMap = {};
|
||||
this.hasConstructor = false;
|
||||
this.className = node.id || t.identifier(file.generateUid("class", scope));
|
||||
this.className = node.id || file.generateUidIdentifier("class", scope);
|
||||
this.superName = node.superClass;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ Class.prototype.run = function () {
|
||||
superClassArgument = superClassCallee = getMemberExpressionObject(superName);
|
||||
} else if (!t.isIdentifier(superName)) {
|
||||
superClassArgument = superName;
|
||||
superClassCallee = superName = t.identifier(file.generateUid("ref", this.scope));
|
||||
superClassCallee = superName = file.generateUidIdentifier("ref", this.scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +254,7 @@ Class.prototype.pushConstructor = function (method) {
|
||||
|
||||
this.hasConstructor = true;
|
||||
t.inherits(construct, fn);
|
||||
t.inheritsComments(construct, method);
|
||||
|
||||
construct.defaults = fn.defaults;
|
||||
construct.params = fn.params;
|
||||
54
lib/6to5/transformation/transformers/es6-constants.js
Normal file
54
lib/6to5/transformation/transformers/es6-constants.js
Normal file
@@ -0,0 +1,54 @@
|
||||
var traverse = require("../../traverse");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.Program =
|
||||
exports.BlockStatement =
|
||||
exports.ForInStatement =
|
||||
exports.ForOfStatement =
|
||||
exports.ForStatement = function (node, parent, file) {
|
||||
var constants = {};
|
||||
|
||||
var check = function (parent, names) {
|
||||
_.each(names, function (nameNode, name) {
|
||||
if (!_.has(constants, name)) return;
|
||||
if (parent && t.isBlockStatement(parent) && parent !== constants[name]) return;
|
||||
|
||||
throw file.errorWithNode(nameNode, name + " is read-only");
|
||||
});
|
||||
};
|
||||
|
||||
var getIds = function (node) {
|
||||
return t.getIds(node, true, ["MemberExpression"]);
|
||||
};
|
||||
|
||||
_.each(node.body, function (child, parent) {
|
||||
if (child && t.isVariableDeclaration(child, { kind: "const" })) {
|
||||
_.each(child.declarations, function (declar) {
|
||||
_.each(getIds(declar), function (nameNode, name) {
|
||||
var names = {};
|
||||
names[name] = nameNode;
|
||||
check(parent, names);
|
||||
|
||||
constants[name] = parent;
|
||||
});
|
||||
|
||||
declar._ignoreConstant = true;
|
||||
});
|
||||
|
||||
child._ignoreConstant = true;
|
||||
child.kind = "let";
|
||||
}
|
||||
});
|
||||
|
||||
if (_.isEmpty(constants)) return;
|
||||
|
||||
traverse(node, function (child, parent) {
|
||||
if (child._ignoreConstant) return;
|
||||
if (t.isVariableDeclaration(child)) return;
|
||||
|
||||
if (t.isVariableDeclarator(child) || t.isDeclaration(child) || t.isAssignmentExpression(child)) {
|
||||
check(parent, getIds(child));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
var traverse = require("../../traverse");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.Function = function (node, parent, file, scope) {
|
||||
if (!node.defaults || !node.defaults.length) return;
|
||||
t.ensureBlock(node);
|
||||
|
||||
var ids = node.params.map(function (param) {
|
||||
return t.getIds(param);
|
||||
});
|
||||
|
||||
var closure = false;
|
||||
|
||||
_.each(node.defaults, function (def, i) {
|
||||
if (!def) return;
|
||||
|
||||
var param = node.params[i];
|
||||
|
||||
// temporal dead zone check - here we prevent accessing of params that
|
||||
// are to the right - ie. uninitialized parameters
|
||||
_.each(ids.slice(i), function (ids) {
|
||||
var check = function (node, parent) {
|
||||
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
|
||||
|
||||
if (_.contains(ids, node.name)) {
|
||||
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
|
||||
}
|
||||
|
||||
if (scope.has(node.name)) {
|
||||
closure = true;
|
||||
}
|
||||
};
|
||||
|
||||
check(def, node);
|
||||
traverse(def, check);
|
||||
});
|
||||
|
||||
// we're accessing a variable that's already defined within this function
|
||||
var has = scope.get(param.name);
|
||||
if (has && !_.contains(node.params, has)) {
|
||||
closure = true;
|
||||
}
|
||||
});
|
||||
|
||||
var body = [];
|
||||
|
||||
_.each(node.defaults, function (def, i) {
|
||||
if (!def) return;
|
||||
|
||||
body.push(util.template("if-undefined-set-to", {
|
||||
VARIABLE: node.params[i],
|
||||
DEFAULT: def
|
||||
}, true));
|
||||
});
|
||||
|
||||
if (closure) {
|
||||
var container = t.functionExpression(null, [], node.body, node.generator);
|
||||
container._aliasFunction = true;
|
||||
|
||||
body.push(t.returnStatement(t.callExpression(container, [])));
|
||||
|
||||
node.body = t.blockStatement(body);
|
||||
} else {
|
||||
node.body.body = body.concat(node.body.body);
|
||||
}
|
||||
|
||||
node.defaults = [];
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
// TODO: Clean up
|
||||
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
@@ -11,50 +13,79 @@ var buildVariableAssign = function (kind, id, init) {
|
||||
}
|
||||
};
|
||||
|
||||
var push = function (kind, nodes, elem, parentId) {
|
||||
var push = function (opts, nodes, elem, parentId) {
|
||||
if (t.isObjectPattern(elem)) {
|
||||
pushObjectPattern(kind, nodes, elem, parentId);
|
||||
pushObjectPattern(opts, nodes, elem, parentId);
|
||||
} else if (t.isArrayPattern(elem)) {
|
||||
pushArrayPattern(kind, nodes, elem, parentId);
|
||||
pushArrayPattern(opts, nodes, elem, parentId);
|
||||
} else if (t.isMemberExpression(elem)) {
|
||||
nodes.push(buildVariableAssign(false, elem, parentId));
|
||||
} else {
|
||||
nodes.push(buildVariableAssign(kind, elem, parentId));
|
||||
nodes.push(buildVariableAssign(opts.kind, elem, parentId));
|
||||
}
|
||||
};
|
||||
|
||||
var pushObjectPattern = function (kind, nodes, pattern, parentId) {
|
||||
_.each(pattern.properties, function (prop) {
|
||||
var pattern2 = prop.value;
|
||||
var patternId2 = t.memberExpression(parentId, prop.key);
|
||||
var pushObjectPattern = function (opts, nodes, pattern, parentId) {
|
||||
_.each(pattern.properties, function (prop, i) {
|
||||
if (t.isSpreadProperty(prop)) {
|
||||
// get all the keys that appear in this object before the current spread
|
||||
var keys = [];
|
||||
_.each(pattern.properties, function (prop2, i2) {
|
||||
if (i2 >= i) return false;
|
||||
if (t.isSpreadProperty(prop2)) return;
|
||||
|
||||
if (t.isPattern(pattern2)) {
|
||||
push(kind, nodes, pattern2, patternId2);
|
||||
var key = prop2.key;
|
||||
if (t.isIdentifier(key)) {
|
||||
key = t.literal(prop2.key.name);
|
||||
}
|
||||
keys.push(key);
|
||||
});
|
||||
keys = t.arrayExpression(keys);
|
||||
|
||||
var value = t.callExpression(opts.file.addDeclaration("object-spread"), [parentId, keys]);
|
||||
nodes.push(buildVariableAssign(opts.kind, prop.argument, value));
|
||||
} else {
|
||||
nodes.push(buildVariableAssign(kind, pattern2, patternId2));
|
||||
var pattern2 = prop.value;
|
||||
var patternId2 = t.memberExpression(parentId, prop.key, prop.computed);
|
||||
|
||||
if (t.isPattern(pattern2)) {
|
||||
push(opts, nodes, pattern2, patternId2);
|
||||
} else {
|
||||
nodes.push(buildVariableAssign(opts.kind, pattern2, patternId2));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var pushArrayPattern = function (kind, nodes, pattern, parentId) {
|
||||
var pushArrayPattern = function (opts, nodes, pattern, parentId) {
|
||||
var _parentId = opts.file.generateUidIdentifier("ref", opts.scope);
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(_parentId, opts.file.toArray(parentId))
|
||||
]));
|
||||
parentId = _parentId;
|
||||
|
||||
_.each(pattern.elements, function (elem, i) {
|
||||
if (!elem) return;
|
||||
|
||||
var newPatternId;
|
||||
|
||||
if (t.isSpreadElement(elem)) {
|
||||
newPatternId = t.callExpression(t.memberExpression(parentId, t.identifier("slice")), [t.literal(i)]);
|
||||
newPatternId = opts.file.toArray(parentId);
|
||||
|
||||
if (+i > 0) {
|
||||
newPatternId = t.callExpression(t.memberExpression(newPatternId, t.identifier("slice")), [t.literal(i)]);
|
||||
}
|
||||
|
||||
elem = elem.argument;
|
||||
} else {
|
||||
newPatternId = t.memberExpression(parentId, t.literal(i), true);
|
||||
}
|
||||
|
||||
push(kind, nodes, elem, newPatternId);
|
||||
push(opts, nodes, elem, newPatternId);
|
||||
});
|
||||
};
|
||||
|
||||
var pushPattern = function (opts) {
|
||||
var kind = opts.kind;
|
||||
var nodes = opts.nodes;
|
||||
var pattern = opts.pattern;
|
||||
var parentId = opts.id;
|
||||
@@ -62,7 +93,7 @@ var pushPattern = function (opts) {
|
||||
var scope = opts.scope;
|
||||
|
||||
if (!t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) {
|
||||
var key = t.identifier(file.generateUid("ref", scope));
|
||||
var key = file.generateUidIdentifier("ref", scope);
|
||||
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(key, parentId)
|
||||
@@ -71,7 +102,7 @@ var pushPattern = function (opts) {
|
||||
parentId = key;
|
||||
}
|
||||
|
||||
push(kind, nodes, pattern, parentId);
|
||||
push(opts, nodes, pattern, parentId);
|
||||
};
|
||||
|
||||
exports.ForInStatement =
|
||||
@@ -82,14 +113,18 @@ exports.ForOfStatement = function (node, parent, file, scope) {
|
||||
var pattern = declar.declarations[0].id;
|
||||
if (!t.isPattern(pattern)) return;
|
||||
|
||||
var key = t.identifier(file.generateUid("ref", scope));
|
||||
var key = file.generateUidIdentifier("ref", scope);
|
||||
node.left = t.variableDeclaration(declar.kind, [
|
||||
t.variableDeclarator(key, null)
|
||||
]);
|
||||
|
||||
var nodes = [];
|
||||
|
||||
push(declar.kind, nodes, pattern, key);
|
||||
push({
|
||||
kind: declar.kind,
|
||||
file: file,
|
||||
scope: scope
|
||||
}, nodes, pattern, key);
|
||||
|
||||
t.ensureBlock(node);
|
||||
|
||||
@@ -106,7 +141,7 @@ exports.Function = function (node, parent, file, scope) {
|
||||
if (!t.isPattern(pattern)) return pattern;
|
||||
|
||||
hasDestructuring = true;
|
||||
var parentId = t.identifier(file.generateUid("ref", scope));
|
||||
var parentId = file.generateUidIdentifier("ref", scope);
|
||||
|
||||
pushPattern({
|
||||
kind: "var",
|
||||
@@ -136,20 +171,52 @@ exports.ExpressionStatement = function (node, parent, file, scope) {
|
||||
|
||||
var nodes = [];
|
||||
|
||||
var ref = t.identifier(file.generateUid("ref", scope));
|
||||
var ref = file.generateUidIdentifier("ref", scope);
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(ref, expr.right)
|
||||
]));
|
||||
|
||||
push(false, nodes, expr.left, ref);
|
||||
push({
|
||||
kind: false,
|
||||
file: file,
|
||||
scope: scope
|
||||
}, nodes, expr.left, ref);
|
||||
|
||||
return nodes;
|
||||
};
|
||||
|
||||
exports.AssignmentExpression = function (node, parent, file) {
|
||||
exports.AssignmentExpression = function (node, parent, file, scope) {
|
||||
if (parent.type === "ExpressionStatement") return;
|
||||
if (!t.isPattern(node.left)) return;
|
||||
throw file.errorWithNode(node, "AssignmentExpression destructuring outside of a ExpressionStatement is forbidden due to current 6to5 limitations");
|
||||
|
||||
var tempName = file.generateUid("temp", scope);
|
||||
var temp = t.identifier(tempName);
|
||||
scope.push(tempName, temp);
|
||||
|
||||
var nodes = [];
|
||||
nodes.push(t.assignmentExpression("=", temp, node.right));
|
||||
|
||||
push({
|
||||
kind: false,
|
||||
file: file,
|
||||
scope: scope
|
||||
}, nodes, node.left, temp);
|
||||
|
||||
nodes.push(temp);
|
||||
|
||||
nodes = nodes.map(function (node) {
|
||||
if (t.isExpressionStatement(node)) {
|
||||
return node.expression;
|
||||
} else if (t.isVariableDeclaration(node)) {
|
||||
var declar = node.declarations[0];
|
||||
scope.push(declar.id.name, declar.id);
|
||||
return t.assignmentExpression("=", declar.id, declar.init);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
});
|
||||
|
||||
return t.sequenceExpression(nodes);
|
||||
};
|
||||
|
||||
exports.VariableDeclaration = function (node, parent, file, scope) {
|
||||
@@ -5,7 +5,7 @@ exports.ForOfStatement = function (node, parent, file, scope) {
|
||||
var left = node.left;
|
||||
var declar;
|
||||
|
||||
var stepKey = t.identifier(file.generateUid("step", scope));
|
||||
var stepKey = file.generateUidIdentifier("step", scope);
|
||||
var stepValue = t.memberExpression(stepKey, t.identifier("value"));
|
||||
|
||||
if (t.isIdentifier(left)) {
|
||||
@@ -19,7 +19,7 @@ exports.ForOfStatement = function (node, parent, file, scope) {
|
||||
}
|
||||
|
||||
var node2 = util.template("for-of", {
|
||||
ITERATOR_KEY: file.generateUid("iterator", scope),
|
||||
ITERATOR_KEY: file.generateUidIdentifier("iterator", scope),
|
||||
STEP_KEY: stepKey,
|
||||
OBJECT: node.right
|
||||
});
|
||||
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* 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 loc = require("../util").loc;
|
||||
var t = require("../../../../types");
|
||||
|
||||
exports.ParenthesizedExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(this.explodeExpression(path.get("expression")));
|
||||
};
|
||||
|
||||
exports.MemberExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.memberExpression(
|
||||
this.explodeExpression(path.get("object")),
|
||||
expr.computed ? explodeViaTempVar(null, path.get("property")) : expr.property,
|
||||
expr.computed
|
||||
));
|
||||
};
|
||||
|
||||
exports.CallExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
var oldCalleePath = path.get("callee");
|
||||
var newCallee = this.explodeExpression(oldCalleePath);
|
||||
|
||||
// If the callee was not previously a MemberExpression, then the
|
||||
// CallExpression was "unqualified," meaning its `this` object should
|
||||
// be the global object. If the exploded expression has become a
|
||||
// MemberExpression, then we need to force it to be unqualified by
|
||||
// using the (0, object.property)(...) trick; otherwise, it will
|
||||
// receive the object of the MemberExpression as its `this` object.
|
||||
if (!t.isMemberExpression(oldCalleePath.node) && t.isMemberExpression(newCallee)) {
|
||||
newCallee = t.sequenceExpression([
|
||||
t.literal(0),
|
||||
newCallee
|
||||
]);
|
||||
}
|
||||
|
||||
return finish(t.callExpression(
|
||||
newCallee,
|
||||
path.get("arguments").map(function (argPath) {
|
||||
return explodeViaTempVar(null, argPath);
|
||||
})
|
||||
));
|
||||
};
|
||||
|
||||
exports.NewExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.newExpression(
|
||||
explodeViaTempVar(null, path.get("callee")),
|
||||
path.get("arguments").map(function (argPath) {
|
||||
return explodeViaTempVar(null, argPath);
|
||||
})
|
||||
));
|
||||
};
|
||||
|
||||
exports.ObjectExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.objectExpression(
|
||||
path.get("properties").map(function (propPath) {
|
||||
return t.property(
|
||||
propPath.value.kind,
|
||||
propPath.value.key,
|
||||
explodeViaTempVar(null, propPath.get("value"))
|
||||
);
|
||||
})
|
||||
));
|
||||
};
|
||||
|
||||
exports.ArrayExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.arrayExpression(
|
||||
path.get("elements").map(function (elemPath) {
|
||||
return explodeViaTempVar(null, elemPath);
|
||||
})
|
||||
));
|
||||
};
|
||||
|
||||
exports.SequenceExpression = function (expr, path, explodeViaTempVar, finish, ignoreResult) {
|
||||
var lastIndex = expr.expressions.length - 1;
|
||||
var self = this;
|
||||
var result;
|
||||
|
||||
path.get("expressions").each(function (exprPath) {
|
||||
if (exprPath.name === lastIndex) {
|
||||
result = self.explodeExpression(exprPath, ignoreResult);
|
||||
} else {
|
||||
self.explodeExpression(exprPath, true);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.LogicalExpression = function (expr, path, explodeViaTempVar, finish, ignoreResult) {
|
||||
var after = loc();
|
||||
var result;
|
||||
|
||||
if (!ignoreResult) {
|
||||
result = this.makeTempVar();
|
||||
}
|
||||
|
||||
var left = explodeViaTempVar(result, path.get("left"));
|
||||
|
||||
if (expr.operator === "&&") {
|
||||
this.jumpIfNot(left, after);
|
||||
} else {
|
||||
assert.strictEqual(expr.operator, "||");
|
||||
this.jumpIf(left, after);
|
||||
}
|
||||
|
||||
explodeViaTempVar(result, path.get("right"), ignoreResult);
|
||||
|
||||
this.mark(after);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.ConditionalExpression = function (expr, path, explodeViaTempVar, finish, ignoreResult) {
|
||||
var elseLoc = loc();
|
||||
var after = loc();
|
||||
var test = this.explodeExpression(path.get("test"));
|
||||
var result;
|
||||
|
||||
this.jumpIfNot(test, elseLoc);
|
||||
|
||||
if (!ignoreResult) {
|
||||
result = this.makeTempVar();
|
||||
}
|
||||
|
||||
explodeViaTempVar(result, path.get("consequent"), ignoreResult);
|
||||
this.jump(after);
|
||||
|
||||
this.mark(elseLoc);
|
||||
explodeViaTempVar(result, path.get("alternate"), ignoreResult);
|
||||
|
||||
this.mark(after);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
exports.UnaryExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.unaryExpression(
|
||||
expr.operator,
|
||||
// Can't (and don't need to) break up the syntax of the argument.
|
||||
// Think about delete a[b].
|
||||
this.explodeExpression(path.get("argument")),
|
||||
!!expr.prefix
|
||||
));
|
||||
};
|
||||
|
||||
exports.BinaryExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.binaryExpression(
|
||||
expr.operator,
|
||||
explodeViaTempVar(null, path.get("left")),
|
||||
explodeViaTempVar(null, path.get("right"))
|
||||
));
|
||||
};
|
||||
|
||||
exports.AssignmentExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.assignmentExpression(
|
||||
expr.operator,
|
||||
this.explodeExpression(path.get("left")),
|
||||
this.explodeExpression(path.get("right"))
|
||||
));
|
||||
};
|
||||
|
||||
exports.UpdateExpression = function (expr, path, explodeViaTempVar, finish) {
|
||||
return finish(t.updateExpression(
|
||||
expr.operator,
|
||||
this.explodeExpression(path.get("argument")),
|
||||
expr.prefix
|
||||
));
|
||||
};
|
||||
|
||||
exports.YieldExpression = function (expr, path) {
|
||||
var after = loc();
|
||||
var arg = expr.argument && this.explodeExpression(path.get("argument"));
|
||||
var result;
|
||||
|
||||
if (arg && expr.delegate) {
|
||||
result = this.makeTempVar();
|
||||
|
||||
this.emit(t.returnStatement(t.callExpression(
|
||||
this.contextProperty("delegateYield"), [
|
||||
arg,
|
||||
t.literal(result.property.name),
|
||||
after
|
||||
]
|
||||
)));
|
||||
|
||||
this.mark(after);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
this.emitAssign(this.contextProperty("next"), after);
|
||||
this.emit(t.returnStatement(arg || null));
|
||||
this.mark(after);
|
||||
|
||||
return this.contextProperty("sent");
|
||||
};
|
||||
@@ -0,0 +1,334 @@
|
||||
/**
|
||||
* 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 leap = require("../leap");
|
||||
var util = require("../util");
|
||||
var t = require("../../../../types");
|
||||
|
||||
var runtimeKeysMethod = util.runtimeProperty("keys");
|
||||
var loc = util.loc;
|
||||
|
||||
exports.ExpressionStatement = function (path) {
|
||||
this.explodeExpression(path.get("expression"), true);
|
||||
};
|
||||
|
||||
exports.LabeledStatement = function (path, stmt) {
|
||||
this.explodeStatement(path.get("body"), stmt.label);
|
||||
};
|
||||
|
||||
exports.WhileStatement = function (path, stmt, labelId) {
|
||||
var before = loc();
|
||||
var after = loc();
|
||||
|
||||
this.mark(before);
|
||||
this.jumpIfNot(this.explodeExpression(path.get("test")), after);
|
||||
this.leapManager.withEntry(
|
||||
new leap.LoopEntry(after, before, labelId),
|
||||
function () { this.explodeStatement(path.get("body")); }
|
||||
);
|
||||
this.jump(before);
|
||||
this.mark(after);
|
||||
};
|
||||
|
||||
exports.DoWhileStatement = function (path, stmt, labelId) {
|
||||
var first = loc();
|
||||
var test = loc();
|
||||
var after = loc();
|
||||
|
||||
this.mark(first);
|
||||
this.leapManager.withEntry(
|
||||
new leap.LoopEntry(after, test, labelId),
|
||||
function () { this.explode(path.get("body")); }
|
||||
);
|
||||
this.mark(test);
|
||||
this.jumpIf(this.explodeExpression(path.get("test")), first);
|
||||
this.mark(after);
|
||||
};
|
||||
|
||||
exports.ForStatement = function (path, stmt, labelId) {
|
||||
var head = loc();
|
||||
var update = loc();
|
||||
var after = loc();
|
||||
|
||||
if (stmt.init) {
|
||||
// We pass true here to indicate that if stmt.init is an expression
|
||||
// then we do not care about its result.
|
||||
this.explode(path.get("init"), true);
|
||||
}
|
||||
|
||||
this.mark(head);
|
||||
|
||||
if (stmt.test) {
|
||||
this.jumpIfNot(this.explodeExpression(path.get("test")), after);
|
||||
} else {
|
||||
// No test means continue unconditionally.
|
||||
}
|
||||
|
||||
this.leapManager.withEntry(
|
||||
new leap.LoopEntry(after, update, labelId),
|
||||
function () { this.explodeStatement(path.get("body")); }
|
||||
);
|
||||
|
||||
this.mark(update);
|
||||
|
||||
if (stmt.update) {
|
||||
// We pass true here to indicate that if stmt.update is an
|
||||
// expression then we do not care about its result.
|
||||
this.explode(path.get("update"), true);
|
||||
}
|
||||
|
||||
this.jump(head);
|
||||
|
||||
this.mark(after);
|
||||
};
|
||||
|
||||
exports.ForInStatement = function (path, stmt, labelId) {
|
||||
t.assertIdentifier(stmt.left);
|
||||
|
||||
var head = loc();
|
||||
var after = loc();
|
||||
|
||||
var keyIterNextFn = this.makeTempVar();
|
||||
this.emitAssign(
|
||||
keyIterNextFn,
|
||||
t.callExpression(
|
||||
runtimeKeysMethod,
|
||||
[this.explodeExpression(path.get("right"))]
|
||||
)
|
||||
);
|
||||
|
||||
this.mark(head);
|
||||
|
||||
var keyInfoTmpVar = this.makeTempVar();
|
||||
this.jumpIf(
|
||||
t.memberExpression(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
keyInfoTmpVar,
|
||||
t.callExpression(keyIterNextFn, [])
|
||||
),
|
||||
t.identifier("done"),
|
||||
false
|
||||
),
|
||||
after
|
||||
);
|
||||
|
||||
this.emitAssign(
|
||||
stmt.left,
|
||||
t.memberExpression(
|
||||
keyInfoTmpVar,
|
||||
t.identifier("value"),
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
this.leapManager.withEntry(
|
||||
new leap.LoopEntry(after, head, labelId),
|
||||
function () { this.explodeStatement(path.get("body")); }
|
||||
);
|
||||
|
||||
this.jump(head);
|
||||
|
||||
this.mark(after);
|
||||
};
|
||||
|
||||
exports.BreakStatement = function (path, stmt) {
|
||||
this.emitAbruptCompletion({
|
||||
type: "break",
|
||||
target: this.leapManager.getBreakLoc(stmt.label)
|
||||
});
|
||||
};
|
||||
|
||||
exports.ContinueStatement = function (path, stmt) {
|
||||
this.emitAbruptCompletion({
|
||||
type: "continue",
|
||||
target: this.leapManager.getContinueLoc(stmt.label)
|
||||
});
|
||||
};
|
||||
|
||||
exports.SwitchStatement = function (path, stmt) {
|
||||
// Always save the discriminant into a temporary variable in case the
|
||||
// test expressions overwrite values like context.sent.
|
||||
var disc = this.emitAssign(
|
||||
this.makeTempVar(),
|
||||
this.explodeExpression(path.get("discriminant"))
|
||||
);
|
||||
|
||||
var after = loc();
|
||||
var defaultLoc = loc();
|
||||
var condition = defaultLoc;
|
||||
var caseLocs = [];
|
||||
var self = this;
|
||||
|
||||
// If there are no cases, .cases might be undefined.
|
||||
var cases = stmt.cases || [];
|
||||
|
||||
for (var i = cases.length - 1; i >= 0; --i) {
|
||||
var c = cases[i];
|
||||
t.assertSwitchCase(c);
|
||||
|
||||
if (c.test) {
|
||||
condition = t.conditionalExpression(
|
||||
t.binaryExpression("===", disc, c.test),
|
||||
caseLocs[i] = loc(),
|
||||
condition
|
||||
);
|
||||
} else {
|
||||
caseLocs[i] = defaultLoc;
|
||||
}
|
||||
}
|
||||
|
||||
this.jump(this.explodeExpression(
|
||||
new types.NodePath(condition, path, "discriminant")
|
||||
));
|
||||
|
||||
this.leapManager.withEntry(
|
||||
new leap.SwitchEntry(after),
|
||||
function () {
|
||||
path.get("cases").each(function (casePath) {
|
||||
var i = casePath.name;
|
||||
|
||||
self.mark(caseLocs[i]);
|
||||
|
||||
casePath.get("consequent").each(
|
||||
self.explodeStatement,
|
||||
self
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
this.mark(after);
|
||||
if (defaultLoc.value === -1) {
|
||||
this.mark(defaultLoc);
|
||||
assert.strictEqual(after.value, defaultLoc.value);
|
||||
}
|
||||
};
|
||||
|
||||
exports.IfStatement = function (path, stmt) {
|
||||
var elseLoc = stmt.alternate && loc();
|
||||
var after = loc();
|
||||
|
||||
this.jumpIfNot(
|
||||
this.explodeExpression(path.get("test")),
|
||||
elseLoc || after
|
||||
);
|
||||
|
||||
this.explodeStatement(path.get("consequent"));
|
||||
|
||||
if (elseLoc) {
|
||||
this.jump(after);
|
||||
this.mark(elseLoc);
|
||||
this.explodeStatement(path.get("alternate"));
|
||||
}
|
||||
|
||||
this.mark(after);
|
||||
};
|
||||
|
||||
exports.ReturnStatement = function (path) {
|
||||
this.emitAbruptCompletion({
|
||||
type: "return",
|
||||
value: this.explodeExpression(path.get("argument"))
|
||||
});
|
||||
};
|
||||
|
||||
exports.TryStatement = function (path, stmt) {
|
||||
var after = loc();
|
||||
var self = this;
|
||||
|
||||
var handler = stmt.handler;
|
||||
if (!handler && stmt.handlers) {
|
||||
handler = stmt.handlers[0] || null;
|
||||
}
|
||||
|
||||
var catchLoc = handler && loc();
|
||||
var catchEntry = catchLoc && new leap.CatchEntry(
|
||||
catchLoc,
|
||||
handler.param
|
||||
);
|
||||
|
||||
var finallyLoc = stmt.finalizer && loc();
|
||||
var finallyEntry = finallyLoc && new leap.FinallyEntry(finallyLoc);
|
||||
|
||||
var tryEntry = new leap.TryEntry(
|
||||
this.getUnmarkedCurrentLoc(),
|
||||
catchEntry,
|
||||
finallyEntry
|
||||
);
|
||||
|
||||
this.tryEntries.push(tryEntry);
|
||||
this.updateContextPrevLoc(tryEntry.firstLoc);
|
||||
|
||||
this.leapManager.withEntry(tryEntry, function () {
|
||||
this.explodeStatement(path.get("block"));
|
||||
|
||||
if (catchLoc) {
|
||||
if (finallyLoc) {
|
||||
// If we have both a catch block and a finally block, then
|
||||
// because we emit the catch block first, we need to jump over
|
||||
// it to the finally block.
|
||||
this.jump(finallyLoc);
|
||||
|
||||
} else {
|
||||
// If there is no finally block, then we need to jump over the
|
||||
// catch block to the fall-through location.
|
||||
this.jump(after);
|
||||
}
|
||||
|
||||
this.updateContextPrevLoc(self.mark(catchLoc));
|
||||
|
||||
var bodyPath = path.get("handler", "body");
|
||||
var safeParam = this.makeTempVar();
|
||||
this.clearPendingException(tryEntry.firstLoc, safeParam);
|
||||
|
||||
var catchScope = bodyPath.scope;
|
||||
var catchParamName = handler.param.name;
|
||||
t.assertCatchClause(catchScope.node);
|
||||
assert.strictEqual(catchScope.lookup(catchParamName), catchScope);
|
||||
|
||||
types.visit(bodyPath, {
|
||||
visitIdentifier: function (path) {
|
||||
if (path.value.name === catchParamName &&
|
||||
path.scope.lookup(catchParamName) === catchScope) {
|
||||
return safeParam;
|
||||
}
|
||||
this.traverse(path);
|
||||
}
|
||||
});
|
||||
|
||||
this.leapManager.withEntry(catchEntry, function () {
|
||||
this.explodeStatement(bodyPath);
|
||||
});
|
||||
}
|
||||
|
||||
if (finallyLoc) {
|
||||
this.updateContextPrevLoc(this.mark(finallyLoc));
|
||||
|
||||
this.leapManager.withEntry(finallyEntry, function () {
|
||||
this.explodeStatement(path.get("finalizer"));
|
||||
});
|
||||
|
||||
this.emit(t.callExpression(
|
||||
this.contextProperty("finish"),
|
||||
[finallyEntry.firstLoc]
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
this.mark(after);
|
||||
};
|
||||
|
||||
exports.ThrowStatement = function (path) {
|
||||
this.emit(t.throwStatement(
|
||||
this.explodeExpression(path.get("argument"))
|
||||
));
|
||||
};
|
||||
@@ -0,0 +1,611 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
exports.Emitter = Emitter;
|
||||
|
||||
var explodeExpressions = require("./explode-expressions");
|
||||
var explodeStatements = require("./explode-statements");
|
||||
var assert = require("assert");
|
||||
var types = require("ast-types");
|
||||
var leap = require("../leap");
|
||||
var meta = require("../meta");
|
||||
var util = require("../util");
|
||||
var t = require("../../../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
var loc = util.loc;
|
||||
var n = types.namedTypes;
|
||||
|
||||
function Emitter(contextId) {
|
||||
assert.ok(this instanceof Emitter);
|
||||
t.assertIdentifier(contextId);
|
||||
|
||||
// In order to make sure the context object does not collide with
|
||||
// anything in the local scope, we might have to rename it, so we
|
||||
// refer to it symbolically instead of just assuming that it will be
|
||||
// called "context".
|
||||
this.contextId = contextId;
|
||||
|
||||
// An append-only list of Statements that grows each time this.emit is
|
||||
// called.
|
||||
this.listing = [];
|
||||
|
||||
// A sparse array whose keys correspond to locations in this.listing
|
||||
// that have been marked as branch/jump targets.
|
||||
this.marked = [true];
|
||||
|
||||
// The last location will be marked when this.getDispatchLoop is
|
||||
// called.
|
||||
this.finalLoc = loc();
|
||||
|
||||
// A list of all leap.TryEntry statements emitted.
|
||||
this.tryEntries = [];
|
||||
|
||||
// Each time we evaluate the body of a loop, we tell this.leapManager
|
||||
// to enter a nested loop context that determines the meaning of break
|
||||
// and continue statements therein.
|
||||
this.leapManager = new leap.LeapManager(this);
|
||||
}
|
||||
|
||||
// Sets the exact value of the given location to the offset of the next
|
||||
// Statement emitted.
|
||||
Emitter.prototype.mark = function (loc) {
|
||||
t.assertLiteral(loc);
|
||||
var index = this.listing.length;
|
||||
if (loc.value === -1) {
|
||||
loc.value = index;
|
||||
} else {
|
||||
// Locations can be marked redundantly, but their values cannot change
|
||||
// once set the first time.
|
||||
assert.strictEqual(loc.value, index);
|
||||
}
|
||||
this.marked[index] = true;
|
||||
return loc;
|
||||
};
|
||||
|
||||
Emitter.prototype.emit = function (node) {
|
||||
if (t.isExpression(node)) node = t.expressionStatement(node);
|
||||
t.assertStatement(node);
|
||||
this.listing.push(node);
|
||||
};
|
||||
|
||||
// Shorthand for emitting assignment statements. This will come in handy
|
||||
// for assignments to temporary variables.
|
||||
Emitter.prototype.emitAssign = function (lhs, rhs) {
|
||||
this.emit(this.assign(lhs, rhs));
|
||||
return lhs;
|
||||
};
|
||||
|
||||
// Shorthand for an assignment statement.
|
||||
Emitter.prototype.assign = function (lhs, rhs) {
|
||||
return t.expressionStatement(
|
||||
t.assignmentExpression("=", lhs, rhs));
|
||||
};
|
||||
|
||||
// Convenience function for generating expressions like context.next,
|
||||
// context.sent, and context.rval.
|
||||
Emitter.prototype.contextProperty = function (name, computed) {
|
||||
return t.memberExpression(
|
||||
this.contextId,
|
||||
computed ? t.literal(name) : t.identifier(name),
|
||||
!!computed
|
||||
);
|
||||
};
|
||||
|
||||
var volatileContextPropertyNames = {
|
||||
prev: true,
|
||||
next: true,
|
||||
sent: true,
|
||||
rval: true
|
||||
};
|
||||
|
||||
// A "volatile" context property is a MemberExpression like context.sent
|
||||
// that should probably be stored in a temporary variable when there's a
|
||||
// possibility the property will get overwritten.
|
||||
Emitter.prototype.isVolatileContextProperty = function (expr) {
|
||||
if (t.isMemberExpression(expr)) {
|
||||
if (expr.computed) {
|
||||
// If it's a computed property such as context[couldBeAnything],
|
||||
// assume the worst in terms of volatility.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isIdentifier(expr.object) &&
|
||||
t.isIdentifier(expr.property) &&
|
||||
expr.object.name === this.contextId.name &&
|
||||
_.has(volatileContextPropertyNames, expr.property.name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Shorthand for setting context.rval and jumping to `context.stop()`.
|
||||
Emitter.prototype.stop = function (rval) {
|
||||
if (rval) {
|
||||
this.setReturnValue(rval);
|
||||
}
|
||||
|
||||
this.jump(this.finalLoc);
|
||||
};
|
||||
|
||||
Emitter.prototype.setReturnValue = function (valuePath) {
|
||||
t.assertExpression(valuePath.value);
|
||||
|
||||
this.emitAssign(
|
||||
this.contextProperty("rval"),
|
||||
this.explodeExpression(valuePath)
|
||||
);
|
||||
};
|
||||
|
||||
Emitter.prototype.clearPendingException = function (tryLoc, assignee) {
|
||||
t.assertLiteral(tryLoc);
|
||||
|
||||
var catchCall = t.callExpression(
|
||||
this.contextProperty("catch", true),
|
||||
[tryLoc]
|
||||
);
|
||||
|
||||
if (assignee) {
|
||||
this.emitAssign(assignee, catchCall);
|
||||
} else {
|
||||
this.emit(catchCall);
|
||||
}
|
||||
};
|
||||
|
||||
// Emits code for an unconditional jump to the given location, even if the
|
||||
// exact value of the location is not yet known.
|
||||
Emitter.prototype.jump = function (toLoc) {
|
||||
this.emitAssign(this.contextProperty("next"), toLoc);
|
||||
this.emit(t.breakStatement());
|
||||
};
|
||||
|
||||
// Conditional jump.
|
||||
Emitter.prototype.jumpIf = function (test, toLoc) {
|
||||
t.assertExpression(test);
|
||||
t.assertLiteral(toLoc);
|
||||
|
||||
this.emit(t.ifStatement(
|
||||
test,
|
||||
t.blockStatement([
|
||||
this.assign(this.contextProperty("next"), toLoc),
|
||||
t.breakStatement()
|
||||
])
|
||||
));
|
||||
};
|
||||
|
||||
// Conditional jump, with the condition negated.
|
||||
Emitter.prototype.jumpIfNot = function (test, toLoc) {
|
||||
t.assertExpression(test);
|
||||
t.assertLiteral(toLoc);
|
||||
|
||||
var negatedTest;
|
||||
if (t.isUnaryExpression(test) && test.operator === "!") {
|
||||
// Avoid double negation.
|
||||
negatedTest = test.argument;
|
||||
} else {
|
||||
negatedTest = t.unaryExpression("!", test);
|
||||
}
|
||||
|
||||
this.emit(t.ifStatement(
|
||||
negatedTest,
|
||||
t.blockStatement([
|
||||
this.assign(this.contextProperty("next"), toLoc),
|
||||
t.breakStatement()
|
||||
])
|
||||
));
|
||||
};
|
||||
|
||||
// Returns a unique MemberExpression that can be used to store and
|
||||
// retrieve temporary values. Since the object of the member expression is
|
||||
// the context object, which is presumed to coexist peacefully with all
|
||||
// other local variables, and since we just increment `nextTempId`
|
||||
// monotonically, uniqueness is assured.
|
||||
var nextTempId = 0;
|
||||
Emitter.prototype.makeTempVar = function () {
|
||||
return this.contextProperty("t" + nextTempId++);
|
||||
};
|
||||
|
||||
Emitter.prototype.getContextFunction = function (id) {
|
||||
var node = t.functionExpression(
|
||||
id || null,
|
||||
[this.contextId],
|
||||
t.blockStatement([this.getDispatchLoop()]),
|
||||
false, // Not a generator anymore!
|
||||
false // Nor an expression.
|
||||
);
|
||||
node._aliasFunction = true;
|
||||
return node;
|
||||
};
|
||||
|
||||
// Turns this.listing into a loop of the form
|
||||
//
|
||||
// while (1) switch (context.next) {
|
||||
// case 0:
|
||||
// ...
|
||||
// case n:
|
||||
// return context.stop();
|
||||
// }
|
||||
//
|
||||
// Each marked location in this.listing will correspond to one generated
|
||||
// case statement.
|
||||
Emitter.prototype.getDispatchLoop = function () {
|
||||
var self = this;
|
||||
var cases = [];
|
||||
var current;
|
||||
|
||||
// If we encounter a break, continue, or return statement in a switch
|
||||
// case, we can skip the rest of the statements until the next case.
|
||||
var alreadyEnded = false;
|
||||
|
||||
self.listing.forEach(function (stmt, i) {
|
||||
if (self.marked.hasOwnProperty(i)) {
|
||||
cases.push(t.switchCase(t.literal(i), current = []));
|
||||
alreadyEnded = false;
|
||||
}
|
||||
|
||||
if (!alreadyEnded) {
|
||||
current.push(stmt);
|
||||
if (isSwitchCaseEnder(stmt))
|
||||
alreadyEnded = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Now that we know how many statements there will be in this.listing,
|
||||
// we can finally resolve this.finalLoc.value.
|
||||
this.finalLoc.value = this.listing.length;
|
||||
|
||||
cases.push(
|
||||
t.switchCase(this.finalLoc, [
|
||||
// Intentionally fall through to the "end" case...
|
||||
]),
|
||||
|
||||
// So that the runtime can jump to the final location without having
|
||||
// to know its offset, we provide the "end" case as a synonym.
|
||||
t.switchCase(t.literal("end"), [
|
||||
// This will check/clear both context.thrown and context.rval.
|
||||
t.returnStatement(
|
||||
t.callExpression(this.contextProperty("stop"), [])
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
return t.whileStatement(
|
||||
t.literal(true),
|
||||
t.switchStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
this.contextProperty("prev"),
|
||||
this.contextProperty("next")
|
||||
),
|
||||
cases
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
// See comment above re: alreadyEnded.
|
||||
function isSwitchCaseEnder(stmt) {
|
||||
return t.isBreakStatement(stmt) ||
|
||||
t.isContinueStatement(stmt) ||
|
||||
t.isReturnStatement(stmt) ||
|
||||
t.isThrowStatement(stmt);
|
||||
}
|
||||
|
||||
Emitter.prototype.getTryEntryList = function () {
|
||||
if (this.tryEntries.length === 0) {
|
||||
// To avoid adding a needless [] to the majority of runtime.wrap
|
||||
// argument lists, force the caller to handle this case specially.
|
||||
return null;
|
||||
}
|
||||
|
||||
var lastLocValue = 0;
|
||||
|
||||
return t.arrayExpression(
|
||||
this.tryEntries.map(function (tryEntry) {
|
||||
var thisLocValue = tryEntry.firstLoc.value;
|
||||
assert.ok(thisLocValue >= lastLocValue, "try entries out of order");
|
||||
lastLocValue = thisLocValue;
|
||||
|
||||
var ce = tryEntry.catchEntry;
|
||||
var fe = tryEntry.finallyEntry;
|
||||
|
||||
var triple = [
|
||||
tryEntry.firstLoc,
|
||||
// The null here makes a hole in the array.
|
||||
ce ? ce.firstLoc : null
|
||||
];
|
||||
|
||||
if (fe) {
|
||||
triple[2] = fe.firstLoc;
|
||||
}
|
||||
|
||||
return t.arrayExpression(triple);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// All side effects must be realized in order.
|
||||
|
||||
// If any subexpression harbors a leap, all subexpressions must be
|
||||
// neutered of side effects.
|
||||
|
||||
// No destructive modification of AST nodes.
|
||||
|
||||
Emitter.prototype.explode = function (path, ignoreResult) {
|
||||
assert.ok(path instanceof types.NodePath);
|
||||
|
||||
var node = path.value;
|
||||
var self = this;
|
||||
|
||||
n.Node.check(node);
|
||||
|
||||
if (t.isStatement(node))
|
||||
return self.explodeStatement(path);
|
||||
|
||||
if (t.isExpression(node))
|
||||
return self.explodeExpression(path, ignoreResult);
|
||||
|
||||
if (t.isDeclaration(node))
|
||||
throw getDeclError(node);
|
||||
|
||||
switch (node.type) {
|
||||
case "Program":
|
||||
return path.get("body").map(self.explodeStatement, self);
|
||||
|
||||
case "VariableDeclarator":
|
||||
throw getDeclError(node);
|
||||
|
||||
// These node types should be handled by their parent nodes
|
||||
// (ObjectExpression, SwitchStatement, and TryStatement, respectively).
|
||||
case "Property":
|
||||
case "SwitchCase":
|
||||
case "CatchClause":
|
||||
throw new Error(node.type + " nodes should be handled by their parents");
|
||||
|
||||
default:
|
||||
throw new Error("unknown Node of type " + JSON.stringify(node.type));
|
||||
}
|
||||
};
|
||||
|
||||
function getDeclError(node) {
|
||||
return new Error(
|
||||
"all declarations should have been transformed into " +
|
||||
"assignments before the Exploder began its work: " +
|
||||
JSON.stringify(node));
|
||||
}
|
||||
|
||||
Emitter.prototype.explodeStatement = function (path, labelId) {
|
||||
assert.ok(path instanceof types.NodePath);
|
||||
|
||||
var stmt = path.value;
|
||||
var self = this;
|
||||
|
||||
t.assertStatement(stmt);
|
||||
|
||||
if (labelId) {
|
||||
t.assertIdentifier(labelId);
|
||||
} else {
|
||||
labelId = null;
|
||||
}
|
||||
|
||||
// Explode BlockStatement nodes even if they do not contain a yield,
|
||||
// because we don't want or need the curly braces.
|
||||
if (t.isBlockStatement(stmt)) {
|
||||
return path.get("body").each(
|
||||
self.explodeStatement,
|
||||
self
|
||||
);
|
||||
}
|
||||
|
||||
if (!meta.containsLeap(stmt)) {
|
||||
// Technically we should be able to avoid emitting the statement
|
||||
// altogether if !meta.hasSideEffects(stmt), but that leads to
|
||||
// confusing generated code (for instance, `while (true) {}` just
|
||||
// disappears) and is probably a more appropriate job for a dedicated
|
||||
// dead code elimination pass.
|
||||
self.emit(stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
var fn = explodeStatements[stmt.type];
|
||||
if (fn) {
|
||||
fn.call(this, path, stmt, labelId);
|
||||
} else {
|
||||
throw new Error("unknown Statement of type " + JSON.stringify(stmt.type));
|
||||
}
|
||||
};
|
||||
|
||||
Emitter.prototype.emitAbruptCompletion = function (record) {
|
||||
if (!isValidCompletion(record)) {
|
||||
assert.ok(
|
||||
false,
|
||||
"invalid completion record: " + JSON.stringify(record)
|
||||
);
|
||||
}
|
||||
|
||||
assert.notStrictEqual(
|
||||
record.type, "normal",
|
||||
"normal completions are not abrupt"
|
||||
);
|
||||
|
||||
var abruptArgs = [t.literal(record.type)];
|
||||
|
||||
if (record.type === "break" || record.type === "continue") {
|
||||
t.assertLiteral(record.target);
|
||||
abruptArgs[1] = record.target;
|
||||
} else if (record.type === "return" || record.type === "throw") {
|
||||
if (record.value) {
|
||||
t.assertExpression(record.value);
|
||||
abruptArgs[1] = record.value;
|
||||
}
|
||||
}
|
||||
|
||||
this.emit(
|
||||
t.returnStatement(
|
||||
t.callExpression(
|
||||
this.contextProperty("abrupt"),
|
||||
abruptArgs
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
function isValidCompletion(record) {
|
||||
var type = record.type;
|
||||
|
||||
if (type === "normal") {
|
||||
return !_.has(record, "target");
|
||||
}
|
||||
|
||||
if (type === "break" || type === "continue") {
|
||||
return !_.has(record, "value") && t.isLiteral(record.target);
|
||||
}
|
||||
|
||||
if (type === "return" || type === "throw") {
|
||||
return _.has(record, "value") && !_.has(record, "target");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not all offsets into emitter.listing are potential jump targets. For
|
||||
// example, execution typically falls into the beginning of a try block
|
||||
// without jumping directly there. This method returns the current offset
|
||||
// without marking it, so that a switch case will not necessarily be
|
||||
// generated for this offset (I say "not necessarily" because the same
|
||||
// location might end up being marked in the process of emitting other
|
||||
// statements). There's no logical harm in marking such locations as jump
|
||||
// targets, but minimizing the number of switch cases keeps the generated
|
||||
// code shorter.
|
||||
Emitter.prototype.getUnmarkedCurrentLoc = function () {
|
||||
return t.literal(this.listing.length);
|
||||
};
|
||||
|
||||
// The context.prev property takes the value of context.next whenever we
|
||||
// evaluate the switch statement discriminant, which is generally good
|
||||
// enough for tracking the last location we jumped to, but sometimes
|
||||
// context.prev needs to be more precise, such as when we fall
|
||||
// successfully out of a try block and into a finally block without
|
||||
// jumping. This method exists to update context.prev to the freshest
|
||||
// available location. If we were implementing a full interpreter, we
|
||||
// would know the location of the current instruction with complete
|
||||
// precision at all times, but we don't have that luxury here, as it would
|
||||
// be costly and verbose to set context.prev before every statement.
|
||||
Emitter.prototype.updateContextPrevLoc = function (loc) {
|
||||
if (loc) {
|
||||
t.assertLiteral(loc);
|
||||
|
||||
if (loc.value === -1) {
|
||||
// If an uninitialized location literal was passed in, set its value
|
||||
// to the current this.listing.length.
|
||||
loc.value = this.listing.length;
|
||||
} else {
|
||||
// Otherwise assert that the location matches the current offset.
|
||||
assert.strictEqual(loc.value, this.listing.length);
|
||||
}
|
||||
|
||||
} else {
|
||||
loc = this.getUnmarkedCurrentLoc();
|
||||
}
|
||||
|
||||
// Make sure context.prev is up to date in case we fell into this try
|
||||
// statement without jumping to it. TODO Consider avoiding this
|
||||
// assignment when we know control must have jumped here.
|
||||
this.emitAssign(this.contextProperty("prev"), loc);
|
||||
};
|
||||
|
||||
Emitter.prototype.explodeExpression = function (path, ignoreResult) {
|
||||
assert.ok(path instanceof types.NodePath);
|
||||
|
||||
var expr = path.value;
|
||||
if (expr) {
|
||||
t.assertExpression(expr);
|
||||
} else {
|
||||
return expr;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
function finish(expr) {
|
||||
t.assertExpression(expr);
|
||||
if (ignoreResult) {
|
||||
self.emit(expr);
|
||||
} else {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
||||
// If the expression does not contain a leap, then we either emit the
|
||||
// expression as a standalone statement or return it whole.
|
||||
if (!meta.containsLeap(expr)) {
|
||||
return finish(expr);
|
||||
}
|
||||
|
||||
// If any child contains a leap (such as a yield or labeled continue or
|
||||
// break statement), then any sibling subexpressions will almost
|
||||
// certainly have to be exploded in order to maintain the order of their
|
||||
// side effects relative to the leaping child(ren).
|
||||
var hasLeapingChildren = meta.containsLeap.onlyChildren(expr);
|
||||
|
||||
// In order to save the rest of explodeExpression from a combinatorial
|
||||
// trainwreck of special cases, explodeViaTempVar is responsible for
|
||||
// deciding when a subexpression needs to be "exploded," which is my
|
||||
// very technical term for emitting the subexpression as an assignment
|
||||
// to a temporary variable and the substituting the temporary variable
|
||||
// for the original subexpression. Think of exploded view diagrams, not
|
||||
// Michael Bay movies. The point of exploding subexpressions is to
|
||||
// control the precise order in which the generated code realizes the
|
||||
// side effects of those subexpressions.
|
||||
function explodeViaTempVar(tempVar, childPath, ignoreChildResult) {
|
||||
assert.ok(childPath instanceof types.NodePath);
|
||||
|
||||
assert.ok(
|
||||
!ignoreChildResult || !tempVar,
|
||||
"Ignoring the result of a child expression but forcing it to " +
|
||||
"be assigned to a temporary variable?"
|
||||
);
|
||||
|
||||
var result = self.explodeExpression(childPath, ignoreChildResult);
|
||||
|
||||
if (ignoreChildResult) {
|
||||
// Side effects already emitted above.
|
||||
|
||||
} else if (tempVar || (hasLeapingChildren &&
|
||||
(self.isVolatileContextProperty(result) ||
|
||||
meta.hasSideEffects(result)))) {
|
||||
// If tempVar was provided, then the result will always be assigned
|
||||
// to it, even if the result does not otherwise need to be assigned
|
||||
// to a temporary variable. When no tempVar is provided, we have
|
||||
// the flexibility to decide whether a temporary variable is really
|
||||
// necessary. In general, temporary assignment is required only
|
||||
// when some other child contains a leap and the child in question
|
||||
// is a context property like $ctx.sent that might get overwritten
|
||||
// or an expression with side effects that need to occur in proper
|
||||
// sequence relative to the leap.
|
||||
result = self.emitAssign(
|
||||
tempVar || self.makeTempVar(),
|
||||
result
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// If ignoreResult is true, then we must take full responsibility for
|
||||
// emitting the expression with all its side effects, and we should not
|
||||
// return a result.
|
||||
|
||||
var fn = explodeExpressions[expr.type];
|
||||
if (fn) {
|
||||
return fn.call(this, expr, path, explodeViaTempVar, finish, ignoreResult);
|
||||
} else {
|
||||
throw new Error("unknown Expression of type " + JSON.stringify(expr.type));
|
||||
}
|
||||
};
|
||||
151
lib/6to5/transformation/transformers/es6-generators/hoist.js
Normal file
151
lib/6to5/transformation/transformers/es6-generators/hoist.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* https://raw.githut.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 t = require("../../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
// 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);
|
||||
t.assertFunction(funPath.value);
|
||||
|
||||
var vars = {};
|
||||
|
||||
function varDeclToExpr(vdec, includeIdentifiers) {
|
||||
t.assertVariableDeclaration(vdec);
|
||||
var exprs = [];
|
||||
|
||||
vdec.declarations.forEach(function (dec) {
|
||||
vars[dec.id.name] = dec.id;
|
||||
|
||||
if (dec.init) {
|
||||
exprs.push(t.assignmentExpression(
|
||||
"=", dec.id, dec.init
|
||||
));
|
||||
} else if (includeIdentifiers) {
|
||||
exprs.push(dec.id);
|
||||
}
|
||||
});
|
||||
|
||||
if (exprs.length === 0)
|
||||
return null;
|
||||
|
||||
if (exprs.length === 1)
|
||||
return exprs[0];
|
||||
|
||||
return t.sequenceExpression(exprs);
|
||||
}
|
||||
|
||||
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 t.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 (t.isVariableDeclaration(init)) {
|
||||
path.get("init").replace(varDeclToExpr(init, false));
|
||||
}
|
||||
this.traverse(path);
|
||||
},
|
||||
|
||||
visitForInStatement: function (path) {
|
||||
var left = path.value.left;
|
||||
if (t.isVariableDeclaration(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 = t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
node.id,
|
||||
t.functionExpression(
|
||||
node.id,
|
||||
node.params,
|
||||
node.body,
|
||||
node.generator,
|
||||
node.expression
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (t.isBlockStatement(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 (t.isIdentifier(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 (!_.has(paramNames, name)) {
|
||||
declarations.push(t.variableDeclarator(vars[name], null));
|
||||
}
|
||||
});
|
||||
|
||||
if (declarations.length === 0) {
|
||||
return null; // Be sure to handle this case!
|
||||
}
|
||||
|
||||
return t.variableDeclaration("var", declarations);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require("./visit").transform;
|
||||
163
lib/6to5/transformation/transformers/es6-generators/leap.js
Normal file
163
lib/6to5/transformation/transformers/es6-generators/leap.js
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
exports.FunctionEntry = FunctionEntry;
|
||||
exports.FinallyEntry = FinallyEntry;
|
||||
exports.SwitchEntry = SwitchEntry;
|
||||
exports.LeapManager = LeapManager;
|
||||
exports.CatchEntry = CatchEntry;
|
||||
exports.LoopEntry = LoopEntry;
|
||||
exports.TryEntry = TryEntry;
|
||||
|
||||
var assert = require("assert");
|
||||
var util = require("util");
|
||||
var t = require("../../../types");
|
||||
|
||||
var inherits = util.inherits;
|
||||
|
||||
function Entry() {
|
||||
assert.ok(this instanceof Entry);
|
||||
}
|
||||
|
||||
function FunctionEntry(returnLoc) {
|
||||
Entry.call(this);
|
||||
|
||||
t.assertLiteral(returnLoc);
|
||||
|
||||
this.returnLoc = returnLoc;
|
||||
}
|
||||
|
||||
inherits(FunctionEntry, Entry);
|
||||
|
||||
function LoopEntry(breakLoc, continueLoc, label) {
|
||||
Entry.call(this);
|
||||
|
||||
t.assertLiteral(breakLoc);
|
||||
t.assertLiteral(continueLoc);
|
||||
|
||||
if (label) {
|
||||
t.assertIdentifier(label);
|
||||
} else {
|
||||
label = null;
|
||||
}
|
||||
|
||||
this.breakLoc = breakLoc;
|
||||
this.continueLoc = continueLoc;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
inherits(LoopEntry, Entry);
|
||||
|
||||
function SwitchEntry(breakLoc) {
|
||||
Entry.call(this);
|
||||
|
||||
t.assertLiteral(breakLoc);
|
||||
|
||||
this.breakLoc = breakLoc;
|
||||
}
|
||||
|
||||
inherits(SwitchEntry, Entry);
|
||||
|
||||
function TryEntry(firstLoc, catchEntry, finallyEntry) {
|
||||
Entry.call(this);
|
||||
|
||||
t.assertLiteral(firstLoc);
|
||||
|
||||
if (catchEntry) {
|
||||
assert.ok(catchEntry instanceof CatchEntry);
|
||||
} else {
|
||||
catchEntry = null;
|
||||
}
|
||||
|
||||
if (finallyEntry) {
|
||||
assert.ok(finallyEntry instanceof FinallyEntry);
|
||||
} else {
|
||||
finallyEntry = null;
|
||||
}
|
||||
|
||||
// Have to have one or the other (or both).
|
||||
assert.ok(catchEntry || finallyEntry);
|
||||
|
||||
this.firstLoc = firstLoc;
|
||||
this.catchEntry = catchEntry;
|
||||
this.finallyEntry = finallyEntry;
|
||||
}
|
||||
|
||||
inherits(TryEntry, Entry);
|
||||
|
||||
function CatchEntry(firstLoc, paramId) {
|
||||
Entry.call(this);
|
||||
|
||||
t.assertLiteral(firstLoc);
|
||||
t.assertIdentifier(paramId);
|
||||
|
||||
this.firstLoc = firstLoc;
|
||||
this.paramId = paramId;
|
||||
}
|
||||
|
||||
inherits(CatchEntry, Entry);
|
||||
|
||||
function FinallyEntry(firstLoc) {
|
||||
Entry.call(this);
|
||||
|
||||
t.assertLiteral(firstLoc);
|
||||
|
||||
this.firstLoc = firstLoc;
|
||||
}
|
||||
|
||||
inherits(FinallyEntry, Entry);
|
||||
|
||||
function LeapManager(emitter) {
|
||||
assert.ok(this instanceof LeapManager);
|
||||
|
||||
var Emitter = require("./emit").Emitter;
|
||||
assert.ok(emitter instanceof Emitter);
|
||||
|
||||
this.emitter = emitter;
|
||||
this.entryStack = [new FunctionEntry(emitter.finalLoc)];
|
||||
}
|
||||
|
||||
LeapManager.prototype.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);
|
||||
}
|
||||
};
|
||||
|
||||
LeapManager.prototype._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;
|
||||
};
|
||||
|
||||
LeapManager.prototype.getBreakLoc = function (label) {
|
||||
return this._findLeapLocation("breakLoc", label);
|
||||
};
|
||||
|
||||
LeapManager.prototype.getContinueLoc = function (label) {
|
||||
return this._findLeapLocation("continueLoc", label);
|
||||
};
|
||||
98
lib/6to5/transformation/transformers/es6-generators/meta.js
Normal file
98
lib/6to5/transformation/transformers/es6-generators/meta.js
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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 _ = require("lodash");
|
||||
|
||||
var isArray = types.builtInTypes.array;
|
||||
var n = types.namedTypes;
|
||||
|
||||
function makePredicate(propertyName, knownTypes) {
|
||||
function onlyChildren(node) {
|
||||
n.Node.check(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.check(node);
|
||||
|
||||
var meta = m(node);
|
||||
if (_.has(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 (_.has(opaqueTypes, node.type)) return meta[propertyName] = false;
|
||||
|
||||
if (_.has(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 (_.has(leapTypes, type)) {
|
||||
sideEffectTypes[type] = leapTypes[type];
|
||||
}
|
||||
}
|
||||
|
||||
exports.hasSideEffects = makePredicate("hasSideEffects", sideEffectTypes);
|
||||
exports.containsLeap = makePredicate("containsLeap", leapTypes);
|
||||
454
lib/6to5/transformation/transformers/es6-generators/runtime.js
Normal file
454
lib/6to5/transformation/transformers/es6-generators/runtime.js
Normal file
@@ -0,0 +1,454 @@
|
||||
/**
|
||||
* 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 iteratorSymbol = typeof Symbol === "function" && Symbol.iterator || "@@iterator";
|
||||
var runtime = global.regeneratorRuntime = exports;
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
28
lib/6to5/transformation/transformers/es6-generators/util.js
Normal file
28
lib/6to5/transformation/transformers/es6-generators/util.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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 t = require("../../../types");
|
||||
|
||||
exports.runtimeProperty = function (name) {
|
||||
return t.memberExpression(
|
||||
t.identifier("regeneratorRuntime"),
|
||||
t.identifier(name)
|
||||
);
|
||||
};
|
||||
|
||||
// Offsets into this.listing that could be used as targets for branches or
|
||||
// jumps are represented as numeric Literal nodes. This representation has
|
||||
// the amazingly convenient benefit of allowing the exact value of the
|
||||
// location to be determined at any time, even after generating code that
|
||||
// refers to the location.
|
||||
|
||||
exports.loc = function () {
|
||||
return t.literal(-1);
|
||||
};
|
||||
221
lib/6to5/transformation/transformers/es6-generators/visit.js
Normal file
221
lib/6to5/transformation/transformers/es6-generators/visit.js
Normal file
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* https://raw.githut.com/facebook/regenerator/master/LICENSE file. An
|
||||
* additional grant of patent rights can be found in the PATENTS file in
|
||||
* the same directory.
|
||||
*/
|
||||
|
||||
var runtimeProperty = require("./util").runtimeProperty;
|
||||
var Emitter = require("./emit").Emitter;
|
||||
var hoist = require("./hoist").hoist;
|
||||
var types = require("ast-types");
|
||||
var t = require("../../../types");
|
||||
|
||||
var runtimeAsyncMethod = runtimeProperty("async");
|
||||
var runtimeWrapMethod = runtimeProperty("wrap");
|
||||
var runtimeMarkMethod = runtimeProperty("mark");
|
||||
|
||||
exports.transform = function transform(node, file) {
|
||||
return types.visit(node, {
|
||||
visitFunction: function (path) {
|
||||
return visitor.call(this, path, file);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var visitor = function (path, file) {
|
||||
// Calling this.traverse(path) first makes for a post-order traversal.
|
||||
this.traverse(path);
|
||||
|
||||
var node = path.value;
|
||||
var scope; // we need to actually get the current scope
|
||||
|
||||
if (!node.generator && !node.async) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.generator = false;
|
||||
|
||||
if (node.expression) {
|
||||
// Transform expression lambdas into normal functions.
|
||||
node.expression = false;
|
||||
node.body = t.blockStatement([
|
||||
t.returnStatement(node.body)
|
||||
]);
|
||||
}
|
||||
|
||||
if (node.async) {
|
||||
awaitVisitor.visit(path.get("body"));
|
||||
}
|
||||
|
||||
var outerFnId = node.id || (
|
||||
node.id = file.generateUidIdentifier("callee", scope)
|
||||
);
|
||||
|
||||
var innerFnId = t.identifier(node.id.name + "$");
|
||||
var contextId = file.generateUidIdentifier("context", scope);
|
||||
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 ? t.literal(null) : outerFnId,
|
||||
t.thisExpression()
|
||||
];
|
||||
|
||||
var tryEntryList = emitter.getTryEntryList();
|
||||
if (tryEntryList) {
|
||||
wrapArgs.push(tryEntryList);
|
||||
}
|
||||
|
||||
var wrapCall = t.callExpression(
|
||||
node.async ? runtimeAsyncMethod : runtimeWrapMethod,
|
||||
wrapArgs
|
||||
);
|
||||
|
||||
outerBody.push(t.returnStatement(wrapCall));
|
||||
node.body = t.blockStatement(outerBody);
|
||||
|
||||
if (node.async) {
|
||||
node.async = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.isFunctionDeclaration(node)) {
|
||||
var pp = path.parent;
|
||||
|
||||
while (pp && !(t.isBlockStatement(pp.value) || t.isProgram(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 = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
node.id,
|
||||
t.callExpression(runtimeMarkMethod, [node])
|
||||
)
|
||||
]);
|
||||
|
||||
// Copy any comments preceding the function declaration to the
|
||||
// variable declaration, to avoid weird formatting consequences.
|
||||
t.inheritsComments(varDecl, node);
|
||||
t.removeComments(node);
|
||||
|
||||
varDecl._blockHoist = true;
|
||||
|
||||
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 {
|
||||
t.assertFunctionExpression(node);
|
||||
return t.callExpression(runtimeMarkMethod, [node]);
|
||||
}
|
||||
};
|
||||
|
||||
function shouldNotHoistAbove(stmtPath) {
|
||||
var value = stmtPath.value;
|
||||
t.assertStatement(value);
|
||||
|
||||
// If the first statement is a "use strict" declaration, make sure to
|
||||
// insert hoisted declarations afterwards.
|
||||
if (t.isExpressionStatement(value) &&
|
||||
t.isLiteral(value.expression) &&
|
||||
value.expression.value === "use strict") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isVariableDeclaration(value)) {
|
||||
for (var i = 0; i < value.declarations.length; ++i) {
|
||||
var decl = value.declarations[i];
|
||||
if (t.isCallExpression(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 t.yieldExpression(path.value.argument, false);
|
||||
}
|
||||
});
|
||||
@@ -74,7 +74,6 @@ function LetScoping(forParent, block, parent, file, scope) {
|
||||
|
||||
this.letReferences = {};
|
||||
this.body = [];
|
||||
this.info = this.getInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,8 +86,13 @@ LetScoping.prototype.run = function () {
|
||||
if (block._letDone) return;
|
||||
block._letDone = true;
|
||||
|
||||
this.info = this.getInfo();
|
||||
|
||||
// remap all let references that exist in upper scopes to their uid
|
||||
this.remap();
|
||||
|
||||
// this is a block within a `Function` so we can safely leave it be
|
||||
if (t.isFunction(this.parent)) return;
|
||||
if (t.isFunction(this.parent)) return this.noClosure();
|
||||
|
||||
// this block has no let references so let's clean up
|
||||
if (!this.info.keys.length) return this.noClosure();
|
||||
@@ -125,31 +129,57 @@ LetScoping.prototype.run = function () {
|
||||
|
||||
// build a call and a unique id that we can assign the return value to
|
||||
var call = t.callExpression(fn, params);
|
||||
var ret = t.identifier(this.file.generateUid("ret", this.scope));
|
||||
var ret = this.file.generateUidIdentifier("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);
|
||||
};
|
||||
|
||||
/**
|
||||
* There are no let references accessed within a closure so we can just traverse
|
||||
* through this block and replace all references that exist in a higher scope to
|
||||
* their uids.
|
||||
* There are no let references accessed within a closure so we can just turn the
|
||||
* lets into vars.
|
||||
*/
|
||||
|
||||
LetScoping.prototype.noClosure = function () {
|
||||
var replacements = this.info.duplicates;
|
||||
var declarators = this.info.declarators;
|
||||
var block = this.block;
|
||||
standardiseLets(this.info.declarators);
|
||||
};
|
||||
|
||||
standardiseLets(declarators);
|
||||
/**
|
||||
* Traverse through block and replace all references that exist in a higher
|
||||
* scope to their uids.
|
||||
*/
|
||||
|
||||
LetScoping.prototype.remap = function () {
|
||||
var replacements = this.info.duplicates;
|
||||
var block = this.block;
|
||||
|
||||
if (_.isEmpty(replacements)) return;
|
||||
|
||||
traverse(block, function (node, parent) {
|
||||
var replace = function (node, parent, scope) {
|
||||
if (!t.isIdentifier(node)) return;
|
||||
if (!t.isReferenced(node, parent)) return;
|
||||
if (scope && scope.hasOwn(node.name)) return;
|
||||
node.name = replacements[node.name] || node.name;
|
||||
});
|
||||
};
|
||||
|
||||
var traverseReplace = function (node, parent) {
|
||||
replace(node, parent);
|
||||
traverse(node, replace);
|
||||
};
|
||||
|
||||
var forParent = this.forParent;
|
||||
if (forParent) {
|
||||
traverseReplace(forParent.right, forParent);
|
||||
traverseReplace(forParent.test, forParent);
|
||||
traverseReplace(forParent.update, forParent);
|
||||
}
|
||||
|
||||
traverse(block, replace);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -181,10 +211,23 @@ LetScoping.prototype.getInfo = function () {
|
||||
keys: []
|
||||
};
|
||||
|
||||
var duplicates = function (id, key) {
|
||||
var has = scope.parentGet(key);
|
||||
|
||||
if (has && has !== id) {
|
||||
// there's a variable with this exact name in an upper scope so we need
|
||||
// to generate a new name
|
||||
opts.duplicates[key] = id.name = file.generateUid(key, scope);
|
||||
}
|
||||
};
|
||||
|
||||
_.each(opts.declarators, function (declar) {
|
||||
opts.declarators.push(declar);
|
||||
|
||||
var keys = t.getIds(declar);
|
||||
var keys = t.getIds(declar, true);
|
||||
_.each(keys, duplicates);
|
||||
keys = _.keys(keys);
|
||||
|
||||
opts.outsideKeys = opts.outsideKeys.concat(keys);
|
||||
opts.keys = opts.keys.concat(keys);
|
||||
});
|
||||
@@ -193,14 +236,7 @@ LetScoping.prototype.getInfo = function () {
|
||||
if (!isLet(declar)) return;
|
||||
|
||||
_.each(t.getIds(declar, true), function (id, key) {
|
||||
var has = scope.parentGet(key);
|
||||
|
||||
if (has && has !== id) {
|
||||
// there's a variable with this exact name in an upper scope so we need
|
||||
// to generate a new name
|
||||
opts.duplicates[key] = id.name = file.generateUid(key, scope);
|
||||
}
|
||||
|
||||
duplicates(id, key);
|
||||
opts.keys.push(key);
|
||||
});
|
||||
});
|
||||
@@ -224,28 +260,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 && !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;
|
||||
};
|
||||
@@ -341,7 +383,7 @@ LetScoping.prototype.getLetReferences = function () {
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
LetScoping.prototype.buildPushDeclar = function (node) {
|
||||
LetScoping.prototype.pushDeclar = function (node) {
|
||||
this.body.push(t.variableDeclaration(node.kind, node.declarations.map(function (declar) {
|
||||
return t.variableDeclarator(declar.id);
|
||||
})));
|
||||
@@ -403,7 +445,7 @@ LetScoping.prototype.buildHas = function (ret, call) {
|
||||
if (has.hasBreak || has.hasContinue) {
|
||||
// ensure that the parent has a label as we're building a switch and we
|
||||
// need to be able to access it
|
||||
var label = forParent.label = forParent.label || t.identifier(this.file.generateUid("loop", this.scope));
|
||||
var label = forParent.label = forParent.label || this.file.generateUidIdentifier("loop", this.scope);
|
||||
|
||||
if (has.hasBreak) {
|
||||
cases.push(t.switchCase(t.literal("break"), [t.breakStatement(label)]));
|
||||
@@ -5,10 +5,10 @@ exports.ImportDeclaration = function (node, parent, file) {
|
||||
|
||||
if (node.specifiers.length) {
|
||||
_.each(node.specifiers, function (specifier) {
|
||||
file.moduleFormatter.importSpecifier(specifier, node, nodes);
|
||||
file.moduleFormatter.importSpecifier(specifier, node, nodes, parent);
|
||||
});
|
||||
} else {
|
||||
file.moduleFormatter.import(node, nodes);
|
||||
file.moduleFormatter.import(node, nodes, parent);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
@@ -18,10 +18,10 @@ exports.ExportDeclaration = function (node, parent, file) {
|
||||
var nodes = [];
|
||||
|
||||
if (node.declaration) {
|
||||
file.moduleFormatter.export(node, nodes);
|
||||
file.moduleFormatter.export(node, nodes, parent);
|
||||
} else {
|
||||
_.each(node.specifiers, function (specifier) {
|
||||
file.moduleFormatter.exportSpecifier(specifier, node, nodes);
|
||||
file.moduleFormatter.exportSpecifier(specifier, node, nodes, parent);
|
||||
});
|
||||
}
|
||||
|
||||
25
lib/6to5/transformation/transformers/es6-rest-parameters.js
Normal file
25
lib/6to5/transformation/transformers/es6-rest-parameters.js
Normal file
@@ -0,0 +1,25 @@
|
||||
var t = require("../../types");
|
||||
|
||||
exports.Function = function (node, parent, file) {
|
||||
if (!node.rest) return;
|
||||
|
||||
var rest = node.rest;
|
||||
delete node.rest;
|
||||
|
||||
t.ensureBlock(node);
|
||||
|
||||
var call = t.callExpression(
|
||||
file.addDeclaration("arguments-to-array"),
|
||||
[t.identifier("arguments")]
|
||||
);
|
||||
|
||||
if (node.params.length) {
|
||||
call = t.callExpression(t.memberExpression(call, t.identifier("slice")), [t.literal(node.params.length)]);
|
||||
}
|
||||
|
||||
call._ignoreAliasFunctions = true;
|
||||
|
||||
node.body.body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(rest, call)
|
||||
]));
|
||||
};
|
||||
@@ -1,15 +1,8 @@
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
var getSpreadLiteral = function (spread) {
|
||||
var literal = spread.argument;
|
||||
if (!t.isArrayExpression(literal)) {
|
||||
literal = t.callExpression(
|
||||
t.memberExpression(t.identifier("Array"), t.identifier("from")),
|
||||
[literal]
|
||||
);
|
||||
}
|
||||
return literal;
|
||||
var getSpreadLiteral = function (spread, file) {
|
||||
return file.toArray(spread.argument);
|
||||
};
|
||||
|
||||
var hasSpread = function (nodes) {
|
||||
@@ -23,7 +16,7 @@ var hasSpread = function (nodes) {
|
||||
return has;
|
||||
};
|
||||
|
||||
var build = function (props) {
|
||||
var build = function (props, file) {
|
||||
var nodes = [];
|
||||
|
||||
var _props = [];
|
||||
@@ -37,7 +30,7 @@ var build = function (props) {
|
||||
_.each(props, function (prop) {
|
||||
if (t.isSpreadElement(prop)) {
|
||||
push();
|
||||
nodes.push(getSpreadLiteral(prop));
|
||||
nodes.push(getSpreadLiteral(prop, file));
|
||||
} else {
|
||||
_props.push(prop);
|
||||
}
|
||||
@@ -48,19 +41,22 @@ var build = function (props) {
|
||||
return nodes;
|
||||
};
|
||||
|
||||
exports.ArrayExpression = function (node) {
|
||||
exports.ArrayExpression = function (node, parent, file) {
|
||||
var elements = node.elements;
|
||||
if (!hasSpread(elements)) return;
|
||||
|
||||
var nodes = build(elements);
|
||||
var nodes = build(elements, file);
|
||||
var first = nodes.shift();
|
||||
|
||||
if (!nodes.length) return first;
|
||||
if (!t.isArrayExpression(first)) {
|
||||
nodes.unshift(first);
|
||||
first = t.arrayExpression([]);
|
||||
}
|
||||
|
||||
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
|
||||
};
|
||||
|
||||
exports.CallExpression = function (node) {
|
||||
exports.CallExpression = function (node, parent, file) {
|
||||
var args = node.arguments;
|
||||
if (!hasSpread(args)) return;
|
||||
|
||||
@@ -68,7 +64,7 @@ exports.CallExpression = function (node) {
|
||||
|
||||
node.arguments = [];
|
||||
|
||||
var nodes = build(args);
|
||||
var nodes = build(args, file);
|
||||
var first = nodes.shift();
|
||||
|
||||
if (nodes.length) {
|
||||
@@ -100,7 +96,7 @@ exports.NewExpression = function (node, parent, file) {
|
||||
var args = node.arguments;
|
||||
if (!hasSpread(args)) return;
|
||||
|
||||
var nodes = build(args);
|
||||
var nodes = build(args, file);
|
||||
var first = nodes.shift();
|
||||
|
||||
if (nodes.length) {
|
||||
@@ -5,19 +5,25 @@ var buildBinaryExpression = function (left, right) {
|
||||
return t.binaryExpression("+", left, right);
|
||||
};
|
||||
|
||||
exports.TaggedTemplateExpression = function (node) {
|
||||
exports.TaggedTemplateExpression = function (node, parent, file) {
|
||||
var args = [];
|
||||
var quasi = node.quasi;
|
||||
|
||||
var strings = quasi.quasis.map(function (elem) {
|
||||
return t.literal(elem.value.raw);
|
||||
});
|
||||
args.push(t.arrayExpression(strings));
|
||||
var strings = [];
|
||||
var raw = [];
|
||||
|
||||
_.each(quasi.expressions, function (expr) {
|
||||
args.push(expr);
|
||||
_.each(quasi.quasis, function (elem) {
|
||||
strings.push(t.literal(elem.value.cooked));
|
||||
raw.push(t.literal(elem.value.raw));
|
||||
});
|
||||
|
||||
args.push(t.callExpression(file.addDeclaration("tagged-template-literal"), [
|
||||
t.arrayExpression(strings),
|
||||
t.arrayExpression(raw)
|
||||
]));
|
||||
|
||||
args = args.concat(quasi.expressions);
|
||||
|
||||
return t.callExpression(node.tag, args);
|
||||
};
|
||||
|
||||
102
lib/6to5/transformation/transformers/es7-abstract-references.js
Normal file
102
lib/6to5/transformation/transformers/es7-abstract-references.js
Normal file
@@ -0,0 +1,102 @@
|
||||
// https://github.com/zenparsing/es-abstract-refs
|
||||
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
|
||||
var container = function (parent, call, ret) {
|
||||
if (t.isExpressionStatement(parent)) {
|
||||
// we don't need to worry about return values
|
||||
return call;
|
||||
} else {
|
||||
var exprs = [];
|
||||
if (t.isSequenceExpression(call)) {
|
||||
exprs = call.expressions;
|
||||
} else {
|
||||
exprs.push(call);
|
||||
}
|
||||
exprs.push(ret);
|
||||
return t.sequenceExpression(exprs);
|
||||
}
|
||||
};
|
||||
|
||||
exports.AssignmentExpression = function (node, parent, file, scope) {
|
||||
var left = node.left;
|
||||
if (!t.isVirtualPropertyExpression(left)) return;
|
||||
|
||||
var value = node.right;
|
||||
var temp;
|
||||
|
||||
// we need to return `node.right`
|
||||
if (!t.isExpressionStatement(parent)) {
|
||||
// `node.right` isn't a simple identifier so we need to reference it
|
||||
if (t.isDynamic(value)) {
|
||||
var tempName = file.generateUid("temp");
|
||||
temp = value = t.identifier(tempName);
|
||||
scope.push(tempName, temp);
|
||||
}
|
||||
}
|
||||
|
||||
var call = util.template("abstract-expression-set", {
|
||||
PROPERTY: left.property,
|
||||
OBJECT: left.object,
|
||||
VALUE: value
|
||||
});
|
||||
|
||||
if (temp) {
|
||||
call = t.sequenceExpression([
|
||||
t.assignmentExpression("=", temp, node.right),
|
||||
call
|
||||
]);
|
||||
}
|
||||
|
||||
return container(parent, call, value);
|
||||
};
|
||||
|
||||
exports.UnaryExpression = function (node, parent) {
|
||||
var arg = node.argument;
|
||||
if (!t.isVirtualPropertyExpression(arg)) return;
|
||||
if (node.operator !== "delete") return;
|
||||
|
||||
var call = util.template("abstract-expression-delete", {
|
||||
PROPERTY: arg.property,
|
||||
OBJECT: arg.object
|
||||
});
|
||||
|
||||
return container(parent, call, t.literal(true));
|
||||
};
|
||||
|
||||
exports.CallExpression = function (node, parent, file, scope) {
|
||||
var callee = node.callee;
|
||||
if (!t.isVirtualPropertyExpression(callee)) return;
|
||||
|
||||
var temp;
|
||||
if (t.isDynamic(callee.object)) {
|
||||
// we need to save `callee.object` so we can call it again
|
||||
var tempName = file.generateUid("temp");
|
||||
temp = t.identifier(tempName);
|
||||
scope.push(tempName, temp);
|
||||
}
|
||||
|
||||
var call = util.template("abstract-expression-call", {
|
||||
PROPERTY: callee.property,
|
||||
OBJECT: temp || callee.object
|
||||
});
|
||||
|
||||
call.arguments = call.arguments.concat(node.arguments);
|
||||
|
||||
if (temp) {
|
||||
return t.sequenceExpression([
|
||||
t.assignmentExpression("=", temp, callee.object),
|
||||
call
|
||||
]);
|
||||
} else {
|
||||
return call;
|
||||
}
|
||||
};
|
||||
|
||||
exports.VirtualPropertyExpression = function (node) {
|
||||
return util.template("abstract-expression-get", {
|
||||
PROPERTY: node.property,
|
||||
OBJECT: node.object
|
||||
});
|
||||
};
|
||||
@@ -2,7 +2,7 @@ var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
var singleArrayExpression = function (node) {
|
||||
var single = function (node, file) {
|
||||
var block = node.blocks[0];
|
||||
|
||||
var templateName = "array-expression-comprehension-map";
|
||||
@@ -11,7 +11,7 @@ var singleArrayExpression = function (node) {
|
||||
var result = util.template(templateName, {
|
||||
STATEMENT: node.body,
|
||||
FILTER: node.filter,
|
||||
ARRAY: block.right,
|
||||
ARRAY: file.toArray(block.right),
|
||||
KEY: block.left
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ var singleArrayExpression = function (node) {
|
||||
};
|
||||
|
||||
var multiple = function (node, file) {
|
||||
var uid = file.generateUid("arr");
|
||||
var uid = file.generateUidIdentifier("arr");
|
||||
|
||||
var container = util.template("array-comprehension-container", {
|
||||
KEY: uid
|
||||
@@ -73,8 +73,8 @@ exports._build = function (node, buildBody) {
|
||||
exports.ComprehensionExpression = function (node, parent, file) {
|
||||
if (node.generator) return;
|
||||
|
||||
if (node.blocks.length === 1 && t.isArrayExpression(node.blocks[0].right)) {
|
||||
return singleArrayExpression(node);
|
||||
if (node.blocks.length === 1) {
|
||||
return single(node, file);
|
||||
} else {
|
||||
return multiple(node, file);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// https://github.com/rwaldron/exponentiation-operator
|
||||
|
||||
var t = require("../../types");
|
||||
var pow = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
|
||||
|
||||
exports.AssignmentExpression = function (node) {
|
||||
if (node.operator !== "**=") return;
|
||||
node.operator = "=";
|
||||
node.right = t.callExpression(pow, [node.left, node.right]);
|
||||
};
|
||||
|
||||
exports.BinaryExpression = function (node) {
|
||||
if (node.operator !== "**") return;
|
||||
|
||||
return t.callExpression(pow, [node.left, node.right]);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
var arrayComprehension = require("./array-comprehension");
|
||||
var arrayComprehension = require("./es7-array-comprehension");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.ComprehensionExpression = function (node) {
|
||||
41
lib/6to5/transformation/transformers/es7-object-spread.js
Normal file
41
lib/6to5/transformation/transformers/es7-object-spread.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// https://github.com/sebmarkbage/ecmascript-rest-spread
|
||||
|
||||
var t = require("../../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.ObjectExpression = function (node) {
|
||||
var hasSpread = false;
|
||||
_.each(node.properties, function (prop) {
|
||||
if (t.isSpreadProperty(prop)) {
|
||||
hasSpread = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!hasSpread) return;
|
||||
|
||||
var args = [];
|
||||
var props = [];
|
||||
|
||||
var push = function () {
|
||||
if (!props.length) return;
|
||||
args.push(t.objectExpression(props));
|
||||
props = [];
|
||||
};
|
||||
|
||||
_.each(node.properties, function (prop) {
|
||||
if (t.isSpreadProperty(prop)) {
|
||||
push();
|
||||
args.push(prop.argument);
|
||||
} else {
|
||||
props.push(prop);
|
||||
}
|
||||
});
|
||||
|
||||
push();
|
||||
|
||||
if (!t.isObjectExpression(args[0])) {
|
||||
args.unshift(t.objectExpression([]));
|
||||
}
|
||||
|
||||
return t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("assign")), args);
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
var regenerator = require("regenerator-6to5");
|
||||
|
||||
module.exports = regenerator.transform;
|
||||
34
lib/6to5/transformation/transformers/react.js
vendored
34
lib/6to5/transformation/transformers/react.js
vendored
@@ -106,11 +106,37 @@ exports.XJSElement = {
|
||||
exit: function (node) {
|
||||
var callExpr = node.openingElement;
|
||||
|
||||
var childrenToRender = node.children.filter(function(child) {
|
||||
return !(t.isLiteral(child) && _.isString(child.value) && child.value.match(/^[ \t]*[\r\n][ \t\r\n]*$/));
|
||||
});
|
||||
_.each(node.children, function (child) {
|
||||
if (t.isLiteral(child)) {
|
||||
var lines = child.value.split(/\r\n|\n|\r/);
|
||||
|
||||
_.each(lines, function (line, i) {
|
||||
var isFirstLine = i === 0;
|
||||
var isLastLine = i === lines.length - 1;
|
||||
|
||||
// replace rendered whitespace tabs with spaces
|
||||
var trimmedLine = line.replace(/\t/g, ' ');
|
||||
|
||||
// trim whitespace touching a newline
|
||||
if (!isFirstLine) {
|
||||
trimmedLine = trimmedLine.replace(/^[ ]+/, '');
|
||||
}
|
||||
|
||||
// trim whitespace touching an endline
|
||||
if (!isLastLine) {
|
||||
trimmedLine = trimmedLine.replace(/[ ]+$/, '');
|
||||
}
|
||||
|
||||
if (trimmedLine) {
|
||||
callExpr.arguments.push(t.literal(trimmedLine));
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
} else if (t.isXJSEmptyExpression(child)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_.each(childrenToRender, function (child) {
|
||||
callExpr.arguments.push(child);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.Function = function (node, parent, file) {
|
||||
if (!node.rest) return;
|
||||
|
||||
var rest = node.rest;
|
||||
delete node.rest;
|
||||
|
||||
var templateName = "arguments-slice-assign";
|
||||
if (node.params.length) templateName += "-arg";
|
||||
|
||||
t.ensureBlock(node);
|
||||
|
||||
var template = util.template(templateName, {
|
||||
SLICE_KEY: file.addDeclaration("slice"),
|
||||
VARIABLE_NAME: rest,
|
||||
SLICE_ARG: t.literal(node.params.length)
|
||||
});
|
||||
|
||||
template.declarations[0].init.arguments[0]._ignoreAliasFunctions = true;
|
||||
|
||||
node.body.body.unshift(template);
|
||||
};
|
||||
@@ -29,26 +29,33 @@ function traverse(parent, callbacks, opts) {
|
||||
// normalise callbacks
|
||||
if (_.isFunction(callbacks)) callbacks = { enter: callbacks };
|
||||
|
||||
_.each(keys, function (key) {
|
||||
for (var i in keys) {
|
||||
var key = keys[i];
|
||||
var nodes = parent[key];
|
||||
if (!nodes) return;
|
||||
if (!nodes) continue;
|
||||
|
||||
var updated = false;
|
||||
|
||||
var handle = function (obj, key) {
|
||||
var node = obj[key];
|
||||
if (!node) return;
|
||||
|
||||
// type is blacklisted
|
||||
if (_.contains(blacklistTypes, node.type)) return;
|
||||
if (blacklistTypes.indexOf(node.type) > -1) return;
|
||||
|
||||
// replace node
|
||||
var maybeReplace = function (result) {
|
||||
if (result === false) return;
|
||||
if (result != null) node = obj[key] = result;
|
||||
|
||||
if (result != null) {
|
||||
updated = true;
|
||||
node = obj[key] = result;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
var opts2 = _.clone(opts);
|
||||
if (t.isScope(node)) opts2.scope = new Scope(opts.scope, node);
|
||||
var opts2 = { scope: opts.scope, blacklist: opts.blacklist };
|
||||
if (t.isScope(node)) opts2.scope = new Scope(node, opts.scope);
|
||||
|
||||
// enter
|
||||
if (callbacks.enter) {
|
||||
@@ -69,22 +76,24 @@ function traverse(parent, callbacks, opts) {
|
||||
};
|
||||
|
||||
if (_.isArray(nodes)) {
|
||||
_.each(nodes, function (node, i) {
|
||||
for (i in nodes) {
|
||||
handle(nodes, i);
|
||||
});
|
||||
}
|
||||
|
||||
parent[key] = _.flatten(parent[key]);
|
||||
if (updated) parent[key] = _.flatten(parent[key]);
|
||||
} else {
|
||||
handle(parent, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
traverse.removeProperties = function (tree) {
|
||||
var clear = function (node) {
|
||||
delete node._scopeReferences;
|
||||
delete node._declarations;
|
||||
delete node.extendedRange;
|
||||
delete node._scopeIds;
|
||||
delete node._parent;
|
||||
delete node._scope;
|
||||
delete node.tokens;
|
||||
delete node.range;
|
||||
delete node.start;
|
||||
|
||||
@@ -4,54 +4,124 @@ var traverse = require("./index");
|
||||
var t = require("../types");
|
||||
var _ = require("lodash");
|
||||
|
||||
function Scope(parent, block) {
|
||||
var FOR_KEYS = ["left", "init"];
|
||||
|
||||
/**
|
||||
* This searches the current "scope" and collects all references/declarations
|
||||
* within.
|
||||
*
|
||||
* @param {Node} block
|
||||
* @param {Scope} [parent]
|
||||
*/
|
||||
|
||||
function Scope(block, parent) {
|
||||
this.parent = parent;
|
||||
this.block = block;
|
||||
this.ids = this.getIds();
|
||||
|
||||
this.getIds();
|
||||
this.references = this.getReferences();
|
||||
}
|
||||
|
||||
Scope.prototype.getIds = function () {
|
||||
var block = this.block;
|
||||
if (block._scopeIds) return block._scopeIds;
|
||||
|
||||
var self = this;
|
||||
var ids = block._scopeIds = {};
|
||||
|
||||
if (t.isBlockStatement(block)) {
|
||||
_.each(block.body, function (node) {
|
||||
if (t.isVariableDeclaration(node) && node.kind !== "var") {
|
||||
self.add(node, ids);
|
||||
}
|
||||
});
|
||||
} else if (t.isProgram(block) || t.isFunction(block)) {
|
||||
traverse(block, function (node, parent) {
|
||||
if (parent !== block && t.isVariableDeclaration(node) && node.kind !== "var") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.isDeclaration(node)) {
|
||||
self.add(node, ids);
|
||||
} else if (t.isFunction(node)) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else if (t.isCatchClause(block)) {
|
||||
self.add(block.param, ids);
|
||||
}
|
||||
|
||||
if (t.isFunction(block)) {
|
||||
_.each(block.params, function (param) {
|
||||
self.add(param, ids);
|
||||
});
|
||||
}
|
||||
|
||||
return ids;
|
||||
Scope.add = function (node, references) {
|
||||
if (!node) return;
|
||||
_.merge(references, t.getIds(node, true));
|
||||
};
|
||||
|
||||
Scope.prototype.add = function (node, ids) {
|
||||
_.merge(ids || this.ids, t.getIds(node, true));
|
||||
Scope.prototype.getReferences = function () {
|
||||
var block = this.block;
|
||||
if (block._scopeReferences) return block._scopeReferences;
|
||||
|
||||
var references = block._scopeReferences = {};
|
||||
|
||||
var add = function (node) {
|
||||
Scope.add(node, references);
|
||||
};
|
||||
|
||||
// ForStatement - left, init
|
||||
|
||||
if (t.isFor(block)) {
|
||||
_.each(FOR_KEYS, function (key) {
|
||||
var node = block[key];
|
||||
if (t.isLet(node)) add(node);
|
||||
});
|
||||
|
||||
block = block.body;
|
||||
}
|
||||
|
||||
// Program, BlockStatement - let variables
|
||||
|
||||
if (t.isBlockStatement(block) || t.isProgram(block)) {
|
||||
_.each(block.body, function (node) {
|
||||
// check for non-var `VariableDeclaration`s
|
||||
if (t.isLet(node)) add(node);
|
||||
});
|
||||
}
|
||||
|
||||
// CatchClause - param
|
||||
|
||||
if (t.isCatchClause(block)) {
|
||||
add(block.param);
|
||||
}
|
||||
|
||||
// Program, Function - var variables
|
||||
|
||||
if (t.isProgram(block) || t.isFunction(block)) {
|
||||
traverse(block, function (node, parent, scope) {
|
||||
if (t.isFor(node)) {
|
||||
_.each(FOR_KEYS, function (key) {
|
||||
var declar = node[key];
|
||||
if (t.isVar(declar)) add(declar);
|
||||
});
|
||||
}
|
||||
|
||||
// this block is a function so we'll stop since none of the variables
|
||||
// declared within are accessible
|
||||
if (t.isFunction(node)) return false;
|
||||
|
||||
if (t.isIdentifier(node) && t.isReferenced(node, parent) && !scope.has(node.name)) {
|
||||
add(node);
|
||||
}
|
||||
|
||||
// we've ran into a declaration!
|
||||
// we'll let the BlockStatement scope deal with `let` declarations
|
||||
if (t.isDeclaration(node) && !t.isLet(node)) {
|
||||
add(node);
|
||||
}
|
||||
}, { scope: this });
|
||||
}
|
||||
|
||||
// Function - params, rest
|
||||
|
||||
if (t.isFunction(block)) {
|
||||
add(block.rest);
|
||||
_.each(block.params, function (param) {
|
||||
add(param);
|
||||
});
|
||||
}
|
||||
|
||||
return references;
|
||||
};
|
||||
|
||||
Scope.prototype.push = function (name, id, init) {
|
||||
var block = this.block;
|
||||
|
||||
if (t.isFor(block) || t.isCatchClause(block) || t.isFunction(block)) {
|
||||
t.ensureBlock(block);
|
||||
block = block.body;
|
||||
}
|
||||
|
||||
if (t.isBlockStatement(block) || t.isProgram(block)) {
|
||||
block._declarations = block._declarations || {};
|
||||
block._declarations[name] = {
|
||||
id: id,
|
||||
init: init
|
||||
};
|
||||
} else {
|
||||
throw new TypeError("cannot add a declaration here in node type " + block.type);
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.add = function (node) {
|
||||
Scope.add(node, this.references);
|
||||
};
|
||||
|
||||
Scope.prototype.get = function (id) {
|
||||
@@ -59,7 +129,7 @@ Scope.prototype.get = function (id) {
|
||||
};
|
||||
|
||||
Scope.prototype.getOwn = function (id) {
|
||||
return _.has(this.ids, id) && this.ids[id];
|
||||
return _.has(this.references, id) && this.references[id];
|
||||
};
|
||||
|
||||
Scope.prototype.parentGet = function (id) {
|
||||
|
||||
@@ -35,9 +35,9 @@
|
||||
"ClassDeclaration": ["Statement", "Declaration", "Class"],
|
||||
"ClassExpression": ["Class"],
|
||||
|
||||
"ForOfStatement": ["Statement", "For"],
|
||||
"ForInStatement": ["Statement", "For"],
|
||||
"ForStatement": ["Statement", "For"],
|
||||
"ForOfStatement": ["Statement", "For", "Scope"],
|
||||
"ForInStatement": ["Statement", "For", "Scope"],
|
||||
"ForStatement": ["Statement", "For", "Scope"],
|
||||
|
||||
"ObjectPattern": ["Pattern"],
|
||||
"ArrayPattern": ["Pattern"],
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
"Property": ["kind", "key", "value", "computed"],
|
||||
"ReturnStatement": ["argument"],
|
||||
"SequenceExpression": ["expressions"],
|
||||
"ThrowExpression": ["argument"],
|
||||
"UnaryExpression": ["operator", "argument", "prefix"],
|
||||
"VariableDeclaration": ["kind", "declarations"],
|
||||
"VariableDeclarator": ["id", "init"]
|
||||
"VariableDeclarator": ["id", "init"],
|
||||
"YieldExpression": ["argument", "delegate"]
|
||||
}
|
||||
|
||||
@@ -2,14 +2,25 @@ var _ = require("lodash");
|
||||
|
||||
var t = exports;
|
||||
|
||||
var addAssert = function (type, is) {
|
||||
t["assert" + type] = function (node, opts) {
|
||||
opts = opts || {};
|
||||
if (!is(node, opts)) {
|
||||
throw new Error("Expected type " + JSON.stringify(type) + " with option " + JSON.stringify(opts));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
t.VISITOR_KEYS = require("./visitor-keys");
|
||||
|
||||
_.each(t.VISITOR_KEYS, function (keys, type) {
|
||||
t["is" + type] = function (node, opts) {
|
||||
var is = t["is" + type] = function (node, opts) {
|
||||
return node && node.type === type && t.shallowEqual(node, opts);
|
||||
};
|
||||
|
||||
addAssert(type, is);
|
||||
});
|
||||
|
||||
//
|
||||
@@ -43,13 +54,23 @@ _.each(t.ALIAS_KEYS, function (aliases, type) {
|
||||
_.each(_aliases, function (types, type) {
|
||||
t[type.toUpperCase() + "_TYPES"] = types;
|
||||
|
||||
t["is" + type] = function (node, opts) {
|
||||
var is = t["is" + type] = function (node, opts) {
|
||||
return node && _.contains(types, node.type) && t.shallowEqual(node, opts);
|
||||
};
|
||||
|
||||
addAssert(type, is);
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
t.isExpression = function (node) {
|
||||
return !t.isStatement(node);
|
||||
};
|
||||
|
||||
addAssert("Expression", t.isExpression);
|
||||
|
||||
//
|
||||
|
||||
t.shallowEqual = function (actual, expected) {
|
||||
var same = true;
|
||||
|
||||
@@ -66,10 +87,23 @@ t.shallowEqual = function (actual, expected) {
|
||||
|
||||
//
|
||||
|
||||
t.isDynamic = function (node) {
|
||||
if (t.isIdentifier(node) || t.isLiteral(node) || t.isThisExpression(node)) {
|
||||
return false;
|
||||
} else if (t.isMemberExpression(node)) {
|
||||
return t.isDynamic(node.object) || t.isDynamic(node.property);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
t.isReferenced = function (node, parent) {
|
||||
// we're a property key so we aren't referenced
|
||||
if (t.isProperty(parent) && parent.key === node) return false;
|
||||
|
||||
// we're a variable declarator id so we aren't referenced
|
||||
if (t.isVariableDeclarator(parent) && parent.id === node) return false;
|
||||
|
||||
var isMemberExpression = t.isMemberExpression(parent);
|
||||
|
||||
// we're in a member expression and we're the computed property so we're referenced
|
||||
@@ -161,7 +195,7 @@ t.toBlock = function (node, parent) {
|
||||
t.getIds = function (node, map, ignoreTypes) {
|
||||
ignoreTypes = ignoreTypes || [];
|
||||
|
||||
var search = [node];
|
||||
var search = [].concat(node);
|
||||
var ids = {};
|
||||
|
||||
while (search.length) {
|
||||
@@ -206,13 +240,37 @@ t.getIds.arrays = {
|
||||
ObjectPattern: "properties"
|
||||
};
|
||||
|
||||
t.isLet = function (node) {
|
||||
return t.isVariableDeclaration(node) && (node.kind !== "var" || node._let);
|
||||
};
|
||||
|
||||
t.isVar = function (node) {
|
||||
return t.isVariableDeclaration(node, { kind: "var" }) && !node._let;
|
||||
};
|
||||
|
||||
t.removeComments = function (child) {
|
||||
delete child.leadingComments;
|
||||
delete child.trailingComments;
|
||||
return child;
|
||||
};
|
||||
|
||||
t.inheritsComments = function (child, parent) {
|
||||
child.leadingComments = _.compact([].concat(child.leadingComments, parent.leadingComments));
|
||||
child.trailingComments = _.compact([].concat(child.trailingComments, parent.trailingComments));
|
||||
return child;
|
||||
};
|
||||
|
||||
t.removeComments = function (node) {
|
||||
delete node.leadingComments;
|
||||
delete node.trailingComments;
|
||||
};
|
||||
|
||||
t.inherits = function (child, parent) {
|
||||
child.loc = parent.loc;
|
||||
child.end = parent.end;
|
||||
child.range = parent.range;
|
||||
child.start = parent.start;
|
||||
child.leadingComments = parent.leadingComments;
|
||||
child.trailingComments = parent.trailingComments;
|
||||
child.loc = parent.loc;
|
||||
child.end = parent.end;
|
||||
child.range = parent.range;
|
||||
child.start = parent.start;
|
||||
t.inheritsComments(child, parent);
|
||||
return child;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,76 +1,78 @@
|
||||
{
|
||||
"ArrayExpression": ["elements"],
|
||||
"ArrayPattern": ["elements"],
|
||||
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
|
||||
"AssignmentExpression": ["left", "right"],
|
||||
"AwaitExpression": ["argument"],
|
||||
"BinaryExpression": ["left", "right"],
|
||||
"BlockStatement": ["body"],
|
||||
"BreakStatement": ["label"],
|
||||
"CallExpression": ["callee", "arguments"],
|
||||
"CatchClause": ["param", "body"],
|
||||
"ClassBody": ["body"],
|
||||
"ClassDeclaration": ["id", "body", "superClass"],
|
||||
"ClassExpression": ["id", "body", "superClass"],
|
||||
"ComprehensionBlock": ["left", "right", "body"],
|
||||
"ComprehensionExpression": ["filter", "blocks", "body"],
|
||||
"ConditionalExpression": ["test", "consequent", "alternate"],
|
||||
"ContinueStatement": ["label"],
|
||||
"DebuggerStatement": [],
|
||||
"DoWhileStatement": ["body", "test"],
|
||||
"EmptyStatement": [],
|
||||
"ExportBatchSpecifier": [],
|
||||
"ExportDeclaration": ["declaration", "specifiers", "source"],
|
||||
"ExportSpecifier": ["id", "name"],
|
||||
"ExpressionStatement": ["expression"],
|
||||
"File": ["program"],
|
||||
"ForInStatement": ["left", "right", "body"],
|
||||
"ForOfStatement": ["left", "right", "body"],
|
||||
"ForStatement": ["init", "test", "update", "body"],
|
||||
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body"],
|
||||
"FunctionExpression": ["id", "params", "defaults", "rest", "body"],
|
||||
"Identifier": [],
|
||||
"IfStatement": ["test", "consequent", "alternate"],
|
||||
"ImportBatchSpecifier": ["id"],
|
||||
"ImportDeclaration": ["specifiers", "source"],
|
||||
"ImportSpecifier": ["id", "name"],
|
||||
"LabeledStatement": ["label", "body"],
|
||||
"Literal": [],
|
||||
"LogicalExpression": ["left", "right"],
|
||||
"MemberExpression": ["object", "property"],
|
||||
"MethodDefinition": ["key", "value"],
|
||||
"NewExpression": ["callee", "arguments"],
|
||||
"ObjectExpression": ["properties"],
|
||||
"ObjectPattern": ["properties"],
|
||||
"ParenthesizedExpression": ["expression"],
|
||||
"Program": ["body"],
|
||||
"Property": ["key", "value"],
|
||||
"ReturnStatement": ["argument"],
|
||||
"SequenceExpression": ["expressions"],
|
||||
"SpreadElement": ["argument"],
|
||||
"SwitchCase": ["test", "consequent"],
|
||||
"SwitchStatement": ["discriminant", "cases"],
|
||||
"TaggedTemplateExpression": ["tag", "quasi"],
|
||||
"TemplateElement": [],
|
||||
"TemplateLiteral": ["quasis", "expressions"],
|
||||
"ThisExpression": [],
|
||||
"ThrowStatement": ["argument"],
|
||||
"TryStatement": ["block", "handlers", "handler", "guardedHandlers", "finalizer"],
|
||||
"UnaryExpression": ["argument"],
|
||||
"UpdateExpression": ["argument"],
|
||||
"VariableDeclaration": ["declarations"],
|
||||
"VariableDeclarator": ["id", "init"],
|
||||
"WhileStatement": ["test", "body"],
|
||||
"WithStatement": ["object", "body"],
|
||||
"XJSAttribute": ["name", "value"],
|
||||
"XJSClosingElement": ["name"],
|
||||
"XJSElement": ["openingElement", "closingElement", "children"],
|
||||
"XJSEmptyExpression": [],
|
||||
"XJSExpressionContainer": ["expression"],
|
||||
"XJSIdentifier": [],
|
||||
"XJSMemberExpression": ["object", "property"],
|
||||
"XJSNamespacedName": ["namespace", "name"],
|
||||
"XJSOpeningElement": ["name", "attributes"],
|
||||
"XJSSpreadAttribute": ["argument"],
|
||||
"YieldExpression": ["argument"]
|
||||
"ArrayExpression": ["elements"],
|
||||
"ArrayPattern": ["elements"],
|
||||
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
|
||||
"AssignmentExpression": ["left", "right"],
|
||||
"AwaitExpression": ["argument"],
|
||||
"BinaryExpression": ["left", "right"],
|
||||
"BlockStatement": ["body"],
|
||||
"BreakStatement": ["label"],
|
||||
"CallExpression": ["callee", "arguments"],
|
||||
"CatchClause": ["param", "body"],
|
||||
"ClassBody": ["body"],
|
||||
"ClassDeclaration": ["id", "body", "superClass"],
|
||||
"ClassExpression": ["id", "body", "superClass"],
|
||||
"ComprehensionBlock": ["left", "right", "body"],
|
||||
"ComprehensionExpression": ["filter", "blocks", "body"],
|
||||
"ConditionalExpression": ["test", "consequent", "alternate"],
|
||||
"ContinueStatement": ["label"],
|
||||
"DebuggerStatement": [],
|
||||
"DoWhileStatement": ["body", "test"],
|
||||
"EmptyStatement": [],
|
||||
"ExportBatchSpecifier": [],
|
||||
"ExportDeclaration": ["declaration", "specifiers", "source"],
|
||||
"ExportSpecifier": ["id", "name"],
|
||||
"ExpressionStatement": ["expression"],
|
||||
"File": ["program"],
|
||||
"ForInStatement": ["left", "right", "body"],
|
||||
"ForOfStatement": ["left", "right", "body"],
|
||||
"ForStatement": ["init", "test", "update", "body"],
|
||||
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body"],
|
||||
"FunctionExpression": ["id", "params", "defaults", "rest", "body"],
|
||||
"Identifier": [],
|
||||
"IfStatement": ["test", "consequent", "alternate"],
|
||||
"ImportBatchSpecifier": ["id"],
|
||||
"ImportDeclaration": ["specifiers", "source"],
|
||||
"ImportSpecifier": ["id", "name"],
|
||||
"LabeledStatement": ["label", "body"],
|
||||
"Literal": [],
|
||||
"LogicalExpression": ["left", "right"],
|
||||
"MemberExpression": ["object", "property"],
|
||||
"MethodDefinition": ["key", "value"],
|
||||
"NewExpression": ["callee", "arguments"],
|
||||
"ObjectExpression": ["properties"],
|
||||
"ObjectPattern": ["properties"],
|
||||
"ParenthesizedExpression": ["expression"],
|
||||
"Program": ["body"],
|
||||
"Property": ["key", "value"],
|
||||
"ReturnStatement": ["argument"],
|
||||
"SequenceExpression": ["expressions"],
|
||||
"SpreadElement": ["argument"],
|
||||
"SpreadProperty": ["argument"],
|
||||
"SwitchCase": ["test", "consequent"],
|
||||
"SwitchStatement": ["discriminant", "cases"],
|
||||
"TaggedTemplateExpression": ["tag", "quasi"],
|
||||
"TemplateElement": [],
|
||||
"TemplateLiteral": ["quasis", "expressions"],
|
||||
"ThisExpression": [],
|
||||
"ThrowStatement": ["argument"],
|
||||
"TryStatement": ["block", "handlers", "handler", "guardedHandlers", "finalizer"],
|
||||
"UnaryExpression": ["argument"],
|
||||
"UpdateExpression": ["argument"],
|
||||
"VariableDeclaration": ["declarations"],
|
||||
"VariableDeclarator": ["id", "init"],
|
||||
"VirtualPropertyExpression": ["object", "property"],
|
||||
"WhileStatement": ["test", "body"],
|
||||
"WithStatement": ["object", "body"],
|
||||
"XJSAttribute": ["name", "value"],
|
||||
"XJSClosingElement": ["name"],
|
||||
"XJSElement": ["openingElement", "closingElement", "children"],
|
||||
"XJSEmptyExpression": [],
|
||||
"XJSExpressionContainer": ["expression"],
|
||||
"XJSIdentifier": [],
|
||||
"XJSMemberExpression": ["object", "property"],
|
||||
"XJSNamespacedName": ["namespace", "name"],
|
||||
"XJSOpeningElement": ["name", "attributes"],
|
||||
"XJSSpreadAttribute": ["argument"],
|
||||
"YieldExpression": ["argument"]
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ exports.canCompile = function (filename, altExts) {
|
||||
return _.contains(exts, ext);
|
||||
};
|
||||
|
||||
exports.isInteger = function (i) {
|
||||
return _.isNumber(i) && i % 1 === 0;
|
||||
};
|
||||
|
||||
exports.resolve = function (loc) {
|
||||
try {
|
||||
return require.resolve(loc);
|
||||
@@ -33,6 +37,21 @@ exports.list = function (val) {
|
||||
return val ? val.split(",") : [];
|
||||
};
|
||||
|
||||
exports.regexify = function (val) {
|
||||
if (!val) return new RegExp(/.^/);
|
||||
if (_.isArray(val)) val = val.join("|");
|
||||
if (_.isString(val)) return new RegExp(val);
|
||||
if (_.isRegExp(val)) return val;
|
||||
throw new TypeError("illegal type for regexify");
|
||||
};
|
||||
|
||||
exports.arrayify = function (val) {
|
||||
if (!val) return [];
|
||||
if (_.isString(val)) return exports.list(val);
|
||||
if (_.isArray(val)) return val;
|
||||
throw new TypeError("illegal type for arrayify");
|
||||
};
|
||||
|
||||
exports.getUid = function (parent, file) {
|
||||
var node;
|
||||
|
||||
@@ -46,7 +65,7 @@ exports.getUid = function (parent, file) {
|
||||
|
||||
if (t.isIdentifier(node)) id = node.name;
|
||||
|
||||
return t.identifier(file.generateUid(id));
|
||||
return file.generateUidIdentifier(id);
|
||||
};
|
||||
|
||||
exports.isAbsolute = function (loc) {
|
||||
@@ -102,8 +121,13 @@ exports.buildDefineProperties = function (mutatorMap) {
|
||||
if (key[0] === "_") return;
|
||||
|
||||
node = _.clone(node);
|
||||
var inheritNode = node;
|
||||
if (t.isMethodDefinition(node)) node = node.value;
|
||||
mapNode.properties.push(t.property("init", t.identifier(key), node));
|
||||
|
||||
var prop = t.property("init", t.identifier(key), node);
|
||||
t.inheritsComments(prop, inheritNode);
|
||||
t.removeComments(inheritNode);
|
||||
mapNode.properties.push(prop);
|
||||
});
|
||||
|
||||
objExpr.properties.push(propNode);
|
||||
@@ -123,23 +147,17 @@ exports.template = function (name, nodes, keepExpression) {
|
||||
|
||||
template = _.cloneDeep(template);
|
||||
|
||||
var inherits = false;
|
||||
if (nodes) {
|
||||
inherits = nodes.inherits;
|
||||
delete nodes.inherits;
|
||||
|
||||
if (!_.isEmpty(nodes)) {
|
||||
traverse(template, function (node) {
|
||||
if (t.isIdentifier(node) && _.has(nodes, node.name)) {
|
||||
var newNode = nodes[node.name];
|
||||
if (_.isString(newNode)) {
|
||||
node.name = newNode;
|
||||
} else {
|
||||
return newNode;
|
||||
}
|
||||
if (!_.isEmpty(nodes)) {
|
||||
traverse(template, function (node) {
|
||||
if (t.isIdentifier(node) && _.has(nodes, node.name)) {
|
||||
var newNode = nodes[node.name];
|
||||
if (_.isString(newNode)) {
|
||||
node.name = newNode;
|
||||
} else {
|
||||
return newNode;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var node = template.body[0];
|
||||
@@ -150,10 +168,6 @@ exports.template = function (name, nodes, keepExpression) {
|
||||
if (t.isParenthesizedExpression(node)) node = node.expression;
|
||||
}
|
||||
|
||||
if (inherits) {
|
||||
node = t.inherits(node, inherits);
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
@@ -204,7 +218,7 @@ exports.parse = function (opts, code, callback) {
|
||||
var ast = acorn.parse(code, {
|
||||
allowReturnOutsideFunction: true,
|
||||
preserveParens: true,
|
||||
ecmaVersion: Infinity,
|
||||
ecmaVersion: opts.experimental ? 7 : 6,
|
||||
strictMode: true,
|
||||
onComment: comments,
|
||||
locations: true,
|
||||
@@ -277,9 +291,5 @@ try {
|
||||
} catch (err) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
|
||||
Object.defineProperty(exports, "templates", {
|
||||
get: function () {
|
||||
return exports.templates = loadTemplates();
|
||||
}
|
||||
});
|
||||
exports.templates = loadTemplates();
|
||||
}
|
||||
|
||||
18
package.json
18
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "6to5",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "1.12.9",
|
||||
"version": "1.13.12",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://github.com/6to5/6to5",
|
||||
"repository": {
|
||||
@@ -35,21 +35,21 @@
|
||||
"test": "make test"
|
||||
},
|
||||
"dependencies": {
|
||||
"ast-types": "~0.6.0",
|
||||
"ast-types": "0.6.5",
|
||||
"commander": "2.5.0",
|
||||
"fs-readdir-recursive": "0.0.2",
|
||||
"fs-readdir-recursive": "0.1.0",
|
||||
"lodash": "2.4.1",
|
||||
"mkdirp": "0.5.0",
|
||||
"es6-shim": "0.20.2",
|
||||
"es6-shim": "0.21.0",
|
||||
"es6-symbol": "0.1.1",
|
||||
"regexpu": "0.3.0",
|
||||
"source-map": "0.1.40",
|
||||
"regenerator-6to5": "https://github.com/6to5/regenerator-6to5/archive/75925940a7bb67d1ee8afec36b6d6eec072fb47c.tar.gz",
|
||||
"chokidar": "0.10.5",
|
||||
"chokidar": "0.11.1",
|
||||
"source-map-support": "0.2.8",
|
||||
"esutils": "1.1.4",
|
||||
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/a6c34ba73e215bd16ee585f6794f6a6587820c58.tar.gz",
|
||||
"estraverse": "^1.7.0"
|
||||
"esutils": "1.1.6",
|
||||
"acorn-6to5": "0.9.1-7",
|
||||
"estraverse": "1.8.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"
|
||||
);
|
||||
}
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user