Compare commits

...

157 Commits

Author SHA1 Message Date
Sebastian McKenzie
02392635ef v3.6.0 2015-02-12 21:57:18 +11:00
Sebastian McKenzie
298cfac7f4 fix linting errors 2015-02-12 21:55:31 +11:00
Sebastian McKenzie
476b683f0f upgrade core-js 2015-02-12 21:53:51 +11:00
Sebastian McKenzie
5c5b66df54 add 3.6.0 changelog 2015-02-12 21:53:45 +11:00
Sebastian McKenzie
e7f6572a3b track arrays to avoid turning something into an array multiple times - closes #757 2015-02-12 21:30:48 +11:00
Sebastian McKenzie
e9cfd2df3e fix toConsumableArray helper 2015-02-12 16:53:00 +11:00
Sebastian McKenzie
a425136680 allow loose = true as an alias for loose = "all" 2015-02-12 16:36:17 +11:00
Sebastian McKenzie
8d06a4301c pdate tests to reflect toConsumableArray updates 2015-02-12 16:35:55 +11:00
Sebastian McKenzie
1909a16dc7 copy over files that we can't compile when specifying a directory in bin/6to5 2015-02-12 16:35:41 +11:00
Sebastian McKenzie
3bfa1f610c add bootstrapping base 2015-02-12 16:35:04 +11:00
Sebastian McKenzie
4faf2b7730 fix namespace name 2015-02-12 16:00:54 +11:00
Sebastian McKenzie
4e5d6ee976 rice up toConsumableArray helper 2015-02-12 16:00:43 +11:00
Sebastian McKenzie
afb1ee79a1 fix autoenabling of playground/experimental when used in whitelist/optional 2015-02-12 16:00:26 +11:00
Sebastian McKenzie
efe3f30741 make minification.renameLocalVariables work 2015-02-12 07:46:34 +11:00
Sebastian McKenzie
5ff0285ba7 use space helper instead of pushing a space in IfStatement generation 2015-02-12 07:46:21 +11:00
Sebastian McKenzie
d7bea2f325 remove legacy jshint comment 2015-02-12 07:46:03 +11:00
Sebastian McKenzie
32316ad942 clean up t.is 2015-02-12 07:45:55 +11:00
Sebastian McKenzie
7953eb560e force experimental and playground flag when whitelisting/optionalising transformers 2015-02-12 07:45:50 +11:00
Sebastian McKenzie
faa10df84c add toConsumableArray helper for spread - fixes #757 2015-02-12 07:37:40 +11:00
Sebastian McKenzie
ae344aa23e recurse over and duplicate array in toArray in order to handle sparse arrays - fixes #754 2015-02-12 00:33:04 +11:00
Sebastian McKenzie
e0bfc72700 fix tail call deopt check 2015-02-11 20:16:50 +11:00
Sebastian McKenzie
bf8f80faf7 add general support for declarations to Scope::rename - closes #751 2015-02-11 20:14:41 +11:00
Sebastian McKenzie
77fa8bf01c fix isReferenced on AssignmentPattern 2015-02-11 20:14:21 +11:00
Sebastian McKenzie
34ca1ac04f delay binding reassignment to after reference replacements - #751 2015-02-11 19:48:54 +11:00
Sebastian McKenzie
85d33536e0 add deopt logging to tail call transformer 2015-02-11 15:59:15 +11:00
Sebastian McKenzie
a4932e0e0f add messages to make it easier to make error messages 2015-02-11 15:57:30 +11:00
Sebastian McKenzie
4ebd0a1e8a upgrade regenerator-6to5 2015-02-11 12:12:43 +11:00
Sebastian McKenzie
14e92e9e3f remove kexec from optionalDependencies 2015-02-11 12:00:38 +11:00
Sebastian McKenzie
13687d98ed bump regenerator-6to5 2015-02-11 11:52:16 +11:00
Sebastian McKenzie
db93c52182 opt out of tail recursion optimisation if the owner id has been reassigned - fixes #744 2015-02-11 11:27:50 +11:00
Sebastian McKenzie
56a953df64 add basic support for class property initializers - #619 2015-02-11 10:59:44 +11:00
Sebastian McKenzie
c38edbbb42 Merge branch 'master' of github.com:6to5/6to5 2015-02-11 08:29:08 +11:00
Sebastian McKenzie
017bb6427a Merge pull request #743 from chicoxyzzy/master
optimise lodash usage
2015-02-11 08:28:58 +11:00
Sebastian McKenzie
714ad40cb0 update contributing guide 2015-02-11 08:28:47 +11:00
Ingvar Stepanyan
904a72fb3a Fix rename not establishing binding. 2015-02-10 17:18:46 +02:00
chico
146835e0f1 fix broken code, lint and codestyle fixes 2015-02-10 18:16:54 +03:00
chico
79ba97872c optimise lodash usage; change contains function to includes for convenience 2015-02-10 17:40:53 +03:00
Sebastian McKenzie
897566ccb3 more reliable scope construction 2015-02-11 00:38:59 +11:00
Sebastian McKenzie
4df1b6700b remove acorn node patching 2015-02-11 00:37:59 +11:00
Sebastian McKenzie
50f903caf7 proper optional builder keys 2015-02-11 00:13:27 +11:00
Sebastian McKenzie
7b8118d8bd default newName in scope.rename to a new uid 2015-02-11 00:13:21 +11:00
Sebastian McKenzie
0c1e1e757c default optional builder keys to false 2015-02-11 00:02:51 +11:00
Sebastian McKenzie
62fa583fc1 fix linting errors 2015-02-10 23:55:11 +11:00
Sebastian McKenzie
8598000a69 restructure Scope API and internal data structure 2015-02-10 23:52:23 +11:00
Sebastian McKenzie
edc8bee38e test for falsy nodes in tail call transformer subtransform 2015-02-10 22:39:46 +11:00
Sebastian McKenzie
45b70d7fba fix bad ctrl+f Class -> ClassTransformer replacement 2015-02-10 22:39:21 +11:00
Sebastian McKenzie
49a53b26bb add scope renaming helper method - fixes #645 - @RReverser 2015-02-10 22:39:07 +11:00
Sebastian McKenzie
329b4e9d21 append Transformer to the end of transformer classes 2015-02-10 22:12:36 +11:00
Sebastian McKenzie
f1bca0013e refactor tail call transformer into a class - @RReverser 2015-02-10 22:11:22 +11:00
Sebastian McKenzie
87af83f1cb Merge pull request #742 from douglasduteil/patch-1
chore(travis): run tests on nodejs 0.12 too
2015-02-10 20:30:30 +11:00
Douglas Duteil
5156574bf2 chore(travis): run tests on nodejs 0.12 too 2015-02-10 10:29:05 +01:00
Sebastian McKenzie
ac098255be fix allowPartial in t.buildMatchMemberExpression 2015-02-10 18:34:16 +11:00
Sebastian McKenzie
47b803ef24 remove old tail call transformer 2015-02-10 18:33:51 +11:00
Sebastian McKenzie
7f61c8b65e add descriptor falsy check to defaults helper - #739 2015-02-10 18:33:29 +11:00
Sebastian McKenzie
4fa9aa63a3 Merge branch 'better-tail-recursion' 2015-02-10 18:04:05 +11:00
Sebastian McKenzie
d582c7c93a Merge pull request #739 from lukescott/defaults-fix
fix defaults helper in strict mode - #738
2015-02-10 18:00:26 +11:00
Sebastian McKenzie
6266f5b924 finish minification.removeConsoleCall transformer #740 2015-02-10 17:56:31 +11:00
Luke Scott
c6920a0e60 fix defaults helper in strict mode - #738 2015-02-09 20:38:57 -08:00
Sebastian McKenzie
825d84ba52 fix defaults helper iteration - #738 2015-02-10 13:20:19 +11:00
Sebastian McKenzie
94a0eb5b06 copy over descriptors and handle non-enumerable properties in defaults helper - fixes #738 2015-02-10 13:06:26 +11:00
Sebastian McKenzie
b6d708caf2 add SpreadProperty to t.getBindingIdentifiers - fixes #734 2015-02-10 09:04:27 +11:00
Ingvar Stepanyan
0d542b61d3 Performance improvements for TCO.
http://jsperf.com/tco/17
2015-02-09 19:00:31 +02:00
Ingvar Stepanyan
5a842ab623 Fix statement substitution in templates. 2015-02-09 17:34:59 +02:00
Sebastian McKenzie
26d4b5f2cf normalise opts.sourceRoot path - 6to5/karma-6to5-preprocessor#5 2015-02-09 23:38:54 +11:00
Sebastian McKenzie
ba0dfac53d add uid scope kind 2015-02-09 21:28:51 +11:00
Sebastian McKenzie
8a4296a948 remove binding kind from pushing bindings to the function scope, better block scoped collision logic, and track label ids as references 2015-02-09 21:21:25 +11:00
Sebastian McKenzie
478f9e028f put function params into the param kind 2015-02-09 20:16:38 +11:00
Sebastian McKenzie
c4e56894d9 ignore hoisted kind when checking for block scoped collisions 2015-02-09 20:03:59 +11:00
Sebastian McKenzie
c6f13844ed move FunctionDeclarations into a hoisted kind 2015-02-09 19:53:46 +11:00
Sebastian McKenzie
5e81653680 change function params binding kind to let 2015-02-09 19:45:03 +11:00
Sebastian McKenzie
8e2df3f1f9 add kinds to binding registration and rename declaration scope methods to bindings 2015-02-09 19:42:52 +11:00
Sebastian McKenzie
a2cc384172 move rest parameters transformer above default parameters 2015-02-09 10:59:31 +11:00
Sebastian McKenzie
d37bf292a1 rename declarationKinds to bindingKinds in scope tracker 2015-02-09 10:59:20 +11:00
Sebastian McKenzie
70eb641530 fix element name in default parameters 2015-02-09 08:46:06 +11:00
Sebastian McKenzie
f845a9b2c4 ignore binding elements when finding the last non-default param - fixes #723 2015-02-09 08:25:58 +11:00
Sebastian McKenzie
ee5cb8d9ed clean up tail call transformer 2015-02-08 22:47:50 +11:00
Sebastian McKenzie
9020a21ba2 3.5.3 2015-02-08 22:17:36 +11:00
Sebastian McKenzie
fdda013d07 v3.5.3 2015-02-08 22:17:05 +11:00
Sebastian McKenzie
64477d934d add 3.5.3 changelog 2015-02-08 22:10:00 +11:00
Sebastian McKenzie
45c507056a add back old tail call implementation 2015-02-08 22:09:41 +11:00
Sebastian McKenzie
730b96c195 3.5.2 2015-02-08 21:23:55 +11:00
Sebastian McKenzie
a185f91433 v3.5.2 2015-02-08 21:23:24 +11:00
Sebastian McKenzie
d053622802 add 3.5.2 changelog 2015-02-08 21:21:38 +11:00
Sebastian McKenzie
74d6b61973 disable es6 tail call tests 2015-02-08 21:21:32 +11:00
Sebastian McKenzie
97784c8cca comment out tailCall transformer 2015-02-08 21:19:01 +11:00
Sebastian McKenzie
812d93553a temporairly disable tailCall transformer 2015-02-08 21:17:21 +11:00
Sebastian McKenzie
d251b4cb56 3.5.1 2015-02-08 21:16:34 +11:00
Sebastian McKenzie
caf38e1962 v3.5.1 2015-02-08 21:04:05 +11:00
Sebastian McKenzie
4ccbee4639 fix linting errors 2015-02-08 20:59:48 +11:00
Sebastian McKenzie
84196a3a07 add 3.5.1 changelog 2015-02-08 20:57:58 +11:00
Ingvar Stepanyan
29361c055a Fix #718. 2015-02-08 11:56:39 +02:00
Sebastian McKenzie
4277265591 Merge branch 'master' of github.com:6to5/6to5 2015-02-08 20:40:47 +11:00
Sebastian McKenzie
812a2b315d bump acorn-6to5 2015-02-08 20:40:30 +11:00
Ingvar Stepanyan
0a1724fc3f Remove no more needed returnBlock helper. 2015-02-08 11:31:19 +02:00
Sebastian McKenzie
bcc9e016b1 only evaluate object destructuring pattern once 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
4ea0175ca7 simplify set template 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
799445c745 add property method assignment wrapper generator template 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
481ea12999 add cleanup internal transformer 2015-02-08 20:23:22 +11:00
Sebastian McKenzie
de6b608dda add _declarations and _scopeInfo to t.inherits 2015-02-08 20:23:21 +11:00
Sebastian McKenzie
606f813822 enable traceur test suite by default 2015-02-08 20:23:21 +11:00
Sebastian McKenzie
e06c8cd106 support generators in nameMethod helper 2015-02-08 20:23:21 +11:00
Ingvar Stepanyan
9e3c67a8a2 Clean up functionChildrenVisitor a bit. 2015-02-08 10:53:09 +02:00
Ingvar Stepanyan
91362f80b1 Clean up transformations after #714.
Since now we have runtime helper, we don't need
expression -> statement conversions anymore.
2015-02-08 10:40:03 +02:00
Sebastian McKenzie
cde988f99f update 3.5.0 changelog 2015-02-08 16:53:33 +11:00
Sebastian McKenzie
9ec0854659 3.5.0 2015-02-08 16:37:13 +11:00
Sebastian McKenzie
bb17571e56 v3.5.0 2015-02-08 16:35:45 +11:00
Sebastian McKenzie
9161af58c0 fix linting errors 2015-02-08 16:32:08 +11:00
Sebastian McKenzie
e39f4e8025 update 3.5.0 changelog 2015-02-08 16:31:24 +11:00
Sebastian McKenzie
f5e9909e71 Merge pull request #716 from daliwali/master
Make `__esModule` property not enumerable
2015-02-08 16:30:26 +11:00
Sebastian McKenzie
46913fc55f add 3.5.0 changelog 2015-02-08 16:22:12 +11:00
Dali Zheng
d358a86e98 make __esModule property not enumerable 2015-02-07 21:19:11 -08:00
Sebastian McKenzie
055545980c update traceur test runner 2015-02-08 16:19:05 +11:00
Sebastian McKenzie
6fd7f9868e upgrade acorn-6to5 2015-02-08 16:18:54 +11:00
Sebastian McKenzie
e8184a9bc5 fix browser api location in browser test 2015-02-08 14:34:43 +11:00
Sebastian McKenzie
f74de3ef55 move destructuring and parameters.rest transformer to above blockScoping 2015-02-08 14:34:34 +11:00
Sebastian McKenzie
9624f8287d add checkNode to block scoped functions transformer 2015-02-08 14:34:10 +11:00
Sebastian McKenzie
e42d5a889e make destructuring in catch clauses block scoped and add support for non-variable destructuring in for-in/of heads 2015-02-08 14:33:55 +11:00
Sebastian McKenzie
4c8e6481b6 make default parameters iife invocation less serious 2015-02-08 09:54:24 +11:00
Sebastian McKenzie
0867df2691 fix ForOf block body not properly inheriting declarations 2015-02-08 09:50:12 +11:00
Sebastian McKenzie
b06f99ab30 add iife detection to non-identifier params in default parameters 2015-02-08 09:37:06 +11:00
Sebastian McKenzie
9afa3f6b58 add opts param to t.isReferencedIdentifier 2015-02-08 09:31:41 +11:00
Sebastian McKenzie
785cb4b72f allow optional transformer to be set via the whitelist 2015-02-08 09:31:30 +11:00
Sebastian McKenzie
dabe69856a add additional checks to transformers 2015-02-08 09:31:19 +11:00
Sebastian McKenzie
24e70802b5 fix block scoped tracking in functions - fixes #710 2015-02-08 09:31:04 +11:00
Sebastian McKenzie
c1ba55a52d Merge pull request #714 from RReverser/master
Added complete TCO (tail call optimization).
2015-02-08 08:55:19 +11:00
Ingvar Stepanyan
4c318166e1 Added complete TCO (tail call optimization).
Works across functions and generates simpler and faster code than #701.
Works even across files when used in conjunction with `runtime` option.

