Compare commits

...

141 Commits

Author SHA1 Message Date
Sebastian McKenzie
9385c7e4ad v2.13.4 2015-01-21 10:27:35 +11:00
Sebastian McKenzie
3c06e68cae fix default parameter node variable name 2015-01-21 10:21:27 +11:00
Sebastian McKenzie
e8810f5124 add 2.13.4 changelog 2015-01-21 10:20:13 +11:00
Sebastian McKenzie
3c258c4716 add proper ordering to function param logic - fixes #549 2015-01-21 10:17:52 +11:00
Sebastian McKenzie
193a3c167e loops should contain their child block let declarations 2015-01-20 19:33:26 +11:00
Sebastian McKenzie
4b525daf72 fix forOf scope declarations not propagating to new for loop - fixes #538 2015-01-20 19:33:05 +11:00
Sebastian McKenzie
e46f42872a add array comprehension collision test #538 2015-01-20 16:52:11 +11:00
Sebastian McKenzie
4790e4068a add for collision test #538 2015-01-20 16:52:00 +11:00
Sebastian McKenzie
26cb5d5a65 add block to for loop scope - fixes #538 2015-01-20 16:48:41 +11:00
Sebastian McKenzie
031bda61cc don't continue let scoping remapping if there are none to be remapped 2015-01-20 16:48:07 +11:00
Sebastian McKenzie
61f1fae83b remove unused template 2015-01-20 16:47:52 +11:00
Sebastian McKenzie
d911bdaf63 add AssignmentPattern support to scope tracking - fixes #537 2015-01-20 08:56:14 +11:00
Sebastian McKenzie
f322252c36 add optional undeclared variable check transformer 2015-01-20 00:17:22 +11:00
Sebastian McKenzie
da16bf1e42 add t.isReferencedIdentifier 2015-01-20 00:17:11 +11:00
Sebastian McKenzie
4a1addc558 better whitespace for VariableDeclarations 2015-01-19 22:09:05 +11:00
Sebastian McKenzie
857abf5024 v2.13.3 2015-01-19 09:05:37 +11:00
Sebastian McKenzie
6d67105bab add coverage and vendor to npmignore 2015-01-19 09:02:51 +11:00
Sebastian McKenzie
078b09676f v2.13.2 2015-01-19 09:00:15 +11:00
Sebastian McKenzie
b719eaf6ab add missing semicolon 2015-01-19 08:58:11 +11:00
Sebastian McKenzie
b63accca25 remove --mangle sort from uglify since it's causing issues in safari/ios 2015-01-19 08:57:43 +11:00
Sebastian McKenzie
2d41b09c3b add 2.12.3 changelog 2015-01-19 08:57:04 +11:00
Sebastian McKenzie
0b44137d1f exclude coverage folder from npm 2015-01-19 08:56:58 +11:00
Sebastian McKenzie
8d8dd5fa37 add let scoping transformer rename note 2015-01-19 08:54:26 +11:00
Sebastian McKenzie
16b7ff972c split up tdz into an optional transformer until it has a better implementation - fixes #527 2015-01-19 08:54:04 +11:00
Sebastian McKenzie
ca41612109 use process.stdin.write instead of console.log to avoid console.log sprintf - fixes #527 2015-01-19 08:53:42 +11:00
Sebastian McKenzie
8fc7af5480 properly reference method body - fixes #530 2015-01-19 08:35:01 +11:00
Sebastian McKenzie
1c6cb7ce40 Merge pull request #526 from tricknotes/remove-unused
Remove unused local variable
2015-01-18 22:30:24 +11:00
Ryunosuke SATO
24d6c3f488 Remove unused local variable
`hasOptional` is assigned but unused from anywhere.
2015-01-18 20:16:32 +09:00
Sebastian McKenzie
d877a04397 v2.13.1 2015-01-18 21:40:21 +11:00
Sebastian McKenzie
4844882f5e break let scoping transformer if there are no block scoped references 2015-01-18 21:37:37 +11:00
Sebastian McKenzie
a80945cfb4 ignore function declarations in TDZ detection 2015-01-18 21:33:22 +11:00
Sebastian McKenzie
6a884c58a7 add 2.13.1 changelog 2015-01-18 21:28:34 +11:00
Sebastian McKenzie
7c4701716c implement block scoping TDZ 2015-01-18 21:26:02 +11:00
Sebastian McKenzie
ecfd5fadc6 v2.13.0 2015-01-18 19:31:07 +11:00
Sebastian McKenzie
c6be5cccd7 update bin/6to5/file to new source-map api 2015-01-18 19:29:18 +11:00
Sebastian McKenzie
dd256dc3f8 add acorn-6to5 changes to 2.13.0 changelog 2015-01-18 19:26:15 +11:00
Sebastian McKenzie
622da331a6 add 2.13.0 changelog 2015-01-18 19:24:54 +11:00
Sebastian McKenzie
5a44793dcb upgrade acorn-6to5 2015-01-18 19:24:49 +11:00
Sebastian McKenzie
9c9a9b0325 make regenerator test future-proof 2015-01-18 18:51:11 +11:00
Sebastian McKenzie
2534f7f2a0 upgrade dependencies 2015-01-18 18:50:58 +11:00
Sebastian McKenzie
36a933a004 add strict mode to every file 2015-01-18 18:44:08 +11:00
Sebastian McKenzie
62c168b13c fix linting errors 2015-01-18 18:41:24 +11:00
Sebastian McKenzie
810c97d7ab actually make destructuring use the provided operator 2015-01-18 18:24:16 +11:00
Sebastian McKenzie
c2b20b18b3 make name method helper export a property method instead of a default 2015-01-18 18:24:05 +11:00
Sebastian McKenzie
309d19960f better traversal context variable names 2015-01-18 18:23:46 +11:00
Sebastian McKenzie
774cb66d9b add isBlockedScoped types helper 2015-01-18 18:23:37 +11:00
Sebastian McKenzie
d360bd5bb7 update misc tests 2015-01-18 18:23:27 +11:00
Sebastian McKenzie
74f5a73d31 update traceur 2015-01-18 18:23:14 +11:00
Sebastian McKenzie
26395a86fa add block scoped functions - fixes #514 2015-01-18 18:23:03 +11:00
Sebastian McKenzie
436c488ee3 revamp let scoping transformer - closes #510 2015-01-18 18:22:37 +11:00
Sebastian McKenzie
93d99077e5 Revert "add loose mode to spread and destructuring"
This reverts commit 95d9f59668.
2015-01-18 12:52:16 +11:00
Sebastian McKenzie
0bb52d6e3d Merge branch 'master' of github.com:6to5/6to5 2015-01-18 12:16:23 +11:00
Sebastian McKenzie
320c78b815 make let scoping collision detection much more reliable 2015-01-18 12:15:50 +11:00
Sebastian McKenzie
ddd59b94b0 upgrade acorn-6to5 2015-01-18 12:15:31 +11:00
Sebastian McKenzie
c210d64557 add loose all option 2015-01-18 12:13:08 +11:00
Sebastian McKenzie
a0f605bbab add way to automatically write expected tests 2015-01-18 12:12:58 +11:00
Sebastian McKenzie
f4b2768194 add todo note to duplicate expression 2015-01-18 12:12:32 +11:00
Sebastian McKenzie
95d9f59668 add loose mode to spread and destructuring 2015-01-18 12:12:12 +11:00
Sebastian McKenzie
c41d799b9b Merge pull request #522 from fabiomcosta/lint_fixes
Fixes lint warnings that are blocking test run
2015-01-18 10:21:12 +11:00
Fabio M. Costa
e7d4642d48 Fixes lint warnings that are blocking test run 2015-01-17 14:19:54 -08:00
Sebastian McKenzie
41949fd58b push uids to scope tracking - fixes #515 2015-01-18 02:36:37 +11:00
Sebastian McKenzie
d0dc972840 fix up formatting in traverse 2015-01-18 02:35:19 +11:00
Sebastian McKenzie
621e66e9ac add private declaration and comprehension expression support to scope tracking and id building 2015-01-18 02:35:08 +11:00
Sebastian McKenzie
529544ce0e use generateUidIdentifier instead of generateUid 2015-01-18 01:16:09 +11:00
Sebastian McKenzie
f298cd3f0f allow single idents in binary assignment operator transformer 2015-01-18 01:15:35 +11:00
Sebastian McKenzie
67029ac8e8 better helpers for assignment operators 2015-01-18 00:37:51 +11:00
Sebastian McKenzie
b54800234f clean up conditional assignment operator transformers 2015-01-17 22:56:49 +11:00
Sebastian McKenzie
ecd85f53b4 Merge pull request #516 from jridgewell/mallot
Playground Proposal: Mallet operator
2015-01-17 21:59:23 +11:00
Sebastian McKenzie
9098852897 abstract out classes super replace 2015-01-17 18:53:49 +11:00
Sebastian McKenzie
3eb4d5b466 fix up styling of #518 2015-01-17 18:53:40 +11:00
Sebastian McKenzie
ddb1c718f1 Merge pull request #518 from gaearon/perf-v8
RFC: V8-specific performance impovements
2015-01-17 18:33:35 +11:00
Sebastian McKenzie
8919873ea1 clean up react/jsx transformer 2015-01-17 18:26:14 +11:00
Sebastian McKenzie
eb9cd95d5a update for head tests 2015-01-17 17:54:04 +11:00
Sebastian McKenzie
4ec701fc44 ignore variable declarations inside loop head in newline generation - fixes #519 2015-01-17 17:44:16 +11:00
Dan Abramov
ff9511d435 Proof of concept of how traversal would look like with state parameter 2015-01-17 05:03:23 +03:00
Justin Ridgewell
ac5a6da1fa Use all falsey values 2015-01-16 19:25:28 -05:00
Justin Ridgewell
616640a128 Playground Proposal: Mallet operator
The mallet operator is similar to the current memoization operator,
except it can be used outside of just objects.

In Ruby, it’s almost the same as `a = a || b`. Note that only `nil` and
`false` are falsey in Ruby. I’ve defined it as `== null`, though that
could be changed to any JS falsey value.
2015-01-16 18:57:15 -05:00
Sebastian McKenzie
1f9ce96e43 fix rest parameter array size error in rest parameter comment 2015-01-17 10:27:01 +11:00
Sebastian McKenzie
dc6a862bec better clarification of rest parameter size construction comment 2015-01-17 10:23:53 +11:00
Dan Abramov
f9480b5280 Avoid closures when traversing 2015-01-17 00:13:39 +03:00
Dan Abramov
8dc4996547 Refactor traversal into smaller methods 2015-01-17 00:13:39 +03:00
Dan Abramov
4f01f67dd6 Avoid delete in favor of null assignment to prevent deoptimizations 2015-01-17 00:13:39 +03:00
Dan Abramov
938026abeb Use toFastProperties to speed up t.* method access 2015-01-17 00:13:38 +03:00
Sebastian McKenzie
76b8945207 v2.12.6 2015-01-16 22:52:12 +11:00
Sebastian McKenzie
e78859fae0 add 2.12.6 changelog 2015-01-16 22:49:31 +11:00
Sebastian McKenzie
d68f1e9910 add flow type generation skeleton 2015-01-16 22:47:55 +11:00
Sebastian McKenzie
20e97f2d9b add flow type visitor keys - none currently as we don't need to traverse over any of them - closes #513 2015-01-16 22:46:09 +11:00
Sebastian McKenzie
750ec7783f v2.12.5 2015-01-16 08:08:52 +11:00
Sebastian McKenzie
14ae438735 remove declarators push in let scoping 2015-01-16 08:06:38 +11:00
Sebastian McKenzie
2f8bdd7e27 add 2.12.5 changelog 2015-01-16 07:59:40 +11:00
Sebastian McKenzie
87da9fcfc5 fix let scoping for loop - closes #509 2015-01-16 07:58:14 +11:00
Sebastian McKenzie
51f6cfddca remove instanbul inclusion 2015-01-16 02:47:20 +11:00
Sebastian McKenzie
b9ad4c2773 v2.12.4 2015-01-16 02:41:23 +11:00
Sebastian McKenzie
228b3dbc34 fix linting errors 2015-01-16 02:38:45 +11:00
Sebastian McKenzie
a01802300f fix default parameters transformer for loops 2015-01-16 02:36:56 +11:00
Sebastian McKenzie
51c6a3fffc fix let scoping body not existing 2015-01-16 02:31:36 +11:00
Sebastian McKenzie
4668e1d67b fix linting errors 2015-01-16 02:29:35 +11:00
Sebastian McKenzie
75e9097e19 add 2.12.4 changelog 2015-01-16 02:29:02 +11:00
Sebastian McKenzie
0627cd94d4 turn array for ins into fors 2015-01-16 02:25:41 +11:00
Sebastian McKenzie
71879d6e8f Merge branch 'master' of github.com:6to5/6to5 2015-01-16 00:50:55 +11:00
Sebastian McKenzie
d7810cac08 add ambiguous rest parameters comment 2015-01-16 00:50:38 +11:00
Sebastian McKenzie
dc9efd21d3 Merge pull request #507 from leebyron/unused
Rm unused dependencies (pass lint)
2015-01-16 00:47:55 +11:00
Lee Byron
347e490614 Rm unused dependencies (pass lint) 2015-01-15 08:47:03 -05:00
Sebastian McKenzie
e512264be7 Merge pull request #506 from leebyron/rest
Improve performance of rest parameter.
2015-01-16 00:43:56 +11:00
Lee Byron
9624663e60 Improve performance of rest parameter.
Rather than initing an empty array and filling, create an array of the correct size up-front. Minor gain on chromium, but considerably (~5x) faster in spidermonkey/firefox.
2015-01-15 08:41:53 -05:00
Sebastian McKenzie
3cf8a6df01 rename replaceInstanceSuperReferences to replaceSuperReferences in classes transformer and add breaks on method definitions 2015-01-15 23:08:28 +11:00
Sebastian McKenzie
88eacecd72 clarify traceur ignore tests 2015-01-15 23:08:06 +11:00
Sebastian McKenzie
fcd3c9ce65 remove register blacklist tests 2015-01-15 23:07:52 +11:00
Sebastian McKenzie
1733bac3bb move chokidar to top 2015-01-15 23:07:46 +11:00
Sebastian McKenzie
21cd063274 Merge pull request #503 from shinnn/output-file-sync
Use output-file-sync instead of mkdirp
2015-01-15 20:32:48 +11:00
Shinnosuke Watanabe
db5750643a use output-file-sync instead of mkdirp
https://github.com/shinnn/output-file-sync
2015-01-15 18:29:40 +09:00
Sebastian McKenzie
60dae7a88d add build comprehension helper 2015-01-15 20:13:24 +11:00
Sebastian McKenzie
790c924b54 abstract out build comprehension helper 2015-01-15 20:13:16 +11:00
Sebastian McKenzie
50d7a46c7f abstract away remap async to generator helper 2015-01-15 20:09:50 +11:00
Sebastian McKenzie
6f7da38957 abstract out named method helper 2015-01-15 20:07:32 +11:00
Sebastian McKenzie
80764c214a add rest parameter comments 2015-01-15 19:52:53 +11:00
Sebastian McKenzie
55054e45da Revert "Improve performance of rest parameter."
This reverts commit e5463cc2a9.
2015-01-15 19:34:33 +11:00
Sebastian McKenzie
060aa5ba0b fix rest parameter check in types.isReferenced 2015-01-15 19:29:54 +11:00
Sebastian McKenzie
688d619bfe add identifier check to class id inheritance 2015-01-15 19:29:54 +11:00
Sebastian McKenzie
6db7fce543 fix computed member expressions in playground memoization 2015-01-15 19:29:54 +11:00
Sebastian McKenzie
41ff1d4ace upgrade acorn-6to5 2015-01-15 19:29:54 +11:00
Sebastian McKenzie
1c6eeba2e9 Merge pull request #499 from leebyron/rest
Improve performance of rest parameter.
2015-01-15 19:28:32 +11:00
Sebastian McKenzie
488b719fde Merge pull request #494 from gaearon/perf-2
Performance impovements
2015-01-15 19:28:04 +11:00
Sebastian McKenzie
af32080287 Merge pull request #498 from leebyron/patch-1
Update CONTRIBUTING.md
2015-01-15 19:27:07 +11:00
Sebastian McKenzie
4c1cd13536 Merge pull request #501 from shinnn/package-json
Update repository info and homepage URL
2015-01-15 14:36:39 +11:00
Dan Abramov
1002cf7796 Avoid Node allocations by making prototype call statics 2015-01-15 04:18:18 +03:00
Shinnosuke Watanabe
081dd33e73 Update repository info and homepage URL
* link to https://6to5.org
* use user/repo style
2015-01-15 10:07:54 +09:00
Sebastian McKenzie
bd9dc4f15d Merge pull request #500 from shinnn/container-based-build
Use container-based infrastructure on Travis CI
2015-01-15 12:01:33 +11:00
Shinnosuke Watanabe
c7ba566ad6 Use container-based infrastructure on Travis CI
http://docs.travis-ci.com/user/workers/container-based-infrastructure/
2015-01-15 09:55:10 +09:00
Dan Abramov
a1b326a0ab Use object lookup instead of array 2015-01-15 03:51:22 +03:00
Dan Abramov
a452f781b8 Slightly refactor and add explanations for optimized functions 2015-01-15 03:39:24 +03:00
Lee Byron
e5463cc2a9 Improve performance of rest parameter.
Rather than initing an empty array and filling, create an array of the correct size up-front. Minor gain on chromium, but considerably (~5x) faster in spidermonkey/firefox.
2015-01-14 19:08:14 -05:00
Lee Byron
7d732ef503 Update CONTRIBUTING.md 2015-01-14 19:01:53 -05:00
Lee Byron
25cb0c6344 Update CONTRIBUTING.md
Explain git init submodules step when checking out
2015-01-14 18:23:49 -05:00
Sebastian McKenzie
45a52bf478 Merge pull request #496 from swirlycheetah/master
Expand upon the contributing guidelines
2015-01-15 09:41:12 +11:00
Chris Wheatley
a14f971b8a add further commands required for workflow 2015-01-14 22:25:20 +00:00
Chris Wheatley
da65500545 expand upon the contributing guidelines 2015-01-14 22:11:46 +00:00
Dan Abramov
58a91ee9e9 Optimize node type lookup 2015-01-14 23:01:58 +03:00
Dan Abramov
19eaa181a5 Speed up common case where consumer moves only forward 2015-01-14 20:02:40 +03:00
Dan Abramov
c7c90acf3f Store ranges instead of line indexes for performance 2015-01-14 19:14:47 +03:00
Dan Abramov
c6f3a55c03 Refactor buffer for clarity and avoid regex for performance 2015-01-14 19:14:47 +03:00
148 changed files with 2282 additions and 1757 deletions

