Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f0b7683a1 | ||
|
|
f0d2cbb055 | ||
|
|
602c5e0ca0 | ||
|
|
2a2dff0eaf | ||
|
|
e1151e08c9 | ||
|
|
84f54ca3c7 | ||
|
|
5fb793b75f | ||
|
|
1adc9bfc70 | ||
|
|
3649fad485 | ||
|
|
0e1743738e | ||
|
|
6ad16302cd | ||
|
|
4b6b7af332 | ||
|
|
55dfb423ee | ||
|
|
9d1bc4817d | ||
|
|
fc8666e7a4 | ||
|
|
07b6881d67 | ||
|
|
1f208a06db | ||
|
|
b5c9c84542 | ||
|
|
492555bb4e | ||
|
|
53d88c0f63 | ||
|
|
8a5da57162 | ||
|
|
1627e2f47e | ||
|
|
e195d6ca55 | ||
|
|
71d5d4fb2c | ||
|
|
dfe13cda0d | ||
|
|
a4c6660d21 | ||
|
|
9676666e7c | ||
|
|
388133642d | ||
|
|
23b5eeb72f | ||
|
|
db36c3a7c2 | ||
|
|
e841b88cbc | ||
|
|
3d874f2479 | ||
|
|
228719102a | ||
|
|
c6ce1a248c | ||
|
|
ba9b85f64b | ||
|
|
56c868efee | ||
|
|
1f3c3832ba | ||
|
|
3b04a8c648 | ||
|
|
2270057b54 | ||
|
|
c3206aa9a4 | ||
|
|
1912d1b26a | ||
|
|
9208e7e594 | ||
|
|
ce332b3384 | ||
|
|
a567531f77 | ||
|
|
9cce72def0 | ||
|
|
2d8581c6dc | ||
|
|
14a000396a | ||
|
|
4c41f5a22f | ||
|
|
6be2a6e02a | ||
|
|
0a4fc16ca0 | ||
|
|
25d8377411 | ||
|
|
14267a788d | ||
|
|
ba5c5760b1 | ||
|
|
49904b3ab3 | ||
|
|
a212f035e4 | ||
|
|
ea471a6a17 | ||
|
|
f5bae0b696 | ||
|
|
9ec9e13aeb | ||
|
|
0b042b2681 | ||
|
|
83b4d12884 | ||
|
|
98d555498d | ||
|
|
fdc05cb977 | ||
|
|
928ebda5bc | ||
|
|
0a2003af66 | ||
|
|
02392635ef | ||
|
|
298cfac7f4 | ||
|
|
476b683f0f | ||
|
|
5c5b66df54 | ||
|
|
e7f6572a3b | ||
|
|
e9cfd2df3e | ||
|
|
a425136680 | ||
|
|
8d06a4301c | ||
|
|
1909a16dc7 | ||
|
|
3bfa1f610c | ||
|
|
4faf2b7730 | ||
|
|
4e5d6ee976 | ||
|
|
afb1ee79a1 | ||
|
|
efe3f30741 | ||
|
|
5ff0285ba7 | ||
|
|
d7bea2f325 | ||
|
|
32316ad942 | ||
|
|
7953eb560e | ||
|
|
faa10df84c | ||
|
|
ae344aa23e | ||
|
|
e0bfc72700 | ||
|
|
bf8f80faf7 | ||
|
|
77fa8bf01c | ||
|
|
34ca1ac04f | ||
|
|
85d33536e0 | ||
|
|
a4932e0e0f | ||
|
|
4ebd0a1e8a | ||
|
|
14e92e9e3f | ||
|
|
13687d98ed | ||
|
|
db93c52182 | ||
|
|
56a953df64 | ||
|
|
c38edbbb42 | ||
|
|
017bb6427a | ||
|
|
714ad40cb0 | ||
|
|
904a72fb3a | ||
|
|
146835e0f1 | ||
|
|
79ba97872c | ||
|
|
897566ccb3 | ||
|
|
4df1b6700b | ||
|
|
50f903caf7 | ||
|
|
7b8118d8bd | ||
|
|
0c1e1e757c | ||
|
|
62fa583fc1 | ||
|
|
8598000a69 | ||
|
|
edc8bee38e | ||
|
|
45b70d7fba | ||
|
|
49a53b26bb | ||
|
|
329b4e9d21 | ||
|
|
f1bca0013e | ||
|
|
87af83f1cb | ||
|
|
5156574bf2 | ||
|
|
ac098255be | ||
|
|
47b803ef24 | ||
|
|
7f61c8b65e | ||
|
|
4fa9aa63a3 | ||
|
|
d582c7c93a | ||
|
|
6266f5b924 | ||
|
|
c6920a0e60 | ||
|
|
825d84ba52 | ||
|
|
94a0eb5b06 | ||
|
|
b6d708caf2 | ||
|
|
0d542b61d3 | ||
|
|
5a842ab623 | ||
|
|
26d4b5f2cf | ||
|
|
ba0dfac53d | ||
|
|
8a4296a948 | ||
|
|
478f9e028f | ||
|
|
c4e56894d9 | ||
|
|
c6f13844ed | ||
|
|
5e81653680 | ||
|
|
8e2df3f1f9 | ||
|
|
a2cc384172 | ||
|
|
d37bf292a1 | ||
|
|
70eb641530 | ||
|
|
f845a9b2c4 | ||
|
|
ee5cb8d9ed | ||
|
|
9020a21ba2 |
5
.6to5rc
Normal file
5
.6to5rc
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"experimental": true,
|
||||
"playground": true,
|
||||
"loose": true
|
||||
}
|
||||
@@ -3,6 +3,7 @@ language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.11"
|
||||
- "0.12"
|
||||
|
||||
branches:
|
||||
except:
|
||||
|
||||
49
CHANGELOG.md
49
CHANGELOG.md
@@ -11,6 +11,55 @@
|
||||
|
||||
_Note: Gaps between patch versions are faulty/broken releases._
|
||||
|
||||
## 3.6.5
|
||||
|
||||
* **Internal**
|
||||
* Upgrade `core-js`.
|
||||
* **Bug Fix**
|
||||
* Fix block scoping leaking variables in IIFE mode.
|
||||
* Fix tail call transformer exploding on return statements as the consequent of an if statement.
|
||||
* **New Feature**
|
||||
* Add `validation.react` transformer.
|
||||
|
||||
## 3.6.4
|
||||
|
||||
* **New Feature**
|
||||
* Add support for flow type casts and module types.
|
||||
|
||||
## 3.6.3
|
||||
|
||||
* **Internal**
|
||||
* Upgrade `acorn-6to5`.
|
||||
* Use `default` property on `6to5-runtime`.
|
||||
|
||||
## 3.6.2
|
||||
|
||||
* **Polish**
|
||||
* Use better iterator detection in `slicedToArray` helper and add support for it to the `selfContained` transformer.
|
||||
|
||||
## 3.6.1
|
||||
|
||||
* **Bug Fix**
|
||||
* Multiline JSX string literals are now supported.
|
||||
* Fix scope tracking import specifiers incorrectly.
|
||||
* Fix templates incorrectly recursing into their replacements.
|
||||
* **Internal**
|
||||
* Type inferrence now extends to function return types.
|
||||
* Upgrade `acorn-6to5`.
|
||||
|
||||
## 3.6.0
|
||||
|
||||
* **New Feature**
|
||||
* Add playground class property initializers.
|
||||
* **Polish**
|
||||
* Completely reimplemented scope tracking, can now track types and optimise certain helpers based on it.
|
||||
* Extremely fast tail recursion optimisation implementation. Thanks [@RReverser](https://github.com/RReverser)!
|
||||
* **Internal**
|
||||
* `kexec` has been removed as an optional dependency and must be user installed.
|
||||
* Upgrade `regenerator-6to5`.
|
||||
* Upgrade `acorn-6to5`.
|
||||
* Upgrade `core-js`.
|
||||
|
||||
## 3.5.3
|
||||
|
||||
* Enable `es6.tailCall` transformer with the first implementation that only works with self referencing calls until we can implement nested tail calls elegantly.
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
# Contributing
|
||||
|
||||
Contributions are always welcome, no matter how large or small. Before contributing, please read the [code of conduct](https://github.com/6to5/6to5/blob/master/CODE_OF_CONDUCT.md).
|
||||
Contributions are always welcome, no matter how large or small. Before
|
||||
contributing, please read the
|
||||
[code of conduct](https://github.com/6to5/6to5/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
|
||||
|
||||
@@ -12,7 +18,8 @@ Contributions are always welcome, no matter how large or small. Before contribut
|
||||
* Link your forked clone (`npm link`)
|
||||
* Develop your changes ensuring you're fetching updates from upstream often
|
||||
* Ensure the test are passing (`make test`)
|
||||
* Create new pull request explaining your proposed change or reference an issue in your commit message
|
||||
* Create new pull request explaining your proposed change or reference an issue
|
||||
in your commit message
|
||||
|
||||
#### Code Standards
|
||||
|
||||
|
||||
11
Makefile
11
Makefile
@@ -5,10 +5,17 @@ UGLIFY_CMD = node_modules/uglify-js/bin/uglifyjs
|
||||
JSHINT_CMD = node_modules/jshint/bin/jshint
|
||||
MOCHA_CMD = node_modules/mocha/bin/_mocha
|
||||
JSCS_CMD = node_modules/jscs/bin/jscs
|
||||
6TO5_CMD = node_modules/6to5/bin/6to5
|
||||
|
||||
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
|
||||
.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
|
||||
|
||||
build-core:
|
||||
#node $(6TO5_CMD) src --out-dir lib
|
||||
|
||||
watch-core:
|
||||
#node $(6TO5_CMD) src --out-dir lib --watch
|
||||
|
||||
build:
|
||||
mkdir -p dist
|
||||
@@ -55,7 +62,7 @@ test-cov:
|
||||
export SIMPLE_6TO5_TESTS=1; \
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
|
||||
|
||||
test-travis: bootstrap
|
||||
test-travis: build-core bootstrap
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
|
||||
if test -n "$$CODECLIMATE_REPO_TOKEN"; then codeclimate < coverage/lcov.info; fi
|
||||
|
||||
|
||||
17
appveyor.yml
17
appveyor.yml
@@ -1,17 +0,0 @@
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: "0.10"
|
||||
- nodejs_version: "0.11"
|
||||
|
||||
install:
|
||||
- "npm install"
|
||||
- "cinst make"
|
||||
|
||||
test_script:
|
||||
- "node --version"
|
||||
- "npm --version"
|
||||
- "make test-spec"
|
||||
|
||||
build: "off"
|
||||
|
||||
version: "{build}"
|
||||
@@ -16,7 +16,9 @@ module.exports = function (commander, filenames, opts) {
|
||||
|
||||
var dest = path.join(commander.outDir, relative);
|
||||
|
||||
var data = util.compile(src, { sourceMapName: dest });
|
||||
var data = util.compile(src, {
|
||||
sourceFileName: path.relative(dest + "/..", src)
|
||||
});
|
||||
|
||||
if (commander.sourceMaps) {
|
||||
var mapLoc = dest + ".map";
|
||||
@@ -37,8 +39,13 @@ module.exports = function (commander, filenames, opts) {
|
||||
if (stat.isDirectory(filename)) {
|
||||
var dirname = filename;
|
||||
|
||||
_.each(util.readdirFilter(dirname), function (filename) {
|
||||
write(path.join(dirname, filename), filename);
|
||||
_.each(util.readdir(dirname), function (filename) {
|
||||
var src = path.join(dirname, filename);
|
||||
if (util.canCompile(filename)) {
|
||||
write(src, filename);
|
||||
} else {
|
||||
outputFileSync(path.join(commander.outDir, filename), fs.readFileSync(src));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
write(filename, filename);
|
||||
|
||||
@@ -26,6 +26,7 @@ commander.option("-c, --remove-comments", "Remove comments from the compiled cod
|
||||
commander.option("-M, --module-ids", "Insert module id in modules", false);
|
||||
commander.option("-R, --react-compat", "Makes the react transformer produce pre-v0.12 code");
|
||||
commander.option("--keep-module-id-extensions", "Keep extensions when generating module ids", false);
|
||||
commander.option("-a, --auxilary-comment [comment]", "Comment text to prepend to all auxilary code");
|
||||
|
||||
commander.on("--help", function () {
|
||||
var outKeys = function (title, obj) {
|
||||
@@ -99,6 +100,7 @@ if (errors.length) {
|
||||
|
||||
exports.opts = {
|
||||
keepModuleIdExtensions: commander.keepModuleIdExtensions,
|
||||
auxilaryComment: commander.auxilaryComment,
|
||||
sourceMapName: commander.outFile,
|
||||
experimental: commander.experimental,
|
||||
reactCompat: commander.reactCompat,
|
||||
|
||||
@@ -12,12 +12,16 @@ exports.readdirFilter = function (filename) {
|
||||
});
|
||||
};
|
||||
|
||||
exports.readdir = readdir;
|
||||
|
||||
exports.canCompile = util.canCompile;
|
||||
|
||||
exports.addSourceMappingUrl = function (code, loc) {
|
||||
return code + "\n//# sourceMappingURL=" + path.basename(loc);
|
||||
};
|
||||
|
||||
exports.transform = function (filename, code, opts) {
|
||||
opts = _.extend(opts || {}, index.opts);
|
||||
opts = _.defaults(opts || {}, index.opts);
|
||||
opts.filename = filename;
|
||||
|
||||
var result;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var t = require("../types");
|
||||
var _ = require("lodash");
|
||||
var includes = require("lodash/collection/includes");
|
||||
|
||||
exports.AssignmentExpression = function (node, parent, detected) {
|
||||
if (node.operator === "**=") {
|
||||
@@ -38,7 +38,7 @@ exports.Property = function (node, parent, detected) {
|
||||
};
|
||||
|
||||
exports.AssignmentPattern = function (node, parent, detected) {
|
||||
if (t.isFunction(parent) && _.contains(parent.params, node)) {
|
||||
if (t.isFunction(parent) && includes(parent.params, node)) {
|
||||
detected("es6.parameters.default");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
module.exports = Buffer;
|
||||
|
||||
var isBoolean = require("lodash/lang/isBoolean");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var isNumber = require("lodash/lang/isNumber");
|
||||
var util = require("../util");
|
||||
|
||||
@@ -159,7 +159,7 @@ Buffer.prototype.isLast = function (cha, trimRight) {
|
||||
var last = buf[buf.length - 1];
|
||||
|
||||
if (Array.isArray(cha)) {
|
||||
return contains(cha, last);
|
||||
return includes(cha, last);
|
||||
} else {
|
||||
return cha === last;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ exports.ObjectTypeIndexer =
|
||||
exports.ObjectTypeProperty =
|
||||
exports.QualifiedTypeIdentifier =
|
||||
exports.UnionTypeAnnotation =
|
||||
exports.TypeCastExpression =
|
||||
exports.VoidTypeAnnotation = function () {
|
||||
// todo: implement these once we have a `--keep-types` option
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ exports.IfStatement = function (node, print) {
|
||||
print.indentOnComments(node.consequent);
|
||||
|
||||
if (node.alternate) {
|
||||
if (this.isLast("}")) this.push(" ");
|
||||
if (this.isLast("}")) this.space();
|
||||
this.keyword("else");
|
||||
|
||||
if (this.format.format && !t.isBlockStatement(node.alternate)) {
|
||||
|
||||
@@ -82,7 +82,7 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (endToken.type.type === "eof") {
|
||||
if (endToken && endToken.type.type === "eof") {
|
||||
return 1;
|
||||
} else {
|
||||
var lines = this.getNewlinesBetween(startToken, endToken);
|
||||
@@ -96,6 +96,8 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
49
lib/6to5/messages.js
Normal file
49
lib/6to5/messages.js
Normal file
@@ -0,0 +1,49 @@
|
||||
var util = require("util");
|
||||
|
||||
exports.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",
|
||||
classesIllegalSuperCall: "Direct super call is illegal in non-constructor, use super.$1() instead",
|
||||
classesIllegalConstructorKind: "Illegal kind for constructor method",
|
||||
scopeDuplicateDeclaration: "Duplicate declaration $1",
|
||||
undeclaredVariable: "Reference to undeclared variable $1",
|
||||
undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?",
|
||||
settersInvalidParamLength: "Setters must have only one parameter",
|
||||
noAssignmentsInForHead: "No assignments allowed in for-in/of head",
|
||||
expectedMemberExpressionOrIdentifier: "Expected type MemeberExpression or Identifier",
|
||||
invalidParentForThisNode: "We don't know how to handle this node within the current parent - please open an issue",
|
||||
readOnly: "$1 is read-only",
|
||||
modulesIllegalExportName: "Illegal export $1",
|
||||
unknownForHead: "Unknown node type $1 in ForStatement",
|
||||
didYouMean: "Did you mean $1?"
|
||||
};
|
||||
|
||||
exports.get = function (key) {
|
||||
var msg = exports.messages[key];
|
||||
if (!msg) throw new ReferenceError("Unknown message `" + key + "`");
|
||||
|
||||
var args = [];
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
args = exports.parseArgs(args);
|
||||
|
||||
return msg.replace(/\$(\d+)/g, function (str, i) {
|
||||
return args[--i];
|
||||
});
|
||||
};
|
||||
|
||||
exports.parseArgs = function (args) {
|
||||
return args.map(function (val) {
|
||||
if (val != null && val.inspect) {
|
||||
return val.inspect();
|
||||
} else {
|
||||
try {
|
||||
return JSON.stringify(val) || val + "";
|
||||
} catch (e) {
|
||||
return util.inspect(val);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -3,8 +3,6 @@
|
||||
var extend = require("lodash/object/extend");
|
||||
var t = require("./types");
|
||||
|
||||
require("./types/node");
|
||||
|
||||
// estraverse
|
||||
|
||||
var estraverse = require("estraverse");
|
||||
|
||||
@@ -8,7 +8,7 @@ var isFunction = require("lodash/lang/isFunction");
|
||||
var transform = require("./index");
|
||||
var generate = require("../generation");
|
||||
var defaults = require("lodash/object/defaults");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var clone = require("../helpers/clone");
|
||||
var parse = require("../helpers/parse");
|
||||
var Scope = require("../traversal/scope");
|
||||
@@ -18,9 +18,10 @@ var each = require("lodash/collection/each");
|
||||
var t = require("../types");
|
||||
|
||||
function File(opts) {
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImported = [];
|
||||
this.dynamicImports = [];
|
||||
this.dynamicImportedNoDefault = [];
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImported = [];
|
||||
this.dynamicImports = [];
|
||||
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
@@ -41,6 +42,7 @@ File.helpers = [
|
||||
"tagged-template-literal-loose",
|
||||
"interop-require",
|
||||
"to-array",
|
||||
"to-consumable-array",
|
||||
"sliced-to-array",
|
||||
"object-without-properties",
|
||||
"has-own",
|
||||
@@ -84,6 +86,7 @@ File.validOptions = [
|
||||
"experimental",
|
||||
"resolveModuleSource",
|
||||
"runtime",
|
||||
"auxilaryComment",
|
||||
|
||||
// these are used by plugins
|
||||
"ignore",
|
||||
@@ -104,6 +107,7 @@ File.prototype.normalizeOptions = function (opts) {
|
||||
defaults(opts, {
|
||||
keepModuleIdExtensions: false,
|
||||
resolveModuleSource: null,
|
||||
auxilaryComment: "",
|
||||
experimental: false,
|
||||
reactCompat: false,
|
||||
playground: false,
|
||||
@@ -123,7 +127,10 @@ File.prototype.normalizeOptions = function (opts) {
|
||||
});
|
||||
|
||||
// normalize windows path separators to unix
|
||||
opts.filename = opts.filename.replace(/\\/g, "/");
|
||||
opts.filename = util.normalisePathSeparator(opts.filename);
|
||||
if (opts.sourceRoot) {
|
||||
opts.sourceRoot = util.normalisePathSeparator(opts.sourceRoot);
|
||||
}
|
||||
|
||||
opts.basename = path.basename(opts.filename, path.extname(opts.filename));
|
||||
|
||||
@@ -132,7 +139,7 @@ File.prototype.normalizeOptions = function (opts) {
|
||||
opts.optional = util.arrayify(opts.optional);
|
||||
opts.loose = util.arrayify(opts.loose);
|
||||
|
||||
if (contains(opts.loose, "all")) {
|
||||
if (includes(opts.loose, "all") || includes(opts.loose, true)) {
|
||||
opts.loose = Object.keys(transform.transformers);
|
||||
}
|
||||
|
||||
@@ -172,11 +179,20 @@ File.prototype.normalizeOptions = function (opts) {
|
||||
"`reactCompat` - backwards compatibility will be removed in v4.0.0");
|
||||
}
|
||||
|
||||
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 contains(this.opts.loose, key);
|
||||
return includes(this.opts.loose, key);
|
||||
};
|
||||
|
||||
File.prototype.buildTransformers = function () {
|
||||
@@ -213,22 +229,6 @@ File.prototype.debug = function (msg) {
|
||||
util.debug(parts);
|
||||
};
|
||||
|
||||
File.prototype.toArray = function (node, i) {
|
||||
if (t.isArrayExpression(node)) {
|
||||
return node;
|
||||
} else if (t.isIdentifier(node) && node.name === "arguments") {
|
||||
return t.callExpression(t.memberExpression(this.addHelper("slice"), t.identifier("call")), [node]);
|
||||
} else {
|
||||
var declarationName = "to-array";
|
||||
var args = [node];
|
||||
if (i) {
|
||||
args.push(t.literal(i));
|
||||
declarationName = "sliced-to-array";
|
||||
}
|
||||
return t.callExpression(this.addHelper(declarationName), args);
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype.getModuleFormatter = function (type) {
|
||||
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
||||
|
||||
@@ -276,17 +276,19 @@ File.prototype.get = function (key) {
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype.addImport = function (source, name) {
|
||||
File.prototype.addImport = function (source, name, noDefault) {
|
||||
name = name || source;
|
||||
var id = this.dynamicImportIds[name];
|
||||
|
||||
if (!id) {
|
||||
id = this.dynamicImportIds[name] = this.generateUidIdentifier(name);
|
||||
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);
|
||||
}
|
||||
@@ -298,8 +300,20 @@ File.prototype.isConsequenceExpressionStatement = function (node) {
|
||||
return t.isExpressionStatement(node) && this.lastStatements.indexOf(node) >= 0;
|
||||
};
|
||||
|
||||
File.prototype.attachAuxilaryComment = function (node) {
|
||||
var comment = this.opts.auxilaryComment;
|
||||
if (comment) {
|
||||
node.leadingComments = node.leadingComments || [];
|
||||
node.leadingComments.push({
|
||||
type: "Line",
|
||||
value: " " + comment
|
||||
});
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
File.prototype.addHelper = function (name) {
|
||||
if (!contains(File.helpers, name)) {
|
||||
if (!includes(File.helpers, name)) {
|
||||
throw new ReferenceError("Unknown helper " + name);
|
||||
}
|
||||
|
||||
@@ -315,7 +329,7 @@ File.prototype.addHelper = function (name) {
|
||||
} else {
|
||||
var ref = util.template(name);
|
||||
ref._compact = true;
|
||||
var uid = this.generateUidIdentifier(name);
|
||||
var uid = this.scope.generateUidIdentifier(name);
|
||||
this.scope.push({
|
||||
key: name,
|
||||
id: uid,
|
||||
@@ -325,6 +339,10 @@ File.prototype.addHelper = function (name) {
|
||||
}
|
||||
};
|
||||
|
||||
File.prototype.logDeopt = function () {
|
||||
// todo, (node, msg)
|
||||
};
|
||||
|
||||
File.prototype.errorWithNode = function (node, msg, Error) {
|
||||
Error = Error || SyntaxError;
|
||||
|
||||
@@ -442,30 +460,3 @@ File.prototype.generate = function () {
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
File.prototype.generateUid = function (name, scope) {
|
||||
name = t.toIdentifier(name).replace(/^_+/, "");
|
||||
|
||||
scope = scope || this.scope;
|
||||
|
||||
var uid;
|
||||
var i = 0;
|
||||
do {
|
||||
uid = this._generateUid(name, i);
|
||||
i++;
|
||||
} while (scope.hasReference(uid));
|
||||
return uid;
|
||||
};
|
||||
|
||||
File.prototype.generateUidIdentifier = function (name, scope) {
|
||||
scope = scope || this.scope;
|
||||
var id = t.identifier(this.generateUid(name, scope));
|
||||
scope.addDeclarationToFunctionScope("var", id);
|
||||
return id;
|
||||
};
|
||||
|
||||
File.prototype._generateUid = function (name, i) {
|
||||
var id = name;
|
||||
if (i > 1) id += i;
|
||||
return "_" + id;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// jsx
|
||||
|
||||
var isString = require("lodash/lang/isString");
|
||||
var messages = require("../../messages");
|
||||
var esutils = require("esutils");
|
||||
var react = require("./react");
|
||||
var t = require("../../types");
|
||||
@@ -28,7 +29,7 @@ module.exports = function (exports, opts) {
|
||||
};
|
||||
|
||||
exports.JSXNamespacedName = function (node, parent, scope, file) {
|
||||
throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
|
||||
throw file.errorWithNode(node, messages.get("JSXNamespacedTags"));
|
||||
};
|
||||
|
||||
exports.JSXMemberExpression = {
|
||||
@@ -45,6 +46,11 @@ module.exports = function (exports, opts) {
|
||||
exports.JSXAttribute = {
|
||||
exit: function (node) {
|
||||
var value = node.value || t.literal(true);
|
||||
|
||||
if (t.isLiteral(value) && isString(value.value)) {
|
||||
value.value = value.value.replace(/\n\s+/g, " ");
|
||||
}
|
||||
|
||||
return t.inherits(t.property("init", node.name, value), node);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ var getObjRef = function (node, nodes, file, scope) {
|
||||
} else if (t.isMemberExpression(node)) {
|
||||
ref = node.object;
|
||||
|
||||
if (t.isIdentifier(ref) && scope.hasReference(ref.name)) {
|
||||
if (t.isIdentifier(ref) && scope.hasGlobal(ref.name)) {
|
||||
// the object reference that we need to save is locally declared
|
||||
// so as per the previous comment we can be 100% sure evaluating
|
||||
// it multiple times will be safe
|
||||
|
||||
@@ -13,7 +13,7 @@ var visitor = {
|
||||
|
||||
// check that we don't have a local variable declared as that removes the need
|
||||
// for the wrapper
|
||||
var localDeclar = scope.getBinding(state.id);
|
||||
var localDeclar = scope.getBindingIdentifier(state.id);
|
||||
if (localDeclar !== state.outerDeclar) return;
|
||||
|
||||
state.selfReference = true;
|
||||
@@ -31,7 +31,7 @@ exports.property = function (node, file, scope) {
|
||||
var state = {
|
||||
id: id,
|
||||
selfReference: false,
|
||||
outerDeclar: scope.getBinding(id),
|
||||
outerDeclar: scope.getBindingIdentifier(id),
|
||||
};
|
||||
|
||||
scope.traverse(node, visitor, state);
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
module.exports = ReplaceSupers;
|
||||
|
||||
var t = require("../../types");
|
||||
var messages = require("../../messages");
|
||||
var t = require("../../types");
|
||||
|
||||
/**
|
||||
* Description
|
||||
@@ -142,7 +143,7 @@ ReplaceSupers.prototype.getThisReference = function () {
|
||||
if (this.topLevelThisReference) {
|
||||
return this.topLevelThisReference;
|
||||
} else {
|
||||
var ref = this.topLevelThisReference = this.file.generateUidIdentifier("this");
|
||||
var ref = this.topLevelThisReference = this.scope.generateUidIdentifier("this");
|
||||
this.methodNode.value.body.body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(this.topLevelThisReference, t.thisExpression())
|
||||
]));
|
||||
@@ -232,7 +233,7 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
|
||||
var thisReference;
|
||||
|
||||
if (isIllegalBareSuper(node, parent)) {
|
||||
throw this.file.errorWithNode(node, "Illegal use of bare super");
|
||||
throw this.file.errorWithNode(node, messages.get("classesIllegalBareSuper"));
|
||||
}
|
||||
|
||||
if (t.isCallExpression(node)) {
|
||||
@@ -248,7 +249,7 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
|
||||
// - 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, "Direct super call is illegal in non-constructor, use super." + methodName + "() instead");
|
||||
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);
|
||||
|
||||
@@ -56,8 +56,9 @@ transform._ensureTransformerNames = function (type, rawKeys) {
|
||||
return keys;
|
||||
};
|
||||
|
||||
transform.transformers = object();
|
||||
transform.namespaces = object();
|
||||
transform.transformerNamespaces = object();
|
||||
transform.transformers = object();
|
||||
transform.namespaces = object();
|
||||
|
||||
transform.deprecatedTransformerMap = require("./transformers/deprecated");
|
||||
transform.moduleFormatters = require("./modules");
|
||||
@@ -66,8 +67,10 @@ var rawTransformers = require("./transformers");
|
||||
|
||||
each(rawTransformers, function (transformer, key) {
|
||||
var namespace = key.split(".")[0];
|
||||
|
||||
transform.namespaces[namespace] = transform.namespaces[namespace] || [];
|
||||
transform.namespaces[namespace].push(key);
|
||||
transform.transformerNamespaces[key] = namespace;
|
||||
|
||||
transform.transformers[key] = new Transformer(key, transformer);
|
||||
});
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
|
||||
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");
|
||||
var extend = require("lodash/object/extend");
|
||||
|
||||
function DefaultFormatter(file) {
|
||||
this.file = file;
|
||||
this.ids = object();
|
||||
this.scope = file.scope;
|
||||
this.file = file;
|
||||
this.ids = object();
|
||||
|
||||
this.hasNonDefaultExports = false;
|
||||
|
||||
@@ -124,13 +126,6 @@ DefaultFormatter.prototype.isLocalReference = function (node) {
|
||||
return t.isIdentifier(node) && localImports[node.name] && localImports[node.name] !== node;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.checkLocalReference = function (node) {
|
||||
var file = this.file;
|
||||
if (this.isLocalReference(node)) {
|
||||
throw file.errorWithNode(node, "Illegal assignment of module import");
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.remapExportAssignment = function (node) {
|
||||
return t.assignmentExpression(
|
||||
"=",
|
||||
@@ -146,7 +141,7 @@ DefaultFormatter.prototype.remapExportAssignment = function (node) {
|
||||
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
|
||||
var localExports = this.localExports;
|
||||
var name = node.name;
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBinding(name);
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBindingIdentifier(name);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getModuleName = function () {
|
||||
@@ -213,14 +208,11 @@ DefaultFormatter.prototype.getExternalReference = function (node, nodes) {
|
||||
|
||||
DefaultFormatter.prototype.checkExportIdentifier = function (node) {
|
||||
if (t.isIdentifier(node, { name: "__esModule" })) {
|
||||
throw this.file.errorWithNode(node, "Illegal export __esModule - this is used internally for CommonJS interop");
|
||||
throw this.file.errorWithNode(node, messages.get("modulesIllegalExportName", node.name));
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
|
||||
var inherits = false;
|
||||
if (node.specifiers.length === 1) inherits = node;
|
||||
|
||||
if (node.source) {
|
||||
var ref = this.getExternalReference(node, nodes);
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ module.exports = AMDFormatter;
|
||||
|
||||
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");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var values = require("lodash/object/values");
|
||||
|
||||
function AMDFormatter() {
|
||||
CommonFormatter.apply(this, arguments);
|
||||
@@ -70,7 +70,7 @@ AMDFormatter.prototype.getModuleName = function () {
|
||||
};
|
||||
|
||||
AMDFormatter.prototype._getExternalReference = function (node) {
|
||||
return this.file.generateUidIdentifier(node.source.value);
|
||||
return this.scope.generateUidIdentifier(node.source.value);
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.importDeclaration = function (node) {
|
||||
@@ -81,12 +81,12 @@ AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
var key = t.getSpecifierName(specifier);
|
||||
var ref = this.getExternalReference(node);
|
||||
|
||||
if (contains(this.file.dynamicImported, 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 (t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {
|
||||
} 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 {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
module.exports = CommonJSFormatter;
|
||||
|
||||
var DefaultFormatter = require("./_default");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var util = require("../../util");
|
||||
var t = require("../../types");
|
||||
|
||||
@@ -14,8 +14,13 @@ function CommonJSFormatter() {
|
||||
util.inherits(CommonJSFormatter, DefaultFormatter);
|
||||
|
||||
CommonJSFormatter.prototype.init = function () {
|
||||
var file = this.file;
|
||||
var scope = file.scope;
|
||||
|
||||
scope.rename("module");
|
||||
|
||||
if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
|
||||
this.file.ast.program.body.push(util.template("exports-module-declaration", true));
|
||||
file.ast.program.body.push(util.template("exports-module-declaration", true));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,8 +31,8 @@ CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes)
|
||||
|
||||
// import foo from "foo";
|
||||
if (t.isSpecifierDefault(specifier)) {
|
||||
if (!contains(this.file.dynamicImported, node)) {
|
||||
if (this.noInteropRequireImport) {
|
||||
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]);
|
||||
@@ -88,7 +93,7 @@ CommonJSFormatter.prototype._getExternalReference = function (node, nodes) {
|
||||
var call = t.callExpression(t.identifier("require"), [node.source]);
|
||||
|
||||
if (this.localImportOccurences[source] > 1) {
|
||||
var uid = this.file.generateUidIdentifier(source);
|
||||
var uid = this.scope.generateUidIdentifier(source);
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(uid, call)
|
||||
]));
|
||||
|
||||
@@ -12,7 +12,7 @@ var each = require("lodash/collection/each");
|
||||
var map = require("lodash/collection/map");
|
||||
|
||||
function SystemFormatter(file) {
|
||||
this.exportIdentifier = file.generateUidIdentifier("export");
|
||||
this.exportIdentifier = file.scope.generateUidIdentifier("export");
|
||||
this.noInteropRequireExport = true;
|
||||
this.noInteropRequireImport = true;
|
||||
|
||||
@@ -29,7 +29,7 @@ SystemFormatter.prototype._addImportSource = function (node, exportNode) {
|
||||
};
|
||||
|
||||
SystemFormatter.prototype.buildExportsWildcard = function (objectIdentifier, node) {
|
||||
var leftIdentifier = this.file.generateUidIdentifier("key");
|
||||
var leftIdentifier = this.scope.generateUidIdentifier("key");
|
||||
var valIdentifier = t.memberExpression(objectIdentifier, leftIdentifier, true);
|
||||
|
||||
var left = t.variableDeclaration("var", [
|
||||
|
||||
3
lib/6to5/transformation/templates/.6to5rc
Normal file
3
lib/6to5/transformation/templates/.6to5rc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"blacklist": ["useStrict"]
|
||||
}
|
||||
1
lib/6to5/transformation/templates/corejs-is-iterator.js
Normal file
1
lib/6to5/transformation/templates/corejs-is-iterator.js
Normal file
@@ -0,0 +1 @@
|
||||
CORE_ID.$for.isIterable(VALUE);
|
||||
@@ -1,7 +1,10 @@
|
||||
(function (obj, defaults) {
|
||||
for (var key in defaults) {
|
||||
if (obj[key] === undefined) {
|
||||
obj[key] = defaults[key];
|
||||
var keys = Object.getOwnPropertyNames(defaults);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var value = Object.getOwnPropertyDescriptor(defaults, key);
|
||||
if (value && value.configurable && obj[key] === undefined) {
|
||||
Object.defineProperty(obj, key, value);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
var helpers = exports.default = {};
|
||||
exports.__esModule = true;
|
||||
@@ -1,12 +1,14 @@
|
||||
(function (arr, i) {
|
||||
if (Array.isArray(arr)) {
|
||||
return arr;
|
||||
} else {
|
||||
} else if (Symbol.iterator in Object(arr)) {
|
||||
var _arr = [];
|
||||
for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
|
||||
_arr.push(_step.value);
|
||||
if (i && _arr.length === i) break;
|
||||
}
|
||||
return _arr;
|
||||
} else {
|
||||
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
{
|
||||
var ARGUMENTS_ID = arguments,
|
||||
THIS_ID = this,
|
||||
SHOULD_CONTINUE_ID,
|
||||
RESULT_ID;
|
||||
|
||||
do {
|
||||
SHOULD_CONTINUE_ID = false;
|
||||
RESULT_ID = FUNCTION.apply(THIS_ID, ARGUMENTS_ID);
|
||||
} while(SHOULD_CONTINUE_ID);
|
||||
|
||||
return RESULT_ID;
|
||||
FUNCTION_ID:while (true) BLOCK
|
||||
}
|
||||
|
||||
8
lib/6to5/transformation/templates/to-consumable-array.js
Normal file
8
lib/6to5/transformation/templates/to-consumable-array.js
Normal file
@@ -0,0 +1,8 @@
|
||||
(function (arr) {
|
||||
if (Array.isArray(arr)) {
|
||||
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
|
||||
return arr2;
|
||||
} else {
|
||||
return Array.from(arr);
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = TransformerPass;
|
||||
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
|
||||
/**
|
||||
* This class is responsible for traversing over the provided `File`s
|
||||
@@ -25,14 +25,14 @@ TransformerPass.prototype.canRun = function () {
|
||||
|
||||
// blacklist
|
||||
var blacklist = opts.blacklist;
|
||||
if (blacklist.length && contains(blacklist, key)) return false;
|
||||
if (blacklist.length && includes(blacklist, key)) return false;
|
||||
|
||||
// whitelist
|
||||
var whitelist = opts.whitelist;
|
||||
if (whitelist.length) return contains(whitelist, key);
|
||||
if (whitelist.length) return includes(whitelist, key);
|
||||
|
||||
// optional
|
||||
if (transformer.optional && !contains(opts.optional, key)) return false;
|
||||
if (transformer.optional && !includes(opts.optional, key)) return false;
|
||||
|
||||
// experimental
|
||||
if (transformer.experimental && !opts.experimental) return false;
|
||||
|
||||
@@ -55,6 +55,8 @@ Transformer.prototype.normalize = function (transformer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "enter" || type === "exit") return;
|
||||
|
||||
if (isFunction(fns)) fns = { enter: fns };
|
||||
|
||||
if (!isObject(fns)) return;
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
|
||||
function transformExpression(node, scope, state) {
|
||||
if (!node) return;
|
||||
|
||||
return (function subTransform(node) {
|
||||
switch (node.type) {
|
||||
case "ConditionalExpression":
|
||||
// any value of ternary operator can be final one
|
||||
subTransform(node.consequent);
|
||||
subTransform(node.alternate);
|
||||
break;
|
||||
|
||||
case "LogicalExpression":
|
||||
// only right expression can be final and so optimized
|
||||
subTransform(node.right);
|
||||
break;
|
||||
|
||||
case "SequenceExpression":
|
||||
// only last element of sequence can be optimized
|
||||
var seq = node.expressions;
|
||||
subTransform(seq[seq.length - 1]);
|
||||
break;
|
||||
|
||||
case "CallExpression":
|
||||
var callee = node.callee, thisBinding;
|
||||
var args = [callee];
|
||||
|
||||
// bind `this` to object in member expressions
|
||||
if (t.isMemberExpression(callee)) {
|
||||
var object = state.wrapSideEffect(callee.object);
|
||||
callee.object = object.expr;
|
||||
thisBinding = object.ref;
|
||||
}
|
||||
|
||||
if (node.arguments.length > 0 || thisBinding) {
|
||||
args.push(t.arrayExpression(node.arguments));
|
||||
}
|
||||
|
||||
if (thisBinding) {
|
||||
args.push(thisBinding);
|
||||
}
|
||||
|
||||
node.callee = state.getHelperRef();
|
||||
node.arguments = args;
|
||||
break;
|
||||
}
|
||||
})(node);
|
||||
}
|
||||
|
||||
var functionChildrenVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isReturnStatement(node)) {
|
||||
// prevent entrance by current visitor
|
||||
this.skip();
|
||||
// transform return argument into statement if
|
||||
// it contains tail recursion
|
||||
transformExpression(node.argument, scope, state);
|
||||
} else if (t.isFunction(node)) {
|
||||
// inner function's bodies are irrelevant
|
||||
this.skip();
|
||||
} else if (t.isTryStatement(parent)) {
|
||||
if (node === parent.block) {
|
||||
// `try`-blocks can't be optimized
|
||||
this.skip();
|
||||
} else if (parent.finalizer && node !== parent.finalizer) {
|
||||
// `catch` clause followed by `finally` can't be optimized
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var functionVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
// traverse all child nodes of this function and find `arguments` and `this`
|
||||
scope.traverse(node, functionChildrenVisitor, state);
|
||||
|
||||
return this.skip();
|
||||
}
|
||||
};
|
||||
|
||||
exports.FunctionDeclaration =
|
||||
exports.FunctionExpression = function (node, parent, scope, file) {
|
||||
var tempId, helperRef;
|
||||
|
||||
var state = {
|
||||
ownerId: node.id,
|
||||
|
||||
getHelperRef: function () {
|
||||
return helperRef = helperRef || file.addHelper("tail-call");
|
||||
},
|
||||
|
||||
wrapSideEffect: function (node) {
|
||||
if (t.isIdentifier(node) || t.isLiteral(node)) {
|
||||
return {expr: node, ref: node};
|
||||
}
|
||||
tempId = tempId || scope.generateUidIdentifier("temp");
|
||||
return {
|
||||
expr: t.assignmentExpression("=", tempId, node),
|
||||
ref: tempId
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// traverse the function and look for tail recursion
|
||||
scope.traverse(node, functionVisitor, state);
|
||||
|
||||
if (tempId) {
|
||||
t.ensureBlock(node).body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(tempId)
|
||||
]));
|
||||
}
|
||||
};
|
||||
@@ -10,7 +10,7 @@ var visitor = {
|
||||
if (!declared) return;
|
||||
|
||||
// declared node is different in this scope
|
||||
if (scope.getBinding(node.name) !== declared) return;
|
||||
if (scope.getBindingIdentifier(node.name) !== declared) return;
|
||||
|
||||
var assert = t.callExpression(
|
||||
state.file.addHelper("temporal-assert-defined"),
|
||||
|
||||
@@ -124,7 +124,7 @@ BlockScoping.prototype.run = function () {
|
||||
if (!this.hasLetReferences) return;
|
||||
|
||||
if (needsClosure) {
|
||||
this.needsClosure();
|
||||
this.wrapClosure();
|
||||
} else {
|
||||
this.remap();
|
||||
}
|
||||
@@ -136,7 +136,7 @@ function replace(node, parent, scope, remaps) {
|
||||
var remap = remaps[node.name];
|
||||
if (!remap) return;
|
||||
|
||||
var ownBinding = scope.getBinding(node.name);
|
||||
var ownBinding = scope.getBindingIdentifier(node.name);
|
||||
if (ownBinding === remap.binding) {
|
||||
node.name = remap.uid;
|
||||
} else {
|
||||
@@ -175,7 +175,7 @@ BlockScoping.prototype.remap = function () {
|
||||
// this is the defining identifier of a declaration
|
||||
var ref = letRefs[key];
|
||||
|
||||
if (scope.parentHasReference(key)) {
|
||||
if (scope.parentHasBinding(key) || scope.hasGlobal(key)) {
|
||||
var uid = scope.generateUidIdentifier(ref.name).name;
|
||||
ref.name = uid;
|
||||
|
||||
@@ -205,9 +205,28 @@ BlockScoping.prototype.remap = function () {
|
||||
* Description
|
||||
*/
|
||||
|
||||
BlockScoping.prototype.needsClosure = function () {
|
||||
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();
|
||||
@@ -216,7 +235,7 @@ BlockScoping.prototype.needsClosure = function () {
|
||||
this.hoistVarDeclarations();
|
||||
|
||||
// turn outsideLetReferences into an array
|
||||
var params = values(this.outsideLetReferences);
|
||||
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));
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
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");
|
||||
|
||||
exports.check = t.isClass;
|
||||
|
||||
exports.ClassDeclaration = function (node, parent, scope, file) {
|
||||
return new Class(node, file, scope, true).run();
|
||||
return new ClassTransformer(node, file, scope, true).run();
|
||||
};
|
||||
|
||||
exports.ClassExpression = function (node, parent, scope, file) {
|
||||
@@ -25,7 +26,7 @@ exports.ClassExpression = function (node, parent, scope, file) {
|
||||
}
|
||||
}
|
||||
|
||||
return new Class(node, file, scope, false).run();
|
||||
return new ClassTransformer(node, file, scope, false).run();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -34,10 +35,10 @@ exports.ClassExpression = function (node, parent, scope, file) {
|
||||
* @param {Node} node
|
||||
* @param {File} file
|
||||
* @param {Scope} scope
|
||||
* @param {Boolean} closure
|
||||
* @param {Boolean} isStatement
|
||||
*/
|
||||
|
||||
function Class(node, file, scope, isStatement) {
|
||||
function ClassTransformer(node, file, scope, isStatement) {
|
||||
this.isStatement = isStatement;
|
||||
this.scope = scope;
|
||||
this.node = node;
|
||||
@@ -61,7 +62,7 @@ function Class(node, file, scope, isStatement) {
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
Class.prototype.run = function () {
|
||||
ClassTransformer.prototype.run = function () {
|
||||
var superName = this.superName;
|
||||
var className = this.className;
|
||||
var file = this.file;
|
||||
@@ -98,8 +99,7 @@ Class.prototype.run = function () {
|
||||
closureArgs.push(superName);
|
||||
|
||||
if (!t.isIdentifier(superName)) {
|
||||
var superRef = this.scope.generateUidBasedOnNode(superName, this.file);
|
||||
superName = superRef;
|
||||
superName = this.scope.generateUidBasedOnNode(superName, this.file);
|
||||
}
|
||||
|
||||
closureParams.push(superName);
|
||||
@@ -138,7 +138,7 @@ Class.prototype.run = function () {
|
||||
* Description
|
||||
*/
|
||||
|
||||
Class.prototype.buildBody = function () {
|
||||
ClassTransformer.prototype.buildBody = function () {
|
||||
var constructor = this.constructor;
|
||||
var className = this.className;
|
||||
var superName = this.superName;
|
||||
@@ -167,6 +167,8 @@ Class.prototype.buildBody = function () {
|
||||
} else if (t.isPrivateDeclaration(node)) {
|
||||
this.closure = true;
|
||||
body.unshift(node);
|
||||
} else if (t.isClassProperty(node)) {
|
||||
this.pushProperty(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,12 +206,12 @@ Class.prototype.buildBody = function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Push a method to it's respective mutatorMap.
|
||||
* Push a method to its respective mutatorMap.
|
||||
*
|
||||
* @param {Node} node MethodDefinition
|
||||
*/
|
||||
|
||||
Class.prototype.pushMethod = function (node) {
|
||||
ClassTransformer.prototype.pushMethod = function (node) {
|
||||
var methodName = node.key;
|
||||
|
||||
var kind = node.kind;
|
||||
@@ -245,15 +247,39 @@ Class.prototype.pushMethod = function (node) {
|
||||
defineMap.push(mutatorMap, methodName, "enumerable", node.computed, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} node
|
||||
*/
|
||||
|
||||
ClassTransformer.prototype.pushProperty = function (node) {
|
||||
if (!node.value) return;
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
Class.prototype.pushConstructor = function (method) {
|
||||
ClassTransformer.prototype.pushConstructor = function (method) {
|
||||
if (method.kind) {
|
||||
throw this.file.errorWithNode(method, "illegal kind for constructor method");
|
||||
throw this.file.errorWithNode(method, messages.get("classesIllegalConstructorKind"));
|
||||
}
|
||||
|
||||
var construct = this.constructor;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = function (node) {
|
||||
return t.isVariableDeclaration(node, { kind: "const" });
|
||||
@@ -11,33 +12,35 @@ var visitor = {
|
||||
if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
|
||||
for (var key in ids) {
|
||||
var id = ids[key];
|
||||
for (var name in ids) {
|
||||
var id = ids[name];
|
||||
|
||||
var constant = state.constants[key];
|
||||
var constant = state.constants[name];
|
||||
|
||||
// no constant exists
|
||||
if (!constant) continue;
|
||||
|
||||
var constantIdentifier = constant.identifier;
|
||||
|
||||
// check if the assignment id matches the constant declaration id
|
||||
// if it does then it was the id used to initially declare the
|
||||
// constant so we can just ignore it
|
||||
if (id === constant) continue;
|
||||
if (id === constantIdentifier) continue;
|
||||
|
||||
// check if there's been a local binding that shadows this constant
|
||||
if (!scope.bindingEquals(key, constant)) continue;
|
||||
if (!scope.bindingIdentifierEquals(name, constantIdentifier)) continue;
|
||||
|
||||
throw state.file.errorWithNode(id, key + " is read-only");
|
||||
throw state.file.errorWithNode(id, messages.get("readOnly", name));
|
||||
}
|
||||
} else if (t.isScope(node)) {
|
||||
} else if (t.isScope(node, parent)) {
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.Scope = function (node, parent, scope, file) {
|
||||
exports.Scopable = function (node, parent, scope, file) {
|
||||
scope.traverse(node, visitor, {
|
||||
constants: scope.getAllDeclarationsOfKind("const"),
|
||||
constants: scope.getAllBindingsOfKind("const"),
|
||||
file: file
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isPattern;
|
||||
|
||||
function Destructuring(opts) {
|
||||
function DestructuringTransformer(opts) {
|
||||
this.blockHoist = opts.blockHoist;
|
||||
this.operator = opts.operator;
|
||||
this.nodes = opts.nodes;
|
||||
@@ -13,7 +14,7 @@ function Destructuring(opts) {
|
||||
this.kind = opts.kind;
|
||||
}
|
||||
|
||||
Destructuring.prototype.buildVariableAssignment = function (id, init) {
|
||||
DestructuringTransformer.prototype.buildVariableAssignment = function (id, init) {
|
||||
var op = this.operator;
|
||||
if (t.isMemberExpression(id)) op = "=";
|
||||
|
||||
@@ -32,7 +33,7 @@ Destructuring.prototype.buildVariableAssignment = function (id, init) {
|
||||
return node;
|
||||
};
|
||||
|
||||
Destructuring.prototype.buildVariableDeclaration = function (id, init) {
|
||||
DestructuringTransformer.prototype.buildVariableDeclaration = function (id, init) {
|
||||
var declar = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(id, init)
|
||||
]);
|
||||
@@ -40,7 +41,7 @@ Destructuring.prototype.buildVariableDeclaration = function (id, init) {
|
||||
return declar;
|
||||
};
|
||||
|
||||
Destructuring.prototype.push = function (elem, parentId) {
|
||||
DestructuringTransformer.prototype.push = function (elem, parentId) {
|
||||
if (t.isObjectPattern(elem)) {
|
||||
this.pushObjectPattern(elem, parentId);
|
||||
} else if (t.isArrayPattern(elem)) {
|
||||
@@ -52,7 +53,7 @@ Destructuring.prototype.push = function (elem, parentId) {
|
||||
}
|
||||
};
|
||||
|
||||
Destructuring.prototype.pushAssignmentPattern = function (pattern, parentId) {
|
||||
DestructuringTransformer.prototype.pushAssignmentPattern = function (pattern, parentId) {
|
||||
var tempParentId = this.scope.generateUidBasedOnNode(parentId);
|
||||
|
||||
var declar = t.variableDeclaration("var", [
|
||||
@@ -71,7 +72,7 @@ Destructuring.prototype.pushAssignmentPattern = function (pattern, parentId) {
|
||||
));
|
||||
};
|
||||
|
||||
Destructuring.prototype.pushObjectSpread = function (pattern, parentId, prop, i) {
|
||||
DestructuringTransformer.prototype.pushObjectSpread = function (pattern, parentId, prop, i) {
|
||||
// get all the keys that appear in this object before the current spread
|
||||
var keys = [];
|
||||
for (var i2 = 0; i2 < pattern.properties.length; i2++) {
|
||||
@@ -92,7 +93,7 @@ Destructuring.prototype.pushObjectSpread = function (pattern, parentId, prop, i)
|
||||
this.nodes.push(this.buildVariableAssignment(prop.argument, value));
|
||||
};
|
||||
|
||||
Destructuring.prototype.pushObjectProperty = function (prop, parentId) {
|
||||
DestructuringTransformer.prototype.pushObjectProperty = function (prop, parentId) {
|
||||
if (t.isLiteral(prop.key)) prop.computed = true;
|
||||
|
||||
var pattern2 = prop.value;
|
||||
@@ -105,7 +106,7 @@ Destructuring.prototype.pushObjectProperty = function (prop, parentId) {
|
||||
}
|
||||
};
|
||||
|
||||
Destructuring.prototype.pushObjectPattern = function (pattern, parentId) {
|
||||
DestructuringTransformer.prototype.pushObjectPattern = function (pattern, parentId) {
|
||||
if (!pattern.properties.length) {
|
||||
this.nodes.push(t.expressionStatement(
|
||||
t.callExpression(this.file.addHelper("object-destructuring-empty"), [parentId])
|
||||
@@ -137,18 +138,20 @@ var hasRest = function (pattern) {
|
||||
return false;
|
||||
};
|
||||
|
||||
Destructuring.prototype.pushArrayPattern = function (pattern, parentId) {
|
||||
DestructuringTransformer.prototype.pushArrayPattern = function (pattern, parentId) {
|
||||
if (!pattern.elements) return;
|
||||
|
||||
// if we have a rest then we need all the elements
|
||||
var count = !hasRest(pattern) && pattern.elements.length;
|
||||
|
||||
var toArray = this.file.toArray(parentId, count);
|
||||
var toArray = this.scope.toArray(parentId, count);
|
||||
|
||||
var _parentId = this.scope.generateUidBasedOnNode(parentId, this.file);
|
||||
var _parentId = this.scope.generateUidBasedOnNode(parentId);
|
||||
this.nodes.push(this.buildVariableDeclaration(_parentId, toArray));
|
||||
parentId = _parentId;
|
||||
|
||||
this.scope.assignTypeGeneric(parentId.name, "Array");
|
||||
|
||||
for (var i = 0; i < pattern.elements.length; i++) {
|
||||
var elem = pattern.elements[i];
|
||||
|
||||
@@ -158,7 +161,7 @@ Destructuring.prototype.pushArrayPattern = function (pattern, parentId) {
|
||||
var newPatternId;
|
||||
|
||||
if (t.isRestElement(elem)) {
|
||||
newPatternId = this.file.toArray(parentId);
|
||||
newPatternId = this.scope.toArray(parentId);
|
||||
|
||||
if (i > 0) {
|
||||
newPatternId = t.callExpression(t.memberExpression(newPatternId, t.identifier("slice")), [t.literal(i)]);
|
||||
@@ -173,7 +176,7 @@ Destructuring.prototype.pushArrayPattern = function (pattern, parentId) {
|
||||
}
|
||||
};
|
||||
|
||||
Destructuring.prototype.init = function (pattern, parentId) {
|
||||
DestructuringTransformer.prototype.init = function (pattern, parentId) {
|
||||
if (!t.isArrayExpression(parentId) && !t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) {
|
||||
var key = this.scope.generateUidBasedOnNode(parentId);
|
||||
this.nodes.push(this.buildVariableDeclaration(key, parentId));
|
||||
@@ -217,7 +220,7 @@ exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
|
||||
var nodes = [];
|
||||
|
||||
var destructuring = new Destructuring({
|
||||
var destructuring = new DestructuringTransformer({
|
||||
kind: left.kind,
|
||||
file: file,
|
||||
scope: scope,
|
||||
@@ -235,15 +238,15 @@ exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
exports.Function = function (node, parent, scope, file) {
|
||||
var nodes = [];
|
||||
|
||||
var hasDestructuring = false;
|
||||
var hasDestructuringTransformer = false;
|
||||
|
||||
node.params = node.params.map(function (pattern, i) {
|
||||
if (!t.isPattern(pattern)) return pattern;
|
||||
|
||||
hasDestructuring = true;
|
||||
hasDestructuringTransformer = true;
|
||||
var parentId = scope.generateUidIdentifier("ref");
|
||||
|
||||
var destructuring = new Destructuring({
|
||||
var destructuring = new DestructuringTransformer({
|
||||
blockHoist: node.params.length - i,
|
||||
nodes: nodes,
|
||||
scope: scope,
|
||||
@@ -255,7 +258,7 @@ exports.Function = function (node, parent, scope, file) {
|
||||
return parentId;
|
||||
});
|
||||
|
||||
if (!hasDestructuring) return;
|
||||
if (!hasDestructuringTransformer) return;
|
||||
|
||||
t.ensureBlock(node);
|
||||
|
||||
@@ -272,7 +275,7 @@ exports.CatchClause = function (node, parent, scope, file) {
|
||||
|
||||
var nodes = [];
|
||||
|
||||
var destructuring = new Destructuring({
|
||||
var destructuring = new DestructuringTransformer({
|
||||
kind: "let",
|
||||
file: file,
|
||||
scope: scope,
|
||||
@@ -298,7 +301,7 @@ exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
t.variableDeclarator(ref, expr.right)
|
||||
]));
|
||||
|
||||
var destructuring = new Destructuring({
|
||||
var destructuring = new DestructuringTransformer({
|
||||
operator: expr.operator,
|
||||
file: file,
|
||||
scope: scope,
|
||||
@@ -321,7 +324,7 @@ exports.AssignmentExpression = function (node, parent, scope, file) {
|
||||
var nodes = [];
|
||||
nodes.push(t.assignmentExpression("=", ref, node.right));
|
||||
|
||||
var destructuring = new Destructuring({
|
||||
var destructuring = new DestructuringTransformer({
|
||||
operator: node.operator,
|
||||
file: file,
|
||||
scope: scope,
|
||||
@@ -356,7 +359,7 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
var patternId = declar.init;
|
||||
var pattern = declar.id;
|
||||
|
||||
var destructuring = new Destructuring({
|
||||
var destructuring = new DestructuringTransformer({
|
||||
nodes: nodes,
|
||||
scope: scope,
|
||||
kind: node.kind,
|
||||
@@ -387,7 +390,7 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
|
||||
declar = declar || t.variableDeclaration(node.kind, []);
|
||||
|
||||
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
|
||||
throw file.errorWithNode(node, "Cannot use this node within the current parent");
|
||||
throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
|
||||
}
|
||||
|
||||
declar.declarations = declar.declarations.concat(node.declarations);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
var messages = require("../../../messages");
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isForOfStatement;
|
||||
|
||||
@@ -17,7 +18,7 @@ exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
// inherit comments from the original loop
|
||||
t.inheritsComments(loop, node);
|
||||
|
||||
// ensure that it's a block so we can take all it's statemetns
|
||||
// ensure that it's a block so we can take all its statements
|
||||
t.ensureBlock(node);
|
||||
|
||||
// add the value declaration to the new loop body
|
||||
@@ -50,7 +51,7 @@ var loose = function (node, parent, scope, file) {
|
||||
t.variableDeclarator(left.declarations[0].id, id)
|
||||
]);
|
||||
} else {
|
||||
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
|
||||
throw file.errorWithNode(left, messages.get("unknownForHead", left.type));
|
||||
}
|
||||
|
||||
var loop = util.template("for-of-loose", {
|
||||
@@ -89,7 +90,7 @@ var spec = function (node, parent, scope, file) {
|
||||
t.variableDeclarator(left.declarations[0].id, stepValue)
|
||||
]);
|
||||
} else {
|
||||
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
|
||||
throw file.errorWithNode(left, messages.get("unknownForHead", left.type));
|
||||
}
|
||||
|
||||
var loop = util.template("for-of", {
|
||||
|
||||
@@ -18,7 +18,7 @@ var iifeVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (!t.isReferencedIdentifier(node, parent)) return;
|
||||
if (!state.scope.hasOwnBinding(node.name)) return;
|
||||
if (state.scope.bindingEquals(node.name, node)) return;
|
||||
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
|
||||
|
||||
state.iife = true;
|
||||
this.stop();
|
||||
@@ -55,7 +55,9 @@ exports.Function = function (node, parent, scope, file) {
|
||||
var param = node.params[i];
|
||||
|
||||
if (!t.isAssignmentPattern(param)) {
|
||||
lastNonDefaultParam = i + 1;
|
||||
if (!t.isRestElement(param)) {
|
||||
lastNonDefaultParam = i + 1;
|
||||
}
|
||||
|
||||
if (!t.isIdentifier(param)) {
|
||||
scope.traverse(param, iifeVisitor, state);
|
||||
@@ -71,10 +73,12 @@ exports.Function = function (node, parent, scope, file) {
|
||||
var left = param.left;
|
||||
var right = param.right;
|
||||
|
||||
node.params[i] = scope.generateUidIdentifier("x");
|
||||
var placeholder = scope.generateUidIdentifier("x");
|
||||
placeholder._isDefaultPlaceholder = true;
|
||||
node.params[i] = placeholder;
|
||||
|
||||
if (!state.iife) {
|
||||
if (t.isIdentifier(right) && scope.hasOwnReference(right.name)) {
|
||||
if (t.isIdentifier(right) && scope.hasOwnBinding(right.name)) {
|
||||
state.iife = true;
|
||||
} else {
|
||||
scope.traverse(right, iifeVisitor, state);
|
||||
|
||||
@@ -60,6 +60,8 @@ exports.Function = function (node, parent, scope) {
|
||||
node.body.body.unshift(restDeclar);
|
||||
}
|
||||
|
||||
scope.assignTypeGeneric(rest.name, "Array");
|
||||
|
||||
var loop = util.template("rest", {
|
||||
ARGUMENTS: argsId,
|
||||
ARRAY_KEY: arrKey,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isSpreadElement;
|
||||
|
||||
var getSpreadLiteral = function (spread, file) {
|
||||
return file.toArray(spread.argument);
|
||||
var getSpreadLiteral = function (spread, scope) {
|
||||
return scope.toArray(spread.argument, true);
|
||||
};
|
||||
|
||||
var hasSpread = function (nodes) {
|
||||
@@ -18,7 +18,7 @@ var hasSpread = function (nodes) {
|
||||
return false;
|
||||
};
|
||||
|
||||
var build = function (props, file) {
|
||||
var build = function (props, scope) {
|
||||
var nodes = [];
|
||||
|
||||
var _props = [];
|
||||
@@ -33,7 +33,7 @@ var build = function (props, file) {
|
||||
var prop = props[i];
|
||||
if (t.isSpreadElement(prop)) {
|
||||
push();
|
||||
nodes.push(getSpreadLiteral(prop, file));
|
||||
nodes.push(getSpreadLiteral(prop, scope));
|
||||
} else {
|
||||
_props.push(prop);
|
||||
}
|
||||
@@ -44,11 +44,11 @@ var build = function (props, file) {
|
||||
return nodes;
|
||||
};
|
||||
|
||||
exports.ArrayExpression = function (node, parent, scope, file) {
|
||||
exports.ArrayExpression = function (node, parent, scope) {
|
||||
var elements = node.elements;
|
||||
if (!hasSpread(elements)) return;
|
||||
|
||||
var nodes = build(elements, file);
|
||||
var nodes = build(elements, scope);
|
||||
var first = nodes.shift();
|
||||
|
||||
if (!t.isArrayExpression(first)) {
|
||||
@@ -59,7 +59,7 @@ exports.ArrayExpression = function (node, parent, scope, file) {
|
||||
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
|
||||
};
|
||||
|
||||
exports.CallExpression = function (node, parent, scope, file) {
|
||||
exports.CallExpression = function (node, parent, scope) {
|
||||
var args = node.arguments;
|
||||
if (!hasSpread(args)) return;
|
||||
|
||||
@@ -71,7 +71,7 @@ exports.CallExpression = function (node, parent, scope, file) {
|
||||
if (args.length === 1 && args[0].argument.name === "arguments") {
|
||||
nodes = [args[0].argument];
|
||||
} else {
|
||||
nodes = build(args, file);
|
||||
nodes = build(args, scope);
|
||||
}
|
||||
|
||||
var first = nodes.shift();
|
||||
@@ -103,9 +103,9 @@ exports.NewExpression = function (node, parent, scope, file) {
|
||||
var args = node.arguments;
|
||||
if (!hasSpread(args)) return;
|
||||
|
||||
var nativeType = t.isIdentifier(node.callee) && contains(t.NATIVE_TYPE_NAMES, node.callee.name);
|
||||
var nativeType = t.isIdentifier(node.callee) && includes(t.NATIVE_TYPE_NAMES, node.callee.name);
|
||||
|
||||
var nodes = build(args, file);
|
||||
var nodes = build(args, scope);
|
||||
|
||||
if (nativeType) {
|
||||
nodes.unshift(t.arrayExpression([t.literal(null)]));
|
||||
|
||||
@@ -1,207 +1,367 @@
|
||||
"use strict";
|
||||
|
||||
var util = require("../../../util");
|
||||
var t = require("../../../types");
|
||||
var reduceRight = require("lodash/collection/reduceRight");
|
||||
var messages = require("../../../messages");
|
||||
var flatten = require("lodash/array/flatten");
|
||||
var util = require("../../../util");
|
||||
var map = require("lodash/collection/map");
|
||||
var t = require("../../../types");
|
||||
|
||||
function returnBlock(expr) {
|
||||
return t.blockStatement([t.returnStatement(expr)]);
|
||||
}
|
||||
|
||||
function transformExpression(node, scope, state) {
|
||||
if (!node) return;
|
||||
function TailCallTransformer(node, scope, file) {
|
||||
this.hasTailRecursion = false;
|
||||
this.needsArguments = false;
|
||||
this.setsArguments = false;
|
||||
this.needsThis = false;
|
||||
this.ownerId = node.id;
|
||||
this.vars = [];
|
||||
|
||||
return (function subTransform(node) {
|
||||
switch (node.type) {
|
||||
case "ConditionalExpression":
|
||||
var callConsequent = subTransform(node.consequent);
|
||||
var callAlternate = subTransform(node.alternate);
|
||||
if (!callConsequent && !callAlternate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if ternary operator had tail recursion in value, convert to optimized if-statement
|
||||
node.type = "IfStatement";
|
||||
node.consequent = callConsequent ? t.toBlock(callConsequent) : returnBlock(node.consequent);
|
||||
if (callAlternate) {
|
||||
node.alternate = t.isIfStatement(callAlternate) ? callAlternate : t.toBlock(callAlternate);
|
||||
} else {
|
||||
node.alternate = returnBlock(node.alternate);
|
||||
}
|
||||
return node;
|
||||
|
||||
case "LogicalExpression":
|
||||
// only call in right-value of can be optimized
|
||||
var callRight = subTransform(node.right);
|
||||
if (!callRight) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cache left value as it might have side-effects
|
||||
var leftId = state.getLeftId();
|
||||
var testExpr = t.assignmentExpression(
|
||||
"=",
|
||||
leftId,
|
||||
node.left
|
||||
);
|
||||
if (node.operator === "&&") {
|
||||
testExpr = t.unaryExpression("!", testExpr);
|
||||
}
|
||||
return [t.ifStatement(testExpr, returnBlock(leftId))].concat(callRight);
|
||||
|
||||
case "SequenceExpression":
|
||||
var seq = node.expressions;
|
||||
|
||||
// only last element can be optimized
|
||||
var lastCall = subTransform(seq[seq.length - 1]);
|
||||
if (!lastCall) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove converted expression from sequence
|
||||
// and convert to regular expression if needed
|
||||
if (--seq.length === 1) {
|
||||
node = seq[0];
|
||||
}
|
||||
|
||||
return [t.expressionStatement(node)].concat(lastCall);
|
||||
|
||||
case "CallExpression":
|
||||
var callee = node.callee, prop, thisBinding, args;
|
||||
|
||||
if (t.isMemberExpression(callee, { computed: false }) &&
|
||||
t.isIdentifier(prop = callee.property)) {
|
||||
switch (prop.name) {
|
||||
case "call":
|
||||
args = t.arrayExpression(node.arguments.slice(1));
|
||||
break;
|
||||
|
||||
case "apply":
|
||||
args = node.arguments[1] || t.identifier("undefined");
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
thisBinding = node.arguments[0];
|
||||
callee = callee.object;
|
||||
}
|
||||
|
||||
// only tail recursion can be optimized as for now
|
||||
if (!t.isIdentifier(callee) || !scope.bindingEquals(callee.name, state.ownerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.hasTailRecursion = true;
|
||||
|
||||
return [
|
||||
t.expressionStatement(t.assignmentExpression(
|
||||
"=",
|
||||
state.getArgumentsId(),
|
||||
args || t.arrayExpression(node.arguments)
|
||||
)),
|
||||
|
||||
t.expressionStatement(t.assignmentExpression(
|
||||
"=",
|
||||
state.getThisId(),
|
||||
thisBinding || t.identifier("undefined")
|
||||
)),
|
||||
|
||||
t.returnStatement(t.assignmentExpression(
|
||||
"=",
|
||||
state.getShouldContinueId(),
|
||||
t.literal(true)
|
||||
))
|
||||
];
|
||||
}
|
||||
})(node);
|
||||
this.scope = scope;
|
||||
this.file = file;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
var functionChildrenVisitor = {
|
||||
TailCallTransformer.prototype.getArgumentsId = function () {
|
||||
return this.argumentsId = this.argumentsId || this.scope.generateUidIdentifier("arguments");
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.getThisId = function () {
|
||||
return this.thisId = this.thisId || this.scope.generateUidIdentifier("this");
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.getLeftId = function () {
|
||||
return this.leftId = this.leftId || this.scope.generateUidIdentifier("left");
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.getFunctionId = function () {
|
||||
return this.functionId = this.functionId || this.scope.generateUidIdentifier("function");
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.getParams = function () {
|
||||
var params = this.params;
|
||||
|
||||
if (!params) {
|
||||
params = this.node.params;
|
||||
this.paramDecls = [];
|
||||
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var param = params[i];
|
||||
if (!param._isDefaultPlaceholder) {
|
||||
this.paramDecls.push(t.variableDeclarator(
|
||||
param,
|
||||
params[i] = this.scope.generateUidIdentifier("x")
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.params = params;
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.hasDeopt = function () {
|
||||
// check if the ownerId has been reassigned, if it has then it's not safe to
|
||||
// perform optimisations
|
||||
var ownerIdInfo = this.scope.getBindingInfo(this.ownerId.name);
|
||||
return ownerIdInfo && ownerIdInfo.reassigned;
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.run = function () {
|
||||
var scope = this.scope;
|
||||
var node = this.node;
|
||||
|
||||
// only tail recursion can be optimized as for now, so we can skip anonymous
|
||||
// functions entirely
|
||||
var ownerId = this.ownerId;
|
||||
if (!ownerId) return;
|
||||
|
||||
// traverse the function and look for tail recursion
|
||||
scope.traverse(node, firstPass, this);
|
||||
|
||||
if (!this.hasTailRecursion) return;
|
||||
|
||||
if (this.hasDeopt()) {
|
||||
this.file.logDeopt(node, messages.get("tailCallReassignmentDeopt"));
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
scope.traverse(node, secondPass, this);
|
||||
|
||||
if (!this.needsThis || !this.needsArguments) {
|
||||
scope.traverse(node, thirdPass, this);
|
||||
}
|
||||
|
||||
var body = t.ensureBlock(node).body;
|
||||
|
||||
if (this.vars.length > 0) {
|
||||
var declarations = flatten(map(this.vars, function (decl) {
|
||||
return decl.declarations;
|
||||
}, this));
|
||||
var statement = reduceRight(declarations, function (expr, decl) {
|
||||
return t.assignmentExpression("=", decl.id, expr);
|
||||
}, t.identifier("undefined"));
|
||||
body.unshift(t.expressionStatement(statement));
|
||||
}
|
||||
|
||||
var paramDecls = this.paramDecls;
|
||||
if (paramDecls.length > 0) {
|
||||
body.unshift(t.variableDeclaration("var", paramDecls));
|
||||
}
|
||||
|
||||
node.body = util.template("tail-call-body", {
|
||||
THIS_ID: this.thisId,
|
||||
ARGUMENTS_ID: this.argumentsId,
|
||||
FUNCTION_ID: this.getFunctionId(),
|
||||
BLOCK: node.body
|
||||
});
|
||||
|
||||
var topVars = [];
|
||||
|
||||
if (this.needsThis) {
|
||||
topVars.push(t.variableDeclarator(this.getThisId(), t.thisExpression()));
|
||||
}
|
||||
|
||||
if (this.needsArguments || this.setsArguments) {
|
||||
var decl = t.variableDeclarator(this.getArgumentsId());
|
||||
if (this.needsArguments) {
|
||||
decl.init = t.identifier("arguments");
|
||||
}
|
||||
topVars.push(decl);
|
||||
}
|
||||
|
||||
var leftId = this.leftId;
|
||||
if (leftId) {
|
||||
topVars.push(t.variableDeclarator(leftId));
|
||||
}
|
||||
|
||||
if (topVars.length > 0) {
|
||||
node.body.body.unshift(t.variableDeclaration("var", topVars));
|
||||
}
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.subTransform = function (node) {
|
||||
if (!node) return;
|
||||
|
||||
var handler = this["subTransform" + node.type];
|
||||
if (handler) return handler.call(this, node);
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.subTransformConditionalExpression = function (node) {
|
||||
var callConsequent = this.subTransform(node.consequent);
|
||||
var callAlternate = this.subTransform(node.alternate);
|
||||
if (!callConsequent && !callAlternate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if ternary operator had tail recursion in value, convert to optimized if-statement
|
||||
node.type = "IfStatement";
|
||||
node.consequent = callConsequent ? t.toBlock(callConsequent) : returnBlock(node.consequent);
|
||||
|
||||
if (callAlternate) {
|
||||
node.alternate = t.isIfStatement(callAlternate) ? callAlternate : t.toBlock(callAlternate);
|
||||
} else {
|
||||
node.alternate = returnBlock(node.alternate);
|
||||
}
|
||||
|
||||
return [node];
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.subTransformLogicalExpression = function (node) {
|
||||
// only call in right-value of can be optimized
|
||||
var callRight = this.subTransform(node.right);
|
||||
if (!callRight) return;
|
||||
|
||||
// cache left value as it might have side-effects
|
||||
var leftId = this.getLeftId();
|
||||
var testExpr = t.assignmentExpression(
|
||||
"=",
|
||||
leftId,
|
||||
node.left
|
||||
);
|
||||
|
||||
if (node.operator === "&&") {
|
||||
testExpr = t.unaryExpression("!", testExpr);
|
||||
}
|
||||
|
||||
return [t.ifStatement(testExpr, returnBlock(leftId))].concat(callRight);
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.subTransformSequenceExpression = function (node) {
|
||||
var seq = node.expressions;
|
||||
|
||||
// only last element can be optimized
|
||||
var lastCall = this.subTransform(seq[seq.length - 1]);
|
||||
if (!lastCall) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove converted expression from sequence
|
||||
// and convert to regular expression if needed
|
||||
if (--seq.length === 1) {
|
||||
node = seq[0];
|
||||
}
|
||||
|
||||
return [t.expressionStatement(node)].concat(lastCall);
|
||||
};
|
||||
|
||||
TailCallTransformer.prototype.subTransformCallExpression = function (node) {
|
||||
var callee = node.callee, thisBinding, args;
|
||||
|
||||
if (t.isMemberExpression(callee, { computed: false }) && t.isIdentifier(callee.property)) {
|
||||
switch (callee.property.name) {
|
||||
case "call":
|
||||
args = t.arrayExpression(node.arguments.slice(1));
|
||||
break;
|
||||
|
||||
case "apply":
|
||||
args = node.arguments[1] || t.identifier("undefined");
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
thisBinding = node.arguments[0];
|
||||
callee = callee.object;
|
||||
}
|
||||
|
||||
// only tail recursion can be optimized as for now
|
||||
if (!t.isIdentifier(callee) || !this.scope.bindingIdentifierEquals(callee.name, this.ownerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hasTailRecursion = true;
|
||||
|
||||
if (this.hasDeopt()) return;
|
||||
|
||||
var body = [];
|
||||
|
||||
if (!t.isThisExpression(thisBinding)) {
|
||||
body.push(t.expressionStatement(t.assignmentExpression(
|
||||
"=",
|
||||
this.getThisId(),
|
||||
thisBinding || t.identifier("undefined")
|
||||
)));
|
||||
}
|
||||
|
||||
if (!args) {
|
||||
args = t.arrayExpression(node.arguments);
|
||||
}
|
||||
|
||||
var argumentsId = this.getArgumentsId();
|
||||
var params = this.getParams();
|
||||
|
||||
body.push(t.expressionStatement(t.assignmentExpression(
|
||||
"=",
|
||||
argumentsId,
|
||||
args
|
||||
)));
|
||||
|
||||
var i, param;
|
||||
|
||||
if (t.isArrayExpression(args)) {
|
||||
var elems = args.elements;
|
||||
for (i = 0; i < elems.length && i < params.length; i++) {
|
||||
param = params[i];
|
||||
var elem = elems[i] || (elems[i] = t.identifier("undefined"));
|
||||
if (!param._isDefaultPlaceholder) {
|
||||
elems[i] = t.assignmentExpression("=", param, elem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.setsArguments = true;
|
||||
for (i = 0; i < params.length; i++) {
|
||||
param = params[i];
|
||||
if (!param._isDefaultPlaceholder) {
|
||||
body.push(t.expressionStatement(t.assignmentExpression(
|
||||
"=",
|
||||
param,
|
||||
t.memberExpression(argumentsId, t.literal(i), true)
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.push(t.continueStatement(this.getFunctionId()));
|
||||
|
||||
return body;
|
||||
};
|
||||
|
||||
// looks for and replaces tail recursion calls
|
||||
var firstPass = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isReturnStatement(node)) {
|
||||
// prevent entrance by current visitor
|
||||
if (t.isIfStatement(node)) {
|
||||
if (t.isReturnStatement(node.alternate)) {
|
||||
t.ensureBlock(node, "alternate");
|
||||
}
|
||||
|
||||
if (t.isReturnStatement(node.consequent)) {
|
||||
t.ensureBlock(node, "consequent");
|
||||
}
|
||||
} else if (t.isReturnStatement(node)) {
|
||||
this.skip();
|
||||
// transform return argument into statement if
|
||||
// it contains tail recursion
|
||||
return transformExpression(node.argument, scope, state);
|
||||
} else if (t.isFunction(node)) {
|
||||
return this.skip();
|
||||
return state.subTransform(node.argument);
|
||||
} else if (t.isTryStatement(parent)) {
|
||||
if (node === parent.block) {
|
||||
return this.skip();
|
||||
} else if (node === parent.finalizer) {
|
||||
return;
|
||||
} else {
|
||||
if (parent.finalizer) {
|
||||
this.skip();
|
||||
}
|
||||
return;
|
||||
this.skip();
|
||||
} else if (parent.finalizer && node !== parent.finalizer) {
|
||||
this.skip();
|
||||
}
|
||||
} else if (t.isFunction(node)) {
|
||||
this.skip();
|
||||
} else if (t.isVariableDeclaration(node)) {
|
||||
this.skip();
|
||||
state.vars.push(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// hoists up function declarations, replaces `this` and `arguments` and marks
|
||||
// them as needed
|
||||
var secondPass = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isThisExpression(node)) {
|
||||
state.needsThis = true;
|
||||
return state.getThisId();
|
||||
} else if (t.isReferencedIdentifier(node, parent, { name: "arguments" })) {
|
||||
state.needsArguments = true;
|
||||
return state.getArgumentsId();
|
||||
} else if (t.isFunction(node)) {
|
||||
this.skip();
|
||||
if (t.isFunctionDeclaration(node)) {
|
||||
node = t.variableDeclaration("var", [
|
||||
t.variableDeclarator(node.id, t.toExpression(node))
|
||||
]);
|
||||
node._blockHoist = 2;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var functionVisitor = {
|
||||
// optimizes recursion by removing `this` and `arguments` if they aren't used
|
||||
var thirdPass = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
// traverse all child nodes of this function and find `arguments` and `this`
|
||||
scope.traverse(node, functionChildrenVisitor, state);
|
||||
if (!t.isExpressionStatement(node)) return;
|
||||
|
||||
return this.skip();
|
||||
}
|
||||
};
|
||||
var expr = node.expression;
|
||||
if (!t.isAssignmentExpression(expr)) return;
|
||||
|
||||
exports.FunctionDeclaration =
|
||||
exports.FunctionExpression = function (node, parent, scope) {
|
||||
// only tail recursion can be optimized as for now,
|
||||
// so we can skip anonymous functions entirely
|
||||
var ownerId = node.id;
|
||||
if (!ownerId) return;
|
||||
|
||||
var argumentsId, thisId, shouldContinueId, leftId;
|
||||
|
||||
var state = {
|
||||
hasTailRecursion: false,
|
||||
ownerId: ownerId,
|
||||
|
||||
getArgumentsId: function () {
|
||||
return argumentsId = argumentsId || scope.generateUidIdentifier("arguments");
|
||||
},
|
||||
|
||||
getThisId: function () {
|
||||
return thisId = thisId || scope.generateUidIdentifier("this");
|
||||
},
|
||||
|
||||
getShouldContinueId: function () {
|
||||
return shouldContinueId = shouldContinueId || scope.generateUidIdentifier("shouldContinue");
|
||||
},
|
||||
|
||||
getLeftId: function () {
|
||||
return leftId = leftId || scope.generateUidIdentifier("left");
|
||||
if (!state.needsThis && expr.left === state.getThisId()) {
|
||||
this.remove();
|
||||
} else if (!state.needsArguments && expr.left === state.getArgumentsId() && t.isArrayExpression(expr.right)) {
|
||||
return map(expr.right.elements, function (elem) {
|
||||
return t.expressionStatement(elem);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// traverse the function and look for tail recursion
|
||||
scope.traverse(node, functionVisitor, state);
|
||||
|
||||
if (!state.hasTailRecursion) return;
|
||||
|
||||
var block = t.ensureBlock(node);
|
||||
|
||||
if (leftId) {
|
||||
block.body.unshift(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(leftId)
|
||||
]));
|
||||
}
|
||||
|
||||
var resultId = scope.generateUidIdentifier("result");
|
||||
state.getShouldContinueId();
|
||||
|
||||
node.body = util.template("tail-call-body", {
|
||||
SHOULD_CONTINUE_ID: shouldContinueId,
|
||||
ARGUMENTS_ID: argumentsId,
|
||||
RESULT_ID: resultId,
|
||||
FUNCTION: t.functionExpression(null, node.params, block),
|
||||
THIS_ID: thisId,
|
||||
});
|
||||
};
|
||||
|
||||
exports.Function = function (node, parent, scope, file) {
|
||||
var tailCall = new TailCallTransformer(node, scope, file);
|
||||
tailCall.run();
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ module.exports = {
|
||||
"validation.undeclaredVariableCheck": require("./validation/undeclared-variable-check"),
|
||||
"validation.noForInOfAssignment": require("./validation/no-for-in-of-assignment"),
|
||||
"validation.setters": require("./validation/setters"),
|
||||
"validation.react": require("./validation/react"),
|
||||
"spec.blockScopedFunctions": require("./spec/block-scoped-functions"),
|
||||
|
||||
"playground.malletOperator": require("./playground/mallet-operator"),
|
||||
@@ -12,6 +13,7 @@ module.exports = {
|
||||
"playground.objectGetterMemoization": require("./playground/object-getter-memoization"),
|
||||
|
||||
reactCompat: require("./other/react-compat"),
|
||||
flow: require("./other/flow"),
|
||||
react: require("./other/react"),
|
||||
|
||||
_modules: require("./internal/modules"),
|
||||
@@ -31,7 +33,6 @@ module.exports = {
|
||||
"es6.objectSuper": require("./es6/object-super"),
|
||||
"es7.objectRestSpread": require("./es7/object-rest-spread"),
|
||||
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
|
||||
"es6.spread": require("./es6/spread"),
|
||||
"es6.templateLiterals": require("./es6/template-literals"),
|
||||
|
||||
"es5.properties.mutators": require("./es5/properties.mutators"),
|
||||
@@ -47,11 +48,15 @@ module.exports = {
|
||||
|
||||
"es6.constants": require("./es6/constants"),
|
||||
|
||||
// needs to be before `es6.parameters.default` as default parameters will destroy the rest param
|
||||
"es6.parameters.rest": require("./es6/parameters.rest"),
|
||||
|
||||
// needs to be after `es6.parameters.rest` as we use `toArray` and avoid turning an already known array into one
|
||||
"es6.spread": require("./es6/spread"),
|
||||
|
||||
// needs to be before `es6.blockScoping` as default parameters have a TDZ
|
||||
"es6.parameters.default": require("./es6/parameters.default"),
|
||||
|
||||
"es6.parameters.rest": require("./es6/parameters.rest"),
|
||||
|
||||
// needs to be before `es6.blockScoping` as let variables may be produced
|
||||
"es6.destructuring": require("./es6/destructuring"),
|
||||
|
||||
@@ -62,6 +67,8 @@ module.exports = {
|
||||
// needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks
|
||||
"es6.blockScopingTDZ": require("./es6/block-scoping-tdz"),
|
||||
|
||||
// needs to be after `es6.parameters.*` and `es6.blockScoping` due to needing pure
|
||||
// identifiers in parameters and variable declarators
|
||||
"es6.tailCall": require("./es6/tail-call"),
|
||||
|
||||
regenerator: require("./other/regenerator"),
|
||||
@@ -81,11 +88,12 @@ module.exports = {
|
||||
_declarations: require("./internal/declarations"),
|
||||
|
||||
_aliasFunctions: require("./internal/alias-functions"),
|
||||
_moduleFormatter: require("./internal/module-formatter"),
|
||||
|
||||
"spec.typeofSymbol": require("./spec/typeof-symbol"),
|
||||
"spec.undefinedToVoid": require("./spec/undefined-to-void"),
|
||||
|
||||
_moduleFormatter: require("./internal/module-formatter"),
|
||||
|
||||
"es3.propertyLiterals": require("./es3/property-literals"),
|
||||
"es3.memberExpressionLiterals": require("./es3/member-expression-literals"),
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ var t = require("../../../types");
|
||||
exports.secondPass = true;
|
||||
|
||||
exports.BlockStatement =
|
||||
exports.Program = function (node) {
|
||||
exports.Program = function (node, parent, scope, file) {
|
||||
if (!node._declarations) return;
|
||||
|
||||
var kinds = {};
|
||||
@@ -19,16 +19,16 @@ exports.Program = function (node) {
|
||||
kind = declar.kind || "var";
|
||||
var declarNode = t.variableDeclarator(declar.id, declar.init);
|
||||
|
||||
if (!declar.init) {
|
||||
if (declar.init) {
|
||||
node.body.unshift(file.attachAuxilaryComment(t.variableDeclaration(kind, [declarNode])));
|
||||
} else {
|
||||
kinds[kind] = kinds[kind] || [];
|
||||
kinds[kind].push(declarNode);
|
||||
} else {
|
||||
node.body.unshift(t.variableDeclaration(kind, [declarNode]));
|
||||
}
|
||||
}
|
||||
|
||||
for (kind in kinds) {
|
||||
node.body.unshift(t.variableDeclaration(kind, kinds[kind]));
|
||||
node.body.unshift(file.attachAuxilaryComment(t.variableDeclaration(kind, kinds[kind])));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
var useStrict = require("../../helpers/use-strict");
|
||||
|
||||
exports.post = function (file) {
|
||||
exports.Program = function (program, parent, scope, file) {
|
||||
if (!file.transformers["es6.modules"].canRun()) return;
|
||||
|
||||
var program = file.ast.program;
|
||||
|
||||
useStrict.wrap(program, function () {
|
||||
program.body = file.dynamicImports.concat(program.body);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,8 @@ var t = require("../../../types");
|
||||
exports.optional = true;
|
||||
|
||||
exports.ExpressionStatement = function (node) {
|
||||
// remove consequenceless expressions such as local variables and literals
|
||||
// remove consequence-less expressions such as local variables and literals
|
||||
// note: will remove directives
|
||||
//
|
||||
// var foo = true; foo; -> var foo = true;
|
||||
// "foo"; ->
|
||||
@@ -33,7 +34,7 @@ exports.IfStatement = {
|
||||
//
|
||||
|
||||
if (t.isLiteral(test) && test.value) {
|
||||
return alternate;
|
||||
return consequent;
|
||||
}
|
||||
|
||||
// we can check if a test will be falsy 100% and if so we can inline the
|
||||
@@ -66,8 +67,7 @@ exports.IfStatement = {
|
||||
// if (foo) {} else { bar; } -> if (!foo) { bar; }
|
||||
//
|
||||
|
||||
if (t.blockStatement(consequent) && !consequent.body.length &&
|
||||
t.isBlockStatement(alternate) && alternate.body.length) {
|
||||
if (t.blockStatement(consequent) && !consequent.body.length && t.isBlockStatement(alternate) && alternate.body.length) {
|
||||
node.consequent = node.alternate;
|
||||
node.alternate = null;
|
||||
node.test = t.unaryExpression("!", test, true);
|
||||
|
||||
@@ -6,8 +6,12 @@ var isConsole = t.buildMatchMemberExpression("console", true);
|
||||
|
||||
exports.optional = true;
|
||||
|
||||
exports.CallExpression = function (node) {
|
||||
exports.CallExpression = function (node, parent) {
|
||||
if (isConsole(node.callee)) {
|
||||
this.remove();
|
||||
if (t.isExpressionStatement(parent)) {
|
||||
this.parentPath.remove();
|
||||
} else {
|
||||
this.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
exports.optional = true;
|
||||
|
||||
exports.Scope = function () {
|
||||
// todo: get all binding identifiers, generate compact names
|
||||
// that wont collide and then call the remap identifier helper
|
||||
|
||||
// this transformer **has** to be ran last as it will absolutley
|
||||
// destroy the scope tree
|
||||
exports.Scopable = function () {
|
||||
//for (var name in scope.bindings) {
|
||||
// scope.rename(name, scope.generateUidIdentifier("a").name);
|
||||
//}
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ exports.Function = function (node, parent, scope, file) {
|
||||
|
||||
return remapAsyncToGenerator(
|
||||
node,
|
||||
t.memberExpression(file.addImport("bluebird"), t.identifier("coroutine")),
|
||||
t.memberExpression(file.addImport("bluebird", null, true), t.identifier("coroutine")),
|
||||
scope
|
||||
);
|
||||
};
|
||||
|
||||
13
lib/6to5/transformation/transformers/other/flow.js
Normal file
13
lib/6to5/transformation/transformers/other/flow.js
Normal file
@@ -0,0 +1,13 @@
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.TypeCastExpression = function (node) {
|
||||
return node.expression;
|
||||
};
|
||||
|
||||
exports.ImportDeclaration = function (node) {
|
||||
if (node.isType) this.remove();
|
||||
};
|
||||
|
||||
exports.ExportDeclaration = function (node) {
|
||||
if (t.isTypeAlias(node.declaration)) this.remove();
|
||||
};
|
||||
@@ -1,10 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
var includes = require("lodash/collection/includes");
|
||||
var util = require("../../../util");
|
||||
var core = require("core-js/library");
|
||||
var t = require("../../../types");
|
||||
var has = require("lodash/object/has");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var t = require("../../../types");
|
||||
|
||||
var isSymboliterator = t.buildMatchMemberExpression("Symbol.iterator");
|
||||
|
||||
var coreHas = function (node) {
|
||||
return node.name !== "_" && has(core, node.name);
|
||||
@@ -30,30 +32,41 @@ var astVisitor = {
|
||||
|
||||
if (!t.isReferenced(obj, node)) return;
|
||||
|
||||
if (!node.computed && coreHas(obj) && has(core[obj.name], prop.name) && !scope.getBinding(obj.name)) {
|
||||
if (!node.computed && coreHas(obj) && has(core[obj.name], prop.name) && !scope.getBindingIdentifier(obj.name)) {
|
||||
this.skip();
|
||||
return t.prependToMemberExpression(node, file.get("coreIdentifier"));
|
||||
}
|
||||
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && contains(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBinding(node.name)) {
|
||||
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && includes(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBindingIdentifier(node.name)) {
|
||||
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
|
||||
return t.memberExpression(file.get("coreIdentifier"), node);
|
||||
} else if (t.isCallExpression(node)) {
|
||||
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)
|
||||
|
||||
if (node.arguments.length) return;
|
||||
|
||||
var callee = node.callee;
|
||||
if (!t.isMemberExpression(callee)) return;
|
||||
if (!callee.computed) return;
|
||||
if (node.arguments.length) return false;
|
||||
|
||||
if (!t.isMemberExpression(callee)) return false;
|
||||
if (!callee.computed) return false;
|
||||
|
||||
prop = callee.property;
|
||||
if (!t.isIdentifier(prop.object, { name: "Symbol" })) return;
|
||||
if (!t.isIdentifier(prop.property, { name: "iterator" })) return;
|
||||
if (!isSymboliterator(prop)) return false;
|
||||
|
||||
return util.template("corejs-iterator", {
|
||||
CORE_ID: file.get("coreIdentifier"),
|
||||
VALUE: callee.object
|
||||
});
|
||||
} else if (t.isBinaryExpression(node)) {
|
||||
// Symbol.iterator in arr -> core.$for.isIterable(arr)
|
||||
|
||||
if (node.operator !== "in") return;
|
||||
|
||||
var left = node.left;
|
||||
if (!isSymboliterator(left)) return;
|
||||
|
||||
return util.template("corejs-is-iterator", {
|
||||
CORE_ID: file.get("coreIdentifier"),
|
||||
VALUE: node.right
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -64,8 +77,8 @@ exports.manipulateOptions = function (opts) {
|
||||
if (opts.whitelist.length) opts.whitelist.push("es6.modules");
|
||||
};
|
||||
|
||||
exports.post = function (file) {
|
||||
file.scope.traverse(file.ast, astVisitor, file);
|
||||
exports.Program = function (node, parent, scope, file) {
|
||||
scope.traverse(node, astVisitor, file);
|
||||
};
|
||||
|
||||
exports.pre = function (file) {
|
||||
@@ -83,7 +96,7 @@ exports.pre = function (file) {
|
||||
};
|
||||
|
||||
exports.Identifier = function (node, parent, scope, file) {
|
||||
if (node.name === "regeneratorRuntime" && t.isReferenced(node, parent)) {
|
||||
if (t.isReferencedIdentifier(node, parent, { name: "regeneratorRuntime" })) {
|
||||
return file.get("regeneratorIdentifier");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
var useStrict = require("../../helpers/use-strict");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.post = function (file) {
|
||||
var program = file.ast.program;
|
||||
exports.Program = function (program) {
|
||||
if (!useStrict.has(program)) {
|
||||
program.body.unshift(t.expressionStatement(t.literal("use strict")));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
var build = require("../../helpers/build-conditional-assignment-operator-transformer");
|
||||
var t = require("../../../types");
|
||||
var messages = require("../../../messages");
|
||||
var build = require("../../helpers/build-conditional-assignment-operator-transformer");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.playground = true;
|
||||
|
||||
@@ -11,7 +12,7 @@ build(exports, {
|
||||
if (is) {
|
||||
var left = node.left;
|
||||
if (!t.isMemberExpression(left) && !t.isIdentifier(left)) {
|
||||
throw file.errorWithNode(left, "Expected type MemeberExpression or Identifier");
|
||||
throw file.errorWithNode(left, messages.get("expectedMemberExpressionOrIdentifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ exports.BindMemberExpression = function (node, parent, scope) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.BindFunctionExpression = function (node, parent, scope, file) {
|
||||
exports.BindFunctionExpression = function (node, parent, scope) {
|
||||
var buildCall = function (args) {
|
||||
var param = scope.generateUidIdentifier("val");
|
||||
return t.functionExpression(null, [param], t.blockStatement([
|
||||
@@ -34,7 +34,7 @@ exports.BindFunctionExpression = function (node, parent, scope, file) {
|
||||
]));
|
||||
};
|
||||
|
||||
var temp = scope.generateTemp(file, "args");
|
||||
var temp = scope.generateTemp("args");
|
||||
|
||||
return t.sequenceExpression([
|
||||
t.assignmentExpression("=", temp, t.arrayExpression(node.arguments)),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var t = require("../../../types");
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.check = t.isFor;
|
||||
|
||||
@@ -9,6 +10,6 @@ exports.ForOfStatement = function (node, parent, scope, file) {
|
||||
var left = node.left;
|
||||
if (t.isVariableDeclaration(left)) {
|
||||
var declar = left.declarations[0];
|
||||
if (declar.init) throw file.errorWithNode(declar, "No assignments allowed in for-in/of head");
|
||||
if (declar.init) throw file.errorWithNode(declar, messages.get("noAssignmentsInForHead"));
|
||||
}
|
||||
};
|
||||
|
||||
25
lib/6to5/transformation/transformers/validation/react.js
vendored
Normal file
25
lib/6to5/transformation/transformers/validation/react.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
|
||||
// check if the input Literal `source` is an alternate casing of "react"
|
||||
var check = function (source, file) {
|
||||
if (t.isLiteral(source)) {
|
||||
var name = source.value;
|
||||
var lower = name.toLowerCase();
|
||||
|
||||
if (lower === "react" && name !== lower) {
|
||||
throw file.errorWithNode(source, messages.get("didYouMean", "react"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.CallExpression = function (node, parent, scope, file) {
|
||||
if (t.isIdentifier(node.callee, { name: "require" }) && node.arguments.length === 1) {
|
||||
check(node.arguments[0], file);
|
||||
}
|
||||
};
|
||||
|
||||
exports.ImportDeclaration =
|
||||
exports.ExportDeclaration = function (node, parent, scope, file) {
|
||||
check(node.source, file);
|
||||
};
|
||||
@@ -1,5 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var messages = require("../../../messages");
|
||||
|
||||
exports.check = function (node) {
|
||||
return node.kind === "set";
|
||||
};
|
||||
@@ -7,6 +9,6 @@ exports.check = function (node) {
|
||||
exports.MethodDefinition =
|
||||
exports.Property = function (node, parent, scope, file) {
|
||||
if (node.kind === "set" && node.value.params.length !== 1) {
|
||||
throw file.errorWithNode(node.value, "Setters must have only one parameter");
|
||||
throw file.errorWithNode(node.value, messages.get("settersInvalidParamLength"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var levenshtein = require("../../../helpers/levenshtein");
|
||||
var messages = require("../../../messages");
|
||||
var t = require("../../../types");
|
||||
|
||||
exports.optional = true;
|
||||
@@ -9,8 +10,6 @@ exports.Identifier = function (node, parent, scope, file) {
|
||||
if (!t.isReferenced(node, parent)) return;
|
||||
if (scope.hasBinding(node.name)) return;
|
||||
|
||||
var msg = "Reference to undeclared variable";
|
||||
|
||||
// get the closest declaration to offer as a suggestion
|
||||
// the variable name may have just been mistyped
|
||||
|
||||
@@ -28,8 +27,11 @@ exports.Identifier = function (node, parent, scope, file) {
|
||||
shortest = distance;
|
||||
}
|
||||
|
||||
var msg;
|
||||
if (closest) {
|
||||
msg += " - Did you mean " + closest + "?";
|
||||
msg = messages.get("undeclaredVariableSuggestion", node.name, closest);
|
||||
} else {
|
||||
msg = messages.get("undeclaredVariable", node.name);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
/* jshint maxparams:7 */
|
||||
|
||||
module.exports = TraversalContext;
|
||||
|
||||
var TraversalPath = require("./path");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
module.exports = traverse;
|
||||
|
||||
var TraversalContext = require("./context");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var t = require("../types");
|
||||
|
||||
function traverse(parent, opts, scope, state) {
|
||||
@@ -102,7 +102,7 @@ function hasBlacklistedType(node, parent, scope, state) {
|
||||
|
||||
traverse.hasType = function (tree, scope, type, blacklistTypes) {
|
||||
// the node we're searching in is blacklisted
|
||||
if (contains(blacklistTypes, tree.type)) return false;
|
||||
if (includes(blacklistTypes, tree.type)) return false;
|
||||
|
||||
// the type we're looking for is the same as the passed node
|
||||
if (tree.type === type) return true;
|
||||
|
||||
@@ -5,7 +5,7 @@ module.exports = TraversalPath;
|
||||
/* jshint maxparams:7 */
|
||||
|
||||
var traverse = require("./index");
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var Scope = require("./scope");
|
||||
var t = require("../types");
|
||||
|
||||
@@ -49,7 +49,7 @@ TraversalPath.getScope = function (node, parent, scope) {
|
||||
var ourScope = scope;
|
||||
|
||||
// we're entering a new scope so let's construct it!
|
||||
if (t.isScope(node)) {
|
||||
if (t.isScope(node, parent)) {
|
||||
ourScope = new Scope(node, parent, scope);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ TraversalPath.prototype.replaceNode = function (replacement) {
|
||||
// we're replacing a statement or block node with an array of statements so we better
|
||||
// ensure that it's a block
|
||||
if (isArray) {
|
||||
if (contains(t.STATEMENT_OR_BLOCK_KEYS, this.key) && !t.isBlockStatement(this.obj)) {
|
||||
if (includes(t.STATEMENT_OR_BLOCK_KEYS, this.key) && !t.isBlockStatement(this.obj)) {
|
||||
t.ensureBlock(this.obj, this.key);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ TraversalPath.prototype.call = function (key) {
|
||||
if (!node) return;
|
||||
|
||||
var opts = this.opts;
|
||||
var fn = opts[key];
|
||||
var fn = opts[key] || opts;
|
||||
if (opts[node.type]) fn = opts[node.type][key] || fn;
|
||||
|
||||
var replacement = fn.call(this, node, this.parent, this.scope, this.state);
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
module.exports = Scope;
|
||||
|
||||
var contains = require("lodash/collection/contains");
|
||||
var includes = require("lodash/collection/includes");
|
||||
var traverse = require("./index");
|
||||
var defaults = require("lodash/object/defaults");
|
||||
var messages = require("../messages");
|
||||
var globals = require("globals");
|
||||
var flatten = require("lodash/array/flatten");
|
||||
var extend = require("lodash/object/extend");
|
||||
var object = require("../helpers/object");
|
||||
var each = require("lodash/collection/each");
|
||||
var has = require("lodash/object/has");
|
||||
var t = require("../types");
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ function Scope(block, parentBlock, parent, file) {
|
||||
this.crawl();
|
||||
}
|
||||
|
||||
Scope.defaultDeclarations = flatten([globals.builtin, globals.browser, globals.node].map(Object.keys));
|
||||
Scope.globals = flatten([globals.builtin, globals.browser, globals.node].map(Object.keys));
|
||||
|
||||
/**
|
||||
* Description
|
||||
@@ -50,12 +50,11 @@ Scope.prototype.traverse = function (node, opts, state) {
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {File} file
|
||||
* @param {String} [name="temp"]
|
||||
*/
|
||||
|
||||
Scope.prototype.generateTemp = function (file, name) {
|
||||
var id = file.generateUidIdentifier(name || "temp", this);
|
||||
Scope.prototype.generateTemp = function (name) {
|
||||
var id = this.generateUidIdentifier(name || "temp");
|
||||
this.push({
|
||||
key: id.name,
|
||||
id: id
|
||||
@@ -70,7 +69,33 @@ Scope.prototype.generateTemp = function (file, name) {
|
||||
*/
|
||||
|
||||
Scope.prototype.generateUidIdentifier = function (name) {
|
||||
return this.file.generateUidIdentifier(name, this);
|
||||
var id = t.identifier(this.generateUid(name));
|
||||
this.getFunctionParent().registerBinding("uid", id);
|
||||
return id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {String} name
|
||||
*/
|
||||
|
||||
Scope.prototype.generateUid = function (name) {
|
||||
name = t.toIdentifier(name).replace(/^_+/, "");
|
||||
|
||||
var uid;
|
||||
var i = 0;
|
||||
do {
|
||||
uid = this._generateUid(name, i);
|
||||
i++;
|
||||
} while (this.hasBinding(uid) || this.hasGlobal(uid));
|
||||
return uid;
|
||||
};
|
||||
|
||||
Scope.prototype._generateUid = function (name, i) {
|
||||
var id = name;
|
||||
if (i > 1) id += i;
|
||||
return "_" + id;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -111,7 +136,7 @@ Scope.prototype.generateUidBasedOnNode = function (parent) {
|
||||
var id = parts.join("$");
|
||||
id = id.replace(/^_/, "") || "ref";
|
||||
|
||||
return this.file.generateUidIdentifier(id, this);
|
||||
return this.generateUidIdentifier(id);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -134,12 +159,50 @@ Scope.prototype.generateTempBasedOnNode = function (node) {
|
||||
return id;
|
||||
};
|
||||
|
||||
Scope.prototype.checkBlockScopedCollisions = function (key, id) {
|
||||
if (this.declarationKinds["let"][key] || this.declarationKinds["const"][key]) {
|
||||
throw this.file.errorWithNode(id, "Duplicate declaration " + key, TypeError);
|
||||
Scope.prototype.checkBlockScopedCollisions = function (kind, name, id) {
|
||||
var local = this.getOwnBindingInfo(name);
|
||||
if (!local) return;
|
||||
|
||||
if (kind === "param") return;
|
||||
if (kind === "hoisted" && local.kind === "let") return;
|
||||
|
||||
if (local.kind === "let" || local.kind === "const" || local.kind === "module") {
|
||||
throw this.file.errorWithNode(id, messages.get("scopeDuplicateDeclaration", name), TypeError);
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.rename = function (oldName, newName) {
|
||||
newName = newName || this.generateUidIdentifier(oldName).name;
|
||||
|
||||
var info = this.getBindingInfo(oldName);
|
||||
if (!info) return;
|
||||
|
||||
var binding = info.identifier;
|
||||
var scope = info.scope;
|
||||
|
||||
scope.traverse(scope.block, {
|
||||
enter: function (node, parent, scope) {
|
||||
if (t.isReferencedIdentifier(node, parent) && node.name === oldName) {
|
||||
node.name = newName;
|
||||
} else if (t.isDeclaration(node)) {
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
for (var name in ids) {
|
||||
if (name === oldName) ids[name].name = newName;
|
||||
}
|
||||
} else if (t.isScope(node, parent)) {
|
||||
if (!scope.bindingIdentifierEquals(oldName, binding)) {
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.clearOwnBinding(oldName);
|
||||
scope.bindings[newName] = info;
|
||||
|
||||
binding.name = newName;
|
||||
};
|
||||
|
||||
Scope.prototype.inferType = function (node) {
|
||||
var target;
|
||||
|
||||
@@ -147,24 +210,56 @@ Scope.prototype.inferType = function (node) {
|
||||
target = node.init;
|
||||
}
|
||||
|
||||
if (t.isLiteral(target) || t.isArrayExpression(target) || t.isObjectExpression(target)) {
|
||||
// todo: possibly call some helper that will resolve these to a flow type annotation
|
||||
if (t.isArrayExpression(target)) {
|
||||
return t.genericTypeAnnotation(t.identifier("Array"));
|
||||
}
|
||||
|
||||
if (t.isCallExpression(target)) {
|
||||
// todo: resolve this to a return type
|
||||
if (t.isObjectExpression(target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.isMemberExpression(target)) {
|
||||
// todo: crawl this and find the correct type, bail on anything that we cannot possibly be 100% confident on
|
||||
if (t.isLiteral(target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.isCallExpression(target) && t.isIdentifier(target.callee)) {
|
||||
var funcInfo = this.getBindingInfo(target.callee.name);
|
||||
if (funcInfo) {
|
||||
var funcNode = funcInfo.node;
|
||||
return !funcInfo.reassigned && t.isFunction(funcNode) && node.returnType;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.isIdentifier(target)) {
|
||||
return this.getType(target.name);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.registerType = function (key, id, node) {
|
||||
Scope.prototype.isTypeGeneric = function (name, genericName) {
|
||||
var info = this.getBindingInfo(name);
|
||||
if (!info) return false;
|
||||
|
||||
var type = info.typeAnnotation;
|
||||
return t.isGenericTypeAnnotation(type) && t.isIdentifier(type.id, { name: genericName });
|
||||
};
|
||||
|
||||
Scope.prototype.assignTypeGeneric = function (name, type) {
|
||||
this.assignType(name, t.genericTypeAnnotation(t.identifier(type)));
|
||||
};
|
||||
|
||||
Scope.prototype.assignType = function (name, type) {
|
||||
var info = this.getBindingInfo(name);
|
||||
if (!info) return;
|
||||
|
||||
info.identifier.typeAnnotation = info.typeAnnotation = type;
|
||||
};
|
||||
|
||||
Scope.prototype.getTypeAnnotation = function (name, id, node) {
|
||||
var info = {
|
||||
annotation: null,
|
||||
inferred: false
|
||||
};
|
||||
|
||||
var type;
|
||||
|
||||
if (id.typeAnnotation) {
|
||||
@@ -172,43 +267,107 @@ Scope.prototype.registerType = function (key, id, node) {
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
info.inferred = true;
|
||||
type = this.inferType(node);
|
||||
}
|
||||
|
||||
if (type) {
|
||||
if (t.isTypeAnnotation(type)) type = type.typeAnnotation;
|
||||
this.types[key] = type;
|
||||
info.annotation = type;
|
||||
}
|
||||
|
||||
return info;
|
||||
};
|
||||
|
||||
Scope.prototype.toArray = function (node, i) {
|
||||
var file = this.file;
|
||||
|
||||
if (t.isIdentifier(node) && this.isTypeGeneric(node.name, "Array")) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (t.isArrayExpression(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (t.isIdentifier(node, { name: "arguments" })) {
|
||||
return t.callExpression(t.memberExpression(file.addHelper("slice"), t.identifier("call")), [node]);
|
||||
}
|
||||
|
||||
var helperName = "to-array";
|
||||
var args = [node];
|
||||
if (i === true) {
|
||||
helperName = "to-consumable-array";
|
||||
} else if (i) {
|
||||
args.push(t.literal(i));
|
||||
helperName = "sliced-to-array";
|
||||
}
|
||||
return t.callExpression(file.addHelper(helperName), args);
|
||||
};
|
||||
|
||||
Scope.prototype.clearOwnBinding = function (name) {
|
||||
delete this.bindings[name];
|
||||
};
|
||||
|
||||
Scope.prototype.registerDeclaration = function (node) {
|
||||
if (t.isFunctionDeclaration(node)) {
|
||||
this.registerBinding("hoisted", node);
|
||||
} else if (t.isVariableDeclaration(node)) {
|
||||
for (var i = 0; i < node.declarations.length; i++) {
|
||||
this.registerBinding(node.kind, node.declarations[i]);
|
||||
}
|
||||
} else if (t.isClassDeclaration(node)) {
|
||||
this.registerBinding("let", node);
|
||||
} else if (t.isImportDeclaration(node) || t.isExportDeclaration(node)) {
|
||||
this.registerBinding("module", node);
|
||||
} else {
|
||||
this.registerBinding("unknown", node);
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.register = function (node, reference, kind) {
|
||||
if (t.isVariableDeclaration(node)) {
|
||||
return this.registerVariableDeclaration(node);
|
||||
Scope.prototype.registerBindingReassignment = function (node) {
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
for (var name in ids) {
|
||||
var info = this.getBindingInfo(name);
|
||||
if (info) {
|
||||
info.reassigned = true;
|
||||
|
||||
if (info.typeAnnotationInferred) {
|
||||
// destroy the inferred typeAnnotation
|
||||
info.typeAnnotation = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.registerBinding = function (kind, node) {
|
||||
if (!kind) throw new ReferenceError("no `kind`");
|
||||
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
|
||||
extend(this.references, ids);
|
||||
for (var name in ids) {
|
||||
var id = ids[name];
|
||||
|
||||
if (reference) return;
|
||||
this.checkBlockScopedCollisions(kind, name, id);
|
||||
|
||||
for (var key in ids) {
|
||||
var id = ids[key];
|
||||
var typeInfo = this.getTypeAnnotation(name, id, node);
|
||||
|
||||
this.checkBlockScopedCollisions(key, id);
|
||||
|
||||
this.registerType(key, id, node);
|
||||
this.bindings[key] = id;
|
||||
this.bindings[name] = {
|
||||
typeAnnotationInferred: typeInfo.inferred,
|
||||
typeAnnotation: typeInfo.annotation,
|
||||
reassigned: false,
|
||||
identifier: id,
|
||||
scope: this,
|
||||
node: node,
|
||||
kind: kind
|
||||
};
|
||||
}
|
||||
|
||||
var kinds = this.declarationKinds[kind];
|
||||
if (kinds) extend(kinds, ids);
|
||||
};
|
||||
|
||||
Scope.prototype.registerVariableDeclaration = function (declar) {
|
||||
var declars = declar.declarations;
|
||||
for (var i = 0; i < declars.length; i++) {
|
||||
this.register(declars[i], false, declar.kind);
|
||||
this.registerBinding(declars[i], declar.kind);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -217,7 +376,7 @@ var functionVariableVisitor = {
|
||||
if (t.isFor(node)) {
|
||||
each(t.FOR_INIT_KEYS, function (key) {
|
||||
var declar = node[key];
|
||||
if (t.isVar(declar)) state.scope.register(declar);
|
||||
if (t.isVar(declar)) state.scope.registerBinding("var", declar);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -235,30 +394,47 @@ var functionVariableVisitor = {
|
||||
if (t.isExportDeclaration(node) && t.isDeclaration(node.declaration)) return;
|
||||
|
||||
// we've ran into a declaration!
|
||||
if (t.isDeclaration(node)) state.scope.register(node);
|
||||
if (t.isDeclaration(node)) state.scope.registerDeclaration(node);
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.addGlobal = function (node) {
|
||||
this.globals[node.name] = node;
|
||||
};
|
||||
|
||||
Scope.prototype.hasGlobal = function (name) {
|
||||
var scope = this;
|
||||
|
||||
do {
|
||||
if (scope.globals[name]) return true;
|
||||
} while (scope = scope.parent);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var programReferenceVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isReferencedIdentifier(node, parent) && !scope.hasReference(node.name)) {
|
||||
state.register(node, true);
|
||||
if (t.isReferencedIdentifier(node, parent) && !scope.hasBinding(node.name)) {
|
||||
state.addGlobal(node);
|
||||
} else if (t.isLabeledStatement(node)) {
|
||||
state.addGlobal(node);
|
||||
} else if (t.isAssignmentExpression(node) || t.isUpdateExpression(node) || (t.isUnaryExpression(node) && node.operator === "delete")) {
|
||||
scope.registerBindingReassignment(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var blockVariableVisitor = {
|
||||
enter: function (node, parent, scope, state) {
|
||||
if (t.isBlockScoped(node)) {
|
||||
state.register(node);
|
||||
} else if (t.isScope(node)) {
|
||||
if (t.isFunctionDeclaration(node) || t.isBlockScoped(node)) {
|
||||
state.registerDeclaration(node);
|
||||
} else if (t.isScope(node, parent)) {
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.crawl = function () {
|
||||
var parent = this.parent;
|
||||
var block = this.block;
|
||||
var i;
|
||||
|
||||
@@ -271,34 +447,18 @@ Scope.prototype.crawl = function () {
|
||||
}
|
||||
|
||||
info = block._scopeInfo = {
|
||||
declarationKinds: {
|
||||
"const": object(),
|
||||
"var": object(),
|
||||
"let": object()
|
||||
},
|
||||
|
||||
references: object(),
|
||||
bindings: object(),
|
||||
types: object(),
|
||||
bindings: object(),
|
||||
globals: object()
|
||||
};
|
||||
|
||||
extend(this, info);
|
||||
|
||||
//
|
||||
|
||||
if (parent && t.isBlockStatement(block)) {
|
||||
if (t.isLoop(parent.block, { body: block }) ||
|
||||
t.isFunction(parent.block, { body: block })) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ForStatement - left, init
|
||||
|
||||
if (t.isLoop(block)) {
|
||||
for (i = 0; i < t.FOR_INIT_KEYS.length; i++) {
|
||||
var node = block[t.FOR_INIT_KEYS[i]];
|
||||
if (t.isBlockScoped(node)) this.register(node, false, true);
|
||||
if (t.isBlockScoped(node)) this.registerBinding("let", node);
|
||||
}
|
||||
|
||||
if (t.isBlockStatement(block.body)) {
|
||||
@@ -310,7 +470,7 @@ Scope.prototype.crawl = function () {
|
||||
|
||||
if (t.isFunctionExpression(block) && block.id) {
|
||||
if (!t.isProperty(this.parentBlock, { method: true })) {
|
||||
this.register(block.id);
|
||||
this.registerBinding("var", block.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +478,7 @@ Scope.prototype.crawl = function () {
|
||||
|
||||
if (t.isFunction(block)) {
|
||||
for (i = 0; i < block.params.length; i++) {
|
||||
this.register(block.params[i]);
|
||||
this.registerBinding("param", block.params[i]);
|
||||
}
|
||||
this.traverse(block.body, blockVariableVisitor, this);
|
||||
}
|
||||
@@ -332,13 +492,13 @@ Scope.prototype.crawl = function () {
|
||||
// CatchClause - param
|
||||
|
||||
if (t.isCatchClause(block)) {
|
||||
this.register(block.param);
|
||||
this.registerBinding("let", block.param);
|
||||
}
|
||||
|
||||
// ComprehensionExpression - blocks
|
||||
|
||||
if (t.isComprehensionExpression(block)) {
|
||||
this.register(block);
|
||||
this.registerBinding("let", block);
|
||||
}
|
||||
|
||||
// Program, Function - var variables
|
||||
@@ -383,26 +543,6 @@ Scope.prototype.push = function (opts) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Walk up the scope tree until we hit a `Function` and then
|
||||
* push our `node` to it's references.
|
||||
*
|
||||
* @param {String} kind
|
||||
* @param {Object} node
|
||||
*/
|
||||
|
||||
Scope.prototype.addDeclarationToFunctionScope = function (kind, node) {
|
||||
var scope = this.getFunctionParent();
|
||||
var ids = t.getBindingIdentifiers(node);
|
||||
|
||||
extend(scope.bindings, ids);
|
||||
extend(scope.references, ids);
|
||||
|
||||
// this ignores the duplicate declaration logic specified in `getInfo`
|
||||
// but it doesn't really matter
|
||||
extend(scope.declarationKinds[kind], ids);
|
||||
};
|
||||
|
||||
/**
|
||||
* Walk up the scope tree until we hit either a Function or reach the
|
||||
* very top and hit Program.
|
||||
@@ -441,72 +581,66 @@ Scope.prototype.getAllBindings = function () {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Scope.prototype.getAllDeclarationsOfKind = function (kind) {
|
||||
Scope.prototype.getAllBindingsOfKind = function (kind) {
|
||||
var ids = object();
|
||||
|
||||
var scope = this;
|
||||
do {
|
||||
defaults(ids, scope.declarationKinds[kind]);
|
||||
for (var name in scope.bindings) {
|
||||
var binding = scope.bindings[name];
|
||||
if (binding.kind === kind) ids[name] = binding;
|
||||
}
|
||||
scope = scope.parent;
|
||||
} while (scope);
|
||||
|
||||
return ids;
|
||||
};
|
||||
|
||||
//
|
||||
// misc
|
||||
|
||||
Scope.prototype.get = function (id, type) {
|
||||
return id && (this.getOwn(id, type) || this.parentGet(id, type));
|
||||
Scope.prototype.bindingIdentifierEquals = function (name, node) {
|
||||
return this.getBindingIdentifier(name) === node;
|
||||
};
|
||||
|
||||
Scope.prototype.getOwn = function (id, type) {
|
||||
var refs = {
|
||||
reference: this.references,
|
||||
binding: this.bindings,
|
||||
type: this.types
|
||||
}[type];
|
||||
return refs && has(refs, id) && refs[id];
|
||||
// get
|
||||
|
||||
Scope.prototype.getBindingInfo = function (name) {
|
||||
var scope = this;
|
||||
|
||||
do {
|
||||
var binding = scope.getOwnBindingInfo(name);
|
||||
if (binding) return binding;
|
||||
} while (scope = scope.parent);
|
||||
};
|
||||
|
||||
Scope.prototype.parentGet = function (id, type) {
|
||||
return this.parent && this.parent.get(id, type);
|
||||
Scope.prototype.getOwnBindingInfo = function (name) {
|
||||
return this.bindings[name];
|
||||
};
|
||||
|
||||
Scope.prototype.has = function (id, type) {
|
||||
if (!id) return false;
|
||||
if (this.hasOwn(id, type)) return true;
|
||||
if (this.parentHas(id, type)) return true;
|
||||
if (contains(Scope.defaultDeclarations, id)) return true;
|
||||
Scope.prototype.getBindingIdentifier = function (name) {
|
||||
var info = this.getBindingInfo(name);
|
||||
return info && info.identifier;
|
||||
};
|
||||
|
||||
Scope.prototype.getOwnBindingIdentifier = function (name) {
|
||||
var binding = this.bindings[name];
|
||||
return binding && binding.identifier;
|
||||
};
|
||||
|
||||
// has
|
||||
|
||||
Scope.prototype.hasOwnBinding = function (name) {
|
||||
return !!this.getOwnBindingInfo(name);
|
||||
};
|
||||
|
||||
Scope.prototype.hasBinding = function (name) {
|
||||
if (!name) return false;
|
||||
if (this.hasOwnBinding(name)) return true;
|
||||
if (this.parentHasBinding(name)) return true;
|
||||
if (includes(Scope.globals, name)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
Scope.prototype.hasOwn = function (id, type) {
|
||||
return !!this.getOwn(id, type);
|
||||
Scope.prototype.parentHasBinding = function (name) {
|
||||
return this.parent && this.parent.hasBinding(name);
|
||||
};
|
||||
|
||||
Scope.prototype.parentHas = function (id, type) {
|
||||
return this.parent && this.parent.has(id, type);
|
||||
};
|
||||
|
||||
each({
|
||||
reference: "Reference",
|
||||
binding: "Binding",
|
||||
type: "Type"
|
||||
}, function (title, type) {
|
||||
Scope.prototype[type + "Equals"] = function (id, node) {
|
||||
return this["get" + title](id) === node;
|
||||
};
|
||||
|
||||
each([
|
||||
"get",
|
||||
"has",
|
||||
"getOwn",
|
||||
"hasOwn",
|
||||
"parentGet",
|
||||
"parentHas",
|
||||
], function (methodName) {
|
||||
Scope.prototype[methodName + title] = function (id) {
|
||||
return this[methodName](id, type);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
"BreakStatement": ["Statement"],
|
||||
"ContinueStatement": ["Statement"],
|
||||
"DebuggerStatement": ["Statement"],
|
||||
"DoWhileStatement": ["Statement", "Loop", "While", "Scope"],
|
||||
"DoWhileStatement": ["Statement", "Loop", "While", "Scopable"],
|
||||
"IfStatement": ["Statement"],
|
||||
"ReturnStatement": ["Statement"],
|
||||
"SwitchStatement": ["Statement"],
|
||||
"ThrowStatement": ["Statement"],
|
||||
"TryStatement": ["Statement"],
|
||||
"WhileStatement": ["Statement", "Loop", "While", "Scope"],
|
||||
"WhileStatement": ["Statement", "Loop", "While", "Scopable"],
|
||||
"WithStatement": ["Statement"],
|
||||
"EmptyStatement": ["Statement"],
|
||||
"LabeledStatement": ["Statement"],
|
||||
@@ -18,13 +18,16 @@
|
||||
"ImportDeclaration": ["Statement", "Declaration"],
|
||||
"PrivateDeclaration": ["Statement", "Declaration"],
|
||||
|
||||
"ArrowFunctionExpression": ["Scope", "Function", "Expression"],
|
||||
"FunctionDeclaration": ["Statement", "Declaration", "Scope", "Function"],
|
||||
"FunctionExpression": ["Scope", "Function", "Expression"],
|
||||
"ArrowFunctionExpression": ["Scopable", "Function", "Expression"],
|
||||
"FunctionDeclaration": ["Statement", "Declaration", "Scopable", "Function"],
|
||||
"FunctionExpression": ["Scopable", "Function", "Expression"],
|
||||
|
||||
"BlockStatement": ["Statement", "Scope"],
|
||||
"Program": ["Scope"],
|
||||
"CatchClause": ["Scope"],
|
||||
"ImportSpecifier": ["ModuleSpecifier"],
|
||||
"ExportSpecifier": ["ModuleSpecifier"],
|
||||
|
||||
"BlockStatement": ["Statement", "Scopable"],
|
||||
"Program": ["Scopable"],
|
||||
"CatchClause": ["Scopable"],
|
||||
|
||||
"LogicalExpression": ["Binary", "Expression"],
|
||||
"BinaryExpression": ["Binary", "Expression"],
|
||||
@@ -36,9 +39,9 @@
|
||||
"ClassDeclaration": ["Statement", "Declaration", "Class"],
|
||||
"ClassExpression": ["Class", "Expression"],
|
||||
|
||||
"ForOfStatement": ["Statement", "For", "Scope", "Loop"],
|
||||
"ForInStatement": ["Statement", "For", "Scope", "Loop"],
|
||||
"ForStatement": ["Statement", "For", "Scope", "Loop"],
|
||||
"ForOfStatement": ["Statement", "For", "Scopable", "Loop"],
|
||||
"ForInStatement": ["Statement", "For", "Scopable", "Loop"],
|
||||
"ForStatement": ["Statement", "For", "Scopable", "Loop"],
|
||||
|
||||
"ObjectPattern": ["Pattern"],
|
||||
"ArrayPattern": ["Pattern"],
|
||||
@@ -53,7 +56,7 @@
|
||||
"BindFunctionExpression": ["Expression"],
|
||||
"BindMemberExpression": ["Expression"],
|
||||
"CallExpression": ["Expression"],
|
||||
"ComprehensionExpression": ["Expression", "Scope"],
|
||||
"ComprehensionExpression": ["Expression", "Scopable"],
|
||||
"ConditionalExpression": ["Expression"],
|
||||
"Identifier": ["Expression"],
|
||||
"Literal": ["Expression"],
|
||||
|
||||
@@ -1,33 +1,168 @@
|
||||
{
|
||||
"ArrayExpression": ["elements"],
|
||||
"ArrowFunctionExpression": ["params", "body"],
|
||||
"AssignmentExpression": ["operator", "left", "right"],
|
||||
"BinaryExpression": ["operator", "left", "right"],
|
||||
"BlockStatement": ["body"],
|
||||
"CallExpression": ["callee", "arguments"],
|
||||
"ConditionalExpression": ["test", "consequent", "alternate"],
|
||||
"ExpressionStatement": ["expression"],
|
||||
"File": ["program", "comments", "tokens"],
|
||||
"FunctionExpression": ["id", "params", "body", "generator"],
|
||||
"FunctionDeclaration": ["id", "params", "body", "generator"],
|
||||
"Identifier": ["name"],
|
||||
"IfStatement": ["test", "consequent", "alternate"],
|
||||
"ImportDeclaration": ["specifiers", "source"],
|
||||
"ImportSpecifier": ["id", "name"],
|
||||
"Literal": ["value"],
|
||||
"LogicalExpression": ["operator", "left", "right"],
|
||||
"MemberExpression": ["object", "property", "computed"],
|
||||
"MethodDefinition": ["key", "value", "computed", "kind"],
|
||||
"NewExpression": ["callee", "arguments"],
|
||||
"ObjectExpression": ["properties"],
|
||||
"Program": ["body"],
|
||||
"Property": ["kind", "key", "value", "computed"],
|
||||
"ReturnStatement": ["argument"],
|
||||
"SequenceExpression": ["expressions"],
|
||||
"ThrowExpression": ["argument"],
|
||||
"UnaryExpression": ["operator", "argument", "prefix"],
|
||||
"VariableDeclaration": ["kind", "declarations"],
|
||||
"VariableDeclarator": ["id", "init"],
|
||||
"WithStatement": ["object", "body"],
|
||||
"YieldExpression": ["argument", "delegate"]
|
||||
"ArrayExpression": {
|
||||
"elements": null
|
||||
},
|
||||
|
||||
"ArrowFunctionExpression": {
|
||||
"params": null,
|
||||
"body": null
|
||||
},
|
||||
|
||||
"AssignmentExpression": {
|
||||
"operator": null,
|
||||
"left": null,
|
||||
"right": null
|
||||
},
|
||||
|
||||
"BinaryExpression": {
|
||||
"operator": null,
|
||||
"left": null,
|
||||
"right": null
|
||||
},
|
||||
|
||||
"BlockStatement": {
|
||||
"body": null
|
||||
},
|
||||
|
||||
"CallExpression": {
|
||||
"callee": null,
|
||||
"arguments": null
|
||||
},
|
||||
|
||||
"ConditionalExpression": {
|
||||
"test": null,
|
||||
"consequent": null,
|
||||
"alternate": null
|
||||
},
|
||||
|
||||
"ExpressionStatement": {
|
||||
"expression": null
|
||||
},
|
||||
|
||||
"File": {
|
||||
"program": null,
|
||||
"comments": null,
|
||||
"tokens": null
|
||||
},
|
||||
|
||||
"FunctionExpression": {
|
||||
"id": null,
|
||||
"params": null,
|
||||
"body": null,
|
||||
"generator": false
|
||||
},
|
||||
|
||||
"FunctionDeclaration": {
|
||||
"id": null,
|
||||
"params": null,
|
||||
"body": null,
|
||||
"generator": false
|
||||
},
|
||||
|
||||
"GenericTypeAnnotation": {
|
||||
"id": null,
|
||||
"typeParameters": null
|
||||
},
|
||||
|
||||
"Identifier": {
|
||||
"name": null
|
||||
},
|
||||
|
||||
"IfStatement": {
|
||||
"test": null,
|
||||
"consequent": null,
|
||||
"alternate": null
|
||||
},
|
||||
|
||||
"ImportDeclaration": {
|
||||
"specifiers": null,
|
||||
"source": null
|
||||
},
|
||||
|
||||
"ImportSpecifier": {
|
||||
"id": null,
|
||||
"name": null
|
||||
},
|
||||
|
||||
"Literal": {
|
||||
"value": null
|
||||
},
|
||||
|
||||
"LogicalExpression": {
|
||||
"operator": null,
|
||||
"left": null,
|
||||
"right": null
|
||||
},
|
||||
|
||||
"MemberExpression": {
|
||||
"object": null,
|
||||
"property": null,
|
||||
"computed": false
|
||||
},
|
||||
|
||||
"MethodDefinition": {
|
||||
"key": null,
|
||||
"value": null,
|
||||
"computed": false,
|
||||
"static": false,
|
||||
"kind": null
|
||||
},
|
||||
|
||||
"NewExpression": {
|
||||
"callee": null,
|
||||
"arguments": null
|
||||
},
|
||||
|
||||
"ObjectExpression": {
|
||||
"properties": null
|
||||
},
|
||||
|
||||
"Program": {
|
||||
"body": null
|
||||
},
|
||||
|
||||
"Property": {
|
||||
"kind": null,
|
||||
"key": null,
|
||||
"value": null,
|
||||
"computed": false
|
||||
},
|
||||
|
||||
"ReturnStatement": {
|
||||
"argument": null
|
||||
},
|
||||
|
||||
"SequenceExpression": {
|
||||
"expressions": null
|
||||
},
|
||||
|
||||
"ThrowExpression": {
|
||||
"argument": null
|
||||
},
|
||||
|
||||
"UnaryExpression": {
|
||||
"operator": null,
|
||||
"argument": null,
|
||||
"prefix": null
|
||||
},
|
||||
|
||||
"VariableDeclaration": {
|
||||
"kind": null,
|
||||
"declarations": null
|
||||
},
|
||||
|
||||
"VariableDeclarator": {
|
||||
"id": null,
|
||||
"init": null
|
||||
},
|
||||
|
||||
"WithStatement": {
|
||||
"object": null,
|
||||
"body": null
|
||||
},
|
||||
|
||||
"YieldExpression": {
|
||||
"argument": null,
|
||||
"delegate": null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
var toFastProperties = require("../helpers/to-fast-properties");
|
||||
var defaults = require("lodash/object/defaults");
|
||||
var isString = require("lodash/lang/isString");
|
||||
var compact = require("lodash/array/compact");
|
||||
var esutils = require("esutils");
|
||||
var object = require("../helpers/object");
|
||||
var Node = require("./node");
|
||||
var each = require("lodash/collection/each");
|
||||
var uniq = require("lodash/array/uniq");
|
||||
|
||||
@@ -72,9 +70,9 @@ each(t.FLIPPED_ALIAS_KEYS, function (types, type) {
|
||||
*/
|
||||
|
||||
t.is = function (type, node, opts, skipAliasCheck) {
|
||||
if (!node) return;
|
||||
if (!node) return false;
|
||||
|
||||
var typeMatches = (type === node.type);
|
||||
var typeMatches = type === node.type;
|
||||
|
||||
if (!typeMatches && !skipAliasCheck) {
|
||||
var aliases = t.FLIPPED_ALIAS_KEYS[type];
|
||||
@@ -97,17 +95,32 @@ t.is = function (type, node, opts, skipAliasCheck) {
|
||||
|
||||
//
|
||||
|
||||
t.BUILDER_KEYS = defaults(require("./builder-keys"), t.VISITOR_KEYS);
|
||||
t.BUILDER_KEYS = require("./builder-keys");
|
||||
|
||||
each(t.VISITOR_KEYS, function (keys, type) {
|
||||
if (t.BUILDER_KEYS[type]) return;
|
||||
|
||||
var defs = {};
|
||||
each(keys, function (key) {
|
||||
defs[key] = null;
|
||||
});
|
||||
t.BUILDER_KEYS[type] = defs;
|
||||
});
|
||||
|
||||
each(t.BUILDER_KEYS, function (keys, type) {
|
||||
t[type[0].toLowerCase() + type.slice(1)] = function () {
|
||||
var args = arguments;
|
||||
var node = new Node;
|
||||
var node = {};
|
||||
node.start = null;
|
||||
node.type = type;
|
||||
each(keys, function (key, i) {
|
||||
node[key] = args[i];
|
||||
});
|
||||
|
||||
var i = 0;
|
||||
|
||||
for (var key in keys) {
|
||||
var arg = arguments[i++];
|
||||
if (arg === undefined) arg = keys[key];
|
||||
node[key] = arg;
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
});
|
||||
@@ -305,7 +318,7 @@ t.isReferenced = function (node, parent) {
|
||||
// no: [NODE = foo] = [];
|
||||
// yes: [foo = NODE] = [];
|
||||
if (t.isAssignmentPattern(parent)) {
|
||||
return parent.right !== node;
|
||||
return parent.right === node;
|
||||
}
|
||||
|
||||
// no: [NODE] = [];
|
||||
@@ -335,8 +348,8 @@ t.isReferenced = function (node, parent) {
|
||||
/**
|
||||
* Check if the input `node` is an `Identifier` and `isReferenced`.
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {Object} parent
|
||||
* @param {Node} node
|
||||
* @parma {Node} parent
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
@@ -390,7 +403,7 @@ t.toIdentifier = function (name) {
|
||||
* Description
|
||||
*
|
||||
* @param {Object} node
|
||||
* @param {String} key
|
||||
* @param {String=} key
|
||||
*/
|
||||
|
||||
t.ensureBlock = function (node, key) {
|
||||
@@ -405,7 +418,7 @@ t.ensureBlock = function (node, key) {
|
||||
* For example, given the match `React.createClass` it would match the
|
||||
* parsed nodes of `React.createClass` and `React["createClass"]`.
|
||||
*
|
||||
* @param {String} match Dot delimetered string
|
||||
* @param {String} match Dot-delimited string
|
||||
* @param {Boolean} [allowPartial] Allow a partial match
|
||||
* @returns {Function}
|
||||
*/
|
||||
@@ -423,6 +436,10 @@ t.buildMatchMemberExpression = function (match, allowPartial) {
|
||||
while (search.length) {
|
||||
var node = search.shift();
|
||||
|
||||
if (allowPartial && i === parts.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isIdentifier(node)) {
|
||||
// this part doesn't match
|
||||
if (parts[i] !== node.name) return false;
|
||||
@@ -445,11 +462,7 @@ t.buildMatchMemberExpression = function (match, allowPartial) {
|
||||
|
||||
// too many parts
|
||||
if (++i > parts.length) {
|
||||
if (allowPartial) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,6 +590,8 @@ t.getBindingIdentifiers = function (node) {
|
||||
|
||||
if (t.isIdentifier(id)) {
|
||||
ids[id.name] = id;
|
||||
} else if (t.isImportSpecifier(id)) {
|
||||
search.push(id.name || id.id);
|
||||
} else if (t.isExportDeclaration(id)) {
|
||||
if (t.isDeclaration(node.declaration)) {
|
||||
search.push(node.declaration);
|
||||
@@ -593,17 +608,16 @@ t.getBindingIdentifiers = function (node) {
|
||||
};
|
||||
|
||||
t.getBindingIdentifiers.keys = {
|
||||
UnaryExpression: ["argument"],
|
||||
AssignmentExpression: ["left"],
|
||||
ImportBatchSpecifier: ["name"],
|
||||
ImportSpecifier: ["name", "id"],
|
||||
ExportSpecifier: ["name", "id"],
|
||||
VariableDeclarator: ["id"],
|
||||
FunctionDeclaration: ["id"],
|
||||
ClassDeclaration: ["id"],
|
||||
MemeberExpression: ["object"],
|
||||
SpreadElement: ["argument"],
|
||||
RestElement: ["argument"],
|
||||
UpdateExpression: ["argument"],
|
||||
SpreadProperty: ["argument"],
|
||||
Property: ["value"],
|
||||
ComprehensionBlock: ["left"],
|
||||
AssignmentPattern: ["left"],
|
||||
@@ -765,5 +779,27 @@ t.isSpecifierDefault = function (specifier) {
|
||||
return specifier.default || t.isIdentifier(specifier.id) && specifier.id.name === "default";
|
||||
};
|
||||
|
||||
/**
|
||||
* Description
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Node} parent
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
t.isScope = function (node, parent) {
|
||||
if (t.isBlockStatement(node)) {
|
||||
if (t.isLoop(parent.block, { body: node })) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t.isFunction(parent.block, { body: node })) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return t.isScopable(node);
|
||||
};
|
||||
|
||||
toFastProperties(t);
|
||||
toFastProperties(t.VISITOR_KEYS);
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = Node;
|
||||
|
||||
var acorn = require("acorn-6to5");
|
||||
|
||||
var oldNode = acorn.Node;
|
||||
acorn.Node = Node;
|
||||
|
||||
function Node() {
|
||||
oldNode.apply(this);
|
||||
}
|
||||
@@ -73,7 +73,7 @@
|
||||
"AnyTypeAnnotation": [],
|
||||
"ArrayTypeAnnotation": [],
|
||||
"BooleanTypeAnnotation": [],
|
||||
"ClassProperty": ["key"],
|
||||
"ClassProperty": ["key", "value"],
|
||||
"DeclareClass": [],
|
||||
"DeclareFunction": [],
|
||||
"DeclareModule": [],
|
||||
@@ -92,6 +92,7 @@
|
||||
"TypeofTypeAnnotation": [],
|
||||
"TypeAlias": [],
|
||||
"TypeAnnotation": [],
|
||||
"TypeCastExpression": ["expression"],
|
||||
"TypeParameterDeclaration": [],
|
||||
"TypeParameterInstantiation": [],
|
||||
"ObjectTypeAnnotation": [],
|
||||
|
||||
@@ -30,6 +30,10 @@ exports.canCompile = function (filename, altExts) {
|
||||
|
||||
exports.canCompile.EXTENSIONS = [".js", ".jsx", ".es6", ".es"];
|
||||
|
||||
exports.normalisePathSeparator = function (filename) {
|
||||
return filename.replace(/\\/g, "/");
|
||||
};
|
||||
|
||||
exports.isInteger = function (i) {
|
||||
return isNumber(i) && i % 1 === 0;
|
||||
};
|
||||
@@ -80,7 +84,11 @@ exports.sourceMapToComment = function (map) {
|
||||
|
||||
var templateVisitor = {
|
||||
enter: function (node, parent, scope, nodes) {
|
||||
if (t.isExpressionStatement(node)) {
|
||||
node = node.expression;
|
||||
}
|
||||
if (t.isIdentifier(node) && has(nodes, node.name)) {
|
||||
this.skip();
|
||||
return nodes[node.name];
|
||||
}
|
||||
}
|
||||
@@ -101,6 +109,8 @@ exports.template = function (name, nodes, keepExpression) {
|
||||
traverse(template, templateVisitor, null, nodes);
|
||||
}
|
||||
|
||||
if (template.body.length > 1) return template.body;
|
||||
|
||||
var node = template.body[0];
|
||||
|
||||
if (!keepExpression && t.isExpressionStatement(node)) {
|
||||
|
||||
12
package.json
12
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "6to5",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "3.5.3",
|
||||
"version": "3.6.5",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://6to5.org/",
|
||||
"repository": "6to5/6to5",
|
||||
@@ -33,12 +33,12 @@
|
||||
"test": "make test"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn-6to5": "0.11.1-28",
|
||||
"acorn-6to5": "0.11.1-31",
|
||||
"ast-types": "~0.6.1",
|
||||
"chalk": "^0.5.1",
|
||||
"chokidar": "0.12.6",
|
||||
"commander": "2.6.0",
|
||||
"core-js": "^0.4.9",
|
||||
"core-js": "^0.5.3",
|
||||
"debug": "^2.1.1",
|
||||
"detect-indent": "3.0.0",
|
||||
"estraverse": "1.9.1",
|
||||
@@ -49,7 +49,7 @@
|
||||
"lodash": "3.0.0",
|
||||
"output-file-sync": "1.1.0",
|
||||
"private": "0.1.6",
|
||||
"regenerator-6to5": "0.8.9-8",
|
||||
"regenerator-6to5": "0.8.10-1",
|
||||
"regexpu": "1.1.0",
|
||||
"roadrunner": "1.0.4",
|
||||
"source-map": "0.1.43",
|
||||
@@ -58,6 +58,7 @@
|
||||
"useragent": "^2.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"6to5": "3.6.0",
|
||||
"browserify": "8.1.1",
|
||||
"chai": "1.10.0",
|
||||
"esvalid": "1.1.0",
|
||||
@@ -69,8 +70,5 @@
|
||||
"mocha": "2.1.0",
|
||||
"rimraf": "2.2.8",
|
||||
"uglify-js": "2.4.16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"kexec": "1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "6to5-runtime",
|
||||
"description": "6to5 selfContained runtime",
|
||||
"version": "3.5.2",
|
||||
"version": "3.6.4",
|
||||
"repository": "6to5/6to5",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>"
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
var buildHelpers = require("../lib/6to5/build-helpers");
|
||||
var transform = require("../lib/6to5/transformation");
|
||||
var util = require("../lib/6to5/util");
|
||||
var fs = require("fs");
|
||||
var t = require("../lib/6to5/types");
|
||||
var _ = require("lodash");
|
||||
@@ -16,8 +17,14 @@ var writeFile = function (filename, content) {
|
||||
fs.writeFileSync(filename, content);
|
||||
};
|
||||
|
||||
var readFile = function (filename) {
|
||||
return fs.readFileSync(require.resolve(filename), "utf8");
|
||||
var readFile = function (filename, defaultify) {
|
||||
var file = fs.readFileSync(require.resolve(filename), "utf8");
|
||||
|
||||
if (defaultify) {
|
||||
file += '\nmodule.exports = { "default": module.exports, __esModule: true };\n';
|
||||
}
|
||||
|
||||
return file;
|
||||
};
|
||||
|
||||
var updatePackage = function () {
|
||||
@@ -37,10 +44,10 @@ var selfContainify = function (code) {
|
||||
};
|
||||
|
||||
var buildHelpers2 = function () {
|
||||
var body = [];
|
||||
var body = util.template("self-contained-helpers-head");
|
||||
var tree = t.program(body);
|
||||
|
||||
buildHelpers(body, t.identifier("exports"));
|
||||
buildHelpers(body, t.identifier("helpers"));
|
||||
|
||||
return transform.fromAst(tree, null, {
|
||||
optional: ["selfContained"]
|
||||
@@ -48,7 +55,7 @@ var buildHelpers2 = function () {
|
||||
};
|
||||
|
||||
writeFile("helpers.js", buildHelpers2());
|
||||
writeFile("core-js.js", readFile("core-js/library"));
|
||||
writeFile("regenerator/index.js", readFile("regenerator-6to5/runtime-module"));
|
||||
writeFile("core-js.js", readFile("core-js/library", true));
|
||||
writeFile("regenerator/index.js", readFile("regenerator-6to5/runtime-module", true));
|
||||
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-6to5/runtime")));
|
||||
updatePackage();
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"args": ["foo"]
|
||||
"args": ["bar"]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var foo = () => console.log("foo");
|
||||
foo();
|
||||
|
||||
import "./bar";
|
||||
import "./bar2";
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"args": ["foo"]
|
||||
"args": ["foo2"]
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ var _classCallCheck = function (instance, Constructor) { if (!(instance instance
|
||||
var Test = function Test() {
|
||||
_classCallCheck(this, Test);
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9iYXIvYmFyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7SUFBTSxJQUFJLFlBQUosSUFBSTt3QkFBSixJQUFJIiwiZmlsZSI6InNyYy9iYXIvYmFyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgVGVzdCB7XG5cbn0iXX0=
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iYXIvYmFyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7SUFBTSxJQUFJLFlBQUosSUFBSTt3QkFBSixJQUFJIiwiZmlsZSI6InNyYy9iYXIvYmFyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgVGVzdCB7XG5cbn0iXX0=
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
arr.map(function (x) {
|
||||
return x * MULTIPLIER;
|
||||
});
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9mb28uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxHQUFHLENBQUMsR0FBRyxDQUFDLFVBQUEsQ0FBQztTQUFJLENBQUMsR0FBRyxVQUFVO0NBQUEsQ0FBQyxDQUFDIiwiZmlsZSI6InNyYy9mb28uanMiLCJzb3VyY2VzQ29udGVudCI6WyJhcnIubWFwKHggPT4geCAqIE1VTFRJUExJRVIpOyJdfQ==
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9mb28uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxHQUFHLENBQUMsR0FBRyxDQUFDLFVBQUEsQ0FBQztTQUFJLENBQUMsR0FBRyxVQUFVO0NBQUEsQ0FBQyxDQUFDIiwiZmlsZSI6InNyYy9mb28uanMiLCJzb3VyY2VzQ29udGVudCI6WyJhcnIubWFwKHggPT4geCAqIE1VTFRJUExJRVIpOyJdfQ==
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["src/bar/bar.js"],"names":[],"mappings":";;;;IAAM,IAAI,YAAJ,IAAI;wBAAJ,IAAI","file":"src/bar/bar.js","sourcesContent":["class Test {\n\n}"]}
|
||||
{"version":3,"sources":["../../src/bar/bar.js"],"names":[],"mappings":";;;;IAAM,IAAI,YAAJ,IAAI;wBAAJ,IAAI","file":"src/bar/bar.js","sourcesContent":["class Test {\n\n}"]}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["src/foo.js"],"names":[],"mappings":";;AAAA,GAAG,CAAC,GAAG,CAAC,UAAA,CAAC;SAAI,CAAC,GAAG,UAAU;CAAA,CAAC,CAAC","file":"src/foo.js","sourcesContent":["arr.map(x => x * MULTIPLIER);"]}
|
||||
{"version":3,"sources":["../src/foo.js"],"names":[],"mappings":";;AAAA,GAAG,CAAC,GAAG,CAAC,UAAA,CAAC;SAAI,CAAC,GAAG,UAAU;CAAA,CAAC,CAAC","file":"src/foo.js","sourcesContent":["arr.map(x => x * MULTIPLIER);"]}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
console.log(this, arguments);
|
||||
return "foo";
|
||||
}
|
||||
return Math.random() > 0.5 ? f.call(this, n - 1) : f.apply(this, [n - 1]);
|
||||
})(1e6) === "foo";
|
||||
@@ -1,9 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
console.log(this, arguments);
|
||||
return "foo";
|
||||
}
|
||||
return Math.random() > 0.5 ? to5Runtime.tailCall(f.call, [this, n - 1], f) : to5Runtime.tailCall(f.apply, [this, [n - 1]], f);
|
||||
})(1000000) === "foo";
|
||||
@@ -1,7 +0,0 @@
|
||||
function f(n) {
|
||||
return n <= 0 ? "foo" : g(n - 1);
|
||||
}
|
||||
|
||||
function g(n) {
|
||||
return n <= 0 ? "goo" : f(n - 1);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
function f(n) {
|
||||
return n <= 0 ? "foo" : to5Runtime.tailCall(g, [n - 1]);
|
||||
}
|
||||
|
||||
function g(n) {
|
||||
return n <= 0 ? "goo" : to5Runtime.tailCall(f, [n - 1]);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
(function f(n) {
|
||||
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || f(n - 1)));
|
||||
})(1e6, true) === "foo";
|
||||
@@ -1,5 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
(function f(n) {
|
||||
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || to5Runtime.tailCall(f, [n - 1])));
|
||||
})(1000000, true) === "foo";
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"runtime": true,
|
||||
"blacklist": []
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
(function f(n = getDefaultValue(), /* should be undefined after first pass */ m) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
// Should be clean (undefined) on each pass
|
||||
var local;
|
||||
return f(n - 1);
|
||||
})(1e6, true) === "foo";
|
||||
@@ -1,11 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
(function f(_x, /* should be undefined after first pass */m) {
|
||||
var n = arguments[0] === undefined ? getDefaultValue() : arguments[0];
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
// Should be clean (undefined) on each pass
|
||||
var local;
|
||||
return to5Runtime.tailCall(f, [n - 1]);
|
||||
})(1000000, true) === "foo";
|
||||
@@ -1,7 +0,0 @@
|
||||
function f() {
|
||||
return getObj().method();
|
||||
}
|
||||
|
||||
function g() {
|
||||
return getFalseValue() || getValue();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
function f() {
|
||||
var _temp;
|
||||
return to5Runtime.tailCall((_temp = getObj()).method, [], _temp);
|
||||
}
|
||||
|
||||
function g() {
|
||||
return getFalseValue() || to5Runtime.tailCall(getValue);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {
|
||||
return f(n - 1);
|
||||
} catch (e) {}
|
||||
})(1e6) === "foo";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return f(n - 1);
|
||||
}
|
||||
})(1e6) === "foo";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return f(n - 1);
|
||||
} finally {}
|
||||
})(1e6) === "foo";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {} finally {
|
||||
return f(n - 1);
|
||||
}
|
||||
})(1e6) === "foo";
|
||||
@@ -1,41 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {
|
||||
return f(n - 1);
|
||||
} catch (e) {}
|
||||
})(1000000) === "foo";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return to5Runtime.tailCall(f, [n - 1]);
|
||||
}
|
||||
})(1000000) === "foo";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return f(n - 1);
|
||||
} finally {}
|
||||
})(1000000) === "foo";
|
||||
|
||||
(function f(n) {
|
||||
if (n <= 0) {
|
||||
return "foo";
|
||||
}
|
||||
try {} finally {
|
||||
return to5Runtime.tailCall(f, [n - 1]);
|
||||
}
|
||||
})(1000000) === "foo";
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Line 2: MULTIPLIER is read-only"
|
||||
"throws": "Line 2: \"MULTIPLIER\" is read-only"
|
||||
}
|
||||
|
||||
9
test/fixtures/transformation/es6-block-scoping-exec/closure-wrap-collision.js
vendored
Normal file
9
test/fixtures/transformation/es6-block-scoping-exec/closure-wrap-collision.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
for (let i = 1; i < 3; i += 1) {
|
||||
(function () {
|
||||
i;
|
||||
})();
|
||||
}
|
||||
|
||||
assert.throws(function () {
|
||||
i;
|
||||
}, ReferenceError);
|
||||
7
test/fixtures/transformation/es6-classes-playground-property-initializers/instance/exec.js
vendored
Normal file
7
test/fixtures/transformation/es6-classes-playground-property-initializers/instance/exec.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
class MyClass {
|
||||
myProp = { someValue: 42 };
|
||||
}
|
||||
|
||||
var myClass = new MyClass;
|
||||
assert.ok(myClass.myProp !== MyClass.prototype.myProp);
|
||||
assert.equal(myClass.myProp.someValue, 42);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user