Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fea487bf91 | ||
|
|
ff2cbd5a2e | ||
|
|
12e01f9e71 | ||
|
|
f62436909d | ||
|
|
e42c1adeb6 | ||
|
|
e30dbbab94 | ||
|
|
e3daa28e60 | ||
|
|
9e5d94126c | ||
|
|
95798bee0b | ||
|
|
63f25ab038 | ||
|
|
27a8f2d2ea | ||
|
|
78434bb404 | ||
|
|
82833a8901 | ||
|
|
93d5288d71 | ||
|
|
5d3074b460 | ||
|
|
a57475abc9 | ||
|
|
09e68d8d46 | ||
|
|
ee850c3aeb | ||
|
|
ff5a149cec | ||
|
|
957118fb41 | ||
|
|
e7ad0a9741 | ||
|
|
24f4b041c7 | ||
|
|
4c77d04b56 | ||
|
|
e945f0d10f | ||
|
|
fb04b2561f | ||
|
|
a4f8b41507 | ||
|
|
1fb6018e9c | ||
|
|
bca233d22c | ||
|
|
c78703e194 | ||
|
|
43fdbe3d6c | ||
|
|
8650ca7d55 | ||
|
|
3a0c226a34 | ||
|
|
73e8bdd048 | ||
|
|
e7c52a734e | ||
|
|
5a81b02569 | ||
|
|
999baf2888 | ||
|
|
70b25e8942 | ||
|
|
2ddbd4eecc | ||
|
|
7520807df3 | ||
|
|
974b71bcc3 | ||
|
|
0aee3c06ec | ||
|
|
a4382580fc | ||
|
|
166b2eda87 | ||
|
|
83c23d266f | ||
|
|
a9db70b60d | ||
|
|
5d90c442cb | ||
|
|
32606ddb93 | ||
|
|
330f6910c6 | ||
|
|
4ca8a0e6e2 | ||
|
|
f097ddeac3 | ||
|
|
1eb53dd13a | ||
|
|
75b5f32e7a | ||
|
|
f753cf4845 | ||
|
|
9a569f64da | ||
|
|
8efeae80af | ||
|
|
4df9cf6c05 | ||
|
|
7729cb4b68 | ||
|
|
307ffcd107 | ||
|
|
751557aef1 | ||
|
|
3f146b54ff | ||
|
|
19a173c622 | ||
|
|
89bcb307a2 | ||
|
|
ded1e02da7 | ||
|
|
564ba67190 | ||
|
|
00c964ed19 | ||
|
|
3ab88e02c7 | ||
|
|
bb2fc830eb | ||
|
|
c6a542fd1d | ||
|
|
553eb2d45e | ||
|
|
b5f3c3f4cc | ||
|
|
5d83638583 | ||
|
|
f7186980e5 | ||
|
|
0eaaaa503e | ||
|
|
51dff364db | ||
|
|
dc6129eb6a | ||
|
|
5b84b9c867 | ||
|
|
04c3027f4d | ||
|
|
95e2345b19 | ||
|
|
eafb02be31 | ||
|
|
b91997354c | ||
|
|
4b8039a00c | ||
|
|
0a0931dc2e | ||
|
|
24ace3c8c2 | ||
|
|
372c06eb80 | ||
|
|
b8121ed4d0 | ||
|
|
1f79445ee5 | ||
|
|
cb46ca60af | ||
|
|
24c0c7679f | ||
|
|
687b0f3180 | ||
|
|
e6855b974b | ||
|
|
a808742c19 | ||
|
|
d7ec337567 | ||
|
|
845f1ce65e | ||
|
|
c3f4091b6d | ||
|
|
edb880f87c | ||
|
|
e8741daee3 | ||
|
|
88563a0c26 | ||
|
|
ccd7a6560c | ||
|
|
c340597fdb | ||
|
|
e498358125 | ||
|
|
c5913564f8 | ||
|
|
662bddbaca | ||
|
|
8f540dfff3 | ||
|
|
1265bc5a92 | ||
|
|
e677c72d58 | ||
|
|
8ca854156a | ||
|
|
81ae656358 | ||
|
|
f2981b7e95 | ||
|
|
99b2e00d33 | ||
|
|
25232d3141 | ||
|
|
5b9878451a | ||
|
|
23d6fb6bb1 | ||
|
|
8d1b5c8ccb | ||
|
|
10bd7d1b91 |
22
.eslintrc
Normal file
22
.eslintrc
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"strict": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unused-vars": 0,
|
||||
"curly": 0,
|
||||
"no-multi-spaces": 0,
|
||||
"key-spacing": 0,
|
||||
"no-return-assign": 0,
|
||||
"consistent-return": 0,
|
||||
"no-shadow": 0,
|
||||
"no-comma-dangle": 0,
|
||||
"no-use-before-define": 0,
|
||||
"no-empty": 0,
|
||||
"new-parens": 0,
|
||||
"no-cond-assign": 0
|
||||
},
|
||||
"env": {
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
27
.jshintrc
27
.jshintrc
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"esnext": true,
|
||||
"indent": 2,
|
||||
"freeze": true,
|
||||
"validthis": true,
|
||||
"camelcase": true,
|
||||
"unused": true,
|
||||
"eqnull": true,
|
||||
"newcap": true,
|
||||
"supernew": true,
|
||||
"noyield": true,
|
||||
"evil": true,
|
||||
"node": true,
|
||||
"boss": true,
|
||||
"expr": true,
|
||||
"undef": true,
|
||||
"maxparams": 5,
|
||||
"maxdepth": 4,
|
||||
|
||||
"globals": {
|
||||
"window": true,
|
||||
"suite": true,
|
||||
"set": true,
|
||||
"before": true,
|
||||
"bench": true
|
||||
}
|
||||
}
|
||||
54
CHANGELOG.md
54
CHANGELOG.md
@@ -13,6 +13,60 @@ _Note: Gaps between patch versions are faulty/broken releases._
|
||||
|
||||
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
|
||||
|
||||
## 4.6.3
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix `arguments` being incorrectly aliased in arrow function rest parameter optimisation.
|
||||
* Make deoptimisation trigger safer.
|
||||
* **New Feature**
|
||||
* Flow types are now retained when blacklisting the `flow` transformer.
|
||||
|
||||
## 4.6.1
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix generators in template directory being transformed.
|
||||
* Fix exposure of `util` for plugins.
|
||||
|
||||
## 4.6.0
|
||||
|
||||
* **New Feature**
|
||||
* Desugar sticky regexes to a new constructor expression so it can be handled by a polyfill.
|
||||
* **Spec Compliancy**
|
||||
* `for...of` now outputs in a lengthy `try...catch` this is to ensure spec compliancy in regards to iterator returns and abrupt completions. See [google/traceur-compiler#1773](https://github.com/google/traceur-compiler/issues/1773) and [babel/babel/#838](https://github.com/babel/babel/issues/838) for more information.
|
||||
* **Polish**
|
||||
* Rest parameters that are only refered to via number properties on member expressions are desugared into a direct `arguments` reference. Thanks [@neVERberleRfellerER](https://github.com/neVERberleRfellerER)!
|
||||
* `$ babel` no longer exits on syntax errors.
|
||||
* **Internal**
|
||||
* Upgrade `browserify`.
|
||||
* Upgrade `source-map`.
|
||||
* Publicly expose more internals.
|
||||
|
||||
## 4.5.5
|
||||
|
||||
* **Polish**
|
||||
* Delete old extensions when overriding them in `babel/register`.
|
||||
|
||||
## 4.5.3
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix whitelisting logic for helper build script.
|
||||
|
||||
## 4.5.2
|
||||
|
||||
* **New Feature**
|
||||
* `returnUsedHelpers` option and add whitelist to `buildHelpers`.
|
||||
* **Bug Fix**
|
||||
* Fix function arity on self referencing inferred named functions.
|
||||
* **Internal**
|
||||
* Bump `acorn-babel`.
|
||||
* Start converting source to ES6...
|
||||
|
||||
## 4.5.1
|
||||
|
||||
**Babel now compiles itself!**
|
||||
|
||||

|
||||
|
||||
## 4.5.0
|
||||
|
||||
* **New Feature**
|
||||
|
||||
@@ -4,10 +4,6 @@ Contributions are always welcome, no matter how large or small. Before
|
||||
contributing, please read the
|
||||
[code of conduct](https://github.com/babel/babel/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
**NOTE:** Please do not send pull requests that fix linting issues. It's highly
|
||||
likely that they've already been fixed by the time it's submitted and it just
|
||||
pollutes the git tree.
|
||||
|
||||
## Developing
|
||||
|
||||
#### Setup
|
||||
@@ -44,15 +40,6 @@ running them with `mocha`:
|
||||
$ mocha test/transformation.js
|
||||
```
|
||||
|
||||
#### Linting
|
||||
|
||||
Please follow the correct code style, this ensures that the code is consistent
|
||||
and increases maintainability.
|
||||
|
||||
```sh
|
||||
$ make lint
|
||||
```
|
||||
|
||||
#### Workflow
|
||||
|
||||
* Fork the repository
|
||||
|
||||
9
Makefile
9
Makefile
@@ -8,7 +8,7 @@ BABEL_CMD = node_modules/babel/bin/babel
|
||||
|
||||
export NODE_ENV = test
|
||||
|
||||
.PHONY: clean test test-cov test-clean lint test-travis test-simple test-all test-browser publish build bootstrap publish-core publish-runtime build-core watch-core
|
||||
.PHONY: clean test test-cov test-clean test-travis test-simple test-all test-browser publish build bootstrap publish-core publish-runtime build-core watch-core
|
||||
|
||||
build-core:
|
||||
node $(BABEL_CMD) src --out-dir lib --copy-files
|
||||
@@ -36,13 +36,10 @@ build:
|
||||
clean:
|
||||
rm -rf coverage templates.json test/tmp dist
|
||||
|
||||
lint:
|
||||
$(JSHINT_CMD) --reporter node_modules/jshint-stylish/stylish.js src bin
|
||||
|
||||
test-clean:
|
||||
rm -rf test/tmp
|
||||
|
||||
test: lint
|
||||
test:
|
||||
$(MOCHA_CMD)
|
||||
make test-clean
|
||||
|
||||
@@ -60,7 +57,7 @@ test-cov:
|
||||
export SIMPLE_BABEL_TESTS=1; \
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
|
||||
|
||||
test-travis: build-core bootstrap
|
||||
test-travis: bootstrap build
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
|
||||
if test -n "$$CODECLIMATE_REPO_TOKEN"; then codeclimate < coverage/lcov.info; fi
|
||||
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
For more information view the <a href="https://babeljs.io/">documentation</a>. For questions
|
||||
and support please visit the <a href="https://gitter.im/babel/babel">gitter room</a> before
|
||||
creating an issue.
|
||||
For questions and support please visit the <a href="https://gitter.im/babel/babel">gitter room</a> before creating an issue.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
@@ -31,6 +31,14 @@ module.exports = function (commander, filenames, opts) {
|
||||
console.log(src + " -> " + dest);
|
||||
};
|
||||
|
||||
var handleFile = function (src, filename) {
|
||||
if (util.canCompile(filename)) {
|
||||
write(src, filename);
|
||||
} else if (commander.copyFiles) {
|
||||
outputFileSync(path.join(commander.outDir, filename), fs.readFileSync(src));
|
||||
}
|
||||
};
|
||||
|
||||
var handle = function (filename) {
|
||||
if (!fs.existsSync(filename)) return;
|
||||
|
||||
@@ -41,11 +49,7 @@ module.exports = function (commander, filenames, opts) {
|
||||
|
||||
_.each(util.readdir(dirname), function (filename) {
|
||||
var src = path.join(dirname, filename);
|
||||
if (util.canCompile(filename)) {
|
||||
write(src, filename);
|
||||
} else if (commander.copyFiles) {
|
||||
outputFileSync(path.join(commander.outDir, filename), fs.readFileSync(src));
|
||||
}
|
||||
handleFile(src, filename);
|
||||
});
|
||||
} else {
|
||||
write(filename, filename);
|
||||
@@ -64,7 +68,11 @@ module.exports = function (commander, filenames, opts) {
|
||||
_.each(["add", "change"], function (type) {
|
||||
watcher.on(type, function (filename) {
|
||||
var relative = path.relative(dirname, filename) || filename;
|
||||
if (util.canCompile(filename)) write(filename, relative);
|
||||
try {
|
||||
handleFile(filename, relative);
|
||||
} catch (err) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,7 +119,11 @@ module.exports = function (commander, filenames) {
|
||||
}).on("all", function (type, filename) {
|
||||
if (type === "add" || type === "change") {
|
||||
console.log(type, filename);
|
||||
walk();
|
||||
try {
|
||||
walk();
|
||||
} catch (err) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,17 +26,7 @@ exports.transform = function (filename, code, opts) {
|
||||
opts.filename = filename;
|
||||
resolveRc(filename, opts);
|
||||
|
||||
var result;
|
||||
try {
|
||||
result = babel.transform(code, opts);
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
console.error("SyntaxError:", e.message);
|
||||
process.exit(1);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
var result = babel.transform(code, opts);
|
||||
result.filename = filename;
|
||||
result.actual = code;
|
||||
return result;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
See [babel.github.io/docs](https://github.com/babel/babel.github.io/tree/master/docs).
|
||||
18
package.json
18
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "babel",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "4.5.1",
|
||||
"version": "4.6.4",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
"repository": "babel/babel",
|
||||
@@ -36,7 +36,7 @@
|
||||
"test": "make test"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn-babel": "0.11.1-34",
|
||||
"acorn-babel": "0.11.1-37",
|
||||
"ast-types": "~0.6.1",
|
||||
"chalk": "^1.0.0",
|
||||
"chokidar": "^0.12.6",
|
||||
@@ -49,7 +49,7 @@
|
||||
"fs-readdir-recursive": "^0.1.0",
|
||||
"globals": "^6.2.0",
|
||||
"is-integer": "^1.0.4",
|
||||
"js-tokens": "0.4.1",
|
||||
"js-tokens": "1.0.0",
|
||||
"leven": "^1.0.1",
|
||||
"line-numbers": "0.2.0",
|
||||
"lodash": "^3.2.0",
|
||||
@@ -57,23 +57,23 @@
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"private": "^0.1.6",
|
||||
"regenerator-babel": "0.8.13-1",
|
||||
"regexpu": "^1.1.1",
|
||||
"regexpu": "^1.1.2",
|
||||
"repeating": "^1.1.2",
|
||||
"shebang-regex": "^1.0.0",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.1.43",
|
||||
"source-map": "^0.4.0",
|
||||
"source-map-support": "^0.2.9",
|
||||
"source-map-to-comment": "^1.0.0",
|
||||
"trim-right": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "4.5.0",
|
||||
"browserify": "^8.1.3",
|
||||
"babel": "4.6.0",
|
||||
"browserify": "^9.0.3",
|
||||
"chai": "^2.0.0",
|
||||
"eslint": "^0.15.1",
|
||||
"babel-eslint": "^1.0.1",
|
||||
"esvalid": "^1.1.0",
|
||||
"istanbul": "^0.3.5",
|
||||
"jshint": "^2.6.0",
|
||||
"jshint-stylish": "^1.0.0",
|
||||
"matcha": "^0.6.0",
|
||||
"mocha": "^2.1.0",
|
||||
"rimraf": "^2.2.8",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "babel-runtime",
|
||||
"description": "babel selfContained runtime",
|
||||
"version": "4.5.0",
|
||||
"version": "4.6.3",
|
||||
"repository": "babel/babel",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var buildHelpers = require("../lib/babel/build-helpers");
|
||||
var transform = require("../lib/babel/transformation");
|
||||
var buildHelpers = require("../lib/babel/build-helpers");
|
||||
var util = require("../lib/babel/util");
|
||||
var fs = require("fs");
|
||||
var t = require("../lib/babel/types");
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
var transform = module.exports = require("../transformation");
|
||||
|
||||
transform.version = require("../../../package").version;
|
||||
|
||||
transform.transform = transform;
|
||||
|
||||
transform.run = function (code, opts) {
|
||||
opts = opts || {};
|
||||
transform.run = function (code, opts = {}) {
|
||||
opts.sourceMap = "inline";
|
||||
return new Function(transform(code, opts).code)();
|
||||
};
|
||||
|
||||
transform.load = function (url, callback, opts, hold) {
|
||||
opts = opts || {};
|
||||
opts.filename = opts.filename || url;
|
||||
transform.load = function (url, callback, opts = {}, hold) {
|
||||
opts.filename ||= url;
|
||||
|
||||
var xhr = global.ActiveXObject ? new global.ActiveXObject("Microsoft.XMLHTTP") : new global.XMLHttpRequest();
|
||||
xhr.open("GET", url, true);
|
||||
|
||||
@@ -1,34 +1,29 @@
|
||||
"use strict";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import transform from "../transformation";
|
||||
import fs from "fs";
|
||||
|
||||
var isFunction = require("lodash/lang/isFunction");
|
||||
var transform = require("../transformation");
|
||||
var util = require("../util");
|
||||
var fs = require("fs");
|
||||
import * as util from "../util";
|
||||
export { util as _util };
|
||||
export { canCompile } from "../util";
|
||||
|
||||
exports.version = require("../../../package").version;
|
||||
export { default as acorn } from "acorn-babel";
|
||||
export { default as transform } from "../transformation";
|
||||
export { default as traverse } from "../traversal";
|
||||
export { default as buildExternalHelpers } from "../build-external-helpers";
|
||||
export { default as types } from "../types";
|
||||
export { version } from "../../../package";
|
||||
|
||||
exports.buildExternalHelpers = require("../build-external-helpers");
|
||||
export function register(opts) {
|
||||
var callback = require("./register/node");
|
||||
if (opts != null) callback(opts);
|
||||
return callback;
|
||||
}
|
||||
|
||||
exports.types = require("../types");
|
||||
|
||||
exports.register = function (opts) {
|
||||
var register = require("./register/node");
|
||||
if (opts != null) register(opts);
|
||||
return register;
|
||||
};
|
||||
|
||||
exports.polyfill = function () {
|
||||
export function polyfill() {
|
||||
require("../polyfill");
|
||||
};
|
||||
}
|
||||
|
||||
exports.canCompile = util.canCompile;
|
||||
|
||||
// do not use this - this is for use by official maintained babel plugins
|
||||
exports._util = util;
|
||||
|
||||
exports.transform = transform;
|
||||
|
||||
exports.transformFile = function (filename, opts, callback) {
|
||||
export function transformFile(filename, opts, callback) {
|
||||
if (isFunction(opts)) {
|
||||
callback = opts;
|
||||
opts = {};
|
||||
@@ -49,10 +44,9 @@ exports.transformFile = function (filename, opts, callback) {
|
||||
|
||||
callback(null, result);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
exports.transformFileSync = function (filename, opts) {
|
||||
opts = opts || {};
|
||||
export function transformFileSync(filename, opts = {}) {
|
||||
opts.filename = filename;
|
||||
return transform(fs.readFileSync(filename), opts);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
// required to safely use babel/register within a browserify codebase
|
||||
|
||||
module.exports = function () {};
|
||||
export default function () {};
|
||||
|
||||
require("../../polyfill");
|
||||
import "../../polyfill";
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
var path = require("path");
|
||||
var os = require("os");
|
||||
var fs = require("fs");
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import fs from "fs";
|
||||
|
||||
var FILENAME = process.env.BABEL_CACHE_PATH || path.join(os.tmpdir(), "babel.json");
|
||||
var data = {};
|
||||
|
||||
exports.save = function () {
|
||||
export function save() {
|
||||
fs.writeFileSync(FILENAME, JSON.stringify(data, null, " "));
|
||||
};
|
||||
}
|
||||
|
||||
exports.load = function () {
|
||||
export function load() {
|
||||
if (process.env.BABEL_DISABLE_CACHE) return;
|
||||
|
||||
process.on("exit", exports.save);
|
||||
process.on("exit", save);
|
||||
|
||||
var sigint = function () {
|
||||
process.removeListener("SIGINT", sigint);
|
||||
exports.save();
|
||||
save();
|
||||
process.kill(process.pid, "SIGINT");
|
||||
};
|
||||
|
||||
@@ -31,8 +29,8 @@ exports.load = function () {
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.get = function () {
|
||||
export function get() {
|
||||
return data;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
require("../../polyfill");
|
||||
|
||||
var sourceMapSupport = require("source-map-support");
|
||||
var registerCache = require("./cache");
|
||||
var resolveRc = require("./resolve-rc");
|
||||
var extend = require("lodash/object/extend");
|
||||
var babel = require("../node");
|
||||
var each = require("lodash/collection/each");
|
||||
var util = require("../../util");
|
||||
var fs = require("fs");
|
||||
import "../../polyfill";
|
||||
import sourceMapSupport from "source-map-support";
|
||||
import * as registerCache from "./cache";
|
||||
import resolveRc from "./resolve-rc";
|
||||
import extend from "lodash/object/extend";
|
||||
import * as babel from "../node";
|
||||
import each from "lodash/collection/each";
|
||||
import * as util from "../../util";
|
||||
import fs from "fs";
|
||||
|
||||
sourceMapSupport.install({
|
||||
retrieveSourceMap: function (source) {
|
||||
handleUncaughtExceptions: false,
|
||||
retrieveSourceMap(source) {
|
||||
var map = maps && maps[source];
|
||||
if (map) {
|
||||
return {
|
||||
@@ -35,7 +33,7 @@ var cache = registerCache.get();
|
||||
var transformOpts = {};
|
||||
var ignoreRegex = /node_modules/;
|
||||
var onlyRegex;
|
||||
var exts = {};
|
||||
var oldHandlers = {};
|
||||
var maps = {};
|
||||
|
||||
var mtime = function (filename) {
|
||||
@@ -107,7 +105,7 @@ var normalLoader = function (m, filename) {
|
||||
};
|
||||
|
||||
var registerExtension = function (ext) {
|
||||
var old = require.extensions[ext];
|
||||
var old = oldHandlers[ext] || oldHandlers[".js"];
|
||||
|
||||
var loader = normalLoader;
|
||||
if (process.env.running_under_istanbul) loader = istanbulLoader; // jshint ignore:line
|
||||
@@ -122,24 +120,25 @@ var registerExtension = function (ext) {
|
||||
};
|
||||
|
||||
var hookExtensions = function (_exts) {
|
||||
each(exts, function (old, ext) {
|
||||
require.extensions[ext] = old;
|
||||
each(oldHandlers, function (old, ext) {
|
||||
if (old === undefined) {
|
||||
delete require.extensions[ext];
|
||||
} else {
|
||||
require.extensions[ext] = old;
|
||||
}
|
||||
});
|
||||
|
||||
exts = {};
|
||||
oldHandlers = {};
|
||||
|
||||
each(_exts, function (ext) {
|
||||
exts[ext] = require.extensions[ext];
|
||||
oldHandlers[ext] = require.extensions[ext];
|
||||
registerExtension(ext);
|
||||
});
|
||||
};
|
||||
|
||||
hookExtensions(util.canCompile.EXTENSIONS);
|
||||
|
||||
module.exports = function (opts) {
|
||||
// normalize options
|
||||
opts = opts || {};
|
||||
|
||||
export default function (opts = {}) {
|
||||
if (opts.only != null) onlyRegex = util.regexify(opts.only);
|
||||
if (opts.ignore != null) ignoreRegex = util.regexify(opts.ignore);
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
var merge = require("lodash/object/merge");
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
import merge from "lodash/object/merge";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
var cache = {};
|
||||
|
||||
@@ -12,9 +10,8 @@ function exists(filename) {
|
||||
return cache[filename] = fs.existsSync(filename);
|
||||
}
|
||||
|
||||
module.exports = function (loc, opts) {
|
||||
export default function (loc, opts = {}) {
|
||||
var rel = ".babelrc";
|
||||
opts = opts || {};
|
||||
|
||||
function find(start, rel) {
|
||||
var file = path.join(start, rel);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"use strict";
|
||||
import buildHelpers from "./build-helpers";
|
||||
import generator from "./generation";
|
||||
import * as util from "./util";
|
||||
import t from "./types";
|
||||
|
||||
var buildHelpers = require("./build-helpers");
|
||||
var generator = require("./generation");
|
||||
var util = require("./util");
|
||||
var t = require("./types");
|
||||
|
||||
module.exports = function () {
|
||||
export default function (whitelist) {
|
||||
var namespace = t.identifier("babelHelpers");
|
||||
|
||||
var body = [];
|
||||
@@ -19,7 +17,7 @@ module.exports = function () {
|
||||
)
|
||||
]));
|
||||
|
||||
buildHelpers(body, namespace);
|
||||
buildHelpers(body, namespace, whitelist);
|
||||
|
||||
return generator(tree).code;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
var File = require("./transformation/file");
|
||||
var util = require("./util");
|
||||
var each = require("lodash/collection/each");
|
||||
var t = require("./types");
|
||||
import File from "./transformation/file";
|
||||
import * as util from "./util";
|
||||
import each from "lodash/collection/each";
|
||||
import t from "./types";
|
||||
|
||||
module.exports = function (body, namespace) {
|
||||
export default function (body, namespace, whitelist = []) {
|
||||
each(File.helpers, function (name) {
|
||||
if (whitelist.length && whitelist.indexOf(name) === -1) return;
|
||||
|
||||
var key = t.identifier(t.toIdentifier(name));
|
||||
body.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", t.memberExpression(namespace, key), util.template(name))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
module.exports = detect;
|
||||
import SYNTAX_KEYS from "./syntax-keys";
|
||||
import traverse from "../traversal";
|
||||
|
||||
var SYNTAX_KEYS = require("./syntax-keys");
|
||||
var traverse = require("../traversal");
|
||||
var visitors = traverse.explode(require("./visitors"));
|
||||
var visitors = traverse.explode(require("./visitors"));
|
||||
|
||||
function detect(ast) {
|
||||
export default function (ast) {
|
||||
var stats = {
|
||||
syntax: {},
|
||||
builtins: {}
|
||||
@@ -15,7 +14,7 @@ function detect(ast) {
|
||||
};
|
||||
|
||||
traverse(ast, {
|
||||
enter: function (node, parent) {
|
||||
enter(node, parent) {
|
||||
if (SYNTAX_KEYS[node.type]) {
|
||||
detectedSyntax(SYNTAX_KEYS[node.type]);
|
||||
}
|
||||
@@ -26,4 +25,4 @@ function detect(ast) {
|
||||
});
|
||||
|
||||
return stats;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
var t = require("../types");
|
||||
var includes = require("lodash/collection/includes");
|
||||
import includes from "lodash/collection/includes";
|
||||
import t from "../types";
|
||||
|
||||
exports.AssignmentExpression = function (node, parent, detected) {
|
||||
export function AssignmentExpression(node, parent, detected) {
|
||||
if (node.operator === "**=") {
|
||||
detected("es6.exponentation");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.BinaryExpression = function (node, parent, detected) {
|
||||
export function BinaryExpression(node, parent, detected) {
|
||||
if (node.operator === "**") {
|
||||
detected("es6.exponentation");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.VariableDeclaration = function (node, parent, detected) {
|
||||
export function VariableDeclaration(node, parent, detected) {
|
||||
if (node.kind === "let" || node.kind === "const") {
|
||||
detected("es6.blockScoping");
|
||||
}
|
||||
@@ -21,9 +21,9 @@ exports.VariableDeclaration = function (node, parent, detected) {
|
||||
if (node.kind === "const") {
|
||||
detected("es6.constants");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.Property = function (node, parent, detected) {
|
||||
export function Property(node, parent, detected) {
|
||||
if (node.shorthand || node.method) {
|
||||
detected("es6.properties.shorthand");
|
||||
}
|
||||
@@ -35,13 +35,13 @@ exports.Property = function (node, parent, detected) {
|
||||
if (node.computed) {
|
||||
detected("es6.properties.computed");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.AssignmentPattern = function (node, parent, detected) {
|
||||
export function AssignmentPattern(node, parent, detected) {
|
||||
if (t.isFunction(parent) && includes(parent.params, node)) {
|
||||
detected("es6.parameters.default");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.Function = function (node, parent, detected) {
|
||||
if (node.generator) {
|
||||
|
||||
@@ -1,175 +1,173 @@
|
||||
"use strict";
|
||||
import repeating from "repeating";
|
||||
import trimRight from "trim-right";
|
||||
import isBoolean from "lodash/lang/isBoolean";
|
||||
import includes from "lodash/collection/includes";
|
||||
import isNumber from "lodash/lang/isNumber";
|
||||
|
||||
module.exports = Buffer;
|
||||
|
||||
var repeating = require("repeating");
|
||||
var trimRight = require("trim-right");
|
||||
var isBoolean = require("lodash/lang/isBoolean");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var isNumber = require("lodash/lang/isNumber");
|
||||
|
||||
function Buffer(position, format) {
|
||||
this.position = position;
|
||||
this._indent = format.indent.base;
|
||||
this.format = format;
|
||||
this.buf = "";
|
||||
}
|
||||
|
||||
Buffer.prototype.get = function () {
|
||||
return trimRight(this.buf);
|
||||
};
|
||||
|
||||
Buffer.prototype.getIndent = function () {
|
||||
if (this.format.compact || this.format.concise) {
|
||||
return "";
|
||||
} else {
|
||||
return repeating(this.format.indent.style, this._indent);
|
||||
export default class Buffer {
|
||||
constructor(position, format) {
|
||||
this.position = position;
|
||||
this._indent = format.indent.base;
|
||||
this.format = format;
|
||||
this.buf = "";
|
||||
}
|
||||
};
|
||||
|
||||
Buffer.prototype.indentSize = function () {
|
||||
return this.getIndent().length;
|
||||
};
|
||||
|
||||
Buffer.prototype.indent = function () {
|
||||
this._indent++;
|
||||
};
|
||||
|
||||
Buffer.prototype.dedent = function () {
|
||||
this._indent--;
|
||||
};
|
||||
|
||||
Buffer.prototype.semicolon = function () {
|
||||
this.push(";");
|
||||
};
|
||||
|
||||
Buffer.prototype.ensureSemicolon = function () {
|
||||
if (!this.isLast(";")) this.semicolon();
|
||||
};
|
||||
|
||||
Buffer.prototype.rightBrace = function () {
|
||||
this.newline(true);
|
||||
this.push("}");
|
||||
};
|
||||
|
||||
Buffer.prototype.keyword = function (name) {
|
||||
this.push(name);
|
||||
this.space();
|
||||
};
|
||||
|
||||
Buffer.prototype.space = function () {
|
||||
if (this.format.compact) return;
|
||||
if (this.buf && !this.isLast(" ") && !this.isLast("\n")) {
|
||||
this.push(" ");
|
||||
get() {
|
||||
return trimRight(this.buf);
|
||||
}
|
||||
};
|
||||
|
||||
Buffer.prototype.removeLast = function (cha) {
|
||||
if (this.format.compact) return;
|
||||
if (!this.isLast(cha)) return;
|
||||
getIndent() {
|
||||
if (this.format.compact || this.format.concise) {
|
||||
return "";
|
||||
} else {
|
||||
return repeating(this.format.indent.style, this._indent);
|
||||
}
|
||||
}
|
||||
|
||||
this.buf = this.buf.substr(0, this.buf.length - 1);
|
||||
this.position.unshift(cha);
|
||||
};
|
||||
indentSize() {
|
||||
return this.getIndent().length;
|
||||
}
|
||||
|
||||
Buffer.prototype.newline = function (i, removeLast) {
|
||||
if (this.format.compact) return;
|
||||
indent() {
|
||||
this._indent++;
|
||||
}
|
||||
|
||||
if (this.format.concise) {
|
||||
dedent() {
|
||||
this._indent--;
|
||||
}
|
||||
|
||||
semicolon() {
|
||||
this.push(";");
|
||||
}
|
||||
|
||||
ensureSemicolon() {
|
||||
if (!this.isLast(";")) this.semicolon();
|
||||
}
|
||||
|
||||
rightBrace() {
|
||||
this.newline(true);
|
||||
this.push("}");
|
||||
}
|
||||
|
||||
keyword(name) {
|
||||
this.push(name);
|
||||
this.space();
|
||||
return;
|
||||
}
|
||||
|
||||
removeLast = removeLast || false;
|
||||
|
||||
if (isNumber(i)) {
|
||||
i = Math.min(2, i);
|
||||
|
||||
if (this.endsWith("{\n") || this.endsWith(":\n")) i--;
|
||||
if (i <= 0) return;
|
||||
|
||||
while (i > 0) {
|
||||
this._newline(removeLast);
|
||||
i--;
|
||||
space() {
|
||||
if (this.format.compact) return;
|
||||
if (this.buf && !this.isLast(" ") && !this.isLast("\n")) {
|
||||
this.push(" ");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBoolean(i)) {
|
||||
removeLast = i;
|
||||
removeLast(cha) {
|
||||
if (this.format.compact) return;
|
||||
if (!this.isLast(cha)) return;
|
||||
|
||||
this.buf = this.buf.substr(0, this.buf.length - 1);
|
||||
this.position.unshift(cha);
|
||||
}
|
||||
|
||||
this._newline(removeLast);
|
||||
};
|
||||
newline(i, removeLast) {
|
||||
if (this.format.compact) return;
|
||||
|
||||
Buffer.prototype._newline = function (removeLast) {
|
||||
// never allow more than two lines
|
||||
if (this.endsWith("\n\n")) return;
|
||||
|
||||
// remove the last newline
|
||||
if (removeLast && this.isLast("\n")) this.removeLast("\n");
|
||||
|
||||
this.removeLast(" ");
|
||||
this._removeSpacesAfterLastNewline();
|
||||
this._push("\n");
|
||||
};
|
||||
|
||||
/**
|
||||
* If buffer ends with a newline and some spaces after it, trim those spaces.
|
||||
*/
|
||||
|
||||
Buffer.prototype._removeSpacesAfterLastNewline = function () {
|
||||
var lastNewlineIndex = this.buf.lastIndexOf("\n");
|
||||
if (lastNewlineIndex === -1)
|
||||
return;
|
||||
|
||||
var index = this.buf.length - 1;
|
||||
while (index > lastNewlineIndex) {
|
||||
if (this.buf[index] !== " ") {
|
||||
break;
|
||||
if (this.format.concise) {
|
||||
this.space();
|
||||
return;
|
||||
}
|
||||
|
||||
index--;
|
||||
removeLast ||= false;
|
||||
|
||||
if (isNumber(i)) {
|
||||
i = Math.min(2, i);
|
||||
|
||||
if (this.endsWith("{\n") || this.endsWith(":\n")) i--;
|
||||
if (i <= 0) return;
|
||||
|
||||
while (i > 0) {
|
||||
this._newline(removeLast);
|
||||
i--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBoolean(i)) {
|
||||
removeLast = i;
|
||||
}
|
||||
|
||||
this._newline(removeLast);
|
||||
}
|
||||
|
||||
if (index === lastNewlineIndex) {
|
||||
this.buf = this.buf.substring(0, index + 1);
|
||||
}
|
||||
};
|
||||
_newline(removeLast) {
|
||||
// never allow more than two lines
|
||||
if (this.endsWith("\n\n")) return;
|
||||
|
||||
Buffer.prototype.push = function (str, noIndent) {
|
||||
if (!this.format.compact && this._indent && !noIndent && str !== "\n") {
|
||||
// we have an indent level and we aren't pushing a newline
|
||||
var indent = this.getIndent();
|
||||
// remove the last newline
|
||||
if (removeLast && this.isLast("\n")) this.removeLast("\n");
|
||||
|
||||
// replace all newlines with newlines with the indentation
|
||||
str = str.replace(/\n/g, "\n" + indent);
|
||||
|
||||
// we've got a newline before us so prepend on the indentation
|
||||
if (this.isLast("\n")) this._push(indent);
|
||||
this.removeLast(" ");
|
||||
this._removeSpacesAfterLastNewline();
|
||||
this._push("\n");
|
||||
}
|
||||
|
||||
this._push(str);
|
||||
};
|
||||
/**
|
||||
* If buffer ends with a newline and some spaces after it, trim those spaces.
|
||||
*/
|
||||
|
||||
Buffer.prototype._push = function (str) {
|
||||
this.position.push(str);
|
||||
this.buf += str;
|
||||
};
|
||||
_removeSpacesAfterLastNewline() {
|
||||
var lastNewlineIndex = this.buf.lastIndexOf("\n");
|
||||
if (lastNewlineIndex === -1)
|
||||
return;
|
||||
|
||||
Buffer.prototype.endsWith = function (str) {
|
||||
return this.buf.slice(-str.length) === str;
|
||||
};
|
||||
var index = this.buf.length - 1;
|
||||
while (index > lastNewlineIndex) {
|
||||
if (this.buf[index] !== " ") {
|
||||
break;
|
||||
}
|
||||
|
||||
Buffer.prototype.isLast = function (cha) {
|
||||
if (this.format.compact) return false;
|
||||
index--;
|
||||
}
|
||||
|
||||
var buf = this.buf;
|
||||
var last = buf[buf.length - 1];
|
||||
|
||||
if (Array.isArray(cha)) {
|
||||
return includes(cha, last);
|
||||
} else {
|
||||
return cha === last;
|
||||
if (index === lastNewlineIndex) {
|
||||
this.buf = this.buf.substring(0, index + 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
push(str, noIndent) {
|
||||
if (!this.format.compact && this._indent && !noIndent && str !== "\n") {
|
||||
// we have an indent level and we aren't pushing a newline
|
||||
var indent = this.getIndent();
|
||||
|
||||
// replace all newlines with newlines with the indentation
|
||||
str = str.replace(/\n/g, "\n" + indent);
|
||||
|
||||
// we've got a newline before us so prepend on the indentation
|
||||
if (this.isLast("\n")) this._push(indent);
|
||||
}
|
||||
|
||||
this._push(str);
|
||||
}
|
||||
|
||||
_push(str) {
|
||||
this.position.push(str);
|
||||
this.buf += str;
|
||||
}
|
||||
|
||||
endsWith(str) {
|
||||
return this.buf.slice(-str.length) === str;
|
||||
}
|
||||
|
||||
isLast(cha) {
|
||||
if (this.format.compact) return false;
|
||||
|
||||
var buf = this.buf;
|
||||
var last = buf[buf.length - 1];
|
||||
|
||||
if (Array.isArray(cha)) {
|
||||
return includes(cha, last);
|
||||
} else {
|
||||
return cha === last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
exports.File = function (node, print) {
|
||||
export function File(node, print) {
|
||||
print(node.program);
|
||||
};
|
||||
}
|
||||
|
||||
exports.Program = function (node, print) {
|
||||
export function Program(node, print) {
|
||||
print.sequence(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.BlockStatement = function (node, print) {
|
||||
export function BlockStatement(node, print) {
|
||||
if (node.body.length === 0) {
|
||||
this.push("{}");
|
||||
} else {
|
||||
@@ -18,4 +16,4 @@ exports.BlockStatement = function (node, print) {
|
||||
this.removeLast("\n");
|
||||
this.rightBrace();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
exports.ClassExpression =
|
||||
exports.ClassDeclaration = function (node, print) {
|
||||
export function ClassDeclaration(node, print) {
|
||||
this.push("class");
|
||||
|
||||
if (node.id) {
|
||||
@@ -9,16 +6,26 @@ exports.ClassDeclaration = function (node, print) {
|
||||
print(node.id);
|
||||
}
|
||||
|
||||
print(node.typeParameters);
|
||||
|
||||
if (node.superClass) {
|
||||
this.push(" extends ");
|
||||
print(node.superClass);
|
||||
print(node.superTypeParameters);
|
||||
}
|
||||
|
||||
if (node.implements) {
|
||||
this.push(" implements ");
|
||||
print.join(node.implements, { separator: ", " });
|
||||
}
|
||||
|
||||
this.space();
|
||||
print(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.ClassBody = function (node, print) {
|
||||
export { ClassDeclaration as ClassExpression };
|
||||
|
||||
export function ClassBody(node, print) {
|
||||
if (node.body.length === 0) {
|
||||
this.push("{}");
|
||||
} else {
|
||||
@@ -31,12 +38,12 @@ exports.ClassBody = function (node, print) {
|
||||
|
||||
this.rightBrace();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.MethodDefinition = function (node, print) {
|
||||
export function MethodDefinition(node, print) {
|
||||
if (node.static) {
|
||||
this.push("static ");
|
||||
}
|
||||
|
||||
this._method(node, print);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
exports.ComprehensionBlock = function (node, print) {
|
||||
export function ComprehensionBlock(node, print) {
|
||||
this.keyword("for");
|
||||
this.push("(");
|
||||
print(node.left);
|
||||
this.push(" of ");
|
||||
print(node.right);
|
||||
this.push(")");
|
||||
};
|
||||
}
|
||||
|
||||
exports.ComprehensionExpression = function (node, print) {
|
||||
export function ComprehensionExpression(node, print) {
|
||||
this.push(node.generator ? "(" : "[");
|
||||
|
||||
print.join(node.blocks, { separator: " " });
|
||||
@@ -26,4 +24,4 @@ exports.ComprehensionExpression = function (node, print) {
|
||||
print(node.body);
|
||||
|
||||
this.push(node.generator ? ")" : "]");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
"use strict";
|
||||
import isInteger from "is-integer";
|
||||
import isNumber from "lodash/lang/isNumber";
|
||||
import t from "../../types";
|
||||
|
||||
var isInteger = require("is-integer");
|
||||
var isNumber = require("lodash/lang/isNumber");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.UnaryExpression = function (node, print) {
|
||||
export function UnaryExpression(node, print) {
|
||||
var hasSpace = /[a-z]$/.test(node.operator);
|
||||
var arg = node.argument;
|
||||
|
||||
@@ -19,9 +17,9 @@ exports.UnaryExpression = function (node, print) {
|
||||
this.push(node.operator);
|
||||
if (hasSpace) this.push(" ");
|
||||
print(node.argument);
|
||||
};
|
||||
}
|
||||
|
||||
exports.UpdateExpression = function (node, print) {
|
||||
export function UpdateExpression(node, print) {
|
||||
if (node.prefix) {
|
||||
this.push(node.operator);
|
||||
print(node.argument);
|
||||
@@ -29,9 +27,9 @@ exports.UpdateExpression = function (node, print) {
|
||||
print(node.argument);
|
||||
this.push(node.operator);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.ConditionalExpression = function (node, print) {
|
||||
export function ConditionalExpression(node, print) {
|
||||
print(node.test);
|
||||
this.space();
|
||||
this.push("?");
|
||||
@@ -41,25 +39,25 @@ exports.ConditionalExpression = function (node, print) {
|
||||
this.push(":");
|
||||
this.space();
|
||||
print(node.alternate);
|
||||
};
|
||||
}
|
||||
|
||||
exports.NewExpression = function (node, print) {
|
||||
export function NewExpression(node, print) {
|
||||
this.push("new ");
|
||||
print(node.callee);
|
||||
this.push("(");
|
||||
print.list(node.arguments);
|
||||
this.push(")");
|
||||
};
|
||||
}
|
||||
|
||||
exports.SequenceExpression = function (node, print) {
|
||||
export function SequenceExpression(node, print) {
|
||||
print.list(node.expressions);
|
||||
};
|
||||
}
|
||||
|
||||
exports.ThisExpression = function () {
|
||||
export function ThisExpression() {
|
||||
this.push("this");
|
||||
};
|
||||
}
|
||||
|
||||
exports.CallExpression = function (node, print) {
|
||||
export function CallExpression(node, print) {
|
||||
print(node.callee);
|
||||
|
||||
this.push("(");
|
||||
@@ -82,7 +80,7 @@ exports.CallExpression = function (node, print) {
|
||||
}
|
||||
|
||||
this.push(")");
|
||||
};
|
||||
}
|
||||
|
||||
var buildYieldAwait = function (keyword) {
|
||||
return function (node, print) {
|
||||
@@ -99,17 +97,17 @@ var buildYieldAwait = function (keyword) {
|
||||
};
|
||||
};
|
||||
|
||||
exports.YieldExpression = buildYieldAwait("yield");
|
||||
exports.AwaitExpression = buildYieldAwait("await");
|
||||
export var YieldExpression = buildYieldAwait("yield");
|
||||
export var AwaitExpression = buildYieldAwait("await");
|
||||
|
||||
exports.EmptyStatement = function () {
|
||||
export function EmptyStatement() {
|
||||
this.semicolon();
|
||||
};
|
||||
}
|
||||
|
||||
exports.ExpressionStatement = function (node, print) {
|
||||
export function ExpressionStatement(node, print) {
|
||||
print(node.expression);
|
||||
this.semicolon();
|
||||
};
|
||||
}
|
||||
|
||||
exports.BinaryExpression =
|
||||
exports.LogicalExpression =
|
||||
@@ -125,7 +123,7 @@ exports.AssignmentExpression = function (node, print) {
|
||||
|
||||
var SCIENTIFIC_NOTATION = /e/i;
|
||||
|
||||
exports.MemberExpression = function (node, print) {
|
||||
export function MemberExpression(node, print) {
|
||||
var obj = node.object;
|
||||
print(obj);
|
||||
|
||||
@@ -151,4 +149,4 @@ exports.MemberExpression = function (node, print) {
|
||||
this.push(".");
|
||||
print(node.property);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,36 +1,226 @@
|
||||
"use strict";
|
||||
import t from "../../types";
|
||||
|
||||
exports.AnyTypeAnnotation =
|
||||
exports.ArrayTypeAnnotation =
|
||||
exports.BooleanTypeAnnotation =
|
||||
exports.ClassProperty =
|
||||
exports.DeclareClass =
|
||||
exports.DeclareFunction =
|
||||
exports.DeclareModule =
|
||||
exports.DeclareVariable =
|
||||
exports.FunctionTypeAnnotation =
|
||||
exports.FunctionTypeParam =
|
||||
exports.GenericTypeAnnotation =
|
||||
exports.InterfaceExtends =
|
||||
exports.InterfaceDeclaration =
|
||||
exports.IntersectionTypeAnnotation =
|
||||
exports.NullableTypeAnnotation =
|
||||
exports.NumberTypeAnnotation =
|
||||
exports.StringLiteralTypeAnnotation =
|
||||
exports.StringTypeAnnotation =
|
||||
exports.TupleTypeAnnotation =
|
||||
exports.TypeofTypeAnnotation =
|
||||
exports.TypeAlias =
|
||||
exports.TypeAnnotation =
|
||||
exports.TypeParameterDeclaration =
|
||||
exports.TypeParameterInstantiation =
|
||||
exports.ObjectTypeAnnotation =
|
||||
exports.ObjectTypeCallProperty =
|
||||
exports.ObjectTypeIndexer =
|
||||
exports.ObjectTypeProperty =
|
||||
exports.QualifiedTypeIdentifier =
|
||||
exports.UnionTypeAnnotation =
|
||||
exports.TypeCastExpression =
|
||||
exports.VoidTypeAnnotation = function () {
|
||||
// todo: implement these once we have a `--keep-types` option
|
||||
};
|
||||
export function AnyTypeAnnotation() {
|
||||
this.push("any");
|
||||
}
|
||||
|
||||
export function ArrayTypeAnnotation(node, print) {
|
||||
print(node.elementType);
|
||||
this.push("[");
|
||||
this.push("]");
|
||||
}
|
||||
|
||||
export function BooleanTypeAnnotation(node) {
|
||||
this.push("bool");
|
||||
}
|
||||
|
||||
export function ClassProperty(node, print) {
|
||||
if (node.static) this.push("static ");
|
||||
print(node.key);
|
||||
print(node.typeAnnotation);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function DeclareClass(node, print) {
|
||||
this.push("declare class ");
|
||||
this._interfaceish(node, print);
|
||||
}
|
||||
|
||||
export function DeclareFunction(node, print) {
|
||||
this.push("declare function ");
|
||||
print(node.id);
|
||||
print(node.id.typeAnnotation.typeAnnotation);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function DeclareModule(node, print) {
|
||||
this.push("declare module ");
|
||||
print(node.id);
|
||||
this.space();
|
||||
print(node.body);
|
||||
}
|
||||
|
||||
export function DeclareVariable(node, print) {
|
||||
this.push("declare var ");
|
||||
print(node.id);
|
||||
print(node.id.typeAnnotation);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function FunctionTypeAnnotation(node, print, parent) {
|
||||
print(node.typeParameters);
|
||||
this.push("(");
|
||||
print.list(node.params);
|
||||
|
||||
if (node.rest) {
|
||||
if (node.params.length) {
|
||||
this.push(",");
|
||||
this.space();
|
||||
}
|
||||
this.push("...");
|
||||
print(node.rest);
|
||||
}
|
||||
|
||||
this.push(")");
|
||||
|
||||
// this node type is overloaded, not sure why but it makes it EXTREMELY annoying
|
||||
if (parent.type === "ObjectTypeProperty" || parent.type === "ObjectTypeCallProperty" || parent.type === "DeclareFunction") {
|
||||
this.push(":");
|
||||
} else {
|
||||
this.space();
|
||||
this.push("=>");
|
||||
}
|
||||
|
||||
this.space();
|
||||
print(node.returnType);
|
||||
}
|
||||
|
||||
export function FunctionTypeParam(node, print) {
|
||||
print(node.name);
|
||||
if (node.optional) this.push("?");
|
||||
this.push(":");
|
||||
this.space();
|
||||
print(node.typeAnnotation);
|
||||
}
|
||||
|
||||
export function InterfaceExtends(node, print) {
|
||||
print(node.id);
|
||||
print(node.typeParameters);
|
||||
}
|
||||
|
||||
export { InterfaceExtends as ClassImplements, InterfaceExtends as GenericTypeAnnotation };
|
||||
|
||||
export function _interfaceish(node, print) {
|
||||
print(node.id);
|
||||
print(node.typeParameters);
|
||||
if (node.extends.length) {
|
||||
this.push(" extends ");
|
||||
print.join(node.extends, { separator: ", " });
|
||||
}
|
||||
this.space();
|
||||
print(node.body);
|
||||
}
|
||||
|
||||
export function InterfaceDeclaration(node, print) {
|
||||
this.push("interface ");
|
||||
this._interfaceish(node, print);
|
||||
}
|
||||
|
||||
export function IntersectionTypeAnnotation(node, print) {
|
||||
print.join(node.types, { separator: " & " });
|
||||
}
|
||||
|
||||
export function NullableTypeAnnotation(node, print) {
|
||||
this.push("?");
|
||||
print(node.typeAnnotation);
|
||||
}
|
||||
|
||||
export function NumberTypeAnnotation() {
|
||||
this.push("number");
|
||||
}
|
||||
|
||||
export function StringLiteralTypeAnnotation(node) {
|
||||
this._stringLiteral(node.value);
|
||||
}
|
||||
|
||||
export function StringTypeAnnotation() {
|
||||
this.push("string");
|
||||
}
|
||||
|
||||
export function TupleTypeAnnotation(node, print) {
|
||||
this.push("[");
|
||||
print.join(node.types, { separator: ", " });
|
||||
this.push("]");
|
||||
}
|
||||
|
||||
export function TypeofTypeAnnotation(node, print) {
|
||||
this.push("typeof ");
|
||||
print(node.argument);
|
||||
}
|
||||
|
||||
export function TypeAlias(node, print) {
|
||||
this.push("type ");
|
||||
print(node.id);
|
||||
print(node.typeParameters);
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.space();
|
||||
print(node.right);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function TypeAnnotation(node, print) {
|
||||
this.push(":");
|
||||
this.space();
|
||||
if (node.optional) this.push("?");
|
||||
print(node.typeAnnotation);
|
||||
}
|
||||
|
||||
export function TypeParameterInstantiation(node, print) {
|
||||
this.push("<");
|
||||
print.join(node.params, { separator: ", " });
|
||||
this.push(">");
|
||||
}
|
||||
|
||||
export { TypeParameterInstantiation as TypeParameterDeclaration };
|
||||
|
||||
export function ObjectTypeAnnotation(node, print) {
|
||||
this.push("{");
|
||||
var props = node.properties.concat(node.callProperties, node.indexers);
|
||||
if (props.length) {
|
||||
this.space();
|
||||
print.list(props, { indent: true, separator: "; " });
|
||||
this.space();
|
||||
}
|
||||
this.push("}");
|
||||
}
|
||||
|
||||
export function ObjectTypeCallProperty(node, print) {
|
||||
if (node.static) this.push("static ");
|
||||
print(node.value);
|
||||
}
|
||||
|
||||
export function ObjectTypeIndexer(node, print) {
|
||||
if (node.static) this.push("static ");
|
||||
this.push("[");
|
||||
print(node.id);
|
||||
this.push(":");
|
||||
this.space();
|
||||
print(node.key);
|
||||
this.push("]");
|
||||
this.push(":");
|
||||
this.space();
|
||||
print(node.value);
|
||||
}
|
||||
|
||||
export function ObjectTypeProperty(node, print) {
|
||||
if (node.static) this.push("static ");
|
||||
print(node.key);
|
||||
if (node.optional) this.push("?");
|
||||
if (!t.isFunctionTypeAnnotation(node.value)) {
|
||||
this.push(":");
|
||||
this.space();
|
||||
}
|
||||
print(node.value);
|
||||
}
|
||||
|
||||
export function QualifiedTypeIdentifier(node, print) {
|
||||
print(node.qualification);
|
||||
this.push(".");
|
||||
print(node.id);
|
||||
}
|
||||
|
||||
export function UnionTypeAnnotation(node, print) {
|
||||
print.join(node.types, { separator: " | " });
|
||||
}
|
||||
|
||||
export function TypeCastExpression(node, print) {
|
||||
this.push("(");
|
||||
print(node.expression);
|
||||
print(node.typeAnnotation);
|
||||
this.push(")");
|
||||
}
|
||||
|
||||
export function VoidTypeAnnotation(node) {
|
||||
this.push("void");
|
||||
}
|
||||
|
||||
@@ -1,45 +1,43 @@
|
||||
"use strict";
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../../types";
|
||||
|
||||
var t = require("../../types");
|
||||
var each = require("lodash/collection/each");
|
||||
|
||||
exports.JSXAttribute = function (node, print) {
|
||||
export function JSXAttribute(node, print) {
|
||||
print(node.name);
|
||||
if (node.value) {
|
||||
this.push("=");
|
||||
print(node.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXIdentifier = function (node) {
|
||||
export function JSXIdentifier(node) {
|
||||
this.push(node.name);
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXNamespacedName = function (node, print) {
|
||||
export function JSXNamespacedName(node, print) {
|
||||
print(node.namespace);
|
||||
this.push(":");
|
||||
print(node.name);
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXMemberExpression = function (node, print) {
|
||||
export function JSXMemberExpression(node, print) {
|
||||
print(node.object);
|
||||
this.push(".");
|
||||
print(node.property);
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXSpreadAttribute = function (node, print) {
|
||||
export function JSXSpreadAttribute(node, print) {
|
||||
this.push("{...");
|
||||
print(node.argument);
|
||||
this.push("}");
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXExpressionContainer = function (node, print) {
|
||||
export function JSXExpressionContainer(node, print) {
|
||||
this.push("{");
|
||||
print(node.expression);
|
||||
this.push("}");
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXElement = function (node, print) {
|
||||
export function JSXElement(node, print) {
|
||||
var open = node.openingElement;
|
||||
print(open);
|
||||
if (open.selfClosing) return;
|
||||
@@ -55,9 +53,9 @@ exports.JSXElement = function (node, print) {
|
||||
this.dedent();
|
||||
|
||||
print(node.closingElement);
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXOpeningElement = function (node, print) {
|
||||
export function JSXOpeningElement(node, print) {
|
||||
this.push("<");
|
||||
print(node.name);
|
||||
if (node.attributes.length > 0) {
|
||||
@@ -65,12 +63,12 @@ exports.JSXOpeningElement = function (node, print) {
|
||||
print.join(node.attributes, { separator: " " });
|
||||
}
|
||||
this.push(node.selfClosing ? " />" : ">");
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXClosingElement = function (node, print) {
|
||||
export function JSXClosingElement(node, print) {
|
||||
this.push("</");
|
||||
print(node.name);
|
||||
this.push(">");
|
||||
};
|
||||
}
|
||||
|
||||
exports.JSXEmptyExpression = function () {};
|
||||
export function JSXEmptyExpression() {}
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
"use strict";
|
||||
import t from "../../types";
|
||||
|
||||
var t = require("../../types");
|
||||
|
||||
exports._params = function (node, print) {
|
||||
export function _params(node, print) {
|
||||
print(node.typeParameters);
|
||||
this.push("(");
|
||||
print.list(node.params);
|
||||
print.list(node.params, {
|
||||
iterator: (node) =>{
|
||||
if (node.optional) this.push("?");
|
||||
print(node.typeAnnotation);
|
||||
}
|
||||
});
|
||||
this.push(")");
|
||||
};
|
||||
|
||||
exports._method = function (node, print) {
|
||||
if (node.returnType) {
|
||||
print(node.returnType);
|
||||
}
|
||||
}
|
||||
|
||||
export function _method(node, print) {
|
||||
var value = node.value;
|
||||
var kind = node.kind;
|
||||
var key = node.key;
|
||||
@@ -34,7 +42,7 @@ exports._method = function (node, print) {
|
||||
this._params(value, print);
|
||||
this.push(" ");
|
||||
print(value.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.FunctionDeclaration =
|
||||
exports.FunctionExpression = function (node, print) {
|
||||
@@ -54,7 +62,7 @@ exports.FunctionExpression = function (node, print) {
|
||||
print(node.body);
|
||||
};
|
||||
|
||||
exports.ArrowFunctionExpression = function (node, print) {
|
||||
export function ArrowFunctionExpression(node, print) {
|
||||
if (node.async) this.push("async ");
|
||||
|
||||
if (node.params.length === 1 && t.isIdentifier(node.params[0])) {
|
||||
@@ -65,4 +73,4 @@ exports.ArrowFunctionExpression = function (node, print) {
|
||||
|
||||
this.push(" => ");
|
||||
print(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
"use strict";
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../../types";
|
||||
|
||||
var t = require("../../types");
|
||||
var each = require("lodash/collection/each");
|
||||
|
||||
exports.ImportSpecifier = function (node, print) {
|
||||
export function ImportSpecifier(node, print) {
|
||||
if (t.isSpecifierDefault(node)) {
|
||||
print(t.getSpecifierName(node));
|
||||
} else {
|
||||
return exports.ExportSpecifier.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.ExportSpecifier = function (node, print) {
|
||||
export function ExportSpecifier(node, print) {
|
||||
print(node.id);
|
||||
if (node.name) {
|
||||
this.push(" as ");
|
||||
print(node.name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.ExportBatchSpecifier = function () {
|
||||
export function ExportBatchSpecifier() {
|
||||
this.push("*");
|
||||
};
|
||||
}
|
||||
|
||||
exports.ExportDeclaration = function (node, print) {
|
||||
export function ExportDeclaration(node, print) {
|
||||
this.push("export ");
|
||||
|
||||
var specifiers = node.specifiers;
|
||||
@@ -55,9 +53,9 @@ exports.ExportDeclaration = function (node, print) {
|
||||
}
|
||||
|
||||
this.ensureSemicolon();
|
||||
};
|
||||
}
|
||||
|
||||
exports.ImportDeclaration = function (node, print) {
|
||||
export function ImportDeclaration(node, print) {
|
||||
this.push("import ");
|
||||
|
||||
if (node.isType) {
|
||||
@@ -92,9 +90,9 @@ exports.ImportDeclaration = function (node, print) {
|
||||
|
||||
print(node.source);
|
||||
this.semicolon();
|
||||
};
|
||||
}
|
||||
|
||||
exports.ImportBatchSpecifier = function (node, print) {
|
||||
export function ImportBatchSpecifier(node, print) {
|
||||
this.push("* as ");
|
||||
print(node.name);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
var each = require("lodash/collection/each");
|
||||
import each from "lodash/collection/each";
|
||||
|
||||
each(["BindMemberExpression", "BindFunctionExpression"], function (type) {
|
||||
exports[type] = function () {
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
"use strict";
|
||||
import repeating from "repeating";
|
||||
import t from "../../types";
|
||||
|
||||
var repeating = require("repeating");
|
||||
var t = require("../../types");
|
||||
|
||||
exports.WithStatement = function (node, print) {
|
||||
export function WithStatement(node, print) {
|
||||
this.keyword("with");
|
||||
this.push("(");
|
||||
print(node.object);
|
||||
this.push(")");
|
||||
print.block(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.IfStatement = function (node, print) {
|
||||
export function IfStatement(node, print) {
|
||||
this.keyword("if");
|
||||
this.push("(");
|
||||
print(node.test);
|
||||
@@ -25,9 +23,9 @@ exports.IfStatement = function (node, print) {
|
||||
this.push("else ");
|
||||
print.indentOnComments(node.alternate);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.ForStatement = function (node, print) {
|
||||
export function ForStatement(node, print) {
|
||||
this.keyword("for");
|
||||
this.push("(");
|
||||
|
||||
@@ -47,15 +45,15 @@ exports.ForStatement = function (node, print) {
|
||||
|
||||
this.push(")");
|
||||
print.block(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.WhileStatement = function (node, print) {
|
||||
export function WhileStatement(node, print) {
|
||||
this.keyword("while");
|
||||
this.push("(");
|
||||
print(node.test);
|
||||
this.push(")");
|
||||
print.block(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
var buildForXStatement = function (op) {
|
||||
return function (node, print) {
|
||||
@@ -69,10 +67,10 @@ var buildForXStatement = function (op) {
|
||||
};
|
||||
};
|
||||
|
||||
exports.ForInStatement = buildForXStatement("in");
|
||||
exports.ForOfStatement = buildForXStatement("of");
|
||||
export var ForInStatement = buildForXStatement("in");
|
||||
export var ForOfStatement = buildForXStatement("of");
|
||||
|
||||
exports.DoWhileStatement = function (node, print) {
|
||||
export function DoWhileStatement(node, print) {
|
||||
this.keyword("do");
|
||||
print(node.body);
|
||||
this.space();
|
||||
@@ -80,7 +78,7 @@ exports.DoWhileStatement = function (node, print) {
|
||||
this.push("(");
|
||||
print(node.test);
|
||||
this.push(");");
|
||||
};
|
||||
}
|
||||
|
||||
var buildLabelStatement = function (prefix, key) {
|
||||
return function (node, print) {
|
||||
@@ -96,17 +94,17 @@ var buildLabelStatement = function (prefix, key) {
|
||||
};
|
||||
};
|
||||
|
||||
exports.ContinueStatement = buildLabelStatement("continue");
|
||||
exports.ReturnStatement = buildLabelStatement("return", "argument");
|
||||
exports.BreakStatement = buildLabelStatement("break");
|
||||
export var ContinueStatement = buildLabelStatement("continue");
|
||||
export var ReturnStatement = buildLabelStatement("return", "argument");
|
||||
export var BreakStatement = buildLabelStatement("break");
|
||||
|
||||
exports.LabeledStatement = function (node, print) {
|
||||
export function LabeledStatement(node, print) {
|
||||
print(node.label);
|
||||
this.push(": ");
|
||||
print(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.TryStatement = function (node, print) {
|
||||
export function TryStatement(node, print) {
|
||||
this.keyword("try");
|
||||
print(node.block);
|
||||
this.space();
|
||||
@@ -125,23 +123,23 @@ exports.TryStatement = function (node, print) {
|
||||
this.push("finally ");
|
||||
print(node.finalizer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.CatchClause = function (node, print) {
|
||||
export function CatchClause(node, print) {
|
||||
this.keyword("catch");
|
||||
this.push("(");
|
||||
print(node.param);
|
||||
this.push(") ");
|
||||
print(node.body);
|
||||
};
|
||||
}
|
||||
|
||||
exports.ThrowStatement = function (node, print) {
|
||||
export function ThrowStatement(node, print) {
|
||||
this.push("throw ");
|
||||
print(node.argument);
|
||||
this.semicolon();
|
||||
};
|
||||
}
|
||||
|
||||
exports.SwitchStatement = function (node, print) {
|
||||
export function SwitchStatement(node, print) {
|
||||
this.keyword("switch");
|
||||
this.push("(");
|
||||
print(node.discriminant);
|
||||
@@ -151,15 +149,15 @@ exports.SwitchStatement = function (node, print) {
|
||||
|
||||
print.sequence(node.cases, {
|
||||
indent: true,
|
||||
addNewlines: function (leading, cas) {
|
||||
addNewlines(leading, cas) {
|
||||
if (!leading && node.cases[node.cases.length - 1] === cas) return -1;
|
||||
}
|
||||
});
|
||||
|
||||
this.push("}");
|
||||
};
|
||||
}
|
||||
|
||||
exports.SwitchCase = function (node, print) {
|
||||
export function SwitchCase(node, print) {
|
||||
if (node.test) {
|
||||
this.push("case ");
|
||||
print(node.test);
|
||||
@@ -172,13 +170,13 @@ exports.SwitchCase = function (node, print) {
|
||||
this.newline();
|
||||
print.sequence(node.consequent, { indent: true });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.DebuggerStatement = function () {
|
||||
export function DebuggerStatement() {
|
||||
this.push("debugger;");
|
||||
};
|
||||
}
|
||||
|
||||
exports.VariableDeclaration = function (node, print, parent) {
|
||||
export function VariableDeclaration(node, print, parent) {
|
||||
this.push(node.kind + " ");
|
||||
|
||||
var hasInits = false;
|
||||
@@ -204,22 +202,21 @@ exports.VariableDeclaration = function (node, print, parent) {
|
||||
if (!t.isFor(parent)) {
|
||||
this.semicolon();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.PrivateDeclaration = function (node, print) {
|
||||
export function PrivateDeclaration(node, print) {
|
||||
this.push("private ");
|
||||
print.join(node.declarations, { separator: ", " });
|
||||
this.semicolon();
|
||||
};
|
||||
}
|
||||
|
||||
exports.VariableDeclarator = function (node, print) {
|
||||
export function VariableDeclarator(node, print) {
|
||||
print(node.id);
|
||||
print(node.id.typeAnnotation);
|
||||
if (node.init) {
|
||||
print(node.id);
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.space();
|
||||
print(node.init);
|
||||
} else {
|
||||
print(node.id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
"use strict";
|
||||
import each from "lodash/collection/each";
|
||||
|
||||
var each = require("lodash/collection/each");
|
||||
|
||||
exports.TaggedTemplateExpression = function (node, print) {
|
||||
export function TaggedTemplateExpression(node, print) {
|
||||
print(node.tag);
|
||||
print(node.quasi);
|
||||
};
|
||||
}
|
||||
|
||||
exports.TemplateElement = function (node) {
|
||||
export function TemplateElement(node) {
|
||||
this._push(node.value.raw);
|
||||
};
|
||||
}
|
||||
|
||||
exports.TemplateLiteral = function (node, print) {
|
||||
export function TemplateLiteral(node, print) {
|
||||
this.push("`");
|
||||
|
||||
var quasis = node.quasis;
|
||||
@@ -28,4 +26,4 @@ exports.TemplateLiteral = function (node, print) {
|
||||
});
|
||||
|
||||
this._push("`");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
"use strict";
|
||||
import each from "lodash/collection/each";
|
||||
|
||||
var each = require("lodash/collection/each");
|
||||
|
||||
exports.Identifier = function (node) {
|
||||
export function Identifier(node) {
|
||||
this.push(node.name);
|
||||
};
|
||||
}
|
||||
|
||||
exports.RestElement =
|
||||
exports.SpreadElement =
|
||||
@@ -13,11 +11,11 @@ exports.SpreadProperty = function (node, print) {
|
||||
print(node.argument);
|
||||
};
|
||||
|
||||
exports.VirtualPropertyExpression = function (node, print) {
|
||||
export function VirtualPropertyExpression(node, print) {
|
||||
print(node.object);
|
||||
this.push("::");
|
||||
print(node.property);
|
||||
};
|
||||
}
|
||||
|
||||
exports.ObjectExpression =
|
||||
exports.ObjectPattern = function (node, print) {
|
||||
@@ -36,7 +34,7 @@ exports.ObjectPattern = function (node, print) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.Property = function (node, print) {
|
||||
export function Property(node, print) {
|
||||
if (node.method || node.kind === "get" || node.kind === "set") {
|
||||
this._method(node, print);
|
||||
} else {
|
||||
@@ -53,7 +51,7 @@ exports.Property = function (node, print) {
|
||||
this.space();
|
||||
print(node.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.ArrayExpression =
|
||||
exports.ArrayPattern = function (node, print) {
|
||||
@@ -80,19 +78,12 @@ exports.ArrayPattern = function (node, print) {
|
||||
this.push("]");
|
||||
};
|
||||
|
||||
exports.Literal = function (node) {
|
||||
export function Literal(node) {
|
||||
var val = node.value;
|
||||
var type = typeof val;
|
||||
|
||||
if (type === "string") {
|
||||
val = JSON.stringify(val);
|
||||
|
||||
// escape illegal js but valid json unicode characters
|
||||
val = val.replace(/[\u000A\u000D\u2028\u2029]/g, function (c) {
|
||||
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
|
||||
this.push(val);
|
||||
this._stringLiteral(val);
|
||||
} else if (type === "number") {
|
||||
this.push(val + "");
|
||||
} else if (type === "boolean") {
|
||||
@@ -102,4 +93,15 @@ exports.Literal = function (node) {
|
||||
} else if (val === null) {
|
||||
this.push("null");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function _stringLiteral(val) {
|
||||
val = JSON.stringify(val);
|
||||
|
||||
// escape illegal js but valid json unicode characters
|
||||
val = val.replace(/[\u000A\u000D\u2028\u2029]/g, function (c) {
|
||||
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
|
||||
this.push(val);
|
||||
}
|
||||
|
||||
@@ -1,37 +1,339 @@
|
||||
"use strict";
|
||||
import detectIndent from "detect-indent";
|
||||
import Whitespace from "./whitespace";
|
||||
import repeating from "repeating";
|
||||
import SourceMap from "./source-map";
|
||||
import Position from "./position";
|
||||
import * as messages from "../messages";
|
||||
import Buffer from "./buffer";
|
||||
import extend from "lodash/object/extend";
|
||||
import each from "lodash/collection/each";
|
||||
import n from "./node";
|
||||
import t from "../types";
|
||||
|
||||
module.exports = function (ast, opts, code) {
|
||||
var gen = new CodeGenerator(ast, opts, code);
|
||||
return gen.generate();
|
||||
};
|
||||
class CodeGenerator {
|
||||
constructor(ast, opts, code) {
|
||||
opts ||= {};
|
||||
|
||||
module.exports.CodeGenerator = CodeGenerator;
|
||||
this.comments = ast.comments || [];
|
||||
this.tokens = ast.tokens || [];
|
||||
this.format = CodeGenerator.normalizeOptions(code, opts);
|
||||
this.opts = opts;
|
||||
this.ast = ast;
|
||||
|
||||
var detectIndent = require("detect-indent");
|
||||
var Whitespace = require("./whitespace");
|
||||
var repeating = require("repeating");
|
||||
var SourceMap = require("./source-map");
|
||||
var Position = require("./position");
|
||||
var messages = require("../messages");
|
||||
var Buffer = require("./buffer");
|
||||
var extend = require("lodash/object/extend");
|
||||
var each = require("lodash/collection/each");
|
||||
var n = require("./node");
|
||||
var t = require("../types");
|
||||
this.whitespace = new Whitespace(this.tokens, this.comments, this.format);
|
||||
this.position = new Position;
|
||||
this.map = new SourceMap(this.position, opts, code);
|
||||
this.buffer = new Buffer(this.position, this.format);
|
||||
}
|
||||
|
||||
function CodeGenerator(ast, opts, code) {
|
||||
opts = opts || {};
|
||||
static normalizeOptions(code, opts) {
|
||||
var style = " ";
|
||||
if (code) {
|
||||
var indent = detectIndent(code).indent;
|
||||
if (indent && indent !== " ") style = indent;
|
||||
}
|
||||
|
||||
this.comments = ast.comments || [];
|
||||
this.tokens = ast.tokens || [];
|
||||
this.format = CodeGenerator.normalizeOptions(code, opts);
|
||||
this.opts = opts;
|
||||
this.ast = ast;
|
||||
var format = {
|
||||
comments: opts.comments == null || opts.comments,
|
||||
compact: opts.compact,
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
style: style,
|
||||
base: 0
|
||||
}
|
||||
};
|
||||
|
||||
this.whitespace = new Whitespace(this.tokens, this.comments, this.format);
|
||||
this.position = new Position;
|
||||
this.map = new SourceMap(this.position, opts, code);
|
||||
this.buffer = new Buffer(this.position, this.format);
|
||||
if (format.compact === "auto") {
|
||||
format.compact = code.length > 100000; // 100KB
|
||||
|
||||
if (format.compact) {
|
||||
console.error(messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static generators = {
|
||||
templateLiterals: require("./generators/template-literals"),
|
||||
comprehensions: require("./generators/comprehensions"),
|
||||
expressions: require("./generators/expressions"),
|
||||
statements: require("./generators/statements"),
|
||||
playground: require("./generators/playground"),
|
||||
classes: require("./generators/classes"),
|
||||
methods: require("./generators/methods"),
|
||||
modules: require("./generators/modules"),
|
||||
types: require("./generators/types"),
|
||||
flow: require("./generators/flow"),
|
||||
base: require("./generators/base"),
|
||||
jsx: require("./generators/jsx")
|
||||
};
|
||||
|
||||
generate() {
|
||||
var ast = this.ast;
|
||||
|
||||
this.print(ast);
|
||||
|
||||
var comments = [];
|
||||
each(ast.comments, function (comment) {
|
||||
if (!comment._displayed) comments.push(comment);
|
||||
});
|
||||
this._printComments(comments);
|
||||
|
||||
return {
|
||||
map: this.map.get(),
|
||||
code: this.buffer.get()
|
||||
};
|
||||
}
|
||||
|
||||
buildPrint(parent) {
|
||||
var print = (node, opts) => {
|
||||
return this.print(node, parent, opts);
|
||||
};
|
||||
|
||||
print.sequence = (nodes, opts = {}) => {
|
||||
opts.statement = true;
|
||||
return this.printJoin(print, nodes, opts);
|
||||
};
|
||||
|
||||
print.join = (nodes, opts) => {
|
||||
return this.printJoin(print, nodes, opts);
|
||||
};
|
||||
|
||||
print.list = function (items, opts = {}) {
|
||||
opts.separator ||= ", ";
|
||||
print.join(items, opts);
|
||||
};
|
||||
|
||||
print.block = (node) => {
|
||||
return this.printBlock(print, node);
|
||||
};
|
||||
|
||||
print.indentOnComments = (node) => {
|
||||
return this.printAndIndentOnComments(print, node);
|
||||
};
|
||||
|
||||
return print;
|
||||
}
|
||||
|
||||
print(node, parent, opts = {}) {
|
||||
if (!node) return;
|
||||
|
||||
if (parent && parent._compact) {
|
||||
node._compact = true;
|
||||
}
|
||||
|
||||
var oldConcise = this.format.concise;
|
||||
if (node._compact) {
|
||||
this.format.concise = true;
|
||||
}
|
||||
|
||||
var newline = (leading) => {
|
||||
if (!opts.statement && !n.isUserWhitespacable(node, parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lines = 0;
|
||||
|
||||
if (node.start != null && !node._ignoreUserWhitespace) {
|
||||
// user node
|
||||
if (leading) {
|
||||
lines = this.whitespace.getNewlinesBefore(node);
|
||||
} else {
|
||||
lines = this.whitespace.getNewlinesAfter(node);
|
||||
}
|
||||
} else {
|
||||
// generated node
|
||||
if (!leading) lines++; // always include at least a single line after
|
||||
if (opts.addNewlines) lines += opts.addNewlines(leading, node) || 0;
|
||||
|
||||
var needs = n.needsWhitespaceAfter;
|
||||
if (leading) needs = n.needsWhitespaceBefore;
|
||||
if (needs(node, parent)) lines++;
|
||||
|
||||
// generated nodes can't add starting file whitespace
|
||||
if (!this.buffer.buf) lines = 0;
|
||||
}
|
||||
|
||||
this.newline(lines);
|
||||
};
|
||||
|
||||
if (this[node.type]) {
|
||||
var needsNoLineTermParens = n.needsParensNoLineTerminator(node, parent);
|
||||
var needsParens = needsNoLineTermParens || n.needsParens(node, parent);
|
||||
|
||||
if (needsParens) this.push("(");
|
||||
if (needsNoLineTermParens) this.indent();
|
||||
|
||||
this.printLeadingComments(node, parent);
|
||||
|
||||
newline(true);
|
||||
|
||||
if (opts.before) opts.before();
|
||||
this.map.mark(node, "start");
|
||||
|
||||
this[node.type](node, this.buildPrint(node), parent);
|
||||
|
||||
if (needsNoLineTermParens) {
|
||||
this.newline();
|
||||
this.dedent();
|
||||
}
|
||||
if (needsParens) this.push(")");
|
||||
|
||||
this.map.mark(node, "end");
|
||||
if (opts.after) opts.after();
|
||||
|
||||
newline(false);
|
||||
|
||||
this.printTrailingComments(node, parent);
|
||||
} else {
|
||||
throw new ReferenceError("unknown node of type " + JSON.stringify(node.type) + " with constructor " + JSON.stringify(node && node.constructor.name));
|
||||
}
|
||||
|
||||
this.format.concise = oldConcise;
|
||||
}
|
||||
|
||||
printJoin(print, nodes, opts = {}) {
|
||||
if (!nodes || !nodes.length) return;
|
||||
|
||||
var len = nodes.length;
|
||||
|
||||
if (opts.indent) this.indent();
|
||||
|
||||
each(nodes, (node, i) => {
|
||||
print(node, {
|
||||
statement: opts.statement,
|
||||
addNewlines: opts.addNewlines,
|
||||
after: () => {
|
||||
if (opts.iterator) {
|
||||
opts.iterator(node, i);
|
||||
}
|
||||
|
||||
if (opts.separator && i < len - 1) {
|
||||
this.push(opts.separator);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (opts.indent) this.dedent();
|
||||
}
|
||||
|
||||
printAndIndentOnComments(print, node) {
|
||||
var indent = !!node.leadingComments;
|
||||
if (indent) this.indent();
|
||||
print(node);
|
||||
if (indent) this.dedent();
|
||||
}
|
||||
|
||||
printBlock(print, node) {
|
||||
if (t.isEmptyStatement(node)) {
|
||||
this.semicolon();
|
||||
} else {
|
||||
this.push(" ");
|
||||
print(node);
|
||||
}
|
||||
}
|
||||
|
||||
generateComment(comment) {
|
||||
var val = comment.value;
|
||||
if (comment.type === "Line") {
|
||||
val = "//" + val;
|
||||
} else {
|
||||
val = "/*" + val + "*/";
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
printTrailingComments(node, parent) {
|
||||
this._printComments(this.getComments("trailingComments", node, parent));
|
||||
}
|
||||
|
||||
printLeadingComments(node, parent) {
|
||||
this._printComments(this.getComments("leadingComments", node, parent));
|
||||
}
|
||||
|
||||
getComments(key, node, parent) {
|
||||
if (t.isExpressionStatement(parent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var comments = [];
|
||||
var nodes = [node];
|
||||
|
||||
if (t.isExpressionStatement(node)) {
|
||||
nodes.push(node.argument);
|
||||
}
|
||||
|
||||
each(nodes, (node) => {
|
||||
comments = comments.concat(this._getComments(key, node));
|
||||
});
|
||||
|
||||
return comments;
|
||||
}
|
||||
|
||||
_getComments(key, node) {
|
||||
return (node && node[key]) || [];
|
||||
}
|
||||
|
||||
_printComments(comments) {
|
||||
if (this.format.compact) return;
|
||||
|
||||
if (!this.format.comments) return;
|
||||
if (!comments || !comments.length) return;
|
||||
|
||||
each(comments, (comment) => {
|
||||
var skip = false;
|
||||
|
||||
// find the original comment in the ast and set it as displayed
|
||||
each(this.ast.comments, function (origComment) {
|
||||
if (origComment.start === comment.start) {
|
||||
// comment has already been output
|
||||
if (origComment._displayed) skip = true;
|
||||
|
||||
origComment._displayed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (skip) return;
|
||||
|
||||
// whitespace before
|
||||
this.newline(this.whitespace.getNewlinesBefore(comment));
|
||||
|
||||
var column = this.position.column;
|
||||
var val = this.generateComment(comment);
|
||||
|
||||
if (column && !this.isLast(["\n", " ", "[", "{"])) {
|
||||
this._push(" ");
|
||||
column++;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (comment.type === "Block" && this.format.indent.adjustMultilineComment) {
|
||||
var offset = comment.loc.start.column;
|
||||
if (offset) {
|
||||
var newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
|
||||
val = val.replace(newlineRegex, "\n");
|
||||
}
|
||||
|
||||
var indent = Math.max(this.indentSize(), column);
|
||||
val = val.replace(/\n/g, "\n" + repeating(" ", indent));
|
||||
}
|
||||
|
||||
if (column === 0) {
|
||||
val = this.getIndent() + val;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
this._push(val);
|
||||
|
||||
// whitespace after
|
||||
this.newline(this.whitespace.getNewlinesAfter(comment));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
each(Buffer.prototype, function (fn, key) {
|
||||
@@ -40,321 +342,13 @@ each(Buffer.prototype, function (fn, key) {
|
||||
};
|
||||
});
|
||||
|
||||
CodeGenerator.normalizeOptions = function (code, opts) {
|
||||
var style = " ";
|
||||
if (code) {
|
||||
var indent = detectIndent(code).indent;
|
||||
if (indent && indent !== " ") style = indent;
|
||||
}
|
||||
|
||||
var format = {
|
||||
comments: opts.comments == null || opts.comments,
|
||||
compact: opts.compact,
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
style: style,
|
||||
base: 0
|
||||
}
|
||||
};
|
||||
|
||||
if (format.compact === "auto") {
|
||||
format.compact = code.length > 100000; // 100KB
|
||||
|
||||
if (format.compact) {
|
||||
console.error(messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
};
|
||||
|
||||
CodeGenerator.generators = {
|
||||
templateLiterals: require("./generators/template-literals"),
|
||||
comprehensions: require("./generators/comprehensions"),
|
||||
expressions: require("./generators/expressions"),
|
||||
statements: require("./generators/statements"),
|
||||
playground: require("./generators/playground"),
|
||||
classes: require("./generators/classes"),
|
||||
methods: require("./generators/methods"),
|
||||
modules: require("./generators/modules"),
|
||||
types: require("./generators/types"),
|
||||
flow: require("./generators/flow"),
|
||||
base: require("./generators/base"),
|
||||
jsx: require("./generators/jsx")
|
||||
};
|
||||
|
||||
each(CodeGenerator.generators, function (generator) {
|
||||
extend(CodeGenerator.prototype, generator);
|
||||
});
|
||||
|
||||
CodeGenerator.prototype.generate = function () {
|
||||
var ast = this.ast;
|
||||
|
||||
this.print(ast);
|
||||
|
||||
var comments = [];
|
||||
each(ast.comments, function (comment) {
|
||||
if (!comment._displayed) comments.push(comment);
|
||||
});
|
||||
this._printComments(comments);
|
||||
|
||||
return {
|
||||
map: this.map.get(),
|
||||
code: this.buffer.get()
|
||||
};
|
||||
module.exports = function (ast, opts, code) {
|
||||
var gen = new CodeGenerator(ast, opts, code);
|
||||
return gen.generate();
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.buildPrint = function (parent) {
|
||||
var print = (node, opts) => {
|
||||
return this.print(node, parent, opts);
|
||||
};
|
||||
|
||||
print.sequence = (nodes, opts) => {
|
||||
opts = opts || {};
|
||||
opts.statement = true;
|
||||
return this.printJoin(print, nodes, opts);
|
||||
};
|
||||
|
||||
print.join = (nodes, opts) => {
|
||||
return this.printJoin(print, nodes, opts);
|
||||
};
|
||||
|
||||
print.list = function (items, opts) {
|
||||
opts = opts || {};
|
||||
opts.separator = opts.separator || ", ";
|
||||
print.join(items, opts);
|
||||
};
|
||||
|
||||
print.block = (node) => {
|
||||
return this.printBlock(print, node);
|
||||
};
|
||||
|
||||
print.indentOnComments = (node) => {
|
||||
return this.printAndIndentOnComments(print, node);
|
||||
};
|
||||
|
||||
return print;
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.print = function (node, parent, opts) {
|
||||
if (!node) return "";
|
||||
|
||||
if (parent && parent._compact) {
|
||||
node._compact = true;
|
||||
}
|
||||
|
||||
var oldConcise = this.format.concise;
|
||||
if (node._compact) {
|
||||
this.format.concise = true;
|
||||
}
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
var newline = (leading) => {
|
||||
if (!opts.statement && !n.isUserWhitespacable(node, parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lines = 0;
|
||||
|
||||
if (node.start != null && !node._ignoreUserWhitespace) {
|
||||
// user node
|
||||
if (leading) {
|
||||
lines = this.whitespace.getNewlinesBefore(node);
|
||||
} else {
|
||||
lines = this.whitespace.getNewlinesAfter(node);
|
||||
}
|
||||
} else {
|
||||
// generated node
|
||||
if (!leading) lines++; // always include at least a single line after
|
||||
if (opts.addNewlines) lines += opts.addNewlines(leading, node) || 0;
|
||||
|
||||
var needs = n.needsWhitespaceAfter;
|
||||
if (leading) needs = n.needsWhitespaceBefore;
|
||||
if (needs(node, parent)) lines++;
|
||||
|
||||
// generated nodes can't add starting file whitespace
|
||||
if (!this.buffer.buf) lines = 0;
|
||||
}
|
||||
|
||||
this.newline(lines);
|
||||
};
|
||||
|
||||
if (this[node.type]) {
|
||||
var needsNoLineTermParens = n.needsParensNoLineTerminator(node, parent);
|
||||
var needsParens = needsNoLineTermParens || n.needsParens(node, parent);
|
||||
|
||||
if (needsParens) this.push("(");
|
||||
if (needsNoLineTermParens) this.indent();
|
||||
|
||||
this.printLeadingComments(node, parent);
|
||||
|
||||
newline(true);
|
||||
|
||||
if (opts.before) opts.before();
|
||||
this.map.mark(node, "start");
|
||||
|
||||
this[node.type](node, this.buildPrint(node), parent);
|
||||
|
||||
if (needsNoLineTermParens) {
|
||||
this.newline();
|
||||
this.dedent();
|
||||
}
|
||||
if (needsParens) this.push(")");
|
||||
|
||||
this.map.mark(node, "end");
|
||||
if (opts.after) opts.after();
|
||||
|
||||
newline(false);
|
||||
|
||||
this.printTrailingComments(node, parent);
|
||||
} else {
|
||||
throw new ReferenceError("unknown node of type " + JSON.stringify(node.type) + " with constructor " + JSON.stringify(node && node.constructor.name));
|
||||
}
|
||||
|
||||
this.format.concise = oldConcise;
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.printJoin = function (print, nodes, opts) {
|
||||
if (!nodes || !nodes.length) return;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
var len = nodes.length;
|
||||
|
||||
if (opts.indent) this.indent();
|
||||
|
||||
each(nodes, (node, i) => {
|
||||
print(node, {
|
||||
statement: opts.statement,
|
||||
addNewlines: opts.addNewlines,
|
||||
after: () => {
|
||||
if (opts.iterator) {
|
||||
opts.iterator(node, i);
|
||||
}
|
||||
|
||||
if (opts.separator && i < len - 1) {
|
||||
this.push(opts.separator);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (opts.indent) this.dedent();
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.printAndIndentOnComments = function (print, node) {
|
||||
var indent = !!node.leadingComments;
|
||||
if (indent) this.indent();
|
||||
print(node);
|
||||
if (indent) this.dedent();
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.printBlock = function (print, node) {
|
||||
if (t.isEmptyStatement(node)) {
|
||||
this.semicolon();
|
||||
} else {
|
||||
this.push(" ");
|
||||
print(node);
|
||||
}
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.generateComment = function (comment) {
|
||||
var val = comment.value;
|
||||
if (comment.type === "Line") {
|
||||
val = "//" + val;
|
||||
} else {
|
||||
val = "/*" + val + "*/";
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.printTrailingComments = function (node, parent) {
|
||||
this._printComments(this.getComments("trailingComments", node, parent));
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.printLeadingComments = function (node, parent) {
|
||||
this._printComments(this.getComments("leadingComments", node, parent));
|
||||
};
|
||||
|
||||
CodeGenerator.prototype.getComments = function (key, node, parent) {
|
||||
if (t.isExpressionStatement(parent)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var comments = [];
|
||||
var nodes = [node];
|
||||
|
||||
if (t.isExpressionStatement(node)) {
|
||||
nodes.push(node.argument);
|
||||
}
|
||||
|
||||
each(nodes, (node) => {
|
||||
comments = comments.concat(this._getComments(key, node));
|
||||
});
|
||||
|
||||
return comments;
|
||||
};
|
||||
|
||||
CodeGenerator.prototype._getComments = function (key, node) {
|
||||
return (node && node[key]) || [];
|
||||
};
|
||||
|
||||
CodeGenerator.prototype._printComments = function (comments) {
|
||||
if (this.format.compact) return;
|
||||
|
||||
if (!this.format.comments) return;
|
||||
if (!comments || !comments.length) return;
|
||||
|
||||
each(comments, (comment) => {
|
||||
var skip = false;
|
||||
|
||||
// find the original comment in the ast and set it as displayed
|
||||
each(this.ast.comments, function (origComment) {
|
||||
if (origComment.start === comment.start) {
|
||||
// comment has already been output
|
||||
if (origComment._displayed) skip = true;
|
||||
|
||||
origComment._displayed = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (skip) return;
|
||||
|
||||
// whitespace before
|
||||
this.newline(this.whitespace.getNewlinesBefore(comment));
|
||||
|
||||
var column = this.position.column;
|
||||
var val = this.generateComment(comment);
|
||||
|
||||
if (column && !this.isLast(["\n", " ", "[", "{"])) {
|
||||
this._push(" ");
|
||||
column++;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (comment.type === "Block" && this.format.indent.adjustMultilineComment) {
|
||||
var offset = comment.loc.start.column;
|
||||
if (offset) {
|
||||
var newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
|
||||
val = val.replace(newlineRegex, "\n");
|
||||
}
|
||||
|
||||
var indent = Math.max(this.indentSize(), column);
|
||||
val = val.replace(/\n/g, "\n" + repeating(" ", indent));
|
||||
}
|
||||
|
||||
if (column === 0) {
|
||||
val = this.getIndent() + val;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
this._push(val);
|
||||
|
||||
// whitespace after
|
||||
this.newline(this.whitespace.getNewlinesAfter(comment));
|
||||
});
|
||||
};
|
||||
module.exports.CodeGenerator = CodeGenerator;
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = Node;
|
||||
|
||||
var whitespace = require("./whitespace");
|
||||
var parens = require("./parentheses");
|
||||
var each = require("lodash/collection/each");
|
||||
var some = require("lodash/collection/some");
|
||||
var t = require("../../types");
|
||||
import whitespace from "./whitespace";
|
||||
import * as parens from "./parentheses";
|
||||
import each from "lodash/collection/each";
|
||||
import some from "lodash/collection/some";
|
||||
import t from "../../types";
|
||||
|
||||
var find = function (obj, node, parent) {
|
||||
if (!obj) return;
|
||||
@@ -26,79 +22,81 @@ var find = function (obj, node, parent) {
|
||||
return result;
|
||||
};
|
||||
|
||||
function Node(node, parent) {
|
||||
this.parent = parent;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
Node.isUserWhitespacable = function (node) {
|
||||
return t.isUserWhitespacable(node);
|
||||
};
|
||||
|
||||
Node.needsWhitespace = function (node, parent, type) {
|
||||
if (!node) return 0;
|
||||
|
||||
if (t.isExpressionStatement(node)) {
|
||||
node = node.expression;
|
||||
export default class Node {
|
||||
constructor(node, parent) {
|
||||
this.parent = parent;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
var linesInfo = find(whitespace.nodes, node, parent);
|
||||
static isUserWhitespacable(node) {
|
||||
return t.isUserWhitespacable(node);
|
||||
}
|
||||
|
||||
if (!linesInfo) {
|
||||
var items = find(whitespace.list, node, parent);
|
||||
if (items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
linesInfo = Node.needsWhitespace(items[i], node, type);
|
||||
if (linesInfo) break;
|
||||
static needsWhitespace(node, parent, type) {
|
||||
if (!node) return 0;
|
||||
|
||||
if (t.isExpressionStatement(node)) {
|
||||
node = node.expression;
|
||||
}
|
||||
|
||||
var linesInfo = find(whitespace.nodes, node, parent);
|
||||
|
||||
if (!linesInfo) {
|
||||
var items = find(whitespace.list, node, parent);
|
||||
if (items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
linesInfo = Node.needsWhitespace(items[i], node, type);
|
||||
if (linesInfo) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (linesInfo && linesInfo[type]) || 0;
|
||||
}
|
||||
|
||||
return (linesInfo && linesInfo[type]) || 0;
|
||||
};
|
||||
|
||||
Node.needsWhitespaceBefore = function (node, parent) {
|
||||
return Node.needsWhitespace(node, parent, "before");
|
||||
};
|
||||
|
||||
Node.needsWhitespaceAfter = function (node, parent) {
|
||||
return Node.needsWhitespace(node, parent, "after");
|
||||
};
|
||||
|
||||
Node.needsParens = function (node, parent) {
|
||||
if (!parent) return false;
|
||||
|
||||
if (t.isNewExpression(parent) && parent.callee === node) {
|
||||
if (t.isCallExpression(node)) return true;
|
||||
|
||||
var hasCall = some(node, function (val) {
|
||||
return t.isCallExpression(val);
|
||||
});
|
||||
if (hasCall) return true;
|
||||
static needsWhitespaceBefore(node, parent) {
|
||||
return Node.needsWhitespace(node, parent, "before");
|
||||
}
|
||||
|
||||
return find(parens, node, parent);
|
||||
};
|
||||
static needsWhitespaceAfter(node, parent) {
|
||||
return Node.needsWhitespace(node, parent, "after");
|
||||
}
|
||||
|
||||
Node.needsParensNoLineTerminator = function (node, parent) {
|
||||
if (!parent) return false;
|
||||
static needsParens(node, parent) {
|
||||
if (!parent) return false;
|
||||
|
||||
if (t.isNewExpression(parent) && parent.callee === node) {
|
||||
if (t.isCallExpression(node)) return true;
|
||||
|
||||
var hasCall = some(node, function (val) {
|
||||
return t.isCallExpression(val);
|
||||
});
|
||||
if (hasCall) return true;
|
||||
}
|
||||
|
||||
return find(parens, node, parent);
|
||||
}
|
||||
|
||||
static needsParensNoLineTerminator(node, parent) {
|
||||
if (!parent) return false;
|
||||
|
||||
// no comments
|
||||
if (!node.leadingComments || !node.leadingComments.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t.isYieldExpression(parent) || t.isAwaitExpression(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isContinueStatement(parent) || t.isBreakStatement(parent) ||
|
||||
t.isReturnStatement(parent) || t.isThrowStatement(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// no comments
|
||||
if (!node.leadingComments || !node.leadingComments.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t.isYieldExpression(parent) || t.isAwaitExpression(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isContinueStatement(parent) || t.isBreakStatement(parent) ||
|
||||
t.isReturnStatement(parent) || t.isThrowStatement(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
each(Node, function (fn, key) {
|
||||
Node.prototype[key] = function () {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../types");
|
||||
var each = require("lodash/collection/each");
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../../types";
|
||||
|
||||
var PRECEDENCE = {};
|
||||
|
||||
@@ -23,14 +21,20 @@ each([
|
||||
});
|
||||
});
|
||||
|
||||
exports.UpdateExpression = function (node, parent) {
|
||||
export function NullableTypeAnnotation(node, parent) {
|
||||
return t.isArrayTypeAnnotation(parent);
|
||||
}
|
||||
|
||||
export { NullableTypeAnnotation as FunctionTypeAnnotation };
|
||||
|
||||
export function UpdateExpression(node, parent) {
|
||||
if (t.isMemberExpression(parent) && parent.object === node) {
|
||||
// (foo++).test()
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.ObjectExpression = function (node, parent) {
|
||||
export function ObjectExpression(node, parent) {
|
||||
if (t.isExpressionStatement(parent)) {
|
||||
// ({ foo: "bar" });
|
||||
return true;
|
||||
@@ -42,9 +46,9 @@ exports.ObjectExpression = function (node, parent) {
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
exports.Binary = function (node, parent) {
|
||||
export function Binary(node, parent) {
|
||||
if ((t.isCallExpression(parent) || t.isNewExpression(parent)) && parent.callee === node) {
|
||||
return true;
|
||||
}
|
||||
@@ -72,9 +76,9 @@ exports.Binary = function (node, parent) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.BinaryExpression = function (node, parent) {
|
||||
export function BinaryExpression(node, parent) {
|
||||
if (node.operator === "in") {
|
||||
// var i = (1 in []);
|
||||
if (t.isVariableDeclarator(parent)) {
|
||||
@@ -86,9 +90,9 @@ exports.BinaryExpression = function (node, parent) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.SequenceExpression = function (node, parent) {
|
||||
export function SequenceExpression(node, parent) {
|
||||
if (t.isForStatement(parent)) {
|
||||
// Although parentheses wouldn't hurt around sequence
|
||||
// expressions in the head of for loops, traditional style
|
||||
@@ -104,9 +108,9 @@ exports.SequenceExpression = function (node, parent) {
|
||||
// Otherwise err on the side of overparenthesization, adding
|
||||
// explicit exceptions above if this proves overzealous.
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
exports.YieldExpression = function (node, parent) {
|
||||
export function YieldExpression(node, parent) {
|
||||
return t.isBinary(parent) ||
|
||||
t.isUnaryLike(parent) ||
|
||||
t.isCallExpression(parent) ||
|
||||
@@ -114,17 +118,17 @@ exports.YieldExpression = function (node, parent) {
|
||||
t.isNewExpression(parent) ||
|
||||
t.isConditionalExpression(parent) ||
|
||||
t.isYieldExpression(parent);
|
||||
};
|
||||
}
|
||||
|
||||
exports.ClassExpression = function (node, parent) {
|
||||
export function ClassExpression(node, parent) {
|
||||
return t.isExpressionStatement(parent);
|
||||
};
|
||||
}
|
||||
|
||||
exports.UnaryLike = function (node, parent) {
|
||||
export function UnaryLike(node, parent) {
|
||||
return t.isMemberExpression(parent) && parent.object === node;
|
||||
};
|
||||
}
|
||||
|
||||
exports.FunctionExpression = function (node, parent) {
|
||||
export function FunctionExpression(node, parent) {
|
||||
// function () {};
|
||||
if (t.isExpressionStatement(parent)) {
|
||||
return true;
|
||||
@@ -139,10 +143,9 @@ exports.FunctionExpression = function (node, parent) {
|
||||
if (t.isCallExpression(parent) && parent.callee === node) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.AssignmentExpression =
|
||||
exports.ConditionalExpression = function (node, parent) {
|
||||
export function ConditionalExpression(node, parent) {
|
||||
if (t.isUnaryLike(parent)) {
|
||||
return true;
|
||||
}
|
||||
@@ -166,4 +169,6 @@ exports.ConditionalExpression = function (node, parent) {
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
export { ConditionalExpression as AssignmentExpression };
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
var isBoolean = require("lodash/lang/isBoolean");
|
||||
var each = require("lodash/collection/each");
|
||||
var map = require("lodash/collection/map");
|
||||
var t = require("../../types");
|
||||
|
||||
var crawl = function (node, state) {
|
||||
state = state || {};
|
||||
import isBoolean from "lodash/lang/isBoolean";
|
||||
import each from "lodash/collection/each";
|
||||
import map from "lodash/collection/map";
|
||||
import t from "../../types";
|
||||
|
||||
function crawl(node, state = {}) {
|
||||
if (t.isMemberExpression(node)) {
|
||||
crawl(node.object, state);
|
||||
if (node.computed) crawl(node.property, state);
|
||||
@@ -20,13 +16,13 @@ var crawl = function (node, state) {
|
||||
} else if (t.isFunction(node)) {
|
||||
state.hasFunction = true;
|
||||
} else if (t.isIdentifier(node)) {
|
||||
state.hasHelper = state.hasHelper || isHelper(node.callee);
|
||||
state.hasHelper ||= isHelper(node.callee);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
}
|
||||
|
||||
var isHelper = function (node) {
|
||||
function isHelper(node) {
|
||||
if (t.isMemberExpression(node)) {
|
||||
return isHelper(node.object) || isHelper(node.property);
|
||||
} else if (t.isIdentifier(node)) {
|
||||
@@ -38,15 +34,15 @@ var isHelper = function (node) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var isType = function (node) {
|
||||
function isType(node) {
|
||||
return t.isLiteral(node) || t.isObjectExpression(node) || t.isArrayExpression(node) ||
|
||||
t.isIdentifier(node) || t.isMemberExpression(node);
|
||||
};
|
||||
}
|
||||
|
||||
exports.nodes = {
|
||||
AssignmentExpression: function (node) {
|
||||
AssignmentExpression(node) {
|
||||
var state = crawl(node.right);
|
||||
if ((state.hasCall && state.hasHelper) || state.hasFunction) {
|
||||
return {
|
||||
@@ -56,13 +52,13 @@ exports.nodes = {
|
||||
}
|
||||
},
|
||||
|
||||
SwitchCase: function (node, parent) {
|
||||
SwitchCase(node, parent) {
|
||||
return {
|
||||
before: node.consequent.length || parent.cases[0] === node
|
||||
};
|
||||
},
|
||||
|
||||
LogicalExpression: function (node) {
|
||||
LogicalExpression(node) {
|
||||
if (t.isFunction(node.left) || t.isFunction(node.right)) {
|
||||
return {
|
||||
after: true
|
||||
@@ -70,7 +66,7 @@ exports.nodes = {
|
||||
}
|
||||
},
|
||||
|
||||
Literal: function (node) {
|
||||
Literal(node) {
|
||||
if (node.value === "use strict") {
|
||||
return {
|
||||
after: true
|
||||
@@ -78,7 +74,7 @@ exports.nodes = {
|
||||
}
|
||||
},
|
||||
|
||||
CallExpression: function (node) {
|
||||
CallExpression(node) {
|
||||
if (t.isFunction(node.callee) || isHelper(node)) {
|
||||
return {
|
||||
before: true,
|
||||
@@ -87,7 +83,7 @@ exports.nodes = {
|
||||
}
|
||||
},
|
||||
|
||||
VariableDeclaration: function (node) {
|
||||
VariableDeclaration(node) {
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
var declar = node.declarations[i];
|
||||
|
||||
@@ -106,7 +102,7 @@ exports.nodes = {
|
||||
}
|
||||
},
|
||||
|
||||
IfStatement: function (node) {
|
||||
IfStatement(node) {
|
||||
if (t.isBlockStatement(node.consequent)) {
|
||||
return {
|
||||
before: true,
|
||||
@@ -126,15 +122,15 @@ exports.nodes.SpreadProperty = function (node, parent) {
|
||||
};
|
||||
|
||||
exports.list = {
|
||||
VariableDeclaration: function (node) {
|
||||
VariableDeclaration(node) {
|
||||
return map(node.declarations, "init");
|
||||
},
|
||||
|
||||
ArrayExpression: function (node) {
|
||||
ArrayExpression(node) {
|
||||
return node.elements;
|
||||
},
|
||||
|
||||
ObjectExpression: function (node) {
|
||||
ObjectExpression(node) {
|
||||
return node.properties;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
"use strict";
|
||||
export default class Position {
|
||||
constructor() {
|
||||
this.line = 1;
|
||||
this.column = 0;
|
||||
}
|
||||
|
||||
module.exports = Position;
|
||||
push(str) {
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (str[i] === "\n") {
|
||||
this.line++;
|
||||
this.column = 0;
|
||||
} else {
|
||||
this.column++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Position() {
|
||||
this.line = 1;
|
||||
this.column = 0;
|
||||
unshift(str) {
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (str[i] === "\n") {
|
||||
this.line--;
|
||||
} else {
|
||||
this.column--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Position.prototype.push = function (str) {
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (str[i] === "\n") {
|
||||
this.line++;
|
||||
this.column = 0;
|
||||
} else {
|
||||
this.column++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Position.prototype.unshift = function (str) {
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (str[i] === "\n") {
|
||||
this.line--;
|
||||
} else {
|
||||
this.column--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,56 +1,54 @@
|
||||
"use strict";
|
||||
import sourceMap from "source-map";
|
||||
import t from "../types";
|
||||
|
||||
module.exports = SourceMap;
|
||||
export default class SourceMap {
|
||||
constructor(position, opts, code) {
|
||||
this.position = position;
|
||||
this.opts = opts;
|
||||
|
||||
var sourceMap = require("source-map");
|
||||
var t = require("../types");
|
||||
if (opts.sourceMap) {
|
||||
this.map = new sourceMap.SourceMapGenerator({
|
||||
file: opts.sourceMapName,
|
||||
sourceRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
function SourceMap(position, opts, code) {
|
||||
this.position = position;
|
||||
this.opts = opts;
|
||||
this.map.setSourceContent(opts.sourceFileName, code);
|
||||
} else {
|
||||
this.map = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.sourceMap) {
|
||||
this.map = new sourceMap.SourceMapGenerator({
|
||||
file: opts.sourceMapName,
|
||||
sourceRoot: opts.sourceRoot
|
||||
get() {
|
||||
var map = this.map;
|
||||
if (map) {
|
||||
return map.toJSON();
|
||||
} else {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
mark(node, type) {
|
||||
var loc = node.loc;
|
||||
if (!loc) return; // no location info
|
||||
|
||||
var map = this.map;
|
||||
if (!map) return; // no source map
|
||||
|
||||
if (t.isProgram(node) || t.isFile(node)) return; // illegal mapping nodes
|
||||
|
||||
var position = this.position;
|
||||
|
||||
var generated = {
|
||||
line: position.line,
|
||||
column: position.column
|
||||
};
|
||||
|
||||
var original = loc[type];
|
||||
|
||||
map.addMapping({
|
||||
source: this.opts.sourceFileName,
|
||||
generated: generated,
|
||||
original: original
|
||||
});
|
||||
|
||||
this.map.setSourceContent(opts.sourceFileName, code);
|
||||
} else {
|
||||
this.map = null;
|
||||
}
|
||||
}
|
||||
|
||||
SourceMap.prototype.get = function () {
|
||||
var map = this.map;
|
||||
if (map) {
|
||||
return map.toJSON();
|
||||
} else {
|
||||
return map;
|
||||
}
|
||||
};
|
||||
|
||||
SourceMap.prototype.mark = function (node, type) {
|
||||
var loc = node.loc;
|
||||
if (!loc) return; // no location info
|
||||
|
||||
var map = this.map;
|
||||
if (!map) return; // no source map
|
||||
|
||||
if (t.isProgram(node) || t.isFile(node)) return; // illegal mapping nodes
|
||||
|
||||
var position = this.position;
|
||||
|
||||
var generated = {
|
||||
line: position.line,
|
||||
column: position.column
|
||||
};
|
||||
|
||||
var original = loc[type];
|
||||
|
||||
map.addMapping({
|
||||
source: this.opts.sourceFileName,
|
||||
generated: generated,
|
||||
original: original
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = Whitespace;
|
||||
|
||||
var sortBy = require("lodash/collection/sortBy");
|
||||
import sortBy from "lodash/collection/sortBy";
|
||||
|
||||
/**
|
||||
* Returns `i`th number from `base`, continuing from 0 when `max` is reached.
|
||||
@@ -24,92 +20,94 @@ function getLookupIndex(i, base, max) {
|
||||
return i;
|
||||
}
|
||||
|
||||
function Whitespace(tokens, comments) {
|
||||
this.tokens = sortBy(tokens.concat(comments), "start");
|
||||
this.used = {};
|
||||
export default class Whitespace {
|
||||
constructor(tokens, comments) {
|
||||
this.tokens = sortBy(tokens.concat(comments), "start");
|
||||
this.used = {};
|
||||
|
||||
// Profiling this code shows that while generator passes over it, indexes
|
||||
// returned by `getNewlinesBefore` and `getNewlinesAfter` are always increasing.
|
||||
// Profiling this code shows that while generator passes over it, indexes
|
||||
// returned by `getNewlinesBefore` and `getNewlinesAfter` are always increasing.
|
||||
|
||||
// We use this implementation detail for an optimization: instead of always
|
||||
// starting to look from `this.tokens[0]`, we will start `for` loops from the
|
||||
// previous successful match. We will enumerate all tokens—but the common
|
||||
// case will be much faster.
|
||||
// We use this implementation detail for an optimization: instead of always
|
||||
// starting to look from `this.tokens[0]`, we will start `for` loops from the
|
||||
// previous successful match. We will enumerate all tokens—but the common
|
||||
// case will be much faster.
|
||||
|
||||
this._lastFoundIndex = 0;
|
||||
}
|
||||
|
||||
Whitespace.prototype.getNewlinesBefore = function (node) {
|
||||
var startToken;
|
||||
var endToken;
|
||||
var tokens = this.tokens;
|
||||
var token;
|
||||
|
||||
for (var j = 0; j < tokens.length; j++) {
|
||||
// optimize for forward traversal by shifting for loop index
|
||||
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||
token = tokens[i];
|
||||
|
||||
// this is the token this node starts with
|
||||
if (node.start === token.start) {
|
||||
startToken = tokens[i - 1];
|
||||
endToken = token;
|
||||
|
||||
this._lastFoundIndex = i;
|
||||
break;
|
||||
}
|
||||
this._lastFoundIndex = 0;
|
||||
}
|
||||
|
||||
return this.getNewlinesBetween(startToken, endToken);
|
||||
};
|
||||
getNewlinesBefore(node) {
|
||||
var startToken;
|
||||
var endToken;
|
||||
var tokens = this.tokens;
|
||||
var token;
|
||||
|
||||
Whitespace.prototype.getNewlinesAfter = function (node) {
|
||||
var startToken;
|
||||
var endToken;
|
||||
var tokens = this.tokens;
|
||||
var token;
|
||||
for (var j = 0; j < tokens.length; j++) {
|
||||
// optimize for forward traversal by shifting for loop index
|
||||
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||
token = tokens[i];
|
||||
|
||||
for (var j = 0; j < tokens.length; j++) {
|
||||
// optimize for forward traversal by shifting for loop index
|
||||
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||
token = tokens[i];
|
||||
// this is the token this node starts with
|
||||
if (node.start === token.start) {
|
||||
startToken = tokens[i - 1];
|
||||
endToken = token;
|
||||
|
||||
// this is the token this node ends with
|
||||
if (node.end === token.end) {
|
||||
startToken = token;
|
||||
endToken = tokens[i + 1];
|
||||
|
||||
this._lastFoundIndex = i;
|
||||
break;
|
||||
this._lastFoundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this.getNewlinesBetween(startToken, endToken);
|
||||
}
|
||||
|
||||
if (endToken && endToken.type.type === "eof") {
|
||||
return 1;
|
||||
} else {
|
||||
var lines = this.getNewlinesBetween(startToken, endToken);
|
||||
if (node.type === "Line" && !lines) {
|
||||
// line comment
|
||||
getNewlinesAfter(node) {
|
||||
var startToken;
|
||||
var endToken;
|
||||
var tokens = this.tokens;
|
||||
var token;
|
||||
|
||||
for (var j = 0; j < tokens.length; j++) {
|
||||
// optimize for forward traversal by shifting for loop index
|
||||
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
|
||||
token = tokens[i];
|
||||
|
||||
// this is the token this node ends with
|
||||
if (node.end === token.end) {
|
||||
startToken = token;
|
||||
endToken = tokens[i + 1];
|
||||
|
||||
this._lastFoundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endToken && endToken.type.type === "eof") {
|
||||
return 1;
|
||||
} else {
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Whitespace.prototype.getNewlinesBetween = function (startToken, endToken) {
|
||||
if (!endToken || !endToken.loc) return 0;
|
||||
|
||||
var start = startToken ? startToken.loc.end.line : 1;
|
||||
var end = endToken.loc.start.line;
|
||||
var lines = 0;
|
||||
|
||||
for (var line = start; line < end; line++) {
|
||||
if (typeof this.used[line] === "undefined") {
|
||||
this.used[line] = true;
|
||||
lines++;
|
||||
var lines = this.getNewlinesBetween(startToken, endToken);
|
||||
if (node.type === "Line" && !lines) {
|
||||
// line comment
|
||||
return 1;
|
||||
} else {
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
};
|
||||
getNewlinesBetween(startToken, endToken) {
|
||||
if (!endToken || !endToken.loc) return 0;
|
||||
|
||||
var start = startToken ? startToken.loc.end.line : 1;
|
||||
var end = endToken.loc.start.line;
|
||||
var lines = 0;
|
||||
|
||||
for (var line = start; line < end; line++) {
|
||||
if (typeof this.used[line] === "undefined") {
|
||||
this.used[line] = true;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
var lineNumbers = require("line-numbers");
|
||||
var repeating = require("repeating");
|
||||
var jsTokens = require("js-tokens");
|
||||
var esutils = require("esutils");
|
||||
var chalk = require("chalk");
|
||||
var ary = require("lodash/function/ary");
|
||||
import lineNumbers from "line-numbers";
|
||||
import repeating from "repeating";
|
||||
import jsTokens from "js-tokens";
|
||||
import esutils from "esutils";
|
||||
import chalk from "chalk";
|
||||
import ary from "lodash/function/ary";
|
||||
|
||||
var defs = {
|
||||
string: chalk.red,
|
||||
punctuation: chalk.white.bold,
|
||||
operator: chalk.white.bold,
|
||||
curly: chalk.green,
|
||||
parens: chalk.blue.bold,
|
||||
square: chalk.yellow,
|
||||
name: chalk.white,
|
||||
keyword: chalk.cyan,
|
||||
number: chalk.magenta,
|
||||
regex: chalk.magenta,
|
||||
comment: chalk.grey,
|
||||
invalid: chalk.inverse
|
||||
string: chalk.red,
|
||||
punctuator: chalk.white.bold,
|
||||
curly: chalk.green,
|
||||
parens: chalk.blue.bold,
|
||||
square: chalk.yellow,
|
||||
name: chalk.white,
|
||||
keyword: chalk.cyan,
|
||||
number: chalk.magenta,
|
||||
regex: chalk.magenta,
|
||||
comment: chalk.grey,
|
||||
invalid: chalk.inverse
|
||||
};
|
||||
|
||||
var newline = /\r\n|[\n\r\u2028\u2029]/;
|
||||
@@ -25,11 +24,11 @@ var newline = /\r\n|[\n\r\u2028\u2029]/;
|
||||
var highlight = function (text) {
|
||||
var tokenType = function (match) {
|
||||
var token = jsTokens.matchToToken(match);
|
||||
if (token.type === "name" && esutils.keyword.isKeywordES6(token.value)) {
|
||||
if (token.type === "name" && esutils.keyword.isReservedWordES6(token.value)) {
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
if (token.type === "punctuation") {
|
||||
if (token.type === "punctuator") {
|
||||
switch (token.value) {
|
||||
case "{":
|
||||
case "}":
|
||||
@@ -77,7 +76,7 @@ module.exports = function (lines, lineNumber, colNumber) {
|
||||
start: start + 1,
|
||||
before: " ",
|
||||
after: " | ",
|
||||
transform: function (params) {
|
||||
transform(params) {
|
||||
if (params.number !== lineNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var t = require("../types");
|
||||
import t from "../types";
|
||||
|
||||
module.exports = function (ast, comments, tokens) {
|
||||
if (ast && ast.type === "Program") {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function () {
|
||||
return Object.create(null);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var normalizeAst = require("./normalize-ast");
|
||||
var estraverse = require("estraverse");
|
||||
var codeFrame = require("./code-frame");
|
||||
var acorn = require("acorn-babel");
|
||||
import normalizeAst from "./normalize-ast";
|
||||
import estraverse from "estraverse";
|
||||
import codeFrame from "./code-frame";
|
||||
import acorn from "acorn-babel";
|
||||
|
||||
module.exports = function (opts, code, callback) {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A trick from Bluebird to force V8 to use fast properties for an object.
|
||||
* Read more: http://stackoverflow.com/questions/24987896/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var util = require("util");
|
||||
import * as util from "util";
|
||||
|
||||
exports.messages = {
|
||||
export var messages = {
|
||||
tailCallReassignmentDeopt: "Function reference has been reassigned so it's probably be dereferenced so we can't optimise this with confidence",
|
||||
JSXNamespacedTags: "Namespace tags are not supported. ReactJSX is not XML.",
|
||||
classesIllegalBareSuper: "Illegal use of bare super",
|
||||
@@ -21,7 +21,7 @@ exports.messages = {
|
||||
codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2."
|
||||
};
|
||||
|
||||
exports.get = function (key) {
|
||||
export function get(key) {
|
||||
var msg = exports.messages[key];
|
||||
if (!msg) throw new ReferenceError("Unknown message `" + key + "`");
|
||||
|
||||
@@ -34,9 +34,9 @@ exports.get = function (key) {
|
||||
return msg.replace(/\$(\d+)/g, function (str, i) {
|
||||
return args[--i];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
exports.parseArgs = function (args) {
|
||||
export function parseArgs(args) {
|
||||
return args.map(function (val) {
|
||||
if (val != null && val.inspect) {
|
||||
return val.inspect();
|
||||
@@ -48,4 +48,4 @@ exports.parseArgs = function (args) {
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
var extend = require("lodash/object/extend");
|
||||
var t = require("./types");
|
||||
import estraverse from "estraverse";
|
||||
import extend from "lodash/object/extend";
|
||||
import types from "ast-types";
|
||||
import t from "./types";
|
||||
|
||||
// estraverse
|
||||
|
||||
var estraverse = require("estraverse");
|
||||
extend(estraverse.VisitorKeys, t.VISITOR_KEYS);
|
||||
|
||||
// regenerator-babel/ast-types
|
||||
|
||||
var types = require("ast-types");
|
||||
var def = types.Type.def;
|
||||
var or = types.Type.or;
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
if (global._babelPolyfill) {
|
||||
throw new Error("only one instance of babel/polyfill is allowed");
|
||||
}
|
||||
global._babelPolyfill = true;
|
||||
|
||||
require("core-js/shim");
|
||||
require("regenerator-babel/runtime");
|
||||
import "core-js/shim";
|
||||
import "regenerator-babel/runtime";
|
||||
|
||||
@@ -1,471 +1,476 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = File;
|
||||
|
||||
var sourceMapToComment = require("source-map-to-comment");
|
||||
var shebangRegex = require("shebang-regex");
|
||||
var isFunction = require("lodash/lang/isFunction");
|
||||
var transform = require("./index");
|
||||
var generate = require("../generation");
|
||||
var defaults = require("lodash/object/defaults");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var assign = require("lodash/object/assign");
|
||||
var parse = require("../helpers/parse");
|
||||
var Scope = require("../traversal/scope");
|
||||
var slash = require("slash");
|
||||
var util = require("../util");
|
||||
var path = require("path");
|
||||
var each = require("lodash/collection/each");
|
||||
var t = require("../types");
|
||||
|
||||
function File(opts) {
|
||||
this.dynamicImportedNoDefault = [];
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImported = [];
|
||||
this.dynamicImports = [];
|
||||
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
|
||||
this.lastStatements = [];
|
||||
this.opts = this.normalizeOptions(opts);
|
||||
this.ast = {};
|
||||
|
||||
this.buildTransformers();
|
||||
}
|
||||
|
||||
File.helpers = [
|
||||
"inherits",
|
||||
"defaults",
|
||||
"prototype-properties",
|
||||
"apply-constructor",
|
||||
"tagged-template-literal",
|
||||
"tagged-template-literal-loose",
|
||||
"interop-require",
|
||||
"to-array",
|
||||
"to-consumable-array",
|
||||
"sliced-to-array",
|
||||
"object-without-properties",
|
||||
"has-own",
|
||||
"slice",
|
||||
"bind",
|
||||
"define-property",
|
||||
"async-to-generator",
|
||||
"interop-require-wildcard",
|
||||
"typeof",
|
||||
"extends",
|
||||
"get",
|
||||
"set",
|
||||
"class-call-check",
|
||||
"object-destructuring-empty",
|
||||
"temporal-undefined",
|
||||
"temporal-assert-defined",
|
||||
"self-global"
|
||||
];
|
||||
|
||||
File.validOptions = [
|
||||
"filename",
|
||||
"filenameRelative",
|
||||
"blacklist",
|
||||
"whitelist",
|
||||
"loose",
|
||||
"optional",
|
||||
"modules",
|
||||
"sourceMap",
|
||||
"sourceMapName",
|
||||
"sourceFileName",
|
||||
"sourceRoot",
|
||||
"moduleRoot",
|
||||
"moduleIds",
|
||||
"comments",
|
||||
"reactCompat",
|
||||
"keepModuleIdExtensions",
|
||||
"code",
|
||||
"ast",
|
||||
"playground",
|
||||
"experimental",
|
||||
"externalHelpers",
|
||||
"auxiliaryComment",
|
||||
"compact",
|
||||
|
||||
"resolveModuleSource",
|
||||
"moduleId",
|
||||
|
||||
// legacy
|
||||
"format",
|
||||
|
||||
// these are used by plugins
|
||||
"ignore",
|
||||
"only",
|
||||
"extensions",
|
||||
"accept"
|
||||
];
|
||||
|
||||
File.prototype.normalizeOptions = function (opts) {
|
||||
opts = assign({}, opts);
|
||||
|
||||
for (var key in opts) {
|
||||
if (key[0] !== "_" && File.validOptions.indexOf(key) < 0) {
|
||||
throw new ReferenceError("Unknown option: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
defaults(opts, {
|
||||
keepModuleIdExtensions: false,
|
||||
resolveModuleSource: null,
|
||||
externalHelpers: false,
|
||||
auxilaryComment: "",
|
||||
experimental: false,
|
||||
reactCompat: false,
|
||||
playground: false,
|
||||
moduleIds: false,
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
optional: [],
|
||||
comments: true,
|
||||
filename: "unknown",
|
||||
modules: "common",
|
||||
compact: "auto",
|
||||
loose: [],
|
||||
code: true,
|
||||
ast: true
|
||||
});
|
||||
|
||||
// normalize windows path separators to unix
|
||||
opts.filename = slash(opts.filename);
|
||||
if (opts.sourceRoot) {
|
||||
opts.sourceRoot = slash(opts.sourceRoot);
|
||||
}
|
||||
|
||||
if (opts.moduleId) {
|
||||
opts.moduleIds = true;
|
||||
}
|
||||
|
||||
opts.basename = path.basename(opts.filename, path.extname(opts.filename));
|
||||
|
||||
opts.blacklist = util.arrayify(opts.blacklist);
|
||||
opts.whitelist = util.arrayify(opts.whitelist);
|
||||
opts.optional = util.arrayify(opts.optional);
|
||||
opts.compact = util.booleanify(opts.compact);
|
||||
opts.loose = util.arrayify(opts.loose);
|
||||
|
||||
if (includes(opts.loose, "all") || includes(opts.loose, true)) {
|
||||
opts.loose = Object.keys(transform.transformers);
|
||||
}
|
||||
|
||||
defaults(opts, {
|
||||
moduleRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceRoot: opts.moduleRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
filenameRelative: opts.filename
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceFileName: opts.filenameRelative,
|
||||
sourceMapName: opts.filenameRelative
|
||||
});
|
||||
|
||||
if (opts.playground) {
|
||||
opts.experimental = true;
|
||||
}
|
||||
|
||||
if (opts.externalHelpers) {
|
||||
this.set("helpersNamespace", t.identifier("babelHelpers"));
|
||||
}
|
||||
|
||||
opts.blacklist = transform._ensureTransformerNames("blacklist", opts.blacklist);
|
||||
opts.whitelist = transform._ensureTransformerNames("whitelist", opts.whitelist);
|
||||
opts.optional = transform._ensureTransformerNames("optional", opts.optional);
|
||||
opts.loose = transform._ensureTransformerNames("loose", opts.loose);
|
||||
|
||||
if (opts.reactCompat) {
|
||||
opts.optional.push("reactCompat");
|
||||
console.error("The reactCompat option has been moved into the optional transformer `reactCompat`");
|
||||
}
|
||||
|
||||
var ensureEnabled = function (key) {
|
||||
var namespace = transform.transformerNamespaces[key];
|
||||
if (namespace === "es7") opts.experimental = true;
|
||||
if (namespace === "playground") opts.playground = true;
|
||||
};
|
||||
|
||||
each(opts.whitelist, ensureEnabled);
|
||||
each(opts.optional, ensureEnabled);
|
||||
|
||||
return opts;
|
||||
};
|
||||
|
||||
File.prototype.isLoose = function (key) {
|
||||
return includes(this.opts.loose, key);
|
||||
};
|
||||
|
||||
File.prototype.buildTransformers = function () {
|
||||
var file = this;
|
||||
|
||||
var transformers = {};
|
||||
|
||||
var secondaryStack = [];
|
||||
var stack = [];
|
||||
|
||||
each(transform.transformers, function (transformer, key) {
|
||||
var pass = transformers[key] = transformer.buildPass(file);
|
||||
|
||||
if (pass.canRun(file)) {
|
||||
stack.push(pass);
|
||||
|
||||
if (transformer.secondPass) {
|
||||
secondaryStack.push(pass);
|
||||
}
|
||||
|
||||
if (transformer.manipulateOptions) {
|
||||
transformer.manipulateOptions(file.opts, file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.transformerStack = stack.concat(secondaryStack);
|
||||
this.transformers = transformers;
|
||||
};
|
||||
|
||||
File.prototype.debug = function (msg) {
|
||||
var parts = this.opts.filename;
|
||||
if (msg) parts += ": " + msg;
|
||||
util.debug(parts);
|
||||
};
|
||||
|
||||
File.prototype.getModuleFormatter = function (type) {
|
||||
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolve(type);
|
||||
if (loc) ModuleFormatter = require(loc);
|
||||
}
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
throw new ReferenceError("Unknown module formatter type " + JSON.stringify(type));
|
||||
}
|
||||
|
||||
return new ModuleFormatter(this);
|
||||
};
|
||||
|
||||
File.prototype.parseShebang = function (code) {
|
||||
var shebangMatch = shebangRegex.exec(code);
|
||||
|
||||
if (shebangMatch) {
|
||||
this.shebang = shebangMatch[0];
|
||||
|
||||
// remove shebang
|
||||
code = code.replace(shebangRegex, "");
|
||||
}
|
||||
|
||||
return code;
|
||||
};
|
||||
|
||||
File.prototype.set = function (key, val) {
|
||||
return this.data[key] = val;
|
||||
};
|
||||
|
||||
File.prototype.setDynamic = function (key, fn) {
|
||||
this.dynamicData[key] = fn;
|
||||
};
|
||||
|
||||
File.prototype.get = function (key) {
|
||||
var data = this.data[key];
|
||||
if (data) {
|
||||
return data;
|
||||
} else {
|
||||
var dynamic = this.dynamicData[key];
|
||||
if (dynamic) {
|
||||
return this.set(key, dynamic());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype.addImport = function (source, name, noDefault) {
|
||||
name = name || source;
|
||||
var id = this.dynamicImportIds[name];
|
||||
|
||||
if (!id) {
|
||||
id = this.dynamicImportIds[name] = this.scope.generateUidIdentifier(name);
|
||||
|
||||
var specifiers = [t.importSpecifier(t.identifier("default"), id)];
|
||||
var declar = t.importDeclaration(specifiers, t.literal(source));
|
||||
declar._blockHoist = 3;
|
||||
|
||||
this.dynamicImported.push(declar);
|
||||
if (noDefault) this.dynamicImportedNoDefault.push(declar);
|
||||
|
||||
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);
|
||||
}
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
File.prototype.isConsequenceExpressionStatement = function (node) {
|
||||
return t.isExpressionStatement(node) && this.lastStatements.indexOf(node) >= 0;
|
||||
};
|
||||
|
||||
File.prototype.attachAuxiliaryComment = function (node) {
|
||||
var comment = this.opts.auxiliaryComment;
|
||||
if (comment) {
|
||||
node.leadingComments = node.leadingComments || [];
|
||||
node.leadingComments.push({
|
||||
type: "Line",
|
||||
value: " " + comment
|
||||
});
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
File.prototype.addHelper = function (name) {
|
||||
if (!includes(File.helpers, name)) {
|
||||
throw new ReferenceError("Unknown helper " + name);
|
||||
}
|
||||
|
||||
var program = this.ast.program;
|
||||
|
||||
var declar = program._declarations && program._declarations[name];
|
||||
if (declar) return declar.id;
|
||||
|
||||
var runtime = this.get("helpersNamespace");
|
||||
if (runtime) {
|
||||
name = t.identifier(t.toIdentifier(name));
|
||||
return t.memberExpression(runtime, name);
|
||||
} else {
|
||||
var ref = util.template(name);
|
||||
ref._compact = true;
|
||||
var uid = this.scope.generateUidIdentifier(name);
|
||||
this.scope.push({
|
||||
key: name,
|
||||
id: uid,
|
||||
init: ref
|
||||
});
|
||||
return uid;
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype.logDeopt = function () {
|
||||
// todo, (node, msg)
|
||||
};
|
||||
|
||||
File.prototype.errorWithNode = function (node, msg, Error) {
|
||||
Error = Error || SyntaxError;
|
||||
|
||||
var loc = node.loc.start;
|
||||
var err = new Error("Line " + loc.line + ": " + msg);
|
||||
err.loc = loc;
|
||||
return err;
|
||||
};
|
||||
|
||||
File.prototype.addCode = function (code) {
|
||||
code = (code || "") + "";
|
||||
this.code = code;
|
||||
return this.parseShebang(code);
|
||||
};
|
||||
|
||||
File.prototype.parse = function (code) {
|
||||
code = this.addCode(code);
|
||||
|
||||
var opts = this.opts;
|
||||
|
||||
opts.allowImportExportEverywhere = this.isLoose("es6.modules");
|
||||
opts.strictMode = this.transformers.useStrict.canRun();
|
||||
|
||||
return parse(opts, code, (tree) => {
|
||||
this.transform(tree);
|
||||
return this.generate();
|
||||
});
|
||||
};
|
||||
|
||||
File.prototype.transform = function (ast) {
|
||||
this.debug();
|
||||
|
||||
this.ast = ast;
|
||||
this.lastStatements = t.getLastStatements(ast.program);
|
||||
this.scope = new Scope(ast.program, ast, null, this);
|
||||
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canRun()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
|
||||
this.checkNode(ast);
|
||||
|
||||
this.call("pre");
|
||||
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
|
||||
this.call("post");
|
||||
};
|
||||
|
||||
File.prototype.call = function (key) {
|
||||
var stack = this.transformerStack;
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var transformer = stack[i].transformer;
|
||||
if (transformer[key]) {
|
||||
transformer[key](this);
|
||||
}
|
||||
}
|
||||
};
|
||||
import sourceMapToComment from "source-map-to-comment";
|
||||
import shebangRegex from "shebang-regex";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import transform from "./index";
|
||||
import generate from "../generation";
|
||||
import defaults from "lodash/object/defaults";
|
||||
import includes from "lodash/collection/includes";
|
||||
import assign from "lodash/object/assign";
|
||||
import parse from "../helpers/parse";
|
||||
import Scope from "../traversal/scope";
|
||||
import slash from "slash";
|
||||
import * as util from "../util";
|
||||
import path from "path";
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../types";
|
||||
|
||||
var checkTransformerVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
checkNode(state.stack, node, scope);
|
||||
}
|
||||
};
|
||||
|
||||
var checkNode = function (stack, node, scope) {
|
||||
function checkNode(stack, node, scope) {
|
||||
each(stack, function (pass) {
|
||||
if (pass.shouldRun) return;
|
||||
pass.checkNode(node, scope);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
File.prototype.checkNode = function (node, scope) {
|
||||
var stack = this.transformerStack;
|
||||
scope = scope || this.scope;
|
||||
export default class File {
|
||||
constructor(opts) {
|
||||
this.dynamicImportedNoDefault = [];
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImported = [];
|
||||
this.dynamicImports = [];
|
||||
|
||||
checkNode(stack, node, scope);
|
||||
this.usedHelpers = {};
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
|
||||
scope.traverse(node, checkTransformerVisitor, {
|
||||
stack: stack
|
||||
});
|
||||
};
|
||||
this.lastStatements = [];
|
||||
this.opts = this.normalizeOptions(opts);
|
||||
this.ast = {};
|
||||
|
||||
File.prototype.generate = function () {
|
||||
var opts = this.opts;
|
||||
var ast = this.ast;
|
||||
this.buildTransformers();
|
||||
}
|
||||
|
||||
var result = {
|
||||
code: "",
|
||||
map: null,
|
||||
ast: null
|
||||
static helpers = [
|
||||
"inherits",
|
||||
"defaults",
|
||||
"prototype-properties",
|
||||
"apply-constructor",
|
||||
"tagged-template-literal",
|
||||
"tagged-template-literal-loose",
|
||||
"interop-require",
|
||||
"to-array",
|
||||
"to-consumable-array",
|
||||
"sliced-to-array",
|
||||
"object-without-properties",
|
||||
"has-own",
|
||||
"slice",
|
||||
"bind",
|
||||
"define-property",
|
||||
"async-to-generator",
|
||||
"interop-require-wildcard",
|
||||
"typeof",
|
||||
"extends",
|
||||
"get",
|
||||
"set",
|
||||
"class-call-check",
|
||||
"object-destructuring-empty",
|
||||
"temporal-undefined",
|
||||
"temporal-assert-defined",
|
||||
"self-global"
|
||||
];
|
||||
|
||||
static validOptions = [
|
||||
"filename",
|
||||
"filenameRelative",
|
||||
"blacklist",
|
||||
"whitelist",
|
||||
"loose",
|
||||
"optional",
|
||||
"modules",
|
||||
"sourceMap",
|
||||
"sourceMapName",
|
||||
"sourceFileName",
|
||||
"sourceRoot",
|
||||
"moduleRoot",
|
||||
"moduleIds",
|
||||
"comments",
|
||||
"reactCompat",
|
||||
"keepModuleIdExtensions",
|
||||
"code",
|
||||
"ast",
|
||||
"playground",
|
||||
"experimental",
|
||||
"externalHelpers",
|
||||
"auxiliaryComment",
|
||||
"compact",
|
||||
"returnUsedHelpers",
|
||||
|
||||
"resolveModuleSource",
|
||||
"moduleId",
|
||||
|
||||
// legacy
|
||||
"format",
|
||||
|
||||
// these are used by plugins
|
||||
"ignore",
|
||||
"only",
|
||||
"extensions",
|
||||
"accept"
|
||||
];
|
||||
|
||||
normalizeOptions(opts) {
|
||||
opts = assign({}, opts);
|
||||
|
||||
for (var key in opts) {
|
||||
if (key[0] !== "_" && File.validOptions.indexOf(key) < 0) {
|
||||
throw new ReferenceError("Unknown option: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
defaults(opts, {
|
||||
keepModuleIdExtensions: false,
|
||||
resolveModuleSource: null,
|
||||
returnUsedHelpers: false,
|
||||
externalHelpers: false,
|
||||
auxilaryComment: "",
|
||||
experimental: false,
|
||||
reactCompat: false,
|
||||
playground: false,
|
||||
moduleIds: false,
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
optional: [],
|
||||
comments: true,
|
||||
filename: "unknown",
|
||||
modules: "common",
|
||||
compact: "auto",
|
||||
loose: [],
|
||||
code: true,
|
||||
ast: true
|
||||
});
|
||||
|
||||
// normalize windows path separators to unix
|
||||
opts.filename = slash(opts.filename);
|
||||
if (opts.sourceRoot) {
|
||||
opts.sourceRoot = slash(opts.sourceRoot);
|
||||
}
|
||||
|
||||
if (opts.moduleId) {
|
||||
opts.moduleIds = true;
|
||||
}
|
||||
|
||||
opts.basename = path.basename(opts.filename, path.extname(opts.filename));
|
||||
|
||||
opts.blacklist = util.arrayify(opts.blacklist);
|
||||
opts.whitelist = util.arrayify(opts.whitelist);
|
||||
opts.optional = util.arrayify(opts.optional);
|
||||
opts.compact = util.booleanify(opts.compact);
|
||||
opts.loose = util.arrayify(opts.loose);
|
||||
|
||||
if (includes(opts.loose, "all") || includes(opts.loose, true)) {
|
||||
opts.loose = Object.keys(transform.transformers);
|
||||
}
|
||||
|
||||
defaults(opts, {
|
||||
moduleRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceRoot: opts.moduleRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
filenameRelative: opts.filename
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceFileName: opts.filenameRelative,
|
||||
sourceMapName: opts.filenameRelative
|
||||
});
|
||||
|
||||
if (opts.playground) {
|
||||
opts.experimental = true;
|
||||
}
|
||||
|
||||
if (opts.externalHelpers) {
|
||||
this.set("helpersNamespace", t.identifier("babelHelpers"));
|
||||
}
|
||||
|
||||
opts.blacklist = transform._ensureTransformerNames("blacklist", opts.blacklist);
|
||||
opts.whitelist = transform._ensureTransformerNames("whitelist", opts.whitelist);
|
||||
opts.optional = transform._ensureTransformerNames("optional", opts.optional);
|
||||
opts.loose = transform._ensureTransformerNames("loose", opts.loose);
|
||||
|
||||
if (opts.reactCompat) {
|
||||
opts.optional.push("reactCompat");
|
||||
console.error("The reactCompat option has been moved into the optional transformer `reactCompat`");
|
||||
}
|
||||
|
||||
var ensureEnabled = function (key) {
|
||||
var namespace = transform.transformerNamespaces[key];
|
||||
if (namespace === "es7") opts.experimental = true;
|
||||
if (namespace === "playground") opts.playground = true;
|
||||
};
|
||||
|
||||
each(opts.whitelist, ensureEnabled);
|
||||
each(opts.optional, ensureEnabled);
|
||||
|
||||
return opts;
|
||||
};
|
||||
|
||||
if (opts.ast) result.ast = ast;
|
||||
if (!opts.code) return result;
|
||||
|
||||
var _result = generate(ast, opts, this.code);
|
||||
result.code = _result.code;
|
||||
result.map = _result.map;
|
||||
|
||||
if (this.shebang) {
|
||||
// add back shebang
|
||||
result.code = this.shebang + "\n" + result.code;
|
||||
isLoose(key) {
|
||||
return includes(this.opts.loose, key);
|
||||
}
|
||||
|
||||
if (opts.sourceMap === "inline") {
|
||||
result.code += "\n" + sourceMapToComment(result.map);
|
||||
result.map = null;
|
||||
buildTransformers() {
|
||||
var file = this;
|
||||
|
||||
var transformers = {};
|
||||
|
||||
var secondaryStack = [];
|
||||
var stack = [];
|
||||
|
||||
each(transform.transformers, function (transformer, key) {
|
||||
var pass = transformers[key] = transformer.buildPass(file);
|
||||
|
||||
if (pass.canRun(file)) {
|
||||
stack.push(pass);
|
||||
|
||||
if (transformer.secondPass) {
|
||||
secondaryStack.push(pass);
|
||||
}
|
||||
|
||||
if (transformer.manipulateOptions) {
|
||||
transformer.manipulateOptions(file.opts, file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.transformerStack = stack.concat(secondaryStack);
|
||||
this.transformers = transformers;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
debug(msg) {
|
||||
var parts = this.opts.filename;
|
||||
if (msg) parts += ": " + msg;
|
||||
util.debug(parts);
|
||||
}
|
||||
|
||||
getModuleFormatter(type) {
|
||||
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolve(type);
|
||||
if (loc) ModuleFormatter = require(loc);
|
||||
}
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
throw new ReferenceError("Unknown module formatter type " + JSON.stringify(type));
|
||||
}
|
||||
|
||||
return new ModuleFormatter(this);
|
||||
}
|
||||
|
||||
parseShebang(code) {
|
||||
var shebangMatch = shebangRegex.exec(code);
|
||||
|
||||
if (shebangMatch) {
|
||||
this.shebang = shebangMatch[0];
|
||||
|
||||
// remove shebang
|
||||
code = code.replace(shebangRegex, "");
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
set(key, val) {
|
||||
return this.data[key] = val;
|
||||
};
|
||||
|
||||
setDynamic(key, fn) {
|
||||
this.dynamicData[key] = fn;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
var data = this.data[key];
|
||||
if (data) {
|
||||
return data;
|
||||
} else {
|
||||
var dynamic = this.dynamicData[key];
|
||||
if (dynamic) {
|
||||
return this.set(key, dynamic());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addImport(source, name, noDefault) {
|
||||
name ||= source;
|
||||
var id = this.dynamicImportIds[name];
|
||||
|
||||
if (!id) {
|
||||
id = this.dynamicImportIds[name] = this.scope.generateUidIdentifier(name);
|
||||
|
||||
var specifiers = [t.importSpecifier(t.identifier("default"), id)];
|
||||
var declar = t.importDeclaration(specifiers, t.literal(source));
|
||||
declar._blockHoist = 3;
|
||||
|
||||
this.dynamicImported.push(declar);
|
||||
if (noDefault) this.dynamicImportedNoDefault.push(declar);
|
||||
|
||||
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
isConsequenceExpressionStatement(node) {
|
||||
return t.isExpressionStatement(node) && this.lastStatements.indexOf(node) >= 0;
|
||||
}
|
||||
|
||||
attachAuxiliaryComment(node) {
|
||||
var comment = this.opts.auxiliaryComment;
|
||||
if (comment) {
|
||||
node.leadingComments ||= [];
|
||||
node.leadingComments.push({
|
||||
type: "Line",
|
||||
value: " " + comment
|
||||
});
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
addHelper(name) {
|
||||
if (!includes(File.helpers, name)) {
|
||||
throw new ReferenceError("Unknown helper " + name);
|
||||
}
|
||||
|
||||
var program = this.ast.program;
|
||||
|
||||
var declar = program._declarations && program._declarations[name];
|
||||
if (declar) return declar.id;
|
||||
|
||||
this.usedHelpers[name] = true;
|
||||
|
||||
var runtime = this.get("helpersNamespace");
|
||||
if (runtime) {
|
||||
name = t.identifier(t.toIdentifier(name));
|
||||
return t.memberExpression(runtime, name);
|
||||
} else {
|
||||
var ref = util.template(name);
|
||||
ref._compact = true;
|
||||
var uid = this.scope.generateUidIdentifier(name);
|
||||
this.scope.push({
|
||||
key: name,
|
||||
id: uid,
|
||||
init: ref
|
||||
});
|
||||
return uid;
|
||||
}
|
||||
}
|
||||
|
||||
logDeopt() {
|
||||
// todo, (node, msg)
|
||||
}
|
||||
|
||||
errorWithNode(node, msg, Error = SyntaxError) {
|
||||
var loc = node.loc.start;
|
||||
var err = new Error("Line " + loc.line + ": " + msg);
|
||||
err.loc = loc;
|
||||
return err;
|
||||
}
|
||||
|
||||
addCode(code) {
|
||||
code = (code || "") + "";
|
||||
this.code = code;
|
||||
return this.parseShebang(code);
|
||||
}
|
||||
|
||||
parse(code) {
|
||||
code = this.addCode(code);
|
||||
|
||||
var opts = this.opts;
|
||||
|
||||
opts.allowImportExportEverywhere = this.isLoose("es6.modules");
|
||||
opts.strictMode = this.transformers.useStrict.canRun();
|
||||
|
||||
return parse(opts, code, (tree) => {
|
||||
this.transform(tree);
|
||||
return this.generate();
|
||||
});
|
||||
}
|
||||
|
||||
transform(ast) {
|
||||
this.debug();
|
||||
|
||||
this.ast = ast;
|
||||
this.lastStatements = t.getLastStatements(ast.program);
|
||||
this.scope = new Scope(ast.program, ast, null, this);
|
||||
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canRun()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
|
||||
this.checkNode(ast);
|
||||
|
||||
this.call("pre");
|
||||
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
|
||||
this.call("post");
|
||||
}
|
||||
|
||||
call(key) {
|
||||
var stack = this.transformerStack;
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var transformer = stack[i].transformer;
|
||||
if (transformer[key]) {
|
||||
transformer[key](this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkNode(node, scope) {
|
||||
var stack = this.transformerStack;
|
||||
scope ||= this.scope;
|
||||
|
||||
checkNode(stack, node, scope);
|
||||
|
||||
scope.traverse(node, checkTransformerVisitor, {
|
||||
stack: stack
|
||||
});
|
||||
}
|
||||
|
||||
generate() {
|
||||
var opts = this.opts;
|
||||
var ast = this.ast;
|
||||
|
||||
var result = {
|
||||
code: "",
|
||||
map: null,
|
||||
ast: null
|
||||
};
|
||||
|
||||
if (this.opts.returnUsedHelpers) {
|
||||
result.usedHelpers = Object.keys(this.usedHelpers);
|
||||
}
|
||||
|
||||
if (opts.ast) result.ast = ast;
|
||||
if (!opts.code) return result;
|
||||
|
||||
var _result = generate(ast, opts, this.code);
|
||||
result.code = _result.code;
|
||||
result.map = _result.map;
|
||||
|
||||
if (this.shebang) {
|
||||
// add back shebang
|
||||
result.code = this.shebang + "\n" + result.code;
|
||||
}
|
||||
|
||||
if (opts.sourceMap === "inline") {
|
||||
result.code += "\n" + sourceMapToComment(result.map);
|
||||
result.map = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var explode = require("./explode-assignable-expression");
|
||||
var t = require("../../types");
|
||||
import explode from "./explode-assignable-expression";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = function (exports, opts) {
|
||||
var isAssignment = function (node) {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../types");
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = function build(node, buildBody) {
|
||||
var self = node.blocks.shift();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var explode = require("./explode-assignable-expression");
|
||||
var t = require("../../types");
|
||||
import explode from "./explode-assignable-expression";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = function (exports, opts) {
|
||||
var buildAssignment = function (left, right) {
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
|
||||
// https://github.com/RReverser/jsx-transpiler
|
||||
|
||||
// jsx
|
||||
|
||||
var isString = require("lodash/lang/isString");
|
||||
var messages = require("../../messages");
|
||||
var esutils = require("esutils");
|
||||
var react = require("./react");
|
||||
var t = require("../../types");
|
||||
import isString from "lodash/lang/isString";
|
||||
import * as messages from "../../messages";
|
||||
import esutils from "esutils";
|
||||
import * as react from "./react";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = function (exports, opts) {
|
||||
exports.check = function (node) {
|
||||
@@ -33,7 +31,7 @@ module.exports = function (exports, opts) {
|
||||
};
|
||||
|
||||
exports.JSXMemberExpression = {
|
||||
exit: function (node) {
|
||||
exit(node) {
|
||||
node.computed = t.isLiteral(node.property);
|
||||
node.type = "MemberExpression";
|
||||
}
|
||||
@@ -44,21 +42,21 @@ module.exports = function (exports, opts) {
|
||||
};
|
||||
|
||||
exports.JSXAttribute = {
|
||||
enter: function (node) {
|
||||
enter(node) {
|
||||
var value = node.value;
|
||||
if (t.isLiteral(value) && isString(value.value)) {
|
||||
value.value = value.value.replace(/\n\s+/g, " ");
|
||||
}
|
||||
},
|
||||
|
||||
exit: function (node) {
|
||||
exit(node) {
|
||||
var value = node.value || t.literal(true);
|
||||
return t.inherits(t.property("init", node.name, value), node);
|
||||
}
|
||||
};
|
||||
|
||||
exports.JSXOpeningElement = {
|
||||
exit: function (node, parent, scope, file) {
|
||||
exit(node, parent, scope, file) {
|
||||
var tagExpr = node.name;
|
||||
var args = [];
|
||||
|
||||
@@ -146,7 +144,7 @@ module.exports = function (exports, opts) {
|
||||
};
|
||||
|
||||
exports.JSXElement = {
|
||||
exit: function (node) {
|
||||
exit(node) {
|
||||
var callExpr = node.openingElement;
|
||||
|
||||
for (var i = 0; i < node.children.length; i++) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
var cloneDeep = require("lodash/lang/cloneDeep");
|
||||
var traverse = require("../../traversal");
|
||||
var clone = require("lodash/lang/clone");
|
||||
var each = require("lodash/collection/each");
|
||||
var has = require("lodash/object/has");
|
||||
var t = require("../../types");
|
||||
import cloneDeep from "lodash/lang/cloneDeep";
|
||||
import traverse from "../../traversal";
|
||||
import clone from "lodash/lang/clone";
|
||||
import each from "lodash/collection/each";
|
||||
import has from "lodash/object/has";
|
||||
import t from "../../types";
|
||||
|
||||
exports.push = function (mutatorMap, key, kind, computed, value) {
|
||||
export function push(mutatorMap, key, kind, computed, value) {
|
||||
var alias;
|
||||
|
||||
if (t.isIdentifier(key)) {
|
||||
@@ -31,9 +31,9 @@ exports.push = function (mutatorMap, key, kind, computed, value) {
|
||||
}
|
||||
|
||||
map[kind] = value;
|
||||
};
|
||||
}
|
||||
|
||||
exports.build = function (mutatorMap) {
|
||||
export function build(mutatorMap) {
|
||||
var objExpr = t.objectExpression([]);
|
||||
|
||||
each(mutatorMap, function (map) {
|
||||
@@ -70,4 +70,4 @@ exports.build = function (mutatorMap) {
|
||||
});
|
||||
|
||||
return objExpr;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../types");
|
||||
import t from "../../types";
|
||||
|
||||
var getObjRef = function (node, nodes, file, scope) {
|
||||
var ref;
|
||||
|
||||
9
src/babel/transformation/helpers/get-function-arity.js
Normal file
9
src/babel/transformation/helpers/get-function-arity.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = function (node) {
|
||||
var lastNonDefault = 0;
|
||||
for (var i = 0; i < node.params.length; i++) {
|
||||
if (!t.isAssignmentPattern(node.params[i])) lastNonDefault = i + 1;
|
||||
}
|
||||
return lastNonDefault;
|
||||
};
|
||||
@@ -1,10 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
import getFunctionArity from "./get-function-arity";
|
||||
import * as util from "../../util";
|
||||
import t from "../../types";
|
||||
|
||||
var visitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
// check if this node is a referenced identifier that matches the same as our
|
||||
// function id
|
||||
if (!t.isReferencedIdentifier(node, parent, { name: state.name })) return;
|
||||
@@ -23,12 +22,21 @@ var wrap = function (state, method, id, scope) {
|
||||
if (state.selfReference) {
|
||||
var templateName = "property-method-assignment-wrapper";
|
||||
if (method.generator) templateName += "-generator";
|
||||
return util.template(templateName, {
|
||||
var template = util.template(templateName, {
|
||||
FUNCTION: method,
|
||||
FUNCTION_ID: id,
|
||||
FUNCTION_KEY: scope.generateUidIdentifier(id.name),
|
||||
WRAPPER_KEY: scope.generateUidIdentifier(id.name + "Wrapper")
|
||||
});
|
||||
|
||||
// shim in dummy params to retain function arity, if you try to read the
|
||||
// source then you'll get the original since it's proxied so it's all good
|
||||
var params = template.callee.body.body[0].declarations[0].init.params;
|
||||
for (var i = 0, len = getFunctionArity(method); i < len; i++) {
|
||||
params.push(scope.generateUidIdentifier("x"));
|
||||
}
|
||||
|
||||
return template;
|
||||
} else {
|
||||
method.id = id;
|
||||
return method;
|
||||
@@ -41,7 +49,7 @@ var visit = function (node, name, scope) {
|
||||
selfReference: false,
|
||||
outerDeclar: scope.getBindingIdentifier(name),
|
||||
references: [],
|
||||
name: name,
|
||||
name: name
|
||||
};
|
||||
|
||||
// check to see if we have a local binding of the id we're setting inside of
|
||||
@@ -81,7 +89,7 @@ var visit = function (node, name, scope) {
|
||||
return state;
|
||||
};
|
||||
|
||||
exports.property = function (node, file, scope) {
|
||||
export function property(node, file, scope) {
|
||||
var key = t.toComputedKey(node, node.key);
|
||||
if (!t.isLiteral(key)) return node; // we can't set a function id with this
|
||||
|
||||
@@ -91,15 +99,15 @@ exports.property = function (node, file, scope) {
|
||||
var method = node.value;
|
||||
var state = visit(method, name, scope);
|
||||
node.value = wrap(state, method, id, scope);
|
||||
};
|
||||
}
|
||||
|
||||
exports.bare = function (node, parent, scope) {
|
||||
export function bare(node, parent, scope) {
|
||||
// has an `id` so we don't need to infer one
|
||||
if (node.id) return;
|
||||
|
||||
var id;
|
||||
if (t.isProperty(parent) && parent.kind === "init" && !parent.computed) {
|
||||
// { foo: function () {} };
|
||||
// { foo() {} };
|
||||
id = parent.key;
|
||||
} else if (t.isVariableDeclarator(parent)) {
|
||||
// var foo = function () {};
|
||||
@@ -115,4 +123,4 @@ exports.bare = function (node, parent, scope) {
|
||||
|
||||
var state = visit(node, name, scope);
|
||||
return wrap(state, node, id, scope);
|
||||
};
|
||||
}
|
||||
|
||||
12
src/babel/transformation/helpers/react.js
vendored
12
src/babel/transformation/helpers/react.js
vendored
@@ -1,8 +1,8 @@
|
||||
var t = require("../../types");
|
||||
import t from "../../types";
|
||||
|
||||
var isCreateClassCallExpression = t.buildMatchMemberExpression("React.createClass");
|
||||
|
||||
exports.isCreateClass = function (node) {
|
||||
export function isCreateClass(node) {
|
||||
if (!node || !t.isCallExpression(node)) return false;
|
||||
|
||||
// not React.createClass call member object
|
||||
@@ -17,10 +17,10 @@ exports.isCreateClass = function (node) {
|
||||
if (!t.isObjectExpression(first)) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
exports.isReactComponent = t.buildMatchMemberExpression("React.Component");
|
||||
export var isReactComponent = t.buildMatchMemberExpression("React.Component");
|
||||
|
||||
exports.isCompatTag = function (tagName) {
|
||||
export function isCompatTag(tagName) {
|
||||
return tagName && /^[a-z]|\-/.test(tagName);
|
||||
};
|
||||
}
|
||||
|
||||
13
src/babel/transformation/helpers/regex.js
Normal file
13
src/babel/transformation/helpers/regex.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import pull from "lodash/array/pull";
|
||||
import t from "../../types";
|
||||
|
||||
export function is(node, flag) {
|
||||
return t.isLiteral(node) && node.regex && node.regex.flags.indexOf(flag) >= 0;
|
||||
}
|
||||
|
||||
export function pullFlag(node, flag) {
|
||||
var flags = node.regex.flags.split("");
|
||||
if (node.regex.flags.indexOf("u") < 0) return;
|
||||
pull(flags, "u");
|
||||
node.regex.flags = flags.join("");
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../types");
|
||||
import t from "../../types";
|
||||
|
||||
var visitor = {
|
||||
enter: function (node) {
|
||||
enter(node) {
|
||||
if (t.isFunction(node)) this.skip();
|
||||
|
||||
if (t.isAwaitExpression(node)) {
|
||||
|
||||
@@ -1,102 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = ReplaceSupers;
|
||||
|
||||
var messages = require("../../messages");
|
||||
var t = require("../../types");
|
||||
import * as messages from "../../messages";
|
||||
import t from "../../types";
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} opts
|
||||
* @param {Boolean} [inClass]
|
||||
*/
|
||||
|
||||
function ReplaceSupers(opts, inClass) {
|
||||
this.topLevelThisReference = opts.topLevelThisReference;
|
||||
this.methodNode = opts.methodNode;
|
||||
this.className = opts.className;
|
||||
this.superName = opts.superName;
|
||||
this.isStatic = opts.isStatic;
|
||||
this.hasSuper = false;
|
||||
this.inClass = inClass;
|
||||
this.isLoose = opts.isLoose;
|
||||
this.scope = opts.scope;
|
||||
this.file = opts.file;
|
||||
function isIllegalBareSuper(node, parent) {
|
||||
if (!isSuper(node, parent)) return false;
|
||||
if (t.isMemberExpression(parent, { computed: false })) return false;
|
||||
if (t.isCallExpression(parent, { callee: node })) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a super class value of the named property.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this)
|
||||
*
|
||||
* @param {Node} property
|
||||
* @param {Node} value
|
||||
* @param {Boolean} isComputed
|
||||
* @param {Node} thisExpression
|
||||
*
|
||||
* @returns {Node}
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.setSuperProperty = function (property, value, isComputed, thisExpression) {
|
||||
return t.callExpression(
|
||||
this.file.addHelper("set"),
|
||||
[
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
|
||||
[
|
||||
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
|
||||
]
|
||||
),
|
||||
isComputed ? property : t.literal(property.name),
|
||||
value,
|
||||
thisExpression
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a node representing the super class value of the named property.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
|
||||
*
|
||||
* @param {Node} property
|
||||
* @param {Boolean} isComputed
|
||||
* @param {Node} thisExpression
|
||||
*
|
||||
* @returns {Node}
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.getSuperProperty = function (property, isComputed, thisExpression) {
|
||||
return t.callExpression(
|
||||
this.file.addHelper("get"),
|
||||
[
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
|
||||
[
|
||||
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
|
||||
]
|
||||
),
|
||||
isComputed ? property : t.literal(property.name),
|
||||
thisExpression
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.replace = function () {
|
||||
this.traverseLevel(this.methodNode.value, true);
|
||||
};
|
||||
function isSuper(node, parent) {
|
||||
return t.isIdentifier(node, { name: "super" }) && t.isReferenced(node, parent);
|
||||
}
|
||||
|
||||
var visitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
var topLevel = state.topLevel;
|
||||
var self = state.self;
|
||||
|
||||
@@ -123,181 +43,263 @@ var visitor = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {Boolean} topLevel
|
||||
*/
|
||||
export default class ReplaceSupers {
|
||||
|
||||
ReplaceSupers.prototype.traverseLevel = function (node, topLevel) {
|
||||
var state = { self: this, topLevel: topLevel };
|
||||
this.scope.traverse(node, visitor, state);
|
||||
};
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} opts
|
||||
* @param {Boolean} [inClass]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.getThisReference = function () {
|
||||
if (this.topLevelThisReference) {
|
||||
return this.topLevelThisReference;
|
||||
} else {
|
||||
var ref = this.topLevelThisReference = this.scope.generateUidIdentifier("this");
|
||||
this.methodNode.value.body.body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(this.topLevelThisReference, t.thisExpression())
|
||||
]));
|
||||
return ref;
|
||||
constructor(opts, inClass) {
|
||||
this.topLevelThisReference = opts.topLevelThisReference;
|
||||
this.methodNode = opts.methodNode;
|
||||
this.className = opts.className;
|
||||
this.superName = opts.superName;
|
||||
this.isStatic = opts.isStatic;
|
||||
this.hasSuper = false;
|
||||
this.inClass = inClass;
|
||||
this.isLoose = opts.isLoose;
|
||||
this.scope = opts.scope;
|
||||
this.file = opts.file;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {Object} id
|
||||
* @param {Object} parent
|
||||
* @returns {Object}
|
||||
*/
|
||||
/**
|
||||
* Sets a super class value of the named property.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this)
|
||||
*
|
||||
* @param {Node} property
|
||||
* @param {Node} value
|
||||
* @param {Boolean} isComputed
|
||||
* @param {Node} thisExpression
|
||||
*
|
||||
* @returns {Node}
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.getLooseSuperProperty = function (id, parent) {
|
||||
var methodNode = this.methodNode;
|
||||
var methodName = methodNode.key;
|
||||
var superName = this.superName || t.identifier("Function");
|
||||
setSuperProperty(property, value, isComputed, thisExpression) {
|
||||
return t.callExpression(
|
||||
this.file.addHelper("set"),
|
||||
[
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
|
||||
[
|
||||
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
|
||||
]
|
||||
),
|
||||
isComputed ? property : t.literal(property.name),
|
||||
value,
|
||||
thisExpression
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (parent.property === id) {
|
||||
return;
|
||||
} else if (t.isCallExpression(parent, { callee: id })) {
|
||||
// super(); -> ClassName.prototype.MethodName.call(this);
|
||||
parent.arguments.unshift(t.thisExpression());
|
||||
/**
|
||||
* Gets a node representing the super class value of the named property.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
|
||||
*
|
||||
* @param {Node} property
|
||||
* @param {Boolean} isComputed
|
||||
* @param {Node} thisExpression
|
||||
*
|
||||
* @returns {Node}
|
||||
*/
|
||||
|
||||
if (methodName.name === "constructor") {
|
||||
// constructor() { super(); }
|
||||
return t.memberExpression(superName, t.identifier("call"));
|
||||
getSuperProperty(property, isComputed, thisExpression) {
|
||||
return t.callExpression(
|
||||
this.file.addHelper("get"),
|
||||
[
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
|
||||
[
|
||||
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
|
||||
]
|
||||
),
|
||||
isComputed ? property : t.literal(property.name),
|
||||
thisExpression
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
replace() {
|
||||
this.traverseLevel(this.methodNode.value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {Boolean} topLevel
|
||||
*/
|
||||
|
||||
traverseLevel(node, topLevel) {
|
||||
var state = { self: this, topLevel: topLevel };
|
||||
this.scope.traverse(node, visitor, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
getThisReference() {
|
||||
if (this.topLevelThisReference) {
|
||||
return this.topLevelThisReference;
|
||||
} else {
|
||||
id = superName;
|
||||
|
||||
// foo() { super(); }
|
||||
if (!methodNode.static) {
|
||||
id = t.memberExpression(id, t.identifier("prototype"));
|
||||
}
|
||||
|
||||
id = t.memberExpression(id, methodName, methodNode.computed);
|
||||
return t.memberExpression(id, t.identifier("call"));
|
||||
var ref = this.topLevelThisReference = this.scope.generateUidIdentifier("this");
|
||||
this.methodNode.value.body.body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(this.topLevelThisReference, t.thisExpression())
|
||||
]));
|
||||
return ref;
|
||||
}
|
||||
} else if (t.isMemberExpression(parent) && !methodNode.static) {
|
||||
// super.test -> ClassName.prototype.test
|
||||
return t.memberExpression(superName, t.identifier("prototype"));
|
||||
} else {
|
||||
return superName;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Function} getThisReference
|
||||
* @param {Object} node
|
||||
* @param {Object} parent
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) {
|
||||
if (t.isIdentifier(node, { name: "super" })) {
|
||||
this.hasSuper = true;
|
||||
return this.getLooseSuperProperty(node, parent);
|
||||
} else if (t.isCallExpression(node)) {
|
||||
var callee = node.callee;
|
||||
if (!t.isMemberExpression(callee)) return;
|
||||
if (callee.object.name !== "super") return;
|
||||
|
||||
// super.test(); -> ClassName.prototype.MethodName.call(this);
|
||||
this.hasSuper = true;
|
||||
t.appendToMemberExpression(callee, t.identifier("call"));
|
||||
node.arguments.unshift(getThisReference());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Function} getThisReference
|
||||
* @param {Object} node
|
||||
* @param {Object} parent
|
||||
*/
|
||||
|
||||
ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
|
||||
var methodNode = this.methodNode;
|
||||
var property;
|
||||
var computed;
|
||||
var args;
|
||||
var thisReference;
|
||||
|
||||
if (isIllegalBareSuper(node, parent)) {
|
||||
throw this.file.errorWithNode(node, messages.get("classesIllegalBareSuper"));
|
||||
}
|
||||
|
||||
if (t.isCallExpression(node)) {
|
||||
var callee = node.callee;
|
||||
if (isSuper(callee, node)) {
|
||||
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
|
||||
property = methodNode.key;
|
||||
computed = methodNode.computed;
|
||||
args = node.arguments;
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {Object} id
|
||||
* @param {Object} parent
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
// bare `super` call is illegal inside non-constructors
|
||||
// - https://esdiscuss.org/topic/super-call-in-methods
|
||||
// - https://twitter.com/wycats/status/544553184396836864
|
||||
if (methodNode.key.name !== "constructor" || !this.inClass) {
|
||||
var methodName = methodNode.key.name || "METHOD_NAME";
|
||||
throw this.file.errorWithNode(node, messages.get("classesIllegalSuperCall", methodName));
|
||||
getLooseSuperProperty(id, parent) {
|
||||
var methodNode = this.methodNode;
|
||||
var methodName = methodNode.key;
|
||||
var superName = this.superName || t.identifier("Function");
|
||||
|
||||
if (parent.property === id) {
|
||||
return;
|
||||
} else if (t.isCallExpression(parent, { callee: id })) {
|
||||
// super(); -> ClassName.prototype.MethodName.call(this);
|
||||
parent.arguments.unshift(t.thisExpression());
|
||||
|
||||
if (methodName.name === "constructor") {
|
||||
// constructor() { super(); }
|
||||
return t.memberExpression(superName, t.identifier("call"));
|
||||
} else {
|
||||
id = superName;
|
||||
|
||||
// foo() { super(); }
|
||||
if (!methodNode.static) {
|
||||
id = t.memberExpression(id, t.identifier("prototype"));
|
||||
}
|
||||
|
||||
id = t.memberExpression(id, methodName, methodNode.computed);
|
||||
return t.memberExpression(id, t.identifier("call"));
|
||||
}
|
||||
} else if (t.isMemberExpression(callee) && isSuper(callee.object, callee)) {
|
||||
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
|
||||
property = callee.property;
|
||||
computed = callee.computed;
|
||||
args = node.arguments;
|
||||
}
|
||||
} else if (t.isMemberExpression(node) && isSuper(node.object, node)) {
|
||||
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
|
||||
property = node.property;
|
||||
computed = node.computed;
|
||||
} else if (t.isAssignmentExpression(node) && isSuper(node.left.object, node.left) && methodNode.kind === "set") {
|
||||
// super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this);
|
||||
this.hasSuper = true;
|
||||
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
|
||||
}
|
||||
|
||||
if (!property) return;
|
||||
|
||||
this.hasSuper = true;
|
||||
|
||||
thisReference = getThisReference();
|
||||
var superProperty = this.getSuperProperty(property, computed, thisReference);
|
||||
if (args) {
|
||||
if (args.length === 1 && t.isSpreadElement(args[0])) {
|
||||
// super(...arguments);
|
||||
return t.callExpression(
|
||||
t.memberExpression(superProperty, t.identifier("apply")),
|
||||
[thisReference, args[0].argument]
|
||||
);
|
||||
} else if (t.isMemberExpression(parent) && !methodNode.static) {
|
||||
// super.test -> ClassName.prototype.test
|
||||
return t.memberExpression(superName, t.identifier("prototype"));
|
||||
} else {
|
||||
return t.callExpression(
|
||||
t.memberExpression(superProperty, t.identifier("call")),
|
||||
[thisReference].concat(args)
|
||||
);
|
||||
return superName;
|
||||
}
|
||||
} else {
|
||||
return superProperty;
|
||||
}
|
||||
};
|
||||
|
||||
var isIllegalBareSuper = function (node, parent) {
|
||||
if (!isSuper(node, parent)) return false;
|
||||
if (t.isMemberExpression(parent, { computed: false })) return false;
|
||||
if (t.isCallExpression(parent, { callee: node })) return false;
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Function} getThisReference
|
||||
* @param {Object} node
|
||||
* @param {Object} parent
|
||||
*/
|
||||
|
||||
var isSuper = function (node, parent) {
|
||||
return t.isIdentifier(node, { name: "super" }) && t.isReferenced(node, parent);
|
||||
};
|
||||
looseHandle(getThisReference, node, parent) {
|
||||
if (t.isIdentifier(node, { name: "super" })) {
|
||||
this.hasSuper = true;
|
||||
return this.getLooseSuperProperty(node, parent);
|
||||
} else if (t.isCallExpression(node)) {
|
||||
var callee = node.callee;
|
||||
if (!t.isMemberExpression(callee)) return;
|
||||
if (callee.object.name !== "super") return;
|
||||
|
||||
// super.test(); -> ClassName.prototype.MethodName.call(this);
|
||||
this.hasSuper = true;
|
||||
t.appendToMemberExpression(callee, t.identifier("call"));
|
||||
node.arguments.unshift(getThisReference());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Function} getThisReference
|
||||
* @param {Object} node
|
||||
* @param {Object} parent
|
||||
*/
|
||||
|
||||
specHandle(getThisReference, node, parent) {
|
||||
var methodNode = this.methodNode;
|
||||
var property;
|
||||
var computed;
|
||||
var args;
|
||||
var thisReference;
|
||||
|
||||
if (isIllegalBareSuper(node, parent)) {
|
||||
throw this.file.errorWithNode(node, messages.get("classesIllegalBareSuper"));
|
||||
}
|
||||
|
||||
if (t.isCallExpression(node)) {
|
||||
var callee = node.callee;
|
||||
if (isSuper(callee, node)) {
|
||||
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
|
||||
property = methodNode.key;
|
||||
computed = methodNode.computed;
|
||||
args = node.arguments;
|
||||
|
||||
// bare `super` call is illegal inside non-constructors
|
||||
// - https://esdiscuss.org/topic/super-call-in-methods
|
||||
// - https://twitter.com/wycats/status/544553184396836864
|
||||
if (methodNode.key.name !== "constructor" || !this.inClass) {
|
||||
var methodName = methodNode.key.name || "METHOD_NAME";
|
||||
throw this.file.errorWithNode(node, messages.get("classesIllegalSuperCall", methodName));
|
||||
}
|
||||
} else if (t.isMemberExpression(callee) && isSuper(callee.object, callee)) {
|
||||
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
|
||||
property = callee.property;
|
||||
computed = callee.computed;
|
||||
args = node.arguments;
|
||||
}
|
||||
} else if (t.isMemberExpression(node) && isSuper(node.object, node)) {
|
||||
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
|
||||
property = node.property;
|
||||
computed = node.computed;
|
||||
} else if (t.isAssignmentExpression(node) && isSuper(node.left.object, node.left) && methodNode.kind === "set") {
|
||||
// super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this);
|
||||
this.hasSuper = true;
|
||||
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
|
||||
}
|
||||
|
||||
if (!property) return;
|
||||
|
||||
this.hasSuper = true;
|
||||
|
||||
thisReference = getThisReference();
|
||||
var superProperty = this.getSuperProperty(property, computed, thisReference);
|
||||
if (args) {
|
||||
if (args.length === 1 && t.isSpreadElement(args[0])) {
|
||||
// super(...arguments);
|
||||
return t.callExpression(
|
||||
t.memberExpression(superProperty, t.identifier("apply")),
|
||||
[thisReference, args[0].argument]
|
||||
);
|
||||
} else {
|
||||
return t.callExpression(
|
||||
t.memberExpression(superProperty, t.identifier("call")),
|
||||
[thisReference, ...args]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return superProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
"use strict";
|
||||
import t from "../../types";
|
||||
|
||||
var t = require("../../types");
|
||||
|
||||
exports.has = function (node) {
|
||||
export function has(node) {
|
||||
var first = node.body[0];
|
||||
return t.isExpressionStatement(first) && t.isLiteral(first.expression, { value: "use strict" });
|
||||
};
|
||||
}
|
||||
|
||||
exports.wrap = function (node, callback) {
|
||||
export function wrap(node, callback) {
|
||||
var useStrictNode;
|
||||
if (exports.has(node)) {
|
||||
useStrictNode = node.body.shift();
|
||||
@@ -18,4 +16,4 @@ exports.wrap = function (node, callback) {
|
||||
if (useStrictNode) {
|
||||
node.body.unshift(useStrictNode);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
"use strict";
|
||||
import normalizeAst from "../helpers/normalize-ast";
|
||||
import Transformer from "./transformer";
|
||||
import object from "../helpers/object";
|
||||
import File from "./file";
|
||||
import each from "lodash/collection/each";
|
||||
|
||||
module.exports = transform;
|
||||
|
||||
var normalizeAst = require("../helpers/normalize-ast");
|
||||
var Transformer = require("./transformer");
|
||||
var object = require("../helpers/object");
|
||||
var File = require("./file");
|
||||
var each = require("lodash/collection/each");
|
||||
|
||||
function transform(code, opts) {
|
||||
export default function transform(code, opts) {
|
||||
var file = new File(opts);
|
||||
return file.parse(code);
|
||||
}
|
||||
@@ -55,12 +51,12 @@ transform.namespaces = object();
|
||||
transform.deprecatedTransformerMap = require("./transformers/deprecated");
|
||||
transform.moduleFormatters = require("./modules");
|
||||
|
||||
var rawTransformers = require("./transformers");
|
||||
import rawTransformers from "./transformers";
|
||||
|
||||
each(rawTransformers, function (transformer, key) {
|
||||
var namespace = key.split(".")[0];
|
||||
|
||||
transform.namespaces[namespace] = transform.namespaces[namespace] || [];
|
||||
transform.namespaces[namespace] ||= [];
|
||||
transform.namespaces[namespace].push(key);
|
||||
transform.transformerNamespaces[key] = namespace;
|
||||
|
||||
|
||||
@@ -1,85 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = DefaultFormatter;
|
||||
|
||||
var messages = require("../../messages");
|
||||
var extend = require("lodash/object/extend");
|
||||
var object = require("../../helpers/object");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
|
||||
function DefaultFormatter(file) {
|
||||
this.scope = file.scope;
|
||||
this.file = file;
|
||||
this.ids = object();
|
||||
|
||||
this.hasNonDefaultExports = false;
|
||||
|
||||
this.hasLocalExports = false;
|
||||
this.hasLocalImports = false;
|
||||
|
||||
this.localImportOccurences = object();
|
||||
this.localExports = object();
|
||||
this.localImports = object();
|
||||
|
||||
this.getLocalExports();
|
||||
this.getLocalImports();
|
||||
|
||||
this.remapAssignments();
|
||||
}
|
||||
|
||||
DefaultFormatter.prototype.doDefaultExportInterop = function (node) {
|
||||
return node.default && !this.noInteropRequireExport && !this.hasNonDefaultExports;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.bumpImportOccurences = function (node) {
|
||||
var source = node.source.value;
|
||||
var occurs = this.localImportOccurences;
|
||||
occurs[source] = occurs[source] || 0;
|
||||
occurs[source] += node.specifiers.length;
|
||||
};
|
||||
|
||||
var exportsVisitor = {
|
||||
enter: function (node, parent, scope, formatter) {
|
||||
var declar = node && node.declaration;
|
||||
if (t.isExportDeclaration(node)) {
|
||||
formatter.hasLocalImports = true;
|
||||
|
||||
if (declar && t.isStatement(declar)) {
|
||||
extend(formatter.localExports, t.getBindingIdentifiers(declar));
|
||||
}
|
||||
|
||||
if (!node.default) {
|
||||
formatter.hasNonDefaultExports = true;
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
formatter.bumpImportOccurences(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getLocalExports = function () {
|
||||
this.file.scope.traverse(this.file.ast, exportsVisitor, this);
|
||||
};
|
||||
|
||||
var importsVisitor = {
|
||||
enter: function (node, parent, scope, formatter) {
|
||||
if (t.isImportDeclaration(node)) {
|
||||
formatter.hasLocalImports = true;
|
||||
extend(formatter.localImports, t.getBindingIdentifiers(node));
|
||||
formatter.bumpImportOccurences(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getLocalImports = function () {
|
||||
this.file.scope.traverse(this.file.ast, importsVisitor, this);
|
||||
};
|
||||
import * as messages from "../../messages";
|
||||
import extend from "lodash/object/extend";
|
||||
import object from "../../helpers/object";
|
||||
import * as util from "../../util";
|
||||
import t from "../../types";
|
||||
|
||||
var remapVisitor = {
|
||||
enter: function (node, parent, scope, formatter) {
|
||||
enter(node, parent, scope, formatter) {
|
||||
if (t.isUpdateExpression(node) && formatter.isLocalReference(node.argument, scope)) {
|
||||
this.skip();
|
||||
|
||||
@@ -115,181 +41,253 @@ var remapVisitor = {
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.remapAssignments = function () {
|
||||
if (this.hasLocalImports) {
|
||||
this.file.scope.traverse(this.file.ast, remapVisitor, this);
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.isLocalReference = function (node) {
|
||||
var localImports = this.localImports;
|
||||
return t.isIdentifier(node) && localImports[node.name] && localImports[node.name] !== node;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.remapExportAssignment = function (node) {
|
||||
return t.assignmentExpression(
|
||||
"=",
|
||||
node.left,
|
||||
t.assignmentExpression(
|
||||
node.operator,
|
||||
t.memberExpression(t.identifier("exports"), node.left),
|
||||
node.right
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
|
||||
var localExports = this.localExports;
|
||||
var name = node.name;
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBindingIdentifier(name);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getModuleName = function () {
|
||||
var opts = this.file.opts;
|
||||
if (opts.moduleId) return opts.moduleId;
|
||||
|
||||
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, "");
|
||||
}
|
||||
|
||||
if (!opts.keepModuleIdExtensions) {
|
||||
// remove extension
|
||||
filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");
|
||||
}
|
||||
|
||||
moduleName += filenameRelative;
|
||||
|
||||
// normalize path separators
|
||||
moduleName = moduleName.replace(/\\/g, "/");
|
||||
|
||||
return moduleName;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype._pushStatement = function (ref, nodes) {
|
||||
if (t.isClass(ref) || t.isFunction(ref)) {
|
||||
if (ref.id) {
|
||||
nodes.push(t.toStatement(ref));
|
||||
ref = ref.id;
|
||||
var importsVisitor = {
|
||||
enter(node, parent, scope, formatter) {
|
||||
if (t.isImportDeclaration(node)) {
|
||||
formatter.hasLocalImports = true;
|
||||
extend(formatter.localImports, t.getBindingIdentifiers(node));
|
||||
formatter.bumpImportOccurences(node);
|
||||
}
|
||||
}
|
||||
|
||||
return ref;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype._hoistExport = function (declar, assign, priority) {
|
||||
if (t.isFunctionDeclaration(declar)) {
|
||||
assign._blockHoist = priority || 2;
|
||||
}
|
||||
var exportsVisitor = {
|
||||
enter(node, parent, scope, formatter) {
|
||||
var declar = node && node.declaration;
|
||||
if (t.isExportDeclaration(node)) {
|
||||
formatter.hasLocalImports = true;
|
||||
|
||||
return assign;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getExternalReference = function (node, nodes) {
|
||||
var ids = this.ids;
|
||||
var id = node.source.value;
|
||||
|
||||
if (ids[id]) {
|
||||
return ids[id];
|
||||
} else {
|
||||
return this.ids[id] = this._getExternalReference(node, nodes);
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.checkExportIdentifier = function (node) {
|
||||
if (t.isIdentifier(node, { name: "__esModule" })) {
|
||||
throw this.file.errorWithNode(node, messages.get("modulesIllegalExportName", node.name));
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
|
||||
if (node.source) {
|
||||
var ref = this.getExternalReference(node, nodes);
|
||||
|
||||
if (t.isExportBatchSpecifier(specifier)) {
|
||||
// export * from "foo";
|
||||
nodes.push(this.buildExportsWildcard(ref, node));
|
||||
} else {
|
||||
if (t.isSpecifierDefault(specifier) && !this.noInteropRequireExport) {
|
||||
// importing a default so we need to normalize it
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
} else {
|
||||
ref = t.memberExpression(ref, t.getSpecifierId(specifier));
|
||||
if (declar && t.isStatement(declar)) {
|
||||
extend(formatter.localExports, t.getBindingIdentifiers(declar));
|
||||
}
|
||||
|
||||
// export { foo } from "test";
|
||||
nodes.push(this.buildExportsAssignment(
|
||||
t.getSpecifierName(specifier),
|
||||
ref,
|
||||
node
|
||||
));
|
||||
if (!node.default) {
|
||||
formatter.hasNonDefaultExports = true;
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
formatter.bumpImportOccurences(node);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// export { foo };
|
||||
nodes.push(this.buildExportsAssignment(t.getSpecifierName(specifier), specifier.id, node));
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.buildExportsWildcard = function (objectIdentifier) {
|
||||
return t.expressionStatement(t.callExpression(this.file.addHelper("defaults"), [
|
||||
t.identifier("exports"),
|
||||
t.callExpression(this.file.addHelper("interop-require-wildcard"), [objectIdentifier])
|
||||
]));
|
||||
};
|
||||
export default class DefaultFormatter {
|
||||
constructor(file) {
|
||||
this.scope = file.scope;
|
||||
this.file = file;
|
||||
this.ids = object();
|
||||
|
||||
DefaultFormatter.prototype.buildExportsAssignment = function (id, init) {
|
||||
this.checkExportIdentifier(id);
|
||||
return util.template("exports-assign", {
|
||||
VALUE: init,
|
||||
KEY: id
|
||||
}, true);
|
||||
};
|
||||
this.hasNonDefaultExports = false;
|
||||
|
||||
DefaultFormatter.prototype.exportDeclaration = function (node, nodes) {
|
||||
var declar = node.declaration;
|
||||
this.hasLocalExports = false;
|
||||
this.hasLocalImports = false;
|
||||
|
||||
var id = declar.id;
|
||||
this.localImportOccurences = object();
|
||||
this.localExports = object();
|
||||
this.localImports = object();
|
||||
|
||||
if (node.default) {
|
||||
id = t.identifier("default");
|
||||
this.getLocalExports();
|
||||
this.getLocalImports();
|
||||
|
||||
this.remapAssignments();
|
||||
}
|
||||
|
||||
var assign;
|
||||
|
||||
if (t.isVariableDeclaration(declar)) {
|
||||
for (var i = 0; i < declar.declarations.length; i++) {
|
||||
var decl = declar.declarations[i];
|
||||
|
||||
decl.init = this.buildExportsAssignment(decl.id, decl.init, node).expression;
|
||||
|
||||
var newDeclar = t.variableDeclaration(declar.kind, [decl]);
|
||||
if (i === 0) t.inherits(newDeclar, declar);
|
||||
nodes.push(newDeclar);
|
||||
}
|
||||
} else {
|
||||
var ref = declar;
|
||||
|
||||
if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) {
|
||||
ref = declar.id;
|
||||
nodes.push(declar);
|
||||
}
|
||||
|
||||
assign = this.buildExportsAssignment(id, ref, node);
|
||||
|
||||
nodes.push(assign);
|
||||
|
||||
this._hoistExport(declar, assign);
|
||||
doDefaultExportInterop(node) {
|
||||
return node.default && !this.noInteropRequireExport && !this.hasNonDefaultExports;
|
||||
}
|
||||
};
|
||||
|
||||
bumpImportOccurences(node) {
|
||||
var source = node.source.value;
|
||||
var occurs = this.localImportOccurences;
|
||||
occurs[source] ||= 0;
|
||||
occurs[source] += node.specifiers.length;
|
||||
}
|
||||
|
||||
getLocalExports() {
|
||||
this.file.scope.traverse(this.file.ast, exportsVisitor, this);
|
||||
}
|
||||
|
||||
getLocalImports() {
|
||||
this.file.scope.traverse(this.file.ast, importsVisitor, this);
|
||||
}
|
||||
|
||||
remapAssignments() {
|
||||
if (this.hasLocalImports) {
|
||||
this.file.scope.traverse(this.file.ast, remapVisitor, this);
|
||||
}
|
||||
}
|
||||
|
||||
isLocalReference(node) {
|
||||
var localImports = this.localImports;
|
||||
return t.isIdentifier(node) && localImports[node.name] && localImports[node.name] !== node;
|
||||
}
|
||||
|
||||
remapExportAssignment(node) {
|
||||
return t.assignmentExpression(
|
||||
"=",
|
||||
node.left,
|
||||
t.assignmentExpression(
|
||||
node.operator,
|
||||
t.memberExpression(t.identifier("exports"), node.left),
|
||||
node.right
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
isLocalReference(node, scope) {
|
||||
var localExports = this.localExports;
|
||||
var name = node.name;
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBindingIdentifier(name);
|
||||
}
|
||||
|
||||
getModuleName() {
|
||||
var opts = this.file.opts;
|
||||
if (opts.moduleId) return opts.moduleId;
|
||||
|
||||
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, "");
|
||||
}
|
||||
|
||||
if (!opts.keepModuleIdExtensions) {
|
||||
// remove extension
|
||||
filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");
|
||||
}
|
||||
|
||||
moduleName += filenameRelative;
|
||||
|
||||
// normalize path separators
|
||||
moduleName = moduleName.replace(/\\/g, "/");
|
||||
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
_pushStatement(ref, nodes) {
|
||||
if (t.isClass(ref) || t.isFunction(ref)) {
|
||||
if (ref.id) {
|
||||
nodes.push(t.toStatement(ref));
|
||||
ref = ref.id;
|
||||
}
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
_hoistExport(declar, assign, priority) {
|
||||
if (t.isFunctionDeclaration(declar)) {
|
||||
assign._blockHoist = priority || 2;
|
||||
}
|
||||
|
||||
return assign;
|
||||
}
|
||||
|
||||
getExternalReference(node, nodes) {
|
||||
var ids = this.ids;
|
||||
var id = node.source.value;
|
||||
|
||||
if (ids[id]) {
|
||||
return ids[id];
|
||||
} else {
|
||||
return this.ids[id] = this._getExternalReference(node, nodes);
|
||||
}
|
||||
}
|
||||
|
||||
checkExportIdentifier(node) {
|
||||
if (t.isIdentifier(node, { name: "__esModule" })) {
|
||||
throw this.file.errorWithNode(node, messages.get("modulesIllegalExportName", node.name));
|
||||
}
|
||||
}
|
||||
|
||||
exportSpecifier(specifier, node, nodes) {
|
||||
if (node.source) {
|
||||
var ref = this.getExternalReference(node, nodes);
|
||||
|
||||
if (t.isExportBatchSpecifier(specifier)) {
|
||||
// export * from "foo";
|
||||
nodes.push(this.buildExportsWildcard(ref, node));
|
||||
} else {
|
||||
if (t.isSpecifierDefault(specifier) && !this.noInteropRequireExport) {
|
||||
// importing a default so we need to normalize it
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
} else {
|
||||
ref = t.memberExpression(ref, t.getSpecifierId(specifier));
|
||||
}
|
||||
|
||||
// export { foo } from "test";
|
||||
nodes.push(this.buildExportsAssignment(
|
||||
t.getSpecifierName(specifier),
|
||||
ref,
|
||||
node
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// export { foo };
|
||||
nodes.push(this.buildExportsAssignment(t.getSpecifierName(specifier), specifier.id, node));
|
||||
}
|
||||
}
|
||||
|
||||
buildExportsWildcard(objectIdentifier) {
|
||||
return t.expressionStatement(t.callExpression(this.file.addHelper("defaults"), [
|
||||
t.identifier("exports"),
|
||||
t.callExpression(this.file.addHelper("interop-require-wildcard"), [objectIdentifier])
|
||||
]));
|
||||
}
|
||||
|
||||
buildExportsAssignment(id, init) {
|
||||
this.checkExportIdentifier(id);
|
||||
return util.template("exports-assign", {
|
||||
VALUE: init,
|
||||
KEY: id
|
||||
}, true);
|
||||
}
|
||||
|
||||
exportDeclaration(node, nodes) {
|
||||
var declar = node.declaration;
|
||||
|
||||
var id = declar.id;
|
||||
|
||||
if (node.default) {
|
||||
id = t.identifier("default");
|
||||
}
|
||||
|
||||
var assign;
|
||||
|
||||
if (t.isVariableDeclaration(declar)) {
|
||||
for (var i = 0; i < declar.declarations.length; i++) {
|
||||
var decl = declar.declarations[i];
|
||||
|
||||
decl.init = this.buildExportsAssignment(decl.id, decl.init, node).expression;
|
||||
|
||||
var newDeclar = t.variableDeclaration(declar.kind, [decl]);
|
||||
if (i === 0) t.inherits(newDeclar, declar);
|
||||
nodes.push(newDeclar);
|
||||
}
|
||||
} else {
|
||||
var ref = declar;
|
||||
|
||||
if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) {
|
||||
ref = declar.id;
|
||||
nodes.push(declar);
|
||||
}
|
||||
|
||||
assign = this.buildExportsAssignment(id, ref, node);
|
||||
|
||||
nodes.push(assign);
|
||||
|
||||
this._hoistExport(declar, assign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use strict";
|
||||
import * as util from "../../util";
|
||||
|
||||
var util = require("../../util");
|
||||
|
||||
module.exports = function (Parent) {
|
||||
export default function (Parent) {
|
||||
var Constructor = function () {
|
||||
this.noInteropRequireImport = true;
|
||||
this.noInteropRequireExport = true;
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = require("./_strict")(require("./amd"));
|
||||
|
||||
@@ -1,108 +1,100 @@
|
||||
"use strict";
|
||||
import DefaultFormatter from "./_default";
|
||||
import CommonFormatter from "./common";
|
||||
import includes from "lodash/collection/includes";
|
||||
import values from "lodash/object/values";
|
||||
import * as util from "../../util";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = AMDFormatter;
|
||||
export default class AMDFormatter extends DefaultFormatter {
|
||||
init = CommonFormatter.prototype.init;
|
||||
|
||||
var DefaultFormatter = require("./_default");
|
||||
var CommonFormatter = require("./common");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var values = require("lodash/object/values");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
buildDependencyLiterals() {
|
||||
var names = [];
|
||||
for (var name in this.ids) {
|
||||
names.push(t.literal(name));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
function AMDFormatter() {
|
||||
CommonFormatter.apply(this, arguments);
|
||||
/**
|
||||
* Wrap the entire body in a `define` wrapper.
|
||||
*/
|
||||
|
||||
transform(program) {
|
||||
var body = program.body;
|
||||
|
||||
// build an array of module names
|
||||
|
||||
var names = [t.literal("exports")];
|
||||
if (this.passModuleArg) names.push(t.literal("module"));
|
||||
names = names.concat(this.buildDependencyLiterals());
|
||||
names = t.arrayExpression(names);
|
||||
|
||||
// build up define container
|
||||
|
||||
var params = values(this.ids);
|
||||
if (this.passModuleArg) params.unshift(t.identifier("module"));
|
||||
params.unshift(t.identifier("exports"));
|
||||
|
||||
var container = t.functionExpression(null, params, t.blockStatement(body));
|
||||
|
||||
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)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AMD module name that we'll prepend to the wrapper
|
||||
* to define this module
|
||||
*/
|
||||
|
||||
getModuleName() {
|
||||
if (this.file.opts.moduleIds) {
|
||||
return DefaultFormatter.prototype.getModuleName.apply(this, arguments);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
_getExternalReference(node) {
|
||||
return this.scope.generateUidIdentifier(node.source.value);
|
||||
}
|
||||
|
||||
importDeclaration(node) {
|
||||
this.getExternalReference(node);
|
||||
}
|
||||
|
||||
importSpecifier(specifier, node, nodes) {
|
||||
var key = t.getSpecifierName(specifier);
|
||||
var ref = this.getExternalReference(node);
|
||||
|
||||
if (includes(this.file.dynamicImportedNoDefault, node)) {
|
||||
// Prevent unnecessary renaming of dynamic imports.
|
||||
this.ids[node.source.value] = ref;
|
||||
} else if (t.isImportBatchSpecifier(specifier)) {
|
||||
// import * as bar from "foo";
|
||||
} else if (!includes(this.file.dynamicImported, node) && t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {
|
||||
// import foo from "foo";
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
} else {
|
||||
// import {foo} from "foo";
|
||||
ref = t.memberExpression(ref, t.getSpecifierId(specifier), false);
|
||||
}
|
||||
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(key, ref)
|
||||
]));
|
||||
}
|
||||
|
||||
exportDeclaration(node) {
|
||||
if (this.doDefaultExportInterop(node)) {
|
||||
this.passModuleArg = true;
|
||||
}
|
||||
|
||||
CommonFormatter.prototype.exportDeclaration.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(AMDFormatter, DefaultFormatter);
|
||||
|
||||
AMDFormatter.prototype.init = CommonFormatter.prototype.init;
|
||||
|
||||
AMDFormatter.prototype.buildDependencyLiterals = function () {
|
||||
var names = [];
|
||||
for (var name in this.ids) {
|
||||
names.push(t.literal(name));
|
||||
}
|
||||
return names;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrap the entire body in a `define` wrapper.
|
||||
*/
|
||||
|
||||
AMDFormatter.prototype.transform = function (program) {
|
||||
var body = program.body;
|
||||
|
||||
// build an array of module names
|
||||
|
||||
var names = [t.literal("exports")];
|
||||
if (this.passModuleArg) names.push(t.literal("module"));
|
||||
names = names.concat(this.buildDependencyLiterals());
|
||||
names = t.arrayExpression(names);
|
||||
|
||||
// build up define container
|
||||
|
||||
var params = values(this.ids);
|
||||
if (this.passModuleArg) params.unshift(t.identifier("module"));
|
||||
params.unshift(t.identifier("exports"));
|
||||
|
||||
var container = t.functionExpression(null, params, t.blockStatement(body));
|
||||
|
||||
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)];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the AMD module name that we'll prepend to the wrapper
|
||||
* to define this module
|
||||
*/
|
||||
|
||||
AMDFormatter.prototype.getModuleName = function () {
|
||||
if (this.file.opts.moduleIds) {
|
||||
return DefaultFormatter.prototype.getModuleName.apply(this, arguments);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
AMDFormatter.prototype._getExternalReference = function (node) {
|
||||
return this.scope.generateUidIdentifier(node.source.value);
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.importDeclaration = function (node) {
|
||||
this.getExternalReference(node);
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
var key = t.getSpecifierName(specifier);
|
||||
var ref = this.getExternalReference(node);
|
||||
|
||||
if (includes(this.file.dynamicImportedNoDefault, node)) {
|
||||
// Prevent unnecessary renaming of dynamic imports.
|
||||
this.ids[node.source.value] = ref;
|
||||
} else if (t.isImportBatchSpecifier(specifier)) {
|
||||
// import * as bar from "foo";
|
||||
} else if (!includes(this.file.dynamicImported, node) && t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {
|
||||
// import foo from "foo";
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
} else {
|
||||
// import {foo} from "foo";
|
||||
ref = t.memberExpression(ref, t.getSpecifierId(specifier), false);
|
||||
}
|
||||
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(key, ref)
|
||||
]));
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.exportDeclaration = function (node) {
|
||||
if (this.doDefaultExportInterop(node)) {
|
||||
this.passModuleArg = true;
|
||||
}
|
||||
|
||||
CommonFormatter.prototype.exportDeclaration.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = require("./_strict")(require("./common"));
|
||||
|
||||
@@ -1,106 +1,98 @@
|
||||
"use strict";
|
||||
import DefaultFormatter from "./_default";
|
||||
import includes from "lodash/collection/includes";
|
||||
import * as util from "../../util";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = CommonJSFormatter;
|
||||
export default class CommonJSFormatter extends DefaultFormatter {
|
||||
init() {
|
||||
var file = this.file;
|
||||
var scope = file.scope;
|
||||
|
||||
var DefaultFormatter = require("./_default");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
scope.rename("module");
|
||||
|
||||
function CommonJSFormatter() {
|
||||
DefaultFormatter.apply(this, arguments);
|
||||
}
|
||||
|
||||
util.inherits(CommonJSFormatter, DefaultFormatter);
|
||||
|
||||
CommonJSFormatter.prototype.init = function () {
|
||||
var file = this.file;
|
||||
var scope = file.scope;
|
||||
|
||||
scope.rename("module");
|
||||
|
||||
if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
|
||||
var templateName = "exports-module-declaration";
|
||||
if (this.file.isLoose("es6.modules")) templateName += "-loose";
|
||||
file.ast.program.body.push(util.template(templateName, true));
|
||||
}
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
var variableName = t.getSpecifierName(specifier);
|
||||
|
||||
var ref = this.getExternalReference(node, nodes);
|
||||
|
||||
// import foo from "foo";
|
||||
if (t.isSpecifierDefault(specifier)) {
|
||||
if (!includes(this.file.dynamicImportedNoDefault, node)) {
|
||||
if (this.noInteropRequireImport || includes(this.file.dynamicImported, node)) {
|
||||
ref = t.memberExpression(ref, t.identifier("default"));
|
||||
} else {
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
}
|
||||
if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
|
||||
var templateName = "exports-module-declaration";
|
||||
if (this.file.isLoose("es6.modules")) templateName += "-loose";
|
||||
file.ast.program.body.push(util.template(templateName, true));
|
||||
}
|
||||
nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, ref)]));
|
||||
} else {
|
||||
if (specifier.type === "ImportBatchSpecifier") {
|
||||
};
|
||||
|
||||
if (!this.noInteropRequireImport) {
|
||||
ref = t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]);
|
||||
importSpecifier(specifier, node, nodes) {
|
||||
var variableName = t.getSpecifierName(specifier);
|
||||
|
||||
var ref = this.getExternalReference(node, nodes);
|
||||
|
||||
// import foo from "foo";
|
||||
if (t.isSpecifierDefault(specifier)) {
|
||||
if (!includes(this.file.dynamicImportedNoDefault, node)) {
|
||||
if (this.noInteropRequireImport || includes(this.file.dynamicImported, node)) {
|
||||
ref = t.memberExpression(ref, t.identifier("default"));
|
||||
} else {
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
}
|
||||
}
|
||||
|
||||
// import * as bar from "foo";
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(variableName, ref)
|
||||
]));
|
||||
nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, ref)]));
|
||||
} else {
|
||||
// import { foo } from "foo";
|
||||
if (specifier.type === "ImportBatchSpecifier") {
|
||||
|
||||
if (!this.noInteropRequireImport) {
|
||||
ref = t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]);
|
||||
}
|
||||
|
||||
// import * as bar from "foo";
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(variableName, ref)
|
||||
]));
|
||||
} else {
|
||||
// import { foo } from "foo";
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
variableName,
|
||||
t.memberExpression(ref, t.getSpecifierId(specifier))
|
||||
)
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
importDeclaration(node, nodes) {
|
||||
// import "foo";
|
||||
nodes.push(util.template("require", {
|
||||
MODULE_NAME: node.source
|
||||
}, true));
|
||||
}
|
||||
|
||||
exportDeclaration(node, nodes) {
|
||||
if (this.doDefaultExportInterop(node)) {
|
||||
var declar = node.declaration;
|
||||
var assign = util.template("exports-default-assign", {
|
||||
VALUE: this._pushStatement(declar, nodes)
|
||||
}, true);
|
||||
|
||||
if (t.isFunctionDeclaration(declar)) {
|
||||
// we can hoist this assignment to the top of the file
|
||||
assign._blockHoist = 3;
|
||||
}
|
||||
|
||||
nodes.push(assign);
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
|
||||
}
|
||||
|
||||
_getExternalReference(node, nodes) {
|
||||
var source = node.source.value;
|
||||
var call = t.callExpression(t.identifier("require"), [node.source]);
|
||||
|
||||
if (this.localImportOccurences[source] > 1) {
|
||||
var uid = this.scope.generateUidIdentifier(source);
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
variableName,
|
||||
t.memberExpression(ref, t.getSpecifierId(specifier))
|
||||
)
|
||||
t.variableDeclarator(uid, call)
|
||||
]));
|
||||
return uid;
|
||||
} else {
|
||||
return call;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.importDeclaration = function (node, nodes) {
|
||||
// import "foo";
|
||||
nodes.push(util.template("require", {
|
||||
MODULE_NAME: node.source
|
||||
}, true));
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.exportDeclaration = function (node, nodes) {
|
||||
if (this.doDefaultExportInterop(node)) {
|
||||
var declar = node.declaration;
|
||||
var assign = util.template("exports-default-assign", {
|
||||
VALUE: this._pushStatement(declar, nodes)
|
||||
}, true);
|
||||
|
||||
if (t.isFunctionDeclaration(declar)) {
|
||||
// we can hoist this assignment to the top of the file
|
||||
assign._blockHoist = 3;
|
||||
}
|
||||
|
||||
nodes.push(assign);
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype._getExternalReference = function (node, nodes) {
|
||||
var source = node.source.value;
|
||||
var call = t.callExpression(t.identifier("require"), [node.source]);
|
||||
|
||||
if (this.localImportOccurences[source] > 1) {
|
||||
var uid = this.scope.generateUidIdentifier(source);
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(uid, call)
|
||||
]));
|
||||
return uid;
|
||||
} else {
|
||||
return call;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
"use strict";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = IgnoreFormatter;
|
||||
|
||||
var t = require("../../types");
|
||||
|
||||
function IgnoreFormatter() {
|
||||
export default class IgnoreFormatter {
|
||||
exportDeclaration(node, nodes) {
|
||||
var declar = t.toStatement(node.declaration, true);
|
||||
if (declar) nodes.push(t.inherits(declar, node));
|
||||
}
|
||||
|
||||
importDeclaration() {}
|
||||
importSpecifier() {}
|
||||
exportSpecifier() {}
|
||||
}
|
||||
|
||||
IgnoreFormatter.prototype.exportDeclaration = function (node, nodes) {
|
||||
var declar = t.toStatement(node.declaration, true);
|
||||
if (declar) nodes.push(t.inherits(declar, node));
|
||||
};
|
||||
|
||||
IgnoreFormatter.prototype.importDeclaration =
|
||||
IgnoreFormatter.prototype.importSpecifier =
|
||||
IgnoreFormatter.prototype.exportSpecifier = function () {
|
||||
|
||||
};
|
||||
|
||||
@@ -1,109 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = SystemFormatter;
|
||||
|
||||
var DefaultFormatter = require("./_default");
|
||||
var AMDFormatter = require("./amd");
|
||||
var util = require("../../util");
|
||||
var last = require("lodash/array/last");
|
||||
var each = require("lodash/collection/each");
|
||||
var map = require("lodash/collection/map");
|
||||
var t = require("../../types");
|
||||
|
||||
function SystemFormatter(file) {
|
||||
this.exportIdentifier = file.scope.generateUidIdentifier("export");
|
||||
this.noInteropRequireExport = true;
|
||||
this.noInteropRequireImport = true;
|
||||
|
||||
DefaultFormatter.apply(this, arguments);
|
||||
}
|
||||
|
||||
util.inherits(SystemFormatter, AMDFormatter);
|
||||
|
||||
SystemFormatter.prototype.init = function () {};
|
||||
|
||||
SystemFormatter.prototype._addImportSource = function (node, exportNode) {
|
||||
node._importSource = exportNode.source && exportNode.source.value;
|
||||
return node;
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.buildExportsWildcard = function (objectIdentifier, node) {
|
||||
var leftIdentifier = this.scope.generateUidIdentifier("key");
|
||||
var valIdentifier = t.memberExpression(objectIdentifier, leftIdentifier, true);
|
||||
|
||||
var left = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(leftIdentifier)
|
||||
]);
|
||||
|
||||
var right = objectIdentifier;
|
||||
|
||||
var block = t.blockStatement([
|
||||
t.expressionStatement(this.buildExportCall(leftIdentifier, valIdentifier))
|
||||
]);
|
||||
|
||||
return this._addImportSource(t.forInStatement(left, right, block), node);
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.buildExportsAssignment = function (id, init, node) {
|
||||
var call = this.buildExportCall(t.literal(id.name), init, true);
|
||||
return this._addImportSource(call, node);
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.remapExportAssignment = function (node) {
|
||||
return this.buildExportCall(t.literal(node.left.name), node);
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.buildExportCall = function (id, init, isStatement) {
|
||||
var call = t.callExpression(this.exportIdentifier, [id, init]);
|
||||
if (isStatement) {
|
||||
return t.expressionStatement(call);
|
||||
} else {
|
||||
return call;
|
||||
}
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
AMDFormatter.prototype.importSpecifier.apply(this, arguments);
|
||||
this._addImportSource(last(nodes), node);
|
||||
};
|
||||
|
||||
var runnerSettersVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (node._importSource === state.source) {
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
each(node.declarations, function (declar) {
|
||||
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
|
||||
state.nodes.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", declar.id, declar.init)
|
||||
));
|
||||
});
|
||||
} else {
|
||||
state.nodes.push(node);
|
||||
}
|
||||
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.buildRunnerSetters = function (block, hoistDeclarators) {
|
||||
var scope = this.file.scope;
|
||||
|
||||
return t.arrayExpression(map(this.ids, function (uid, source) {
|
||||
var state = {
|
||||
source: source,
|
||||
nodes: [],
|
||||
hoistDeclarators: hoistDeclarators
|
||||
};
|
||||
|
||||
scope.traverse(block, runnerSettersVisitor, state);
|
||||
|
||||
return t.functionExpression(null, [uid], t.blockStatement(state.nodes));
|
||||
}));
|
||||
};
|
||||
import DefaultFormatter from "./_default";
|
||||
import AMDFormatter from "./amd";
|
||||
import * as util from "../../util";
|
||||
import last from "lodash/array/last";
|
||||
import each from "lodash/collection/each";
|
||||
import map from "lodash/collection/map";
|
||||
import t from "../../types";
|
||||
|
||||
var hoistVariablesVisitor = {
|
||||
enter: function (node, parent, scope, hoistDeclarators) {
|
||||
enter(node, parent, scope, hoistDeclarators) {
|
||||
if (t.isFunction(node)) {
|
||||
// nothing inside is accessible
|
||||
return this.skip();
|
||||
@@ -148,7 +52,7 @@ var hoistVariablesVisitor = {
|
||||
};
|
||||
|
||||
var hoistFunctionsVisitor = {
|
||||
enter: function (node, parent, scope, handlerBody) {
|
||||
enter(node, parent, scope, handlerBody) {
|
||||
if (t.isFunction(node)) this.skip();
|
||||
|
||||
if (t.isFunctionDeclaration(node) || node._blockHoist) {
|
||||
@@ -158,39 +62,131 @@ var hoistFunctionsVisitor = {
|
||||
}
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.transform = function (program) {
|
||||
var hoistDeclarators = [];
|
||||
var moduleName = this.getModuleName();
|
||||
var moduleNameLiteral = t.literal(moduleName);
|
||||
var runnerSettersVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (node._importSource === state.source) {
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
each(node.declarations, function (declar) {
|
||||
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
|
||||
state.nodes.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", declar.id, declar.init)
|
||||
));
|
||||
});
|
||||
} else {
|
||||
state.nodes.push(node);
|
||||
}
|
||||
|
||||
var block = t.blockStatement(program.body);
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var runner = util.template("system", {
|
||||
MODULE_NAME: moduleNameLiteral,
|
||||
MODULE_DEPENDENCIES: t.arrayExpression(this.buildDependencyLiterals()),
|
||||
EXPORT_IDENTIFIER: this.exportIdentifier,
|
||||
SETTERS: this.buildRunnerSetters(block, hoistDeclarators),
|
||||
EXECUTE: t.functionExpression(null, [], block)
|
||||
}, true);
|
||||
export default class SystemFormatter extends AMDFormatter {
|
||||
constructor(file) {
|
||||
this.exportIdentifier = file.scope.generateUidIdentifier("export");
|
||||
this.noInteropRequireExport = true;
|
||||
this.noInteropRequireImport = true;
|
||||
|
||||
var handlerBody = runner.expression.arguments[2].body.body;
|
||||
if (!moduleName) runner.expression.arguments.shift();
|
||||
|
||||
var returnStatement = handlerBody.pop();
|
||||
|
||||
// hoist up all variable declarations
|
||||
this.file.scope.traverse(block, hoistVariablesVisitor, hoistDeclarators);
|
||||
|
||||
if (hoistDeclarators.length) {
|
||||
var hoistDeclar = t.variableDeclaration("var", hoistDeclarators);
|
||||
hoistDeclar._blockHoist = true;
|
||||
handlerBody.unshift(hoistDeclar);
|
||||
DefaultFormatter.apply(this, arguments);
|
||||
}
|
||||
|
||||
// hoist up function declarations for circular references
|
||||
this.file.scope.traverse(block, hoistFunctionsVisitor, handlerBody);
|
||||
init() {}
|
||||
|
||||
handlerBody.push(returnStatement);
|
||||
_addImportSource(node, exportNode) {
|
||||
node._importSource = exportNode.source && exportNode.source.value;
|
||||
return node;
|
||||
}
|
||||
|
||||
program.body = [runner];
|
||||
};
|
||||
buildExportsWildcard(objectIdentifier, node) {
|
||||
var leftIdentifier = this.scope.generateUidIdentifier("key");
|
||||
var valIdentifier = t.memberExpression(objectIdentifier, leftIdentifier, true);
|
||||
|
||||
var left = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(leftIdentifier)
|
||||
]);
|
||||
|
||||
var right = objectIdentifier;
|
||||
|
||||
var block = t.blockStatement([
|
||||
t.expressionStatement(this.buildExportCall(leftIdentifier, valIdentifier))
|
||||
]);
|
||||
|
||||
return this._addImportSource(t.forInStatement(left, right, block), node);
|
||||
}
|
||||
|
||||
buildExportsAssignment(id, init, node) {
|
||||
var call = this.buildExportCall(t.literal(id.name), init, true);
|
||||
return this._addImportSource(call, node);
|
||||
}
|
||||
|
||||
remapExportAssignment(node) {
|
||||
return this.buildExportCall(t.literal(node.left.name), node);
|
||||
}
|
||||
|
||||
buildExportCall(id, init, isStatement) {
|
||||
var call = t.callExpression(this.exportIdentifier, [id, init]);
|
||||
if (isStatement) {
|
||||
return t.expressionStatement(call);
|
||||
} else {
|
||||
return call;
|
||||
}
|
||||
}
|
||||
|
||||
importSpecifier(specifier, node, nodes) {
|
||||
AMDFormatter.prototype.importSpecifier.apply(this, arguments);
|
||||
this._addImportSource(last(nodes), node);
|
||||
}
|
||||
|
||||
buildRunnerSetters(block, hoistDeclarators) {
|
||||
var scope = this.file.scope;
|
||||
|
||||
return t.arrayExpression(map(this.ids, function (uid, source) {
|
||||
var state = {
|
||||
source: source,
|
||||
nodes: [],
|
||||
hoistDeclarators: hoistDeclarators
|
||||
};
|
||||
|
||||
scope.traverse(block, runnerSettersVisitor, state);
|
||||
|
||||
return t.functionExpression(null, [uid], t.blockStatement(state.nodes));
|
||||
}));
|
||||
}
|
||||
|
||||
transform(program) {
|
||||
var hoistDeclarators = [];
|
||||
var moduleName = this.getModuleName();
|
||||
var moduleNameLiteral = t.literal(moduleName);
|
||||
|
||||
var block = t.blockStatement(program.body);
|
||||
|
||||
var runner = util.template("system", {
|
||||
MODULE_NAME: moduleNameLiteral,
|
||||
MODULE_DEPENDENCIES: t.arrayExpression(this.buildDependencyLiterals()),
|
||||
EXPORT_IDENTIFIER: this.exportIdentifier,
|
||||
SETTERS: this.buildRunnerSetters(block, hoistDeclarators),
|
||||
EXECUTE: t.functionExpression(null, [], block)
|
||||
}, true);
|
||||
|
||||
var handlerBody = runner.expression.arguments[2].body.body;
|
||||
if (!moduleName) runner.expression.arguments.shift();
|
||||
|
||||
var returnStatement = handlerBody.pop();
|
||||
|
||||
// hoist up all variable declarations
|
||||
this.file.scope.traverse(block, hoistVariablesVisitor, hoistDeclarators);
|
||||
|
||||
if (hoistDeclarators.length) {
|
||||
var hoistDeclar = t.variableDeclaration("var", hoistDeclarators);
|
||||
hoistDeclar._blockHoist = true;
|
||||
handlerBody.unshift(hoistDeclar);
|
||||
}
|
||||
|
||||
// hoist up function declarations for circular references
|
||||
this.file.scope.traverse(block, hoistFunctionsVisitor, handlerBody);
|
||||
|
||||
handlerBody.push(returnStatement);
|
||||
|
||||
program.body = [runner];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = require("./_strict")(require("./umd"));
|
||||
|
||||
@@ -1,73 +1,65 @@
|
||||
"use strict";
|
||||
import AMDFormatter from "./amd";
|
||||
import values from "lodash/object/values";
|
||||
import * as util from "../../util";
|
||||
import t from "../../types";
|
||||
|
||||
module.exports = UMDFormatter;
|
||||
export default class UMDFormatter extends AMDFormatter {
|
||||
transform(program) {
|
||||
var body = program.body;
|
||||
|
||||
var AMDFormatter = require("./amd");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
var values = require("lodash/object/values");
|
||||
// build an array of module names
|
||||
|
||||
function UMDFormatter() {
|
||||
AMDFormatter.apply(this, arguments);
|
||||
}
|
||||
var names = [];
|
||||
for (var name in this.ids) {
|
||||
names.push(t.literal(name));
|
||||
}
|
||||
|
||||
util.inherits(UMDFormatter, AMDFormatter);
|
||||
// factory
|
||||
|
||||
UMDFormatter.prototype.transform = function (program) {
|
||||
var body = program.body;
|
||||
var ids = values(this.ids);
|
||||
var args = [t.identifier("exports")];
|
||||
if (this.passModuleArg) args.push(t.identifier("module"));
|
||||
args = args.concat(ids);
|
||||
|
||||
// build an array of module names
|
||||
var factory = t.functionExpression(null, args, t.blockStatement(body));
|
||||
|
||||
var names = [];
|
||||
for (var name in this.ids) {
|
||||
names.push(t.literal(name));
|
||||
// amd
|
||||
|
||||
var defineArgs = [t.literal("exports")];
|
||||
if (this.passModuleArg) defineArgs.push(t.literal("module"));
|
||||
defineArgs = defineArgs.concat(names);
|
||||
defineArgs = [t.arrayExpression(defineArgs)];
|
||||
|
||||
// common
|
||||
|
||||
var testExports = util.template("test-exports");
|
||||
var testModule = util.template("test-module");
|
||||
var commonTests = this.passModuleArg ? t.logicalExpression("&&", testExports, testModule) : testExports;
|
||||
|
||||
var commonArgs = [t.identifier("exports")];
|
||||
if (this.passModuleArg) commonArgs.push(t.identifier("module"));
|
||||
commonArgs = commonArgs.concat(names.map(function (name) {
|
||||
return t.callExpression(t.identifier("require"), [name]);
|
||||
}));
|
||||
|
||||
// globals
|
||||
|
||||
//var umdArgs = [];
|
||||
|
||||
//
|
||||
|
||||
var moduleName = this.getModuleName();
|
||||
if (moduleName) defineArgs.unshift(t.literal(moduleName));
|
||||
|
||||
var runner = util.template("umd-runner-body", {
|
||||
AMD_ARGUMENTS: defineArgs,
|
||||
COMMON_TEST: commonTests,
|
||||
COMMON_ARGUMENTS: commonArgs
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
var call = t.callExpression(runner, [factory]);
|
||||
program.body = [t.expressionStatement(call)];
|
||||
}
|
||||
|
||||
// factory
|
||||
|
||||
var ids = values(this.ids);
|
||||
var args = [t.identifier("exports")];
|
||||
if (this.passModuleArg) args.push(t.identifier("module"));
|
||||
args = args.concat(ids);
|
||||
|
||||
var factory = t.functionExpression(null, args, t.blockStatement(body));
|
||||
|
||||
// amd
|
||||
|
||||
var defineArgs = [t.literal("exports")];
|
||||
if (this.passModuleArg) defineArgs.push(t.literal("module"));
|
||||
defineArgs = defineArgs.concat(names);
|
||||
defineArgs = [t.arrayExpression(defineArgs)];
|
||||
|
||||
// common
|
||||
|
||||
var testExports = util.template("test-exports");
|
||||
var testModule = util.template("test-module");
|
||||
var commonTests = this.passModuleArg ? t.logicalExpression("&&", testExports, testModule) : testExports;
|
||||
|
||||
var commonArgs = [t.identifier("exports")];
|
||||
if (this.passModuleArg) commonArgs.push(t.identifier("module"));
|
||||
commonArgs = commonArgs.concat(names.map(function (name) {
|
||||
return t.callExpression(t.identifier("require"), [name]);
|
||||
}));
|
||||
|
||||
// globals
|
||||
|
||||
//var umdArgs = [];
|
||||
|
||||
//
|
||||
|
||||
var moduleName = this.getModuleName();
|
||||
if (moduleName) defineArgs.unshift(t.literal(moduleName));
|
||||
|
||||
var runner = util.template("umd-runner-body", {
|
||||
AMD_ARGUMENTS: defineArgs,
|
||||
COMMON_TEST: commonTests,
|
||||
COMMON_ARGUMENTS: commonArgs
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
var call = t.callExpression(runner, [factory]);
|
||||
program.body = [t.expressionStatement(call)];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"blacklist": ["useStrict", "es6.blockScoping"]
|
||||
"blacklist": ["useStrict", "es6.blockScoping", "regenerator"]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
for (var ITERATOR_KEY = OBJECT[Symbol.iterator](), STEP_KEY; !(STEP_KEY = ITERATOR_KEY.next()).done; ) {
|
||||
var ITERATOR_COMPLETION = true;
|
||||
var ITERATOR_HAD_ERROR_KEY = false;
|
||||
var ITERATOR_ERROR_KEY = undefined;
|
||||
try {
|
||||
for (var ITERATOR_KEY = OBJECT[Symbol.iterator](), STEP_KEY; !(ITERATOR_COMPLETION = (STEP_KEY = ITERATOR_KEY.next()).done); ITERATOR_COMPLETION = true) {
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
ITERATOR_HAD_ERROR_KEY = true;
|
||||
ITERATOR_ERROR_KEY = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!ITERATOR_COMPLETION && ITERATOR_KEY.return) {
|
||||
ITERATOR_KEY.return();
|
||||
}
|
||||
} finally {
|
||||
if (ITERATOR_HAD_ERROR_KEY) {
|
||||
throw ITERATOR_ERROR_KEY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
module.exports = TransformerPass;
|
||||
|
||||
var includes = require("lodash/collection/includes");
|
||||
import includes from "lodash/collection/includes";
|
||||
|
||||
/**
|
||||
* This class is responsible for traversing over the provided `File`s
|
||||
* AST and running it's parent transformers handlers over it.
|
||||
*/
|
||||
|
||||
function TransformerPass(file, transformer) {
|
||||
this.transformer = transformer;
|
||||
this.shouldRun = !transformer.check;
|
||||
this.handlers = transformer.handlers;
|
||||
this.file = file;
|
||||
}
|
||||
export default class TransformerPass {
|
||||
constructor(file, transformer) {
|
||||
this.transformer = transformer;
|
||||
this.shouldRun = !transformer.check;
|
||||
this.handlers = transformer.handlers;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
TransformerPass.prototype.canRun = function () {
|
||||
var transformer = this.transformer;
|
||||
canRun() {
|
||||
var transformer = this.transformer;
|
||||
|
||||
var opts = this.file.opts;
|
||||
var key = transformer.key;
|
||||
var opts = this.file.opts;
|
||||
var key = transformer.key;
|
||||
|
||||
// internal
|
||||
if (key[0] === "_") return true;
|
||||
// internal
|
||||
if (key[0] === "_") return true;
|
||||
|
||||
// blacklist
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && includes(blacklist, key)) return false;
|
||||
// blacklist
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && includes(blacklist, key)) return false;
|
||||
|
||||
// whitelist
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist.length) return includes(whitelist, key);
|
||||
// whitelist
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist.length) return includes(whitelist, key);
|
||||
|
||||
// optional
|
||||
if (transformer.optional && !includes(opts.optional, key)) return false;
|
||||
// optional
|
||||
if (transformer.optional && !includes(opts.optional, key)) return false;
|
||||
|
||||
// experimental
|
||||
if (transformer.experimental && !opts.experimental) return false;
|
||||
// experimental
|
||||
if (transformer.experimental && !opts.experimental) return false;
|
||||
|
||||
// playground
|
||||
if (transformer.playground && !opts.playground) return false;
|
||||
// playground
|
||||
if (transformer.playground && !opts.playground) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
TransformerPass.prototype.checkNode = function (node) {
|
||||
var check = this.transformer.check;
|
||||
if (check) {
|
||||
return this.shouldRun = check(node);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TransformerPass.prototype.transform = function () {
|
||||
if (!this.shouldRun) return;
|
||||
checkNode(node) {
|
||||
var check = this.transformer.check;
|
||||
if (check) {
|
||||
return this.shouldRun = check(node);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var file = this.file;
|
||||
transform() {
|
||||
if (!this.shouldRun) return;
|
||||
|
||||
file.debug("Running transformer " + this.transformer.key);
|
||||
var file = this.file;
|
||||
|
||||
file.scope.traverse(file.ast, this.handlers, file);
|
||||
};
|
||||
file.debug("Running transformer " + this.transformer.key);
|
||||
|
||||
file.scope.traverse(file.ast, this.handlers, file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = Transformer;
|
||||
|
||||
var TransformerPass = require("./transformer-pass");
|
||||
var isFunction = require("lodash/lang/isFunction");
|
||||
var traverse = require("../traversal");
|
||||
var isObject = require("lodash/lang/isObject");
|
||||
var assign = require("lodash/object/assign");
|
||||
var each = require("lodash/collection/each");
|
||||
import TransformerPass from "./transformer-pass";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import traverse from "../traversal";
|
||||
import isObject from "lodash/lang/isObject";
|
||||
import assign from "lodash/object/assign";
|
||||
import each from "lodash/collection/each";
|
||||
|
||||
/**
|
||||
* This is the class responsible for normalising a transformers handlers
|
||||
@@ -15,59 +11,61 @@ var each = require("lodash/collection/each");
|
||||
* actually running the transformer over the provided `File`.
|
||||
*/
|
||||
|
||||
function Transformer(key, transformer, opts) {
|
||||
transformer = assign({}, transformer);
|
||||
export default class Transformer {
|
||||
constructor(transformerKey, transformer, opts) {
|
||||
transformer = assign({}, transformer);
|
||||
|
||||
var take = function (key) {
|
||||
var val = transformer[key];
|
||||
delete transformer[key];
|
||||
return val;
|
||||
};
|
||||
var take = function (key) {
|
||||
var val = transformer[key];
|
||||
delete transformer[key];
|
||||
return val;
|
||||
};
|
||||
|
||||
this.manipulateOptions = take("manipulateOptions");
|
||||
this.check = take("check");
|
||||
this.post = take("post");
|
||||
this.pre = take("pre");
|
||||
this.manipulateOptions = take("manipulateOptions");
|
||||
this.check = take("check");
|
||||
this.post = take("post");
|
||||
this.pre = take("pre");
|
||||
|
||||
this.experimental = !!take("experimental");
|
||||
this.playground = !!take("playground");
|
||||
this.secondPass = !!take("secondPass");
|
||||
this.optional = !!take("optional");
|
||||
this.experimental = !!take("experimental");
|
||||
this.playground = !!take("playground");
|
||||
this.secondPass = !!take("secondPass");
|
||||
this.optional = !!take("optional");
|
||||
|
||||
this.handlers = this.normalize(transformer);
|
||||
this.opts = opts || {};
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
Transformer.prototype.normalize = function (transformer) {
|
||||
if (isFunction(transformer)) {
|
||||
transformer = { ast: transformer };
|
||||
this.handlers = this.normalize(transformer);
|
||||
this.opts ||= {};
|
||||
this.key = transformerKey;
|
||||
}
|
||||
|
||||
traverse.explode(transformer);
|
||||
|
||||
each(transformer, (fns, type) => {
|
||||
// hidden property
|
||||
if (type[0] === "_") {
|
||||
this[type] = fns;
|
||||
return;
|
||||
normalize(transformer) {
|
||||
if (isFunction(transformer)) {
|
||||
transformer = { ast: transformer };
|
||||
}
|
||||
|
||||
if (type === "enter" || type === "exit") return;
|
||||
traverse.explode(transformer);
|
||||
|
||||
if (isFunction(fns)) fns = { enter: fns };
|
||||
each(transformer, (fns, type) => {
|
||||
// hidden property
|
||||
if (type[0] === "_") {
|
||||
this[type] = fns;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isObject(fns)) return;
|
||||
if (type === "enter" || type === "exit") return;
|
||||
|
||||
if (!fns.enter) fns.enter = function () { };
|
||||
if (!fns.exit) fns.exit = function () { };
|
||||
if (isFunction(fns)) fns = { enter: fns };
|
||||
|
||||
transformer[type] = fns;
|
||||
});
|
||||
if (!isObject(fns)) return;
|
||||
|
||||
return transformer;
|
||||
};
|
||||
if (!fns.enter) fns.enter = function () { };
|
||||
if (!fns.exit) fns.exit = function () { };
|
||||
|
||||
Transformer.prototype.buildPass = function (file) {
|
||||
return new TransformerPass(file, this);
|
||||
};
|
||||
transformer[type] = fns;
|
||||
});
|
||||
|
||||
return transformer;
|
||||
}
|
||||
|
||||
buildPass(file) {
|
||||
return new TransformerPass(file, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
{
|
||||
"selfContained": "runtime"
|
||||
"selfContained": "runtime",
|
||||
"unicode-regex": "regex.unicode",
|
||||
|
||||
"minification.deadCodeElimination": "utility.deadCodeElimination",
|
||||
"minification.removeConsoleCalls": "utility.removeConsole",
|
||||
"minification.removeDebugger": "utility.removeDebugger"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use strict";
|
||||
import t from "../../../types";
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.MemberExpression = function (node) {
|
||||
export function MemberExpression(node) {
|
||||
var prop = node.property;
|
||||
if (node.computed && t.isLiteral(prop) && t.isValidIdentifier(prop.value)) {
|
||||
// foo["bar"] => foo.bar
|
||||
@@ -13,4 +11,4 @@ exports.MemberExpression = function (node) {
|
||||
node.property = t.literal(prop.name);
|
||||
node.computed = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"use strict";
|
||||
import t from "../../../types";
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.Property = function (node) {
|
||||
export function Property(node) {
|
||||
var key = node.key;
|
||||
if (t.isLiteral(key) && t.isValidIdentifier(key.value)) {
|
||||
// "foo": "bar" -> foo: "bar"
|
||||
@@ -12,4 +10,4 @@ exports.Property = function (node) {
|
||||
// default: "bar" -> "default": "bar"
|
||||
node.key = t.literal(key.name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
"use strict";
|
||||
import * as defineMap from "../../helpers/define-map";
|
||||
import t from "../../../types";
|
||||
|
||||
var defineMap = require("../../helpers/define-map");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
export function check(node) {
|
||||
return t.isProperty(node) && (node.kind === "get" || node.kind === "set");
|
||||
};
|
||||
}
|
||||
|
||||
exports.ObjectExpression = function (node) {
|
||||
export function ObjectExpression(node) {
|
||||
var mutatorMap = {};
|
||||
var hasAny = false;
|
||||
|
||||
@@ -27,4 +25,4 @@ exports.ObjectExpression = function (node) {
|
||||
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")),
|
||||
[node, defineMap.build(mutatorMap)]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
"use strict";
|
||||
import t from "../../../types";
|
||||
|
||||
var t = require("../../../types");
|
||||
export var check = t.isArrowFunctionExpression;
|
||||
|
||||
exports.check = t.isArrowFunctionExpression;
|
||||
|
||||
exports.ArrowFunctionExpression = function (node) {
|
||||
export function ArrowFunctionExpression(node) {
|
||||
t.ensureBlock(node);
|
||||
|
||||
node._aliasFunction = "arrow";
|
||||
@@ -12,4 +10,4 @@ exports.ArrowFunctionExpression = function (node) {
|
||||
node.type = "FunctionExpression";
|
||||
|
||||
return node;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
import t from "../../../types";
|
||||
|
||||
var visitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
|
||||
var declared = state.letRefs[node.name];
|
||||
@@ -28,11 +26,9 @@ var visitor = {
|
||||
}
|
||||
};
|
||||
|
||||
exports.optional = true;
|
||||
export var optional = true;
|
||||
|
||||
exports.Loop =
|
||||
exports.Program =
|
||||
exports.BlockStatement = function (node, parent, scope, file) {
|
||||
export function BlockStatement(node, parent, scope, file) {
|
||||
var letRefs = node._letReferences;
|
||||
if (!letRefs) return;
|
||||
|
||||
@@ -42,4 +38,6 @@ exports.BlockStatement = function (node, parent, scope, file) {
|
||||
};
|
||||
|
||||
scope.traverse(node, visitor, state);
|
||||
};
|
||||
}
|
||||
|
||||
export { BlockStatement as Program, BlockStatement as Loop };
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
"use strict";
|
||||
import traverse from "../../../traversal";
|
||||
import object from "../../../helpers/object";
|
||||
import * as util from "../../../util";
|
||||
import t from "../../../types";
|
||||
import values from "lodash/object/values";
|
||||
import extend from "lodash/object/extend";
|
||||
|
||||
var traverse = require("../../../traversal");
|
||||
var object = require("../../../helpers/object");
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
var values = require("lodash/object/values");
|
||||
var extend = require("lodash/object/extend");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const");
|
||||
};
|
||||
|
||||
var isLet = function (node, parent) {
|
||||
function isLet(node, parent) {
|
||||
if (!t.isVariableDeclaration(node)) return false;
|
||||
if (node._let) return true;
|
||||
if (node.kind !== "let") return false;
|
||||
@@ -20,30 +14,34 @@ var isLet = function (node, parent) {
|
||||
if (isLetInitable(node, parent)) {
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
var declar = node.declarations[i];
|
||||
declar.init = declar.init || t.identifier("undefined");
|
||||
declar.init ||= t.identifier("undefined");
|
||||
}
|
||||
}
|
||||
|
||||
node._let = true;
|
||||
node.kind = "var";
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
var isLetInitable = function (node, parent) {
|
||||
function isLetInitable(node, parent) {
|
||||
return !t.isFor(parent) || !t.isFor(parent, { left: node });
|
||||
};
|
||||
}
|
||||
|
||||
var isVar = function (node, parent) {
|
||||
function isVar(node, parent) {
|
||||
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent);
|
||||
};
|
||||
}
|
||||
|
||||
var standardizeLets = function (declars) {
|
||||
function standardizeLets(declars) {
|
||||
for (var i = 0; i < declars.length; i++) {
|
||||
delete declars[i]._let;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
export function check(node) {
|
||||
return t.isVariableDeclaration(node) && (node.kind === "let" || node.kind === "const");
|
||||
}
|
||||
|
||||
export function VariableDeclaration(node, parent, scope, file) {
|
||||
if (!isLet(node, parent)) return;
|
||||
|
||||
if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun()) {
|
||||
@@ -63,9 +61,9 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
|
||||
return nodes;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.Loop = function (node, parent, scope, file) {
|
||||
export function Loop(node, parent, scope, file) {
|
||||
var init = node.left || node.init;
|
||||
if (isLet(init, node)) {
|
||||
t.ensureBlock(node);
|
||||
@@ -73,62 +71,16 @@ exports.Loop = function (node, parent, scope, file) {
|
||||
}
|
||||
var blockScoping = new BlockScoping(node, node.body, parent, scope, file);
|
||||
blockScoping.run();
|
||||
};
|
||||
}
|
||||
|
||||
exports.Program =
|
||||
exports.BlockStatement = function (block, parent, scope, file) {
|
||||
export function BlockStatement(block, parent, scope, file) {
|
||||
if (!t.isLoop(parent)) {
|
||||
var blockScoping = new BlockScoping(false, block, parent, scope, file);
|
||||
blockScoping.run();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Boolean|Node} loopParent
|
||||
* @param {Node} block
|
||||
* @param {Node} parent
|
||||
* @param {Scope} scope
|
||||
* @param {File} file
|
||||
*/
|
||||
|
||||
function BlockScoping(loopParent, block, parent, scope, file) {
|
||||
this.loopParent = loopParent;
|
||||
this.parent = parent;
|
||||
this.scope = scope;
|
||||
this.block = block;
|
||||
this.file = file;
|
||||
|
||||
this.outsideLetReferences = object();
|
||||
this.hasLetReferences = false;
|
||||
this.letReferences = block._letReferences = object();
|
||||
this.body = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the ball rolling.
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.run = function () {
|
||||
var block = this.block;
|
||||
if (block._letDone) return;
|
||||
block._letDone = true;
|
||||
|
||||
var needsClosure = this.getLetReferences();
|
||||
|
||||
// this is a block within a `Function/Program` so we can safely leave it be
|
||||
if (t.isFunction(this.parent) || t.isProgram(this.block)) return;
|
||||
|
||||
// we can skip everything
|
||||
if (!this.hasLetReferences) return;
|
||||
|
||||
if (needsClosure) {
|
||||
this.wrapClosure();
|
||||
} else {
|
||||
this.remap();
|
||||
}
|
||||
};
|
||||
export { BlockStatement as Program };
|
||||
|
||||
function replace(node, parent, scope, remaps) {
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
@@ -155,118 +107,17 @@ function traverseReplace(node, parent, scope, remaps) {
|
||||
scope.traverse(node, replaceVisitor, remaps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.remap = function () {
|
||||
var hasRemaps = false;
|
||||
var letRefs = this.letReferences;
|
||||
var scope = this.scope;
|
||||
|
||||
// alright, so since we aren't wrapping this block in a closure
|
||||
// we have to check if any of our let variables collide with
|
||||
// those in upper scopes and then if they do, generate a uid
|
||||
// for them and replace all references with it
|
||||
var remaps = object();
|
||||
|
||||
for (var key in letRefs) {
|
||||
// just an Identifier node we collected in `getLetReferences`
|
||||
// this is the defining identifier of a declaration
|
||||
var ref = letRefs[key];
|
||||
|
||||
if (scope.parentHasBinding(key) || scope.hasGlobal(key)) {
|
||||
var uid = scope.generateUidIdentifier(ref.name).name;
|
||||
ref.name = uid;
|
||||
|
||||
hasRemaps = true;
|
||||
remaps[key] = remaps[uid] = {
|
||||
binding: ref,
|
||||
uid: uid
|
||||
};
|
||||
var letReferenceBlockVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isFunction(node)) {
|
||||
scope.traverse(node, letReferenceFunctionVisitor, state);
|
||||
return this.skip();
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRemaps) return;
|
||||
|
||||
//
|
||||
|
||||
var loopParent = this.loopParent;
|
||||
if (loopParent) {
|
||||
traverseReplace(loopParent.right, loopParent, scope, remaps);
|
||||
traverseReplace(loopParent.test, loopParent, scope, remaps);
|
||||
traverseReplace(loopParent.update, loopParent, scope, remaps);
|
||||
}
|
||||
|
||||
scope.traverse(this.block, replaceVisitor, remaps);
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.wrapClosure = function () {
|
||||
var block = this.block;
|
||||
|
||||
var outsideRefs = this.outsideLetReferences;
|
||||
|
||||
// remap loop heads with colliding variables
|
||||
if (this.loopParent) {
|
||||
for (var name in outsideRefs) {
|
||||
var id = outsideRefs[name];
|
||||
|
||||
if (this.scope.hasGlobal(id.name)) {
|
||||
delete outsideRefs[id.name];
|
||||
delete this.letReferences[id.name];
|
||||
|
||||
this.scope.rename(id.name);
|
||||
|
||||
this.letReferences[id.name] = id;
|
||||
outsideRefs[id.name] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we're inside of a for loop then we search to see if there are any
|
||||
// `break`s, `continue`s, `return`s etc
|
||||
this.has = this.checkLoop();
|
||||
|
||||
// hoist var references to retain scope
|
||||
this.hoistVarDeclarations();
|
||||
|
||||
// turn outsideLetReferences into an array
|
||||
var params = values(outsideRefs);
|
||||
|
||||
// build the closure that we're going to wrap the block with
|
||||
var fn = t.functionExpression(null, params, t.blockStatement(block.body));
|
||||
fn._aliasFunction = true;
|
||||
|
||||
// replace the current block body with the one we're going to build
|
||||
block.body = this.body;
|
||||
|
||||
// build a call and a unique id that we can assign the return value to
|
||||
var call = t.callExpression(fn, params);
|
||||
var ret = this.scope.generateUidIdentifier("ret");
|
||||
|
||||
// handle generators
|
||||
var hasYield = traverse.hasType(fn.body, this.scope, "YieldExpression", t.FUNCTION_TYPES);
|
||||
if (hasYield) {
|
||||
fn.generator = true;
|
||||
call = t.yieldExpression(call, true);
|
||||
}
|
||||
|
||||
// handlers async functions
|
||||
var hasAsync = traverse.hasType(fn.body, this.scope, "AwaitExpression", t.FUNCTION_TYPES);
|
||||
if (hasAsync) {
|
||||
fn.async = true;
|
||||
call = t.awaitExpression(call, true);
|
||||
}
|
||||
|
||||
this.build(ret, call);
|
||||
};
|
||||
|
||||
var letReferenceFunctionVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
// not a direct reference
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
|
||||
@@ -281,65 +132,30 @@ var letReferenceFunctionVisitor = {
|
||||
}
|
||||
};
|
||||
|
||||
var letReferenceBlockVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isFunction(node)) {
|
||||
scope.traverse(node, letReferenceFunctionVisitor, state);
|
||||
var hoistVarDeclarationsVisitor = {
|
||||
enter(node, parent, scope, self) {
|
||||
if (t.isForStatement(node)) {
|
||||
if (isVar(node.init, node)) {
|
||||
node.init = t.sequenceExpression(self.pushDeclar(node.init));
|
||||
}
|
||||
} else if (t.isFor(node)) {
|
||||
if (isVar(node.left, node)) {
|
||||
node.left = node.left.declarations[0].id;
|
||||
}
|
||||
} else if (isVar(node, parent)) {
|
||||
return self.pushDeclar(node).map(t.expressionStatement);
|
||||
} else if (t.isFunction(node)) {
|
||||
return this.skip();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.getLetReferences = function () {
|
||||
var block = this.block;
|
||||
|
||||
var declarators = block._letDeclarators || [];
|
||||
var declar;
|
||||
|
||||
//
|
||||
for (var i = 0; i < declarators.length; i++) {
|
||||
declar = declarators[i];
|
||||
extend(this.outsideLetReferences, t.getBindingIdentifiers(declar));
|
||||
}
|
||||
|
||||
//
|
||||
if (block.body) {
|
||||
for (i = 0; i < block.body.length; i++) {
|
||||
declar = block.body[i];
|
||||
if (isLet(declar, block)) {
|
||||
declarators = declarators.concat(declar.declarations);
|
||||
}
|
||||
var loopLabelVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isLabeledStatement(node)) {
|
||||
state.innerLabels.push(node.label.name);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
for (i = 0; i < declarators.length; i++) {
|
||||
declar = declarators[i];
|
||||
var keys = t.getBindingIdentifiers(declar);
|
||||
extend(this.letReferences, keys);
|
||||
this.hasLetReferences = true;
|
||||
}
|
||||
|
||||
// no let references so we can just quit
|
||||
if (!this.hasLetReferences) return;
|
||||
|
||||
// set let references to plain var references
|
||||
standardizeLets(declarators);
|
||||
|
||||
var state = {
|
||||
letReferences: this.letReferences,
|
||||
closurify: false
|
||||
};
|
||||
|
||||
// traverse through this block, stopping on functions and checking if they
|
||||
// contain any local let references
|
||||
this.scope.traverse(this.block, letReferenceBlockVisitor, state);
|
||||
|
||||
return state.closurify;
|
||||
};
|
||||
|
||||
var loopNodeTo = function (node) {
|
||||
@@ -351,7 +167,7 @@ var loopNodeTo = function (node) {
|
||||
};
|
||||
|
||||
var loopVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
var replace;
|
||||
|
||||
if (t.isLoop(node)) {
|
||||
@@ -402,160 +218,346 @@ var loopVisitor = {
|
||||
}
|
||||
};
|
||||
|
||||
var loopLabelVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isLabeledStatement(node)) {
|
||||
state.innerLabels.push(node.label.name);
|
||||
}
|
||||
}
|
||||
};
|
||||
class BlockScoping {
|
||||
|
||||
/**
|
||||
* If we're inside of a loop then traverse it and check if it has one of
|
||||
* the following node types `ReturnStatement`, `BreakStatement`,
|
||||
* `ContinueStatement` and replace it with a return value that we can track
|
||||
* later on.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Boolean|Node} loopParent
|
||||
* @param {Node} block
|
||||
* @param {Node} parent
|
||||
* @param {Scope} scope
|
||||
* @param {File} file
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.checkLoop = function () {
|
||||
var state = {
|
||||
hasBreakContinue: false,
|
||||
ignoreLabeless: false,
|
||||
innerLabels: [],
|
||||
hasReturn: false,
|
||||
isLoop: !!this.loopParent,
|
||||
map: {}
|
||||
};
|
||||
constructor(loopParent, block, parent, scope, file) {
|
||||
this.loopParent = loopParent;
|
||||
this.parent = parent;
|
||||
this.scope = scope;
|
||||
this.block = block;
|
||||
this.file = file;
|
||||
|
||||
this.scope.traverse(this.block, loopLabelVisitor, state);
|
||||
this.scope.traverse(this.block, loopVisitor, state);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
var hoistVarDeclarationsVisitor = {
|
||||
enter: function (node, parent, scope, self) {
|
||||
if (t.isForStatement(node)) {
|
||||
if (isVar(node.init, node)) {
|
||||
node.init = t.sequenceExpression(self.pushDeclar(node.init));
|
||||
}
|
||||
} else if (t.isFor(node)) {
|
||||
if (isVar(node.left, node)) {
|
||||
node.left = node.left.declarations[0].id;
|
||||
}
|
||||
} else if (isVar(node, parent)) {
|
||||
return self.pushDeclar(node).map(t.expressionStatement);
|
||||
} else if (t.isFunction(node)) {
|
||||
return this.skip();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hoist all var declarations in this block to before it so they retain scope
|
||||
* once we wrap everything in a closure.
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.hoistVarDeclarations = function () {
|
||||
traverse(this.block, hoistVarDeclarationsVisitor, this.scope, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn a `VariableDeclaration` into an array of `AssignmentExpressions` with
|
||||
* their declarations hoisted to before the closure wrapper.
|
||||
*
|
||||
* @param {Node} node VariableDeclaration
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.pushDeclar = function (node) {
|
||||
this.body.push(t.variableDeclaration(node.kind, node.declarations.map(function (declar) {
|
||||
return t.variableDeclarator(declar.id);
|
||||
})));
|
||||
|
||||
var replace = [];
|
||||
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
var declar = node.declarations[i];
|
||||
if (!declar.init) continue;
|
||||
|
||||
var expr = t.assignmentExpression("=", declar.id, declar.init);
|
||||
replace.push(t.inherits(expr, declar));
|
||||
this.outsideLetReferences = object();
|
||||
this.hasLetReferences = false;
|
||||
this.letReferences = block._letReferences = object();
|
||||
this.body = [];
|
||||
}
|
||||
|
||||
return replace;
|
||||
};
|
||||
/**
|
||||
* Start the ball rolling.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Push the closure to the body.
|
||||
*
|
||||
* @param {Node} ret Identifier
|
||||
* @param {Node} call CallExpression
|
||||
*/
|
||||
run() {
|
||||
var block = this.block;
|
||||
if (block._letDone) return;
|
||||
block._letDone = true;
|
||||
|
||||
BlockScoping.prototype.build = function (ret, call) {
|
||||
var has = this.has;
|
||||
if (has.hasReturn || has.hasBreakContinue) {
|
||||
this.buildHas(ret, call);
|
||||
} else {
|
||||
this.body.push(t.expressionStatement(call));
|
||||
}
|
||||
};
|
||||
var needsClosure = this.getLetReferences();
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} ret Identifier
|
||||
* @param {Node} call CallExpression
|
||||
*/
|
||||
// this is a block within a `Function/Program` so we can safely leave it be
|
||||
if (t.isFunction(this.parent) || t.isProgram(this.block)) return;
|
||||
|
||||
BlockScoping.prototype.buildHas = function (ret, call) {
|
||||
var body = this.body;
|
||||
// we can skip everything
|
||||
if (!this.hasLetReferences) return;
|
||||
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(ret, call)
|
||||
]));
|
||||
|
||||
var loopParent = this.loopParent;
|
||||
var retCheck;
|
||||
var has = this.has;
|
||||
var cases = [];
|
||||
|
||||
if (has.hasReturn) {
|
||||
// typeof ret === "object"
|
||||
retCheck = util.template("let-scoping-return", {
|
||||
RETURN: ret
|
||||
});
|
||||
}
|
||||
|
||||
if (has.hasBreakContinue) {
|
||||
if (!loopParent) {
|
||||
throw new Error("Has no loop parent but we're trying to reassign breaks " +
|
||||
"and continues, something is going wrong here.");
|
||||
}
|
||||
|
||||
for (var key in has.map) {
|
||||
cases.push(t.switchCase(t.literal(key), [has.map[key]]));
|
||||
}
|
||||
|
||||
if (has.hasReturn) {
|
||||
cases.push(t.switchCase(null, [retCheck]));
|
||||
}
|
||||
|
||||
if (cases.length === 1) {
|
||||
var single = cases[0];
|
||||
body.push(this.file.attachAuxiliaryComment(t.ifStatement(
|
||||
t.binaryExpression("===", ret, single.test),
|
||||
single.consequent[0]
|
||||
)));
|
||||
if (needsClosure) {
|
||||
this.wrapClosure();
|
||||
} else {
|
||||
body.push(this.file.attachAuxiliaryComment(t.switchStatement(ret, cases)));
|
||||
}
|
||||
} else {
|
||||
if (has.hasReturn) {
|
||||
body.push(this.file.attachAuxiliaryComment(retCheck));
|
||||
this.remap();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
remap() {
|
||||
var hasRemaps = false;
|
||||
var letRefs = this.letReferences;
|
||||
var scope = this.scope;
|
||||
|
||||
// alright, so since we aren't wrapping this block in a closure
|
||||
// we have to check if any of our let variables collide with
|
||||
// those in upper scopes and then if they do, generate a uid
|
||||
// for them and replace all references with it
|
||||
var remaps = object();
|
||||
|
||||
for (var key in letRefs) {
|
||||
// just an Identifier node we collected in `getLetReferences`
|
||||
// this is the defining identifier of a declaration
|
||||
var ref = letRefs[key];
|
||||
|
||||
if (scope.parentHasBinding(key) || scope.hasGlobal(key)) {
|
||||
var uid = scope.generateUidIdentifier(ref.name).name;
|
||||
ref.name = uid;
|
||||
|
||||
hasRemaps = true;
|
||||
remaps[key] = remaps[uid] = {
|
||||
binding: ref,
|
||||
uid: uid
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRemaps) return;
|
||||
|
||||
//
|
||||
|
||||
var loopParent = this.loopParent;
|
||||
if (loopParent) {
|
||||
traverseReplace(loopParent.right, loopParent, scope, remaps);
|
||||
traverseReplace(loopParent.test, loopParent, scope, remaps);
|
||||
traverseReplace(loopParent.update, loopParent, scope, remaps);
|
||||
}
|
||||
|
||||
scope.traverse(this.block, replaceVisitor, remaps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
wrapClosure() {
|
||||
var block = this.block;
|
||||
|
||||
var outsideRefs = this.outsideLetReferences;
|
||||
|
||||
// remap loop heads with colliding variables
|
||||
if (this.loopParent) {
|
||||
for (var name in outsideRefs) {
|
||||
var id = outsideRefs[name];
|
||||
|
||||
if (this.scope.hasGlobal(id.name) || this.scope.parentHasBinding(id.name)) {
|
||||
delete outsideRefs[id.name];
|
||||
delete this.letReferences[id.name];
|
||||
|
||||
this.scope.rename(id.name);
|
||||
|
||||
this.letReferences[id.name] = id;
|
||||
outsideRefs[id.name] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we're inside of a for loop then we search to see if there are any
|
||||
// `break`s, `continue`s, `return`s etc
|
||||
this.has = this.checkLoop();
|
||||
|
||||
// hoist var references to retain scope
|
||||
this.hoistVarDeclarations();
|
||||
|
||||
// turn outsideLetReferences into an array
|
||||
var params = values(outsideRefs);
|
||||
|
||||
// build the closure that we're going to wrap the block with
|
||||
var fn = t.functionExpression(null, params, t.blockStatement(block.body));
|
||||
fn._aliasFunction = true;
|
||||
|
||||
// replace the current block body with the one we're going to build
|
||||
block.body = this.body;
|
||||
|
||||
// build a call and a unique id that we can assign the return value to
|
||||
var call = t.callExpression(fn, params);
|
||||
var ret = this.scope.generateUidIdentifier("ret");
|
||||
|
||||
// handle generators
|
||||
var hasYield = traverse.hasType(fn.body, this.scope, "YieldExpression", t.FUNCTION_TYPES);
|
||||
if (hasYield) {
|
||||
fn.generator = true;
|
||||
call = t.yieldExpression(call, true);
|
||||
}
|
||||
|
||||
// handlers async functions
|
||||
var hasAsync = traverse.hasType(fn.body, this.scope, "AwaitExpression", t.FUNCTION_TYPES);
|
||||
if (hasAsync) {
|
||||
fn.async = true;
|
||||
call = t.awaitExpression(call, true);
|
||||
}
|
||||
|
||||
this.build(ret, call);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
getLetReferences() {
|
||||
var block = this.block;
|
||||
|
||||
var declarators = block._letDeclarators || [];
|
||||
var declar;
|
||||
|
||||
//
|
||||
for (var i = 0; i < declarators.length; i++) {
|
||||
declar = declarators[i];
|
||||
extend(this.outsideLetReferences, t.getBindingIdentifiers(declar));
|
||||
}
|
||||
|
||||
//
|
||||
if (block.body) {
|
||||
for (i = 0; i < block.body.length; i++) {
|
||||
declar = block.body[i];
|
||||
if (isLet(declar, block)) {
|
||||
declarators = declarators.concat(declar.declarations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
for (i = 0; i < declarators.length; i++) {
|
||||
declar = declarators[i];
|
||||
var keys = t.getBindingIdentifiers(declar);
|
||||
extend(this.letReferences, keys);
|
||||
this.hasLetReferences = true;
|
||||
}
|
||||
|
||||
// no let references so we can just quit
|
||||
if (!this.hasLetReferences) return;
|
||||
|
||||
// set let references to plain var references
|
||||
standardizeLets(declarators);
|
||||
|
||||
var state = {
|
||||
letReferences: this.letReferences,
|
||||
closurify: false
|
||||
};
|
||||
|
||||
// traverse through this block, stopping on functions and checking if they
|
||||
// contain any local let references
|
||||
this.scope.traverse(this.block, letReferenceBlockVisitor, state);
|
||||
|
||||
return state.closurify;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're inside of a loop then traverse it and check if it has one of
|
||||
* the following node types `ReturnStatement`, `BreakStatement`,
|
||||
* `ContinueStatement` and replace it with a return value that we can track
|
||||
* later on.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
checkLoop() {
|
||||
var state = {
|
||||
hasBreakContinue: false,
|
||||
ignoreLabeless: false,
|
||||
innerLabels: [],
|
||||
hasReturn: false,
|
||||
isLoop: !!this.loopParent,
|
||||
map: {}
|
||||
};
|
||||
|
||||
this.scope.traverse(this.block, loopLabelVisitor, state);
|
||||
this.scope.traverse(this.block, loopVisitor, state);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hoist all var declarations in this block to before it so they retain scope
|
||||
* once we wrap everything in a closure.
|
||||
*/
|
||||
|
||||
hoistVarDeclarations() {
|
||||
traverse(this.block, hoistVarDeclarationsVisitor, this.scope, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a `VariableDeclaration` into an array of `AssignmentExpressions` with
|
||||
* their declarations hoisted to before the closure wrapper.
|
||||
*
|
||||
* @param {Node} node VariableDeclaration
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
pushDeclar(node) {
|
||||
this.body.push(t.variableDeclaration(node.kind, node.declarations.map(function (declar) {
|
||||
return t.variableDeclarator(declar.id);
|
||||
})));
|
||||
|
||||
var replace = [];
|
||||
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
var declar = node.declarations[i];
|
||||
if (!declar.init) continue;
|
||||
|
||||
var expr = t.assignmentExpression("=", declar.id, declar.init);
|
||||
replace.push(t.inherits(expr, declar));
|
||||
}
|
||||
|
||||
return replace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the closure to the body.
|
||||
*
|
||||
* @param {Node} ret Identifier
|
||||
* @param {Node} call CallExpression
|
||||
*/
|
||||
|
||||
build(ret, call) {
|
||||
var has = this.has;
|
||||
if (has.hasReturn || has.hasBreakContinue) {
|
||||
this.buildHas(ret, call);
|
||||
} else {
|
||||
this.body.push(t.expressionStatement(call));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} ret Identifier
|
||||
* @param {Node} call CallExpression
|
||||
*/
|
||||
|
||||
buildHas(ret, call) {
|
||||
var body = this.body;
|
||||
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(ret, call)
|
||||
]));
|
||||
|
||||
var loopParent = this.loopParent;
|
||||
var retCheck;
|
||||
var has = this.has;
|
||||
var cases = [];
|
||||
|
||||
if (has.hasReturn) {
|
||||
// typeof ret === "object"
|
||||
retCheck = util.template("let-scoping-return", {
|
||||
RETURN: ret
|
||||
});
|
||||
}
|
||||
|
||||
if (has.hasBreakContinue) {
|
||||
if (!loopParent) {
|
||||
throw new Error("Has no loop parent but we're trying to reassign breaks " +
|
||||
"and continues, something is going wrong here.");
|
||||
}
|
||||
|
||||
for (var key in has.map) {
|
||||
cases.push(t.switchCase(t.literal(key), [has.map[key]]));
|
||||
}
|
||||
|
||||
if (has.hasReturn) {
|
||||
cases.push(t.switchCase(null, [retCheck]));
|
||||
}
|
||||
|
||||
if (cases.length === 1) {
|
||||
var single = cases[0];
|
||||
body.push(this.file.attachAuxiliaryComment(t.ifStatement(
|
||||
t.binaryExpression("===", ret, single.test),
|
||||
single.consequent[0]
|
||||
)));
|
||||
} else {
|
||||
body.push(this.file.attachAuxiliaryComment(t.switchStatement(ret, cases)));
|
||||
}
|
||||
} else {
|
||||
if (has.hasReturn) {
|
||||
body.push(this.file.attachAuxiliaryComment(retCheck));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
"use strict";
|
||||
import ReplaceSupers from "../../helpers/replace-supers";
|
||||
import * as nameMethod from "../../helpers/name-method";
|
||||
import * as defineMap from "../../helpers/define-map";
|
||||
import * as messages from "../../../messages";
|
||||
import * as util from "../../../util";
|
||||
import t from "../../../types";
|
||||
|
||||
var ReplaceSupers = require("../../helpers/replace-supers");
|
||||
var nameMethod = require("../../helpers/name-method");
|
||||
var defineMap = require("../../helpers/define-map");
|
||||
var messages = require("../../../messages");
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
export var check = t.isClass;
|
||||
|
||||
exports.check = t.isClass;
|
||||
|
||||
exports.ClassDeclaration = function (node, parent, scope, file) {
|
||||
export function ClassDeclaration(node, parent, scope, file) {
|
||||
return new ClassTransformer(node, file, scope, true).run();
|
||||
};
|
||||
}
|
||||
|
||||
exports.ClassExpression = function (node, parent, scope, file) {
|
||||
export function ClassExpression(node, parent, scope, file) {
|
||||
if (!node.id) {
|
||||
if (t.isProperty(parent) && parent.value === node && !parent.computed && t.isIdentifier(parent.key)) {
|
||||
// var o = { foo: class {} };
|
||||
@@ -27,279 +25,282 @@ exports.ClassExpression = function (node, parent, scope, file) {
|
||||
}
|
||||
|
||||
return new ClassTransformer(node, file, scope, false).run();
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {File} file
|
||||
* @param {Scope} scope
|
||||
* @param {Boolean} isStatement
|
||||
*/
|
||||
|
||||
function ClassTransformer(node, file, scope, isStatement) {
|
||||
this.isStatement = isStatement;
|
||||
this.scope = scope;
|
||||
this.node = node;
|
||||
this.file = file;
|
||||
|
||||
this.hasInstanceMutators = false;
|
||||
this.hasStaticMutators = false;
|
||||
|
||||
this.instanceMutatorMap = {};
|
||||
this.staticMutatorMap = {};
|
||||
this.hasConstructor = false;
|
||||
this.className = node.id || scope.generateUidIdentifier("class");
|
||||
this.superName = node.superClass || t.identifier("Function");
|
||||
this.hasSuper = !!node.superClass;
|
||||
this.isLoose = file.isLoose("es6.classes");
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
class ClassTransformer {
|
||||
|
||||
ClassTransformer.prototype.run = function () {
|
||||
var superName = this.superName;
|
||||
var className = this.className;
|
||||
var classBody = this.node.body.body;
|
||||
var file = this.file;
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {File} file
|
||||
* @param {Scope} scope
|
||||
* @param {Boolean} isStatement
|
||||
*/
|
||||
|
||||
//
|
||||
constructor(node, file, scope, isStatement) {
|
||||
this.isStatement = isStatement;
|
||||
this.scope = scope;
|
||||
this.node = node;
|
||||
this.file = file;
|
||||
|
||||
var body = this.body = [];
|
||||
this.hasInstanceMutators = false;
|
||||
this.hasStaticMutators = false;
|
||||
|
||||
var constructorBody = t.blockStatement([
|
||||
t.expressionStatement(t.callExpression(file.addHelper("class-call-check"), [
|
||||
t.thisExpression(),
|
||||
className
|
||||
]))
|
||||
]);
|
||||
|
||||
var constructor;
|
||||
if (this.node.id) {
|
||||
constructor = t.functionDeclaration(className, [], constructorBody);
|
||||
body.push(constructor);
|
||||
} else {
|
||||
var constructorName = null;
|
||||
// when a class has no parent and there is only a constructor or no body
|
||||
// then the constructor is not wrapped in a closure and needs to be named
|
||||
var containsOnlyConstructor = classBody.length === 1 && classBody[0].key.name === "constructor";
|
||||
if (!this.hasSuper && (classBody.length === 0 || containsOnlyConstructor)) {
|
||||
constructorName = className;
|
||||
}
|
||||
|
||||
constructor = t.functionExpression(constructorName, [], constructorBody);
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(className, constructor)
|
||||
]));
|
||||
}
|
||||
this.constructor = constructor;
|
||||
|
||||
var closureParams = [];
|
||||
var closureArgs = [];
|
||||
|
||||
//
|
||||
|
||||
if (this.hasSuper) {
|
||||
closureArgs.push(superName);
|
||||
|
||||
if (!t.isIdentifier(superName)) {
|
||||
superName = this.scope.generateUidBasedOnNode(superName, this.file);
|
||||
}
|
||||
|
||||
closureParams.push(superName);
|
||||
|
||||
this.superName = superName;
|
||||
body.push(t.expressionStatement(t.callExpression(file.addHelper("inherits"), [className, superName])));
|
||||
this.instanceMutatorMap = {};
|
||||
this.staticMutatorMap = {};
|
||||
this.hasConstructor = false;
|
||||
this.className = node.id || scope.generateUidIdentifier("class");
|
||||
this.superName = node.superClass || t.identifier("Function");
|
||||
this.hasSuper = !!node.superClass;
|
||||
this.isLoose = file.isLoose("es6.classes");
|
||||
}
|
||||
|
||||
this.buildBody();
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
t.inheritsComments(body[0], this.node);
|
||||
run() {
|
||||
var superName = this.superName;
|
||||
var className = this.className;
|
||||
var classBody = this.node.body.body;
|
||||
var file = this.file;
|
||||
|
||||
var init;
|
||||
//
|
||||
|
||||
if (body.length === 1) {
|
||||
// only a constructor so no need for a closure container
|
||||
init = t.toExpression(constructor);
|
||||
} else {
|
||||
body.push(t.returnStatement(className));
|
||||
init = t.callExpression(
|
||||
t.functionExpression(null, closureParams, t.blockStatement(body)),
|
||||
closureArgs
|
||||
);
|
||||
}
|
||||
var body = this.body = [];
|
||||
|
||||
if (this.isStatement) {
|
||||
return t.variableDeclaration("let", [
|
||||
t.variableDeclarator(className, init)
|
||||
var constructorBody = t.blockStatement([
|
||||
t.expressionStatement(t.callExpression(file.addHelper("class-call-check"), [
|
||||
t.thisExpression(),
|
||||
className
|
||||
]))
|
||||
]);
|
||||
} else {
|
||||
return init;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
ClassTransformer.prototype.buildBody = function () {
|
||||
var constructor = this.constructor;
|
||||
var className = this.className;
|
||||
var superName = this.superName;
|
||||
var classBody = this.node.body.body;
|
||||
var body = this.body;
|
||||
|
||||
for (var i = 0; i < classBody.length; i++) {
|
||||
var node = classBody[i];
|
||||
if (t.isMethodDefinition(node)) {
|
||||
var replaceSupers = new ReplaceSupers({
|
||||
methodNode: node,
|
||||
className: this.className,
|
||||
superName: this.superName,
|
||||
isStatic: node.static,
|
||||
isLoose: this.isLoose,
|
||||
scope: this.scope,
|
||||
file: this.file
|
||||
}, true);
|
||||
replaceSupers.replace();
|
||||
|
||||
if ((!node.computed && t.isIdentifier(node.key, { name: "constructor" })) || t.isLiteral(node.key, { value: "constructor" })) {
|
||||
this.pushConstructor(node);
|
||||
} else {
|
||||
this.pushMethod(node);
|
||||
var constructor;
|
||||
if (this.node.id) {
|
||||
constructor = t.functionDeclaration(className, [], constructorBody);
|
||||
body.push(constructor);
|
||||
} else {
|
||||
var constructorName = null;
|
||||
// when a class has no parent and there is only a constructor or no body
|
||||
// then the constructor is not wrapped in a closure and needs to be named
|
||||
var containsOnlyConstructor = classBody.length === 1 && classBody[0].key.name === "constructor";
|
||||
if (!this.hasSuper && (classBody.length === 0 || containsOnlyConstructor)) {
|
||||
constructorName = className;
|
||||
}
|
||||
} else if (t.isPrivateDeclaration(node)) {
|
||||
this.closure = true;
|
||||
body.unshift(node);
|
||||
} else if (t.isClassProperty(node)) {
|
||||
this.pushProperty(node);
|
||||
|
||||
constructor = t.functionExpression(constructorName, [], constructorBody);
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(className, constructor)
|
||||
]));
|
||||
}
|
||||
this.constructor = constructor;
|
||||
|
||||
var closureParams = [];
|
||||
var closureArgs = [];
|
||||
|
||||
//
|
||||
|
||||
if (this.hasSuper) {
|
||||
closureArgs.push(superName);
|
||||
|
||||
if (!t.isIdentifier(superName)) {
|
||||
superName = this.scope.generateUidBasedOnNode(superName, this.file);
|
||||
}
|
||||
|
||||
closureParams.push(superName);
|
||||
|
||||
this.superName = superName;
|
||||
body.push(t.expressionStatement(t.callExpression(file.addHelper("inherits"), [className, superName])));
|
||||
}
|
||||
|
||||
this.buildBody();
|
||||
|
||||
t.inheritsComments(body[0], this.node);
|
||||
|
||||
var init;
|
||||
|
||||
if (body.length === 1) {
|
||||
// only a constructor so no need for a closure container
|
||||
init = t.toExpression(constructor);
|
||||
} else {
|
||||
body.push(t.returnStatement(className));
|
||||
init = t.callExpression(
|
||||
t.functionExpression(null, closureParams, t.blockStatement(body)),
|
||||
closureArgs
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isStatement) {
|
||||
return t.variableDeclaration("let", [
|
||||
t.variableDeclarator(className, init)
|
||||
]);
|
||||
} else {
|
||||
return init;
|
||||
}
|
||||
}
|
||||
|
||||
// we have no constructor, we have a super, and the super doesn't appear to be falsy
|
||||
if (!this.hasConstructor && this.hasSuper && !t.isFalsyExpression(superName)) {
|
||||
var helperName = "class-super-constructor-call";
|
||||
if (this.isLoose) helperName += "-loose";
|
||||
constructor.body.body.push(util.template(helperName, {
|
||||
CLASS_NAME: className,
|
||||
SUPER_NAME: this.superName
|
||||
}, true));
|
||||
}
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
|
||||
var instanceProps;
|
||||
var staticProps;
|
||||
buildBody() {
|
||||
var constructor = this.constructor;
|
||||
var className = this.className;
|
||||
var superName = this.superName;
|
||||
var classBody = this.node.body.body;
|
||||
var body = this.body;
|
||||
|
||||
if (this.hasInstanceMutators) {
|
||||
instanceProps = defineMap.build(this.instanceMutatorMap);
|
||||
}
|
||||
for (var i = 0; i < classBody.length; i++) {
|
||||
var node = classBody[i];
|
||||
if (t.isMethodDefinition(node)) {
|
||||
var replaceSupers = new ReplaceSupers({
|
||||
methodNode: node,
|
||||
className: this.className,
|
||||
superName: this.superName,
|
||||
isStatic: node.static,
|
||||
isLoose: this.isLoose,
|
||||
scope: this.scope,
|
||||
file: this.file
|
||||
}, true);
|
||||
replaceSupers.replace();
|
||||
|
||||
if (this.hasStaticMutators) {
|
||||
staticProps = defineMap.build(this.staticMutatorMap);
|
||||
}
|
||||
|
||||
if (instanceProps || staticProps) {
|
||||
staticProps = staticProps || t.literal(null);
|
||||
|
||||
var args = [className, staticProps];
|
||||
if (instanceProps) args.push(instanceProps);
|
||||
|
||||
body.push(t.expressionStatement(
|
||||
t.callExpression(this.file.addHelper("prototype-properties"), args)
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Push a method to its respective mutatorMap.
|
||||
*
|
||||
* @param {Node} node MethodDefinition
|
||||
*/
|
||||
|
||||
ClassTransformer.prototype.pushMethod = function (node) {
|
||||
var methodName = node.key;
|
||||
|
||||
var kind = node.kind;
|
||||
|
||||
if (kind === "") {
|
||||
nameMethod.property(node, this.file, this.scope);
|
||||
|
||||
if (this.isLoose) {
|
||||
// use assignments instead of define properties for loose classes
|
||||
|
||||
var className = this.className;
|
||||
if (!node.static) className = t.memberExpression(className, t.identifier("prototype"));
|
||||
methodName = t.memberExpression(className, methodName, node.computed);
|
||||
|
||||
var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
|
||||
t.inheritsComments(expr, node);
|
||||
this.body.push(expr);
|
||||
return;
|
||||
if ((!node.computed && t.isIdentifier(node.key, { name: "constructor" })) || t.isLiteral(node.key, { value: "constructor" })) {
|
||||
this.pushConstructor(node);
|
||||
} else {
|
||||
this.pushMethod(node);
|
||||
}
|
||||
} else if (t.isPrivateDeclaration(node)) {
|
||||
this.closure = true;
|
||||
body.unshift(node);
|
||||
} else if (t.isClassProperty(node)) {
|
||||
this.pushProperty(node);
|
||||
}
|
||||
}
|
||||
|
||||
kind = "value";
|
||||
// we have no constructor, we have a super, and the super doesn't appear to be falsy
|
||||
if (!this.hasConstructor && this.hasSuper && t.evaluateTruthy(superName) !== false) {
|
||||
var helperName = "class-super-constructor-call";
|
||||
if (this.isLoose) helperName += "-loose";
|
||||
constructor.body.body.push(util.template(helperName, {
|
||||
CLASS_NAME: className,
|
||||
SUPER_NAME: this.superName
|
||||
}, true));
|
||||
}
|
||||
|
||||
var instanceProps;
|
||||
var staticProps;
|
||||
|
||||
if (this.hasInstanceMutators) {
|
||||
instanceProps = defineMap.build(this.instanceMutatorMap);
|
||||
}
|
||||
|
||||
if (this.hasStaticMutators) {
|
||||
staticProps = defineMap.build(this.staticMutatorMap);
|
||||
}
|
||||
|
||||
if (instanceProps || staticProps) {
|
||||
staticProps ||= t.literal(null);
|
||||
|
||||
var args = [className, staticProps];
|
||||
if (instanceProps) args.push(instanceProps);
|
||||
|
||||
body.push(t.expressionStatement(
|
||||
t.callExpression(this.file.addHelper("prototype-properties"), args)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
var mutatorMap = this.instanceMutatorMap;
|
||||
if (node.static) {
|
||||
this.hasStaticMutators = true;
|
||||
mutatorMap = this.staticMutatorMap;
|
||||
} else {
|
||||
this.hasInstanceMutators = true;
|
||||
/**
|
||||
* Push a method to its respective mutatorMap.
|
||||
*
|
||||
* @param {Node} node MethodDefinition
|
||||
*/
|
||||
|
||||
pushMethod(node) {
|
||||
var methodName = node.key;
|
||||
|
||||
var kind = node.kind;
|
||||
|
||||
if (kind === "") {
|
||||
nameMethod.property(node, this.file, this.scope);
|
||||
|
||||
if (this.isLoose) {
|
||||
// use assignments instead of define properties for loose classes
|
||||
|
||||
var className = this.className;
|
||||
if (!node.static) className = t.memberExpression(className, t.identifier("prototype"));
|
||||
methodName = t.memberExpression(className, methodName, node.computed);
|
||||
|
||||
var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
|
||||
t.inheritsComments(expr, node);
|
||||
this.body.push(expr);
|
||||
return;
|
||||
}
|
||||
|
||||
kind = "value";
|
||||
}
|
||||
|
||||
var mutatorMap = this.instanceMutatorMap;
|
||||
if (node.static) {
|
||||
this.hasStaticMutators = true;
|
||||
mutatorMap = this.staticMutatorMap;
|
||||
} else {
|
||||
this.hasInstanceMutators = true;
|
||||
}
|
||||
|
||||
defineMap.push(mutatorMap, methodName, kind, node.computed, node);
|
||||
defineMap.push(mutatorMap, methodName, "enumerable", node.computed, false);
|
||||
}
|
||||
|
||||
defineMap.push(mutatorMap, methodName, kind, node.computed, node);
|
||||
defineMap.push(mutatorMap, methodName, "enumerable", node.computed, false);
|
||||
};
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} node
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} node
|
||||
*/
|
||||
pushProperty(node) {
|
||||
if (!node.value) return;
|
||||
|
||||
ClassTransformer.prototype.pushProperty = function (node) {
|
||||
if (!node.value) return;
|
||||
var key;
|
||||
|
||||
var key;
|
||||
|
||||
if (node.static) {
|
||||
key = t.memberExpression(this.className, node.key);
|
||||
this.body.push(
|
||||
t.expressionStatement(t.assignmentExpression("=", key, node.value))
|
||||
);
|
||||
} else {
|
||||
key = t.memberExpression(t.thisExpression(), node.key);
|
||||
this.constructor.body.body.unshift(
|
||||
t.expressionStatement(t.assignmentExpression("=", key, node.value))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace the constructor body of our class.
|
||||
*
|
||||
* @param {Node} method MethodDefinition
|
||||
*/
|
||||
|
||||
ClassTransformer.prototype.pushConstructor = function (method) {
|
||||
if (method.kind) {
|
||||
throw this.file.errorWithNode(method, messages.get("classesIllegalConstructorKind"));
|
||||
if (node.static) {
|
||||
key = t.memberExpression(this.className, node.key);
|
||||
this.body.push(
|
||||
t.expressionStatement(t.assignmentExpression("=", key, node.value))
|
||||
);
|
||||
} else {
|
||||
key = t.memberExpression(t.thisExpression(), node.key);
|
||||
this.constructor.body.body.unshift(
|
||||
t.expressionStatement(t.assignmentExpression("=", key, node.value))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var construct = this.constructor;
|
||||
var fn = method.value;
|
||||
/**
|
||||
* Replace the constructor body of our class.
|
||||
*
|
||||
* @param {Node} method MethodDefinition
|
||||
*/
|
||||
|
||||
this.hasConstructor = true;
|
||||
pushConstructor(method) {
|
||||
if (method.kind) {
|
||||
throw this.file.errorWithNode(method, messages.get("classesIllegalConstructorKind"));
|
||||
}
|
||||
|
||||
t.inherits(construct, fn);
|
||||
t.inheritsComments(construct, method);
|
||||
var construct = this.constructor;
|
||||
var fn = method.value;
|
||||
|
||||
construct._ignoreUserWhitespace = true;
|
||||
construct.params = fn.params;
|
||||
construct.body.body = construct.body.body.concat(fn.body.body);
|
||||
};
|
||||
this.hasConstructor = true;
|
||||
|
||||
t.inherits(construct, fn);
|
||||
t.inheritsComments(construct, method);
|
||||
|
||||
construct._ignoreUserWhitespace = true;
|
||||
construct.params = fn.params;
|
||||
construct.body.body = construct.body.body.concat(fn.body.body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
"use strict";
|
||||
import * as messages from "../../../messages";
|
||||
import t from "../../../types";
|
||||
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
export function check(node) {
|
||||
return t.isVariableDeclaration(node, { kind: "const" });
|
||||
};
|
||||
}
|
||||
|
||||
var visitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
|
||||
@@ -38,13 +36,13 @@ var visitor = {
|
||||
}
|
||||
};
|
||||
|
||||
exports.Scopable = function (node, parent, scope, file) {
|
||||
export function Scopable(node, parent, scope, file) {
|
||||
scope.traverse(node, visitor, {
|
||||
constants: scope.getAllBindingsOfKind("const"),
|
||||
file: file
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
exports.VariableDeclaration = function (node) {
|
||||
export function VariableDeclaration(node) {
|
||||
if (node.kind === "const") node.kind = "let";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,275 +1,9 @@
|
||||
"use strict";
|
||||
import * as messages from "../../../messages";
|
||||
import t from "../../../types";
|
||||
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
export var check = t.isPattern;
|
||||
|
||||
exports.check = t.isPattern;
|
||||
|
||||
function DestructuringTransformer(opts) {
|
||||
this.blockHoist = opts.blockHoist;
|
||||
this.operator = opts.operator;
|
||||
this.nodes = opts.nodes;
|
||||
this.scope = opts.scope;
|
||||
this.file = opts.file;
|
||||
this.kind = opts.kind;
|
||||
}
|
||||
|
||||
DestructuringTransformer.prototype.buildVariableAssignment = function (id, init) {
|
||||
var op = this.operator;
|
||||
if (t.isMemberExpression(id)) op = "=";
|
||||
|
||||
var node;
|
||||
|
||||
if (op) {
|
||||
node = t.expressionStatement(t.assignmentExpression(op, id, init));
|
||||
} else {
|
||||
node = t.variableDeclaration(this.kind, [
|
||||
t.variableDeclarator(id, init)
|
||||
]);
|
||||
}
|
||||
|
||||
node._blockHoist = this.blockHoist;
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.buildVariableDeclaration = function (id, init) {
|
||||
var declar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(id, init)
|
||||
]);
|
||||
declar._blockHoist = this.blockHoist;
|
||||
return declar;
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.push = function (id, init) {
|
||||
if (t.isObjectPattern(id)) {
|
||||
this.pushObjectPattern(id, init);
|
||||
} else if (t.isArrayPattern(id)) {
|
||||
this.pushArrayPattern(id, init);
|
||||
} else if (t.isAssignmentPattern(id)) {
|
||||
this.pushAssignmentPattern(id, init);
|
||||
} else {
|
||||
this.nodes.push(this.buildVariableAssignment(id, init));
|
||||
}
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.get = function () {
|
||||
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.pushAssignmentPattern = function (pattern, valueRef) {
|
||||
// we need to assign the current value of the assignment to avoid evaluating
|
||||
// it more than once
|
||||
|
||||
var tempValueRef = this.scope.generateUidBasedOnNode(valueRef);
|
||||
|
||||
var declar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(tempValueRef, valueRef)
|
||||
]);
|
||||
declar._blockHoist = this.blockHoist;
|
||||
this.nodes.push(declar);
|
||||
|
||||
//
|
||||
|
||||
this.nodes.push(this.buildVariableAssignment(
|
||||
pattern.left,
|
||||
t.conditionalExpression(
|
||||
t.binaryExpression("===", tempValueRef, t.identifier("undefined")),
|
||||
pattern.right,
|
||||
tempValueRef
|
||||
)
|
||||
));
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.pushObjectSpread = function (pattern, objRef, spreadProp, spreadPropIndex) {
|
||||
// get all the keys that appear in this object before the current spread
|
||||
|
||||
var keys = [];
|
||||
|
||||
for (var i = 0; i < pattern.properties.length; i++) {
|
||||
var prop = pattern.properties[i];
|
||||
|
||||
// we've exceeded the index of the spread property to all properties to the
|
||||
// right need to be ignored
|
||||
if (i >= spreadPropIndex) break;
|
||||
|
||||
// ignore other spread properties
|
||||
if (t.isSpreadProperty(prop)) continue;
|
||||
|
||||
var key = prop.key;
|
||||
if (t.isIdentifier(key)) key = t.literal(prop.key.name);
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
keys = t.arrayExpression(keys);
|
||||
|
||||
//
|
||||
|
||||
var value = t.callExpression(this.file.addHelper("object-without-properties"), [objRef, keys]);
|
||||
this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.pushObjectProperty = function (prop, propRef) {
|
||||
if (t.isLiteral(prop.key)) prop.computed = true;
|
||||
|
||||
var pattern = prop.value;
|
||||
var objRef = t.memberExpression(propRef, prop.key, prop.computed);
|
||||
|
||||
if (t.isPattern(pattern)) {
|
||||
this.push(pattern, objRef);
|
||||
} else {
|
||||
this.nodes.push(this.buildVariableAssignment(pattern, objRef));
|
||||
}
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.pushObjectPattern = function (pattern, objRef) {
|
||||
// https://github.com/babel/babel/issues/681
|
||||
|
||||
if (!pattern.properties.length) {
|
||||
this.nodes.push(t.expressionStatement(
|
||||
t.callExpression(this.file.addHelper("object-destructuring-empty"), [objRef])
|
||||
));
|
||||
}
|
||||
|
||||
// if we have more than one properties in this pattern and the objectRef is a
|
||||
// member expression then we need to assign it to a temporary variable so it's
|
||||
// only evaluated once
|
||||
|
||||
if (pattern.properties.length > 1 && t.isMemberExpression(objRef)) {
|
||||
var temp = this.scope.generateUidBasedOnNode(objRef, this.file);
|
||||
this.nodes.push(this.buildVariableDeclaration(temp, objRef));
|
||||
objRef = temp;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (var i = 0; i < pattern.properties.length; i++) {
|
||||
var prop = pattern.properties[i];
|
||||
if (t.isSpreadProperty(prop)) {
|
||||
this.pushObjectSpread(pattern, objRef, prop, i);
|
||||
} else {
|
||||
this.pushObjectProperty(prop, objRef);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var hasRest = function (pattern) {
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
if (t.isRestElement(pattern.elements[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.canUnpackArrayPattern = function (pattern, arr) {
|
||||
// not an array so there's no way we can deal with this
|
||||
if (!t.isArrayExpression(arr)) return false;
|
||||
|
||||
// pattern has less elements than the array and doesn't have a rest so some
|
||||
// elements wont be evaluated
|
||||
if (pattern.elements.length > arr.elements.length) return;
|
||||
if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) return false;
|
||||
|
||||
// deopt on holes
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
if (!pattern.elements[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.pushUnpackedArrayPattern = function (pattern, arr) {
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
var elem = pattern.elements[i];
|
||||
if (t.isRestElement(elem)) {
|
||||
this.push(elem.argument, t.arrayExpression(arr.elements.slice(i)));
|
||||
} else {
|
||||
this.push(elem, arr.elements[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.pushArrayPattern = function (pattern, arrayRef) {
|
||||
if (!pattern.elements) return;
|
||||
|
||||
// optimise basic array destructuring of an array expression
|
||||
//
|
||||
// we can't do this to a pattern of unequal size to it's right hand
|
||||
// array expression as then there will be values that wont be evaluated
|
||||
//
|
||||
// eg: var [a, b] = [1, 2];
|
||||
|
||||
if (this.canUnpackArrayPattern(pattern, arrayRef)) {
|
||||
return this.pushUnpackedArrayPattern(pattern, arrayRef);
|
||||
}
|
||||
|
||||
// if we have a rest then we need all the elements so don't tell
|
||||
// `scope.toArray` to only get a certain amount
|
||||
|
||||
var count = !hasRest(pattern) && pattern.elements.length;
|
||||
|
||||
// so we need to ensure that the `arrayRef` is an array, `scope.toArray` will
|
||||
// return a locally bound identifier if it's been inferred to be an array,
|
||||
// otherwise it'll be a call to a helper that will ensure it's one
|
||||
|
||||
var toArray = this.scope.toArray(arrayRef, count);
|
||||
|
||||
if (t.isIdentifier(toArray)) {
|
||||
// we've been given an identifier so it must have been inferred to be an
|
||||
// array
|
||||
arrayRef = toArray;
|
||||
} else {
|
||||
arrayRef = this.scope.generateUidBasedOnNode(arrayRef);
|
||||
this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
|
||||
this.scope.assignTypeGeneric(arrayRef.name, "Array");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
var elem = pattern.elements[i];
|
||||
|
||||
// hole
|
||||
if (!elem) continue;
|
||||
|
||||
var elemRef;
|
||||
|
||||
if (t.isRestElement(elem)) {
|
||||
elemRef = this.scope.toArray(arrayRef);
|
||||
|
||||
if (i > 0) {
|
||||
elemRef = t.callExpression(t.memberExpression(elemRef, t.identifier("slice")), [t.literal(i)]);
|
||||
}
|
||||
|
||||
// set the element to the rest element argument since we've dealt with it
|
||||
// being a rest already
|
||||
elem = elem.argument;
|
||||
} else {
|
||||
elemRef = t.memberExpression(arrayRef, t.literal(i), true);
|
||||
}
|
||||
|
||||
this.push(elem, elemRef);
|
||||
}
|
||||
};
|
||||
|
||||
DestructuringTransformer.prototype.init = function (pattern, ref) {
|
||||
// trying to destructure a value that we can't evaluate more than once so we
|
||||
// need to save it to a variable
|
||||
|
||||
if (!t.isArrayExpression(ref) && !t.isMemberExpression(ref) && !t.isIdentifier(ref)) {
|
||||
var key = this.scope.generateUidBasedOnNode(ref);
|
||||
this.nodes.push(this.buildVariableDeclaration(key, ref));
|
||||
ref = key;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
this.push(pattern, ref);
|
||||
};
|
||||
|
||||
exports.ForInStatement =
|
||||
exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
var left = node.left;
|
||||
|
||||
if (t.isPattern(left)) {
|
||||
@@ -315,7 +49,9 @@ exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
|
||||
var block = node.body;
|
||||
block.body = nodes.concat(block.body);
|
||||
};
|
||||
}
|
||||
|
||||
export { ForOfStatement as ForInStatement };
|
||||
|
||||
exports.Function = function (node, parent, scope, file) {
|
||||
var nodes = [];
|
||||
@@ -348,7 +84,7 @@ exports.Function = function (node, parent, scope, file) {
|
||||
block.body = nodes.concat(block.body);
|
||||
};
|
||||
|
||||
exports.CatchClause = function (node, parent, scope, file) {
|
||||
export function CatchClause(node, parent, scope, file) {
|
||||
var pattern = node.param;
|
||||
if (!t.isPattern(pattern)) return;
|
||||
|
||||
@@ -368,9 +104,9 @@ exports.CatchClause = function (node, parent, scope, file) {
|
||||
node.body.body = nodes.concat(node.body.body);
|
||||
|
||||
return node;
|
||||
};
|
||||
}
|
||||
|
||||
exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
export function ExpressionStatement(node, parent, scope, file) {
|
||||
var expr = node.expression;
|
||||
if (expr.type !== "AssignmentExpression") return;
|
||||
if (!t.isPattern(expr.left)) return;
|
||||
@@ -392,9 +128,9 @@ exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
destructuring.init(expr.left, ref);
|
||||
|
||||
return nodes;
|
||||
};
|
||||
}
|
||||
|
||||
exports.AssignmentExpression = function (node, parent, scope, file) {
|
||||
export function AssignmentExpression(node, parent, scope, file) {
|
||||
if (!t.isPattern(node.left)) return;
|
||||
|
||||
var ref = scope.generateUidIdentifier("temp");
|
||||
@@ -417,18 +153,18 @@ exports.AssignmentExpression = function (node, parent, scope, file) {
|
||||
nodes.push(ref);
|
||||
|
||||
return t.toSequenceExpression(nodes, scope);
|
||||
};
|
||||
}
|
||||
|
||||
var variableDeclarationHasPattern = function (node) {
|
||||
function variableDeclarationHasPattern(node) {
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
if (t.isPattern(node.declarations[i].id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
export function VariableDeclaration(node, parent, scope, file) {
|
||||
if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;
|
||||
if (!variableDeclarationHasPattern(node)) return;
|
||||
|
||||
@@ -469,7 +205,7 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
node = nodes[i];
|
||||
declar = declar || t.variableDeclaration(node.kind, []);
|
||||
declar ||= t.variableDeclaration(node.kind, []);
|
||||
|
||||
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
|
||||
throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
|
||||
@@ -483,3 +219,264 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
|
||||
return nodes;
|
||||
};
|
||||
|
||||
var hasRest = function (pattern) {
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
if (t.isRestElement(pattern.elements[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
class DestructuringTransformer {
|
||||
constructor(opts) {
|
||||
this.blockHoist = opts.blockHoist;
|
||||
this.operator = opts.operator;
|
||||
this.nodes = opts.nodes;
|
||||
this.scope = opts.scope;
|
||||
this.file = opts.file;
|
||||
this.kind = opts.kind;
|
||||
}
|
||||
|
||||
buildVariableAssignment(id, init) {
|
||||
var op = this.operator;
|
||||
if (t.isMemberExpression(id)) op = "=";
|
||||
|
||||
var node;
|
||||
|
||||
if (op) {
|
||||
node = t.expressionStatement(t.assignmentExpression(op, id, init));
|
||||
} else {
|
||||
node = t.variableDeclaration(this.kind, [
|
||||
t.variableDeclarator(id, init)
|
||||
]);
|
||||
}
|
||||
|
||||
node._blockHoist = this.blockHoist;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
buildVariableDeclaration(id, init) {
|
||||
var declar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(id, init)
|
||||
]);
|
||||
declar._blockHoist = this.blockHoist;
|
||||
return declar;
|
||||
}
|
||||
|
||||
push(id, init) {
|
||||
if (t.isObjectPattern(id)) {
|
||||
this.pushObjectPattern(id, init);
|
||||
} else if (t.isArrayPattern(id)) {
|
||||
this.pushArrayPattern(id, init);
|
||||
} else if (t.isAssignmentPattern(id)) {
|
||||
this.pushAssignmentPattern(id, init);
|
||||
} else {
|
||||
this.nodes.push(this.buildVariableAssignment(id, init));
|
||||
}
|
||||
}
|
||||
|
||||
pushAssignmentPattern(pattern, valueRef) {
|
||||
// we need to assign the current value of the assignment to avoid evaluating
|
||||
// it more than once
|
||||
|
||||
var tempValueRef = this.scope.generateUidBasedOnNode(valueRef);
|
||||
|
||||
var declar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(tempValueRef, valueRef)
|
||||
]);
|
||||
declar._blockHoist = this.blockHoist;
|
||||
this.nodes.push(declar);
|
||||
|
||||
//
|
||||
|
||||
this.nodes.push(this.buildVariableAssignment(
|
||||
pattern.left,
|
||||
t.conditionalExpression(
|
||||
t.binaryExpression("===", tempValueRef, t.identifier("undefined")),
|
||||
pattern.right,
|
||||
tempValueRef
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
pushObjectSpread(pattern, objRef, spreadProp, spreadPropIndex) {
|
||||
// get all the keys that appear in this object before the current spread
|
||||
|
||||
var keys = [];
|
||||
|
||||
for (var i = 0; i < pattern.properties.length; i++) {
|
||||
var prop = pattern.properties[i];
|
||||
|
||||
// we've exceeded the index of the spread property to all properties to the
|
||||
// right need to be ignored
|
||||
if (i >= spreadPropIndex) break;
|
||||
|
||||
// ignore other spread properties
|
||||
if (t.isSpreadProperty(prop)) continue;
|
||||
|
||||
var key = prop.key;
|
||||
if (t.isIdentifier(key)) key = t.literal(prop.key.name);
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
keys = t.arrayExpression(keys);
|
||||
|
||||
//
|
||||
|
||||
var value = t.callExpression(this.file.addHelper("object-without-properties"), [objRef, keys]);
|
||||
this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
|
||||
}
|
||||
|
||||
pushObjectProperty(prop, propRef) {
|
||||
if (t.isLiteral(prop.key)) prop.computed = true;
|
||||
|
||||
var pattern = prop.value;
|
||||
var objRef = t.memberExpression(propRef, prop.key, prop.computed);
|
||||
|
||||
if (t.isPattern(pattern)) {
|
||||
this.push(pattern, objRef);
|
||||
} else {
|
||||
this.nodes.push(this.buildVariableAssignment(pattern, objRef));
|
||||
}
|
||||
}
|
||||
|
||||
pushObjectPattern(pattern, objRef) {
|
||||
// https://github.com/babel/babel/issues/681
|
||||
|
||||
if (!pattern.properties.length) {
|
||||
this.nodes.push(t.expressionStatement(
|
||||
t.callExpression(this.file.addHelper("object-destructuring-empty"), [objRef])
|
||||
));
|
||||
}
|
||||
|
||||
// if we have more than one properties in this pattern and the objectRef is a
|
||||
// member expression then we need to assign it to a temporary variable so it's
|
||||
// only evaluated once
|
||||
|
||||
if (pattern.properties.length > 1 && t.isMemberExpression(objRef)) {
|
||||
var temp = this.scope.generateUidBasedOnNode(objRef, this.file);
|
||||
this.nodes.push(this.buildVariableDeclaration(temp, objRef));
|
||||
objRef = temp;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (var i = 0; i < pattern.properties.length; i++) {
|
||||
var prop = pattern.properties[i];
|
||||
if (t.isSpreadProperty(prop)) {
|
||||
this.pushObjectSpread(pattern, objRef, prop, i);
|
||||
} else {
|
||||
this.pushObjectProperty(prop, objRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canUnpackArrayPattern(pattern, arr) {
|
||||
// not an array so there's no way we can deal with this
|
||||
if (!t.isArrayExpression(arr)) return false;
|
||||
|
||||
// pattern has less elements than the array and doesn't have a rest so some
|
||||
// elements wont be evaluated
|
||||
if (pattern.elements.length > arr.elements.length) return;
|
||||
if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) return false;
|
||||
|
||||
// deopt on holes
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
if (!pattern.elements[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pushUnpackedArrayPattern(pattern, arr) {
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
var elem = pattern.elements[i];
|
||||
if (t.isRestElement(elem)) {
|
||||
this.push(elem.argument, t.arrayExpression(arr.elements.slice(i)));
|
||||
} else {
|
||||
this.push(elem, arr.elements[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pushArrayPattern(pattern, arrayRef) {
|
||||
if (!pattern.elements) return;
|
||||
|
||||
// optimise basic array destructuring of an array expression
|
||||
//
|
||||
// we can't do this to a pattern of unequal size to it's right hand
|
||||
// array expression as then there will be values that wont be evaluated
|
||||
//
|
||||
// eg: var [a, b] = [1, 2];
|
||||
|
||||
if (this.canUnpackArrayPattern(pattern, arrayRef)) {
|
||||
return this.pushUnpackedArrayPattern(pattern, arrayRef);
|
||||
}
|
||||
|
||||
// if we have a rest then we need all the elements so don't tell
|
||||
// `scope.toArray` to only get a certain amount
|
||||
|
||||
var count = !hasRest(pattern) && pattern.elements.length;
|
||||
|
||||
// so we need to ensure that the `arrayRef` is an array, `scope.toArray` will
|
||||
// return a locally bound identifier if it's been inferred to be an array,
|
||||
// otherwise it'll be a call to a helper that will ensure it's one
|
||||
|
||||
var toArray = this.scope.toArray(arrayRef, count);
|
||||
|
||||
if (t.isIdentifier(toArray)) {
|
||||
// we've been given an identifier so it must have been inferred to be an
|
||||
// array
|
||||
arrayRef = toArray;
|
||||
} else {
|
||||
arrayRef = this.scope.generateUidBasedOnNode(arrayRef);
|
||||
this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
|
||||
this.scope.assignTypeGeneric(arrayRef.name, "Array");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
var elem = pattern.elements[i];
|
||||
|
||||
// hole
|
||||
if (!elem) continue;
|
||||
|
||||
var elemRef;
|
||||
|
||||
if (t.isRestElement(elem)) {
|
||||
elemRef = this.scope.toArray(arrayRef);
|
||||
|
||||
if (i > 0) {
|
||||
elemRef = t.callExpression(t.memberExpression(elemRef, t.identifier("slice")), [t.literal(i)]);
|
||||
}
|
||||
|
||||
// set the element to the rest element argument since we've dealt with it
|
||||
// being a rest already
|
||||
elem = elem.argument;
|
||||
} else {
|
||||
elemRef = t.memberExpression(arrayRef, t.literal(i), true);
|
||||
}
|
||||
|
||||
this.push(elem, elemRef);
|
||||
}
|
||||
}
|
||||
|
||||
init(pattern, ref) {
|
||||
// trying to destructure a value that we can't evaluate more than once so we
|
||||
// need to save it to a variable
|
||||
|
||||
if (!t.isArrayExpression(ref) && !t.isMemberExpression(ref) && !t.isIdentifier(ref)) {
|
||||
var key = this.scope.generateUidBasedOnNode(ref);
|
||||
this.nodes.push(this.buildVariableDeclaration(key, ref));
|
||||
ref = key;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
this.push(pattern, ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
"use strict";
|
||||
import * as messages from "../../../messages";
|
||||
import * as util from "../../../util";
|
||||
import t from "../../../types";
|
||||
|
||||
var messages = require("../../../messages");
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
export var check = t.isForOfStatement;
|
||||
|
||||
exports.check = t.isForOfStatement;
|
||||
|
||||
exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
export function ForOfStatement(node, parent, scope, file) {
|
||||
var callback = spec;
|
||||
if (file.isLoose("es6.forOf")) callback = loose;
|
||||
|
||||
@@ -34,11 +32,15 @@ exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
// todo: find out why this is necessary? #538
|
||||
loop._scopeInfo = node._scopeInfo;
|
||||
|
||||
return loop;
|
||||
};
|
||||
if (build.replaceParent) {
|
||||
this.parentPath.node = build.node;
|
||||
} else {
|
||||
return build.node;
|
||||
}
|
||||
}
|
||||
|
||||
var breakVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
if (t.isLoop(node)) {
|
||||
state.ignoreLabeless = true;
|
||||
scope.traverse(node, breakVisitor, state);
|
||||
@@ -99,7 +101,9 @@ var loose = function (node, parent, scope, file) {
|
||||
|
||||
scope.traverse(node, breakVisitor, {
|
||||
iteratorKey: iteratorKey,
|
||||
wrapReturn: function (node) {
|
||||
label: t.isLabeledStatement(parent) && parent.label.name,
|
||||
|
||||
wrapReturn: function (node) {
|
||||
return t.ifStatement(
|
||||
t.logicalExpression(
|
||||
"&&",
|
||||
@@ -107,19 +111,21 @@ var loose = function (node, parent, scope, file) {
|
||||
t.memberExpression(iteratorKey, t.identifier("return")
|
||||
)
|
||||
), node);
|
||||
},
|
||||
label: t.isLabeledStatement(parent) && parent.label.name
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
return {
|
||||
declar: declar,
|
||||
node: loop,
|
||||
loop: loop
|
||||
};
|
||||
};
|
||||
|
||||
var spec = function (node, parent, scope, file) {
|
||||
|
||||
|
||||
var left = node.left;
|
||||
var declar;
|
||||
|
||||
@@ -142,26 +148,42 @@ var spec = function (node, parent, scope, file) {
|
||||
|
||||
var iteratorKey = scope.generateUidIdentifier("iterator");
|
||||
|
||||
var loop = util.template("for-of", {
|
||||
ITERATOR_KEY: iteratorKey,
|
||||
STEP_KEY: stepKey,
|
||||
OBJECT: node.right
|
||||
var template = util.template("for-of", {
|
||||
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
|
||||
ITERATOR_COMPLETION: scope.generateUidIdentifier("iteratorNormalCompletion"),
|
||||
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
|
||||
ITERATOR_KEY: iteratorKey,
|
||||
STEP_KEY: stepKey,
|
||||
OBJECT: node.right,
|
||||
BODY: null
|
||||
});
|
||||
|
||||
var isLabeledParent = t.isLabeledStatement(parent);
|
||||
|
||||
var tryBody = template[3].block.body;
|
||||
var loop = tryBody[0];
|
||||
|
||||
if (isLabeledParent) {
|
||||
tryBody[0] = t.labeledStatement(parent.label, loop);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
scope.traverse(node, breakVisitor, {
|
||||
iteratorKey: iteratorKey,
|
||||
wrapReturn: function (node) {
|
||||
label: isLabeledParent && parent.label.name,
|
||||
|
||||
wrapReturn: function (node) {
|
||||
return t.ifStatement(t.memberExpression(iteratorKey, t.identifier("return")), node);
|
||||
},
|
||||
label: t.isLabeledStatement(parent) && parent.label.name
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
return {
|
||||
declar: declar,
|
||||
loop: loop
|
||||
replaceParent: isLabeledParent,
|
||||
declar: declar,
|
||||
loop: loop,
|
||||
node: template
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
"use strict";
|
||||
import t from "../../../types";
|
||||
|
||||
var t = require("../../../types");
|
||||
export { check } from "../internal/modules";
|
||||
|
||||
exports.check = require("../internal/modules").check;
|
||||
|
||||
exports.ImportDeclaration = function (node, parent, scope, file) {
|
||||
export function ImportDeclaration(node, parent, scope, file) {
|
||||
// flow type
|
||||
if (node.isType) return;
|
||||
|
||||
@@ -24,9 +22,9 @@ exports.ImportDeclaration = function (node, parent, scope, file) {
|
||||
}
|
||||
|
||||
return nodes;
|
||||
};
|
||||
}
|
||||
|
||||
exports.ExportDeclaration = function (node, parent, scope, file) {
|
||||
export function ExportDeclaration(node, parent, scope, file) {
|
||||
// flow type
|
||||
if (t.isTypeAlias(node.declaration)) return;
|
||||
|
||||
@@ -55,4 +53,4 @@ exports.ExportDeclaration = function (node, parent, scope, file) {
|
||||
}
|
||||
|
||||
return nodes;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
"use strict";
|
||||
import ReplaceSupers from "../../helpers/replace-supers";
|
||||
import t from "../../../types";
|
||||
|
||||
var ReplaceSupers = require("../../helpers/replace-supers");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
export function check(node) {
|
||||
return t.isIdentifier(node, { name: "super" });
|
||||
};
|
||||
}
|
||||
|
||||
exports.Property = function (node, parent, scope, file) {
|
||||
export function Property(node, parent, scope, file) {
|
||||
if (!node.method) return;
|
||||
|
||||
var value = node.value;
|
||||
@@ -31,4 +29,4 @@ exports.Property = function (node, parent, scope, file) {
|
||||
])
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"use strict";
|
||||
import * as util from "../../../util";
|
||||
import t from "../../../types";
|
||||
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
export function check(node) {
|
||||
return t.isFunction(node) && hasDefaults(node);
|
||||
};
|
||||
}
|
||||
|
||||
var hasDefaults = function (node) {
|
||||
for (var i = 0; i < node.params.length; i++) {
|
||||
@@ -15,7 +13,7 @@ var hasDefaults = function (node) {
|
||||
};
|
||||
|
||||
var iifeVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
enter(node, parent, scope, state) {
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
if (!state.scope.hasOwnBinding(node.name)) return;
|
||||
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
|
||||
|
||||
@@ -1,9 +1,55 @@
|
||||
"use strict";
|
||||
import isNumber from "lodash/lang/isNumber";
|
||||
import * as util from "../../../util";
|
||||
import t from "../../../types";
|
||||
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
export var check = t.isRestElement;
|
||||
|
||||
exports.check = t.isRestElement;
|
||||
var memberExpressionOptimisationVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
// check if this scope has a local binding that will shadow the rest parameter
|
||||
if (t.isScope(node, parent) && !scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
// skip over functions as whatever `arguments` we reference inside will refer
|
||||
// to the wrong function
|
||||
if (t.isFunctionDeclaration(node) || t.isFunctionExpression(node)) {
|
||||
state.noOptimise = true;
|
||||
scope.traverse(node, memberExpressionOptimisationVisitor, state);
|
||||
state.noOptimise = false;
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
// is this a referenced identifier and is it referencing the rest parameter?
|
||||
if (!t.isReferencedIdentifier(node, parent, { name: state.name })) return;
|
||||
|
||||
if (!state.noOptimise && t.isMemberExpression(parent) && parent.computed) {
|
||||
// if we know that this member expression is referencing a number then we can safely
|
||||
// optimise it
|
||||
var prop = parent.property;
|
||||
if (isNumber(prop.value) || t.isUnaryExpression(prop) || t.isBinaryExpression(prop)) {
|
||||
state.candidates.push(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
state.canOptimise = false;
|
||||
this.stop();
|
||||
}
|
||||
};
|
||||
|
||||
function optimizeMemberExpression(parent, offset) {
|
||||
var newExpr;
|
||||
var prop = parent.property;
|
||||
|
||||
if (t.isLiteral(prop)) {
|
||||
prop.value += offset;
|
||||
prop.raw = String(prop.value);
|
||||
} else { // // UnaryExpression, BinaryExpression
|
||||
newExpr = t.binaryExpression("+", prop, t.literal(offset));
|
||||
parent.property = newExpr;
|
||||
}
|
||||
}
|
||||
|
||||
var hasRest = function (node) {
|
||||
return t.isRestElement(node.params[node.params.length - 1]);
|
||||
@@ -19,6 +65,41 @@ exports.Function = function (node, parent, scope) {
|
||||
// otherwise `arguments` will be remapped in arrow functions
|
||||
argsId._ignoreAliasFunctions = true;
|
||||
|
||||
// support patterns
|
||||
if (t.isPattern(rest)) {
|
||||
var pattern = rest;
|
||||
rest = scope.generateUidIdentifier("ref");
|
||||
var declar = t.variableDeclaration("var", pattern.elements.map(function (elem, index) {
|
||||
var accessExpr = t.memberExpression(rest, t.literal(index), true);
|
||||
return t.variableDeclarator(elem, accessExpr);
|
||||
}));
|
||||
node.body.body.unshift(declar);
|
||||
}
|
||||
|
||||
// check if rest is used in member expressions and optimise for those cases
|
||||
|
||||
var state = {
|
||||
outerBinding: scope.getBindingIdentifier(rest.name),
|
||||
canOptimise: true,
|
||||
candidates: [],
|
||||
method: node,
|
||||
name: rest.name
|
||||
};
|
||||
|
||||
scope.traverse(node, memberExpressionOptimisationVisitor, state);
|
||||
|
||||
// we only have shorthands and there's no other references
|
||||
if (state.canOptimise && state.candidates.length) {
|
||||
for (var i = 0; i < state.candidates.length; i++) {
|
||||
var candidate = state.candidates[i];
|
||||
candidate.node = argsId;
|
||||
optimizeMemberExpression(candidate.parent, node.params.length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var start = t.literal(node.params.length);
|
||||
var key = scope.generateUidIdentifier("key");
|
||||
var len = scope.generateUidIdentifier("len");
|
||||
@@ -44,22 +125,6 @@ exports.Function = function (node, parent, scope) {
|
||||
);
|
||||
}
|
||||
|
||||
// support patterns
|
||||
if (t.isPattern(rest)) {
|
||||
var pattern = rest;
|
||||
rest = scope.generateUidIdentifier("ref");
|
||||
|
||||
// let the destructuring transformer handle this
|
||||
var restDeclar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(pattern, rest)
|
||||
]);
|
||||
|
||||
// retain evaluation position
|
||||
restDeclar._blockHoist = node.params.length + 1;
|
||||
|
||||
node.body.body.unshift(restDeclar);
|
||||
}
|
||||
|
||||
scope.assignTypeGeneric(rest.name, "Array");
|
||||
|
||||
var loop = util.template("rest", {
|
||||
|
||||
@@ -1,50 +1,6 @@
|
||||
"use strict";
|
||||
import t from "../../../types";
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isProperty(node) && node.computed;
|
||||
};
|
||||
|
||||
exports.ObjectExpression = function (node, parent, scope, file) {
|
||||
var hasComputed = false;
|
||||
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
|
||||
if (hasComputed) break;
|
||||
}
|
||||
|
||||
if (!hasComputed) return;
|
||||
|
||||
var initProps = [];
|
||||
var objId = scope.generateUidBasedOnNode(parent);
|
||||
|
||||
//
|
||||
|
||||
var body = [];
|
||||
var container = t.functionExpression(null, [], t.blockStatement(body));
|
||||
container._aliasFunction = true;
|
||||
|
||||
//
|
||||
|
||||
var callback = spec;
|
||||
if (file.isLoose("es6.properties.computed")) callback = loose;
|
||||
|
||||
var result = callback(node, body, objId, initProps, file);
|
||||
if (result) return result;
|
||||
|
||||
//
|
||||
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(objId, t.objectExpression(initProps))
|
||||
]));
|
||||
|
||||
body.push(t.returnStatement(objId));
|
||||
|
||||
return t.callExpression(container, []);
|
||||
};
|
||||
|
||||
var loose = function (node, body, objId) {
|
||||
function loose(node, body, objId) {
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
|
||||
@@ -56,9 +12,9 @@ var loose = function (node, body, objId) {
|
||||
)
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var spec = function (node, body, objId, initProps, file) {
|
||||
function spec(node, body, objId, initProps, file) {
|
||||
var props = node.properties;
|
||||
var prop, key;
|
||||
|
||||
@@ -126,4 +82,46 @@ var spec = function (node, body, objId, initProps, file) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function check(node) {
|
||||
return t.isProperty(node) && node.computed;
|
||||
}
|
||||
|
||||
export function ObjectExpression(node, parent, scope, file) {
|
||||
var hasComputed = false;
|
||||
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
|
||||
if (hasComputed) break;
|
||||
}
|
||||
|
||||
if (!hasComputed) return;
|
||||
|
||||
var initProps = [];
|
||||
var objId = scope.generateUidBasedOnNode(parent);
|
||||
|
||||
//
|
||||
|
||||
var body = [];
|
||||
var container = t.functionExpression(null, [], t.blockStatement(body));
|
||||
container._aliasFunction = true;
|
||||
|
||||
//
|
||||
|
||||
var callback = spec;
|
||||
if (file.isLoose("es6.properties.computed")) callback = loose;
|
||||
|
||||
var result = callback(node, body, objId, initProps, file);
|
||||
if (result) return result;
|
||||
|
||||
//
|
||||
|
||||
body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(objId, t.objectExpression(initProps))
|
||||
]));
|
||||
|
||||
body.push(t.returnStatement(objId));
|
||||
|
||||
return t.callExpression(container, []);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
"use strict";
|
||||
import clone from "lodash/lang/clone";
|
||||
import t from "../../../types";
|
||||
|
||||
var clone = require("lodash/lang/clone");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
export function check(node) {
|
||||
return t.isProperty(node) && (node.method || node.shorthand);
|
||||
};
|
||||
}
|
||||
|
||||
exports.Property = function (node) {
|
||||
export function Property(node) {
|
||||
if (node.method) {
|
||||
node.method = false;
|
||||
}
|
||||
@@ -16,4 +14,4 @@ exports.Property = function (node) {
|
||||
node.shorthand = false;
|
||||
node.key = t.removeComments(clone(node.key));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
14
src/babel/transformation/transformers/es6/regex.sticky.js
Normal file
14
src/babel/transformation/transformers/es6/regex.sticky.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as regex from "../../helpers/regex";
|
||||
import t from "../../../types";
|
||||
|
||||
export function check(node) {
|
||||
return regex.is(node, "y");
|
||||
}
|
||||
|
||||
export function Literal(node) {
|
||||
if (!regex.is(node, "y")) return;
|
||||
return t.newExpression(t.identifier("RegExp"), [
|
||||
t.literal(node.regex.pattern),
|
||||
t.literal(node.regex.flags)
|
||||
]);
|
||||
}
|
||||
12
src/babel/transformation/transformers/es6/regex.unicode.js
Normal file
12
src/babel/transformation/transformers/es6/regex.unicode.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import rewritePattern from "regexpu/rewrite-pattern";
|
||||
import * as regex from "../../helpers/regex";
|
||||
|
||||
export function check(node) {
|
||||
return regex.is(node, "u");
|
||||
}
|
||||
|
||||
export function Literal(node) {
|
||||
if (!regex.is(node, "u")) return;
|
||||
regex.pullFlag(node, "y");
|
||||
node.regex.pattern = rewritePattern(node.regex.pattern, node.regex.flags);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user