Compare commits

...

93 Commits

Author SHA1 Message Date
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
Sebastian McKenzie
0799ed7116 v3.4.0 2015-02-07 10:41:38 +11:00
Sebastian McKenzie
5537250d4f fix linting errors 2015-02-07 10:40:01 +11:00
Sebastian McKenzie
7ada50937b add 3.4.0 changelog 2015-02-07 10:39:24 +11:00
Sebastian McKenzie
f2ae88af93 add commonStandard module formatter - fixes #675
will be merged into strict formatters in next major
TODO: rewrite all module formatters as they've gotten out of han
2015-02-07 10:31:52 +11:00
Sebastian McKenzie
726451f86f reverts d6b39bc89b 2015-02-07 09:54:18 +11:00
Sebastian McKenzie
306cfc6328 fix 3.3.12 changelog misspelling 2015-02-07 09:53:18 +11:00
Sebastian McKenzie
a051a47048 reorder types requires 2015-02-07 08:11:42 +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
Sebastian McKenzie
ad60d49611 fix bindingEquals in constants transformer 2015-02-06 23:35:19 +11:00
Sebastian McKenzie
a6d1a5a724 add bindingEquals, typeEquals, referenceEquals helper methods to Scope 2015-02-06 23:07:10 +11:00
Sebastian McKenzie
399d835285 fix linting errors 2015-02-06 23:06:54 +11:00
Sebastian McKenzie
b66367ddde change namespace of minification.propertyLiterals and minifciation.memberExpressionLiterals to es3 2015-02-06 22:42:16 +11:00
Sebastian McKenzie
37d29b7a6f clean up function scope collection - @RReverser 2015-02-06 22:04:13 +11:00
Sebastian McKenzie
1e708fb373 fix traverse test 2015-02-06 01:59:45 +11:00
Sebastian McKenzie
76ae1682a3 remove context arg in favor of this, rename TraversalIteration to TraversalPath, and remove ast handlers 2015-02-06 01:47:43 +11:00
Sebastian McKenzie
2ef0aa95c5 clean up indentation 2015-02-06 01:17:42 +11:00
Sebastian McKenzie
9cbb49c6b2 don't return the sourcemap when inline is requested - 6to5/grunt-6to5#18 2015-02-05 22:25:33 +11:00
Sebastian McKenzie
f04a734838 fix module ids shorthand arg - fixes #696 2015-02-05 22:19:39 +11:00
Sebastian McKenzie
beb5ccab25 split up traversal so it's easier to maintain and extend later on 2015-02-05 19:42:08 +11:00
Sebastian McKenzie
b8f8f24e82 add newline to es6 destructuring member expression test 2015-02-05 19:41:53 +11:00
Sebastian McKenzie
c35a007401 simplify replace supers helper 2015-02-05 19:41:37 +11:00
Sebastian McKenzie
e639c82f2f fix internal refactoring... 2015-02-05 14:08:02 +11:00
Sebastian McKenzie
f365cc1248 more internal rearchitecturing 2015-02-05 14:05:15 +11:00
Sebastian McKenzie
2b75c67448 better scope traversal inferType todo comments 2015-02-05 11:16:13 +11:00
197 changed files with 2029 additions and 1164 deletions

View File

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

View File

@@ -2,6 +2,7 @@
"esnext": true, "esnext": true,
"indent": 2, "indent": 2,
"freeze": true, "freeze": true,
"validthis": true,
"camelcase": true, "camelcase": true,
"unused": true, "unused": true,
"eqnull": true, "eqnull": true,

View File

@@ -11,10 +11,50 @@
_Note: Gaps between patch versions are faulty/broken releases._ _Note: Gaps between patch versions are faulty/broken releases._
## 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**
* Add `commonStandard` module formatter.
* **Bug Fix**
* Fix conflicting `--module-ids` shorthand arg in `$ 6to5`.
* **Internal**
* Lots of internal refactoring with scope tracking and traversal.
* **Polish**
* Don't return `map` in the API result if `sourceMap` was set to `"inline"`.
## 3.3.12 ## 3.3.12
* **Bug Fix** * **Bug Fix**
* Don't override `MemberExpression`s with `core-js` in `selfContaiend` if a local binding exists. * Don't override `MemberExpression`s with `core-js` in `selfContained` if a local binding exists.
## 3.3.11 ## 3.3.11

View File