Closes #256.
2015-02-07 22:22:38 +02:00
Sebastian McKenzie
c0af67eca1 add support for super in object literals - fixes #411 2015-02-08 02:01:17 +11:00
Sebastian McKenzie
eb14f1da00 implement optional TDZ - fixes #563 2015-02-08 01:27:22 +11:00
Sebastian McKenzie
3361b81658 expose parentPath 2015-02-08 01:27:00 +11:00
Sebastian McKenzie
a15f218e9b dump code to esvalid errors 2015-02-08 01:26:46 +11:00
Sebastian McKenzie
067cf43f52 fix File::addHelper unknown helper error message 2015-02-08 00:01:26 +11:00
Sebastian McKenzie
689ce048e6 remove tail call exec test 2015-02-07 23:52:41 +11:00
Sebastian McKenzie
8a143bf957 use a template in tail call transformer - @RReverser 2015-02-07 23:52:35 +11:00
Sebastian McKenzie
9f7bcf585d remove dead TraversalContext code 2015-02-07 23:51:05 +11:00
Sebastian McKenzie
f9efd8a272 fix error message in File::addHelper 2015-02-07 23:50:56 +11:00
Sebastian McKenzie
8cd2326ff9 Merge branch 'master' of github.com:6to5/6to5 2015-02-07 23:37:51 +11:00
Sebastian McKenzie
eb1ae70bfa Merge pull request #701 from RReverser/master
Add tail recursion optimization.
2015-02-07 23:37:43 +11:00
Ingvar Stepanyan
24ef81908c Increase test timeout for Travis. 2015-02-07 14:34:23 +02:00
Ingvar Stepanyan
b53b41cef3 Provide placeholders for proper function length. 2015-02-07 14:26:03 +02:00
Sebastian McKenzie
ad245ed46a 3.4.1 2015-02-07 19:48:59 +11:00
Sebastian McKenzie
3f6199493e v3.4.1 2015-02-07 19:48:28 +11:00
Sebastian McKenzie
e06aac4783 Revert "make export { foo as default }; trigger common interop"
This reverts commit 07c7b5b419.
2015-02-07 19:40:49 +11:00
Sebastian McKenzie
6a5adfe338 update 3.4.1 changelog 2015-02-07 19:40:29 +11:00
Sebastian McKenzie
07c7b5b419 make export { foo as default }; trigger common interop 2015-02-07 19:29:59 +11:00
Sebastian McKenzie
7f985fe08a fix incorrect strict module formatter variable - fixes #706 2015-02-07 19:29:32 +11:00
Sebastian McKenzie
38f02a6429 add 3.4.1 changelog 2015-02-07 19:19:55 +11:00
Sebastian McKenzie
f943bdcac0 Merge branch 'master' of github.com:6to5/6to5 2015-02-07 19:18:29 +11:00
Sebastian McKenzie
8dc634edfc add options to require cache key - fixes #707 2015-02-07 19:18:12 +11:00
Sebastian McKenzie
05b9cf17f0 Merge pull request #708 from tricknotes/avoid-conflict
Switch short option of `--module-ids` from `-i` to `-M`
2015-02-07 19:12:22 +11:00
Ryunosuke SATO
69bbe89616 Switch short option of --module-ids from -i to -M
`-i` conflicts with `--optional` option.

```
$ bin/6to5/index.js --help | grep "\-i,"
    -i, --optional [list]        List of optional transformers to enable
    -i, --module-ids             Insert module id in modules
```
2015-02-07 16:37:38 +09:00
Sebastian McKenzie
6b49958f7c Merge branch 'master' of github.com:6to5/6to5 2015-02-07 15:59:15 +11:00
Sebastian McKenzie
e75ce94578 move reactCompat option onto an optional transformer 2015-02-07 15:59:00 +11:00
Sebastian McKenzie
f666473724 Merge pull request #705 from cesarandreu/patch-2
Add 6to5-runtime README
2015-02-07 13:54:58 +11:00
Cesar Andreu
ae817e3c9c Add 6to5-runtime README 2015-02-06 18:53:42 -08:00
Sebastian McKenzie
2e9352de14 3.4.0 2015-02-07 10:44:06 +11:00
Sebastian McKenzie
1e9e55ddef fix browser build location in makefile 2015-02-07 10:42:28 +11:00
Ingvar Stepanyan
5b2216b348 Add tail recursion optimization.
As per ES6, VMs should perform tail call optimization and prevent growth of call stack.
This adds tail call optimization for recursion case (when function has explicit name and calls itself in `return`).
Cross-function optimization is not currently performed as it's more complicated and requires value tracking.
2015-02-06 16:34:35 +02:00
193 changed files with 2347 additions and 925 deletions

5
.6to5rc Normal file
View File

@@ -0,0 +1,5 @@
{
"experimental": true,
"playground": true,
"loose": true
}

View File

@@ -6,6 +6,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.js]
[*.{js,json}]
indent_style = space
indent_size = 2

View File

@@ -3,6 +3,7 @@ language: node_js
node_js:
- "0.10"
- "0.11"
- "0.12"
branches:
except:

View File