View File

@@ -10,3 +10,5 @@ dist
tests.json
CHANGELOG.md
.package.json
coverage
vendor

View File

@@ -1,3 +1,4 @@
sudo: false
language: node_js
node_js:
- "0.10"

View File

@@ -11,6 +11,80 @@
_Note: Gaps between patch versions are faulty/broken releases._
## 2.13.4
* **Bug Fix**
* Fix ordering of destructuring and default params.
* Fix loop body scope.
* Fix `for...of` transformation not retaining it's scope.
* Add destructuring assignment support to scope tracking.
* **Polish**
* More reliable newlines for pretty printing variable declarations.
## 2.13.3
* **Internal**
* Add `coverage` and `vendor` to npmignore.
## 2.13.2
* **Bug Fix**
* Fix `super` inside of nested functions.
* **Internal**
* Move let scoping TDZ into a separate transformer until it's more solid.
* Use `process.stdin.write` instead of `console.log` in `bin` to avoid sprintfification.
## 2.13.1
* **New Feature**
* Temporal dead zone for block binding.
## 2.13.0
* **New Feature**
* Block scoped functions.
* Add `--loose all` option.
* Add playground mallet operator thanks to [@jridgewell](https://github.com/jridgewell).
* **Bug Fix**
* Rewrote large parts of the let scoping transformer. Now passes all known tests.
* **Internal**
* Even more optimisations thanks to the awesome [@gaearon](https://github.com/gaearon).
* Upgrade `acorn-6to5`.
* Fixes exponentation operator thanks to [@charliesome](https://github.com/charliesome).
* Fix flow optional parameters with types.
* Upgrade `chokidar` to `0.12.6`.
* Upgrade `commander` to `2.6.0`.
* Upgrade `core-js` to `0.4.5`.
* Upgrade `estraverse` to `1.9.1`.
* Upgrade `jshint` to `2.5.11`.
* Upgrade `regenerator` to `0.8.9`.
* Upgrade `regexpu` to `1.0.0`.
* Upgrade `source-map` to `0.1.43`.
* Upgrade `source-map-support` to `0.2.9`.
* Upgrade `browserify` to `8.1.1`.
* Upgrade `chai` to `1.10.0`.
* Upgrade `istanbul` to `0.3.5`.
* Upgrade `mocha` to `2.1.0`.
* Upgrade `uglify-js` to `2.4.16`.
## 2.12.6
* **Bug Fix**
* Add missing flow type traversal keys.
## 2.12.5
* **Internal**
* Fix incorrect `for...in` loop still causing `ember-script` issues.
## 2.12.4
* **Polish**
* Rest parameters now allocate the array before populating.
* **Internal**
* `for...in` loops have been changed to optimised `for` loops - better performance and no enumeration of protoype keys.
* Parts of the code generator have now been optimised thanks to [gaearon](https://github.com/gaearon).
## 2.12.3
* **Spec Compliancy**

View File

@@ -1,6 +1,20 @@
# Contributing
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).
## Developing
#### Workflow
* Fork the repository
* Clone your fork and change directory to it (`git clone git@github.com:yourUserName/6to5.git && cd 6to5`)
* Install the project dependencies (`make bootstrap`)
* 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
#### Code Standards
* **General**
* No ES6 syntax features or methods, exclusively ES5.

View File

@@ -1,6 +1,7 @@
BROWSERIFY_CMD = node_modules/browserify/bin/cmd.js
ISTANBUL_CMD = node_modules/istanbul/lib/cli.js cover
UGLIFY_CMD = node_modules/uglify-js/bin/uglifyjs --mangle sort
UGLIFY_CMD = node_modules/uglify-js/bin/uglifyjs
#UGLIFY_CMD = node_modules/uglify-js/bin/uglifyjs --mangle sort
JSHINT_CMD = node_modules/jshint/bin/jshint
MOCHA_CMD = node_modules/mocha/bin/_mocha

View File

@@ -11,3 +11,4 @@
* Add autoindentation.
* Move `super` transformation from classes into a separate transformer that also supports object expressions.
* Remove fast transformer backwards compatibility.
* Rename let scoping transformer to block scoping.

View File

@@ -1,9 +1,9 @@
var chokidar = require("chokidar");
var mkdirp = require("mkdirp");
var path = require("path");
var util = require("./util");
var fs = require("fs");
var _ = require("lodash");
var outputFileSync = require("output-file-sync");
var chokidar = require("chokidar");
var path = require("path");
var util = require("./util");
var fs = require("fs");
var _ = require("lodash");
module.exports = function (commander, filenames, opts) {
if (commander.sourceMapsInline) {
@@ -15,16 +15,13 @@ module.exports = function (commander, filenames, opts) {
var data = util.compile(src, { sourceMapName: dest });
var up = path.normalize(dest + "/..");
mkdirp.sync(up);
if (commander.sourceMaps) {
var mapLoc = dest + ".map";
data.code = util.addSourceMappingUrl(data.code, mapLoc);
fs.writeFileSync(mapLoc, JSON.stringify(data.map));
outputFileSync(mapLoc, JSON.stringify(data.map));
}
fs.writeFileSync(dest, data.code);
outputFileSync(dest, data.code);
console.log(src + " -> " + dest);
};

View File

@@ -28,7 +28,7 @@ module.exports = function (commander, filenames) {
map.setSourceContent(filename, result.actual);
consumer.eachMapping(function (mapping) {
map._mappings.push({
map._mappings.add({
generatedLine: mapping.generatedLine + offset,
generatedColumn: mapping.generatedColumn,
originalLine: mapping.originalLine,
@@ -63,7 +63,7 @@ module.exports = function (commander, filenames) {
fs.writeFileSync(commander.outFile, result.code);
} else {
console.log(result.code);
process.stdout.write(result.code + "\n");
}
};

View File

@@ -34,13 +34,10 @@ commander.on("--help", function(){
console.log(" " + title + ":");
console.log();
var hasOptional = true;
_.each(_.keys(obj).sort(), function (key) {
if (key[0] === "_") return;
if (obj[key].optional) {
hasOptional = true;
key = "[" + key + "]";
}

View File

@@ -1,3 +1,5 @@
"use strict";
var transform = module.exports = require("./transformation/transform");
transform.version = require("../../package").version;

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = File;
var SHEBANG_REGEX = /^\#\!.*/;
@@ -78,6 +80,10 @@ File.normaliseOptions = function (opts) {
opts.optional = util.arrayify(opts.optional);
opts.loose = util.arrayify(opts.loose);
if (_.contains(opts.loose, "all")) {
opts.loose = Object.keys(transform.transformers);
}
// todo: remove in 3.0.0
_.each({
fastForOf: "forOf",
@@ -325,7 +331,10 @@ File.prototype.generateUid = function (name, scope) {
};
File.prototype.generateUidIdentifier = function (name, scope) {
return t.identifier(this.generateUid(name, scope));
scope = scope || this.scope;
var id = t.identifier(this.generateUid(name, scope));
scope.add(id);
return id;
};
File.prototype._generateUid = function (name) {

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = Buffer;
var util = require("../util");
@@ -67,32 +69,57 @@ Buffer.prototype.removeLast = function (cha) {
Buffer.prototype.newline = function (i, removeLast) {
if (this.format.compact) return;
if (_.isBoolean(i)) {
removeLast = i;
i = null;
}
removeLast = removeLast || false;
if (_.isNumber(i)) {
if (this.endsWith("{\n")) i--;
if (this.endsWith(util.repeat(i, "\n"))) return;
for (var j = 0; j < i; j++) {
this.newline(null, removeLast);
while (i--) {
this._newline(removeLast);
}
return;
}
if (_.isBoolean(i)) {
removeLast = i;
}
this._newline(removeLast);
};
Buffer.prototype._newline = function (removeLast) {
if (removeLast && this.isLast("\n")) this.removeLast("\n");
this.removeLast(" ");
// remove whitespace if last character was a newline
this.buf = this.buf.replace(/\n +$/, "\n");
this._removeSpacesAfterLastNewline();
this._push("\n");
};
/**
* If buffer ends with a newline and some spaces after it, trim those spaces.
*/
Buffer.prototype._removeSpacesAfterLastNewline = function () {
var lastNewlineIndex = this.buf.lastIndexOf('\n');
if (lastNewlineIndex === -1)
return;
var index = this.buf.length - 1;
while (index > lastNewlineIndex) {
if (this.buf[index] !== ' ') {
break;
}
index--;
}
if (index === lastNewlineIndex) {
this.buf = this.buf.substring(0, index + 1);
}
};
Buffer.prototype.push = function (str, noIndent) {
if (this._indent && !noIndent && str !== "\n") {
// we have an indent level and we aren't pushing a newline

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = function (ast, opts, code) {
var gen = new CodeGenerator(ast, opts, code);
return gen.generate();

View File

@@ -1,3 +1,5 @@
"use strict";
exports.File = function (node, print) {
print(node.program);
};

View File

@@ -1,3 +1,5 @@
"use strict";
exports.ClassExpression =
exports.ClassDeclaration = function (node, print) {
this.push("class");

View File

@@ -1,3 +1,5 @@
"use strict";
exports.ComprehensionBlock = function (node, print) {
this.keyword("for");
this.push("(");

View File

@@ -1,3 +1,5 @@
"use strict";
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");

View File

@@ -1,3 +1,35 @@
exports.ClassProperty = function () {
throw new Error("not implemented");
"use strict";
exports.AnyTypeAnnotation =
exports.ArrayTypeAnnotation =
exports.BooleanTypeAnnotation =
exports.ClassProperty =
exports.DeclareClass =
exports.DeclareFunction =
exports.DeclareModule =
exports.DeclareVariable =
exports.FunctionTypeAnnotation =
exports.FunctionTypeParam =
exports.GenericTypeAnnotation =
exports.InterfaceExtends =
exports.InterfaceDeclaration =
exports.IntersectionTypeAnnotation =
exports.NullableTypeAnnotation =
exports.NumberTypeAnnotation =
exports.StringLiteralTypeAnnotation =
exports.StringTypeAnnotation =
exports.TupleTypeAnnotation =
exports.TypeofTypeAnnotation =
exports.TypeAlias =
exports.TypeAnnotation =
exports.TypeParameterDeclaration =
exports.TypeParameterInstantiation =
exports.ObjectTypeAnnotation =
exports.ObjectTypeCallProperty =
exports.ObjectTypeIndexer =
exports.ObjectTypeProperty =
exports.QualifiedTypeIdentifier =
exports.UnionTypeAnnotation =
exports.VoidTypeAnnotation = function () {
// todo: implement these once we have a `--keep-types` option
};

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
var _ = require("lodash");

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
exports._params = function (node, print) {

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
var _ = require("lodash");

View File

@@ -1,3 +1,5 @@
"use strict";
var _ = require("lodash");
_.each(["BindMemberExpression", "BindFunctionExpression"], function (type) {

View File

@@ -1,3 +1,5 @@
"use strict";
var util = require("../../util");
var t = require("../../types");
@@ -167,18 +169,19 @@ exports.DebuggerStatement = function () {
exports.VariableDeclaration = function (node, print, parent) {
this.push(node.kind + " ");
var inits = 0;
var noInits = 0;
for (var i in node.declarations) {
if (node.declarations[i].init) {
inits++;
} else {
noInits++;
var hasInits = false;
// don't add whitespace to loop heads
if (!t.isFor(parent)) {
for (var i = 0; i < node.declarations.length; i++) {
if (node.declarations[i].init) {
// has an init so let's split it up over multiple lines
hasInits = true;
}
}
}
var sep = ",";
if (inits > noInits) { // more inits than noinits
if (hasInits) {
sep += "\n" + util.repeat(node.kind.length + 1);
} else {
sep += " ";

View File

@@ -1,3 +1,5 @@
"use strict";
var _ = require("lodash");
exports.TaggedTemplateExpression = function (node, print) {

View File

@@ -1,3 +1,5 @@
"use strict";
var _ = require("lodash");
exports.Identifier = function (node) {

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = Node;
var whitespace = require("./whitespace");
@@ -13,7 +15,7 @@ var find = function (obj, node, parent) {
for (var i = 0; i < types.length; i++) {
var type = types[i];
if (t["is" + type](node)) {
if (t.is(type, node)) {
var fn = obj[type];
result = fn(node, parent);
if (result != null) break;
@@ -28,13 +30,11 @@ function Node(node, parent) {
this.node = node;
}
Node.prototype.isUserWhitespacable = function () {
return t.isUserWhitespacable(this.node);
Node.isUserWhitespacable = function (node) {
return t.isUserWhitespacable(node);
};
Node.prototype.needsWhitespace = function (type) {
var parent = this.parent;
var node = this.node;
Node.needsWhitespace = function (node, parent, type) {
if (!node) return 0;
if (t.isExpressionStatement(node)) {
@@ -51,18 +51,15 @@ Node.prototype.needsWhitespace = function (type) {
return lines || 0;
};
Node.prototype.needsWhitespaceBefore = function () {
return this.needsWhitespace("before");
Node.needsWhitespaceBefore = function (node, parent) {
return Node.needsWhitespace(node, parent, "before");
};
Node.prototype.needsWhitespaceAfter = function () {
return this.needsWhitespace("after");
Node.needsWhitespaceAfter = function (node, parent) {
return Node.needsWhitespace(node, parent, "after");
};
Node.prototype.needsParens = function () {
var parent = this.parent;
var node = this.node;
Node.needsParens = function (node, parent) {
if (!parent) return false;
if (t.isNewExpression(parent) && parent.callee === node) {
@@ -77,10 +74,7 @@ Node.prototype.needsParens = function () {
return find(parens, node, parent);
};
Node.prototype.needsParensNoLineTerminator = function () {
var parent = this.parent;
var node = this.node;
Node.needsParensNoLineTerminator = function (node, parent) {
if (!parent) return false;
// no comments
@@ -100,17 +94,18 @@ Node.prototype.needsParensNoLineTerminator = function () {
return false;
};
_.each(Node.prototype, function (fn, key) {
Node[key] = function (node, parent) {
var n = new Node(node, parent);
_.each(Node, function (fn, key) {
Node.prototype[key] = function () {
// Avoid leaking arguments to prevent deoptimization
var skipCount = 2;
var args = new Array(arguments.length - skipCount);
var args = new Array(arguments.length + 2);
args[0] = this.node;
args[1] = this.parent;
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i + 2];
args[i + 2] = arguments[i];
}
return n[key].apply(n, args);
return Node[key].apply(null, args);
};
});

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
var _ = require("lodash");

View File

@@ -1,3 +1,5 @@
"use strict";
var _ = require("lodash");
var t = require("../../types");

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = Position;
function Position() {

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = SourceMap;
var sourceMap = require("source-map");

View File

@@ -1,10 +1,40 @@
"use strict";
module.exports = Whitespace;
var _ = require("lodash");
var _ = require("lodash");
/**
* Returns `i`th number from `base`, continuing from 0 when `max` is reached.
* Useful for shifting `for` loop by a fixed number but going over all items.
*
* @param {Number} i Current index in the loop
* @param {Number} base Start index for which to return 0
* @param {Number} max Array length
* @returns {Number} shiftedIndex
*/
function getLookupIndex(i, base, max) {
i += base;
if (i >= max)
i -= max;
return i;
}
function Whitespace(tokens, comments) {
this.tokens = _.sortBy(tokens.concat(comments), "start");
this.used = [];
this.used = {};
// Profiling this code shows that while generator passes over it, indexes
// returned by `getNewlinesBefore` and `getNewlinesAfter` are always increasing.
// We use this implementation detail for an optimization: instead of always
// starting to look from `this.tokens[0]`, we will start `for` loops from the
// previous successful match. We will enumerate all tokens—but the common
// case will be much faster.
this._lastFoundIndex = 0;
}
Whitespace.prototype.getNewlinesBefore = function (node) {
@@ -13,13 +43,17 @@ Whitespace.prototype.getNewlinesBefore = function (node) {
var tokens = this.tokens;
var token;
for (var i = 0; i < tokens.length; i++) {
for (var j = 0; j < tokens.length; j++) {
// optimize for forward traversal by shifting for loop index
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
token = tokens[i];
// this is the token this node starts with
if (node.start === token.start) {
startToken = tokens[i - 1];
endToken = token;
this._lastFoundIndex = i;
break;
}
}
@@ -33,13 +67,17 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
var tokens = this.tokens;
var token;
for (var i = 0; i < tokens.length; i++) {
for (var j = 0; j < tokens.length; j++) {
// optimize for forward traversal by shifting for loop index
var i = getLookupIndex(j, this._lastFoundIndex, this.tokens.length);
token = tokens[i];
// this is the token this node ends with
if (node.end === token.end) {
startToken = token;
endToken = tokens[i + 1];
this._lastFoundIndex = i;
break;
}
}
@@ -60,12 +98,11 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
Whitespace.prototype.getNewlinesBetween = function (startToken, endToken) {
var start = startToken ? startToken.loc.end.line : 1;
var end = endToken.loc.start.line;
var lines = 0;
for (var line = start; line < end; line++) {
if (!_.contains(this.used, line)) {
this.used.push(line);
if (typeof this.used[line] === 'undefined') {
this.used[line] = true;
lines++;
}
}

View File

@@ -1,3 +1,5 @@
"use strict";
var transform = require("./transformation/transform");
var util = require("./util");
var fs = require("fs");

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("./types");
var _ = require("lodash");

View File

@@ -1,2 +1,4 @@
"use strict";
require("core-js/shim");
require("regenerator/runtime");

View File

@@ -1,3 +1,5 @@
"use strict";
// required to safely use 6to5/register within a browserify codebase
module.exports = function () {};

View File

@@ -1,3 +1,5 @@
"use strict";
require("./polyfill");
var sourceMapSupport = require("source-map-support");
@@ -21,51 +23,6 @@ sourceMapSupport.install({
}
});
//
var blacklist = [];
var blacklistTest = function (transformer, code) {
try {
if (_.isFunction(code)) {
code();
} else {
new Function(code);
}
blacklist.push(transformer);
} catch (err) {
if (err.name !== "SyntaxError") throw err;
}
};
blacklistTest("arrayComprehension", "var foo = [for (foo of bar) foo * foo];");
blacklistTest("generatorComprehension", "var foo = (for (foo of bar) foo * foo)");
blacklistTest("arrowFunctions", "var foo = x => x * x;");
blacklistTest("classes", "class Foo {}");
blacklistTest("computedPropertyNames", "var foo = { [foo]: bar };");
blacklistTest("constants", function () {
try {
new Function("const foo = 'foo';\nfoo = 'wow';");
} catch (err) {
return; // constants are supported
}
throw new SyntaxError;
});
blacklistTest("defaultParamaters", "var foo = function (bar = 0) {};");
blacklistTest("destructuring", "var { x, y } = { x: 0, y: 0 };");
blacklistTest("forOf", "for (var foo of bar) {}");
blacklistTest("generators", "function* foo() {}\nasync function bar() {}"); // generators/async functions delegated to same transformer
blacklistTest("letScoping", "let foo = 0;");
blacklistTest("modules", 'import foo from "from";');
blacklistTest("propertyMethodAssignment", "{ get foo() {} }");
blacklistTest("propertyNameShorthand", "var foo = { x, y };");
blacklistTest("restParameters", "function foo(...bar) {}");
blacklistTest("spread", "foo(...bar);");
blacklistTest("templateLiterals", "var foo = `foo`;");
blacklistTest("unicodeRegex", function () { new RegExp("foo", "u"); });
//
var transformOpts = {};
var ignoreRegex = /node_modules/;
var onlyRegex;
@@ -95,7 +52,6 @@ var loader = function (m, filename) {
result = result || to5.transformFileSync(filename, _.extend({
whitelist: whitelist,
blacklist: blacklist,
sourceMap: true,
ast: false
}, transformOpts));

View File

@@ -1,3 +1,5 @@
"use strict";
var generator = require("./generation/generator");
var util = require("./util");
var File = require("./file");

View File

@@ -0,0 +1,17 @@
"use strict";
/**
* A trick from Bluebird to force V8 to use fast properties for an object.
* Read more: http://stackoverflow.com/questions/24987896/
*
* Use %HasFastProperties(obj) and --allow-natives-syntax to check whether
* a particular object already has fast properties.
*/
module.exports = function toFastProperties(obj) {
/*jshint -W027*/
function f() {}
f.prototype = obj;
return f;
eval(obj);
};

View File

@@ -0,0 +1,45 @@
"use strict";
var explode = require("./explode-assignable-expression");
var t = require("../../types");
module.exports = function (exports, opts) {
var isAssignment = function (node) {
return node.operator === opts.operator + "=";
};
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (!isAssignment(expr)) return;
var nodes = [];
var exploded = explode(expr.left, nodes, file, scope, true);
nodes.push(t.expressionStatement(
buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!isAssignment(node)) return;
var nodes = [];
var exploded = explode(node.left, nodes, file, scope);
nodes.push(opts.build(exploded.uid, node.right));
nodes.push(exploded.ref);
return t.toSequenceExpression(nodes, scope);
};
exports.BinaryExpression = function (node) {
if (node.operator !== opts.operator) return;
return opts.build(node.left, node.right);
};
};

View File

@@ -0,0 +1,25 @@
"use strict";
var t = require("../../types");
module.exports = function build(node, buildBody) {
var self = node.blocks.shift();
if (!self) return;
var child = build(node, buildBody);
if (!child) {
// last item
child = buildBody();
// add a filter as this is our final stop
if (node.filter) {
child = t.ifStatement(node.filter, t.blockStatement([child]));
}
}
return t.forOfStatement(
t.variableDeclaration("let", [t.variableDeclarator(self.left)]),
self.right,
t.blockStatement([child])
);
};

View File

@@ -0,0 +1,45 @@
"use strict";
var explode = require("./explode-assignable-expression");
var t = require("../../types");
module.exports = function (exports, opts) {
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (!opts.is(expr, file)) return;
var nodes = [];
var exploded = explode(expr.left, nodes, file, scope);
nodes.push(t.ifStatement(
opts.build(exploded.uid, file),
t.expressionStatement(buildAssignment(exploded.ref, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!opts.is(node, file)) return;
var nodes = [];
var exploded = explode(node.left, nodes, file, scope);
nodes.push(t.logicalExpression(
"&&",
opts.build(exploded.uid, file),
buildAssignment(exploded.ref, node.right)
));
// todo: duplicate expression node
nodes.push(exploded.ref);
return t.toSequenceExpression(nodes, scope);
};
};

View File

@@ -0,0 +1,57 @@
"use strict";
var t = require("../../types");
var getObjRef = function (node, nodes, file, scope) {
var ref;
if (t.isIdentifier(node)) {
ref = node;
} else if (t.isMemberExpression(node)) {
ref = node.object;
} else {
throw new Error("We can't explode this node type " + node.type);
}
var temp = scope.generateUidBasedOnNode(ref, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, ref)
]));
return temp;
};
var getPropRef = function (node, nodes, file, scope) {
var prop = node.property;
var key = t.toComputedKey(node, prop);
if (t.isLiteral(key)) return key;
var temp = scope.generateUidBasedOnNode(prop, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, prop)
]));
return temp;
};
module.exports = function (node, nodes, file, scope, allowedSingleIdent) {
var obj;
if (t.isIdentifier(node) && allowedSingleIdent) {
obj = node;
} else {
obj = getObjRef(node, nodes, file, scope);
}
var ref, uid;
if (t.isIdentifier(node)) {
ref = node;
uid = obj;
} else {
var prop = getPropRef(node, nodes, file, scope);
var computed = node.computed || t.isLiteral(prop);
uid = ref = t.memberExpression(obj, prop, computed);
}
return {
uid: uid,
ref: ref
};
};

View File

@@ -0,0 +1,50 @@
"use strict";
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var traverser = {
enter: function (node, parent, scope, context, state) {
// check if this node is an identifier that matches the same as our function id
if (!t.isIdentifier(node, { name: state.id })) return;
// check if this node is the one referenced
if (!t.isReferenced(node, parent)) return;
// check that we don't have a local variable declared as that removes the need
// for the wrapper
var localDeclar = scope.get(state.id, true);
if (localDeclar !== state.outerDeclar) return;
state.selfReference = true;
context.stop();
}
};
exports.property = function (node, file, scope) {
var key = t.toComputedKey(node, node.key);
if (!t.isLiteral(key)) return node; // we can't set a function id with this
var id = t.toIdentifier(key.value);
key = t.identifier(id);
var state = {
id: id,
selfReference: false,
outerDeclar: scope.get(id, true),
};
traverse(node, traverser, scope, state);
if (state.selfReference) {
node.value = util.template("property-method-assignment-wrapper", {
FUNCTION: node.value,
FUNCTION_ID: key,
FUNCTION_KEY: file.generateUidIdentifier(id, scope),
WRAPPER_KEY: file.generateUidIdentifier(id + "Wrapper", scope)
});
} else {
node.value.id = key;
}
};

View File

@@ -0,0 +1,31 @@
"use strict";
var traverse = require("../../traverse");
var t = require("../../types");
module.exports = function (node, callId) {
node.async = false;
node.generator = true;
traverse(node, {
enter: function (node, parent, scope, context) {
if (t.isFunction(node)) context.skip();
if (t.isAwaitExpression(node)) {
node.type = "YieldExpression";
}
}
});
var call = t.callExpression(callId, [node]);
if (t.isFunctionDeclaration(node)) {
var declar = t.variableDeclaration("var", [
t.variableDeclarator(node.id, call)
]);
declar._blockHoist = true;
return declar;
} else {
return call;
}
};

View File

@@ -0,0 +1,246 @@
"use strict";
module.exports = ReplaceSupers;
var traverse = require("../../traverse");
var t = require("../../types");
/**
* Description
*
* @param {Object} methodNode
* @param {Object} className
* @param {Object} superName
* @param {Boolean} isLoose
* @param {File} file
*/
function ReplaceSupers(methodNode, className, superName, isLoose, file) {
this.topLevelThisReference = null;
this.methodNode = methodNode;
this.className = className;
this.superName = superName;
this.isLoose = isLoose;
this.file = file;
}
/**
* Gets a node representing the super class value of the named property.
*
* @example
*
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
*
* @param {Node} property
* @param {boolean} isStatic
* @param {boolean} isComputed
*
* @returns {Node}
*/
ReplaceSupers.prototype.superProperty = function (property, isStatic, isComputed, thisExpression) {
return t.callExpression(
this.file.addHelper("get"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name),
thisExpression
]
);
};
/**
* Description
*
* @param {Object} node
* @param {Object} id
* @param {Object} parent
* @returns {Object}
*/
ReplaceSupers.prototype.looseSuperProperty = function (methodNode, id, parent) {
var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function");
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superName, t.identifier("call"));
} else {
id = superName;
// foo() { super(); }
if (!methodNode.static) {
id = t.memberExpression(id, t.identifier("prototype"));
}
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
return t.memberExpression(superName, t.identifier("prototype"));
} else {
return superName;
}
};
/**
* Description
*/
ReplaceSupers.prototype.replace = function () {
this.traverseLevel(this.methodNode.value, true);
};
/**
* Description
*
* @param {Object} node
* @param {Boolean} topLevel
*/
ReplaceSupers.prototype.traverseLevel = function (node, topLevel) {
var self = this;
traverse(node, {
enter: function (node, parent, scope, context) {
if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
// we need to call traverseLevel again so we're context aware
self.traverseLevel(node, false);
return context.skip();
}
if (t.isProperty(node, { method: true }) || t.isMethodDefinition(node)) {
// break on object methods
return context.skip();
}
var getThisReference = function () {
if (topLevel) {
// top level so `this` is the instance
return t.thisExpression();
} else {
// not in the top level so we need to create a reference
return self.getThisReference();
}
};
var callback = self.specHandle;
if (self.isLoose) callback = self.looseHandle;
return callback.call(self, getThisReference, node, parent);
}
});
};
/**
* Description
*/
ReplaceSupers.prototype.getThisReference = function () {
if (this.topLevelThisReference) {
return this.topLevelThisReference;
} else {
var ref = this.topLevelThisReference = this.file.generateUidIdentifier("this");
this.methodNode.value.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(this.topLevelThisReference, t.thisExpression())
]));
return ref;
}
};
/**
* Description
*
* @param {Function} getThisReference
* @param {Object} node
* @param {Object} parent
*/
ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return this.looseSuperProperty(this.methodNode, node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference());
}
};
/**
* Description
*
* @param {Function} getThisReference
* @param {Object} node
* @param {Object} parent
*/
ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
var methodNode = this.methodNode;
var property;
var computed;
var args;
if (t.isIdentifier(node, { name: "super" })) {
if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) {
throw this.file.errorWithNode(node, "illegal use of bare super");
}
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (t.isIdentifier(callee, { name: "super" })) {
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
property = methodNode.key;
computed = methodNode.computed;
args = node.arguments;
} else {
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
property = callee.property;
computed = callee.computed;
args = node.arguments;
}
} else if (t.isMemberExpression(node)) {
if (!t.isIdentifier(node.object, { name: "super" })) return;
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
property = node.property;
computed = node.computed;
}
if (!property) return;
var thisReference = getThisReference();
var superProperty = this.superProperty(property, methodNode.static, computed, thisReference);
if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments);
return t.callExpression(
t.memberExpression(superProperty, t.identifier("apply")),
[thisReference, args[0].argument]
);
} else {
return t.callExpression(
t.memberExpression(superProperty, t.identifier("call")),
[thisReference].concat(args)
);
}
} else {
return superProperty;
}
};

View File

@@ -0,0 +1,21 @@
"use strict";
var t = require("../../types");
exports.has = function (node) {
var first = node.body[0];
return t.isExpressionStatement(first) && t.isLiteral(first.expression, { value: "use strict" });
};
exports.wrap = function (node, callback) {
var useStrictNode;
if (exports.has(node)) {
useStrictNode = node.body.shift();
}
callback();
if (useStrictNode) {
node.body.unshift(useStrictNode);
}
};

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = DefaultFormatter;
var traverse = require("../../traverse");
@@ -16,35 +18,51 @@ function DefaultFormatter(file) {
//this.checkCollisions();
}
var exportsTraverser = {
enter: function (node, parent, scope, context, localExports) {
var declar = node && node.declaration;
if (t.isExportDeclaration(node) && declar && t.isStatement(declar)) {
_.extend(localExports, t.getIds(declar, true));
}
}
};
DefaultFormatter.prototype.getLocalExports = function () {
var localExports = {};
traverse(this.file.ast, {
enter: function (node) {
var declar = node && node.declaration;
if (t.isExportDeclaration(node) && declar && t.isStatement(declar)) {
_.extend(localExports, t.getIds(declar, true));
}
}
});
traverse(this.file.ast, exportsTraverser, null, localExports);
return localExports;
};
var importsTraverser = {
enter: function (node, parent, scope, context, localImports) {
if (t.isImportDeclaration(node)) {
_.extend(localImports, t.getIds(node, true));
}
}
};
DefaultFormatter.prototype.getLocalImports = function () {
var localImports = {};
traverse(this.file.ast, {
enter: function (node) {
if (t.isImportDeclaration(node)) {
_.extend(localImports, t.getIds(node, true));
}
}
});
traverse(this.file.ast, importsTraverser, null, localImports);
return localImports;
};
var collissionsTraverser = {
enter: function (node, parent, scope, context, check) {
if (t.isAssignmentExpression(node)) {
var left = node.left;
if (t.isMemberExpression(left)) {
while (left.object) left = left.object;
}
check(left);
} else if (t.isDeclaration(node)) {
_.each(t.getIds(node, true), check);
}
}
};
DefaultFormatter.prototype.checkCollisions = function () {
// todo: all check export collissions
@@ -61,21 +79,7 @@ DefaultFormatter.prototype.checkCollisions = function () {
}
};
traverse(file.ast, {
enter: function (node) {
if (t.isAssignmentExpression(node)) {
var left = node.left;
if (t.isMemberExpression(left)) {
while (left.object) left = left.object;
}
check(left);
} else if (t.isDeclaration(node)) {
_.each(t.getIds(node, true), check);
}
}
});
traverse(file.ast, collissionsTraverser, null, check);
};
DefaultFormatter.prototype.remapExportAssignment = function (node) {
@@ -100,9 +104,9 @@ DefaultFormatter.prototype.remapAssignments = function () {
};
traverse(this.file.ast, {
enter: function (node, parent, scope) {
enter: function (node, parent, scope, context, isLocalReference) {
if (t.isUpdateExpression(node) && isLocalReference(node.argument, scope)) {
this.skip();
context.skip();
// expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));
@@ -130,11 +134,11 @@ DefaultFormatter.prototype.remapAssignments = function () {
}
if (t.isAssignmentExpression(node) && isLocalReference(node.left, scope)) {
this.skip();
context.skip();
return self.remapExportAssignment(node);
}
}
});
}, null, isLocalReference);
};
DefaultFormatter.prototype.getModuleName = function () {
@@ -244,13 +248,13 @@ DefaultFormatter.prototype.exportDeclaration = function (node, nodes) {
var assign;
if (t.isVariableDeclaration(declar)) {
for (var i in declar.declarations) {
for (var i = 0; i < declar.declarations.length; i++) {
var decl = declar.declarations[i];
decl.init = this._exportsAssign(decl.id, decl.init, node).expression;
var newDeclar = t.variableDeclaration(declar.kind, [decl]);
if (i === "0") t.inherits(newDeclar, declar);
if (i === 0) t.inherits(newDeclar, declar);
nodes.push(newDeclar);
}
} else {

View File

@@ -1,3 +1,5 @@
"use strict";
var util = require("../../util");
module.exports = function (Parent) {

View File

@@ -1 +1,3 @@
"use strict";
module.exports = require("./_strict")(require("./amd"));

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = AMDFormatter;
var DefaultFormatter = require("./_default");

View File

@@ -1 +1,3 @@
"use strict";
module.exports = require("./_strict")(require("./common"));

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = CommonJSFormatter;
var DefaultFormatter = require("./_default");

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = IgnoreFormatter;
var t = require("../../types");

View File

@@ -1,7 +1,9 @@
"use strict";
module.exports = SystemFormatter;
var AMDFormatter = require("./amd");
var useStrict = require("../transformers/use-strict");
var useStrict = require("../helpers/use-strict");
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
@@ -63,28 +65,31 @@ SystemFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
SystemFormatter.prototype.buildRunnerSetters = function (block, hoistDeclarators) {
return t.arrayExpression(_.map(this.ids, function (uid, source) {
var nodes = [];
var state = {
nodes: [],
hoistDeclarators: hoistDeclarators
};
traverse(block, {
enter: function (node) {
enter: function (node, parent, scope, context, state) {
if (node._importSource === source) {
if (t.isVariableDeclaration(node)) {
_.each(node.declarations, function (declar) {
hoistDeclarators.push(t.variableDeclarator(declar.id));
nodes.push(t.expressionStatement(
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
state.nodes.push(t.expressionStatement(
t.assignmentExpression("=", declar.id, declar.init)
));
});
} else {
nodes.push(node);
state.nodes.push(node);
}
this.remove();
context.remove();
}
}
});
}, null, state);
return t.functionExpression(null, [uid], t.blockStatement(nodes));
return t.functionExpression(null, [uid], t.blockStatement(state.nodes));
}));
};
@@ -112,10 +117,10 @@ SystemFormatter.prototype.transform = function (ast) {
// hoist up all variable declarations
traverse(block, {
enter: function (node, parent, scope) {
enter: function (node, parent, scope, context, hoistDeclarators) {
if (t.isFunction(node)) {
// nothing inside is accessible
return this.skip();
return context.skip();
}
if (t.isVariableDeclaration(node)) {
@@ -150,7 +155,8 @@ SystemFormatter.prototype.transform = function (ast) {
return nodes;
}
}
});
}, null, hoistDeclarators);
if (hoistDeclarators.length) {
var hoistDeclar = t.variableDeclaration("var", hoistDeclarators);
hoistDeclar._blockHoist = true;
@@ -159,19 +165,19 @@ SystemFormatter.prototype.transform = function (ast) {
// hoist up function declarations for circular references
traverse(block, {
enter: function (node) {
if (t.isFunction(node)) this.skip();
enter: function (node, parent, scope, context, handlerBody) {
if (t.isFunction(node)) context.skip();
if (t.isFunctionDeclaration(node) || node._blockHoist) {
handlerBody.push(node);
this.remove();
context.remove();
}
}
});
}, null, handlerBody);
handlerBody.push(returnStatement);
if (useStrict._has(block)) {
if (useStrict.has(block)) {
handlerBody.unshift(block.body.shift());
}

View File

@@ -1 +1,3 @@
"use strict";
module.exports = require("./_strict")(require("./umd"));

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = UMDFormatter;
var AMDFormatter = require("./amd");

View File

@@ -1,3 +0,0 @@
ARRAY.forEach(function (KEY) {
});

View File

@@ -1,3 +1,3 @@
for (var KEY = START; KEY < ARGUMENTS.length; KEY++) {
for (var LEN = ARGUMENTS.length, ARRAY = Array(ARRAY_LEN), KEY = START; KEY < LEN; KEY++) {
ARRAY[ARRAY_KEY] = ARGUMENTS[KEY];
}

View File

@@ -1,3 +1,5 @@
"use strict";
module.exports = transform;
var Transformer = require("./transformer");
@@ -20,7 +22,7 @@ transform.fromAst = function (ast, code, opts) {
};
transform._ensureTransformerNames = function (type, keys) {
for (var i in keys) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!_.has(transform.transformers, key)) {
throw new ReferenceError("unknown transformer " + key + " specified in " + type);
@@ -44,8 +46,10 @@ transform.moduleFormatters = {
_.each({
specNoForInOfAssignment: require("./transformers/spec-no-for-in-of-assignment"),
specSetters: require("./transformers/spec-setters"),
specBlockScopedFunctions: require("./transformers/spec-block-scoped-functions"),
// playground
malletOperator: require("./transformers/playground-mallet-operator"),
methodBinding: require("./transformers/playground-method-binding"),
memoizationOperator: require("./transformers/playground-memoization-operator"),
objectGetterMemoization: require("./transformers/playground-object-getter-memoization"),
@@ -67,14 +71,15 @@ _.each({
templateLiterals: require("./transformers/es6-template-literals"),
propertyMethodAssignment: require("./transformers/es6-property-method-assignment"),
computedPropertyNames: require("./transformers/es6-computed-property-names"),
destructuring: require("./transformers/es6-destructuring"),
defaultParameters: require("./transformers/es6-default-parameters"),
destructuring: require("./transformers/es6-destructuring"),
forOf: require("./transformers/es6-for-of"),
unicodeRegex: require("./transformers/es6-unicode-regex"),
abstractReferences: require("./transformers/es7-abstract-references"),
constants: require("./transformers/es6-constants"),
letScoping: require("./transformers/es6-let-scoping"),
blockScopingTDZ: require("./transformers/optional-block-scoping-tdz"),
_blockHoist: require("./transformers/_block-hoist"),
@@ -93,6 +98,7 @@ _.each({
typeofSymbol: require("./transformers/optional-typeof-symbol"),
coreAliasing: require("./transformers/optional-core-aliasing"),
undefinedToVoid: require("./transformers/optional-undefined-to-void"),
undeclaredVariableCheck: require("./transformers/optional-undeclared-variable-check"),
// spec
specPropertyLiterals: require("./transformers/spec-property-literals"),

View File

@@ -1,9 +1,30 @@
"use strict";
module.exports = Transformer;
var traverse = require("../traverse");
var t = require("../types");
var _ = require("lodash");
function noop() { }
function enter(node, parent, scope, context, args) {
var fns = args[1][node.type];
if (!fns) return;
return fns.enter(node, parent, scope, context, args[0]);
}
function exit(node, parent, scope, context, args) {
var fns = args[1][node.type];
if (!fns) return;
return fns.exit(node, parent, scope, context, args[0]);
}
var traverseOpts = {
enter: enter,
exit: exit
};
function Transformer(key, transformer, opts) {
this.manipulateOptions = transformer.manipulateOptions;
this.experimental = !!transformer.experimental;
@@ -32,6 +53,9 @@ Transformer.prototype.normalise = function (transformer) {
if (!_.isObject(fns)) return;
if (!fns.enter) fns.enter = noop;
if (!fns.exit) fns.exit = noop;
transformer[type] = fns;
var aliases = t.FLIPPED_ALIAS_KEYS[type];
@@ -54,28 +78,8 @@ Transformer.prototype.astRun = function (file, key) {
};
Transformer.prototype.transform = function (file) {
var transformer = this.transformer;
var build = function (exit) {
return function (node, parent, scope) {
var fns = transformer[node.type];
if (!fns) return;
var fn = fns.enter;
if (exit) fn = fns.exit;
if (!fn) return;
return fn.call(this, node, parent, file, scope);
};
};
this.astRun(file, "before");
traverse(file.ast, {
enter: build(),
exit: build(true)
});
traverse(file.ast, traverseOpts, null, [file, this.transformer]);
this.astRun(file, "after");
};

View File

@@ -1,57 +1,64 @@
"use strict";
var traverse = require("../../traverse");
var t = require("../../types");
var functionChildrenTraverser = {
enter: function (node, parent, scope, context, state) {
if (t.isFunction(node) && !node._aliasFunction) {
return context.skip();
}
if (node._ignoreAliasFunctions) return context.skip();
var getId;
if (t.isIdentifier(node) && node.name === "arguments") {
getId = state.getArgumentsId;
} else if (t.isThisExpression(node)) {
getId = state.getThisId;
} else {
return;
}
if (t.isReferenced(node, parent)) return getId();
}
};
var functionTraverser = {
enter: function (node, parent, scope, context, state) {
if (!node._aliasFunction) {
if (t.isFunction(node)) {
// stop traversal of this node as it'll be hit again by this transformer
return context.skip();
} else {
return;
}
}
// traverse all child nodes of this function and find `arguments` and `this`
traverse(node, functionChildrenTraverser, null, state);
return context.skip();
}
};
var go = function (getBody, node, file, scope) {
var argumentsId;
var thisId;
var getArgumentsId = function () {
return argumentsId = argumentsId || file.generateUidIdentifier("arguments", scope);
};
var getThisId = function () {
return thisId = thisId || file.generateUidIdentifier("this", scope);
var state = {
getArgumentsId: function () {
return argumentsId = argumentsId || file.generateUidIdentifier("arguments", scope);
},
getThisId: function () {
return thisId = thisId || file.generateUidIdentifier("this", scope);
}
};
// traverse the function and find all alias functions so we can alias
// `arguments` and `this` if necessary
traverse(node, {
enter: function (node) {
if (!node._aliasFunction) {
if (t.isFunction(node)) {
// stop traversal of this node as it'll be hit again by this transformer
return this.skip();
} else {
return;
}
}
// traverse all child nodes of this function and find `arguments` and `this`
traverse(node, {
enter: function (node, parent) {
if (t.isFunction(node) && !node._aliasFunction) {
return this.skip();
}
if (node._ignoreAliasFunctions) return this.skip();
var getId;
if (t.isIdentifier(node) && node.name === "arguments") {
getId = getArgumentsId;
} else if (t.isThisExpression(node)) {
getId = getThisId;
} else {
return;
}
if (t.isReferenced(node, parent)) return getId();
}
});
return this.skip();
}
});
traverse(node, functionTraverser, null, state);
var body;
@@ -71,14 +78,14 @@ var go = function (getBody, node, file, scope) {
}
};
exports.Program = function (node, parent, file, scope) {
exports.Program = function (node, parent, scope, context, file) {
go(function () {
return node.body;
}, node, file, scope);
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, file, scope) {
exports.FunctionExpression = function (node, parent, scope, context, file) {
go(function () {
t.ensureBlock(node);
return node.body.body;

View File

@@ -1,4 +1,6 @@
var useStrict = require("./use-strict");
"use strict";
var useStrict = require("../helpers/use-strict");
var _ = require("lodash");
// Priority:
@@ -12,13 +14,13 @@ exports.BlockStatement =
exports.Program = {
exit: function (node) {
var hasChange = false;
for (var i in node.body) {
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (bodyNode && bodyNode._blockHoist != null) hasChange = true;
}
if (!hasChange) return;
useStrict._wrap(node, function () {
useStrict.wrap(node, function () {
var nodePriorities = _.groupBy(node.body, function (bodyNode) {
var priority = bodyNode._blockHoist;
if (priority == null) priority = 1;

View File

@@ -1,14 +1,18 @@
var useStrict = require("./use-strict");
"use strict";
var useStrict = require("../helpers/use-strict");
var t = require("../../types");
exports.secondPass = true;
exports.BlockStatement =
exports.Program = function (node) {
if (!node._declarations) return;
var kinds = {};
var kind;
useStrict._wrap(node, function () {
useStrict.wrap(node, function () {
for (var i in node._declarations) {
var declar = node._declarations[i];

View File

@@ -1,3 +1,5 @@
"use strict";
var transform = require("../transform");
exports.ast = {

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
exports.ArrowFunctionExpression = function (node) {

View File

@@ -1,20 +1,23 @@
var propertyMethodAssignment = require("./es6-property-method-assignment");
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
"use strict";
exports.ClassDeclaration = function (node, parent, file, scope) {
var ReplaceSupers = require("../helpers/replace-supers");
var nameMethod = require("../helpers/name-method");
var util = require("../../util");
var t = require("../../types");
exports.ClassDeclaration = function (node, parent, scope, context, file) {
return new Class(node, file, scope, true).run();
};
exports.ClassExpression = function (node, parent, file, scope) {
exports.ClassExpression = function (node, parent, scope, context, file) {
if (!node.id) {
if (t.isProperty(parent) && parent.value === node && !parent.computed && t.isIdentifier(parent.key)) {
// var o = { foo: class {} };
node.id = parent.key;
}
if (t.isVariableDeclarator(parent)) {
if (t.isVariableDeclarator(parent) && t.isIdentifier(parent.id)) {
// var foo = class {};
node.id = parent.id;
}
}
@@ -131,10 +134,11 @@ Class.prototype.buildBody = function () {
var classBody = this.node.body.body;
var body = this.body;
for (var i in classBody) {
for (var i = 0; i < classBody.length; i++) {
var node = classBody[i];
if (t.isMethodDefinition(node)) {
this.replaceInstanceSuperReferences(node);
var replaceSupers = new ReplaceSupers(node, this.className, this.superName, this.isLoose, this.file);
replaceSupers.replace();
if (node.key.name === "constructor") {
this.pushConstructor(node);
@@ -193,7 +197,7 @@ Class.prototype.pushMethod = function (node) {
var kind = node.kind;
if (kind === "") {
propertyMethodAssignment._namedMethod(node, this.file, this.scope);
nameMethod.property(node, this.file, this.scope);
if (this.isLoose) {
// use assignments instead of define properties for loose classes
@@ -222,193 +226,6 @@ Class.prototype.pushMethod = function (node) {
util.pushMutatorMap(mutatorMap, methodName, kind, node.computed, node);
};
/**
* Gets a node representing the super class value of the named property.
*
* @example
*
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
*
* @param {Node} property
* @param {boolean} isStatic
* @param {boolean} isComputed
*
* @returns {Node}
*/
Class.prototype.superProperty = function (property, isStatic, isComputed, thisExpression) {
return t.callExpression(
this.file.addHelper("get"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name),
thisExpression
]
);
};
/**
* Description
*
* @param {Object} node
* @param {Object} id
* @param {Object} parent
* @returns {Object}
*/
Class.prototype.looseSuperProperty = function (methodNode, id, parent) {
var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function");
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superName, t.identifier("call"));
} else {
id = superName;
// foo() { super(); }
if (!methodNode.static) {
id = t.memberExpression(id, t.identifier("prototype"));
}
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
return t.memberExpression(superName, t.identifier("prototype"));
} else {
return superName;
}
};
/**
* Replace all `super` references with a reference to our `superClass`.
*
* @param {Node} methodNode MethodDefinition
*/
Class.prototype.replaceInstanceSuperReferences = function (methodNode) {
var method = methodNode.value;
var self = this;
var topLevelThisReference;
traverseLevel(method, true);
if (topLevelThisReference) {
method.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(topLevelThisReference, t.thisExpression())
]));
}
function traverseLevel(node, topLevel) {
traverse(node, {
enter: function (node, parent) {
if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
// we need to call traverseLevel again so we're context aware
traverseLevel(node, false);
return this.skip();
}
var getThisReference = function () {
if (topLevel) {
// top level so `this` is the instance
return t.thisExpression();
} else {
// not in the top level so we need to create a reference
return topLevelThisReference = topLevelThisReference || self.file.generateUidIdentifier("this");
}
};
var callback = specHandle;
if (self.isLoose) callback = looseHandle;
return callback(getThisReference, node, parent);
}
});
}
function looseHandle(getThisReference, node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return self.looseSuperProperty(methodNode, node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference());
}
}
function specHandle(getThisReference, node, parent) {
var property;
var computed;
var args;
if (t.isIdentifier(node, { name: "super" })) {
if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) {
throw self.file.errorWithNode(node, "illegal use of bare super");
}
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (t.isIdentifier(callee, { name: "super" })) {
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
property = methodNode.key;
computed = methodNode.computed;
args = node.arguments;
} else {
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
property = callee.property;
computed = callee.computed;
args = node.arguments;
}
} else if (t.isMemberExpression(node)) {
if (!t.isIdentifier(node.object, { name: "super" })) return;
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
property = node.property;
computed = node.computed;
}
if (!property) return;
var thisReference = getThisReference();
var superProperty = self.superProperty(property, methodNode.static, computed, thisReference);
if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments);
return t.callExpression(
t.memberExpression(superProperty, t.identifier("apply")),
[thisReference, args[0].argument]
);
} else {
return t.callExpression(
t.memberExpression(superProperty, t.identifier("call")),
[thisReference].concat(args)
);
}
} else {
return superProperty;
}
}
};
/**
* Replace the constructor body of our class.
*

View File

@@ -1,9 +1,11 @@
"use strict";
var t = require("../../types");
exports.ObjectExpression = function (node, parent, file, scope) {
exports.ObjectExpression = function (node, parent, scope, context, file) {
var hasComputed = false;
for (var i in node.properties) {
for (var i = 0; i < node.properties.length; i++) {
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
if (hasComputed) break;
}
@@ -39,7 +41,7 @@ exports.ObjectExpression = function (node, parent, file, scope) {
};
var loose = function (node, body, objId) {
for (var i in node.properties) {
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
body.push(t.expressionStatement(
@@ -58,7 +60,7 @@ var spec = function (node, body, objId, initProps, file) {
// normalise key
for (var i in props) {
for (var i = 0; i < props.length; i++) {
prop = props[i];
if (prop.kind !== "init") continue;
@@ -73,7 +75,7 @@ var spec = function (node, body, objId, initProps, file) {
var broken = false;
for (i in props) {
for (i = 0; i < props.length; i++) {
prop = props[i];
if (prop.computed) {
@@ -89,7 +91,7 @@ var spec = function (node, body, objId, initProps, file) {
// add a simple assignment for all Symbol member expressions due to symbol polyfill limitations
// otherwise use Object.defineProperty
for (i in props) {
for (i = 0; i < props.length; i++) {
prop = props[i];
if (!prop) continue;

View File

@@ -1,3 +1,5 @@
"use strict";
var traverse = require("../../traverse");
var t = require("../../types");
var _ = require("lodash");
@@ -6,7 +8,7 @@ exports.Program =
exports.BlockStatement =
exports.ForInStatement =
exports.ForOfStatement =
exports.ForStatement = function (node, parent, file) {
exports.ForStatement = function (node, parent, scope, context, file) {
var hasConstants = false;
var constants = {};
@@ -44,7 +46,7 @@ exports.ForStatement = function (node, parent, file) {
}
if (t.isVariableDeclaration(child, { kind: "const" })) {
for (var i in child.declarations) {
for (var i = 0; i < child.declarations.length; i++) {
var declar = child.declarations[i];
var ids = getIds(declar);
@@ -69,14 +71,19 @@ exports.ForStatement = function (node, parent, file) {
if (!hasConstants) return;
var state = {
check: check,
getIds: getIds
};
traverse(node, {
enter: function (child, parent, scope) {
enter: function (child, parent, scope, context, state) {
if (child._ignoreConstant) return;
if (t.isVariableDeclaration(child)) return;
if (t.isVariableDeclarator(child) || t.isDeclaration(child) || t.isAssignmentExpression(child)) {
check(parent, getIds(child), scope);
state.check(parent, state.getIds(child), scope);
}
}
});
}, null, state);
};

View File

@@ -1,8 +1,10 @@
"use strict";
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
exports.Function = function (node, parent, file, scope) {
exports.Function = function (node, parent, scope, context, file) {
if (!node.defaults || !node.defaults.length) return;
t.ensureBlock(node);
@@ -11,12 +13,11 @@ exports.Function = function (node, parent, file, scope) {
});
var iife = false;
var i;
var def;
var checkTDZ = function (ids) {
var checkTDZ = function (param, def, ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (!t.isReferencedIdentifier(node, parent)) return;
if (ids.indexOf(node.name) >= 0) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
@@ -28,10 +29,13 @@ exports.Function = function (node, parent, file, scope) {
};
check(def, node);
traverse(def, { enter: check });
if (!t.isPattern(param)) {
traverse(def, { enter: check });
}
};
for (i in node.defaults) {
for (var i = 0; i < node.defaults.length; i++) {
def = node.defaults[i];
if (!def) continue;
@@ -40,8 +44,8 @@ exports.Function = function (node, parent, file, scope) {
// temporal dead zone check - here we prevent accessing of params that
// are to the right - ie. uninitialized parameters
var rightIds = ids.slice(i);
for (i in rightIds) {
checkTDZ(rightIds[i]);
for (var i2 = 0; i2 < rightIds.length; i2++) {
checkTDZ(param, def, rightIds[i2]);
}
// we're accessing a variable that's already defined within this function
@@ -58,19 +62,21 @@ exports.Function = function (node, parent, file, scope) {
var lastNonDefaultParam = 0;
for (i in node.defaults) {
for (i = 0; i < node.defaults.length; i++) {
def = node.defaults[i];
if (!def) {
lastNonDefaultParam = +i + 1;
continue;
}
body.push(util.template("default-parameter", {
var defNode = util.template("default-parameter", {
VARIABLE_NAME: node.params[i],
DEFAULT_VALUE: def,
ARGUMENT_KEY: t.literal(+i),
ARGUMENTS: argsIdentifier
}, true));
}, true);
defNode._blockHoist = node.defaults.length - i;
body.push(defNode);
}
// we need to cut off all trailing default parameters

View File

@@ -1,3 +1,5 @@
"use strict";
// TODO: Clean up
var t = require("../../types");
@@ -6,13 +8,27 @@ var buildVariableAssign = function (opts, id, init) {
var op = opts.operator;
if (t.isMemberExpression(id)) op = "=";
var node;
if (op) {
return t.expressionStatement(t.assignmentExpression("=", id, init));
node = t.expressionStatement(t.assignmentExpression(op, id, init));
} else {
return t.variableDeclaration(opts.kind, [
node = t.variableDeclaration(opts.kind, [
t.variableDeclarator(id, init)
]);
}
node._blockHoist = opts.blockHoist;
return node;
};
var buildVariableDeclar = function (opts, id, init) {
var declar = t.variableDeclaration("var", [
t.variableDeclarator(id, init)
]);
declar._blockHoist = opts.blockHoist;
return declar;
};
var push = function (opts, nodes, elem, parentId) {
@@ -46,12 +62,12 @@ var pushAssignmentPattern = function (opts, nodes, pattern, parentId) {
};
var pushObjectPattern = function (opts, nodes, pattern, parentId) {
for (var i in pattern.properties) {
for (var i = 0; i < pattern.properties.length; i++) {
var prop = pattern.properties[i];
if (t.isSpreadProperty(prop)) {
// get all the keys that appear in this object before the current spread
var keys = [];
for (var i2 in pattern.properties) {
for (var i2 = 0; i2 < pattern.properties.length; i2++) {
var prop2 = pattern.properties[i2];
if (i2 >= i) break;
@@ -88,7 +104,7 @@ var pushArrayPattern = function (opts, nodes, pattern, parentId) {
var i;
var hasSpreadElement = false;
for (i in pattern.elements) {
for (i = 0; i < pattern.elements.length; i++) {
if (t.isSpreadElement(pattern.elements[i])) {
hasSpreadElement = true;
break;
@@ -98,12 +114,10 @@ var pushArrayPattern = function (opts, nodes, pattern, parentId) {
var toArray = opts.file.toArray(parentId, !hasSpreadElement && pattern.elements.length);
var _parentId = opts.scope.generateUidBasedOnNode(parentId, opts.file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(_parentId, toArray)
]));
nodes.push(buildVariableDeclar(opts, _parentId, toArray));
parentId = _parentId;
for (i in pattern.elements) {
for (i = 0; i < pattern.elements.length; i++) {
var elem = pattern.elements[i];
if (!elem) continue;
@@ -136,11 +150,7 @@ var pushPattern = function (opts) {
if (!t.isArrayExpression(parentId) && !t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) {
var key = scope.generateUidBasedOnNode(parentId, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(key, parentId)
]));
nodes.push(buildVariableDeclar(opts, key, parentId));
parentId = key;
}
@@ -148,7 +158,7 @@ var pushPattern = function (opts) {
};
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, file, scope) {
exports.ForOfStatement = function (node, parent, scope, context, file) {
var declar = node.left;
if (!t.isVariableDeclaration(declar)) return;
@@ -174,24 +184,25 @@ exports.ForOfStatement = function (node, parent, file, scope) {
block.body = nodes.concat(block.body);
};
exports.Function = function (node, parent, file, scope) {
exports.Function = function (node, parent, scope, context, file) {
var nodes = [];
var hasDestructuring = false;
node.params = node.params.map(function (pattern) {
node.params = node.params.map(function (pattern, i) {
if (!t.isPattern(pattern)) return pattern;
hasDestructuring = true;
var parentId = file.generateUidIdentifier("ref", scope);
pushPattern({
kind: "var",
nodes: nodes,
pattern: pattern,
id: parentId,
file: file,
scope: scope
blockHoist: node.params.length - i,
pattern: pattern,
nodes: nodes,
scope: scope,
file: file,
kind: "var",
id: parentId
});
return parentId;
@@ -205,7 +216,7 @@ exports.Function = function (node, parent, file, scope) {
block.body = nodes.concat(block.body);
};
exports.CatchClause = function (node, parent, file, scope) {
exports.CatchClause = function (node, parent, scope, context, file) {
var pattern = node.param;
if (!t.isPattern(pattern)) return;
@@ -223,7 +234,7 @@ exports.CatchClause = function (node, parent, file, scope) {
node.body.body = nodes.concat(node.body.body);
};
exports.ExpressionStatement = function (node, parent, file, scope) {
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (expr.type !== "AssignmentExpression") return;
@@ -245,14 +256,13 @@ exports.ExpressionStatement = function (node, parent, file, scope) {
return nodes;
};
exports.AssignmentExpression = function (node, parent, file, scope) {
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (parent.type === "ExpressionStatement") return;
if (!t.isPattern(node.left)) return;
var tempName = file.generateUid("temp", scope);
var ref = t.identifier(tempName);
var ref = file.generateUidIdentifier("temp", scope);
scope.push({
key: tempName,
key: ref.name,
id: ref
});
@@ -270,7 +280,7 @@ exports.AssignmentExpression = function (node, parent, file, scope) {
return t.toSequenceExpression(nodes, scope);
};
exports.VariableDeclaration = function (node, parent, file, scope) {
exports.VariableDeclaration = function (node, parent, scope, context, file) {
if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;
var nodes = [];
@@ -278,7 +288,7 @@ exports.VariableDeclaration = function (node, parent, file, scope) {
var declar;
var hasPattern = false;
for (i in node.declarations) {
for (i = 0; i < node.declarations.length; i++) {
declar = node.declarations[i];
if (t.isPattern(declar.id)) {
hasPattern = true;
@@ -287,18 +297,18 @@ exports.VariableDeclaration = function (node, parent, file, scope) {
}
if (!hasPattern) return;
for (i in node.declarations) {
for (i = 0; i < node.declarations.length; i++) {
declar = node.declarations[i];
var patternId = declar.init;
var pattern = declar.id;
var opts = {
kind: node.kind,
nodes: nodes,
pattern: pattern,
id: patternId,
nodes: nodes,
scope: scope,
kind: node.kind,
file: file,
scope: scope
id: patternId,
};
if (t.isPattern(pattern) && patternId) {
@@ -317,7 +327,7 @@ exports.VariableDeclaration = function (node, parent, file, scope) {
if (!t.isProgram(parent) && !t.isBlockStatement(parent)) {
declar = null;
for (i in nodes) {
for (i = 0; i < nodes.length; i++) {
node = nodes[i];
declar = declar || t.variableDeclaration(node.kind, []);

View File

@@ -1,11 +1,13 @@
"use strict";
var util = require("../../util");
var t = require("../../types");
exports.ForOfStatement = function (node, parent, file, scope) {
exports.ForOfStatement = function (node, parent, scope, context, file) {
var callback = spec;
if (file.isLoose("forOf")) callback = loose;
var build = callback(node, parent, file, scope);
var build = callback(node, parent, scope, context, file);
var declar = build.declar;
var loop = build.loop;
var block = loop.body;
@@ -28,10 +30,13 @@ exports.ForOfStatement = function (node, parent, file, scope) {
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
// todo: find out why this is necessary? #538
loop._scopeInfo = node._scopeInfo;
return loop;
};
var loose = function (node, parent, file, scope) {
var loose = function (node, parent, scope, context, file) {
var left = node.left;
var declar, id;
@@ -63,7 +68,7 @@ var loose = function (node, parent, file, scope) {
};
};
var spec = function (node, parent, file, scope) {
var spec = function (node, parent, scope, context, file) {
var left = node.left;
var declar;

View File

@@ -1,3 +1,5 @@
"use strict";
var regenerator = require("regenerator");
exports.ast = {

View File

@@ -1,3 +1,5 @@
"use strict";
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
@@ -25,7 +27,7 @@ var isVar = function (node, parent) {
};
var standardiseLets = function (declars) {
for (var i in declars) {
for (var i = 0; i < declars.length; i++) {
delete declars[i]._let;
}
};
@@ -34,7 +36,7 @@ exports.VariableDeclaration = function (node, parent) {
isLet(node, parent);
};
exports.Loop = function (node, parent, file, scope) {
exports.Loop = function (node, parent, scope, context, file) {
var init = node.left || node.init;
if (isLet(init, node)) {
t.ensureBlock(node);
@@ -46,7 +48,7 @@ exports.Loop = function (node, parent, file, scope) {
node.label = parent.label;
}
var letScoping = new LetScoping(node, node.body, parent, file, scope);
var letScoping = new LetScoping(node, node.body, parent, scope, file);
letScoping.run();
if (node.label && !t.isLabeledStatement(parent)) {
@@ -55,9 +57,10 @@ exports.Loop = function (node, parent, file, scope) {
}
};
exports.BlockStatement = function (block, parent, file, scope) {
exports.Program =
exports.BlockStatement = function (block, parent, scope, context, file) {
if (!t.isLoop(parent)) {
var letScoping = new LetScoping(false, block, parent, file, scope);
var letScoping = new LetScoping(false, block, parent, scope, file);
letScoping.run();
}
};
@@ -68,19 +71,21 @@ exports.BlockStatement = function (block, parent, file, scope) {
* @param {Boolean|Node} loopParent
* @param {Node} block
* @param {Node} parent
* @param {File} file
* @param {Scope} scope
* @param {File} file
*/
function LetScoping(loopParent, block, parent, file, scope) {
function LetScoping(loopParent, block, parent, scope, file) {
this.loopParent = loopParent;
this.parent = parent;
this.scope = scope;
this.block = block;
this.file = file;
this.letReferences = {};
this.body = [];
this.outsideLetReferences = {};
this.hasLetReferences = false;
this.letReferences = block._letReferences = {};
this.body = [];
}
/**
@@ -89,27 +94,98 @@ function LetScoping(loopParent, block, parent, file, scope) {
LetScoping.prototype.run = function () {
var block = this.block;
if (block._letDone) return;
block._letDone = true;
this.info = this.getInfo();
var needsClosure = this.getLetReferences();
// remap all let references that exist in upper scopes to their uid
this.remap();
// this is a block within a `Function/Program` so we can safely leave it be
if (t.isFunction(this.parent) || t.isProgram(this.block)) return;
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(this.parent)) return this.noClosure();
// we can skip everything
if (!this.hasLetReferences) return;
// this block has no let references so let's clean up
if (!this.info.keys.length) return this.noClosure();
if (needsClosure) {
this.needsClosure();
} else {
this.remap();
}
};
// returns whether or not there are any outside let references within any
// functions
var referencesInClosure = this.getLetReferences();
/**
* Description
*/
// no need for a closure so let's clean up
if (!referencesInClosure) return this.noClosure();
LetScoping.prototype.remap = function () {
var hasRemaps = false;
var letRefs = this.letReferences;
var scope = this.scope;
var file = this.file;
// alright, so since we aren't wrapping this block in a closure
// we have to check if any of our let variables collide with
// those in upper scopes and then if they do, generate a uid
// for them and replace all references with it
var remaps = {};
for (var key in letRefs) {
// just an Identifier node we collected in `getLetReferences`
// this is the defining identifier of a declaration
var ref = letRefs[key];
if (scope.parentHas(key)) {
var uid = file.generateUidIdentifier(ref.name, scope).name;
ref.name = uid;
hasRemaps = true;
remaps[key] = remaps[uid] = {
node: ref,
uid: uid
};
}
}
if (!hasRemaps) return;
//
var replace = function (node, parent, scope, context, remaps) {
if (!t.isReferencedIdentifier(node, parent)) return;
var remap = remaps[node.name];
if (!remap) return;
var own = scope.get(node.name, true);
if (own === remap.node) {
node.name = remap.uid;
} else {
// scope already has it's own declaration that doesn't
// match the one we have a stored replacement for
if (context) context.skip();
}
};
var traverseReplace = function (node, parent) {
replace(node, parent, scope, null, remaps);
traverse(node, { enter: replace }, scope, remaps);
};
var loopParent = this.loopParent;
if (loopParent) {
traverseReplace(loopParent.right, loopParent);
traverseReplace(loopParent.test, loopParent);
traverseReplace(loopParent.update, loopParent);
}
traverse(this.block, { enter: replace }, scope, remaps);
};
/**
* Description
*/
LetScoping.prototype.needsClosure = function () {
var block = this.block;
// if we're inside of a for loop then we search to see if there are any
// `break`s, `continue`s, `return`s etc
@@ -118,22 +194,16 @@ LetScoping.prototype.run = function () {
// hoist var references to retain scope
this.hoistVarDeclarations();
// set let references to plain var references
standardiseLets(this.info.declarators);
// turn letReferences into an array
var letReferences = _.values(this.letReferences);
// turn outsideLetReferences into an array
var params = _.values(this.outsideLetReferences);
// build the closure that we're going to wrap the block with
var fn = t.functionExpression(null, letReferences, t.blockStatement(block.body));
var fn = t.functionExpression(null, params, t.blockStatement(block.body));
fn._aliasFunction = true;
// replace the current block body with the one we're going to build
block.body = this.body;
// change upper scope references with their uid if they have one
var params = this.getParams(letReferences);
// build a call and a unique id that we can assign the return value to
var call = t.callExpression(fn, params);
var ret = this.file.generateUidIdentifier("ret", this.scope);
@@ -147,117 +217,78 @@ LetScoping.prototype.run = function () {
this.build(ret, call);
};
/**
* There are no let references accessed within a closure so we can just turn the
* lets into vars.
*/
LetScoping.prototype.noClosure = function () {
standardiseLets(this.info.declarators);
};
/**
* Traverse through block and replace all references that exist in a higher
* scope to their uids.
*/
LetScoping.prototype.remap = function () {
var replacements = this.info.duplicates;
var block = this.block;
if (!this.info.hasDuplicates) return;
var replace = function (node, parent, scope) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
if (scope && scope.hasOwn(node.name)) return;
node.name = replacements[node.name] || node.name;
};
var traverseReplace = function (node, parent) {
replace(node, parent);
traverse(node, { enter: replace });
};
var loopParent = this.loopParent;
if (loopParent) {
traverseReplace(loopParent.right, loopParent);
traverseReplace(loopParent.test, loopParent);
traverseReplace(loopParent.update, loopParent);
}
traverse(block, { enter: replace });
};
/**
* Description
*
* @returns {Object}
*/
LetScoping.prototype.getInfo = function () {
LetScoping.prototype.getLetReferences = function () {
var block = this.block;
var scope = this.scope;
var file = this.file;
var opts = {
// array of `Identifier` names of let variables that appear lexically out of
// this scope but should be accessible - eg. `ForOfStatement`.left
outsideKeys: [],
// array of let `VariableDeclarator`s that are a part of this block
declarators: block._letDeclars || [],
// object of duplicate ids and their aliases - if there's an `Identifier`
// name that's used in an upper scope we generate a unique id and replace
// all references with it
duplicates: {},
hasDuplicates: false,
// array of `Identifier` names of let variables that are accessible within
// the current block
keys: []
};
var duplicates = function (id, key) {
var has = scope.parentGet(key);
if (has && has !== id) {
// there's a variable with this exact name in an upper scope so we need
// to generate a new name
opts.duplicates[key] = id.name = file.generateUid(key, scope);
opts.hasDuplicates = true;
}
};
var i;
var declarators = block._letDeclars || [];
var declar;
for (i in opts.declarators) {
declar = opts.declarators[i];
opts.declarators.push(declar);
var keys = t.getIds(declar, true);
_.each(keys, duplicates);
keys = Object.keys(keys);
opts.outsideKeys = opts.outsideKeys.concat(keys);
opts.keys = opts.keys.concat(keys);
//
for (var i = 0; i < declarators.length; i++) {
declar = declarators[i];
_.extend(this.outsideLetReferences, t.getIds(declar, true));
}
for (i in block.body) {
declar = block.body[i];
if (!isLet(declar, block)) continue;
var declars = t.getIds(declar, true);
for (var key in declars) {
duplicates(declars[key], key);
opts.keys.push(key);
//
if (block.body) {
for (i = 0; i < block.body.length; i++) {
declar = block.body[i];
if (isLet(declar, block)) {
declarators = declarators.concat(declar.declarations);
}
}
}
return opts;
//
for (i = 0; i < declarators.length; i++) {
declar = declarators[i];
var keys = t.getIds(declar, true);
_.extend(this.letReferences, keys);
this.hasLetReferences = true;
}
// no let references so we can just quit
if (!this.hasLetReferences) return;
// set let references to plain var references
standardiseLets(declarators);
var state = {
letReferences: this.letReferences,
closurify: false
};
// traverse through this block, stopping on functions and checking if they
// contain any local let references
traverse(this.block, {
enter: function (node, parent, scope, context, state) {
if (t.isFunction(node)) {
traverse(node, {
enter: function (node, parent) {
// not a direct reference
if (!t.isReferencedIdentifier(node, parent)) return;
// this scope has a variable with the same name so it couldn't belong
// to our let scope
if (scope.hasOwn(node.name, true)) return;
// not a part of our scope
if (!state.letReferences[node.name]) return;
state.closurify = true;
}
}, scope, state);
return context.skip();
}
}
}, this.scope, state);
return state.closurify;
};
/**
@@ -277,11 +308,11 @@ LetScoping.prototype.checkLoop = function () {
};
traverse(this.block, {
enter: function (node, parent) {
enter: function (node, parent, scope, context) {
var replace;
if (t.isFunction(node) || t.isLoop(node)) {
return this.skip();
return context.skip();
}
if (node && !node.label) {
@@ -305,7 +336,7 @@ LetScoping.prototype.checkLoop = function () {
if (replace) return t.inherits(replace, node);
}
});
}, this.scope, has);
return has;
};
@@ -316,9 +347,8 @@ LetScoping.prototype.checkLoop = function () {
*/
LetScoping.prototype.hoistVarDeclarations = function () {
var self = this;
traverse(this.block, {
enter: function (node, parent) {
enter: function (node, parent, scope, context, self) {
if (t.isForStatement(node)) {
if (isVar(node.init, node)) {
node.init = t.sequenceExpression(self.pushDeclar(node.init));
@@ -330,71 +360,10 @@ LetScoping.prototype.hoistVarDeclarations = function () {
} else if (isVar(node, parent)) {
return self.pushDeclar(node).map(t.expressionStatement);
} else if (t.isFunction(node)) {
return this.skip();
return context.skip();
}
}
});
};
/**
* Build up a parameter list that we'll call our closure wrapper with, replacing
* all duplicate ids with their uid.
*
* @param {Array} params
* @returns {Array}
*/
LetScoping.prototype.getParams = function (params) {
var info = this.info;
params = _.cloneDeep(params);
_.each(params, function (param) {
param.name = info.duplicates[param.name] || param.name;
});
return params;
};
/**
* Get all let references within this block. Stopping whenever we reach another
* block.
*/
LetScoping.prototype.getLetReferences = function () {
var closurify = false;
var self = this;
// traverse through this block, stopping on functions and checking if they
// contain any outside let references
traverse(this.block, {
enter: function (node, parent, scope) {
if (t.isFunction(node)) {
traverse(node, {
enter: function (node, parent) {
// not an identifier so we have no use
if (!t.isIdentifier(node)) return;
// not a direct reference
if (!t.isReferenced(node, parent)) return;
// this scope has a variable with the same name so it couldn't belong
// to our let scope
if (scope.hasOwn(node.name, true)) return;
closurify = true;
// this key doesn't appear just outside our scope
if (!_.contains(self.info.outsideKeys, node.name)) return;
// push this badboy
self.letReferences[node.name] = node;
}
});
return this.skip();
}
}
});
return closurify;
}, this.scope, this);
};
/**
@@ -412,7 +381,7 @@ LetScoping.prototype.pushDeclar = function (node) {
var replace = [];
for (var i in node.declarations) {
for (var i = 0; i < node.declarations.length; i++) {
var declar = node.declarations[i];
if (!declar.init) continue;

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
exports.ast = {
@@ -6,11 +8,11 @@ exports.ast = {
}
};
exports.ImportDeclaration = function (node, parent, file) {
exports.ImportDeclaration = function (node, parent, scope, context, file) {
var nodes = [];
if (node.specifiers.length) {
for (var i in node.specifiers) {
for (var i = 0; i < node.specifiers.length; i++) {
file.moduleFormatter.importSpecifier(node.specifiers[i], node, nodes, parent);
}
} else {
@@ -26,7 +28,7 @@ exports.ImportDeclaration = function (node, parent, file) {
return nodes;
};
exports.ExportDeclaration = function (node, parent, file) {
exports.ExportDeclaration = function (node, parent, scope, context, file) {
var nodes = [];
if (node.declaration) {
@@ -39,7 +41,7 @@ exports.ExportDeclaration = function (node, parent, file) {
file.moduleFormatter.exportDeclaration(node, nodes, parent);
} else {
for (var i in node.specifiers) {
for (var i = 0; i < node.specifiers.length; i++) {
file.moduleFormatter.exportSpecifier(node.specifiers[i], node, nodes, parent);
}
}

View File

@@ -1,53 +1,15 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
"use strict";
exports._namedMethod = function (node, file, scope) {
var key = t.toComputedKey(node, node.key);
if (!t.isLiteral(key)) return node; // we can't set a function id with this
var nameMethod = require("../helpers/name-method");
var util = require("../../util");
var t = require("../../types");
var id = t.toIdentifier(key.value);
key = t.identifier(id);
var selfReference = false;
var outerDeclar = scope.get(id, true);
traverse(node, {
enter: function (node, parent, scope) {
// check if this node is an identifier that matches the same as our function id
if (!t.isIdentifier(node, { name: id })) return;
// check if this node is the one referenced
if (!t.isReferenced(node, parent)) return;
// check that we don't have a local variable declared as that removes the need
// for the wrapper
var localDeclar = scope.get(id, true);
if (localDeclar !== outerDeclar) return;
selfReference = true;
this.stop();
}
}, scope);
if (selfReference) {
node.value = util.template("property-method-assignment-wrapper", {
FUNCTION: node.value,
FUNCTION_ID: key,
FUNCTION_KEY: file.generateUidIdentifier(id, scope),
WRAPPER_KEY: file.generateUidIdentifier(id + "Wrapper", scope)
});
} else {
node.value.id = key;
}
};
exports.Property = function (node, parent, file, scope) {
exports.Property = function (node, parent, scope, context, file) {
if (!node.method) return;
node.method = false;
exports._namedMethod(node, file, scope);
nameMethod.property(node, file, scope);
};
exports.ObjectExpression = function (node) {

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
var _ = require("lodash");

View File

@@ -1,36 +1,55 @@
"use strict";
var util = require("../../util");
var t = require("../../types");
exports.Function = function (node, parent, file) {
exports.Function = function (node, parent, scope, context, file) {
if (!node.rest) return;
var rest = node.rest;
delete node.rest;
node.rest = null;
t.ensureBlock(node);
var argsId = t.identifier("arguments");
// otherwise `arguments` will be remapped in arrow functions
argsId._ignoreAliasFunctions = true;
var start = t.literal(node.params.length);
var key = file.generateUidIdentifier("key");
var len = file.generateUidIdentifier("len");
var arrKey = key;
var arrLen = len;
if (node.params.length) {
arrKey = t.binaryExpression("-", arrKey, start);
// this method has additional params, so we need to subtract
// the index of the current argument position from the
// position in the array that we want to populate
arrKey = t.binaryExpression("-", key, start);
// we need to work out the size of the array that we're
// going to store all the rest parameters
//
// we need to add a check to avoid constructing the array
// with <0 if there are less arguments than params as it'll
// cause an error
arrLen = t.conditionalExpression(
t.binaryExpression(">", len, start),
t.binaryExpression("-", len, start),
t.literal(0)
);
}
node.body.body.unshift(
t.variableDeclaration("var", [
t.variableDeclarator(rest, t.arrayExpression([]))
]),
util.template("rest", {
ARGUMENTS: argsId,
ARRAY_KEY: arrKey,
ARRAY_LEN: arrLen,
START: start,
ARRAY: rest,
KEY: key
KEY: key,
LEN: len,
})
);
};

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
var _ = require("lodash");
@@ -6,7 +8,7 @@ var getSpreadLiteral = function (spread, file) {
};
var hasSpread = function (nodes) {
for (var i in nodes) {
for (var i = 0; i < nodes.length; i++) {
if (t.isSpreadElement(nodes[i])) {
return true;
}
@@ -25,7 +27,7 @@ var build = function (props, file) {
_props = [];
};
for (var i in props) {
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (t.isSpreadElement(prop)) {
push();
@@ -40,7 +42,7 @@ var build = function (props, file) {
return nodes;
};
exports.ArrayExpression = function (node, parent, file) {
exports.ArrayExpression = function (node, parent, scope, context, file) {
var elements = node.elements;
if (!hasSpread(elements)) return;
@@ -55,7 +57,7 @@ exports.ArrayExpression = function (node, parent, file) {
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
};
exports.CallExpression = function (node, parent, file, scope) {
exports.CallExpression = function (node, parent, scope, context, file) {
var args = node.arguments;
if (!hasSpread(args)) return;
@@ -95,7 +97,7 @@ exports.CallExpression = function (node, parent, file, scope) {
node.arguments.unshift(contextLiteral);
};
exports.NewExpression = function (node, parent, file) {
exports.NewExpression = function (node, parent, scope, context, file) {
var args = node.arguments;
if (!hasSpread(args)) return;

View File

@@ -1,17 +1,19 @@
"use strict";
var t = require("../../types");
var buildBinaryExpression = function (left, right) {
return t.binaryExpression("+", left, right);
};
exports.TaggedTemplateExpression = function (node, parent, file) {
exports.TaggedTemplateExpression = function (node, parent, scope, context, file) {
var args = [];
var quasi = node.quasi;
var strings = [];
var raw = [];
for (var i in quasi.quasis) {
for (var i = 0; i < quasi.quasis.length; i++) {
var elem = quasi.quasis[i];
strings.push(t.literal(elem.value.cooked));
raw.push(t.literal(elem.value.raw));
@@ -33,7 +35,7 @@ exports.TemplateLiteral = function (node) {
var nodes = [];
var i;
for (i in node.quasis) {
for (i = 0; i < node.quasis.length; i++) {
var elem = node.quasis[i];
nodes.push(t.literal(elem.value.cooked));
@@ -49,7 +51,7 @@ exports.TemplateLiteral = function (node) {
var root = buildBinaryExpression(nodes.shift(), nodes.shift());
for (i in nodes) {
for (i = 0; i < nodes.length; i++) {
root = buildBinaryExpression(root, nodes[i]);
}

View File

@@ -1,3 +1,5 @@
"use strict";
var rewritePattern = require("regexpu/rewrite-pattern");
var _ = require("lodash");

View File

@@ -1,3 +1,5 @@
"use strict";
// https://github.com/zenparsing/es-abstract-refs
var util = require("../../util");
@@ -21,7 +23,7 @@ var container = function (parent, call, ret) {
}
};
exports.AssignmentExpression = function (node, parent, file, scope) {
exports.AssignmentExpression = function (node, parent, scope, context, file) {
var left = node.left;
if (!t.isVirtualPropertyExpression(left)) return;
@@ -74,7 +76,7 @@ exports.UnaryExpression = function (node, parent) {
return container(parent, call, t.literal(true));
};
exports.CallExpression = function (node, parent, file, scope) {
exports.CallExpression = function (node, parent, scope, context, file) {
var callee = node.callee;
if (!t.isVirtualPropertyExpression(callee)) return;

View File

@@ -1,10 +1,13 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
"use strict";
var buildComprehension = require("../helpers/build-comprehension");
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
exports.experimental = true;
var build = function (node, parent, file, scope) {
var build = function (node, parent, scope, context, file) {
var uid = scope.generateUidBasedOnNode(parent, file);
var container = util.template("array-comprehension-container", {
@@ -22,7 +25,7 @@ var build = function (node, parent, file, scope) {
var returnStatement = body.pop();
body.push(exports._build(node, function () {
body.push(buildComprehension(node, function () {
return util.template("array-push", {
STATEMENT: node.body,
KEY: uid
@@ -33,30 +36,8 @@ var build = function (node, parent, file, scope) {
return container;
};
exports._build = function (node, buildBody) {
var self = node.blocks.shift();
if (!self) return;
var child = exports._build(node, buildBody);
if (!child) {
// last item
child = buildBody();
// add a filter as this is our final stop
if (node.filter) {
child = t.ifStatement(node.filter, t.blockStatement([child]));
}
}
return t.forOfStatement(
t.variableDeclaration("let", [t.variableDeclarator(self.left)]),
self.right,
t.blockStatement([child])
);
};
exports.ComprehensionExpression = function (node, parent, file, scope) {
exports.ComprehensionExpression = function (node, parent, scope, context, file) {
if (node.generator) return;
return build(node, parent, file, scope);
return build(node, parent, scope, context, file);
};

View File

@@ -1,18 +1,18 @@
"use strict";
// https://github.com/rwaldron/exponentiation-operator
exports.experimental = true;
var t = require("../../types");
var pow = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
var build = require("../helpers/build-binary-assignment-operator-transformer");
var t = require("../../types");
exports.AssignmentExpression = function (node) {
if (node.operator !== "**=") return;
node.operator = "=";
node.right = t.callExpression(pow, [node.left, node.right]);
};
var MATH_POW = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
exports.BinaryExpression = function (node) {
if (node.operator !== "**") return;
build(exports, {
operator: "**",
return t.callExpression(pow, [node.left, node.right]);
};
build: function (left, right) {
return t.callExpression(MATH_POW, [left, right]);
}
});

View File

@@ -1,4 +1,6 @@
var arrayComprehension = require("./es7-array-comprehension");
"use strict";
var buildComprehension = require("../helpers/build-comprehension");
var t = require("../../types");
exports.experimental = true;
@@ -10,7 +12,7 @@ exports.ComprehensionExpression = function (node) {
var container = t.functionExpression(null, [], t.blockStatement(body), true);
container._aliasFunction = true;
body.push(arrayComprehension._build(node, function () {
body.push(buildComprehension(node, function () {
return t.expressionStatement(t.yieldExpression(node.body));
}));

View File

@@ -1,14 +1,16 @@
"use strict";
// https://github.com/sebmarkbage/ecmascript-rest-spread
var t = require("../../types");
exports.experimental = true;
exports.ObjectExpression = function (node, parent, file) {
exports.ObjectExpression = function (node, parent, scope, context, file) {
var hasSpread = false;
var i;
var prop;
for (i in node.properties) {
for (i = 0; i < node.properties.length; i++) {
prop = node.properties[i];
if (t.isSpreadProperty(prop)) {
hasSpread = true;
@@ -26,7 +28,7 @@ exports.ObjectExpression = function (node, parent, file) {
props = [];
};
for (i in node.properties) {
for (i = 0; i < node.properties.length; i++) {
prop = node.properties[i];
if (t.isSpreadProperty(prop)) {
push();

View File

@@ -1,11 +1,14 @@
var bluebirdCoroutines = require("./optional-bluebird-coroutines");
"use strict";
var remapAsyncToGenerator = require("../helpers/remap-async-to-generator");
var bluebirdCoroutines = require("./optional-bluebird-coroutines");
exports.optional = true;
exports.manipulateOptions = bluebirdCoroutines.manipulateOptions;
exports.Function = function (node, parent, file) {
exports.Function = function (node, parent, scope, context, file) {
if (!node.async || node.generator) return;
return bluebirdCoroutines._Function(node, file.addHelper("async-to-generator"));
return remapAsyncToGenerator(node, file.addHelper("async-to-generator"));
};

View File

@@ -0,0 +1,46 @@
var traverse = require("../../traverse");
var t = require("../../types");
exports.optional = true;
exports.Loop =
exports.Program =
exports.BlockStatement = function (node, parent, scope, context, file) {
var letRefs = node._letReferences;
if (!letRefs) return;
var state = {
letRefs: letRefs,
file: file
};
traverse(node, {
enter: function (node, parent, scope, context, state) {
if (!t.isReferencedIdentifier(node, parent)) return;
var declared = state.letRefs[node.name];
if (!declared) return;
// declared node is different in this scope
if (scope.get(node.name, true) !== declared) return;
var declaredLoc = declared.loc;
var referenceLoc = node.loc;
if (!declaredLoc || !referenceLoc) return;
// does this reference appear on a line before the declaration?
var before = referenceLoc.start.line < declaredLoc.start.line;
if (referenceLoc.start.line === declaredLoc.start.line) {
// this reference appears on the same line
// check it appears before the declaration
before = referenceLoc.start.col < declaredLoc.start.col;
}
if (before) {
throw state.file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
}
}, scope, state);
};

View File

@@ -1,5 +1,7 @@
var traverse = require("../../traverse");
var t = require("../../types");
"use strict";
var remapAsyncToGenerator = require("../helpers/remap-async-to-generator");
var t = require("../../types");
exports.manipulateOptions = function (opts) {
opts.experimental = true;
@@ -8,36 +10,12 @@ exports.manipulateOptions = function (opts) {
exports.optional = true;
exports._Function = function (node, callId) {
node.async = false;
node.generator = true;
traverse(node, {
enter: function (node) {
if (t.isFunction(node)) this.skip();
if (t.isAwaitExpression(node)) {
node.type = "YieldExpression";
}
}
});
var call = t.callExpression(callId, [node]);
if (t.isFunctionDeclaration(node)) {
var declar = t.variableDeclaration("var", [
t.variableDeclarator(node.id, call)
]);
declar._blockHoist = true;
return declar;
} else {
return call;
}
};
exports.Function = function (node, parent, file) {
exports.Function = function (node, parent, scope, context, file) {
if (!node.async || node.generator) return;
var id = file.addImport("bluebird");
return exports._Function(node, t.memberExpression(id, t.identifier("coroutine")));
return remapAsyncToGenerator(
node,
t.memberExpression(file.addImport("bluebird"), t.identifier("coroutine"))
);
};

View File

@@ -1,3 +1,5 @@
"use strict";
var traverse = require("../../traverse");
var util = require("../../util");
var core = require("core-js/library");
@@ -26,7 +28,7 @@ exports.ast = {
exit: function (ast, file) {
traverse(ast, {
enter: function (node, parent) {
enter: function (node, parent, scope, context) {
var prop;
if (t.isMemberExpression(node) && t.isReferenced(node, parent)) {
@@ -37,10 +39,10 @@ exports.ast = {
if (!t.isReferenced(obj, node)) return;
if (!node.computed && coreHas(obj) && _.has(core[obj.name], prop.name)) {
this.skip();
context.skip();
return t.prependToMemberExpression(node, file._coreId);
}
} else if (t.isIdentifier(node) && !t.isMemberExpression(parent) && t.isReferenced(node, parent) && _.contains(ALIASABLE_CONSTRUCTORS, node.name)) {
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && _.contains(ALIASABLE_CONSTRUCTORS, node.name)) {
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
return t.memberExpression(file._coreId, node);
} else if (t.isCallExpression(node)) {

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
var _ = require("lodash");
@@ -17,7 +19,7 @@ var buildDefaultsCallExpression = function (expr, ref, file) {
exports.optional = true;
exports.secondPass = true;
exports.AssignmentExpression = function (node, parent, file, scope) {
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!isProtoAssignmentExpression(node)) return;
@@ -32,7 +34,7 @@ exports.AssignmentExpression = function (node, parent, file, scope) {
return t.toSequenceExpression(nodes);
};
exports.ExpressionStatement = function (node, parent, file) {
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (!t.isAssignmentExpression(expr, { operator: "=" })) return;
@@ -41,10 +43,10 @@ exports.ExpressionStatement = function (node, parent, file) {
}
};
exports.ObjectExpression = function (node, parent, file) {
exports.ObjectExpression = function (node, parent, scope, context, file) {
var proto;
for (var i in node.properties) {
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
if (isProtoKey(prop)) {

View File

@@ -1,9 +1,11 @@
"use strict";
var t = require("../../types");
exports.optional = true;
exports.UnaryExpression = function (node, parent, file) {
this.skip();
exports.UnaryExpression = function (node, parent, scope, context, file) {
context.skip();
if (node.operator === "typeof") {
var call = t.callExpression(file.addHelper("typeof"), [node.argument]);

View File

@@ -0,0 +1,7 @@
exports.optional = true;
exports.Identifier = function (node, parent, scope, context, file) {
if (!scope.has(node.name, true)) {
throw file.errorWithNode(node, "Reference to undeclared variable");
}
};

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
exports.optional = true;

View File

@@ -0,0 +1,21 @@
"use strict";
var build = require("../helpers/build-conditional-assignment-operator-transformer");
var t = require("../../types");
build(exports, {
is: function (node, file) {
var is = t.isAssignmentExpression(node) && node.operator === "||=";
if (is) {
var left = node.left;
if (!t.isMemberExpression(left) && !t.isIdentifier(left)) {
throw file.errorWithNode(left, "Expected type MemeberExpression or Identifier");
}
return true;
}
},
build: function (node) {
return t.unaryExpression("!", node, true);
}
});

View File

@@ -1,86 +1,23 @@
var t = require("../../types");
"use strict";
var isMemo = function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "?=";
if (is) t.assertMemberExpression(node.left);
return is;
};
var build = require("../helpers/build-conditional-assignment-operator-transformer");
var t = require("../../types");
var getPropRef = function (nodes, prop, file, scope) {
if (t.isIdentifier(prop)) {
return t.literal(prop.name);
} else {
var temp = scope.generateUidBasedOnNode(prop, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, prop)
]));
return temp;
build(exports, {
is: function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "?=";
if (is) t.assertMemberExpression(node.left);
return is;
},
build: function (node, file) {
return t.unaryExpression(
"!",
t.callExpression(
t.memberExpression(file.addHelper("has-own"), t.identifier("call")),
[node.object, node.property]
),
true
);
}
};
var getObjRef = function (nodes, obj, file, scope) {
var temp = scope.generateUidBasedOnNode(obj, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, obj)
]));
return temp;
};
var buildHasOwn = function (obj, prop, file) {
return t.unaryExpression(
"!",
t.callExpression(
t.memberExpression(file.addHelper("has-own"), t.identifier("call")),
[obj, prop]
),
true
);
};
var buildAbsoluteRef = function (left, obj, prop) {
var computed = left.computed || t.isLiteral(prop);
return t.memberExpression(obj, prop, computed);
};
var buildAssignment = function (expr, obj, prop) {
return t.assignmentExpression("=", buildAbsoluteRef(expr.left, obj, prop), expr.right);
};
exports.ExpressionStatement = function (node, parent, file, scope) {
var expr = node.expression;
if (!isMemo(expr)) return;
var nodes = [];
var left = expr.left;
var obj = getObjRef(nodes, left.object, file, scope);
var prop = getPropRef(nodes, left.property, file, scope);
nodes.push(t.ifStatement(
buildHasOwn(obj, prop, file),
t.expressionStatement(buildAssignment(expr, obj, prop))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, file, scope) {
if (t.isExpressionStatement(parent)) return;
if (!isMemo(node)) return;
var nodes = [];
var left = node.left;
var obj = getObjRef(nodes, left.object, file, scope);
var prop = getPropRef(nodes, left.property, file, scope);
nodes.push(t.logicalExpression(
"&&",
buildHasOwn(obj, prop, file),
buildAssignment(node, obj, prop)
));
nodes.push(buildAbsoluteRef(left, obj, prop));
return t.toSequenceExpression(nodes, scope);
};
});

View File

@@ -1,6 +1,8 @@
"use strict";
var t = require("../../types");
exports.BindMemberExpression = function (node, parent, file, scope) {
exports.BindMemberExpression = function (node, parent, scope, context, file) {
var object = node.object;
var prop = node.property;
@@ -22,7 +24,7 @@ exports.BindMemberExpression = function (node, parent, file, scope) {
}
};
exports.BindFunctionExpression = function (node, parent, file, scope) {
exports.BindFunctionExpression = function (node, parent, scope, context, file) {
var buildCall = function (args) {
var param = file.generateUidIdentifier("val", scope);
return t.functionExpression(null, [param], t.blockStatement([

View File

@@ -1,8 +1,10 @@
"use strict";
var traverse = require("../../traverse");
var t = require("../../types");
exports.Property =
exports.MethodDefinition = function (node, parent, file) {
exports.MethodDefinition = function (node, parent, scope, context, file) {
if (node.kind !== "memo") return;
node.kind = "get";

View File

@@ -1,3 +1,5 @@
"use strict";
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
@@ -15,7 +17,7 @@ exports.XJSIdentifier = function (node) {
}
};
exports.XJSNamespacedName = function (node, parent, file) {
exports.XJSNamespacedName = function (node, parent, scope, context, file) {
throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
};
@@ -37,12 +39,12 @@ exports.XJSAttribute = {
}
};
var isTag = function(tagName) {
return (/^[a-z]|\-/).test(tagName);
var isCompatTag = function(tagName) {
return /^[a-z]|\-/.test(tagName);
};
exports.XJSOpeningElement = {
exit: function (node, parent, file) {
exit: function (node, parent, scope, context, file) {
var reactCompat = file.opts.reactCompat;
var tagExpr = node.name;
var args = [];
@@ -55,7 +57,7 @@ exports.XJSOpeningElement = {
}
if (!reactCompat) {
if (tagName && isTag(tagName)) {
if (tagName && isCompatTag(tagName)) {
args.push(t.literal(tagName));
} else {
args.push(tagExpr);
@@ -64,48 +66,7 @@ exports.XJSOpeningElement = {
var attribs = node.attributes;
if (attribs.length) {
var _props = [];
var objs = [];
// so basically in order to support spread elements we
// loop over all the attributes, breaking on spreads
// we then push a new object containing all prior attributes
// to an array for later processing
var pushProps = function () {
if (!_props.length) return;
objs.push(t.objectExpression(_props));
_props = [];
};
while (attribs.length) {
var prop = attribs.shift();
if (t.isXJSSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
} else {
_props.push(prop);
}
}
pushProps();
if (objs.length === 1) {
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
// spread it
attribs = t.callExpression(
t.memberExpression(t.identifier("React"), t.identifier("__spread")),
objs
);
}
attribs = buildXJSOpeningElementAttributes(attribs);
} else {
attribs = t.literal(null);
}
@@ -113,7 +74,7 @@ exports.XJSOpeningElement = {
args.push(attribs);
if (reactCompat) {
if (tagName && isTag(tagName)) {
if (tagName && isCompatTag(tagName)) {
return t.callExpression(
t.memberExpression(
t.memberExpression(t.identifier("React"), t.identifier("DOM")),
@@ -131,41 +92,64 @@ exports.XJSOpeningElement = {
}
};
/**
* The logic for this is quite terse. It's because we need to
* support spread elements. We loop over all attributes,
* breaking on spreads, we then push a new object containg
* all prior attributes to an array for later processing.
*/
var buildXJSOpeningElementAttributes = function (attribs) {
var _props = [];
var objs = [];
var pushProps = function () {
if (!_props.length) return;
objs.push(t.objectExpression(_props));
_props = [];
};
while (attribs.length) {
var prop = attribs.shift();
if (t.isXJSSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
} else {
_props.push(prop);
}
}
pushProps();
if (objs.length === 1) {
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
// spread it
attribs = t.callExpression(
t.memberExpression(t.identifier("React"), t.identifier("__spread")),
objs
);
}
return attribs;
};
exports.XJSElement = {
exit: function (node) {
var callExpr = node.openingElement;
var i;
for (i in node.children) {
for (var i = 0; i < node.children.length; i++) {
var child = node.children[i];
if (t.isLiteral(child) && _.isString(child.value)) {
var lines = child.value.split(/\r\n|\n|\r/);
for (i in lines) {
var line = lines[i];
var isFirstLine = i === "0";
var isLastLine = +i === lines.length - 1;
// replace rendered whitespace tabs with spaces
var trimmedLine = line.replace(/\t/g, " ");
// trim whitespace touching a newline
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, "");
}
// trim whitespace touching an endline
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, "");
}
if (trimmedLine) {
callExpr.arguments.push(t.literal(trimmedLine));
}
}
cleanXJSElementLiteralChild(child, callExpr.arguments);
continue;
} else if (t.isXJSEmptyExpression(child)) {
continue;
@@ -182,35 +166,69 @@ exports.XJSElement = {
}
};
var cleanXJSElementLiteralChild = function (child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var isFirstLine = i === 0;
var isLastLine = i === lines.length - 1;
// replace rendered whitespace tabs with spaces
var trimmedLine = line.replace(/\t/g, " ");
// trim whitespace touching a newline
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, "");
}
// trim whitespace touching an endline
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, "");
}
if (trimmedLine) {
args.push(t.literal(trimmedLine));
}
}
};
// display names
var addDisplayName = function (id, call) {
if (!call || !t.isCallExpression(call)) return;
var isCreateClass = function (call) {
if (!call || !t.isCallExpression(call)) return false;
var callee = call.callee;
if (!t.isMemberExpression(callee)) return;
if (!t.isMemberExpression(callee)) return false;
// not React
// not React call member object
var obj = callee.object;
if (!t.isIdentifier(obj, { name: "React" })) return;
if (!t.isIdentifier(obj, { name: "React" })) return false;
// not createClass
// not createClass call member property
var prop = callee.property;
if (!t.isIdentifier(prop, { name: "createClass" })) return;
if (!t.isIdentifier(prop, { name: "createClass" })) return false;
// no arguments
// no call arguments
var args = call.arguments;
if (args.length !== 1) return;
if (args.length !== 1) return false;
// not an object
// first call arg is not an object
var first = args[0];
if (!t.isObjectExpression(first)) return;
var props = first.properties;
return true;
};
var addDisplayName = function (id, call) {
if (!isCreateClass(call)) return;
var props = call.arguments[0].properties;
var safe = true;
for (var i in props) {
prop = props[i];
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (t.isIdentifier(prop.key, { name: "displayName" })) {
safe = false;
break;

View File

@@ -0,0 +1,24 @@
"use strict";
var t = require("../../types");
exports.FunctionDeclaration = function (node, parent) {
if (t.isProgram(parent) || t.isExportDeclaration(parent)) {
return;
}
// this is to avoid triggering the TDZ detection
node.id.loc = null;
var declar = t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
// hoist it up above everything else
declar._blockHoist = 2;
// todo: name this
node.id = null;
return declar;
};

View File

@@ -1,3 +1,5 @@
"use strict";
var t = require("../../types");
exports.MemberExpression = function (node) {

Some files were not shown because too many files have changed in this diff Show More