@@ -18,7 +18,7 @@ build:
node $(BROWSERIFY_CMD) -e lib/6to5/polyfill.js >dist/polyfill.js node $(BROWSERIFY_CMD) -e lib/6to5/polyfill.js >dist/polyfill.js
node $(UGLIFY_CMD) dist/polyfill.js >dist/polyfill.min.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 $(UGLIFY_CMD) dist/6to5.js >dist/6to5.min.js
node bin/6to5-runtime >dist/runtime.js node bin/6to5-runtime >dist/runtime.js
@@ -92,7 +92,7 @@ publish:
make publish-core make publish-core
make publish-runtime make publish-runtime
rm -rf templates.json browser.js browser-polyfill.js rm -rf templates.json browser.js browser-polyfill.js runtime.js
publish-runtime: publish-runtime:
cd packages; \ cd packages; \

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("-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("-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("-c, --remove-comments", "Remove comments from the compiled code", false);
commander.option("-m, --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("-R, --react-compat", "Makes the react transformer produce pre-v0.12 code");
commander.option("--keep-module-id-extensions", "Keep extensions when generating module ids", false); commander.option("--keep-module-id-extensions", "Keep extensions when generating module ids", false);

View File

@@ -2,7 +2,7 @@ var readdir = require("fs-readdir-recursive");
var index = require("./index"); var index = require("./index");
var util = require("../../lib/6to5/util"); var util = require("../../lib/6to5/util");
var path = require("path"); var path = require("path");
var to5 = require("../../lib/6to5"); var to5 = require("../../lib/6to5/api/node");
var fs = require("fs"); var fs = require("fs");
var _ = require("lodash"); var _ = require("lodash");

View File

@@ -4,7 +4,7 @@ var commander = require("commander");
var Module = require("module"); var Module = require("module");
var path = require("path"); var path = require("path");
var repl = require("repl"); var repl = require("repl");
var to5 = require("../lib/6to5"); var to5 = require("../lib/6to5/api/node");
var util = require("../lib/6to5/util"); var util = require("../lib/6to5/util");
var vm = require("vm"); var vm = require("vm");
var _ = require("lodash"); var _ = require("lodash");

View File

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

View File

@@ -1,24 +1,24 @@
"use strict"; "use strict";
var transform = require("./transformation");
var util = require("./util");
var fs = require("fs");
var isFunction = require("lodash/lang/isFunction"); var isFunction = require("lodash/lang/isFunction");
var transform = require("../transformation");
var util = require("../util");
var fs = require("fs");
exports.version = require("../../package").version; exports.version = require("../../../package").version;
exports.runtime = require("./build-runtime"); exports.runtime = require("../build-runtime");
exports.types = require("./types"); exports.types = require("../types");
exports.register = function (opts) { exports.register = function (opts) {
var register = require("./register"); var register = require("./register/node");
if (opts != null) register(opts); if (opts != null) register(opts);
return register; return register;
}; };
exports.polyfill = function () { exports.polyfill = function () {
require("./polyfill"); require("../polyfill");
}; };
exports.canCompile = util.canCompile; exports.canCompile = util.canCompile;

View File

@@ -4,4 +4,4 @@
module.exports = function () {}; module.exports = function () {};
require("./polyfill"); require("../../polyfill");

View File

@@ -1,14 +1,14 @@
"use strict"; "use strict";
require("./polyfill"); require("../../polyfill");
var sourceMapSupport = require("source-map-support"); var sourceMapSupport = require("source-map-support");
var registerCache = require("./register-cache"); var registerCache = require("./cache");
var util = require("./util");
var to5 = require("./index");
var fs = require("fs");
var extend = require("lodash/object/extend"); var extend = require("lodash/object/extend");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
var util = require("../../util");
var to5 = require("../node");
var fs = require("fs");
sourceMapSupport.install({ sourceMapSupport.install({
retrieveSourceMap: function (source) { retrieveSourceMap: function (source) {
@@ -44,8 +44,10 @@ var mtime = function (filename) {
var compile = function (filename) { var compile = function (filename) {
var result; var result;
var cacheKey = filename + ":" + JSON.stringify(transformOpts);
if (cache) { if (cache) {
var cached = cache[filename]; var cached = cache[cacheKey];
if (cached && cached.mtime === mtime(filename)) { if (cached && cached.mtime === mtime(filename)) {
result = cached; result = cached;
} }
@@ -60,7 +62,7 @@ var compile = function (filename) {
if (cache) { if (cache) {
result.mtime = mtime(filename); result.mtime = mtime(filename);
cache[filename] = result; cache[cacheKey] = result;
} }
maps[filename] = result.map; maps[filename] = result.map;

View File

@@ -1,4 +1,4 @@
var File = require("./file"); var File = require("./transformation/file");
var util = require("./util"); var util = require("./util");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
var t = require("./types"); var t = require("./types");

View File

@@ -1,7 +1,7 @@
module.exports = detect; module.exports = detect;
var SYNTAX_KEYS = require("./syntax-keys"); var SYNTAX_KEYS = require("./syntax-keys");
var traverse = require("../traverse"); var traverse = require("../traversal");
var visitors = traverse.explode(require("./visitors")); var visitors = traverse.explode(require("./visitors"));
function detect(ast) { function detect(ast) {

View File

@@ -2,10 +2,10 @@
module.exports = Buffer; module.exports = Buffer;
var util = require("../util");
var isNumber = require("lodash/lang/isNumber");
var isBoolean = require("lodash/lang/isBoolean"); var isBoolean = require("lodash/lang/isBoolean");
var contains = require("lodash/collection/contains"); var contains = require("lodash/collection/contains");
var isNumber = require("lodash/lang/isNumber");
var util = require("../util");
function Buffer(position, format) { function Buffer(position, format) {
this.position = position; this.position = position;

View File

@@ -12,12 +12,12 @@ var Whitespace = require("./whitespace");
var SourceMap = require("./source-map"); var SourceMap = require("./source-map");
var Position = require("./position"); var Position = require("./position");
var Buffer = require("./buffer"); var Buffer = require("./buffer");
var extend = require("lodash/object/extend");
var merge = require("lodash/object/merge");
var each = require("lodash/collection/each");
var util = require("../util"); var util = require("../util");
var n = require("./node"); var n = require("./node");
var t = require("../types"); var t = require("../types");
var each = require("lodash/collection/each");
var extend = require("lodash/object/extend");
var merge = require("lodash/object/merge");
function CodeGenerator(ast, opts, code) { function CodeGenerator(ast, opts, code) {
opts = opts || {}; opts = opts || {};
@@ -25,6 +25,7 @@ function CodeGenerator(ast, opts, code) {
this.comments = ast.comments || []; this.comments = ast.comments || [];
this.tokens = ast.tokens || []; this.tokens = ast.tokens || [];
this.format = CodeGenerator.normalizeOptions(code, opts); this.format = CodeGenerator.normalizeOptions(code, opts);
this.opts = opts;
this.ast = ast; this.ast = ast;
this.whitespace = new Whitespace(this.tokens, this.comments); this.whitespace = new Whitespace(this.tokens, this.comments);

View File

@@ -0,0 +1,9 @@
var t = require("../types");
module.exports = function (ast, comments, tokens) {
if (ast && ast.type === "Program") {
return t.file(ast, comments || [], tokens || []);
} else {
throw new Error("Not a valid ast?");
}
};

49
lib/6to5/helpers/parse.js Normal file
View File

@@ -0,0 +1,49 @@
var normalizeAst = require("./normalize-ast");
var estraverse = require("estraverse");
var codeFrame = require("./code-frame");
var acorn = require("acorn-6to5");
module.exports = function (opts, code, callback) {
try {
var comments = [];
var tokens = [];
var ast = acorn.parse(code, {
allowImportExportEverywhere: opts.allowImportExportEverywhere,
allowReturnOutsideFunction: !opts._anal,
ecmaVersion: opts.experimental ? 7 : 6,
playground: opts.playground,
strictMode: opts.strictMode,
onComment: comments,
locations: true,
onToken: tokens,
ranges: true
});
estraverse.attachComments(ast, comments, tokens);
ast = normalizeAst(ast, comments, tokens);
if (callback) {
return callback(ast);
} else {
return ast;
}
} catch (err) {
if (!err._6to5) {
err._6to5 = true;
var message = opts.filename + ": " + err.message;
var loc = err.loc;
if (loc) {
var frame = codeFrame(code, loc.line, loc.column + 1);
message += frame;
}
if (err.stack) err.stack = err.stack.replace(err.message, message);
err.message = message;
}
throw err;
}
};

View File

@@ -1,7 +1,7 @@
"use strict"; "use strict";
var t = require("./types");
var extend = require("lodash/object/extend"); var extend = require("lodash/object/extend");
var t = require("./types");
require("./types/node"); require("./types/node");

View File

@@ -5,16 +5,17 @@ module.exports = File;
var SHEBANG_REGEX = /^\#\!.*/; var SHEBANG_REGEX = /^\#\!.*/;
var isFunction = require("lodash/lang/isFunction"); var isFunction = require("lodash/lang/isFunction");
var transform = require("./transformation"); var transform = require("./index");
var generate = require("./generation"); var generate = require("../generation");
var defaults = require("lodash/object/defaults"); var defaults = require("lodash/object/defaults");
var contains = require("lodash/collection/contains"); var contains = require("lodash/collection/contains");
var clone = require("./helpers/clone"); var clone = require("../helpers/clone");
var Scope = require("./traverse/scope"); var parse = require("../helpers/parse");
var util = require("./util"); var Scope = require("../traversal/scope");
var util = require("../util");
var path = require("path"); var path = require("path");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
var t = require("./types"); var t = require("../types");
function File(opts) { function File(opts) {
this.dynamicImportIds = {}; this.dynamicImportIds = {};
@@ -53,7 +54,10 @@ File.helpers = [
"get", "get",
"set", "set",
"class-call-check", "class-call-check",
"object-destructuring-empty" "object-destructuring-empty",
"temporal-undefined",
"temporal-assert-defined",
"tail-call"
]; ];
File.validOptions = [ File.validOptions = [
@@ -159,8 +163,14 @@ File.prototype.normalizeOptions = function (opts) {
opts.blacklist = transform._ensureTransformerNames("blacklist", opts.blacklist); opts.blacklist = transform._ensureTransformerNames("blacklist", opts.blacklist);
opts.whitelist = transform._ensureTransformerNames("whitelist", opts.whitelist); opts.whitelist = transform._ensureTransformerNames("whitelist", opts.whitelist);
opts.optional = transform._ensureTransformerNames("optional", opts.optional); opts.optional = transform._ensureTransformerNames("optional", opts.optional);
opts.loose = transform._ensureTransformerNames("loose", opts.loose); 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");
}
return opts; return opts;
}; };
@@ -197,6 +207,12 @@ File.prototype.buildTransformers = function () {
this.transformers = transformers; this.transformers = transformers;
}; };
File.prototype.debug = function (msg) {
var parts = this.opts.filename;
if (msg) parts += ": " + msg;
util.debug(parts);
};
File.prototype.toArray = function (node, i) { File.prototype.toArray = function (node, i) {
if (t.isArrayExpression(node)) { if (t.isArrayExpression(node)) {
return node; return node;
@@ -284,7 +300,7 @@ File.prototype.isConsequenceExpressionStatement = function (node) {
File.prototype.addHelper = function (name) { File.prototype.addHelper = function (name) {
if (!contains(File.helpers, name)) { if (!contains(File.helpers, name)) {
throw new ReferenceError("unknown declaration " + name); throw new ReferenceError("Unknown helper " + name);
} }
var program = this.ast.program; var program = this.ast.program;
@@ -334,16 +350,14 @@ File.prototype.parse = function (code) {
opts.allowImportExportEverywhere = this.isLoose("es6.modules"); opts.allowImportExportEverywhere = this.isLoose("es6.modules");
//opts.strictMode = this.transformers.useStrict.canRun(); //opts.strictMode = this.transformers.useStrict.canRun();
return util.parse(opts, code, function (tree) { return parse(opts, code, function (tree) {
self.transform(tree); self.transform(tree);
return self.generate(); return self.generate();
}); });
}; };
File.prototype.transform = function (ast) { File.prototype.transform = function (ast) {
var self = this; this.debug();
util.debug(this.opts.filename);
this.ast = ast; this.ast = ast;
this.lastStatements = t.getLastStatements(ast.program); this.lastStatements = t.getLastStatements(ast.program);
@@ -356,42 +370,46 @@ File.prototype.transform = function (ast) {
this.checkNode(ast); this.checkNode(ast);
var astRun = function (key) { this.call("pre");
each(self.transformerStack, function (pass) {
pass.astRun(key);
});
};
astRun("enter");
each(this.transformerStack, function (pass) { each(this.transformerStack, function (pass) {
pass.transform(); pass.transform();
}); });
astRun("exit"); this.call("post");
}; };
var checkTransformerVisitor = { File.prototype.call = function (key) {
enter: function (node, parent, scope, context, state) { var stack = this.transformerStack;
state.check(node, scope); for (var i = 0; i < stack.length; i++) {
var transformer = stack[i].transformer;
if (transformer[key]) {
transformer[key](this);
}
} }
}; };
var checkTransformerVisitor = {
enter: function (node, parent, scope, state) {
checkNode(state.stack, node, scope);
}
};
var checkNode = function (stack, node, scope) {
each(stack, function (pass) {
if (pass.shouldRun) return;
pass.checkNode(node, scope);
});
};
File.prototype.checkNode = function (node, scope) { File.prototype.checkNode = function (node, scope) {
var self = this; var stack = this.transformerStack;
scope = scope || this.scope; scope = scope || this.scope;
var check = function (node, scope) { checkNode(stack, node, scope);
each(self.transformerStack, function (pass) {
if (pass.shouldRun) return;
pass.checkNode(node, scope);
});
};
check(node, scope);
scope.traverse(node, checkTransformerVisitor, { scope.traverse(node, checkTransformerVisitor, {
check: check stack: stack
}); });
}; };
@@ -419,6 +437,7 @@ File.prototype.generate = function () {
if (opts.sourceMap === "inline") { if (opts.sourceMap === "inline") {
result.code += "\n" + util.sourceMapToComment(result.map); result.code += "\n" + util.sourceMapToComment(result.map);
result.map = null;
} }
return result; return result;

View File

@@ -12,7 +12,7 @@ module.exports = function (exports, opts) {
return t.assignmentExpression("=", left, right); return t.assignmentExpression("=", left, right);
}; };
exports.ExpressionStatement = function (node, parent, scope, context, file) { exports.ExpressionStatement = function (node, parent, scope, file) {
// hit the `AssignmentExpression` one below // hit the `AssignmentExpression` one below
if (file.isConsequenceExpressionStatement(node)) return; if (file.isConsequenceExpressionStatement(node)) return;
@@ -29,7 +29,7 @@ module.exports = function (exports, opts) {
return nodes; return nodes;
}; };
exports.AssignmentExpression = function (node, parent, scope, context, file) { exports.AssignmentExpression = function (node, parent, scope, file) {
if (!isAssignment(node)) return; if (!isAssignment(node)) return;
var nodes = []; var nodes = [];

View File

@@ -8,7 +8,7 @@ module.exports = function (exports, opts) {
return t.assignmentExpression("=", left, right); return t.assignmentExpression("=", left, right);
}; };
exports.ExpressionStatement = function (node, parent, scope, context, file) { exports.ExpressionStatement = function (node, parent, scope, file) {
// hit the `AssignmentExpression` one below // hit the `AssignmentExpression` one below
if (file.isConsequenceExpressionStatement(node)) return; if (file.isConsequenceExpressionStatement(node)) return;
@@ -27,7 +27,7 @@ module.exports = function (exports, opts) {
return nodes; return nodes;
}; };
exports.AssignmentExpression = function (node, parent, scope, context, file) { exports.AssignmentExpression = function (node, parent, scope, file) {
if (!opts.is(node, file)) return; if (!opts.is(node, file)) return;
var nodes = []; var nodes = [];

View File

@@ -0,0 +1,278 @@
"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 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, "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);
}
};
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

@@ -1,6 +1,6 @@
var cloneDeep = require("lodash/lang/cloneDeep"); var cloneDeep = require("lodash/lang/cloneDeep");
var traverse = require("../../traverse"); var traverse = require("../../traversal");
var clone = require("lodash/lang/clone"); var clone = require("lodash/lang/clone");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
var has = require("lodash/object/has"); var has = require("lodash/object/has");
var t = require("../../types"); var t = require("../../types");

View File

@@ -4,7 +4,7 @@ var util = require("../../util");
var t = require("../../types"); var t = require("../../types");
var visitor = { var visitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
// check if this node is an identifier that matches the same as our function id // check if this node is an identifier that matches the same as our function id
if (!t.isIdentifier(node, { name: state.id })) return; if (!t.isIdentifier(node, { name: state.id })) return;
@@ -17,7 +17,7 @@ var visitor = {
if (localDeclar !== state.outerDeclar) return; if (localDeclar !== state.outerDeclar) return;
state.selfReference = true; state.selfReference = true;
context.stop(); this.stop();
} }
}; };
@@ -36,15 +36,18 @@ exports.property = function (node, file, scope) {
scope.traverse(node, visitor, state); scope.traverse(node, visitor, state);
var method = node.value;
if (state.selfReference) { if (state.selfReference) {
// todo: support generators var templateName = "property-method-assignment-wrapper";
node.value = util.template("property-method-assignment-wrapper", { if (method.generator) templateName += "-generator";
FUNCTION: node.value, node.value = util.template(templateName, {
FUNCTION: method,
FUNCTION_ID: key, FUNCTION_ID: key,
FUNCTION_KEY: scope.generateUidIdentifier(id), FUNCTION_KEY: scope.generateUidIdentifier(id),
WRAPPER_KEY: scope.generateUidIdentifier(id + "Wrapper") WRAPPER_KEY: scope.generateUidIdentifier(id + "Wrapper")
}); });
} else { } 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.isReactComponent = t.buildMatchMemberExpression("React.Component");
exports.isCompatTag = function (tagName) {
return tagName && /^[a-z]|\-/.test(tagName);
};

View File

@@ -3,8 +3,8 @@
var t = require("../../types"); var t = require("../../types");
var visitor = { var visitor = {
enter: function (node, parent, scope, context) { enter: function (node) {
if (t.isFunction(node)) context.skip(); if (t.isFunction(node)) this.skip();
if (t.isAwaitExpression(node)) { if (t.isAwaitExpression(node)) {
node.type = "YieldExpression"; node.type = "YieldExpression";

View File

@@ -8,13 +8,17 @@ var t = require("../../types");
* Description * Description
* *
* @param {Object} opts * @param {Object} opts
* @param {Boolean} [inClass]
*/ */
function ReplaceSupers(opts) { function ReplaceSupers(opts, inClass) {
this.topLevelThisReference = null; this.topLevelThisReference = opts.topLevelThisReference;
this.methodNode = opts.methodNode; this.methodNode = opts.methodNode;
this.className = opts.className; this.className = opts.className;
this.superName = opts.superName; this.superName = opts.superName;
this.isStatic = opts.isStatic;
this.hasSuper = false;
this.inClass = inClass;
this.isLoose = opts.isLoose; this.isLoose = opts.isLoose;
this.scope = opts.scope; this.scope = opts.scope;
this.file = opts.file; this.file = opts.file;
@@ -28,16 +32,23 @@ function ReplaceSupers(opts) {
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this) * _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this)
* *
* @param {Node} property * @param {Node} property
* @param {boolean} isStatic * @param {Node} value
* @param {boolean} isComputed * @param {Boolean} isComputed
* @param {Node} thisExpression
* *
* @returns {Node} * @returns {Node}
*/ */
ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, isComputed, thisExpression) {
ReplaceSupers.prototype.setSuperProperty = function (property, value, isComputed, thisExpression) {
return t.callExpression( return t.callExpression(
this.file.addHelper("set"), this.file.addHelper("set"),
[ [
isStatic ? this.superName : t.memberExpression(this.superName, t.identifier("prototype")), t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name), isComputed ? property : t.literal(property.name),
value, value,
thisExpression thisExpression
@@ -53,17 +64,22 @@ ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic,
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this) * _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
* *
* @param {Node} property * @param {Node} property
* @param {boolean} isStatic * @param {Boolean} isComputed
* @param {boolean} isComputed * @param {Node} thisExpression
* *
* @returns {Node} * @returns {Node}
*/ */
ReplaceSupers.prototype.getSuperProperty = function (property, isStatic, isComputed, thisExpression) { ReplaceSupers.prototype.getSuperProperty = function (property, isComputed, thisExpression) {
return t.callExpression( return t.callExpression(
this.file.addHelper("get"), this.file.addHelper("get"),
[ [
isStatic ? this.superName : t.memberExpression(this.superName, t.identifier("prototype")), t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name), isComputed ? property : t.literal(property.name),
thisExpression thisExpression
] ]
@@ -79,19 +95,19 @@ ReplaceSupers.prototype.replace = function () {
}; };
var visitor = { var visitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
var topLevel = state.topLevel; var topLevel = state.topLevel;
var self = state.self; var self = state.self;
if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) { if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
// we need to call traverseLevel again so we're context aware // we need to call traverseLevel again so we're context aware
self.traverseLevel(node, false); self.traverseLevel(node, false);
return context.skip(); return this.skip();
} }
if (t.isProperty(node, { method: true }) || t.isMethodDefinition(node)) { if (t.isProperty(node, { method: true }) || t.isMethodDefinition(node)) {
// break on object methods // break on object methods
return context.skip(); return this.skip();
} }
var getThisReference = topLevel ? var getThisReference = topLevel ?
@@ -143,7 +159,8 @@ ReplaceSupers.prototype.getThisReference = function () {
* @returns {Object} * @returns {Object}
*/ */
ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent) { ReplaceSupers.prototype.getLooseSuperProperty = function (id, parent) {
var methodNode = this.methodNode;
var methodName = methodNode.key; var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function"); var superName = this.superName || t.identifier("Function");
@@ -185,13 +202,15 @@ ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent
ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) { ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) {
if (t.isIdentifier(node, { name: "super" })) { 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)) { } else if (t.isCallExpression(node)) {
var callee = node.callee; var callee = node.callee;
if (!t.isMemberExpression(callee)) return; if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return; if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this); // super.test(); -> ClassName.prototype.MethodName.call(this);
this.hasSuper = true;
t.appendToMemberExpression(callee, t.identifier("call")); t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference()); node.arguments.unshift(getThisReference());
} }
@@ -212,13 +231,13 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
var args; var args;
var thisReference; var thisReference;
if (t.isIdentifier(node, { name: "super" })) { if (isIllegalBareSuper(node, parent)) {
if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) { throw this.file.errorWithNode(node, "Illegal use of bare super");
throw this.file.errorWithNode(node, "illegal use of bare super"); }
}
} else if (t.isCallExpression(node)) { if (t.isCallExpression(node)) {
var callee = node.callee; var callee = node.callee;
if (t.isIdentifier(callee, { name: "super" })) { if (isSuper(callee, node)) {
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this); // super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
property = methodNode.key; property = methodNode.key;
computed = methodNode.computed; computed = methodNode.computed;
@@ -227,38 +246,32 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
// bare `super` call is illegal inside non-constructors // bare `super` call is illegal inside non-constructors
// - https://esdiscuss.org/topic/super-call-in-methods // - https://esdiscuss.org/topic/super-call-in-methods
// - https://twitter.com/wycats/status/544553184396836864 // - 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"; 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, "Direct super call is illegal in non-constructor, use super." + methodName + "() instead");
} }
} else { } else if (t.isMemberExpression(callee) && isSuper(callee.object, callee)) {
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this); // super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
property = callee.property; property = callee.property;
computed = callee.computed; computed = callee.computed;
args = node.arguments; args = node.arguments;
} }
} else if (t.isMemberExpression(node)) { } else if (t.isMemberExpression(node) && isSuper(node.object, node)) {
if (!t.isIdentifier(node.object, { name: "super" })) return;
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this); // super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
property = node.property; property = node.property;
computed = node.computed; computed = node.computed;
} else if (t.isAssignmentExpression(node)) { } else if (t.isAssignmentExpression(node) && isSuper(node.left.object, node.left) && methodNode.kind === "set") {
if (!t.isIdentifier(node.left.object, { name: "super" })) return;
if (methodNode.kind !== "set") return;
thisReference = getThisReference();
// super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this); // super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this);
return this.setSuperProperty(node.left.property, node.right, methodNode.static, node.left.computed, thisReference); this.hasSuper = true;
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
} }
if (!property) return; if (!property) return;
this.hasSuper = true;
thisReference = getThisReference(); thisReference = getThisReference();
var superProperty = this.getSuperProperty(property, methodNode.static, computed, thisReference); var superProperty = this.getSuperProperty(property, computed, thisReference);
if (args) { if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) { if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments); // super(...arguments);
@@ -276,3 +289,14 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
return superProperty; return superProperty;
} }
}; };
var isIllegalBareSuper = function (node, parent) {
if (!isSuper(node, parent)) return false;
if (t.isMemberExpression(parent, { computed: false })) return false;
if (t.isCallExpression(parent, { callee: node })) return false;
return true;
};
var isSuper = function (node, parent) {
return t.isIdentifier(node, { name: "super" }) && t.isReferenced(node, parent);
};

View File

@@ -2,11 +2,11 @@
module.exports = transform; module.exports = transform;
var Transformer = require("./transformer"); var normalizeAst = require("../helpers/normalize-ast");
var object = require("../helpers/object"); var Transformer = require("./transformer");
var File = require("../file"); var object = require("../helpers/object");
var util = require("../util"); var File = require("./file");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
function transform(code, opts) { function transform(code, opts) {
var file = new File(opts); var file = new File(opts);
@@ -14,7 +14,7 @@ function transform(code, opts) {
} }
transform.fromAst = function (ast, code, opts) { transform.fromAst = function (ast, code, opts) {
ast = util.normalizeAst(ast); ast = normalizeAst(ast);
var file = new File(opts); var file = new File(opts);
file.addCode(code); file.addCode(code);

View File

@@ -27,7 +27,7 @@ function DefaultFormatter(file) {
} }
DefaultFormatter.prototype.doDefaultExportInterop = function (node) { DefaultFormatter.prototype.doDefaultExportInterop = function (node) {
return node.default && !this.noInteropRequire && !this.hasNonDefaultExports; return node.default && !this.noInteropRequireExport && !this.hasNonDefaultExports;
}; };
DefaultFormatter.prototype.bumpImportOccurences = function (node) { DefaultFormatter.prototype.bumpImportOccurences = function (node) {
@@ -38,7 +38,7 @@ DefaultFormatter.prototype.bumpImportOccurences = function (node) {
}; };
var exportsVisitor = { var exportsVisitor = {
enter: function (node, parent, scope, context, formatter) { enter: function (node, parent, scope, formatter) {
var declar = node && node.declaration; var declar = node && node.declaration;
if (t.isExportDeclaration(node)) { if (t.isExportDeclaration(node)) {
formatter.hasLocalImports = true; formatter.hasLocalImports = true;
@@ -63,7 +63,7 @@ DefaultFormatter.prototype.getLocalExports = function () {
}; };
var importsVisitor = { var importsVisitor = {
enter: function (node, parent, scope, context, formatter) { enter: function (node, parent, scope, formatter) {
if (t.isImportDeclaration(node)) { if (t.isImportDeclaration(node)) {
formatter.hasLocalImports = true; formatter.hasLocalImports = true;
extend(formatter.localImports, t.getBindingIdentifiers(node)); extend(formatter.localImports, t.getBindingIdentifiers(node));
@@ -77,9 +77,9 @@ DefaultFormatter.prototype.getLocalImports = function () {
}; };
var remapVisitor = { var remapVisitor = {
enter: function (node, parent, scope, context, formatter) { enter: function (node, parent, scope, formatter) {
if (t.isUpdateExpression(node) && formatter.isLocalReference(node.argument, scope)) { if (t.isUpdateExpression(node) && formatter.isLocalReference(node.argument, scope)) {
context.skip(); this.skip();
// expand to long file assignment expression // expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1)); var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));
@@ -107,7 +107,7 @@ var remapVisitor = {
} }
if (t.isAssignmentExpression(node) && formatter.isLocalReference(node.left, scope)) { if (t.isAssignmentExpression(node) && formatter.isLocalReference(node.left, scope)) {
context.skip(); this.skip();
return formatter.remapExportAssignment(node); return formatter.remapExportAssignment(node);
} }
} }
@@ -228,7 +228,7 @@ DefaultFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
// export * from "foo"; // export * from "foo";
nodes.push(this.buildExportsWildcard(ref, node)); nodes.push(this.buildExportsWildcard(ref, node));
} else { } else {
if (t.isSpecifierDefault(specifier) && !this.noInteropRequire) { if (t.isSpecifierDefault(specifier) && !this.noInteropRequireExport) {
// importing a default so we need to normalize it // importing a default so we need to normalize it
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]); ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
} else { } else {

View File

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

View File

@@ -29,9 +29,8 @@ AMDFormatter.prototype.buildDependencyLiterals = function () {
* Wrap the entire body in a `define` wrapper. * Wrap the entire body in a `define` wrapper.
*/ */
AMDFormatter.prototype.transform = function (ast) { AMDFormatter.prototype.transform = function (program) {
var program = ast.program; var body = program.body;
var body = program.body;
// build an array of module names // build an array of module names
@@ -87,7 +86,7 @@ AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
this.ids[node.source.value] = ref; this.ids[node.source.value] = ref;
} else if (t.isImportBatchSpecifier(specifier)) { } else if (t.isImportBatchSpecifier(specifier)) {
// import * as bar from "foo"; // import * as bar from "foo";
} else if (t.isSpecifierDefault(specifier) && !this.noInteropRequire) { } else if (t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {
// import foo from "foo"; // import foo from "foo";
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]); ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
} else { } else {

View File

@@ -0,0 +1,13 @@
"use strict";
module.exports = CommonStandardFormatter;
var CommonStrictFormatter = require("./common-strict");
var util = require("../../util");
function CommonStandardFormatter() {
this.noInteropRequireImport = true;
CommonStrictFormatter.apply(this, arguments);
}
util.inherits(CommonStandardFormatter, CommonStrictFormatter);

View File

@@ -14,7 +14,7 @@ function CommonJSFormatter() {
util.inherits(CommonJSFormatter, DefaultFormatter); util.inherits(CommonJSFormatter, DefaultFormatter);
CommonJSFormatter.prototype.init = function () { CommonJSFormatter.prototype.init = function () {
if (this.hasNonDefaultExports) { if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
this.file.ast.program.body.push(util.template("exports-module-declaration", true)); this.file.ast.program.body.push(util.template("exports-module-declaration", true));
} }
}; };
@@ -27,19 +27,23 @@ CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes)
// import foo from "foo"; // import foo from "foo";
if (t.isSpecifierDefault(specifier)) { if (t.isSpecifierDefault(specifier)) {
if (!contains(this.file.dynamicImported, node)) { if (!contains(this.file.dynamicImported, node)) {
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]); if (this.noInteropRequireImport) {
ref = t.memberExpression(ref, t.identifier("default"));
} else {
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
}
} }
nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, ref)])); nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, ref)]));
} else { } else {
if (specifier.type === "ImportBatchSpecifier") { if (specifier.type === "ImportBatchSpecifier") {
if (!this.noInteropRequireImport) {
ref = t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]);
}
// import * as bar from "foo"; // import * as bar from "foo";
nodes.push(t.variableDeclaration("var", [ nodes.push(t.variableDeclaration("var", [
t.variableDeclarator( t.variableDeclarator(variableName, ref)
variableName,
t.callExpression(this.file.addHelper("interop-require-wildcard"), [
ref
])
)
])); ]));
} else { } else {
// import { foo } from "foo"; // import { foo } from "foo";

View File

@@ -1,10 +1,11 @@
module.exports = { module.exports = {
commonStrict: require("./common-strict"), commonStandard: require("./common-standard"),
amdStrict: require("./amd-strict"), commonStrict: require("./common-strict"),
umdStrict: require("./umd-strict"), amdStrict: require("./amd-strict"),
common: require("./common"), umdStrict: require("./umd-strict"),
system: require("./system"), common: require("./common"),
ignore: require("./ignore"), system: require("./system"),
amd: require("./amd"), ignore: require("./ignore"),
umd: require("./umd") amd: require("./amd"),
umd: require("./umd")
}; };

View File

@@ -13,7 +13,8 @@ var map = require("lodash/collection/map");
function SystemFormatter(file) { function SystemFormatter(file) {
this.exportIdentifier = file.generateUidIdentifier("export"); this.exportIdentifier = file.generateUidIdentifier("export");
this.noInteropRequire = true; this.noInteropRequireExport = true;
this.noInteropRequireImport = true;
DefaultFormatter.apply(this, arguments); DefaultFormatter.apply(this, arguments);
} }
@@ -68,7 +69,7 @@ SystemFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
}; };
var runnerSettersVisitor = { var runnerSettersVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (node._importSource === state.source) { if (node._importSource === state.source) {
if (t.isVariableDeclaration(node)) { if (t.isVariableDeclaration(node)) {
each(node.declarations, function (declar) { each(node.declarations, function (declar) {
@@ -81,7 +82,7 @@ var runnerSettersVisitor = {
state.nodes.push(node); state.nodes.push(node);
} }
context.remove(); this.remove();
} }
} }
}; };
@@ -103,10 +104,10 @@ SystemFormatter.prototype.buildRunnerSetters = function (block, hoistDeclarators
}; };
var hoistVariablesVisitor = { var hoistVariablesVisitor = {
enter: function (node, parent, scope, context, hoistDeclarators) { enter: function (node, parent, scope, hoistDeclarators) {
if (t.isFunction(node)) { if (t.isFunction(node)) {
// nothing inside is accessible // nothing inside is accessible
return context.skip(); return this.skip();
} }
if (t.isVariableDeclaration(node)) { if (t.isVariableDeclaration(node)) {
@@ -148,19 +149,17 @@ var hoistVariablesVisitor = {
}; };
var hoistFunctionsVisitor = { var hoistFunctionsVisitor = {
enter: function (node, parent, scope, context, handlerBody) { enter: function (node, parent, scope, handlerBody) {
if (t.isFunction(node)) context.skip(); if (t.isFunction(node)) this.skip();
if (t.isFunctionDeclaration(node) || node._blockHoist) { if (t.isFunctionDeclaration(node) || node._blockHoist) {
handlerBody.push(node); handlerBody.push(node);
context.remove(); this.remove();
} }
} }
}; };
SystemFormatter.prototype.transform = function (ast) { SystemFormatter.prototype.transform = function (program) {
var program = ast.program;
var hoistDeclarators = []; var hoistDeclarators = [];
var moduleName = this.getModuleName(); var moduleName = this.getModuleName();
var moduleNameLiteral = t.literal(moduleName); var moduleNameLiteral = t.literal(moduleName);

View File

@@ -13,9 +13,8 @@ function UMDFormatter() {
util.inherits(UMDFormatter, AMDFormatter); util.inherits(UMDFormatter, AMDFormatter);
UMDFormatter.prototype.transform = function (ast) { UMDFormatter.prototype.transform = function (program) {
var program = ast.program; var body = program.body;
var body = program.body;
// build an array of module names // build an array of module names

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 +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) { if (desc === undefined) {
var parent = Object.getPrototypeOf(object); var parent = Object.getPrototypeOf(object);
if (parent === null) { if (parent !== null) {
return;
} else {
return set(parent, property, value, receiver); return set(parent, property, value, receiver);
} }
} else if ("value" in desc && desc.writable) { } else if ("value" in desc && desc.writable) {
desc.value = value; return desc.value = value;
return;
} else { } else {
var setter = desc.set; var setter = desc.set;
if (setter === undefined) { if (setter !== undefined) {
return; return setter.call(receiver, value);
} }
return setter.call(receiver, value);
} }
}); });

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

@@ -1,6 +1,5 @@
module.exports = TransformerPass; module.exports = TransformerPass;
var util = require("../util");
var contains = require("lodash/collection/contains"); var contains = require("lodash/collection/contains");
/** /**
@@ -15,17 +14,6 @@ function TransformerPass(file, transformer) {
this.file = file; this.file = file;
} }
TransformerPass.prototype.astRun = function (key) {
if (!this.shouldRun) return;
var handlers = this.handlers;
var file = this.file;
if (handlers.ast && handlers.ast[key]) {
handlers.ast[key](file.ast, file);
}
};
TransformerPass.prototype.canRun = function () { TransformerPass.prototype.canRun = function () {
var transformer = this.transformer; var transformer = this.transformer;
@@ -41,7 +29,7 @@ TransformerPass.prototype.canRun = function () {
// whitelist // whitelist
var whitelist = opts.whitelist; var whitelist = opts.whitelist;
if (whitelist.length && !contains(whitelist, key)) return false; if (whitelist.length) return contains(whitelist, key);
// optional // optional
if (transformer.optional && !contains(opts.optional, key)) return false; if (transformer.optional && !contains(opts.optional, key)) return false;
@@ -64,31 +52,12 @@ TransformerPass.prototype.checkNode = function (node) {
} }
}; };
var transformVisitor = {
enter: function (node, parent, scope, context, state) {
var fns = state.handlers[node.type];
if (!fns) return;
return fns.enter(node, parent, scope, context, state.file, state.pass);
},
exit: function (node, parent, scope, context, state) {
var fns = state.handlers[node.type];
if (!fns) return;
return fns.exit(node, parent, scope, context, state.file, state.pass);
}
};
TransformerPass.prototype.transform = function () { TransformerPass.prototype.transform = function () {
if (!this.shouldRun) return; if (!this.shouldRun) return;
var file = this.file; var file = this.file;
util.debug(file.opts.filename + ": Running transformer " + this.transformer.key); file.debug("Running transformer " + this.transformer.key);
this.astRun("before"); file.scope.traverse(file.ast, this.handlers, file);
var state = { file: file, handlers: this.handlers, pass: this };
file.scope.traverse(file.ast, transformVisitor, state);
this.astRun("after");
}; };

View File

@@ -4,8 +4,9 @@ module.exports = Transformer;
var TransformerPass = require("./transformer-pass"); var TransformerPass = require("./transformer-pass");
var isFunction = require("lodash/lang/isFunction"); var isFunction = require("lodash/lang/isFunction");
var traverse = require("../traverse"); var traverse = require("../traversal");
var isObject = require("lodash/lang/isObject"); var isObject = require("lodash/lang/isObject");
var clone = require("../helpers/clone");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
/** /**
@@ -15,13 +16,23 @@ var each = require("lodash/collection/each");
*/ */
function Transformer(key, transformer, opts) { function Transformer(key, transformer, opts) {
this.manipulateOptions = transformer.manipulateOptions; transformer = clone(transformer);
this.check = transformer.check;
this.experimental = !!transformer.experimental; var take = function (key) {
this.playground = !!transformer.playground; var val = transformer[key];
this.secondPass = !!transformer.secondPass; delete transformer[key];
this.optional = !!transformer.optional; return val;
};
this.manipulateOptions = take("manipulateOptions");
this.check = take("check");
this.post = take("post");
this.pre = take("pre");
this.experimental = !!take("experimental");
this.playground = !!take("playground");
this.secondPass = !!take("secondPass");
this.optional = !!take("optional");
this.handlers = this.normalize(transformer); this.handlers = this.normalize(transformer);
this.opts = opts || {}; this.opts = opts || {};

View File

@@ -34,6 +34,8 @@
"coreAliasing": "selfContained", "coreAliasing": "selfContained",
"undefinedToVoid": "spec.undefinedToVoid", "undefinedToVoid": "spec.undefinedToVoid",
"undeclaredVariableCheck": "validation.undeclaredVariableCheck", "undeclaredVariableCheck": "validation.undeclaredVariableCheck",
"specPropertyLiterals": "minification.propertyLiterals", "specPropertyLiterals": "es3.propertyLiterals",
"specMemberExpressionLiterals": "minification.memberExpressionLiterals" "specMemberExpressionLiterals": "es3.memberExpressionLiterals",
"minification.propertyLiterals": "es3.propertyLiterals",
"minification.memberExpressionLiterals": "es3.memberExpressionLiterals"
} }

View File

@@ -3,7 +3,7 @@
var t = require("../../../types"); var t = require("../../../types");
var visitor = { var visitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (!t.isReferencedIdentifier(node, parent)) return; if (!t.isReferencedIdentifier(node, parent)) return;
var declared = state.letRefs[node.name]; var declared = state.letRefs[node.name];
@@ -12,22 +12,18 @@ var visitor = {
// declared node is different in this scope // declared node is different in this scope
if (scope.getBinding(node.name) !== declared) return; if (scope.getBinding(node.name) !== declared) return;
var declaredLoc = declared.loc; var assert = t.callExpression(
var referenceLoc = node.loc; 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? if (t.isAssignmentExpression(parent) || t.isUpdateExpression(parent)) {
var before = referenceLoc.start.line < declaredLoc.start.line; if (parent._ignoreBlockScopingTDZ) return;
this.parentPath.replaceNode(t.sequenceExpression([assert, parent]));
if (referenceLoc.start.line === declaredLoc.start.line) { } else {
// this reference appears on the same line return t.logicalExpression("&&", assert, node);
// 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");
} }
} }
}; };
@@ -36,7 +32,7 @@ exports.optional = true;
exports.Loop = exports.Loop =
exports.Program = exports.Program =
exports.BlockStatement = function (node, parent, scope, context, file) { exports.BlockStatement = function (node, parent, scope, file) {
var letRefs = node._letReferences; var letRefs = node._letReferences;
if (!letRefs) return; if (!letRefs) return;

View File

@@ -1,6 +1,6 @@
"use strict"; "use strict";
var traverse = require("../../../traverse"); var traverse = require("../../../traversal");
var object = require("../../../helpers/object"); var object = require("../../../helpers/object");
var util = require("../../../util"); var util = require("../../../util");
var t = require("../../../types"); var t = require("../../../types");
@@ -17,7 +17,7 @@ var isLet = function (node, parent) {
if (node.kind !== "let") return false; if (node.kind !== "let") return false;
// https://github.com/6to5/6to5/issues/255 // 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++) { for (var i = 0; i < node.declarations.length; i++) {
var declar = node.declarations[i]; var declar = node.declarations[i];
declar.init = declar.init || t.identifier("undefined"); declar.init = declar.init || t.identifier("undefined");
@@ -29,6 +29,10 @@ var isLet = function (node, parent) {
return true; return true;
}; };
var isLetInitable = function (node, parent) {
return !t.isFor(parent) || t.isFor(parent) && parent.left !== node;
};
var isVar = function (node, parent) { var isVar = function (node, parent) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent); return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent);
}; };
@@ -39,11 +43,29 @@ var standardizeLets = function (declars) {
} }
}; };
exports.VariableDeclaration = function (node, parent) { exports.VariableDeclaration = function (node, parent, scope, file) {
isLet(node, parent); 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, context, file) { exports.Loop = function (node, parent, scope, file) {
var init = node.left || node.init; var init = node.left || node.init;
if (isLet(init, node)) { if (isLet(init, node)) {
t.ensureBlock(node); t.ensureBlock(node);
@@ -54,7 +76,7 @@ exports.Loop = function (node, parent, scope, context, file) {
}; };
exports.Program = exports.Program =
exports.BlockStatement = function (block, parent, scope, context, file) { exports.BlockStatement = function (block, parent, scope, file) {
if (!t.isLoop(parent)) { if (!t.isLoop(parent)) {
var blockScoping = new BlockScoping(false, block, parent, scope, file); var blockScoping = new BlockScoping(false, block, parent, scope, file);
blockScoping.run(); blockScoping.run();
@@ -108,7 +130,7 @@ BlockScoping.prototype.run = function () {
} }
}; };
function replace(node, parent, scope, context, remaps) { function replace(node, parent, scope, remaps) {
if (!t.isReferencedIdentifier(node, parent)) return; if (!t.isReferencedIdentifier(node, parent)) return;
var remap = remaps[node.name]; var remap = remaps[node.name];
@@ -120,7 +142,7 @@ function replace(node, parent, scope, context, remaps) {
} else { } else {
// scope already has it's own binding that doesn't // scope already has it's own binding that doesn't
// match the one we have a stored replacement for // match the one we have a stored replacement for
if (context) context.skip(); if (this) this.skip();
} }
} }
@@ -129,7 +151,7 @@ var replaceVisitor = {
}; };
function traverseReplace(node, parent, scope, remaps) { function traverseReplace(node, parent, scope, remaps) {
replace(node, parent, scope, null, remaps); replace(node, parent, scope, remaps);
scope.traverse(node, replaceVisitor, remaps); scope.traverse(node, replaceVisitor, remaps);
} }
@@ -225,7 +247,7 @@ BlockScoping.prototype.needsClosure = function () {
}; };
var letReferenceFunctionVisitor = { var letReferenceFunctionVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
// not a direct reference // not a direct reference
if (!t.isReferencedIdentifier(node, parent)) return; if (!t.isReferencedIdentifier(node, parent)) return;
@@ -241,10 +263,10 @@ var letReferenceFunctionVisitor = {
}; };
var letReferenceBlockVisitor = { var letReferenceBlockVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isFunction(node)) { if (t.isFunction(node)) {
scope.traverse(node, letReferenceFunctionVisitor, state); scope.traverse(node, letReferenceFunctionVisitor, state);
return context.skip(); return this.skip();
} }
} }
}; };
@@ -310,7 +332,7 @@ var loopNodeTo = function (node) {
}; };
var loopVisitor = { var loopVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
var replace; var replace;
if (t.isLoop(node)) { if (t.isLoop(node)) {
@@ -320,7 +342,7 @@ var loopVisitor = {
} }
if (t.isFunction(node) || t.isLoop(node)) { if (t.isFunction(node) || t.isLoop(node)) {
return context.skip(); return this.skip();
} }
var loopText = loopNodeTo(node); var loopText = loopNodeTo(node);
@@ -362,7 +384,7 @@ var loopVisitor = {
}; };
var loopLabelVisitor = { var loopLabelVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isLabeledStatement(node)) { if (t.isLabeledStatement(node)) {
state.innerLabels.push(node.label.name); state.innerLabels.push(node.label.name);
} }
@@ -395,7 +417,7 @@ BlockScoping.prototype.checkLoop = function () {
}; };
var hoistVarDeclarationsVisitor = { var hoistVarDeclarationsVisitor = {
enter: function (node, parent, scope, context, self) { enter: function (node, parent, scope, self) {
if (t.isForStatement(node)) { if (t.isForStatement(node)) {
if (isVar(node.init, node)) { if (isVar(node.init, node)) {
node.init = t.sequenceExpression(self.pushDeclar(node.init)); node.init = t.sequenceExpression(self.pushDeclar(node.init));
@@ -407,7 +429,7 @@ var hoistVarDeclarationsVisitor = {
} else if (isVar(node, parent)) { } else if (isVar(node, parent)) {
return self.pushDeclar(node).map(t.expressionStatement); return self.pushDeclar(node).map(t.expressionStatement);
} else if (t.isFunction(node)) { } else if (t.isFunction(node)) {
return context.skip(); return this.skip();
} }
} }
}; };

View File

@@ -8,11 +8,11 @@ var t = require("../../../types");
exports.check = t.isClass; exports.check = t.isClass;
exports.ClassDeclaration = function (node, parent, scope, context, file) { exports.ClassDeclaration = function (node, parent, scope, file) {
return new Class(node, file, scope, true).run(); return new Class(node, file, scope, true).run();
}; };
exports.ClassExpression = function (node, parent, scope, context, file) { exports.ClassExpression = function (node, parent, scope, file) {
if (!node.id) { if (!node.id) {
if (t.isProperty(parent) && parent.value === node && !parent.computed && t.isIdentifier(parent.key)) { if (t.isProperty(parent) && parent.value === node && !parent.computed && t.isIdentifier(parent.key)) {
// var o = { foo: class {} }; // var o = { foo: class {} };
@@ -152,10 +152,11 @@ Class.prototype.buildBody = function () {
methodNode: node, methodNode: node,
className: this.className, className: this.className,
superName: this.superName, superName: this.superName,
isStatic: node.static,
isLoose: this.isLoose, isLoose: this.isLoose,
scope: this.scope, scope: this.scope,
file: this.file file: this.file
}); }, true);
replaceSupers.replace(); replaceSupers.replace();
if (node.key.name === "constructor") { if (node.key.name === "constructor") {

View File

@@ -7,7 +7,7 @@ exports.check = function (node) {
}; };
var visitor = { var visitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) { if (t.isAssignmentExpression(node) || t.isUpdateExpression(node)) {
var ids = t.getBindingIdentifiers(node); var ids = t.getBindingIdentifiers(node);
@@ -24,18 +24,18 @@ var visitor = {
// constant so we can just ignore it // constant so we can just ignore it
if (id === constant) continue; if (id === constant) continue;
var localBinding = scope.getBinding(key); // check if there's been a local binding that shadows this constant
if (localBinding !== constant) continue; if (!scope.bindingEquals(key, constant)) continue;
throw state.file.errorWithNode(id, key + " is read-only"); throw state.file.errorWithNode(id, key + " is read-only");
} }
} else if (t.isScope(node)) { } else if (t.isScope(node)) {
context.skip(); this.skip();
} }
} }
}; };
exports.Scope = function (node, parent, scope, context, file) { exports.Scope = function (node, parent, scope, file) {
scope.traverse(node, visitor, { scope.traverse(node, visitor, {
constants: scope.getAllDeclarationsOfKind("const"), constants: scope.getAllDeclarationsOfKind("const"),
file: file file: file

View File

@@ -112,6 +112,12 @@ Destructuring.prototype.pushObjectPattern = function (pattern, 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++) { for (var i = 0; i < pattern.properties.length; i++) {
var prop = pattern.properties[i]; var prop = pattern.properties[i];
if (t.isSpreadProperty(prop)) { if (t.isSpreadProperty(prop)) {
@@ -178,22 +184,41 @@ Destructuring.prototype.init = function (pattern, parentId) {
}; };
exports.ForInStatement = exports.ForInStatement =
exports.ForOfStatement = function (node, parent, scope, context, file) { exports.ForOfStatement = function (node, parent, scope, file) {
var declar = node.left; var left = node.left;
if (!t.isVariableDeclaration(declar)) return;
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; if (!t.isPattern(pattern)) return;
var key = scope.generateUidIdentifier("ref"); var key = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration(declar.kind, [ node.left = t.variableDeclaration(left.kind, [
t.variableDeclarator(key, null) t.variableDeclarator(key, null)
]); ]);
var nodes = []; var nodes = [];
var destructuring = new Destructuring({ var destructuring = new Destructuring({
kind: declar.kind, kind: left.kind,
file: file, file: file,
scope: scope, scope: scope,
nodes: nodes nodes: nodes
@@ -207,7 +232,7 @@ exports.ForOfStatement = function (node, parent, scope, context, file) {
block.body = nodes.concat(block.body); block.body = nodes.concat(block.body);
}; };
exports.Function = function (node, parent, scope, context, file) { exports.Function = function (node, parent, scope, file) {
var nodes = []; var nodes = [];
var hasDestructuring = false; var hasDestructuring = false;
@@ -238,7 +263,7 @@ exports.Function = function (node, parent, scope, context, file) {
block.body = nodes.concat(block.body); block.body = nodes.concat(block.body);
}; };
exports.CatchClause = function (node, parent, scope, context, file) { exports.CatchClause = function (node, parent, scope, file) {
var pattern = node.param; var pattern = node.param;
if (!t.isPattern(pattern)) return; if (!t.isPattern(pattern)) return;
@@ -248,7 +273,7 @@ exports.CatchClause = function (node, parent, scope, context, file) {
var nodes = []; var nodes = [];
var destructuring = new Destructuring({ var destructuring = new Destructuring({
kind: "var", kind: "let",
file: file, file: file,
scope: scope, scope: scope,
nodes: nodes nodes: nodes
@@ -256,9 +281,11 @@ exports.CatchClause = function (node, parent, scope, context, file) {
destructuring.init(pattern, ref); destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body); node.body.body = nodes.concat(node.body.body);
return node;
}; };
exports.ExpressionStatement = function (node, parent, scope, context, file) { exports.ExpressionStatement = function (node, parent, scope, file) {
var expr = node.expression; var expr = node.expression;
if (expr.type !== "AssignmentExpression") return; if (expr.type !== "AssignmentExpression") return;
if (!t.isPattern(expr.left)) return; if (!t.isPattern(expr.left)) return;
@@ -282,7 +309,7 @@ exports.ExpressionStatement = function (node, parent, scope, context, file) {
return nodes; return nodes;
}; };
exports.AssignmentExpression = function (node, parent, scope, context, file) { exports.AssignmentExpression = function (node, parent, scope, file) {
if (!t.isPattern(node.left)) return; if (!t.isPattern(node.left)) return;
var ref = scope.generateUidIdentifier("temp"); var ref = scope.generateUidIdentifier("temp");
@@ -316,7 +343,7 @@ var variableDeclarationhasPattern = function (node) {
return false; return false;
}; };
exports.VariableDeclaration = function (node, parent, scope, context, file) { exports.VariableDeclaration = function (node, parent, scope, file) {
if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return; if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;
if (!variableDeclarationhasPattern(node)) return; if (!variableDeclarationhasPattern(node)) return;

View File

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

View File

@@ -4,7 +4,7 @@ var t = require("../../../types");
exports.check = require("../internal/modules").check; exports.check = require("../internal/modules").check;
exports.ImportDeclaration = function (node, parent, scope, context, file) { exports.ImportDeclaration = function (node, parent, scope, file) {
var nodes = []; var nodes = [];
if (node.specifiers.length) { if (node.specifiers.length) {
@@ -23,7 +23,7 @@ exports.ImportDeclaration = function (node, parent, scope, context, file) {
return nodes; return nodes;
}; };
exports.ExportDeclaration = function (node, parent, scope, context, file) { exports.ExportDeclaration = function (node, parent, scope, file) {
var nodes = []; var nodes = [];
var i; var i;

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) { var hasDefaults = function (node) {
for (var i = 0; i < node.params.length; i++) { 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; return false;
}; };
var iifeVisitor = { var iifeVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isReferencedIdentifier(node, parent) && state.scope.hasOwnReference(node.name)) { if (!t.isReferencedIdentifier(node, parent)) return;
state.iife = true; if (!state.scope.hasOwnBinding(node.name)) return;
context.stop(); if (state.scope.bindingEquals(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; if (!hasDefaults(node)) return;
t.ensureBlock(node); t.ensureBlock(node);
@@ -37,11 +39,32 @@ exports.Function = function (node, parent, scope) {
var state = { iife: false, scope: 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++) { for (var i = 0; i < node.params.length; i++) {
var param = node.params[i]; var param = node.params[i];
if (!t.isAssignmentPattern(param)) { if (!t.isAssignmentPattern(param)) {
lastNonDefaultParam = +i + 1; 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; continue;
} }
@@ -58,14 +81,7 @@ exports.Function = function (node, parent, scope) {
} }
} }
var defNode = util.template("default-parameter", { pushDefNode(left, right, i);
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(+i),
ARGUMENTS: argsIdentifier
}, true);
defNode._blockHoist = node.params.length - i;
body.push(defNode);
} }
// we need to cut off all trailing default parameters // we need to cut off all trailing default parameters

View File

@@ -6,7 +6,7 @@ exports.check = function (node) {
return t.isProperty(node) && node.computed; return t.isProperty(node) && node.computed;
}; };
exports.ObjectExpression = function (node, parent, scope, context, file) { exports.ObjectExpression = function (node, parent, scope, file) {
var hasComputed = false; var hasComputed = false;
for (var i = 0; i < node.properties.length; i++) { for (var i = 0; i < node.properties.length; i++) {

View File

@@ -8,7 +8,7 @@ exports.check = function (node) {
return t.isProperty(node) && (node.method || node.shorthand); return t.isProperty(node) && (node.method || node.shorthand);
}; };
exports.Property = function (node, parent, scope, context, file) { exports.Property = function (node, parent, scope, file) {
if (node.method) { if (node.method) {
node.method = false; node.method = false;
nameMethod.property(node, file, scope); nameMethod.property(node, file, scope);

View File

@@ -44,7 +44,7 @@ var build = function (props, file) {
return nodes; return nodes;
}; };
exports.ArrayExpression = function (node, parent, scope, context, file) { exports.ArrayExpression = function (node, parent, scope, file) {
var elements = node.elements; var elements = node.elements;
if (!hasSpread(elements)) return; if (!hasSpread(elements)) return;
@@ -59,7 +59,7 @@ exports.ArrayExpression = function (node, parent, scope, context, file) {
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes); return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
}; };
exports.CallExpression = function (node, parent, scope, context, file) { exports.CallExpression = function (node, parent, scope, file) {
var args = node.arguments; var args = node.arguments;
if (!hasSpread(args)) return; if (!hasSpread(args)) return;
@@ -73,8 +73,8 @@ exports.CallExpression = function (node, parent, scope, context, file) {
} else { } else {
nodes = build(args, file); nodes = build(args, file);
} }
var first = nodes.shift();
var first = nodes.shift();
if (nodes.length) { if (nodes.length) {
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes)); node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes));
} else { } else {
@@ -99,7 +99,7 @@ exports.CallExpression = function (node, parent, scope, context, file) {
node.arguments.unshift(contextLiteral); node.arguments.unshift(contextLiteral);
}; };
exports.NewExpression = function (node, parent, scope, context, file) { exports.NewExpression = function (node, parent, scope, file) {
var args = node.arguments; var args = node.arguments;
if (!hasSpread(args)) return; if (!hasSpread(args)) return;

View File

@@ -0,0 +1,116 @@
"use strict";
var t = require("../../../types");
function transformExpression(node, scope, state) {
if (!node) return;
return (function subTransform(node) {
switch (node.type) {
case "ConditionalExpression":
// any value of ternary operator can be final one
subTransform(node.consequent);
subTransform(node.alternate);
break;
case "LogicalExpression":
// only right expression can be final and so optimized
subTransform(node.right);
break;
case "SequenceExpression":
// only last element of sequence can be optimized
var seq = node.expressions;
subTransform(seq[seq.length - 1]);
break;
case "CallExpression":
var callee = node.callee, thisBinding;
var args = [callee];
// bind `this` to object in member expressions
if (t.isMemberExpression(callee)) {
var object = state.wrapSideEffect(callee.object);
callee.object = object.expr;
thisBinding = object.ref;
}
if (node.arguments.length > 0 || thisBinding) {
args.push(t.arrayExpression(node.arguments));
}
if (thisBinding) {
args.push(thisBinding);
}
node.callee = state.getHelperRef();
node.arguments = args;
break;
}
})(node);
}
var functionChildrenVisitor = {
enter: function (node, parent, scope, state) {
if (t.isReturnStatement(node)) {
// prevent entrance by current visitor
this.skip();
// transform return argument into statement if
// it contains tail recursion
transformExpression(node.argument, scope, state);
} else if (t.isFunction(node)) {
// inner function's bodies are irrelevant
this.skip();
} else if (t.isTryStatement(parent)) {
if (node === parent.block) {
// `try`-blocks can't be optimized
this.skip();
} else if (parent.finalizer && node !== parent.finalizer) {
// `catch` clause followed by `finally` can't be optimized
this.skip();
}
}
}
};
var functionVisitor = {
enter: function (node, parent, scope, state) {
// traverse all child nodes of this function and find `arguments` and `this`
scope.traverse(node, functionChildrenVisitor, state);
return this.skip();
}
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, scope, file) {
var tempId, helperRef;
var state = {
ownerId: node.id,
getHelperRef: function () {
return helperRef = helperRef || file.addHelper("tail-call");
},
wrapSideEffect: function (node) {
if (t.isIdentifier(node) || t.isLiteral(node)) {
return {expr: node, ref: node};
}
tempId = tempId || scope.generateUidIdentifier("temp");
return {
expr: t.assignmentExpression("=", tempId, node),
ref: tempId
};
}
};
// traverse the function and look for tail recursion
scope.traverse(node, functionVisitor, state);
if (tempId) {
t.ensureBlock(node).body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(tempId)
]));
}
};

View File

@@ -10,7 +10,7 @@ exports.check = function (node) {
return t.isTemplateLiteral(node) || t.isTaggedTemplateExpression(node); return t.isTemplateLiteral(node) || t.isTaggedTemplateExpression(node);
}; };
exports.TaggedTemplateExpression = function (node, parent, scope, context, file) { exports.TaggedTemplateExpression = function (node, parent, scope, file) {
var args = []; var args = [];
var quasi = node.quasi; var quasi = node.quasi;

View File

@@ -23,7 +23,7 @@ var container = function (parent, call, ret, file) {
} }
}; };
exports.AssignmentExpression = function (node, parent, scope, context, file) { exports.AssignmentExpression = function (node, parent, scope, file) {
var left = node.left; var left = node.left;
if (!t.isVirtualPropertyExpression(left)) return; if (!t.isVirtualPropertyExpression(left)) return;
@@ -63,7 +63,7 @@ exports.AssignmentExpression = function (node, parent, scope, context, file) {
return container(parent, call, value, file); return container(parent, call, value, file);
}; };
exports.UnaryExpression = function (node, parent, scope, context, file) { exports.UnaryExpression = function (node, parent, scope, file) {
var arg = node.argument; var arg = node.argument;
if (!t.isVirtualPropertyExpression(arg)) return; if (!t.isVirtualPropertyExpression(arg)) return;
if (node.operator !== "delete") return; if (node.operator !== "delete") return;

View File

@@ -1,13 +1,13 @@
"use strict"; "use strict";
var buildComprehension = require("../../helpers/build-comprehension"); var buildComprehension = require("../../helpers/build-comprehension");
var traverse = require("../../../traverse"); var traverse = require("../../../traversal");
var util = require("../../../util"); var util = require("../../../util");
var t = require("../../../types"); var t = require("../../../types");
exports.experimental = true; exports.experimental = true;
exports.ComprehensionExpression = function (node, parent, scope, context, file) { exports.ComprehensionExpression = function (node, parent, scope, file) {
var callback = array; var callback = array;
if (node.generator) callback = generator; if (node.generator) callback = generator;
return callback(node, parent, scope, file); return callback(node, parent, scope, file);

View File

@@ -19,7 +19,7 @@ var hasSpread = function (node) {
return false; return false;
}; };
exports.ObjectExpression = function (node, parent, scope, context, file) { exports.ObjectExpression = function (node, parent, scope, file) {
if (!hasSpread(node)) return; if (!hasSpread(node)) return;
var args = []; var args = [];

View File

@@ -11,6 +11,7 @@ module.exports = {
"playground.memoizationOperator": require("./playground/memoization-operator"), "playground.memoizationOperator": require("./playground/memoization-operator"),
"playground.objectGetterMemoization": require("./playground/object-getter-memoization"), "playground.objectGetterMemoization": require("./playground/object-getter-memoization"),
reactCompat: require("./other/react-compat"),
react: require("./other/react"), react: require("./other/react"),
_modules: require("./internal/modules"), _modules: require("./internal/modules"),
@@ -27,6 +28,7 @@ module.exports = {
asyncToGenerator: require("./other/async-to-generator"), asyncToGenerator: require("./other/async-to-generator"),
bluebirdCoroutines: require("./other/bluebird-coroutines"), bluebirdCoroutines: require("./other/bluebird-coroutines"),
"es6.objectSuper": require("./es6/object-super"),
"es7.objectRestSpread": require("./es7/object-rest-spread"), "es7.objectRestSpread": require("./es7/object-rest-spread"),
"es7.exponentiationOperator": require("./es7/exponentiation-operator"), "es7.exponentiationOperator": require("./es7/exponentiation-operator"),
"es6.spread": require("./es6/spread"), "es6.spread": require("./es6/spread"),
@@ -45,6 +47,14 @@ module.exports = {
"es6.constants": require("./es6/constants"), "es6.constants": require("./es6/constants"),
// needs to be before `es6.blockScoping` as default parameters have a TDZ
"es6.parameters.default": require("./es6/parameters.default"),
"es6.parameters.rest": require("./es6/parameters.rest"),
// needs to be before `es6.blockScoping` as let variables may be produced
"es6.destructuring": require("./es6/destructuring"),
// needs to be before `_aliasFunction` due to block scopes sometimes being wrapped in a // needs to be before `_aliasFunction` due to block scopes sometimes being wrapped in a
// closure // closure
"es6.blockScoping": require("./es6/block-scoping"), "es6.blockScoping": require("./es6/block-scoping"),
@@ -52,10 +62,7 @@ module.exports = {
// needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks // needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks
"es6.blockScopingTDZ": require("./es6/block-scoping-tdz"), "es6.blockScopingTDZ": require("./es6/block-scoping-tdz"),
"es6.parameters.default": require("./es6/parameters.default"), "es6.tailCall": require("./es6/tail-call"),
"es6.parameters.rest": require("./es6/parameters.rest"),
"es6.destructuring": require("./es6/destructuring"),
regenerator: require("./other/regenerator"), regenerator: require("./other/regenerator"),
@@ -79,11 +86,13 @@ module.exports = {
"spec.typeofSymbol": require("./spec/typeof-symbol"), "spec.typeofSymbol": require("./spec/typeof-symbol"),
"spec.undefinedToVoid": require("./spec/undefined-to-void"), "spec.undefinedToVoid": require("./spec/undefined-to-void"),
"minification.propertyLiterals": require("./minification/property-literals"), "es3.propertyLiterals": require("./es3/property-literals"),
"minification.memberExpressionLiterals": require("./minification/member-expression-literals"), "es3.memberExpressionLiterals": require("./es3/member-expression-literals"),
"minification.removeDebugger": require("./minification/remove-debugger"), "minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsoleCalls": require("./minification/remove-console-calls"), "minification.removeConsoleCalls": require("./minification/remove-console-calls"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"), "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

@@ -3,12 +3,12 @@
var t = require("../../../types"); var t = require("../../../types");
var functionChildrenVisitor = { var functionChildrenVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isFunction(node) && !node._aliasFunction) { if (t.isFunction(node) && !node._aliasFunction) {
return context.skip(); return this.skip();
} }
if (node._ignoreAliasFunctions) return context.skip(); if (node._ignoreAliasFunctions) return this.skip();
var getId; var getId;
@@ -25,11 +25,11 @@ var functionChildrenVisitor = {
}; };
var functionVisitor = { var functionVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (!node._aliasFunction) { if (!node._aliasFunction) {
if (t.isFunction(node)) { if (t.isFunction(node)) {
// stop traversal of this node as it'll be hit again by this transformer // stop traversal of this node as it'll be hit again by this transformer
return context.skip(); return this.skip();
} else { } else {
return; return;
} }
@@ -38,7 +38,7 @@ var functionVisitor = {
// traverse all child nodes of this function and find `arguments` and `this` // traverse all child nodes of this function and find `arguments` and `this`
scope.traverse(node, functionChildrenVisitor, state); scope.traverse(node, functionChildrenVisitor, state);
return context.skip(); return this.skip();
} }
}; };

View File

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

View File

@@ -2,16 +2,16 @@
var useStrict = require("../../helpers/use-strict"); var useStrict = require("../../helpers/use-strict");
exports.ast = { exports.post = function (file) {
exit: function (ast, file) { if (!file.transformers["es6.modules"].canRun()) return;
if (!file.transformers["es6.modules"].canRun()) return;
useStrict.wrap(ast.program, function () { var program = file.ast.program;
ast.program.body = file.dynamicImports.concat(ast.program.body);
});
if (file.moduleFormatter.transform) { useStrict.wrap(program, function () {
file.moduleFormatter.transform(ast); program.body = file.dynamicImports.concat(program.body);
} });
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program);
} }
}; };

View File

@@ -8,7 +8,7 @@
var t = require("../../../types"); var t = require("../../../types");
var resolveModuleSource = function (node, parent, scope, context, file) { var resolveModuleSource = function (node, parent, scope, file) {
var resolveModuleSource = file.opts.resolveModuleSource; var resolveModuleSource = file.opts.resolveModuleSource;
if (node.source && resolveModuleSource) { if (node.source && resolveModuleSource) {
node.source.value = resolveModuleSource(node.source.value); node.source.value = resolveModuleSource(node.source.value);

View File

@@ -2,7 +2,7 @@ var t = require("../../../types");
exports.optional = true; exports.optional = true;
exports.ExpressionStatement = function (node, parent, scope, context) { exports.ExpressionStatement = function (node) {
// remove consequenceless expressions such as local variables and literals // remove consequenceless expressions such as local variables and literals
// //
// var foo = true; foo; -> var foo = true; // var foo = true; foo; -> var foo = true;
@@ -11,12 +11,12 @@ exports.ExpressionStatement = function (node, parent, scope, context) {
var expr = node.expression; var expr = node.expression;
if (t.isLiteral(expr) || (t.isIdentifier(node) && t.hasBinding(node.name))) { if (t.isLiteral(expr) || (t.isIdentifier(node) && t.hasBinding(node.name))) {
context.remove(); this.remove();
} }
}; };
exports.IfStatement = { exports.IfStatement = {
exit: function (node, parent, scope, context) { exit: function (node) {
// todo: in scenarios where we can just return the consequent or // todo: in scenarios where we can just return the consequent or
// alternate we should drop the block statement if it contains no // alternate we should drop the block statement if it contains no
// block scoped variables // block scoped variables
@@ -25,7 +25,7 @@ exports.IfStatement = {
var alternate = node.alternate; var alternate = node.alternate;
var test = node.test; var test = node.test;
// we can check if a test will be truthy 100% and if so we can inline // we can check if a test will be truthy 100% and if so then we can inline
// the consequent and completely ignore the alternate // the consequent and completely ignore the alternate
// //
// if (true) { foo; } -> { foo; } // if (true) { foo; } -> { foo; }
@@ -36,8 +36,8 @@ exports.IfStatement = {
return alternate; return alternate;
} }
// we can check if a test will be falsy 100% and if so we can inline // we can check if a test will be falsy 100% and if so we can inline the
// the alternate if there is one and completely remove the consequent // alternate if there is one and completely remove the consequent
// //
// if ("") { bar; } else { foo; } -> { foo; } // if ("") { bar; } else { foo; } -> { foo; }
// if ("") { bar; } -> // if ("") { bar; } ->
@@ -47,7 +47,7 @@ exports.IfStatement = {
if (alternate) { if (alternate) {
return alternate; return alternate;
} else { } else {
return context.remove(); return this.remove();
} }
} }
@@ -60,11 +60,10 @@ exports.IfStatement = {
alternate = node.alternate = null; alternate = node.alternate = null;
} }
// turn alternate blocks into a consequent and flip the test if the // if the consequent block is empty turn alternate blocks into a consequent
// consequent block is empty // and flip the test
// //
// if (foo) {} else { bar; } // if (foo) {} else { bar; } -> if (!foo) { bar; }
// if (!foo) { bar; }
// //
if (t.blockStatement(consequent) && !consequent.body.length && if (t.blockStatement(consequent) && !consequent.body.length &&

View File

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

View File

@@ -2,8 +2,8 @@ var t = require("../../../types");
exports.optional = true; exports.optional = true;
exports.ExpressionStatement = function (node, parent, scope, context) { exports.ExpressionStatement = function (node) {
if (t.isIdentifier(node.expression, { name: "debugger" })) { if (t.isIdentifier(node.expression, { name: "debugger" })) {
context.remove(); this.remove();
} }
}; };

View File

@@ -5,6 +5,7 @@ exports.optional = true;
exports.Scope = function () { exports.Scope = function () {
// todo: get all binding identifiers, generate compact names // todo: get all binding identifiers, generate compact names
// that wont collide and then call the remap identifier helper // that wont collide and then call the remap identifier helper
// this transformer **has** to be ran last as it will absolutley // this transformer **has** to be ran last as it will absolutley
// destroy the scope tree // destroy the scope tree
}; };

View File

@@ -7,7 +7,7 @@ exports.optional = true;
exports.manipulateOptions = bluebirdCoroutines.manipulateOptions; exports.manipulateOptions = bluebirdCoroutines.manipulateOptions;
exports.Function = function (node, parent, scope, context, file) { exports.Function = function (node, parent, scope, file) {
if (!node.async || node.generator) return; if (!node.async || node.generator) return;
return remapAsyncToGenerator(node, file.addHelper("async-to-generator"), scope); return remapAsyncToGenerator(node, file.addHelper("async-to-generator"), scope);

View File

@@ -10,7 +10,7 @@ exports.manipulateOptions = function (opts) {
exports.optional = true; exports.optional = true;
exports.Function = function (node, parent, scope, context, file) { exports.Function = function (node, parent, scope, file) {
if (!node.async || node.generator) return; if (!node.async || node.generator) return;
return remapAsyncToGenerator( return remapAsyncToGenerator(

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"; "use strict";
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser) var react = require("../../helpers/react");
// https://github.com/RReverser/jsx-transpiler var t = require("../../../types");
// jsx require("../../helpers/build-react-transformer")(exports, {
pre: function (state) {
var isString = require("lodash/lang/isString"); var tagName = state.tagName;
var esutils = require("esutils"); var args = state.args;
var react = require("../../helpers/react"); if (react.isCompatTag(tagName)) {
var t = require("../../../types"); args.push(t.literal(tagName));
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, context, 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, context, 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);
} else { } else {
attribs = t.literal(null); args.push(state.tagExpr);
} }
},
args.push(attribs); post: function (state) {
state.callee = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
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);
} }
}; });
/**
* 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, context, 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

@@ -7,10 +7,9 @@ exports.check = function (node) {
return t.isFunction(node) && (node.async || node.generator); return t.isFunction(node) && (node.async || node.generator);
}; };
exports.ast = { exports.Program = {
before: function (ast, file) { enter: function (ast) {
regenerator.transform(ast, { regenerator.transform(ast);
includeRuntime: file.opts.includeRegenerator && "if used" this.stop();
});
} }
}; };

View File

@@ -20,7 +20,7 @@ var ALIASABLE_CONSTRUCTORS = [
]; ];
var astVisitor = { var astVisitor = {
enter: function (node, parent, scope, context, file) { enter: function (node, parent, scope, file) {
var prop; var prop;
if (t.isMemberExpression(node) && t.isReferenced(node, parent)) { if (t.isMemberExpression(node) && t.isReferenced(node, parent)) {
@@ -31,7 +31,7 @@ var astVisitor = {
if (!t.isReferenced(obj, node)) return; 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.getBinding(obj.name)) {
context.skip(); this.skip();
return t.prependToMemberExpression(node, file.get("coreIdentifier")); 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) && contains(ALIASABLE_CONSTRUCTORS, node.name) && !scope.getBinding(node.name)) {
@@ -64,27 +64,25 @@ exports.manipulateOptions = function (opts) {
if (opts.whitelist.length) opts.whitelist.push("es6.modules"); if (opts.whitelist.length) opts.whitelist.push("es6.modules");
}; };
exports.ast = { exports.post = function (file) {
enter: function (ast, file) { file.scope.traverse(file.ast, astVisitor, file);
file.setDynamic("runtimeIdentifier", function () {
return file.addImport("6to5-runtime/helpers", "to5Helpers");
});
file.setDynamic("coreIdentifier", function () {
return file.addImport("6to5-runtime/core-js", "core");
});
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport("6to5-runtime/regenerator", "regeneratorRuntime");
});
},
after: function (ast, file) {
file.scope.traverse(ast, astVisitor, file);
}
}; };
exports.Identifier = function (node, parent, scope, context, file) { exports.pre = function (file) {
file.setDynamic("runtimeIdentifier", function () {
return file.addImport("6to5-runtime/helpers", "to5Helpers");
});
file.setDynamic("coreIdentifier", function () {
return file.addImport("6to5-runtime/core-js", "core");
});
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport("6to5-runtime/regenerator", "regeneratorRuntime");
});
};
exports.Identifier = function (node, parent, scope, file) {
if (node.name === "regeneratorRuntime" && t.isReferenced(node, parent)) { if (node.name === "regeneratorRuntime" && t.isReferenced(node, parent)) {
return file.get("regeneratorIdentifier"); return file.get("regeneratorIdentifier");
} }

View File

@@ -3,17 +3,16 @@
var useStrict = require("../../helpers/use-strict"); var useStrict = require("../../helpers/use-strict");
var t = require("../../../types"); var t = require("../../../types");
exports.ast = { exports.post = function (file) {
exit: function (ast) { var program = file.ast.program;
if (!useStrict.has(ast.program)) { if (!useStrict.has(program)) {
ast.program.body.unshift(t.expressionStatement(t.literal("use strict"))); program.body.unshift(t.expressionStatement(t.literal("use strict")));
}
} }
}; };
exports.FunctionDeclaration = exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, scope, context) { exports.FunctionExpression = function () {
context.skip(); this.skip();
}; };
exports.ThisExpression = function () { exports.ThisExpression = function () {

View File

@@ -26,7 +26,7 @@ exports.BindMemberExpression = function (node, parent, scope) {
} }
}; };
exports.BindFunctionExpression = function (node, parent, scope, context, file) { exports.BindFunctionExpression = function (node, parent, scope, file) {
var buildCall = function (args) { var buildCall = function (args) {
var param = scope.generateUidIdentifier("val"); var param = scope.generateUidIdentifier("val");
return t.functionExpression(null, [param], t.blockStatement([ return t.functionExpression(null, [param], t.blockStatement([

View File

@@ -5,8 +5,8 @@ var t = require("../../../types");
exports.playground = true; exports.playground = true;
var visitor = { var visitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isFunction(node)) return; if (t.isFunction(node)) return this.skip();
if (t.isReturnStatement(node) && node.argument) { if (t.isReturnStatement(node) && node.argument) {
node.argument = t.memberExpression(t.callExpression(state.file.addHelper("define-property"), [ node.argument = t.memberExpression(t.callExpression(state.file.addHelper("define-property"), [
@@ -19,10 +19,9 @@ var visitor = {
}; };
exports.Property = exports.Property =
exports.MethodDefinition = function (node, parent, scope, context, file) { exports.MethodDefinition = function (node, parent, scope, file) {
if (node.kind !== "memo") return; if (node.kind !== "memo") return;
node.kind = "get"; node.kind = "get";
file.checkNode(node, scope);
var value = node.value; var value = node.value;
t.ensureBlock(value); t.ensureBlock(value);
@@ -39,4 +38,6 @@ exports.MethodDefinition = function (node, parent, scope, context, file) {
}; };
scope.traverse(value, visitor, state); scope.traverse(value, visitor, state);
return node;
}; };

View File

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

View File

@@ -19,7 +19,7 @@ var buildDefaultsCallExpression = function (expr, ref, file) {
exports.optional = true; exports.optional = true;
exports.secondPass = true; exports.secondPass = true;
exports.AssignmentExpression = function (node, parent, scope, context, file) { exports.AssignmentExpression = function (node, parent, scope, file) {
if (!isProtoAssignmentExpression(node)) return; if (!isProtoAssignmentExpression(node)) return;
var nodes = []; var nodes = [];
@@ -33,7 +33,7 @@ exports.AssignmentExpression = function (node, parent, scope, context, file) {
return t.toSequenceExpression(nodes); return t.toSequenceExpression(nodes);
}; };
exports.ExpressionStatement = function (node, parent, scope, context, file) { exports.ExpressionStatement = function (node, parent, scope, file) {
var expr = node.expression; var expr = node.expression;
if (!t.isAssignmentExpression(expr, { operator: "=" })) return; if (!t.isAssignmentExpression(expr, { operator: "=" })) return;
@@ -42,7 +42,7 @@ exports.ExpressionStatement = function (node, parent, scope, context, file) {
} }
}; };
exports.ObjectExpression = function (node, parent, scope, context, file) { exports.ObjectExpression = function (node, parent, scope, file) {
var proto; var proto;
for (var i = 0; i < node.properties.length; i++) { for (var i = 0; i < node.properties.length; i++) {

View File

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

View File

@@ -2,8 +2,10 @@
var t = require("../../../types"); var t = require("../../../types");
exports.check = t.isFor;
exports.ForInStatement = exports.ForInStatement =
exports.ForOfStatement = function (node, parent, scope, context, file) { exports.ForOfStatement = function (node, parent, scope, file) {
var left = node.left; var left = node.left;
if (t.isVariableDeclaration(left)) { if (t.isVariableDeclaration(left)) {
var declar = left.declarations[0]; var declar = left.declarations[0];

View File

@@ -1,7 +1,11 @@
"use strict"; "use strict";
exports.check = function (node) {
return node.kind === "set";
};
exports.MethodDefinition = exports.MethodDefinition =
exports.Property = function (node, parent, scope, context, file) { exports.Property = function (node, parent, scope, file) {
if (node.kind === "set" && node.value.params.length !== 1) { 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, "Setters must have only one parameter");
} }

View File

@@ -5,7 +5,7 @@ var t = require("../../../types");
exports.optional = true; exports.optional = true;
exports.Identifier = function (node, parent, scope, context, file) { exports.Identifier = function (node, parent, scope, file) {
if (!t.isReferenced(node, parent)) return; if (!t.isReferenced(node, parent)) return;
if (scope.hasBinding(node.name)) return; if (scope.hasBinding(node.name)) return;

View File

@@ -0,0 +1,56 @@
"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, parentPath) {
this.shouldFlatten = false;
this.parentPath = parentPath;
this.scope = scope;
this.state = state;
this.opts = opts;
}
TraversalContext.prototype.flatten = function () {
this.shouldFlatten = true;
};
TraversalContext.prototype.visitNode = function (node, obj, key) {
var iteration = new TraversalPath(this, node, obj, key);
return iteration.visit();
};
TraversalContext.prototype.visit = function (node, key) {
var nodes = node[key];
if (!nodes) return;
if (!Array.isArray(nodes)) {
return this.visitNode(node, node, key);
}
// nothing to traverse!
if (nodes.length === 0) {
return;
}
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] && this.visitNode(node, nodes, i)) {
return true;
}
}
if (this.shouldFlatten) {
node[key] = flatten(node[key]);
if (key === "body") {
// we can safely compact this
node[key] = compact(node[key]);
}
}
};

121
lib/6to5/traversal/index.js Normal file
View File

@@ -0,0 +1,121 @@
"use strict";
module.exports = traverse;
var TraversalContext = require("./context");
var contains = require("lodash/collection/contains");
var t = require("../types");
function traverse(parent, opts, scope, state) {
if (!parent) return;
if (!opts.noScope && !scope) {
if (parent.type !== "Program" && parent.type !== "File") {
throw new Error("Must pass a scope unless traversing a Program/File got a " + parent.type + " node");
}
}
if (!opts) opts = {};
if (!opts.enter) opts.enter = function () { };
if (!opts.exit) opts.exit = function () { };
// array of nodes
if (Array.isArray(parent)) {
for (var i = 0; i < parent.length; i++) {
traverse.node(parent[i], opts, scope, state);
}
} else {
traverse.node(parent, 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, parentPath);
for (var i = 0; i < keys.length; i++) {
if (context.visit(node, keys[i])) {
return;
}
}
};
function clearNode(node) {
node._declarations = null;
node.extendedRange = null;
node._scopeInfo = null;
node.tokens = null;
node.range = null;
node.start = null;
node.end = null;
node.loc = null;
node.raw = null;
if (Array.isArray(node.trailingComments)) {
clearComments(node.trailingComments);
}
if (Array.isArray(node.leadingComments)) {
clearComments(node.leadingComments);
}
}
var clearVisitor = {
noScope: true,
enter: clearNode
};
function clearComments(comments) {
for (var i = 0; i < comments.length; i++) {
clearNode(comments[i]);
}
}
traverse.removeProperties = function (tree) {
clearNode(tree);
traverse(tree, clearVisitor);
return tree;
};
traverse.explode = function (obj) {
for (var type in obj) {
var fns = obj[type];
var aliases = t.FLIPPED_ALIAS_KEYS[type];
if (aliases) {
for (var i = 0; i < aliases.length; i++) {
obj[aliases[i]] = fns;
}
}
}
return obj;
};
function hasBlacklistedType(node, parent, scope, state) {
if (node.type === state.type) {
state.has = true;
this.skip();
}
}
traverse.hasType = function (tree, scope, type, blacklistTypes) {
// the node we're searching in is blacklisted
if (contains(blacklistTypes, tree.type)) return false;
// the type we're looking for is the same as the passed node
if (tree.type === type) return true;
var state = {
has: false,
type: type
};
traverse(tree, {
blacklist: blacklistTypes,
enter: hasBlacklistedType
}, scope, state);
return state.has;
};

156
lib/6to5/traversal/path.js Normal file
View File

@@ -0,0 +1,156 @@
"use strict";
module.exports = TraversalPath;
/* jshint maxparams:7 */
var traverse = require("./index");
var contains = require("lodash/collection/contains");
var Scope = require("./scope");
var t = require("../types");
function TraversalPath(context, parent, obj, key) {
this.shouldRemove = false;
this.shouldSkip = false;
this.shouldStop = false;
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;
}
TraversalPath.prototype.remove = function () {
this.shouldRemove = true;
this.shouldSkip = true;
};
TraversalPath.prototype.skip = function () {
this.shouldSkip = true;
};
TraversalPath.prototype.stop = function () {
this.shouldStop = true;
this.shouldSkip = true;
};
TraversalPath.prototype.flatten = function () {
this.context.flatten();
};
TraversalPath.getScope = function (node, parent, scope) {
var ourScope = scope;
// we're entering a new scope so let's construct it!
if (t.isScope(node)) {
ourScope = new Scope(node, parent, scope);
}
return ourScope;
};
TraversalPath.prototype.maybeRemove = function () {
if (this.shouldRemove) {
this.setNode(null);
this.flatten();
}
};
TraversalPath.prototype.setNode = function (val) {
return this.obj[this.key] = val;
};
TraversalPath.prototype.getNode = function () {
return this.obj[this.key];
};
TraversalPath.prototype.replaceNode = function (replacement) {
var isArray = Array.isArray(replacement);
// inherit comments from original node to the first replacement node
var inheritTo = replacement;
if (isArray) inheritTo = replacement[0];
if (inheritTo) t.inheritsComments(inheritTo, this.getNode());
// replace the node
this.setNode(replacement);
var file = this.scope && this.scope.file;
if (file) {
if (isArray) {
for (var i = 0; i < replacement.length; i++) {
file.checkNode(replacement[i], this.scope);
}
} else {
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)) {
t.ensureBlock(this.obj, this.key);
}
this.flatten();
}
};
TraversalPath.prototype.call = function (key) {
var node = this.getNode();
if (!node) return;
var opts = this.opts;
var fn = opts[key];
if (opts[node.type]) fn = opts[node.type][key] || fn;
var replacement = fn.call(this, node, this.parent, this.scope, this.state);
if (replacement) {
this.replaceNode(replacement);
node = replacement;
}
this.maybeRemove();
return node;
};
TraversalPath.prototype.visit = function () {
var opts = this.opts;
var node = this.getNode();
// type is blacklisted
if (opts.blacklist && opts.blacklist.indexOf(node.type) > -1) {
return;
}
this.call("enter");
if (this.shouldSkip) {
return this.shouldStop;
}
node = this.getNode();
if (Array.isArray(node)) {
// 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, this);
}
} else {
traverse.node(node, opts, this.scope, this.state, this);
this.call("exit");
}
return this.shouldStop;
};

View File

@@ -148,16 +148,15 @@ Scope.prototype.inferType = function (node) {
} }
if (t.isLiteral(target) || t.isArrayExpression(target) || t.isObjectExpression(target)) { if (t.isLiteral(target) || t.isArrayExpression(target) || t.isObjectExpression(target)) {
// todo: possibly call some helper that will resolve these to a type annotation // todo: possibly call some helper that will resolve these to a flow type annotation
} }
if (t.isCallExpression(target)) { if (t.isCallExpression(target)) {
// todo: need to resolve this to a return type // todo: resolve this to a return type
} }
if (t.isMemberExpression(target)) { if (t.isMemberExpression(target)) {
// todo: crawl this and find the correct type, bail on anything that we cannot // todo: crawl this and find the correct type, bail on anything that we cannot possibly be 100% confident on
// possibly be 100% confident on
} }
if (t.isIdentifier(target)) { if (t.isIdentifier(target)) {
@@ -214,7 +213,7 @@ Scope.prototype.registerVariableDeclaration = function (declar) {
}; };
var functionVariableVisitor = { var functionVariableVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isFor(node)) { if (t.isFor(node)) {
each(t.FOR_INIT_KEYS, function (key) { each(t.FOR_INIT_KEYS, function (key) {
var declar = node[key]; var declar = node[key];
@@ -224,7 +223,7 @@ var functionVariableVisitor = {
// this block is a function so we'll stop since none of the variables // this block is a function so we'll stop since none of the variables
// declared within are accessible // declared within are accessible
if (t.isFunction(node)) return context.skip(); if (t.isFunction(node)) return this.skip();
// function identifier doesn't belong to this scope // function identifier doesn't belong to this scope
if (state.blockId && node === state.blockId) return; if (state.blockId && node === state.blockId) return;
@@ -241,7 +240,7 @@ var functionVariableVisitor = {
}; };
var programReferenceVisitor = { var programReferenceVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isReferencedIdentifier(node, parent) && !scope.hasReference(node.name)) { if (t.isReferencedIdentifier(node, parent) && !scope.hasReference(node.name)) {
state.register(node, true); state.register(node, true);
} }
@@ -249,11 +248,11 @@ var programReferenceVisitor = {
}; };
var blockVariableVisitor = { var blockVariableVisitor = {
enter: function (node, parent, scope, context, state) { enter: function (node, parent, scope, state) {
if (t.isBlockScoped(node)) { if (t.isBlockScoped(node)) {
state.register(node); state.register(node);
} else if (t.isScope(node)) { } else if (t.isScope(node)) {
context.skip(); this.skip();
} }
} }
}; };
@@ -287,9 +286,11 @@ Scope.prototype.crawl = function () {
// //
if (parent && t.isBlockStatement(block) && t.isLoop(parent.block, { body: block })) { if (parent && t.isBlockStatement(block)) {
// delegate let bindings to the parent loop if (t.isLoop(parent.block, { body: block }) ||
return; t.isFunction(parent.block, { body: block })) {
return;
}
} }
// ForStatement - left, init // ForStatement - left, init
@@ -305,7 +306,24 @@ Scope.prototype.crawl = function () {
} }
} }
// Program, BlockStatement - let variables // FunctionExpression - id
if (t.isFunctionExpression(block) && block.id) {
if (!t.isProperty(this.parentBlock, { method: true })) {
this.register(block.id);
}
}
// Function - params, rest
if (t.isFunction(block)) {
for (i = 0; i < block.params.length; i++) {
this.register(block.params[i]);
}
this.traverse(block.body, blockVariableVisitor, this);
}
// Program, BlockStatement, Function - let variables
if (t.isBlockStatement(block) || t.isProgram(block)) { if (t.isBlockStatement(block) || t.isProgram(block)) {
this.traverse(block, blockVariableVisitor, this); this.traverse(block, blockVariableVisitor, this);
@@ -323,14 +341,6 @@ Scope.prototype.crawl = function () {
this.register(block); this.register(block);
} }
// Function - params, rest
if (t.isFunction(block)) {
for (i = 0; i < block.params.length; i++) {
this.register(block.params[i]);
}
}
// Program, Function - var variables // Program, Function - var variables
if (t.isProgram(block) || t.isFunction(block)) { if (t.isProgram(block) || t.isFunction(block)) {
@@ -340,14 +350,6 @@ Scope.prototype.crawl = function () {
}); });
} }
if (t.isFunctionExpression(block) && block.id) {
if (!t.isProperty(this.parentBlock, { method: true })) {
// SpiderMonkey AST doesn't use MethodDefinition here when it probably
// should since they should be semantically the same?
this.register(block.id);
}
}
// Program // Program
if (t.isProgram(block)) { if (t.isProgram(block)) {
@@ -403,7 +405,7 @@ Scope.prototype.addDeclarationToFunctionScope = function (kind, node) {
/** /**
* Walk up the scope tree until we hit either a Function or reach the * Walk up the scope tree until we hit either a Function or reach the
* very top at hit Program. * very top and hit Program.
*/ */
Scope.prototype.getFunctionParent = function () { Scope.prototype.getFunctionParent = function () {
@@ -491,6 +493,10 @@ each({
binding: "Binding", binding: "Binding",
type: "Type" type: "Type"
}, function (title, type) { }, function (title, type) {
Scope.prototype[type + "Equals"] = function (id, node) {
return this["get" + title](id) === node;
};
each([ each([
"get", "get",
"has", "has",

View File

@@ -1,274 +0,0 @@
"use strict";
module.exports = traverse;
/* jshint maxparams:7 */
var Scope = require("./scope");
var t = require("../types");
var contains = require("lodash/collection/contains");
var flatten = require("lodash/array/flatten");
var compact = require("lodash/array/compact");
function TraversalContext(scope) {
this.shouldFlatten = false;
this.shouldRemove = false;
this.shouldSkip = false;
this.shouldStop = false;
this.scope = scope;
}
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.maybeRemove = function (obj, key) {
if (this.shouldRemove) {
obj[key] = null;
this.flatten();
}
};
TraversalContext.prototype.replaceNode = function (obj, key, node, replacement, scope) {
var isArray = Array.isArray(replacement);
// inherit comments from original node to the first replacement node
var inheritTo = replacement;
if (isArray) inheritTo = replacement[0];
if (inheritTo) t.inheritsComments(inheritTo, node);
// replace the node
obj[key] = replacement;
var file = this.scope && this.scope.file;
if (file) {
if (isArray) {
for (var i = 0; i < replacement.length; i++) {
file.checkNode(replacement[i], scope);
}
} else {
file.checkNode(replacement, 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 && contains(t.STATEMENT_OR_BLOCK_KEYS, key) && !t.isBlockStatement(obj)) {
t.ensureBlock(obj, key);
}
if (isArray) {
this.flatten();
}
};
TraversalContext.prototype.call = function (fn, obj, key, node, parent, scope, state) {
var replacement = fn(node, parent, scope, this, state);
if (replacement) {
this.replaceNode(obj, key, node, replacement, scope);
node = replacement;
}
this.maybeRemove(obj, key);
return node;
};
TraversalContext.prototype.visitNode = function (obj, key, opts, scope, parent, state) {
this.reset();
var node = obj[key];
// type is blacklisted
if (opts.blacklist && opts.blacklist.indexOf(node.type) > -1) {
return;
}
var ourScope = scope;
// we're entering a new scope so let's construct it!
if (!opts.noScope && t.isScope(node)) {
ourScope = new Scope(node, parent, scope);
}
node = this.call(opts.enter, obj, key, node, parent, ourScope, state);
if (this.shouldSkip) {
return this.shouldStop;
}
if (Array.isArray(node)) {
// 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++) {
traverseNode(node[i], opts, ourScope, state);
}
} else {
traverseNode(node, opts, ourScope, state);
this.call(opts.exit, obj, key, node, parent, ourScope, state);
}
return this.shouldStop;
};
TraversalContext.prototype.visit = function (node, key, opts, scope, state) {
var nodes = node[key];
if (!nodes) return;
if (!Array.isArray(nodes)) {
return this.visitNode(node, key, opts, scope, node, state);
}
if (nodes.length === 0) {
return;
}
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] && this.visitNode(nodes, i, opts, scope, node, state)) {
return true;
}
}
if (this.shouldFlatten) {
node[key] = flatten(node[key]);
if (key === "body") {
// we can safely compact this
node[key] = compact(node[key]);
}
}
};
function traverseNode(node, opts, scope, state) {
var keys = t.VISITOR_KEYS[node.type];
if (!keys) return;
var context = new TraversalContext(scope);
for (var i = 0; i < keys.length; i++) {
if (context.visit(node, keys[i], opts, scope, state)) {
return;
}
}
}
function traverse(parent, opts, scope, state) {
if (!parent) return;
if (!opts.noScope && !scope) {
if (parent.type !== "Program" && parent.type !== "File") {
throw new Error("Must pass a scope unless traversing a Program/File got a " + parent.type + " node");
}
}
if (!opts) opts = {};
if (!opts.enter) opts.enter = function () { };
if (!opts.exit) opts.exit = function () { };
// array of nodes
if (Array.isArray(parent)) {
for (var i = 0; i < parent.length; i++) {
traverseNode(parent[i], opts, scope, state);
}
} else {
traverseNode(parent, opts, scope, state);
}
}
function clearNode(node) {
node._declarations = null;
node.extendedRange = null;
node._scopeInfo = null;
node.tokens = null;
node.range = null;
node.start = null;
node.end = null;
node.loc = null;
node.raw = null;
if (Array.isArray(node.trailingComments)) {
clearComments(node.trailingComments);
}
if (Array.isArray(node.leadingComments)) {
clearComments(node.leadingComments);
}
}
var clearVisitor = {
noScope: true,
enter: clearNode
};
function clearComments(comments) {
for (var i = 0; i < comments.length; i++) {
clearNode(comments[i]);
}
}
traverse.removeProperties = function (tree) {
clearNode(tree);
traverse(tree, clearVisitor);
return tree;
};
traverse.explode = function (obj) {
for (var type in obj) {
var fns = obj[type];
var aliases = t.FLIPPED_ALIAS_KEYS[type];
if (aliases) {
for (var i = 0; i < aliases.length; i++) {
obj[aliases[i]] = fns;
}
}
}
return obj;
};
function hasBlacklistedType(node, parent, scope, context, state) {
if (node.type === state.type) {
state.has = true;
context.skip();
}
}
traverse.hasType = function (tree, scope, type, blacklistTypes) {
// the node we're searching in is blacklisted
if (contains(blacklistTypes, tree.type)) return false;
// the type we're looking for is the same as the passed node
if (tree.type === type) return true;
var state = {
has: false,
type: type
};
traverse(tree, {
blacklist: blacklistTypes,
enter: hasBlacklistedType
}, scope, state);
return state.has;
};

View File

@@ -1,14 +1,14 @@
"use strict"; "use strict";
var toFastProperties = require("../helpers/to-fast-properties"); 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 esutils = require("esutils");
var object = require("../helpers/object"); var object = require("../helpers/object");
var Node = require("./node"); var Node = require("./node");
var each = require("lodash/collection/each"); var each = require("lodash/collection/each");
var uniq = require("lodash/array/uniq"); var uniq = require("lodash/array/uniq");
var compact = require("lodash/array/compact");
var defaults = require("lodash/object/defaults");
var isString = require("lodash/lang/isString");
var t = exports; var t = exports;
@@ -340,8 +340,8 @@ t.isReferenced = function (node, parent) {
* @returns {Boolean} * @returns {Boolean}
*/ */
t.isReferencedIdentifier = function (node, parent) { t.isReferencedIdentifier = function (node, parent, opts) {
return t.isIdentifier(node) && t.isReferenced(node, parent); return t.isIdentifier(node, opts) && t.isReferenced(node, parent);
}; };
/** /**
@@ -395,7 +395,7 @@ t.toIdentifier = function (name) {
t.ensureBlock = function (node, key) { t.ensureBlock = function (node, key) {
key = key || "body"; key = key || "body";
node[key] = t.toBlock(node[key], node); return node[key] = t.toBlock(node[key], node);
}; };
/** /**
@@ -690,10 +690,12 @@ t.inheritsComments = function (child, parent) {
*/ */
t.inherits = function (child, parent) { t.inherits = function (child, parent) {
child.range = parent.range; child._declarations = parent._declarations;
child.start = parent.start; child._scopeInfo = parent._scopeInfo;
child.loc = parent.loc; child.range = parent.range;
child.end = parent.end; child.start = parent.start;
child.loc = parent.loc;
child.end = parent.end;
t.inheritsComments(child, parent); t.inheritsComments(child, parent);
return child; return child;
}; };

View File

@@ -2,23 +2,21 @@
require("./patch"); require("./patch");
var estraverse = require("estraverse"); var cloneDeep = require("lodash/lang/cloneDeep");
var codeFrame = require("./helpers/code-frame"); var contains = require("lodash/collection/contains");
var traverse = require("./traverse"); var traverse = require("./traversal");
var debug = require("debug/node");
var acorn = require("acorn-6to5");
var path = require("path");
var util = require("util");
var fs = require("fs");
var t = require("./types");
var each = require("lodash/collection/each");
var isNumber = require("lodash/lang/isNumber"); var isNumber = require("lodash/lang/isNumber");
var isString = require("lodash/lang/isString"); var isString = require("lodash/lang/isString");
var isRegExp = require("lodash/lang/isRegExp"); var isRegExp = require("lodash/lang/isRegExp");
var isEmpty = require("lodash/lang/isEmpty"); var isEmpty = require("lodash/lang/isEmpty");
var cloneDeep = require("lodash/lang/cloneDeep"); var parse = require("./helpers/parse");
var debug = require("debug/node");
var path = require("path");
var util = require("util");
var each = require("lodash/collection/each");
var has = require("lodash/object/has"); var has = require("lodash/object/has");
var contains = require("lodash/collection/contains"); var fs = require("fs");
var t = require("./types");
exports.inherits = util.inherits; exports.inherits = util.inherits;
@@ -81,7 +79,7 @@ exports.sourceMapToComment = function (map) {
}; };
var templateVisitor = { var templateVisitor = {
enter: function (node, parent, scope, context, nodes) { enter: function (node, parent, scope, nodes) {
if (t.isIdentifier(node) && has(nodes, node.name)) { if (t.isIdentifier(node) && has(nodes, node.name)) {
return nodes[node.name]; return nodes[node.name];
} }
@@ -123,61 +121,8 @@ exports.repeat = function (width, cha) {
return result; return result;
}; };
exports.normalizeAst = function (ast, comments, tokens) {
if (ast && ast.type === "Program") {
return t.file(ast, comments || [], tokens || []);
} else {
throw new Error("Not a valid ast?");
}
};
exports.parse = function (opts, code, callback) {
try {
var comments = [];
var tokens = [];
var ast = acorn.parse(code, {
allowImportExportEverywhere: opts.allowImportExportEverywhere,
allowReturnOutsideFunction: !opts._anal,
ecmaVersion: opts.experimental ? 7 : 6,
playground: opts.playground,
strictMode: opts.strictMode,
onComment: comments,
locations: true,
onToken: tokens,
ranges: true
});
estraverse.attachComments(ast, comments, tokens);
ast = exports.normalizeAst(ast, comments, tokens);
if (callback) {
return callback(ast);
} else {
return ast;
}
} catch (err) {
if (!err._6to5) {
err._6to5 = true;
var message = opts.filename + ": " + err.message;
var loc = err.loc;
if (loc) {
var frame = codeFrame(code, loc.line, loc.column + 1);
message += frame;
}
if (err.stack) err.stack = err.stack.replace(err.message, message);
err.message = message;
}
throw err;
}
};
exports.parseTemplate = function (loc, code) { exports.parseTemplate = function (loc, code) {
var ast = exports.parse({ filename: loc }, code).program; var ast = parse({ filename: loc }, code).program;
return traverse.removeProperties(ast); return traverse.removeProperties(ast);
}; };

View File

@@ -1,22 +1,21 @@
{ {
"name": "6to5", "name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps", "description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "3.3.12", "version": "3.5.1",
"author": "Sebastian McKenzie <sebmck@gmail.com>", "author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://6to5.org/", "homepage": "https://6to5.org/",
"repository": "6to5/6to5", "repository": "6to5/6to5",
"preferGlobal": true, "preferGlobal": true,
"main": "lib/6to5/index.js", "main": "lib/6to5/api/node.js",
"browser": {
"./lib/6to5/api/register/node.js": "./lib/6to5/api/register/browser.js"
},
"bin": { "bin": {
"6to5": "./bin/6to5/index.js", "6to5": "./bin/6to5/index.js",
"6to5-minify": "./bin/6to5-minify", "6to5-minify": "./bin/6to5-minify",
"6to5-node": "./bin/6to5-node", "6to5-node": "./bin/6to5-node",
"6to5-runtime": "./bin/6to5-runtime" "6to5-runtime": "./bin/6to5-runtime"
}, },
"browser": {
"./lib/6to5/index.js": "./lib/6to5/browser.js",
"./lib/6to5/register.js": "./lib/6to5/register-browser.js"
},
"keywords": [ "keywords": [
"harmony", "harmony",
"classes", "classes",
@@ -34,7 +33,7 @@
"test": "make test" "test": "make test"
}, },
"dependencies": { "dependencies": {
"acorn-6to5": "0.11.1-25", "acorn-6to5": "0.11.1-28",
"ast-types": "~0.6.1", "ast-types": "~0.6.1",
"chalk": "^0.5.1", "chalk": "^0.5.1",
"chokidar": "0.12.6", "chokidar": "0.12.6",

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", "name": "6to5-runtime",
"description": "6to5 selfContained runtime", "description": "6to5 selfContained runtime",
"version": "3.3.11", "version": "3.5.0",
"repository": "6to5/6to5", "repository": "6to5/6to5",
"author": "Sebastian McKenzie <sebmck@gmail.com>" "author": "Sebastian McKenzie <sebmck@gmail.com>"
} }

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