@@ -11,6 +11,55 @@
_Note: Gaps between patch versions are faulty/broken releases._
## 3.6.0
* **New Feature**
* Add playground class property initializers.
* **Polish**
* Completely reimplemented scope tracking, can now track types and optimise certain helpers based on it.
* Extremely fast tail recursion optimisation implementation. Thanks [@RReverser](https://github.com/RReverser)!
* **Internal**
* Upgrade `regenerator-6to5`.
* Upgrade `acorn-6to5`.
* Upgrade `core-js`.
## 3.5.3
* Enable `es6.tailCall` transformer with the first implementation that only works with self referencing calls until we can implement nested tail calls elegantly.
## 3.5.2
* Disable `es6.tailCall` temporairly after reports of it breaking.
## 3.5.1
* **Polish**
* Allow tail calls to work across files without the runtime.
* **Internal**
* Upgrade `acorn-6to5`.
## 3.5.0
* **Bug Fix**
* Destructuring patterns as the left operator in `ForInStatement`/`ForOfStatement`.
* **Polish**
* Make default parameter IIFE invocation smarter.
* Make `__esModule` flag non-enumerable. Thanks [@daliwali](https://github.com/daliwali)!
* **Internal**
* More performance improvements.
* Parsing is now ~30% faster thanks to [marijnh/acorn@7264bc0178e7e6af7cfe02e9e0c6b26ee0e6007f](https://github.com/marijnh/acorn/commit/7264bc0178e7e6af7cfe02e9e0c6b26ee0e6007f).
* **New Feature**
* Optional `es6.blockScopingTDZ` is now completely functional and handles all edgecases.
* `super` in object literals.
* Tail call optimisation. Thanks [@RReverser](https://github.com/RReverser)!
## 3.4.1
* **Bug Fix**
* Fix conflicting `--module-ids` shorthand arg in `$ 6to5`.
* Add require hook options to cache key.
* Fix strict module formatter.
## 3.4.0
* **New Feature**

View File

@@ -1,6 +1,12 @@
# Contributing
Contributions are always welcome, no matter how large or small. Before contributing, please read the [code of conduct](https://github.com/6to5/6to5/blob/master/CODE_OF_CONDUCT.md).
Contributions are always welcome, no matter how large or small. Before
contributing, please read the
[code of conduct](https://github.com/6to5/6to5/blob/master/CODE_OF_CONDUCT.md).
**NOTE:** Please do not send pull requests that fix linting issues. It's highly
likely that they've already been fixed by the time it's submitted and it just
pollutes the git tree.
## Developing
@@ -12,7 +18,8 @@ Contributions are always welcome, no matter how large or small. Before contribut
* Link your forked clone (`npm link`)
* Develop your changes ensuring you're fetching updates from upstream often
* Ensure the test are passing (`make test`)
* Create new pull request explaining your proposed change or reference an issue in your commit message
* Create new pull request explaining your proposed change or reference an issue
in your commit message
#### Code Standards

View File

@@ -5,10 +5,17 @@ UGLIFY_CMD = node_modules/uglify-js/bin/uglifyjs
JSHINT_CMD = node_modules/jshint/bin/jshint
MOCHA_CMD = node_modules/mocha/bin/_mocha
JSCS_CMD = node_modules/jscs/bin/jscs
6TO5_CMD = node_modules/6to5/bin/6to5
export NODE_ENV = test
.PHONY: clean test test-cov test-clean lint test-travis test-simple test-all test-browser publish build bootstrap publish-core publish-runtime
.PHONY: clean test test-cov test-clean lint test-travis test-simple test-all test-browser publish build bootstrap publish-core publish-runtime build-core watch-core
build-core:
#node $(6TO5_CMD) src --out-dir lib
watch-core:
#node $(6TO5_CMD) src --out-dir lib --watch
build:
mkdir -p dist
@@ -18,7 +25,7 @@ build:
node $(BROWSERIFY_CMD) -e lib/6to5/polyfill.js >dist/polyfill.js
node $(UGLIFY_CMD) dist/polyfill.js >dist/polyfill.min.js
node $(BROWSERIFY_CMD) lib/6to5/browser.js -s to5 >dist/6to5.js
node $(BROWSERIFY_CMD) lib/6to5/api/browser.js -s to5 >dist/6to5.js
node $(UGLIFY_CMD) dist/6to5.js >dist/6to5.min.js
node bin/6to5-runtime >dist/runtime.js
@@ -55,7 +62,7 @@ test-cov:
export SIMPLE_6TO5_TESTS=1; \
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
test-travis: bootstrap
test-travis: build-core bootstrap
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
if test -n "$$CODECLIMATE_REPO_TOKEN"; then codeclimate < coverage/lcov.info; fi

View File

@@ -1,17 +0,0 @@
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.11"
install:
- "npm install"
- "cinst make"
test_script:
- "node --version"
- "npm --version"
- "make test-spec"
build: "off"
version: "{build}"

View File

@@ -37,8 +37,13 @@ module.exports = function (commander, filenames, opts) {
if (stat.isDirectory(filename)) {
var dirname = filename;
_.each(util.readdirFilter(dirname), function (filename) {
write(path.join(dirname, filename), filename);
_.each(util.readdir(dirname), function (filename) {
var src = path.join(dirname, filename);
if (util.canCompile(filename)) {
write(src, filename);
} else {
outputFileSync(path.join(commander.outDir, filename), fs.readFileSync(src));
}
});
} else {
write(filename, filename);

View File

@@ -23,7 +23,7 @@ commander.option("-L, --loose [list]", "List of transformers to enable loose mod
commander.option("-o, --out-file [out]", "Compile all input files into a single file");
commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory");
commander.option("-c, --remove-comments", "Remove comments from the compiled code", false);
commander.option("-i, --module-ids", "Insert module id in modules", false);
commander.option("-M, --module-ids", "Insert module id in modules", false);
commander.option("-R, --react-compat", "Makes the react transformer produce pre-v0.12 code");
commander.option("--keep-module-id-extensions", "Keep extensions when generating module ids", false);

View File

@@ -12,6 +12,10 @@ exports.readdirFilter = function (filename) {
});
};
exports.readdir = readdir;
exports.canCompile = util.canCompile;
exports.addSourceMappingUrl = function (code, loc) {
return code + "\n//# sourceMappingURL=" + path.basename(loc);
};

View File

@@ -44,8 +44,10 @@ var mtime = function (filename) {
var compile = function (filename) {
var result;
var cacheKey = filename + ":" + JSON.stringify(transformOpts);
if (cache) {
var cached = cache[filename];
var cached = cache[cacheKey];
if (cached && cached.mtime === mtime(filename)) {
result = cached;
}
@@ -60,7 +62,7 @@ var compile = function (filename) {
if (cache) {
result.mtime = mtime(filename);
cache[filename] = result;
cache[cacheKey] = result;
}
maps[filename] = result.map;

View File

@@ -1,5 +1,5 @@
var t = require("../types");
var _ = require("lodash");
var includes = require("lodash/collection/includes");
exports.AssignmentExpression = function (node, parent, detected) {
if (node.operator === "**=") {
@@ -38,7 +38,7 @@ exports.Property = function (node, parent, detected) {
};
exports.AssignmentPattern = function (node, parent, detected) {
if (t.isFunction(parent) && _.contains(parent.params, node)) {
if (t.isFunction(parent) && includes(parent.params, node)) {
detected("es6.parameters.default");
}
};

View File

@@ -3,7 +3,7 @@
module.exports = Buffer;
var isBoolean = require("lodash/lang/isBoolean");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var isNumber = require("lodash/lang/isNumber");
var util = require("../util");
@@ -159,7 +159,7 @@ Buffer.prototype.isLast = function (cha, trimRight) {
var last = buf[buf.length - 1];
if (Array.isArray(cha)) {
return contains(cha, last);
return includes(cha, last);
} else {
return cha === last;
}

View File

@@ -21,7 +21,7 @@ exports.IfStatement = function (node, print) {
print.indentOnComments(node.consequent);
if (node.alternate) {
if (this.isLast("}")) this.push(" ");
if (this.isLast("}")) this.space();
this.keyword("else");
if (this.format.format && !t.isBlockStatement(node.alternate)) {

48
lib/6to5/messages.js Normal file
View File

@@ -0,0 +1,48 @@
var util = require("util");
exports.messages = {
tailCallReassignmentDeopt: "Function reference has been reassigned so it's probably be dereferenced so we can't optimise this with confidence",
JSXNamespacedTags: "Namespace tags are not supported. ReactJSX is not XML.",
classesIllegalBareSuper: "Illegal use of bare super",
classesIllegalSuperCall: "Direct super call is illegal in non-constructor, use super.$1() instead",
classesIllegalConstructorKind: "Illegal kind for constructor method",
scopeDuplicateDeclaration: "Duplicate declaration $1",
undeclaredVariable: "Reference to undeclared variable $1",
undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?",
settersInvalidParamLength: "Setters must have only one parameter",
noAssignmentsInForHead: "No assignments allowed in for-in/of head",
expectedMemberExpressionOrIdentifier: "Expected type MemeberExpression or Identifier",
invalidParentForThisNode: "We don't know how to handle this node within the current parent - please open an issue",
readOnly: "$1 is read-only",
modulesIllegalExportName: "Illegal export $1",
unknownForHead: "Unknown node type $1 in ForStatement"
};
exports.get = function (key) {
var msg = exports.messages[key];
if (!msg) throw new ReferenceError("Unknown message `" + key + "`");
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
args = exports.parseArgs(args);
return msg.replace(/\$(\d+)/g, function (str, i) {
return args[--i];
});
};
exports.parseArgs = function (args) {
return args.map(function (val) {
if (val != null && val.inspect) {
return val.inspect();
} else {
try {
return JSON.stringify(val) || val + "";
} catch (e) {
return util.inspect(val);
}
}
});
};

View File

@@ -3,8 +3,6 @@
var extend = require("lodash/object/extend");
var t = require("./types");
require("./types/node");
// estraverse
var estraverse = require("estraverse");

View File

@@ -8,7 +8,7 @@ var isFunction = require("lodash/lang/isFunction");
var transform = require("./index");
var generate = require("../generation");
var defaults = require("lodash/object/defaults");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var clone = require("../helpers/clone");
var parse = require("../helpers/parse");
var Scope = require("../traversal/scope");
@@ -41,6 +41,7 @@ File.helpers = [
"tagged-template-literal-loose",
"interop-require",
"to-array",
"to-consumable-array",
"sliced-to-array",
"object-without-properties",
"has-own",
@@ -54,7 +55,10 @@ File.helpers = [
"get",
"set",
"class-call-check",
"object-destructuring-empty"
"object-destructuring-empty",
"temporal-undefined",
"temporal-assert-defined",
"tail-call"
];
File.validOptions = [
@@ -120,7 +124,10 @@ File.prototype.normalizeOptions = function (opts) {
});
// normalize windows path separators to unix
opts.filename = opts.filename.replace(/\\/g, "/");
opts.filename = util.normalisePathSeparator(opts.filename);
if (opts.sourceRoot) {
opts.sourceRoot = util.normalisePathSeparator(opts.sourceRoot);
}
opts.basename = path.basename(opts.filename, path.extname(opts.filename));
@@ -129,7 +136,7 @@ File.prototype.normalizeOptions = function (opts) {
opts.optional = util.arrayify(opts.optional);
opts.loose = util.arrayify(opts.loose);
if (contains(opts.loose, "all")) {
if (includes(opts.loose, "all") || includes(opts.loose, true)) {
opts.loose = Object.keys(transform.transformers);
}
@@ -163,11 +170,26 @@ File.prototype.normalizeOptions = function (opts) {
opts.optional = transform._ensureTransformerNames("optional", opts.optional);
opts.loose = transform._ensureTransformerNames("loose", opts.loose);
if (opts.reactCompat) {
opts.optional.push("reactCompat");
console.error("The reactCompat option has been moved into the optional transformer " +
"`reactCompat` - backwards compatibility will be removed in v4.0.0");
}
var ensureEnabled = function (key) {
var namespace = transform.transformerNamespaces[key];
if (namespace === "es7") opts.experimental = true;
if (namespace === "playground") opts.playground = true;
};
each(opts.whitelist, ensureEnabled);
each(opts.optional, ensureEnabled);
return opts;
};
File.prototype.isLoose = function (key) {
return contains(this.opts.loose, key);
return includes(this.opts.loose, key);
};
File.prototype.buildTransformers = function () {
@@ -204,22 +226,6 @@ File.prototype.debug = function (msg) {
util.debug(parts);
};
File.prototype.toArray = function (node, i) {
if (t.isArrayExpression(node)) {
return node;
} else if (t.isIdentifier(node) && node.name === "arguments") {
return t.callExpression(t.memberExpression(this.addHelper("slice"), t.identifier("call")), [node]);
} else {
var declarationName = "to-array";
var args = [node];
if (i) {
args.push(t.literal(i));
declarationName = "sliced-to-array";
}
return t.callExpression(this.addHelper(declarationName), args);
}
};
File.prototype.getModuleFormatter = function (type) {
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
@@ -290,8 +296,8 @@ File.prototype.isConsequenceExpressionStatement = function (node) {
};
File.prototype.addHelper = function (name) {
if (!contains(File.helpers, name)) {
throw new ReferenceError("unknown declaration " + name);
if (!includes(File.helpers, name)) {
throw new ReferenceError("Unknown helper " + name);
}
var program = this.ast.program;
@@ -316,6 +322,10 @@ File.prototype.addHelper = function (name) {
}
};
File.prototype.logDeopt = function () {
// todo, (node, msg)
};
File.prototype.errorWithNode = function (node, msg, Error) {
Error = Error || SyntaxError;
@@ -444,14 +454,14 @@ File.prototype.generateUid = function (name, scope) {
do {
uid = this._generateUid(name, i);
i++;
} while (scope.hasReference(uid));
} while (scope.hasBinding(uid) || scope.hasGlobal(uid));
return uid;
};
File.prototype.generateUidIdentifier = function (name, scope) {
scope = scope || this.scope;
var id = t.identifier(this.generateUid(name, scope));
scope.addDeclarationToFunctionScope("var", id);
scope.getFunctionParent().registerBinding("uid", id);
return id;
};

View File

@@ -0,0 +1,279 @@
"use strict";
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
// jsx
var isString = require("lodash/lang/isString");
var messages = require("../../messages");
var esutils = require("esutils");
var react = require("./react");
var t = require("../../types");
module.exports = function (exports, opts) {
exports.check = function (node) {
if (t.isJSX(node)) return true;
if (react.isCreateClass(node)) return true;
return false;
};
exports.JSXIdentifier = function (node, parent) {
if (node.name === "this" && t.isReferenced(node, parent)) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return t.literal(node.name);
}
};
exports.JSXNamespacedName = function (node, parent, scope, file) {
throw file.errorWithNode(node, messages.get("JSXNamespacedTags"));
};
exports.JSXMemberExpression = {
exit: function (node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.JSXExpressionContainer = function (node) {
return node.expression;
};
exports.JSXAttribute = {
exit: function (node) {
var value = node.value || t.literal(true);
return t.inherits(t.property("init", node.name, value), node);
}
};
exports.JSXOpeningElement = {
exit: function (node, parent, scope, file) {
var tagExpr = node.name;
var args = [];
var tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
var state = {
tagExpr: tagExpr,
tagName: tagName,
args: args
};
if (opts.pre) {
opts.pre(state);
}
var attribs = node.attributes;
if (attribs.length) {
attribs = buildJSXOpeningElementAttributes(attribs, file);
} else {
attribs = t.literal(null);
}
args.push(attribs);
if (opts.post) {
opts.post(state);
}
return state.call || t.callExpression(state.callee, args);
}
};
/**
* 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 buildJSXOpeningElementAttributes = function (attribs, file) {
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.isJSXSpreadAttribute(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(
file.addHelper("extends"),
objs
);
}
return attribs;
};
exports.JSXElement = {
exit: function (node) {
var callExpr = node.openingElement;
for (var i = 0; i < node.children.length; i++) {
var child = node.children[i];
if (t.isLiteral(child) && typeof child.value === "string") {
cleanJSXElementLiteralChild(child, callExpr.arguments);
continue;
} else if (t.isJSXEmptyExpression(child)) {
continue;
}
callExpr.arguments.push(child);
}
callExpr.arguments = flatten(callExpr.arguments);
if (callExpr.arguments.length >= 3) {
callExpr._prettyCall = true;
}
return t.inherits(callExpr, node);
}
};
var isStringLiteral = function (node) {
return t.isLiteral(node) && isString(node.value);
};
var flatten = function (args) {
var flattened = [];
var last;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (isStringLiteral(arg) && isStringLiteral(last)) {
last.value += arg.value;
} else {
last = arg;
flattened.push(arg);
}
}
return flattened;
};
var cleanJSXElementLiteralChild = function (child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
var lastNonEmptyLine = 0;
var i;
for (i = 0; i < lines.length; i++) {
if (lines[i].match(/[^ \t]/)) {
lastNonEmptyLine = i;
}
}
for (i = 0; i < lines.length; i++) {
var line = lines[i];
var isFirstLine = i === 0;
var isLastLine = i === lines.length - 1;
var isLastNonEmptyLine = i === lastNonEmptyLine;
// 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) {
if (!isLastNonEmptyLine) {
trimmedLine += " ";
}
args.push(t.literal(trimmedLine));
}
}
};
// display names
var addDisplayName = function (id, call) {
var props = call.arguments[0].properties;
var safe = true;
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (t.isIdentifier(prop.key, { name: "displayName" })) {
safe = false;
break;
}
}
if (safe) {
props.unshift(t.property("init", t.identifier("displayName"), t.literal(id)));
}
};
exports.ExportDeclaration = function (node, parent, scope, file) {
if (node.default && react.isCreateClass(node.declaration)) {
addDisplayName(file.opts.basename, node.declaration);
}
};
exports.AssignmentExpression =
exports.Property =
exports.VariableDeclarator = function (node) {
var left, right;
if (t.isAssignmentExpression(node)) {
left = node.left;
right = node.right;
} else if (t.isProperty(node)) {
left = node.key;
right = node.value;
} else if (t.isVariableDeclarator(node)) {
left = node.id;
right = node.init;
}
if (t.isMemberExpression(left)) {
left = left.property;
}
if (t.isIdentifier(left) && react.isCreateClass(right)) {
addDisplayName(left.name, right);
}
};
};

View File

@@ -18,7 +18,7 @@ var getObjRef = function (node, nodes, file, scope) {
} else if (t.isMemberExpression(node)) {
ref = node.object;
if (t.isIdentifier(ref) && scope.hasReference(ref.name)) {
if (t.isIdentifier(ref) && scope.hasGlobal(ref.name)) {
// the object reference that we need to save is locally declared
// so as per the previous comment we can be 100% sure evaluating
// it multiple times will be safe

View File

@@ -13,7 +13,7 @@ var visitor = {
// check that we don't have a local variable declared as that removes the need
// for the wrapper
var localDeclar = scope.getBinding(state.id);
var localDeclar = scope.getBindingIdentifier(state.id);
if (localDeclar !== state.outerDeclar) return;
state.selfReference = true;
@@ -31,20 +31,23 @@ exports.property = function (node, file, scope) {
var state = {
id: id,
selfReference: false,
outerDeclar: scope.getBinding(id),
outerDeclar: scope.getBindingIdentifier(id),
};
scope.traverse(node, visitor, state);
var method = node.value;
if (state.selfReference) {
// todo: support generators
node.value = util.template("property-method-assignment-wrapper", {
FUNCTION: node.value,
var templateName = "property-method-assignment-wrapper";
if (method.generator) templateName += "-generator";
node.value = util.template(templateName, {
FUNCTION: method,
FUNCTION_ID: key,
FUNCTION_KEY: scope.generateUidIdentifier(id),
WRAPPER_KEY: scope.generateUidIdentifier(id + "Wrapper")
});
} else {
node.value.id = key;
method.id = key;
}
};

View File

@@ -20,3 +20,7 @@ exports.isCreateClass = function (node) {
};
exports.isReactComponent = t.buildMatchMemberExpression("React.Component");
exports.isCompatTag = function (tagName) {
return tagName && /^[a-z]|\-/.test(tagName);
};

View File

@@ -2,19 +2,24 @@
module.exports = ReplaceSupers;
var t = require("../../types");
var messages = require("../../messages");
var t = require("../../types");
/**
* Description
*
* @param {Object} opts
* @param {Boolean} [inClass]
*/
function ReplaceSupers(opts) {
this.topLevelThisReference = null;
function ReplaceSupers(opts, inClass) {
this.topLevelThisReference = opts.topLevelThisReference;
this.methodNode = opts.methodNode;
this.className = opts.className;
this.superName = opts.superName;
this.isStatic = opts.isStatic;
this.hasSuper = false;
this.inClass = inClass;
this.isLoose = opts.isLoose;
this.scope = opts.scope;
this.file = opts.file;
@@ -28,19 +33,21 @@ function ReplaceSupers(opts) {
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this)
*
* @param {Node} property
* @param {boolean} isStatic
* @param {boolean} isComputed
* @param {Node} value
* @param {Boolean} isComputed
* @param {Node} thisExpression
*
* @returns {Node}
*/
ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, isComputed, thisExpression) {
ReplaceSupers.prototype.setSuperProperty = function (property, value, isComputed, thisExpression) {
return t.callExpression(
this.file.addHelper("set"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name),
@@ -58,20 +65,20 @@ ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic,
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
*
* @param {Node} property
* @param {boolean} isStatic
* @param {boolean} isComputed
* @param {Boolean} isComputed
* @param {Node} thisExpression
*
* @returns {Node}
*/
ReplaceSupers.prototype.getSuperProperty = function (property, isStatic, isComputed, thisExpression) {
ReplaceSupers.prototype.getSuperProperty = function (property, 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"))
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name),
@@ -153,7 +160,8 @@ ReplaceSupers.prototype.getThisReference = function () {
* @returns {Object}
*/
ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent) {
ReplaceSupers.prototype.getLooseSuperProperty = function (id, parent) {
var methodNode = this.methodNode;
var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function");
@@ -195,13 +203,15 @@ ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent
ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return this.getLooseSuperProperty(this.methodNode, node, parent);
this.hasSuper = true;
return this.getLooseSuperProperty(node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
this.hasSuper = true;
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference());
}
@@ -223,7 +233,7 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
var thisReference;
if (isIllegalBareSuper(node, parent)) {
throw this.file.errorWithNode(node, "Illegal use of bare super");
throw this.file.errorWithNode(node, messages.get("classesIllegalBareSuper"));
}
if (t.isCallExpression(node)) {
@@ -237,9 +247,9 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
// bare `super` call is illegal inside non-constructors
// - https://esdiscuss.org/topic/super-call-in-methods
// - https://twitter.com/wycats/status/544553184396836864
if (methodNode.key.name !== "constructor") {
if (methodNode.key.name !== "constructor" || !this.inClass) {
var methodName = methodNode.key.name || "METHOD_NAME";
throw this.file.errorWithNode(node, "Direct super call is illegal in non-constructor, use super." + methodName + "() instead");
throw this.file.errorWithNode(node, messages.get("classesIllegalSuperCall", methodName));
}
} else if (t.isMemberExpression(callee) && isSuper(callee.object, callee)) {
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
@@ -253,13 +263,16 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
computed = node.computed;
} else if (t.isAssignmentExpression(node) && isSuper(node.left.object, node.left) && methodNode.kind === "set") {
// super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this);
return this.setSuperProperty(node.left.property, node.right, methodNode.static, node.left.computed, getThisReference());
this.hasSuper = true;
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
}
if (!property) return;
this.hasSuper = true;
thisReference = getThisReference();
var superProperty = this.getSuperProperty(property, methodNode.static, computed, thisReference);
var superProperty = this.getSuperProperty(property, computed, thisReference);
if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments);

View File

@@ -56,8 +56,9 @@ transform._ensureTransformerNames = function (type, rawKeys) {
return keys;
};
transform.transformers = object();
transform.namespaces = object();
transform.transformerNamespaces = object();
transform.transformers = object();
transform.namespaces = object();
transform.deprecatedTransformerMap = require("./transformers/deprecated");
transform.moduleFormatters = require("./modules");
@@ -66,8 +67,10 @@ var rawTransformers = require("./transformers");
each(rawTransformers, function (transformer, key) {
var namespace = key.split(".")[0];
transform.namespaces[namespace] = transform.namespaces[namespace] || [];
transform.namespaces[namespace].push(key);
transform.transformerNamespaces[key] = namespace;
transform.transformers[key] = new Transformer(key, transformer);
});

View File

@@ -2,10 +2,11 @@
module.exports = DefaultFormatter;
var messages = require("../../messages");
var extend = require("lodash/object/extend");
var object = require("../../helpers/object");
var util = require("../../util");
var t = require("../../types");
var extend = require("lodash/object/extend");
function DefaultFormatter(file) {
this.file = file;
@@ -124,13 +125,6 @@ DefaultFormatter.prototype.isLocalReference = function (node) {
return t.isIdentifier(node) && localImports[node.name] && localImports[node.name] !== node;
};
DefaultFormatter.prototype.checkLocalReference = function (node) {
var file = this.file;
if (this.isLocalReference(node)) {
throw file.errorWithNode(node, "Illegal assignment of module import");
}
};
DefaultFormatter.prototype.remapExportAssignment = function (node) {
return t.assignmentExpression(
"=",
@@ -146,7 +140,7 @@ DefaultFormatter.prototype.remapExportAssignment = function (node) {
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
var localExports = this.localExports;
var name = node.name;
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBinding(name);
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.getBindingIdentifier(name);
};
DefaultFormatter.prototype.getModuleName = function () {
@@ -213,7 +207,7 @@ DefaultFormatter.prototype.getExternalReference = function (node, nodes) {
DefaultFormatter.prototype.checkExportIdentifier = function (node) {
if (t.isIdentifier(node, { name: "__esModule" })) {
throw this.file.errorWithNode(node, "Illegal export __esModule - this is used internally for CommonJS interop");
throw this.file.errorWithNode(node, messages.get("modulesIllegalExportName", node.name));
}
};

View File

@@ -4,7 +4,7 @@ var util = require("../../util");
module.exports = function (Parent) {
var Constructor = function () {
this.noInteropRequire = true;
this.noInteropRequireExport = true;
Parent.apply(this, arguments);
};

View File

@@ -6,7 +6,7 @@ var DefaultFormatter = require("./_default");
var CommonFormatter = require("./common");
var util = require("../../util");
var t = require("../../types");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var values = require("lodash/object/values");
function AMDFormatter() {
@@ -81,7 +81,7 @@ AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var key = t.getSpecifierName(specifier);
var ref = this.getExternalReference(node);
if (contains(this.file.dynamicImported, node)) {
if (includes(this.file.dynamicImported, node)) {
// Prevent unnecessary renaming of dynamic imports.
this.ids[node.source.value] = ref;
} else if (t.isImportBatchSpecifier(specifier)) {

View File

@@ -3,7 +3,7 @@
module.exports = CommonJSFormatter;
var DefaultFormatter = require("./_default");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var util = require("../../util");
var t = require("../../types");
@@ -14,8 +14,13 @@ function CommonJSFormatter() {
util.inherits(CommonJSFormatter, DefaultFormatter);
CommonJSFormatter.prototype.init = function () {
var file = this.file;
var scope = file.scope;
scope.rename("module");
if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
this.file.ast.program.body.push(util.template("exports-module-declaration", true));
file.ast.program.body.push(util.template("exports-module-declaration", true));
}
};
@@ -26,7 +31,7 @@ CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes)
// import foo from "foo";
if (t.isSpecifierDefault(specifier)) {
if (!contains(this.file.dynamicImported, node)) {
if (!includes(this.file.dynamicImported, node)) {
if (this.noInteropRequireImport) {
ref = t.memberExpression(ref, t.identifier("default"));
} else {

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["useStrict"]
}

View File

@@ -1 +1 @@
var VARIABLE_NAME = ARGUMENTS[ARGUMENT_KEY] === undefined ? DEFAULT_VALUE : ARGUMENTS[ARGUMENT_KEY];
let VARIABLE_NAME = ARGUMENTS[ARGUMENT_KEY] === undefined ? DEFAULT_VALUE : ARGUMENTS[ARGUMENT_KEY];

View File

@@ -1,7 +1,10 @@
(function (obj, defaults) {
for (var key in defaults) {
if (obj[key] === undefined) {
obj[key] = defaults[key];
var keys = Object.getOwnPropertyNames(defaults);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = Object.getOwnPropertyDescriptor(defaults, key);
if (value && value.configurable && obj[key] === undefined) {
Object.defineProperty(obj, key, value);
}
}
return obj;

View File

@@ -1 +1,3 @@
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,11 @@
(function (FUNCTION_KEY) {
var WRAPPER_KEY = function* FUNCTION_ID() {
return yield* FUNCTION_KEY.apply(this, arguments);
};
WRAPPER_KEY.toString = function () {
return FUNCTION_KEY.toString();
};
return WRAPPER_KEY;
})(FUNCTION)

View File

@@ -4,21 +4,16 @@
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return;
} else {
if (parent !== null) {
return set(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
return;
return desc.value = value;
} else {
var setter = desc.set;
if (setter === undefined) {
return;
if (setter !== undefined) {
return setter.call(receiver, value);
}
return setter.call(receiver, value);
}
});

View File

@@ -0,0 +1,3 @@
{
FUNCTION_ID:while (true) BLOCK
}

View File

@@ -0,0 +1,23 @@
(function () {
function Tail(func, args, context) {
this.func = func;
this.args = args;
this.context = context;
}
Tail.prototype._isTailDescriptor = true;
var isRunning = false;
return function (func, args, context) {
var result = new Tail(func, args, context);
if (!isRunning) {
isRunning = true;
do {
result = result.func.apply(result.context, result.args);
} while (result instanceof Tail || (result && result._isTailDescriptor));
isRunning = false;
}
return result;
};
})()

View File

@@ -0,0 +1,6 @@
(function (val, name, undef) {
if (val === undef) {
throw new ReferenceError(name + " is not defined - temporal dead zone");
}
return true;
})

View File

@@ -0,0 +1 @@
({})

View File

@@ -0,0 +1,8 @@
(function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
});

View File

@@ -1,6 +1,6 @@
module.exports = TransformerPass;
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
/**
* This class is responsible for traversing over the provided `File`s
@@ -25,14 +25,14 @@ TransformerPass.prototype.canRun = function () {
// blacklist
var blacklist = opts.blacklist;
if (blacklist.length && contains(blacklist, key)) return false;
if (blacklist.length && includes(blacklist, key)) return false;
// whitelist
var whitelist = opts.whitelist;
if (whitelist.length && !contains(whitelist, key)) return false;
if (whitelist.length) return includes(whitelist, key);
// optional
if (transformer.optional && !contains(opts.optional, key)) return false;
if (transformer.optional && !includes(opts.optional, key)) return false;
// experimental
if (transformer.experimental && !opts.experimental) return false;

View File

@@ -10,24 +10,20 @@ var visitor = {
if (!declared) return;
// declared node is different in this scope
if (scope.getBinding(node.name) !== declared) return;
if (scope.getBindingIdentifier(node.name) !== declared) return;
var declaredLoc = declared.loc;
var referenceLoc = node.loc;
var assert = t.callExpression(
state.file.addHelper("temporal-assert-defined"),
[node, t.literal(node.name), state.file.addHelper("temporal-undefined")]
);
if (!declaredLoc || !referenceLoc) return;
this.skip();
// 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");
if (t.isAssignmentExpression(parent) || t.isUpdateExpression(parent)) {
if (parent._ignoreBlockScopingTDZ) return;
this.parentPath.replaceNode(t.sequenceExpression([assert, parent]));
} else {
return t.logicalExpression("&&", assert, node);
}
}
};

View File

@@ -17,7 +17,7 @@ var isLet = function (node, parent) {
if (node.kind !== "let") return false;
// https://github.com/6to5/6to5/issues/255
if (!t.isFor(parent) || t.isFor(parent) && parent.left !== node) {
if (isLetInitable(node, parent)) {
for (var i = 0; i < node.declarations.length; i++) {
var declar = node.declarations[i];
declar.init = declar.init || t.identifier("undefined");
@@ -29,6 +29,10 @@ var isLet = function (node, parent) {
return true;
};
var isLetInitable = function (node, parent) {
return !t.isFor(parent) || t.isFor(parent) && parent.left !== node;
};
var isVar = function (node, parent) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent);
};
@@ -39,8 +43,26 @@ var standardizeLets = function (declars) {
}
};
exports.VariableDeclaration = function (node, parent) {
isLet(node, parent);
exports.VariableDeclaration = function (node, parent, scope, file) {
if (!isLet(node, parent)) return;
if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun()) {
var nodes = [node];
for (var i = 0; i < node.declarations.length; i++) {
var decl = node.declarations[i];
if (decl.init) {
var assign = t.assignmentExpression("=", decl.id, decl.init);
assign._ignoreBlockScopingTDZ = true;
nodes.push(t.expressionStatement(assign));
}
decl.init = file.addHelper("temporal-undefined");
}
node._blockHoist = 2;
return nodes;
}
};
exports.Loop = function (node, parent, scope, file) {
@@ -114,7 +136,7 @@ function replace(node, parent, scope, remaps) {
var remap = remaps[node.name];
if (!remap) return;
var ownBinding = scope.getBinding(node.name);
var ownBinding = scope.getBindingIdentifier(node.name);
if (ownBinding === remap.binding) {
node.name = remap.uid;
} else {
@@ -153,7 +175,7 @@ BlockScoping.prototype.remap = function () {
// this is the defining identifier of a declaration
var ref = letRefs[key];
if (scope.parentHasReference(key)) {
if (scope.parentHasBinding(key) || scope.hasGlobal(key)) {
var uid = scope.generateUidIdentifier(ref.name).name;
ref.name = uid;

View File

@@ -3,13 +3,14 @@
var ReplaceSupers = require("../../helpers/replace-supers");
var nameMethod = require("../../helpers/name-method");
var defineMap = require("../../helpers/define-map");
var messages = require("../../../messages");
var util = require("../../../util");
var t = require("../../../types");
exports.check = t.isClass;
exports.ClassDeclaration = function (node, parent, scope, file) {
return new Class(node, file, scope, true).run();
return new ClassTransformer(node, file, scope, true).run();
};
exports.ClassExpression = function (node, parent, scope, file) {
@@ -25,7 +26,7 @@ exports.ClassExpression = function (node, parent, scope, file) {
}
}
return new Class(node, file, scope, false).run();
return new ClassTransformer(node, file, scope, false).run();
};
/**
@@ -37,7 +38,7 @@ exports.ClassExpression = function (node, parent, scope, file) {
* @param {Boolean} closure
*/
function Class(node, file, scope, isStatement) {
function ClassTransformer(node, file, scope, isStatement) {
this.isStatement = isStatement;
this.scope = scope;
this.node = node;
@@ -61,7 +62,7 @@ function Class(node, file, scope, isStatement) {
* @returns {Array}
*/
Class.prototype.run = function () {
ClassTransformer.prototype.run = function () {
var superName = this.superName;
var className = this.className;
var file = this.file;
@@ -138,7 +139,7 @@ Class.prototype.run = function () {
* Description
*/
Class.prototype.buildBody = function () {
ClassTransformer.prototype.buildBody = function () {
var constructor = this.constructor;
var className = this.className;
var superName = this.superName;
@@ -152,10 +153,11 @@ Class.prototype.buildBody = function () {
methodNode: node,
className: this.className,
superName: this.superName,
isStatic: node.static,
isLoose: this.isLoose,
scope: this.scope,
file: this.file
});
}, true);
replaceSupers.replace();
if (node.key.name === "constructor") {
@@ -166,6 +168,8 @@ Class.prototype.buildBody = function () {
} else if (t.isPrivateDeclaration(node)) {
this.closure = true;
body.unshift(node);
} else if (t.isClassProperty(node)) {
this.pushProperty(node);
}
}
@@ -208,7 +212,7 @@ Class.prototype.buildBody = function () {
* @param {Node} node MethodDefinition
*/
Class.prototype.pushMethod = function (node) {
ClassTransformer.prototype.pushMethod = function (node) {
var methodName = node.key;
var kind = node.kind;
@@ -244,15 +248,39 @@ Class.prototype.pushMethod = function (node) {
defineMap.push(mutatorMap, methodName, "enumerable", node.computed, false);
};
/**
* Description
*
* @param {Node} node
*/
ClassTransformer.prototype.pushProperty = function (node) {
if (!node.value) return;
var key;
if (node.static) {
key = t.memberExpression(this.className, node.key);
this.body.push(
t.expressionStatement(t.assignmentExpression("=", key, node.value))
);
} else {
key = t.memberExpression(t.thisExpression(), node.key);
this.constructor.body.body.unshift(
t.expressionStatement(t.assignmentExpression("=", key, node.value))
);
}
};
/**
* Replace the constructor body of our class.
*
* @param {Node} method MethodDefinition
*/
Class.prototype.pushConstructor = function (method) {
ClassTransformer.prototype.pushConstructor = function (method) {
if (method.kind) {
throw this.file.errorWithNode(method, "illegal kind for constructor method");
throw this.file.errorWithNode(method, messages.get("classesIllegalConstructorKind"));
}
var construct = this.constructor;

View File

@@ -1,6 +1,7 @@
"use strict";
var t = require("../../../types");
var messages = require("../../../messages");
var t = require("../../../types");
exports.check = function (node) {
return t.isVariableDeclaration(node, { kind: "const" });
@@ -11,33 +12,35 @@ var visitor = {
if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
var ids = t.getBindingIdentifiers(node);
for (var key in ids) {
var id = ids[key];
for (var name in ids) {
var id = ids[name];
var constant = state.constants[key];
var constant = state.constants[name];
// no constant exists
if (!constant) continue;
var constantIdentifier = constant.identifier;
// check if the assignment id matches the constant declaration id
// if it does then it was the id used to initially declare the
// constant so we can just ignore it
if (id === constant) continue;
if (id === constantIdentifier) continue;
// check if there's been a local binding that shadows this constant
if (!scope.bindingEquals(key, constant)) continue;
if (!scope.bindingIdentifierEquals(name, constantIdentifier)) continue;
throw state.file.errorWithNode(id, key + " is read-only");
throw state.file.errorWithNode(id, messages.get("readOnly", name));
}
} else if (t.isScope(node)) {
} else if (t.isScope(node, parent)) {
this.skip();
}
}
};
exports.Scope = function (node, parent, scope, file) {
exports.Scopable = function (node, parent, scope, file) {
scope.traverse(node, visitor, {
constants: scope.getAllDeclarationsOfKind("const"),
constants: scope.getAllBindingsOfKind("const"),
file: file
});
};

View File

@@ -1,10 +1,11 @@
"use strict";
var t = require("../../../types");
var messages = require("../../../messages");
var t = require("../../../types");
exports.check = t.isPattern;
function Destructuring(opts) {
function DestructuringTransformer(opts) {
this.blockHoist = opts.blockHoist;
this.operator = opts.operator;
this.nodes = opts.nodes;
@@ -13,7 +14,7 @@ function Destructuring(opts) {
this.kind = opts.kind;
}
Destructuring.prototype.buildVariableAssignment = function (id, init) {
DestructuringTransformer.prototype.buildVariableAssignment = function (id, init) {
var op = this.operator;
if (t.isMemberExpression(id)) op = "=";
@@ -32,7 +33,7 @@ Destructuring.prototype.buildVariableAssignment = function (id, init) {
return node;
};
Destructuring.prototype.buildVariableDeclaration = function (id, init) {
DestructuringTransformer.prototype.buildVariableDeclaration = function (id, init) {
var declar = t.variableDeclaration("var", [
t.variableDeclarator(id, init)
]);
@@ -40,7 +41,7 @@ Destructuring.prototype.buildVariableDeclaration = function (id, init) {
return declar;
};
Destructuring.prototype.push = function (elem, parentId) {
DestructuringTransformer.prototype.push = function (elem, parentId) {
if (t.isObjectPattern(elem)) {
this.pushObjectPattern(elem, parentId);
} else if (t.isArrayPattern(elem)) {
@@ -52,7 +53,7 @@ Destructuring.prototype.push = function (elem, parentId) {
}
};
Destructuring.prototype.pushAssignmentPattern = function (pattern, parentId) {
DestructuringTransformer.prototype.pushAssignmentPattern = function (pattern, parentId) {
var tempParentId = this.scope.generateUidBasedOnNode(parentId);
var declar = t.variableDeclaration("var", [
@@ -71,7 +72,7 @@ Destructuring.prototype.pushAssignmentPattern = function (pattern, parentId) {
));
};
Destructuring.prototype.pushObjectSpread = function (pattern, parentId, prop, i) {
DestructuringTransformer.prototype.pushObjectSpread = function (pattern, parentId, prop, i) {
// get all the keys that appear in this object before the current spread
var keys = [];
for (var i2 = 0; i2 < pattern.properties.length; i2++) {
@@ -92,7 +93,7 @@ Destructuring.prototype.pushObjectSpread = function (pattern, parentId, prop, i)
this.nodes.push(this.buildVariableAssignment(prop.argument, value));
};
Destructuring.prototype.pushObjectProperty = function (prop, parentId) {
DestructuringTransformer.prototype.pushObjectProperty = function (prop, parentId) {
if (t.isLiteral(prop.key)) prop.computed = true;
var pattern2 = prop.value;
@@ -105,13 +106,19 @@ Destructuring.prototype.pushObjectProperty = function (prop, parentId) {
}
};
Destructuring.prototype.pushObjectPattern = function (pattern, parentId) {
DestructuringTransformer.prototype.pushObjectPattern = function (pattern, parentId) {
if (!pattern.properties.length) {
this.nodes.push(t.expressionStatement(
t.callExpression(this.file.addHelper("object-destructuring-empty"), [parentId])
));
}
if (pattern.properties.length > 1 && t.isMemberExpression(parentId)) {
var temp = this.scope.generateUidBasedOnNode(parentId, this.file);
this.nodes.push(this.buildVariableDeclaration(temp, parentId));
parentId = temp;
}
for (var i = 0; i < pattern.properties.length; i++) {
var prop = pattern.properties[i];
if (t.isSpreadProperty(prop)) {
@@ -131,18 +138,20 @@ var hasRest = function (pattern) {
return false;
};
Destructuring.prototype.pushArrayPattern = function (pattern, parentId) {
DestructuringTransformer.prototype.pushArrayPattern = function (pattern, parentId) {
if (!pattern.elements) return;
// if we have a rest then we need all the elements
var count = !hasRest(pattern) && pattern.elements.length;
var toArray = this.file.toArray(parentId, count);
var toArray = this.scope.toArray(parentId, count);
var _parentId = this.scope.generateUidBasedOnNode(parentId, this.file);
var _parentId = this.scope.generateUidBasedOnNode(parentId);
this.nodes.push(this.buildVariableDeclaration(_parentId, toArray));
parentId = _parentId;
this.scope.assignTypeGeneric(parentId.name, "Array");
for (var i = 0; i < pattern.elements.length; i++) {
var elem = pattern.elements[i];
@@ -152,7 +161,7 @@ Destructuring.prototype.pushArrayPattern = function (pattern, parentId) {
var newPatternId;
if (t.isRestElement(elem)) {
newPatternId = this.file.toArray(parentId);
newPatternId = this.scope.toArray(parentId);
if (i > 0) {
newPatternId = t.callExpression(t.memberExpression(newPatternId, t.identifier("slice")), [t.literal(i)]);
@@ -167,7 +176,7 @@ Destructuring.prototype.pushArrayPattern = function (pattern, parentId) {
}
};
Destructuring.prototype.init = function (pattern, parentId) {
DestructuringTransformer.prototype.init = function (pattern, parentId) {
if (!t.isArrayExpression(parentId) && !t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) {
var key = this.scope.generateUidBasedOnNode(parentId);
this.nodes.push(this.buildVariableDeclaration(key, parentId));
@@ -179,21 +188,40 @@ Destructuring.prototype.init = function (pattern, parentId) {
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, scope, file) {
var declar = node.left;
if (!t.isVariableDeclaration(declar)) return;
var left = node.left;
var pattern = declar.declarations[0].id;
if (t.isPattern(left)) {
// for ({ length: k } in { abc: 3 });
var temp = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration("var", [
t.variableDeclarator(temp)
]);
t.ensureBlock(node);
node.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(left, temp)
]));
return;
}
if (!t.isVariableDeclaration(left)) return;
var pattern = left.declarations[0].id;
if (!t.isPattern(pattern)) return;
var key = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration(declar.kind, [
node.left = t.variableDeclaration(left.kind, [
t.variableDeclarator(key, null)
]);
var nodes = [];
var destructuring = new Destructuring({
kind: declar.kind,
var destructuring = new DestructuringTransformer({
kind: left.kind,
file: file,
scope: scope,
nodes: nodes
@@ -210,15 +238,15 @@ exports.ForOfStatement = function (node, parent, scope, file) {
exports.Function = function (node, parent, scope, file) {
var nodes = [];
var hasDestructuring = false;
var hasDestructuringTransformer = false;
node.params = node.params.map(function (pattern, i) {
if (!t.isPattern(pattern)) return pattern;
hasDestructuring = true;
hasDestructuringTransformer = true;
var parentId = scope.generateUidIdentifier("ref");
var destructuring = new Destructuring({
var destructuring = new DestructuringTransformer({
blockHoist: node.params.length - i,
nodes: nodes,
scope: scope,
@@ -230,7 +258,7 @@ exports.Function = function (node, parent, scope, file) {
return parentId;
});
if (!hasDestructuring) return;
if (!hasDestructuringTransformer) return;
t.ensureBlock(node);
@@ -247,8 +275,8 @@ exports.CatchClause = function (node, parent, scope, file) {
var nodes = [];
var destructuring = new Destructuring({
kind: "var",
var destructuring = new DestructuringTransformer({
kind: "let",
file: file,
scope: scope,
nodes: nodes
@@ -256,6 +284,8 @@ exports.CatchClause = function (node, parent, scope, file) {
destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body);
return node;
};
exports.ExpressionStatement = function (node, parent, scope, file) {
@@ -271,7 +301,7 @@ exports.ExpressionStatement = function (node, parent, scope, file) {
t.variableDeclarator(ref, expr.right)
]));
var destructuring = new Destructuring({
var destructuring = new DestructuringTransformer({
operator: expr.operator,
file: file,
scope: scope,
@@ -294,7 +324,7 @@ exports.AssignmentExpression = function (node, parent, scope, file) {
var nodes = [];
nodes.push(t.assignmentExpression("=", ref, node.right));
var destructuring = new Destructuring({
var destructuring = new DestructuringTransformer({
operator: node.operator,
file: file,
scope: scope,
@@ -329,7 +359,7 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
var patternId = declar.init;
var pattern = declar.id;
var destructuring = new Destructuring({
var destructuring = new DestructuringTransformer({
nodes: nodes,
scope: scope,
kind: node.kind,
@@ -360,7 +390,7 @@ exports.VariableDeclaration = function (node, parent, scope, file) {
declar = declar || t.variableDeclaration(node.kind, []);
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
throw file.errorWithNode(node, "Cannot use this node within the current parent");
throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
}
declar.declarations = declar.declarations.concat(node.declarations);

View File

@@ -1,7 +1,8 @@
"use strict";
var util = require("../../../util");
var t = require("../../../types");
var messages = require("../../../messages");
var util = require("../../../util");
var t = require("../../../types");
exports.check = t.isForOfStatement;
@@ -28,6 +29,8 @@ exports.ForOfStatement = function (node, parent, scope, file) {
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
t.inherits(loop, node);
// todo: find out why this is necessary? #538
loop._scopeInfo = node._scopeInfo;
@@ -48,7 +51,7 @@ var loose = function (node, parent, scope, file) {
t.variableDeclarator(left.declarations[0].id, id)
]);
} else {
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
throw file.errorWithNode(left, messages.get("unknownForHead", left.type));
}
var loop = util.template("for-of-loose", {
@@ -87,7 +90,7 @@ var spec = function (node, parent, scope, file) {
t.variableDeclarator(left.declarations[0].id, stepValue)
]);
} else {
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
throw file.errorWithNode(left, messages.get("unknownForHead", left.type));
}
var loop = util.template("for-of", {

View File

@@ -0,0 +1,34 @@
"use strict";
var ReplaceSupers = require("../../helpers/replace-supers");
var t = require("../../../types");
exports.check = function (node) {
return t.isIdentifier(node, { name: "super" });
};
exports.Property = function (node, parent, scope, file) {
if (!node.method) return;
var value = node.value;
var thisExpr = scope.generateUidIdentifier("this");
var replaceSupers = new ReplaceSupers({
topLevelThisReference: thisExpr,
methodNode: node,
className: thisExpr,
isStatic: true,
scope: scope,
file: file
});
replaceSupers.replace();
if (replaceSupers.hasSuper) {
value.body.body.unshift(
t.variableDeclaration("var", [
t.variableDeclarator(thisExpr, t.thisExpression())
])
);
}
};

View File

@@ -9,21 +9,23 @@ exports.check = function (node) {
var hasDefaults = function (node) {
for (var i = 0; i < node.params.length; i++) {
if (t.isAssignmentPattern(node.params[i])) return true;
if (!t.isIdentifier(node.params[i])) return true;
}
return false;
};
var iifeVisitor = {
enter: function (node, parent, scope, state) {
if (t.isReferencedIdentifier(node, parent) && state.scope.hasOwnReference(node.name)) {
state.iife = true;
this.stop();
}
if (!t.isReferencedIdentifier(node, parent)) return;
if (!state.scope.hasOwnBinding(node.name)) return;
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
state.iife = true;
this.stop();
}
};
exports.Function = function (node, parent, scope) {
exports.Function = function (node, parent, scope, file) {
if (!hasDefaults(node)) return;
t.ensureBlock(node);
@@ -37,35 +39,53 @@ exports.Function = function (node, parent, scope) {
var state = { iife: false, scope: scope };
var pushDefNode = function (left, right, i) {
var defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(i),
ARGUMENTS: argsIdentifier
}, true);
file.checkNode(defNode);
defNode._blockHoist = node.params.length - i;
body.push(defNode);
};
for (var i = 0; i < node.params.length; i++) {
var param = node.params[i];
if (!t.isAssignmentPattern(param)) {
lastNonDefaultParam = +i + 1;
if (!t.isRestElement(param)) {
lastNonDefaultParam = i + 1;
}
if (!t.isIdentifier(param)) {
scope.traverse(param, iifeVisitor, state);
}
if (file.transformers["es6.blockScopingTDZ"].canRun()) {
pushDefNode(param, t.identifier("undefined"), i);
}
continue;
}
var left = param.left;
var right = param.right;
node.params[i] = scope.generateUidIdentifier("x");
var placeholder = scope.generateUidIdentifier("x");
placeholder._isDefaultPlaceholder = true;
node.params[i] = placeholder;
if (!state.iife) {
if (t.isIdentifier(right) && scope.hasOwnReference(right.name)) {
if (t.isIdentifier(right) && scope.hasOwnBinding(right.name)) {
state.iife = true;
} else {
scope.traverse(right, iifeVisitor, state);
}
}
var defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(+i),
ARGUMENTS: argsIdentifier
}, true);
defNode._blockHoist = node.params.length - i;
body.push(defNode);
pushDefNode(left, right, i);
}
// we need to cut off all trailing default parameters

View File

@@ -60,6 +60,8 @@ exports.Function = function (node, parent, scope) {
node.body.body.unshift(restDeclar);
}
scope.assignTypeGeneric(rest.name, "Array");
var loop = util.template("rest", {
ARGUMENTS: argsId,
ARRAY_KEY: arrKey,

View File

@@ -1,12 +1,12 @@
"use strict";
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var t = require("../../../types");
exports.check = t.isSpreadElement;
var getSpreadLiteral = function (spread, file) {
return file.toArray(spread.argument);
var getSpreadLiteral = function (spread, scope) {
return scope.toArray(spread.argument, true);
};
var hasSpread = function (nodes) {
@@ -18,7 +18,7 @@ var hasSpread = function (nodes) {
return false;
};
var build = function (props, file) {
var build = function (props, scope) {
var nodes = [];
var _props = [];
@@ -33,7 +33,7 @@ var build = function (props, file) {
var prop = props[i];
if (t.isSpreadElement(prop)) {
push();
nodes.push(getSpreadLiteral(prop, file));
nodes.push(getSpreadLiteral(prop, scope));
} else {
_props.push(prop);
}
@@ -44,11 +44,11 @@ var build = function (props, file) {
return nodes;
};
exports.ArrayExpression = function (node, parent, scope, file) {
exports.ArrayExpression = function (node, parent, scope) {
var elements = node.elements;
if (!hasSpread(elements)) return;
var nodes = build(elements, file);
var nodes = build(elements, scope);
var first = nodes.shift();
if (!t.isArrayExpression(first)) {
@@ -59,7 +59,7 @@ exports.ArrayExpression = function (node, parent, scope, file) {
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
};
exports.CallExpression = function (node, parent, scope, file) {
exports.CallExpression = function (node, parent, scope) {
var args = node.arguments;
if (!hasSpread(args)) return;
@@ -71,10 +71,10 @@ exports.CallExpression = function (node, parent, scope, file) {
if (args.length === 1 && args[0].argument.name === "arguments") {
nodes = [args[0].argument];
} else {
nodes = build(args, file);
nodes = build(args, scope);
}
var first = nodes.shift();
var first = nodes.shift();
if (nodes.length) {
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes));
} else {
@@ -103,9 +103,9 @@ exports.NewExpression = function (node, parent, scope, file) {
var args = node.arguments;
if (!hasSpread(args)) return;
var nativeType = t.isIdentifier(node.callee) && contains(t.NATIVE_TYPE_NAMES, node.callee.name);
var nativeType = t.isIdentifier(node.callee) && includes(t.NATIVE_TYPE_NAMES, node.callee.name);
var nodes = build(args, file);
var nodes = build(args, scope);
if (nativeType) {
nodes.unshift(t.arrayExpression([t.literal(null)]));

View File

@@ -0,0 +1,359 @@
"use strict";
var reduceRight = require("lodash/collection/reduceRight");
var messages = require("../../../messages");
var flatten = require("lodash/array/flatten");
var util = require("../../../util");
var map = require("lodash/collection/map");
var t = require("../../../types");
function returnBlock(expr) {
return t.blockStatement([t.returnStatement(expr)]);
}
function TailCallTransformer(node, scope, file) {
this.hasTailRecursion = false;
this.needsArguments = false;
this.setsArguments = false;
this.needsThis = false;
this.ownerId = node.id;
this.vars = [];
this.scope = scope;
this.file = file;
this.node = node;
}
TailCallTransformer.prototype.getArgumentsId = function () {
return this.argumentsId = this.argumentsId || this.scope.generateUidIdentifier("arguments");
};
TailCallTransformer.prototype.getThisId = function () {
return this.thisId = this.thisId || this.scope.generateUidIdentifier("this");
};
TailCallTransformer.prototype.getLeftId = function () {
return this.leftId = this.leftId || this.scope.generateUidIdentifier("left");
};
TailCallTransformer.prototype.getFunctionId = function () {
return this.functionId = this.functionId || this.scope.generateUidIdentifier("function");
};
TailCallTransformer.prototype.getParams = function () {
var params = this.params;
if (!params) {
params = this.node.params;
this.paramDecls = [];
for (var i = 0; i < params.length; i++) {
var param = params[i];
if (!param._isDefaultPlaceholder) {
this.paramDecls.push(t.variableDeclarator(
param,
params[i] = this.scope.generateUidIdentifier("x")
));
}
}
}
return this.params = params;
};
TailCallTransformer.prototype.hasDeopt = function () {
// check if the ownerId has been reassigned, if it has then it's not safe to
// perform optimisations
var ownerIdInfo = this.scope.getBindingInfo(this.ownerId.name);
return ownerIdInfo && ownerIdInfo.reassigned;
};
TailCallTransformer.prototype.run = function () {
var scope = this.scope;
var node = this.node;
// only tail recursion can be optimized as for now, so we can skip anonymous
// functions entirely
var ownerId = this.ownerId;
if (!ownerId) return;
// traverse the function and look for tail recursion
scope.traverse(node, firstPass, this);
if (!this.hasTailRecursion) return;
if (this.hasDeopt()) {
this.file.logDeopt(node, messages.get("tailCallReassignmentDeopt"));
return;
}
//
scope.traverse(node, secondPass, this);
if (!this.needsThis || !this.needsArguments) {
scope.traverse(node, thirdPass, this);
}
var body = t.ensureBlock(node).body;
if (this.vars.length > 0) {
var declarations = flatten(map(this.vars, function (decl) {
return decl.declarations;
}, this));
var statement = reduceRight(declarations, function (expr, decl) {
return t.assignmentExpression("=", decl.id, expr);
}, t.identifier("undefined"));
body.unshift(t.expressionStatement(statement));
}
var paramDecls = this.paramDecls;
if (paramDecls.length > 0) {
body.unshift(t.variableDeclaration("var", paramDecls));
}
node.body = util.template("tail-call-body", {
THIS_ID: this.thisId,
ARGUMENTS_ID: this.argumentsId,
FUNCTION_ID: this.getFunctionId(),
BLOCK: node.body
});
var topVars = [];
if (this.needsThis) {
topVars.push(t.variableDeclarator(this.getThisId(), t.thisExpression()));
}
if (this.needsArguments || this.setsArguments) {
var decl = t.variableDeclarator(this.getArgumentsId());
if (this.needsArguments) {
decl.init = t.identifier("arguments");
}
topVars.push(decl);
}
var leftId = this.leftId;
if (leftId) {
topVars.push(t.variableDeclarator(leftId));
}
if (topVars.length > 0) {
node.body.body.unshift(t.variableDeclaration("var", topVars));
}
};
TailCallTransformer.prototype.subTransform = function (node) {
if (!node) return;
var handler = this["subTransform" + node.type];
if (handler) return handler.call(this, node);
};
TailCallTransformer.prototype.subTransformConditionalExpression = function (node) {
var callConsequent = this.subTransform(node.consequent);
var callAlternate = this.subTransform(node.alternate);
if (!callConsequent && !callAlternate) {
return;
}
// if ternary operator had tail recursion in value, convert to optimized if-statement
node.type = "IfStatement";
node.consequent = callConsequent ? t.toBlock(callConsequent) : returnBlock(node.consequent);
if (callAlternate) {
node.alternate = t.isIfStatement(callAlternate) ? callAlternate : t.toBlock(callAlternate);
} else {
node.alternate = returnBlock(node.alternate);
}
return [node];
};
TailCallTransformer.prototype.subTransformLogicalExpression = function (node) {
// only call in right-value of can be optimized
var callRight = this.subTransform(node.right);
if (!callRight) return;
// cache left value as it might have side-effects
var leftId = this.getLeftId();
var testExpr = t.assignmentExpression(
"=",
leftId,
node.left
);
if (node.operator === "&&") {
testExpr = t.unaryExpression("!", testExpr);
}
return [t.ifStatement(testExpr, returnBlock(leftId))].concat(callRight);
};
TailCallTransformer.prototype.subTransformSequenceExpression = function (node) {
var seq = node.expressions;
// only last element can be optimized
var lastCall = this.subTransform(seq[seq.length - 1]);
if (!lastCall) {
return;
}
// remove converted expression from sequence
// and convert to regular expression if needed
if (--seq.length === 1) {
node = seq[0];
}
return [t.expressionStatement(node)].concat(lastCall);
};
TailCallTransformer.prototype.subTransformCallExpression = function (node) {
var callee = node.callee, thisBinding, args;
if (t.isMemberExpression(callee, { computed: false }) && t.isIdentifier(callee.property)) {
switch (callee.property.name) {
case "call":
args = t.arrayExpression(node.arguments.slice(1));
break;
case "apply":
args = node.arguments[1] || t.identifier("undefined");
break;
default:
return;
}
thisBinding = node.arguments[0];
callee = callee.object;
}
// only tail recursion can be optimized as for now
if (!t.isIdentifier(callee) || !this.scope.bindingIdentifierEquals(callee.name, this.ownerId)) {
return;
}
this.hasTailRecursion = true;
if (this.hasDeopt()) return;
var body = [];
if (!t.isThisExpression(thisBinding)) {
body.push(t.expressionStatement(t.assignmentExpression(
"=",
this.getThisId(),
thisBinding || t.identifier("undefined")
)));
}
if (!args) {
args = t.arrayExpression(node.arguments);
}
var argumentsId = this.getArgumentsId();
var params = this.getParams();
body.push(t.expressionStatement(t.assignmentExpression(
"=",
argumentsId,
args
)));
var i, param;
if (t.isArrayExpression(args)) {
var elems = args.elements;
for (i = 0; i < elems.length && i < params.length; i++) {
param = params[i];
var elem = elems[i] || (elems[i] = t.identifier("undefined"));
if (!param._isDefaultPlaceholder) {
elems[i] = t.assignmentExpression("=", param, elem);
}
}
} else {
this.setsArguments = true;
for (i = 0; i < params.length; i++) {
param = params[i];
if (!param._isDefaultPlaceholder) {
body.push(t.expressionStatement(t.assignmentExpression(
"=",
param,
t.memberExpression(argumentsId, t.literal(i), true)
)));
}
}
}
body.push(t.continueStatement(this.getFunctionId()));
return body;
};
// looks for and replaces tail recursion calls
var firstPass = {
enter: function (node, parent, scope, state) {
if (t.isReturnStatement(node)) {
this.skip();
return state.subTransform(node.argument);
} else if (t.isTryStatement(parent)) {
if (node === parent.block) {
this.skip();
} else if (parent.finalizer && node !== parent.finalizer) {
this.skip();
}
} else if (t.isFunction(node)) {
this.skip();
} else if (t.isVariableDeclaration(node)) {
this.skip();
state.vars.push(node);
}
}
};
// hoists up function declarations, replaces `this` and `arguments` and marks
// them as needed
var secondPass = {
enter: function (node, parent, scope, state) {
if (t.isThisExpression(node)) {
state.needsThis = true;
return state.getThisId();
} else if (t.isReferencedIdentifier(node, parent, { name: "arguments" })) {
state.needsArguments = true;
return state.getArgumentsId();
} else if (t.isFunction(node)) {
this.skip();
if (t.isFunctionDeclaration(node)) {
node = t.variableDeclaration("var", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
node._blockHoist = 2;
return node;
}
}
}
};
// optimizes recursion by removing `this` and `arguments` if they aren't used
var thirdPass = {
enter: function (node, parent, scope, state) {
if (!t.isExpressionStatement(node)) return;
var expr = node.expression;
if (!t.isAssignmentExpression(expr)) return;
if (!state.needsThis && expr.left === state.getThisId()) {
this.remove();
} else if (!state.needsArguments && expr.left === state.getArgumentsId() && t.isArrayExpression(expr.right)) {
return map(expr.right.elements, function (elem) {
return t.expressionStatement(elem);
});
}
}
};
exports.Function = function (node, parent, scope, file) {
var tailCall = new TailCallTransformer(node, scope, file);
tailCall.run();
};

View File

@@ -11,6 +11,7 @@ module.exports = {
"playground.memoizationOperator": require("./playground/memoization-operator"),
"playground.objectGetterMemoization": require("./playground/object-getter-memoization"),
reactCompat: require("./other/react-compat"),
react: require("./other/react"),
_modules: require("./internal/modules"),
@@ -27,9 +28,9 @@ module.exports = {
asyncToGenerator: require("./other/async-to-generator"),
bluebirdCoroutines: require("./other/bluebird-coroutines"),
"es6.objectSuper": require("./es6/object-super"),
"es7.objectRestSpread": require("./es7/object-rest-spread"),
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
"es6.spread": require("./es6/spread"),
"es6.templateLiterals": require("./es6/template-literals"),
"es5.properties.mutators": require("./es5/properties.mutators"),
@@ -45,6 +46,18 @@ module.exports = {
"es6.constants": require("./es6/constants"),
// needs to be before `es6.parameters.default` as default parameters will destroy the rest param
"es6.parameters.rest": require("./es6/parameters.rest"),
// needs to be after `es6.parameters.rest` as we use `toArray` and avoid turning an already known array into one
"es6.spread": require("./es6/spread"),
// needs to be before `es6.blockScoping` as default parameters have a TDZ
"es6.parameters.default": require("./es6/parameters.default"),
// needs to be before `es6.blockScoping` as let variables may be produced
"es6.destructuring": require("./es6/destructuring"),
// needs to be before `_aliasFunction` due to block scopes sometimes being wrapped in a
// closure
"es6.blockScoping": require("./es6/block-scoping"),
@@ -52,10 +65,9 @@ module.exports = {
// needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks
"es6.blockScopingTDZ": require("./es6/block-scoping-tdz"),
"es6.parameters.default": require("./es6/parameters.default"),
"es6.parameters.rest": require("./es6/parameters.rest"),
"es6.destructuring": require("./es6/destructuring"),
// needs to be after `es6.parameters.*` and `es6.blockScoping` due to needing pure
// identifiers in parameters and variable declarators
"es6.tailCall": require("./es6/tail-call"),
regenerator: require("./other/regenerator"),
@@ -85,5 +97,7 @@ module.exports = {
"minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsoleCalls": require("./minification/remove-console-calls"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
"minification.renameLocalVariables": require("./minification/rename-local-variables")
"minification.renameLocalVariables": require("./minification/rename-local-variables"),
_cleanUp: require("./internal/cleanup")
};

View File

@@ -0,0 +1,5 @@
exports.SequenceExpression = function (node) {
if (node.expressions.length === 1) {
return node.expressions[0];
}
};

View File

@@ -6,8 +6,12 @@ var isConsole = t.buildMatchMemberExpression("console", true);
exports.optional = true;
exports.CallExpression = function (node) {
exports.CallExpression = function (node, parent) {
if (isConsole(node.callee)) {
this.remove();
if (t.isExpressionStatement(parent)) {
this.parentPath.remove();
} else {
this.remove();
}
}
};

View File

@@ -2,10 +2,8 @@
exports.optional = true;
exports.Scope = function () {
// todo: get all binding identifiers, generate compact names
// that wont collide and then call the remap identifier helper
// this transformer **has** to be ran last as it will absolutley
// destroy the scope tree
exports.Scopable = function () {
//for (var name in scope.bindings) {
// scope.rename(name, scope.generateUidIdentifier("a").name);
//}
};

View File

@@ -0,0 +1,29 @@
"use strict";
var react = require("../../helpers/react");
var t = require("../../../types");
exports.manipulateOptions = function (opts) {
opts.blacklist.push("react");
};
exports.optional = true;
require("../../helpers/build-react-transformer")(exports, {
pre: function (state) {
state.callee = state.tagExpr;
},
post: function (state) {
if (react.isCompatTag(state.tagName)) {
state.call = t.callExpression(
t.memberExpression(
t.memberExpression(t.identifier("React"), t.identifier("DOM")),
state.tagExpr,
t.isLiteral(state.tagExpr)
),
state.args
);
}
}
});

View File

@@ -1,291 +1,20 @@
"use strict";
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
var react = require("../../helpers/react");
var t = require("../../../types");
// jsx
var isString = require("lodash/lang/isString");
var esutils = require("esutils");
var react = require("../../helpers/react");
var t = require("../../../types");
exports.check = function (node) {
if (t.isJSX(node)) return true;
if (react.isCreateClass(node)) return true;
return false;
};
exports.JSXIdentifier = function (node, parent) {
if (node.name === "this" && t.isReferenced(node, parent)) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return t.literal(node.name);
}
};
exports.JSXNamespacedName = function (node, parent, scope, file) {
throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
};
exports.JSXMemberExpression = {
exit: function (node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.JSXExpressionContainer = function (node) {
return node.expression;
};
exports.JSXAttribute = {
exit: function (node) {
var value = node.value || t.literal(true);
return t.inherits(t.property("init", node.name, value), node);
}
};
var isCompatTag = function (tagName) {
return /^[a-z]|\-/.test(tagName);
};
exports.JSXOpeningElement = {
exit: function (node, parent, scope, file) {
var reactCompat = file.opts.reactCompat;
var tagExpr = node.name;
var args = [];
var tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
if (!reactCompat) {
if (tagName && isCompatTag(tagName)) {
args.push(t.literal(tagName));
} else {
args.push(tagExpr);
}
}
var attribs = node.attributes;
if (attribs.length) {
attribs = buildJSXOpeningElementAttributes(attribs, file);
require("../../helpers/build-react-transformer")(exports, {
pre: function (state) {
var tagName = state.tagName;
var args = state.args;
if (react.isCompatTag(tagName)) {
args.push(t.literal(tagName));
} else {
attribs = t.literal(null);
args.push(state.tagExpr);
}
},
args.push(attribs);
if (reactCompat) {
if (tagName && isCompatTag(tagName)) {
return t.callExpression(
t.memberExpression(
t.memberExpression(t.identifier("React"), t.identifier("DOM")),
tagExpr,
t.isLiteral(tagExpr)
),
args
);
}
} else {
tagExpr = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
}
return t.callExpression(tagExpr, args);
post: function (state) {
state.callee = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
}
};
/**
* 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 buildJSXOpeningElementAttributes = function (attribs, file) {
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.isJSXSpreadAttribute(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(
file.addHelper("extends"),
objs
);
}
return attribs;
};
exports.JSXElement = {
exit: function (node) {
var callExpr = node.openingElement;
for (var i = 0; i < node.children.length; i++) {
var child = node.children[i];
if (t.isLiteral(child) && typeof child.value === "string") {
cleanJSXElementLiteralChild(child, callExpr.arguments);
continue;
} else if (t.isJSXEmptyExpression(child)) {
continue;
}
callExpr.arguments.push(child);
}
callExpr.arguments = flatten(callExpr.arguments);
if (callExpr.arguments.length >= 3) {
callExpr._prettyCall = true;
}
return t.inherits(callExpr, node);
}
};
var isStringLiteral = function (node) {
return t.isLiteral(node) && isString(node.value);
};
var flatten = function (args) {
var flattened = [];
var last;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (isStringLiteral(arg) && isStringLiteral(last)) {
last.value += arg.value;
} else {
last = arg;
flattened.push(arg);
}
}
return flattened;
};
var cleanJSXElementLiteralChild = function (child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
var lastNonEmptyLine = 0;
var i;
for (i = 0; i < lines.length; i++) {
if (lines[i].match(/[^ \t]/)) {
lastNonEmptyLine = i;
}
}
for (i = 0; i < lines.length; i++) {
var line = lines[i];
var isFirstLine = i === 0;
var isLastLine = i === lines.length - 1;
var isLastNonEmptyLine = i === lastNonEmptyLine;
// 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) {
if (!isLastNonEmptyLine) {
trimmedLine += " ";
}
args.push(t.literal(trimmedLine));
}
}
};
// display names
var addDisplayName = function (id, call) {
var props = call.arguments[0].properties;
var safe = true;
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (t.isIdentifier(prop.key, { name: "displayName" })) {
safe = false;
break;
}
}
if (safe) {
props.unshift(t.property("init", t.identifier("displayName"), t.literal(id)));
}
};
exports.ExportDeclaration = function (node, parent, scope, file) {
if (node.default && react.isCreateClass(node.declaration)) {
addDisplayName(file.opts.basename, node.declaration);
}
};
exports.AssignmentExpression =
exports.Property =
exports.VariableDeclarator = function (node) {
var left, right;
if (t.isAssignmentExpression(node)) {
left = node.left;
right = node.right;
} else if (t.isProperty(node)) {
left = node.key;
right = node.value;
} else if (t.isVariableDeclarator(node)) {
left = node.id;
right = node.init;
}
if (t.isMemberExpression(left)) {
left = left.property;
}
if (t.isIdentifier(left) && react.isCreateClass(right)) {
addDisplayName(left.name, right);
}
};
});

View File

@@ -4,7 +4,7 @@ var util = require("../../../util");
var core = require("core-js/library");
var t = require("../../../types");
var has = require("lodash/object/has");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var coreHas = function (node) {
return node.name !== "_" && has(core, node.name);
@@ -30,11 +30,11 @@ var astVisitor = {
if (!t.isReferenced(obj, node)) return;
if (!node.computed && coreHas(obj) && has(core[obj.name], prop.name) && !scope.getBinding(obj.name)) {
if (!node.computed && coreHas(obj) && has(core[obj.name], prop.name) && !scope.getBindingIdentifier(obj.name)) {
this.skip();
return t.prependToMemberExpression(node, file.get("coreIdentifier"));
}
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && contains(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBinding(node.name)) {
} else if (t.isReferencedIdentifier(node, parent) && !t.isMemberExpression(parent) && includes(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBindingIdentifier(node.name)) {
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
return t.memberExpression(file.get("coreIdentifier"), node);
} else if (t.isCallExpression(node)) {

View File

@@ -1,7 +1,8 @@
"use strict";
var build = require("../../helpers/build-conditional-assignment-operator-transformer");
var t = require("../../../types");
var messages = require("../../../messages");
var build = require("../../helpers/build-conditional-assignment-operator-transformer");
var t = require("../../../types");
exports.playground = true;
@@ -11,7 +12,7 @@ build(exports, {
if (is) {
var left = node.left;
if (!t.isMemberExpression(left) && !t.isIdentifier(left)) {
throw file.errorWithNode(left, "Expected type MemeberExpression or Identifier");
throw file.errorWithNode(left, messages.get("expectedMemberExpressionOrIdentifier"));
}
return true;
}

View File

@@ -2,7 +2,7 @@
var t = require("../../../types");
exports.BlockStatement = function (node, parent) {
exports.BlockStatement = function (node, parent, scope, file) {
if ((t.isFunction(parent) && parent.body === node) || t.isExportDeclaration(parent)) {
return;
}
@@ -22,5 +22,7 @@ exports.BlockStatement = function (node, parent) {
func.id = null;
node.body[i] = declar;
file.checkNode(declar);
}
};

View File

@@ -1,12 +1,15 @@
"use strict";
var t = require("../../../types");
var messages = require("../../../messages");
var t = require("../../../types");
exports.check = t.isFor;
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, scope, file) {
var left = node.left;
if (t.isVariableDeclaration(left)) {
var declar = left.declarations[0];
if (declar.init) throw file.errorWithNode(declar, "No assignments allowed in for-in/of head");
if (declar.init) throw file.errorWithNode(declar, messages.get("noAssignmentsInForHead"));
}
};

View File

@@ -1,8 +1,14 @@
"use strict";
var messages = require("../../../messages");
exports.check = function (node) {
return node.kind === "set";
};
exports.MethodDefinition =
exports.Property = function (node, parent, scope, file) {
if (node.kind === "set" && node.value.params.length !== 1) {
throw file.errorWithNode(node.value, "Setters must have only one parameter");
throw file.errorWithNode(node.value, messages.get("settersInvalidParamLength"));
}
};

View File

@@ -1,6 +1,7 @@
"use strict";
var levenshtein = require("../../../helpers/levenshtein");
var messages = require("../../../messages");
var t = require("../../../types");
exports.optional = true;
@@ -9,8 +10,6 @@ exports.Identifier = function (node, parent, scope, file) {
if (!t.isReferenced(node, parent)) return;
if (scope.hasBinding(node.name)) return;
var msg = "Reference to undeclared variable";
// get the closest declaration to offer as a suggestion
// the variable name may have just been mistyped
@@ -28,8 +27,11 @@ exports.Identifier = function (node, parent, scope, file) {
shortest = distance;
}
var msg;
if (closest) {
msg += " - Did you mean " + closest + "?";
msg = messages.get("undeclaredVariableSuggestion", node.name, closest);
} else {
msg = messages.get("undeclaredVariable", node.name);
}
//

View File

@@ -1,49 +1,25 @@
"use strict";
/* jshint maxparams:7 */
module.exports = TraversalContext;
var TraversalPath = require("./path");
var flatten = require("lodash/array/flatten");
var compact = require("lodash/array/compact");
function TraversalContext(scope, opts, state) {
function TraversalContext(scope, opts, state, parentPath) {
this.shouldFlatten = false;
this.parentPath = parentPath;
this.scope = scope;
this.state = state;
this.opts = opts;
this.reset();
}
TraversalContext.prototype.flatten = function () {
this.shouldFlatten = true;
};
TraversalContext.prototype.remove = function () {
this.shouldRemove = true;
this.shouldSkip = true;
};
TraversalContext.prototype.skip = function () {
this.shouldSkip = true;
};
TraversalContext.prototype.stop = function () {
this.shouldStop = true;
this.shouldSkip = true;
};
TraversalContext.prototype.reset = function () {
this.shouldRemove = false;
this.shouldSkip = false;
this.shouldStop = false;
};
TraversalContext.prototype.visitNode = function (node, obj, key) {
this.reset();
var iteration = new TraversalPath(this, node, obj, key);
return iteration.visit();
};

View File

@@ -3,7 +3,7 @@
module.exports = traverse;
var TraversalContext = require("./context");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var t = require("../types");
function traverse(parent, opts, scope, state) {
@@ -29,11 +29,11 @@ function traverse(parent, opts, scope, state) {
}
}
traverse.node = function (node, opts, scope, state) {
traverse.node = function (node, opts, scope, state, parentPath) {
var keys = t.VISITOR_KEYS[node.type];
if (!keys) return;
var context = new TraversalContext(scope, opts, state);
var context = new TraversalContext(scope, opts, state, parentPath);
for (var i = 0; i < keys.length; i++) {
if (context.visit(node, keys[i])) {
return;
@@ -102,7 +102,7 @@ function hasBlacklistedType(node, parent, scope, state) {
traverse.hasType = function (tree, scope, type, blacklistTypes) {
// the node we're searching in is blacklisted
if (contains(blacklistTypes, tree.type)) return false;
if (includes(blacklistTypes, tree.type)) return false;
// the type we're looking for is the same as the passed node
if (tree.type === type) return true;

View File

@@ -5,7 +5,7 @@ module.exports = TraversalPath;
/* jshint maxparams:7 */
var traverse = require("./index");
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var Scope = require("./scope");
var t = require("../types");
@@ -14,16 +14,17 @@ function TraversalPath(context, parent, obj, key) {
this.shouldSkip = false;
this.shouldStop = false;
this.context = context;
this.state = this.context.state;
this.opts = this.context.opts;
this.parentPath = context.parentPath;
this.context = context;
this.state = this.context.state;
this.opts = this.context.opts;
this.key = key;
this.obj = obj;
this.parent = parent;
this.scope = TraversalPath.getScope(this.getNode(), parent, context.scope);
this.state = context.state;
this.parent = parent;
this.scope = TraversalPath.getScope(this.getNode(), parent, context.scope);
this.state = context.state;
}
TraversalPath.prototype.remove = function () {
@@ -48,7 +49,7 @@ TraversalPath.getScope = function (node, parent, scope) {
var ourScope = scope;
// we're entering a new scope so let's construct it!
if (t.isScope(node)) {
if (t.isScope(node, parent)) {
ourScope = new Scope(node, parent, scope);
}
@@ -70,7 +71,7 @@ TraversalPath.prototype.getNode = function () {
return this.obj[this.key];
};
TraversalPath.prototype.replaceNode = function (replacement, scope) {
TraversalPath.prototype.replaceNode = function (replacement) {
var isArray = Array.isArray(replacement);
// inherit comments from original node to the first replacement node
@@ -85,17 +86,17 @@ TraversalPath.prototype.replaceNode = function (replacement, scope) {
if (file) {
if (isArray) {
for (var i = 0; i < replacement.length; i++) {
file.checkNode(replacement[i], scope);
file.checkNode(replacement[i], this.scope);
}
} else {
file.checkNode(replacement, scope);
file.checkNode(replacement, this.scope);
}
}
// we're replacing a statement or block node with an array of statements so we better
// ensure that it's a block
if (isArray) {
if (contains(t.STATEMENT_OR_BLOCK_KEYS, this.key) && !t.isBlockStatement(this.obj)) {
if (includes(t.STATEMENT_OR_BLOCK_KEYS, this.key) && !t.isBlockStatement(this.obj)) {
t.ensureBlock(this.obj, this.key);
}
@@ -144,10 +145,10 @@ TraversalPath.prototype.visit = function () {
// traverse over these replacement nodes we purposely don't call exitNode
// as the original node has been destroyed
for (var i = 0; i < node.length; i++) {
traverse.node(node[i], opts, this.scope, this.state);
traverse.node(node[i], opts, this.scope, this.state, this);
}
} else {
traverse.node(node, opts, this.scope, this.state);
traverse.node(node, opts, this.scope, this.state, this);
this.call("exit");
}

View File

@@ -2,15 +2,15 @@
module.exports = Scope;
var contains = require("lodash/collection/contains");
var includes = require("lodash/collection/includes");
var traverse = require("./index");
var defaults = require("lodash/object/defaults");
var messages = require("../messages");
var globals = require("globals");
var flatten = require("lodash/array/flatten");
var extend = require("lodash/object/extend");
var object = require("../helpers/object");
var each = require("lodash/collection/each");
var has = require("lodash/object/has");
var t = require("../types");
/**
@@ -134,12 +134,50 @@ Scope.prototype.generateTempBasedOnNode = function (node) {
return id;
};
Scope.prototype.checkBlockScopedCollisions = function (key, id) {
if (this.declarationKinds["let"][key] || this.declarationKinds["const"][key]) {
throw this.file.errorWithNode(id, "Duplicate declaration " + key, TypeError);
Scope.prototype.checkBlockScopedCollisions = function (kind, name, id) {
var local = this.getOwnBindingInfo(name);
if (!local) return;
if (kind === "param") return;
if (kind === "hoisted" && local.kind === "let") return;
if (local.kind === "let" || local.kind === "const") {
throw this.file.errorWithNode(id, messages.get("scopeDuplicateDeclaration", name), TypeError);
}
};
Scope.prototype.rename = function (oldName, newName) {
newName = newName || this.generateUidIdentifier(oldName).name;
var info = this.getBindingInfo(oldName);
if (!info) return;
var binding = info.identifier;
var scope = info.scope;
scope.traverse(scope.block, {
enter: function (node, parent, scope) {
if (t.isReferencedIdentifier(node, parent) && node.name === oldName) {
node.name = newName;
} else if (t.isDeclaration(node)) {
var ids = t.getBindingIdentifiers(node);
for (var name in ids) {
if (name === oldName) ids[name].name = newName;
}
} else if (t.isScope(node, parent)) {
if (!scope.bindingIdentifierEquals(oldName, binding)) {
this.skip();
}
}
}
});
this.clearOwnBinding(oldName);
scope.bindings[newName] = info;
binding.name = newName;
};
Scope.prototype.inferType = function (node) {
var target;
@@ -147,10 +185,6 @@ Scope.prototype.inferType = function (node) {
target = node.init;
}
if (t.isLiteral(target) || t.isArrayExpression(target) || t.isObjectExpression(target)) {
// todo: possibly call some helper that will resolve these to a flow type annotation
}
if (t.isCallExpression(target)) {
// todo: resolve this to a return type
}
@@ -160,11 +194,30 @@ Scope.prototype.inferType = function (node) {
}
if (t.isIdentifier(target)) {
return this.getType(target.name);
// todo
}
};
Scope.prototype.registerType = function (key, id, node) {
Scope.prototype.isTypeGeneric = function (name, genericName) {
var info = this.getBindingInfo(name);
if (!info) return false;
var type = info.typeAnnotation;
return t.isGenericTypeAnnotation(type) && t.isIdentifier(type.id, { name: genericName });
};
Scope.prototype.assignTypeGeneric = function (name, type) {
this.assignType(name, t.genericTypeAnnotation(t.identifier(type)));
};
Scope.prototype.assignType = function (name, type) {
var info = this.getBindingInfo(name);
if (!info) return;
info.identifier.typeAnnotation = info.typeAnnotation = type;
};
Scope.prototype.getTypeAnnotation = function (key, id, node) {
var type;
if (id.typeAnnotation) {
@@ -177,38 +230,88 @@ Scope.prototype.registerType = function (key, id, node) {
if (type) {
if (t.isTypeAnnotation(type)) type = type.typeAnnotation;
this.types[key] = type;
return type;
}
};
Scope.prototype.register = function (node, reference, kind) {
if (t.isVariableDeclaration(node)) {
return this.registerVariableDeclaration(node);
Scope.prototype.toArray = function (node, i) {
var file = this.file;
if (t.isIdentifier(node) && this.isTypeGeneric(node.name, "Array")) {
return node;
}
if (t.isArrayExpression(node)) {
return node;
}
if (t.isIdentifier(node, { name: "arguments" })) {
return t.callExpression(t.memberExpression(file.addHelper("slice"), t.identifier("call")), [node]);
}
var helperName = "to-array";
var args = [node];
if (i === true) {
helperName = "to-consumable-array";
} else if (i) {
args.push(t.literal(i));
helperName = "sliced-to-array";
}
return t.callExpression(file.addHelper(helperName), args);
};
Scope.prototype.clearOwnBinding = function (name) {
delete this.bindings[name];
};
Scope.prototype.registerDeclaration = function (node) {
if (t.isFunctionDeclaration(node)) {
this.registerBinding("hoisted", node);
} else if (t.isVariableDeclaration(node)) {
for (var i = 0; i < node.declarations.length; i++) {
this.registerBinding(node.kind, node.declarations[i]);
}
} else if (t.isClassDeclaration(node)) {
this.registerBinding("let", node);
} else if (t.isImportDeclaration(node) || t.isExportDeclaration(node)) {
this.registerBinding("module", node);
} else {
this.registerBinding("unknown", node);
}
};
Scope.prototype.registerBindingReassignment = function (node) {
var ids = t.getBindingIdentifiers(node);
for (var name in ids) {
var info = this.getBindingInfo(name);
if (info) info.reassigned = true;
}
};
Scope.prototype.registerBinding = function (kind, node) {
if (!kind) throw new ReferenceError("no `kind`");
var ids = t.getBindingIdentifiers(node);
extend(this.references, ids);
for (var name in ids) {
var id = ids[name];
if (reference) return;
this.checkBlockScopedCollisions(kind, name, id);
for (var key in ids) {
var id = ids[key];
this.checkBlockScopedCollisions(key, id);
this.registerType(key, id, node);
this.bindings[key] = id;
this.bindings[name] = {
typeAnnotation: this.getTypeAnnotation(name, id, node),
reassigned: false,
identifier: id,
scope: this,
kind: kind
};
}
var kinds = this.declarationKinds[kind];
if (kinds) extend(kinds, ids);
};
Scope.prototype.registerVariableDeclaration = function (declar) {
var declars = declar.declarations;
for (var i = 0; i < declars.length; i++) {
this.register(declars[i], false, declar.kind);
this.registerBinding(declars[i], declar.kind);
}
};
@@ -217,7 +320,7 @@ var functionVariableVisitor = {
if (t.isFor(node)) {
each(t.FOR_INIT_KEYS, function (key) {
var declar = node[key];
if (t.isVar(declar)) state.scope.register(declar);
if (t.isVar(declar)) state.scope.registerBinding("var", declar);
});
}
@@ -235,30 +338,47 @@ var functionVariableVisitor = {
if (t.isExportDeclaration(node) && t.isDeclaration(node.declaration)) return;
// we've ran into a declaration!
if (t.isDeclaration(node)) state.scope.register(node);
if (t.isDeclaration(node)) state.scope.registerDeclaration(node);
}
};
Scope.prototype.addGlobal = function (node) {
this.globals[node.name] = node;
};
Scope.prototype.hasGlobal = function (name) {
var scope = this;
do {
if (scope.globals[name]) return true;
} while (scope = scope.parent);
return false;
};
var programReferenceVisitor = {
enter: function (node, parent, scope, state) {
if (t.isReferencedIdentifier(node, parent) && !scope.hasReference(node.name)) {
state.register(node, true);
if (t.isReferencedIdentifier(node, parent) && !scope.hasBinding(node.name)) {
state.addGlobal(node);
} else if (t.isLabeledStatement(node)) {
state.addGlobal(node);
} else if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
scope.registerBindingReassignment(node);
}
}
};
var blockVariableVisitor = {
enter: function (node, parent, scope, state) {
if (t.isBlockScoped(node)) {
state.register(node);
} else if (t.isScope(node)) {
if (t.isFunctionDeclaration(node) || t.isBlockScoped(node)) {
state.registerDeclaration(node);
} else if (t.isScope(node, parent)) {
this.skip();
}
}
};
Scope.prototype.crawl = function () {
var parent = this.parent;
var block = this.block;
var i;
@@ -271,34 +391,18 @@ Scope.prototype.crawl = function () {
}
info = block._scopeInfo = {
declarationKinds: {
"const": object(),
"var": object(),
"let": object()
},
references: object(),
bindings: object(),
types: object(),
bindings: object(),
globals: object()
};
extend(this, info);
//
if (parent && t.isBlockStatement(block)) {
if (t.isLoop(parent.block, { body: block }) ||
t.isFunction(parent.block, { body: block })) {
return;
}
}
// ForStatement - left, init
if (t.isLoop(block)) {
for (i = 0; i < t.FOR_INIT_KEYS.length; i++) {
var node = block[t.FOR_INIT_KEYS[i]];
if (t.isBlockScoped(node)) this.register(node, false, true);
if (t.isBlockScoped(node)) this.registerBinding("let", node);
}
if (t.isBlockStatement(block.body)) {
@@ -310,7 +414,7 @@ Scope.prototype.crawl = function () {
if (t.isFunctionExpression(block) && block.id) {
if (!t.isProperty(this.parentBlock, { method: true })) {
this.register(block.id);
this.registerBinding("var", block.id);
}
}
@@ -318,26 +422,27 @@ Scope.prototype.crawl = function () {
if (t.isFunction(block)) {
for (i = 0; i < block.params.length; i++) {
this.register(block.params[i]);
this.registerBinding("param", block.params[i]);
}
this.traverse(block.body, blockVariableVisitor, this);
}
// Program, BlockStatement, Function - let variables
if (t.isBlockStatement(block) || t.isProgram(block) || t.isFunction(block)) {
if (t.isBlockStatement(block) || t.isProgram(block)) {
this.traverse(block, blockVariableVisitor, this);
}
// CatchClause - param
if (t.isCatchClause(block)) {
this.register(block.param);
this.registerBinding("let", block.param);
}
// ComprehensionExpression - blocks
if (t.isComprehensionExpression(block)) {
this.register(block);
this.registerBinding("let", block);
}
// Program, Function - var variables
@@ -382,26 +487,6 @@ Scope.prototype.push = function (opts) {
}
};
/**
* Walk up the scope tree until we hit a `Function` and then
* push our `node` to it's references.
*
* @param {String} kind
* @param {Object} node
*/
Scope.prototype.addDeclarationToFunctionScope = function (kind, node) {
var scope = this.getFunctionParent();
var ids = t.getBindingIdentifiers(node);
extend(scope.bindings, ids);
extend(scope.references, ids);
// this ignores the duplicate declaration logic specified in `getInfo`
// but it doesn't really matter
extend(scope.declarationKinds[kind], ids);
};
/**
* Walk up the scope tree until we hit either a Function or reach the
* very top and hit Program.
@@ -440,72 +525,66 @@ Scope.prototype.getAllBindings = function () {
* @returns {Object}
*/
Scope.prototype.getAllDeclarationsOfKind = function (kind) {
Scope.prototype.getAllBindingsOfKind = function (kind) {
var ids = object();
var scope = this;
do {
defaults(ids, scope.declarationKinds[kind]);
for (var name in scope.bindings) {
var binding = scope.bindings[name];
if (binding.kind === kind) ids[name] = binding;
}
scope = scope.parent;
} while (scope);
return ids;
};
//
// misc
Scope.prototype.get = function (id, type) {
return id && (this.getOwn(id, type) || this.parentGet(id, type));
Scope.prototype.bindingIdentifierEquals = function (name, node) {
return this.getBindingIdentifier(name) === node;
};
Scope.prototype.getOwn = function (id, type) {
var refs = {
reference: this.references,
binding: this.bindings,
type: this.types
}[type];
return refs && has(refs, id) && refs[id];
// get
Scope.prototype.getBindingInfo = function (name) {
var scope = this;
do {
var binding = scope.getOwnBindingInfo(name);
if (binding) return binding;
} while (scope = scope.parent);
};
Scope.prototype.parentGet = function (id, type) {
return this.parent && this.parent.get(id, type);
Scope.prototype.getOwnBindingInfo = function (name) {
return this.bindings[name];
};
Scope.prototype.has = function (id, type) {
if (!id) return false;
if (this.hasOwn(id, type)) return true;
if (this.parentHas(id, type)) return true;
if (contains(Scope.defaultDeclarations, id)) return true;
Scope.prototype.getBindingIdentifier = function (name) {
var info = this.getBindingInfo(name);
return info && info.identifier;
};
Scope.prototype.getOwnBindingIdentifier = function (name) {
var binding = this.bindings[name];
return binding && binding.identifier;
};
// has
Scope.prototype.hasOwnBinding = function (name) {
return !!this.getOwnBindingInfo(name);
};
Scope.prototype.hasBinding = function (name) {
if (!name) return false;
if (this.hasOwnBinding(name)) return true;
if (this.parentHasBinding(name)) return true;
if (includes(Scope.defaultDeclarations, name)) return true;
return false;
};
Scope.prototype.hasOwn = function (id, type) {
return !!this.getOwn(id, type);
Scope.prototype.parentHasBinding = function (name) {
return this.parent && this.parent.hasBinding(name);
};
Scope.prototype.parentHas = function (id, type) {
return this.parent && this.parent.has(id, type);
};
each({
reference: "Reference",
binding: "Binding",
type: "Type"
}, function (title, type) {
Scope.prototype[type + "Equals"] = function (id, node) {
return this["get" + title](id) === node;
};
each([
"get",
"has",
"getOwn",
"hasOwn",
"parentGet",
"parentHas",
], function (methodName) {
Scope.prototype[methodName + title] = function (id) {
return this[methodName](id, type);
};
});
});

View File

@@ -3,13 +3,13 @@
"BreakStatement": ["Statement"],
"ContinueStatement": ["Statement"],
"DebuggerStatement": ["Statement"],
"DoWhileStatement": ["Statement", "Loop", "While", "Scope"],
"DoWhileStatement": ["Statement", "Loop", "While", "Scopable"],
"IfStatement": ["Statement"],
"ReturnStatement": ["Statement"],
"SwitchStatement": ["Statement"],
"ThrowStatement": ["Statement"],
"TryStatement": ["Statement"],
"WhileStatement": ["Statement", "Loop", "While", "Scope"],
"WhileStatement": ["Statement", "Loop", "While", "Scopable"],
"WithStatement": ["Statement"],
"EmptyStatement": ["Statement"],
"LabeledStatement": ["Statement"],
@@ -18,13 +18,13 @@
"ImportDeclaration": ["Statement", "Declaration"],
"PrivateDeclaration": ["Statement", "Declaration"],
"ArrowFunctionExpression": ["Scope", "Function", "Expression"],
"FunctionDeclaration": ["Statement", "Declaration", "Scope", "Function"],
"FunctionExpression": ["Scope", "Function", "Expression"],
"ArrowFunctionExpression": ["Scopable", "Function", "Expression"],
"FunctionDeclaration": ["Statement", "Declaration", "Scopable", "Function"],
"FunctionExpression": ["Scopable", "Function", "Expression"],
"BlockStatement": ["Statement", "Scope"],
"Program": ["Scope"],
"CatchClause": ["Scope"],
"BlockStatement": ["Statement", "Scopable"],
"Program": ["Scopable"],
"CatchClause": ["Scopable"],
"LogicalExpression": ["Binary", "Expression"],
"BinaryExpression": ["Binary", "Expression"],
@@ -36,9 +36,9 @@
"ClassDeclaration": ["Statement", "Declaration", "Class"],
"ClassExpression": ["Class", "Expression"],
"ForOfStatement": ["Statement", "For", "Scope", "Loop"],
"ForInStatement": ["Statement", "For", "Scope", "Loop"],
"ForStatement": ["Statement", "For", "Scope", "Loop"],
"ForOfStatement": ["Statement", "For", "Scopable", "Loop"],
"ForInStatement": ["Statement", "For", "Scopable", "Loop"],
"ForStatement": ["Statement", "For", "Scopable", "Loop"],
"ObjectPattern": ["Pattern"],
"ArrayPattern": ["Pattern"],
@@ -53,7 +53,7 @@
"BindFunctionExpression": ["Expression"],
"BindMemberExpression": ["Expression"],
"CallExpression": ["Expression"],
"ComprehensionExpression": ["Expression", "Scope"],
"ComprehensionExpression": ["Expression", "Scopable"],
"ConditionalExpression": ["Expression"],
"Identifier": ["Expression"],
"Literal": ["Expression"],

View File

@@ -1,33 +1,168 @@
{
"ArrayExpression": ["elements"],
"ArrowFunctionExpression": ["params", "body"],
"AssignmentExpression": ["operator", "left", "right"],
"BinaryExpression": ["operator", "left", "right"],
"BlockStatement": ["body"],
"CallExpression": ["callee", "arguments"],
"ConditionalExpression": ["test", "consequent", "alternate"],
"ExpressionStatement": ["expression"],
"File": ["program", "comments", "tokens"],
"FunctionExpression": ["id", "params", "body", "generator"],
"FunctionDeclaration": ["id", "params", "body", "generator"],
"Identifier": ["name"],
"IfStatement": ["test", "consequent", "alternate"],
"ImportDeclaration": ["specifiers", "source"],
"ImportSpecifier": ["id", "name"],
"Literal": ["value"],
"LogicalExpression": ["operator", "left", "right"],
"MemberExpression": ["object", "property", "computed"],
"MethodDefinition": ["key", "value", "computed", "kind"],
"NewExpression": ["callee", "arguments"],
"ObjectExpression": ["properties"],
"Program": ["body"],
"Property": ["kind", "key", "value", "computed"],
"ReturnStatement": ["argument"],
"SequenceExpression": ["expressions"],
"ThrowExpression": ["argument"],
"UnaryExpression": ["operator", "argument", "prefix"],
"VariableDeclaration": ["kind", "declarations"],
"VariableDeclarator": ["id", "init"],
"WithStatement": ["object", "body"],
"YieldExpression": ["argument", "delegate"]
"ArrayExpression": {
"elements": null
},
"ArrowFunctionExpression": {
"params": null,
"body": null
},
"AssignmentExpression": {
"operator": null,
"left": null,
"right": null
},
"BinaryExpression": {
"operator": null,
"left": null,
"right": null
},
"BlockStatement": {
"body": null
},
"CallExpression": {
"callee": null,
"arguments": null
},
"ConditionalExpression": {
"test": null,
"consequent": null,
"alternate": null
},
"ExpressionStatement": {
"expression": null
},
"File": {
"program": null,
"comments": null,
"tokens": null
},
"FunctionExpression": {
"id": null,
"params": null,
"body": null,
"generator": false
},
"FunctionDeclaration": {
"id": null,
"params": null,
"body": null,
"generator": false
},
"GenericTypeAnnotation": {
"id": null,
"typeParameters": null
},
"Identifier": {
"name": null
},
"IfStatement": {
"test": null,
"consequent": null,
"alternate": null
},
"ImportDeclaration": {
"specifiers": null,
"source": null
},
"ImportSpecifier": {
"id": null,
"name": null
},
"Literal": {
"value": null
},
"LogicalExpression": {
"operator": null,
"left": null,
"right": null
},
"MemberExpression": {
"object": null,
"property": null,
"computed": false
},
"MethodDefinition": {
"key": null,
"value": null,
"computed": false,
"static": false,
"kind": null
},
"NewExpression": {
"callee": null,
"arguments": null
},
"ObjectExpression": {
"properties": null
},
"Program": {
"body": null
},
"Property": {
"kind": null,
"key": null,
"value": null,
"computed": false
},
"ReturnStatement": {
"argument": null
},
"SequenceExpression": {
"expressions": null
},
"ThrowExpression": {
"argument": null
},
"UnaryExpression": {
"operator": null,
"argument": null,
"prefix": null
},
"VariableDeclaration": {
"kind": null,
"declarations": null
},
"VariableDeclarator": {
"id": null,
"init": null
},
"WithStatement": {
"object": null,
"body": null
},
"YieldExpression": {
"argument": null,
"delegate": null
}
}

View File

@@ -1,12 +1,10 @@
"use strict";
var toFastProperties = require("../helpers/to-fast-properties");
var defaults = require("lodash/object/defaults");
var isString = require("lodash/lang/isString");
var compact = require("lodash/array/compact");
var esutils = require("esutils");
var object = require("../helpers/object");
var Node = require("./node");
var each = require("lodash/collection/each");
var uniq = require("lodash/array/uniq");
@@ -72,9 +70,9 @@ each(t.FLIPPED_ALIAS_KEYS, function (types, type) {
*/
t.is = function (type, node, opts, skipAliasCheck) {
if (!node) return;
if (!node) return false;
var typeMatches = (type === node.type);
var typeMatches = type === node.type;
if (!typeMatches && !skipAliasCheck) {
var aliases = t.FLIPPED_ALIAS_KEYS[type];
@@ -97,17 +95,32 @@ t.is = function (type, node, opts, skipAliasCheck) {
//
t.BUILDER_KEYS = defaults(require("./builder-keys"), t.VISITOR_KEYS);
t.BUILDER_KEYS = require("./builder-keys");
each(t.VISITOR_KEYS, function (keys, type) {
if (t.BUILDER_KEYS[type]) return;
var defs = {};
each(keys, function (key) {
defs[key] = null;
});
t.BUILDER_KEYS[type] = defs;
});
each(t.BUILDER_KEYS, function (keys, type) {
t[type[0].toLowerCase() + type.slice(1)] = function () {
var args = arguments;
var node = new Node;
var node = {};
node.start = null;
node.type = type;
each(keys, function (key, i) {
node[key] = args[i];
});
var i = 0;
for (var key in keys) {
var arg = arguments[i++];
if (arg === undefined) arg = keys[key];
node[key] = arg;
}
return node;
};
});
@@ -305,7 +318,7 @@ t.isReferenced = function (node, parent) {
// no: [NODE = foo] = [];
// yes: [foo = NODE] = [];
if (t.isAssignmentPattern(parent)) {
return parent.right !== node;
return parent.right === node;
}
// no: [NODE] = [];
@@ -335,13 +348,13 @@ t.isReferenced = function (node, parent) {
/**
* Check if the input `node` is an `Identifier` and `isReferenced`.
*
* @param {Object} node
* @param {Object} parent
* @param {Node} node
* @parma {Node} parent
* @returns {Boolean}
*/
t.isReferencedIdentifier = function (node, parent) {
return t.isIdentifier(node) && t.isReferenced(node, parent);
t.isReferencedIdentifier = function (node, parent, opts) {
return t.isIdentifier(node, opts) && t.isReferenced(node, parent);
};
/**
@@ -395,7 +408,7 @@ t.toIdentifier = function (name) {
t.ensureBlock = function (node, key) {
key = key || "body";
node[key] = t.toBlock(node[key], node);
return node[key] = t.toBlock(node[key], node);
};
/**
@@ -423,6 +436,10 @@ t.buildMatchMemberExpression = function (match, allowPartial) {
while (search.length) {
var node = search.shift();
if (allowPartial && i === parts.length) {
return true;
}
if (t.isIdentifier(node)) {
// this part doesn't match
if (parts[i] !== node.name) return false;
@@ -445,11 +462,7 @@ t.buildMatchMemberExpression = function (match, allowPartial) {
// too many parts
if (++i > parts.length) {
if (allowPartial) {
return true;
} else {
return false;
}
return false;
}
}
@@ -600,10 +613,11 @@ t.getBindingIdentifiers.keys = {
VariableDeclarator: ["id"],
FunctionDeclaration: ["id"],
ClassDeclaration: ["id"],
MemeberExpression: ["object"],
MemberExpression: ["object"],
SpreadElement: ["argument"],
RestElement: ["argument"],
UpdateExpression: ["argument"],
SpreadProperty: ["argument"],
Property: ["value"],
ComprehensionBlock: ["left"],
AssignmentPattern: ["left"],
@@ -690,10 +704,12 @@ t.inheritsComments = function (child, parent) {
*/
t.inherits = function (child, parent) {
child.range = parent.range;
child.start = parent.start;
child.loc = parent.loc;
child.end = parent.end;
child._declarations = parent._declarations;
child._scopeInfo = parent._scopeInfo;
child.range = parent.range;
child.start = parent.start;
child.loc = parent.loc;
child.end = parent.end;
t.inheritsComments(child, parent);
return child;
};
@@ -763,5 +779,27 @@ t.isSpecifierDefault = function (specifier) {
return specifier.default || t.isIdentifier(specifier.id) && specifier.id.name === "default";
};
/**
* Description
*
* @param {Node} node
* @param {Node} parent
* @returns {Boolean}
*/
t.isScope = function (node, parent) {
if (t.isBlockStatement(node)) {
if (t.isLoop(parent.block, { body: node })) {
return false;
}
if (t.isFunction(parent.block, { body: node })) {
return false;
}
}
return t.isScopable(node);
};
toFastProperties(t);
toFastProperties(t.VISITOR_KEYS);

View File

@@ -1,12 +0,0 @@
"use strict";
module.exports = Node;
var acorn = require("acorn-6to5");
var oldNode = acorn.Node;
acorn.Node = Node;
function Node() {
oldNode.apply(this);
}

View File

@@ -73,7 +73,7 @@
"AnyTypeAnnotation": [],
"ArrayTypeAnnotation": [],
"BooleanTypeAnnotation": [],
"ClassProperty": ["key"],
"ClassProperty": ["key", "value"],
"DeclareClass": [],
"DeclareFunction": [],
"DeclareModule": [],

View File

@@ -30,6 +30,10 @@ exports.canCompile = function (filename, altExts) {
exports.canCompile.EXTENSIONS = [".js", ".jsx", ".es6", ".es"];
exports.normalisePathSeparator = function (filename) {
return filename.replace(/\\/g, "/");
};
exports.isInteger = function (i) {
return isNumber(i) && i % 1 === 0;
};
@@ -80,6 +84,9 @@ exports.sourceMapToComment = function (map) {
var templateVisitor = {
enter: function (node, parent, scope, nodes) {
if (t.isExpressionStatement(node)) {
node = node.expression;
}
if (t.isIdentifier(node) && has(nodes, node.name)) {
return nodes[node.name];
}

View File

@@ -1,7 +1,7 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "3.4.0",
"version": "3.6.0",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://6to5.org/",
"repository": "6to5/6to5",
@@ -33,12 +33,12 @@
"test": "make test"
},
"dependencies": {
"acorn-6to5": "0.11.1-25",
"acorn-6to5": "0.11.1-29",
"ast-types": "~0.6.1",
"chalk": "^0.5.1",
"chokidar": "0.12.6",
"commander": "2.6.0",
"core-js": "^0.4.9",
"core-js": "^0.5.2",
"debug": "^2.1.1",
"detect-indent": "3.0.0",
"estraverse": "1.9.1",
@@ -49,7 +49,7 @@
"lodash": "3.0.0",
"output-file-sync": "1.1.0",
"private": "0.1.6",
"regenerator-6to5": "0.8.9-8",
"regenerator-6to5": "0.8.10-1",
"regexpu": "1.1.0",
"roadrunner": "1.0.4",
"source-map": "0.1.43",
@@ -58,6 +58,7 @@
"useragent": "^2.1.5"
},
"devDependencies": {
"6to5": "3.5.3",
"browserify": "8.1.1",
"chai": "1.10.0",
"esvalid": "1.1.0",
@@ -69,8 +70,5 @@
"mocha": "2.1.0",
"rimraf": "2.2.8",
"uglify-js": "2.4.16"
},
"optionalDependencies": {
"kexec": "1.0.0"
}
}

View File

@@ -0,0 +1,5 @@
# 6to5-runtime
6to5 self-contained runtime
For more information please look at [6to5](https://github.com/6to5/6to5).

View File

@@ -1,7 +1,7 @@
{
"name": "6to5-runtime",
"description": "6to5 selfContained runtime",
"version": "3.3.12",
"version": "3.5.3",
"repository": "6to5/6to5",
"author": "Sebastian McKenzie <sebmck@gmail.com>"
}

View File

@@ -1,5 +1,5 @@
if (process.browser) {
require("../lib/6to5/browser");
require("../lib/6to5/api/browser");
require("./generation");
require("./transformation");
require("./traverse");

View File

@@ -19,14 +19,14 @@ var readFile = exports.readFile = function (filename) {
}
};
exports.esvalid = function (ast, loc) {
exports.esvalid = function (ast, code, loc) {
var errors = esvalid.errors(ast);
if (errors.length) {
var msg = [];
_.each(errors, function (err) {
msg.push(err.message + " - " + JSON.stringify(err.node));
});
throw new Error(loc + ": " + msg.join(". "));
throw new Error(loc + ": " + msg.join(". ") + "\n" + code);
}
};

View File

@@ -16,6 +16,14 @@ global.assertNoOwnProperties = function (obj) {
assert.equal(Object.getOwnPropertyNames(obj).length, 0);
};
global.assertHasOwnProperty = function () {
};
global.assertLacksOwnProperty = function () {
};
global.assertArrayEquals = assert.deepEqual;
global.assert = chai.assert;
global.chai = chai;
@@ -29,6 +37,8 @@ chai.assert.throw = function (fn, msg) {
msg = "Generator is already running";
} else if (msg === "Sent value to newborn generator") {
msg = /^attempt to send (.*?) to newborn generator$/;
} else if (msg === "super prototype must be an Object or null") {
msg = "Object prototype may only be an Object or null";
}
return chai.assert._throw(fn, msg);
@@ -54,7 +64,7 @@ var run = function (task, done) {
var checkAst = function (result, opts) {
if (noCheckAst) return;
helper.esvalid(result.ast.program, opts.loc);
helper.esvalid(result.ast.program, result.code, opts.loc);
};
if (execCode) {
@@ -129,12 +139,7 @@ module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
var runTest = function (done) {
var runTask = function () {
try {
run(task, done);
} catch (err) {
if (task.options.after) task.options.after();
throw err;
}
run(task, done);
};
_.extend(task.options, taskOpts);

View File

@@ -17,6 +17,6 @@ suite("api", function () {
var file = new File;
assert.throws(function () {
file.addHelper("foob");
}, /unknown declaration foob/);
}, /Unknown helper foob/);
});
});

View File

@@ -1,3 +1,3 @@
{
"throws": "Line 2: MULTIPLIER is read-only"
"throws": "Line 2: \"MULTIPLIER\" is read-only"
}

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,3 @@
a = 1;
let a = 2;

View File

@@ -0,0 +1,7 @@
function b() {
assert.equals(a, 1);
}
let a = 1;
b();

View File

@@ -0,0 +1,7 @@
function b() {
assert.equals(a, 1);
}
b();
let a = 1;

View File

@@ -0,0 +1,3 @@
a;
let a = 1;

View File

@@ -0,0 +1,3 @@
function foo(bar = bar2, bar2) {}
foo();

View File

@@ -0,0 +1,4 @@
{
"optional": "es6.blockScopingTDZ",
"throws": "is not defined - temporal dead zone"
}

View File

@@ -0,0 +1,3 @@
a++;
let a = 1;

View File

@@ -0,0 +1,3 @@
let a = 1;
a = 2;
assert.equal(a, 2);

View File

@@ -0,0 +1,7 @@
let a = 1;
function b() {
return a + 1;
}
assert.equal(b(), 2);

View File

@@ -0,0 +1,3 @@
function foo(bar, bar2 = bar) {}
foo();

View File

@@ -0,0 +1,3 @@
{
"optional": "es6.blockScopingTDZ"
}

View File

@@ -0,0 +1,3 @@
let a = 1;
a++;
assert.equal(a, 2);

View File

@@ -1,2 +0,0 @@
qux;
let qux = 456;

View File

@@ -1,4 +0,0 @@
{
"throws": "Temporal dead zone - accessing a variable before it's initialized",
"optional": ["es6.blockScopingTDZ"]
}

View File

@@ -1,3 +1,4 @@
{
"loose": ["es6.classes"]
"loose": ["es6.classes"],
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,7 @@
class MyClass {
myProp = { someValue: 42 };
}
var myClass = new MyClass;
assert.ok(myClass.myProp !== MyClass.prototype.myProp);
assert.equal(myClass.myProp.someValue, 42);

View File

@@ -0,0 +1,3 @@
{
"playground": true
}

View File

@@ -0,0 +1,5 @@
class MyClass {
static myProp = { someValue: 42 };
}
assert.equal(MyClass.myProp.someValue, 42);

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

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