Compare commits

..

310 Commits

Author SHA1 Message Date
Sebastian McKenzie
c6a7a9c401 v1.11.10 2014-11-11 09:48:28 +11:00
Sebastian McKenzie
608df54b02 bump acorn-6to5 version to one that supports async/await - closes #134 2014-11-11 09:47:29 +11:00
Sebastian McKenzie
2ac83ec95b v1.11.9 2014-11-11 08:07:29 +11:00
Sebastian McKenzie
e4596f638d only check string literals in property-literals transformer 2014-11-11 08:06:31 +11:00
Sebastian McKenzie
1425af9b2a v1.11.8 2014-11-11 07:51:43 +11:00
Sebastian McKenzie
9351c6470f bump regenerator version 2014-11-11 07:50:07 +11:00
Sebastian McKenzie
7b8a50509a v1.11.7 2014-11-11 01:07:20 +11:00
Sebastian McKenzie
1400dee0c1 delegate code and opts assurance to File 2014-11-11 01:06:29 +11:00
Sebastian McKenzie
9e2fc6db9c clone options - sindresorhus/grunt-6to5#7 2014-11-11 01:04:39 +11:00
Sebastian McKenzie
aef5b89492 fix appveyor badge 2014-11-10 21:12:30 +11:00
Sebastian McKenzie
e0bf6f698e add appveyor badge to readme 2014-11-10 21:09:09 +11:00
Sebastian McKenzie
1ac459a05d better appveyor make test 2014-11-10 21:09:04 +11:00
Sebastian McKenzie
1b49835b27 v1.11.6 2014-11-10 16:46:40 +11:00
Sebastian McKenzie
db7b6a4972 fix canCompile in readdirFilter in bin/6to5 util 2014-11-10 16:45:30 +11:00
Sebastian McKenzie
79045e15c5 remove second canCompile declaration 2014-11-10 16:42:04 +11:00
Sebastian McKenzie
b7e6d8f998 add appveyor.yml 2014-11-10 16:31:32 +11:00
Sebastian McKenzie
88c6ce4e48 v1.11.5 2014-11-10 13:10:39 +11:00
Sebastian McKenzie
8c97f1d92e allow constant properties to be modified - fixes #131 2014-11-10 13:09:45 +11:00
Sebastian McKenzie
833e8b091b v1.11.4 2014-11-10 13:02:04 +11:00
Sebastian McKenzie
23ebb23944 add missing util declaration to let scoping transformer 2014-11-10 13:00:52 +11:00
Sebastian McKenzie
778cab33d5 move canCompile method to util 2014-11-10 12:59:24 +11:00
Sebastian McKenzie
5849c6af17 add canCompile method to node api 2014-11-10 12:58:44 +11:00
Sebastian McKenzie
bb0655d8f6 move transformer assignment to new Transformer 2014-11-10 08:21:35 +11:00
Sebastian McKenzie
9977a5f614 change gitter travis hook to always 2014-11-10 08:20:18 +11:00
Sebastian McKenzie
9318d63b5c add let-scoping-return template to let scoping transformer 2014-11-10 08:16:47 +11:00
Sebastian McKenzie
b2ab0dbedc add self-global template to runtime generation 2014-11-10 08:16:38 +11:00
Sebastian McKenzie
e0d3e18865 add allowReturnOutsideFunction to util.parse and make nodes optional in util.template 2014-11-10 08:16:22 +11:00
Sebastian McKenzie
3a3ad4775b add gitter webhook to travis 2014-11-10 08:16:00 +11:00
Sebastian McKenzie
40fdd2a828 dry up types.getIds 2014-11-10 00:51:46 +11:00
Sebastian McKenzie
12f66e852a v1.11.3 2014-11-10 00:22:09 +11:00
Sebastian McKenzie
c61c9aab56 remove invalid ObjectPattern assignment 2014-11-10 00:19:37 +11:00
Sebastian McKenzie
7adc919bb6 remove invalid ObjectPattern destructuring assignment 2014-11-10 00:18:01 +11:00
Sebastian McKenzie
9989b89b92 v1.11.2 2014-11-09 22:27:52 +11:00
Sebastian McKenzie
361ef02a88 support ParenthesizedExpression in types.getIds 2014-11-09 22:26:48 +11:00
Sebastian McKenzie
72369c90a2 update dependencies 2014-11-09 22:11:06 +11:00
Sebastian McKenzie
fa26174d3f better isParenthesizedExpression support for destructuring 2014-11-09 22:10:59 +11:00
Sebastian McKenzie
227d51a556 add AssignmentExpression ObjectPattern test 2014-11-09 22:10:43 +11:00
Sebastian McKenzie
a5f00aa3f6 v1.11.1 2014-11-09 21:39:19 +11:00
Sebastian McKenzie
a47723c66c fix destructuring to support ParanthesizedExpression 2014-11-09 21:37:59 +11:00
Sebastian McKenzie
ab2f652bdf break up let scoping transformer some more 2014-11-09 21:25:14 +11:00
Sebastian McKenzie
5aff7709f7 add back _property-literals transformer that somehow disappeared? 2014-11-09 21:25:05 +11:00
Sebastian McKenzie
06ba731452 traverse: pass opts.scope instead of opts 2014-11-09 21:24:48 +11:00
Sebastian McKenzie
f4c81531ad break up let scoping 2014-11-09 20:31:46 +11:00
Sebastian McKenzie
19b115c76b generator: dry up ForXStatements and *Statements 2014-11-09 20:31:36 +11:00
Sebastian McKenzie
96b08bf7df remove codeclimate from travis 2014-11-09 20:20:21 +11:00
Sebastian McKenzie
8f435d59da change sebmck to new 6to5 org 2014-11-09 20:08:36 +11:00
Sebastian McKenzie
6df03c00a8 Merge pull request #130 from thejameskyle/patch-1
Update logo on README
2014-11-09 20:05:11 +11:00
James Kyle
4ec134814e Update logo on README 2014-11-09 01:04:32 -08:00
Sebastian McKenzie
4fb50cfe20 v1.11.0 2014-11-09 18:45:50 +11:00
Sebastian McKenzie
bac952e036 move runtime to dist/runtime 2014-11-09 18:42:42 +11:00
Sebastian McKenzie
9844540bb0 add npm release-only files to gitignore 2014-11-09 18:38:09 +11:00
Sebastian McKenzie
1a9a60e010 fix polyfill require path 2014-11-09 18:37:57 +11:00
Sebastian McKenzie
e26812e622 remove v8-argv 2014-11-09 18:33:07 +11:00
Sebastian McKenzie
7f306388e4 remove polyfill from root 2014-11-09 18:32:19 +11:00
Sebastian McKenzie
b217453d49 clean up runtime generation declarations 2014-11-09 18:22:26 +11:00
Sebastian McKenzie
463165e0c8 remove unneccesary declaration 2014-11-09 18:22:12 +11:00
Sebastian McKenzie
85d7da9a7c fix comment space column bug 2014-11-09 18:22:04 +11:00
Sebastian McKenzie
48f6c5c649 remove i from mocha globals 2014-11-09 18:21:50 +11:00
Sebastian McKenzie
d1187dde82 fix up tests to work with the new code generator 2014-11-09 18:21:42 +11:00
Sebastian McKenzie
f21a6b36ac peg regenerator-6to5 and acorn-6to5 to a commit 2014-11-09 18:21:29 +11:00
Sebastian McKenzie
407bb9278f uglify polyfill.js and use minified versions in npm release 2014-11-09 16:41:45 +11:00
Sebastian McKenzie
70b3d88455 fix browser polyfill copytext 2014-11-09 16:40:46 +11:00
Sebastian McKenzie
98df094e60 fix cached templates exporting 2014-11-09 16:40:37 +11:00
Sebastian McKenzie
4bae820a5a remove Error.captureStackTrace monkey patch as it's no longer necessary with the latest ast-types 2014-11-09 16:37:47 +11:00
Sebastian McKenzie
4e8afa18da move Polyfill from caveats 2014-11-09 16:34:21 +11:00
Sebastian McKenzie
fbf0c25bbe include polyfill 2014-11-09 16:33:26 +11:00
Sebastian McKenzie
a90da9908c only prepend whitespace to properties if we're the first 2014-11-09 16:28:56 +11:00
Sebastian McKenzie
bd51215316 change Runtime to Optional runtime in README 2014-11-09 16:28:21 +11:00
Sebastian McKenzie
e3c6ee5c88 only use needsParens if the node has changed parent 2014-11-09 16:28:05 +11:00
Sebastian McKenzie
8c40db5658 use Program builder 2014-11-09 16:27:39 +11:00
Sebastian McKenzie
4d59976d82 remove _parent from nodes in traverse.removeProperties 2014-11-09 16:27:31 +11:00
Sebastian McKenzie
83286cccd2 use file node builder and save parents to ast tree 2014-11-09 16:26:52 +11:00
Sebastian McKenzie
de7edcaeb0 finalize ast-types 2014-11-09 16:26:32 +11:00
Sebastian McKenzie
6c8db61b23 switch to regenerator-6to5 2014-11-09 16:26:27 +11:00
Sebastian McKenzie
e3d2748970 fix up react display-name test whitespace 2014-11-09 16:26:12 +11:00
Sebastian McKenzie
fa8c570e77 add File and Program to builder keys 2014-11-09 16:25:55 +11:00
Sebastian McKenzie
677f9805c6 update ast-types and add regenerator-6to5 2014-11-09 16:25:45 +11:00
Sebastian McKenzie
eff5efaf10 fix up patching 2014-11-09 13:42:11 +11:00
Sebastian McKenzie
a909a6febd add CatchClause scope 2014-11-09 13:42:00 +11:00
Sebastian McKenzie
61ee0ef6f6 fix generation comments return-no-argument test whitespace 2014-11-09 12:14:15 +11:00
Sebastian McKenzie
07c15f02e6 update generation test to new api 2014-11-09 12:13:55 +11:00
Sebastian McKenzie
3f4068ae00 fix runtime declaration inclusion copytext 2014-11-09 12:12:23 +11:00
Sebastian McKenzie
dce41bb989 fix up tests 2014-11-09 12:09:59 +11:00
Sebastian McKenzie
896663056d add ParenthesizedExpression builder 2014-11-09 12:09:42 +11:00
Sebastian McKenzie
dfe4ce86e0 fix up templateLiterals blacklist check 2014-11-09 12:09:32 +11:00
Sebastian McKenzie
24f0120e01 add patch so we can patch estraverse and ast-types 2014-11-09 12:09:07 +11:00
Sebastian McKenzie
0108562e88 remove unused key variable 2014-11-09 12:07:57 +11:00
Sebastian McKenzie
e4e4ae5b1d fix up node inheritance 2014-11-09 12:07:46 +11:00
Sebastian McKenzie
ba04377ed8 add types.toIdentifier 2014-11-09 12:07:25 +11:00
Sebastian McKenzie
cd9e289dee traverse: clean up scope getIds building 2014-11-09 12:07:14 +11:00
Sebastian McKenzie
0b86a2fef8 use acorns preserveParens 2014-11-09 12:06:56 +11:00
Sebastian McKenzie
b84cb1828b generator: avoid redundant source map mappings 2014-11-09 12:03:47 +11:00
Sebastian McKenzie
aedc013ab8 generator: rename Whitespace methods 2014-11-09 12:03:31 +11:00
Sebastian McKenzie
ab9cd4e630 add support for an optional runtime - closes #129 2014-11-09 12:02:06 +11:00
Sebastian McKenzie
8ef5148870 fix up modules tests 2014-11-08 12:00:49 +11:00
Sebastian McKenzie
4cb90cb1e0 add precedence to generated node generation 2014-11-08 12:00:26 +11:00
Sebastian McKenzie
d0a33ab933 add inherits option to util.template 2014-11-08 12:00:12 +11:00
Sebastian McKenzie
9ea4431ba3 add alternate shallow equals option to types.is* 2014-11-08 11:59:54 +11:00
Sebastian McKenzie
08580edda8 fix up some tests 2014-11-08 09:17:21 +11:00
Sebastian McKenzie
5c6d57c51b add transformation and generation folders 2014-11-08 09:17:12 +11:00
Sebastian McKenzie
744d1af485 move down propertyLiterals transformer in case classes produces any 2014-11-07 21:10:28 +11:00
Sebastian McKenzie
591b78b159 move property literal check to a separate transformer 2014-11-07 21:01:39 +11:00
Sebastian McKenzie
49ea641314 ignore computed property literals that are valid identifiers 2014-11-07 20:51:01 +11:00
Sebastian McKenzie
37a7c92500 remove duplicate mutator map test 2014-11-07 20:47:15 +11:00
Sebastian McKenzie
35b7b140da fix pointless newlines after left braces 2014-11-07 20:47:09 +11:00
Sebastian McKenzie
159f5217e3 simplify ast transformer code 2014-11-07 20:46:54 +11:00
Sebastian McKenzie
795e38e4f4 add Statement node type 2014-11-07 20:46:43 +11:00
Sebastian McKenzie
2a9af21e93 add modules ignore tests 2014-11-07 20:46:20 +11:00
Sebastian McKenzie
e327e041ab add basic generation tests 2014-11-07 20:46:11 +11:00
Sebastian McKenzie
f8e8cd3979 support SpreadElement in destructuring - fixes #128 2014-11-07 20:46:02 +11:00
Sebastian McKenzie
b3206d94a6 Merge branch 'master' into experimental
Conflicts:
	README.md
	lib/6to5/register.js
2014-11-07 13:54:59 +11:00
Sebastian McKenzie
fcbd315bc1 v1.10.12 2014-11-07 13:53:15 +11:00
Sebastian McKenzie
71646f4ade register: fix ignoreRegex compatibility check 2014-11-07 13:52:13 +11:00
Sebastian McKenzie
56ac964e54 remove newline assurance and add optional Error constructor to File::errorWithNode 2014-11-07 13:51:31 +11:00
Sebastian McKenzie
e5f1eb64b6 clarify default ignore in 6to5/register 2014-11-07 13:41:24 +11:00
Sebastian McKenzie
6145f0a03b v1.10.11 2014-11-07 13:17:41 +11:00
Sebastian McKenzie
54f901f131 require: add missing blacklistTests, implement opts.whitelist and opts.only - closes #125
Conflicts:
	lib/6to5/register.js
2014-11-07 13:16:26 +11:00
Sebastian McKenzie
df70be4ebb clean up and fix tests 2014-11-07 12:33:35 +11:00
Sebastian McKenzie
99ba77bb0b nicer removeProperties for comments 2014-11-07 12:33:22 +11:00
Sebastian McKenzie
346f72be05 ensure files end with a newline 2014-11-07 12:32:48 +11:00
Sebastian McKenzie
c0e6cda071 add UserWhitespacable alias to Property 2014-11-07 12:32:31 +11:00
Sebastian McKenzie
c054ff7bbb better whitespace detection in generator 2014-11-07 12:32:15 +11:00
Sebastian McKenzie
771d3dc8a0 don't inherit from XJSAttribute in jsx transformer because it causes some weird whitespace issues 2014-11-07 12:31:54 +11:00
Sebastian McKenzie
e8d4806b45 combine export declaration assignments into variable declarations 2014-11-07 12:31:31 +11:00
Sebastian McKenzie
469a522300 better whitespace for code generation 2014-11-07 12:31:09 +11:00
Sebastian McKenzie
4068a8bf68 remove exposure to generator from browser build 2014-11-07 12:30:29 +11:00
Sebastian McKenzie
a04513a3c7 faster util.pushMutatorMap aliases 2014-11-07 12:28:52 +11:00
Sebastian McKenzie
6f0ca947a7 remove exposure to generate and util 2014-11-07 12:28:28 +11:00
Sebastian McKenzie
dd62244e10 use v8-argv to make sure node is ran with --harmony for 6to5-node 2014-11-07 12:28:17 +11:00
Sebastian McKenzie
12f68b05c3 better Symbol polyfill existence check because the one es6-symbol uses isn't reliable 2014-11-07 12:27:57 +11:00
Sebastian McKenzie
62fe128132 more support to t.getIds and add t.needsWhitespaceBefore method 2014-11-07 12:26:48 +11:00
Sebastian McKenzie
bf632ca20b more efficient constants collision checking 2014-11-07 12:26:19 +11:00
Sebastian McKenzie
26428cde41 require: add missing blacklistTests, implement opts.whitelist and opts.only - closes #125 2014-11-07 12:25:42 +11:00
Sebastian McKenzie
9bb8a16d93 change polyfill to monkey patch in browser comment 2014-11-05 15:22:17 +11:00
Sebastian McKenzie
44cd044586 add duo and karma plugins to readme - thanks @shuhei and @bd-labs! 2014-11-05 15:22:07 +11:00
Sebastian McKenzie
765899a521 use push instead of _push for first backtick in template literals 2014-11-04 18:37:00 +11:00
Sebastian McKenzie
1d40cac52f let ExpressionStatements handle child comments 2014-11-04 18:34:21 +11:00
Sebastian McKenzie
fb0325a4d8 add support for SpreadElement to types.getIds 2014-11-04 18:33:48 +11:00
Sebastian McKenzie
1df25a633c fix code reference on generate 2014-11-04 18:33:33 +11:00
Sebastian McKenzie
cfbaae456b use _push instead of push on template literals end 2014-11-04 18:32:51 +11:00
Sebastian McKenzie
95ace3220d fix indentation on generation comments tests 2014-11-04 18:32:30 +11:00
Sebastian McKenzie
2e0f3de72c add missing util require 2014-11-04 18:07:28 +11:00
Sebastian McKenzie
732c21d42a clean up some tests 2014-11-04 18:07:19 +11:00
Sebastian McKenzie
a535007a35 clean up let scoping transformer and add lots of comments 2014-11-04 18:06:54 +11:00
Sebastian McKenzie
5ff6f445b2 fix class computed methods 2014-11-04 15:53:36 +11:00
Sebastian McKenzie
d7ae3b506a fix linting errors 2014-11-04 15:53:11 +11:00
Sebastian McKenzie
287cbbb6a1 implement new and improved let scoping - fixes #91, fixes #102, fixes #124 2014-11-04 14:59:44 +11:00
Sebastian McKenzie
d1088583ba default generateUid scope to Program 2014-11-04 12:57:06 +11:00
Sebastian McKenzie
c967cded78 make id optional in t.getIds 2014-11-04 12:56:53 +11:00
Sebastian McKenzie
71d87f5b97 cache scope ids and limit id variable declarations to kind 2014-11-04 12:56:37 +11:00
Sebastian McKenzie
56271efada pass scope to transformers 2014-11-04 12:48:08 +11:00
Sebastian McKenzie
89fbb06658 simplify VariableDeclaration ForStatement check 2014-11-04 12:47:56 +11:00
Sebastian McKenzie
43ee3b77f3 add SequenceExpression and UnaryExpression builders 2014-11-04 12:47:39 +11:00
Sebastian McKenzie
9ef826b53e move visitor-keys from traverse to types 2014-11-04 12:47:27 +11:00
Sebastian McKenzie
6519ceaa63 move util.getIds to types.getIds 2014-11-04 12:47:03 +11:00
Sebastian McKenzie
d28496006e implement Scope so we can keep track of references to avoid collisions when generating ids 2014-11-04 12:46:47 +11:00
Sebastian McKenzie
5f9710e61f add explanation for gross Error.captureStackTrace polyfill 2014-11-04 12:45:17 +11:00
Sebastian McKenzie
c4cadd8a64 add text/6to5 to browser compilation script types 2014-11-04 09:13:50 +11:00
Sebastian McKenzie
d3c5b8ef0b automatic browser <script type="text/ecmascript-6"> compilation - closes #97 2014-11-04 08:56:48 +11:00
Sebastian McKenzie
120df2c611 make browser api backwards compatible 2014-11-04 08:22:44 +11:00
Sebastian McKenzie
719d23eb3b add Error.captureStackTrace polyfill so browser build will work in non-v8 environments - fixes #107 2014-11-04 08:19:13 +11:00
Sebastian McKenzie
364abf60ea fix generation test whitespace 2014-11-04 08:05:09 +11:00
Sebastian McKenzie
0f5a141c91 change acorn-ast-types to ast-types 2014-11-04 08:04:41 +11:00
Sebastian McKenzie
fca3a0c56f generator: add ensureSemicolon and printBlock methods 2014-11-04 08:04:32 +11:00
Sebastian McKenzie
e88505aba6 better ExportDeclaration generation 2014-11-04 08:04:22 +11:00
Sebastian McKenzie
500a0bdfb6 better whitespace for blocks and methods 2014-11-04 08:04:11 +11:00
Sebastian McKenzie
2a0efceef5 change behaviour of tests and browser testing/build 2014-11-04 08:03:52 +11:00
Sebastian McKenzie
225754ae12 Merge branch 'master' into experimental 2014-11-03 21:18:50 +11:00
Sebastian McKenzie
6f230de01c fix maybeReplace wrong node callback bug 2014-11-03 21:17:56 +11:00
Sebastian McKenzie
3c3746b21f fix transformer alias types key 2014-11-03 21:17:42 +11:00
Sebastian McKenzie
f49f057b33 generator: add trim option to isLast 2014-11-03 21:17:17 +11:00
Sebastian McKenzie
e3b9a0dd38 update alias-functions transformer to use types 2014-11-03 21:16:15 +11:00
Sebastian McKenzie
f540c3f4b7 fix test newlines 2014-11-03 21:15:58 +11:00
Sebastian McKenzie
6e5917e537 make array comprehensions use for-of unless using an array literal - fixes #98 2014-11-03 21:15:49 +11:00
Sebastian McKenzie
816c1d304b remove builders and move them to automatially generated types 2014-11-03 21:13:35 +11:00
Sebastian McKenzie
5deeae1aa2 travis: ignore experimental branch 2014-11-03 18:26:50 +11:00
Sebastian McKenzie
718e342e86 fix classes supername transformer inference 2014-11-03 18:22:57 +11:00
Sebastian McKenzie
cb98605520 add example usage for custom module formatters 2014-11-03 18:20:01 +11:00
Sebastian McKenzie
600513bcab add ignore module formatter - closes #119 2014-11-03 18:18:51 +11:00
Sebastian McKenzie
620e5791af use t.is* methods to nicen up code 2014-11-03 18:10:52 +11:00
Sebastian McKenzie
47ee2cc99f simplify err.loc references 2014-11-03 17:53:08 +11:00
Sebastian McKenzie
6cc70f7465 compare code instead of ast for transformation tests 2014-11-03 17:52:59 +11:00
Sebastian McKenzie
20484c66c5 add types.inherits method that inherits loc, range, start, end etc 2014-11-03 17:52:50 +11:00
Sebastian McKenzie
171bcad870 make transformation tests compare output instead of ast 2014-11-03 17:52:15 +11:00
Sebastian McKenzie
c963c30107 fix errorWithNode line mapping 2014-11-03 17:50:25 +11:00
Sebastian McKenzie
795183569d fix export default assignment bug 2014-11-03 14:40:47 +11:00
Sebastian McKenzie
9a3c973280 add removeLastNewline to generator and add newlines to generated nodes 2014-11-03 14:40:33 +11:00
Sebastian McKenzie
95f3ca6348 Merge branch 'master' into code-generator
Conflicts:
	lib/6to5/transformers/classes.js
	test/fixtures/transformation/source-maps/class/expected.js
	test/fixtures/transformation/source-maps/class/source-mappings.json
2014-11-03 13:38:44 +11:00
Sebastian McKenzie
c17878913b add classProps declaration to simplify/nicen up class property defining - closes #88 2014-11-03 13:36:23 +11:00
Sebastian McKenzie
c8139317ee add static property inherit warning for IE <= 9 to README - closes #116 2014-11-03 13:09:36 +11:00
Sebastian McKenzie
6d6039aeb6 Merge branch 'master' into code-generator 2014-11-03 12:36:11 +11:00
Sebastian McKenzie
74f11dfddf add chai to devDependencies 2014-11-03 12:35:59 +11:00
Sebastian McKenzie
4c63b4ea1e Merge branch 'master' into code-generator 2014-11-03 12:34:15 +11:00
Sebastian McKenzie
6332e725fe update bin tests to match updated use strict behaviour 2014-11-03 12:34:00 +11:00
Sebastian McKenzie
f3d371869d Merge branch 'master' into code-generator
Conflicts:
	lib/6to5/register.js
2014-11-03 12:22:07 +11:00
Sebastian McKenzie
89ecd46b77 move _moduleFormatter transformer before useStrict transformer and remove duplicate use strict removing - fixes #114 2014-11-03 12:20:47 +11:00
Sebastian McKenzie
9f8e8d96a8 simplify hasParans for NewExpression 2014-11-03 12:15:57 +11:00
Sebastian McKenzie
a7bbd1dd3e generator: fix comments in harmony-edgecase tests 2014-11-03 12:15:44 +11:00
Sebastian McKenzie
6d961c1857 faster traverse.hasType with array of nodes 2014-11-03 12:15:27 +11:00
Sebastian McKenzie
e13a650d05 remove IfStatement making consequent and alternate blocks 2014-11-03 11:17:36 +11:00
Sebastian McKenzie
3cd7ed69a3 remove useless blank template 2014-11-03 11:16:48 +11:00
Sebastian McKenzie
93c6d69e21 make transformation tests ignore whitespace 2014-11-03 11:15:06 +11:00
Sebastian McKenzie
57d3c836bd register: add additional blacklistTests 2014-11-03 11:14:52 +11:00
Sebastian McKenzie
115282d57b generator: add _push method to simplify buffer pushing and location tracking 2014-11-03 11:13:37 +11:00
Sebastian McKenzie
72d924d85b generator: fix NewExpression arguments 2014-11-03 11:12:30 +11:00
Sebastian McKenzie
6838062279 move util.errorWithNode to File 2014-11-03 11:11:37 +11:00
Sebastian McKenzie
bc79cec15a add NewExpression support to needsParans 2014-11-03 11:11:07 +11:00
Sebastian McKenzie
85f0f6fb14 add whitespace option and move util.errorWithNode to File 2014-11-03 11:09:58 +11:00
Sebastian McKenzie
bf61c1e85d remove recast and add ast-types 2014-11-03 11:09:24 +11:00
Sebastian McKenzie
bd2e3d784f fix source-map transformation tests 2014-11-03 11:09:14 +11:00
Sebastian McKenzie
7e8c5cd20f Merge pull request #118 from amsul/patch-1
Added ability to register 6to5 with a blacklist
2014-11-02 10:39:13 +11:00
amsul
ddbb522392 Updated blacklist option to replace reference 2014-11-01 19:36:10 -04:00
amsul
288cfd1f00 Added ability to register 6to5 with a blacklist
Currently, to achieve this, I have to use this workaround:

```js
var to5 = require('6to5')
delete to5.transform.transformers.generators
require('6to5/register')
```

After this simple change, I can make it much nicer:

```js
require('6to5/register')({
    blacklist: ['generators']
})
```

Cheers!
2014-11-01 14:15:52 -04:00
Sebastian McKenzie
435b9434ea don't mess with the indentation of TemplateElements 2014-11-01 23:26:48 +11:00
Sebastian McKenzie
2409b017db generator: remove parans around ConditionalExpression 2014-11-01 23:08:50 +11:00
Sebastian McKenzie
99f2864048 generator: remove redundant print call 2014-11-01 23:08:33 +11:00
Sebastian McKenzie
5351057557 generator: move BlockStatement to base generator 2014-11-01 23:08:16 +11:00
Sebastian McKenzie
1a5ee7d5da change acorn-jsx to acorn-6to5 2014-11-01 23:07:53 +11:00
Sebastian McKenzie
ebea86c527 split up types.ensureBlock into types.toBlock 2014-11-01 23:07:34 +11:00
Sebastian McKenzie
bf58004947 generator: add intelligent whitespace based on tokens on nodes in a sequence 2014-11-01 23:07:17 +11:00
Sebastian McKenzie
f0c78102ca move template literal generators into separate file 2014-11-01 19:37:21 +11:00
Sebastian McKenzie
da1512eeb0 rename generation test names to be more descriptive 2014-11-01 19:34:16 +11:00
Sebastian McKenzie
43ea593677 traverse.removeProperties: remove raw property 2014-11-01 19:29:17 +11:00
Sebastian McKenzie
629cea497f move keyword method and restyle variable declarations 2014-11-01 19:29:02 +11:00
Sebastian McKenzie
9475dc681f finish jsx generator 2014-11-01 19:28:42 +11:00
Sebastian McKenzie
6e41309ede add err.stack test to code frame error capture 2014-11-01 19:28:35 +11:00
Sebastian McKenzie
42322e1ce7 add examples to types.needsParans tests 2014-11-01 19:27:42 +11:00
Sebastian McKenzie
400fa8ed97 remove unused ParenthesizedExpression 2014-11-01 19:27:23 +11:00
Sebastian McKenzie
07e2842226 implement array comprehension generator 2014-11-01 19:27:09 +11:00
Sebastian McKenzie
7d46b7c465 expose generator 2014-11-01 17:56:07 +11:00
Sebastian McKenzie
fcf6c9e066 generator: add isLast helper method 2014-11-01 17:53:01 +11:00
Sebastian McKenzie
a5523664fc generator: add alternate support to IfStatement 2014-11-01 17:52:48 +11:00
Sebastian McKenzie
1841f5c8a0 v1.10.10 2014-11-01 16:08:11 +11:00
Sebastian McKenzie
33f8988313 support for numeric literals with recast - fixes #117 2014-11-01 16:06:46 +11:00
Sebastian McKenzie
1d3544eadc fix function generation spacing 2014-11-01 16:00:17 +11:00
Sebastian McKenzie
646bdfd04c types.needsParans: add parent ExpressionStatement check for FunctionExpression 2014-11-01 15:58:44 +11:00
Sebastian McKenzie
aba9bba7db generator: use new keyword method for keywords 2014-11-01 15:56:27 +11:00
Sebastian McKenzie
e77382582f generator: add keyword method, remove __ident method and implement better position tracking 2014-11-01 15:56:10 +11:00
Sebastian McKenzie
af997b9945 Merge pull request #115 from djindjic/patch-1
Just a little info added
2014-11-01 08:39:33 +11:00
Aleksandar Djindjic
a2332f08bc Just a little info added
I needed this and it maybe help to someone else
2014-10-31 14:58:46 +01:00
Sebastian McKenzie
bbffde374e Merge branch 'master' into code-generator 2014-10-31 21:39:47 +11:00
Sebastian McKenzie
115dca56b6 v1.10.9 2014-10-31 21:39:17 +11:00
Sebastian McKenzie
251e4d01c8 join together declarations in destructuring to return a single node if possible - fixes #113 2014-10-31 21:38:22 +11:00
Sebastian McKenzie
0fbf0e2a77 generator: add semicolon helper method, add optional printJoin iterator 2014-10-31 21:24:54 +11:00
Sebastian McKenzie
e8628ea1a7 add chai 2014-10-31 21:24:36 +11:00
Sebastian McKenzie
a5a8f08bb8 generator: implement missing node types 2014-10-31 21:23:45 +11:00
Sebastian McKenzie
d376bd3c0e generator: remove redundant async tests 2014-10-31 21:23:31 +11:00
Sebastian McKenzie
20818b086c generator: add support for modules 2014-10-31 21:22:56 +11:00
Sebastian McKenzie
f9ef1723a6 generator: add support for ForOfStatement 2014-10-31 21:22:43 +11:00
Sebastian McKenzie
6e7b8a14fe remove comments in traverse.removeProperties 2014-10-31 21:22:28 +11:00
Sebastian McKenzie
622bb2e962 types: add more tests for optional paranthesis 2014-10-31 21:22:03 +11:00
Sebastian McKenzie
5c5348537d generator: add support for method properties and computed keys and shorthand 2014-10-31 21:21:50 +11:00
Sebastian McKenzie
0def62b918 replace single quotes with double quotes in generaton tests 2014-10-31 21:21:26 +11:00
Sebastian McKenzie
530ad78428 fix & html entity in travis badge branch url - thanks @davidchambers 2014-10-31 11:51:49 +11:00
Sebastian McKenzie
daced12baa add base for TemplateLiteral generator 2014-10-31 11:51:00 +11:00
Sebastian McKenzie
51f18a152e fix test generation actual ast 2014-10-31 11:50:52 +11:00
Sebastian McKenzie
51f72ace57 Merge pull request #112 from thejameskyle/travis-badge
Add ?branch=master to Travis CI badge
2014-10-31 11:47:50 +11:00
James Kyle
2fa36b30d5 Add ?branch=master to Travis CI badge 2014-10-30 17:46:08 -07:00
Sebastian McKenzie
11270e0803 Merge branch 'master' into code-generator
Conflicts:
	lib/6to5/transformers/rest-parameters.js
2014-10-31 11:44:48 +11:00
Sebastian McKenzie
6f8cbf0ad1 v1.10.8 2014-10-31 11:43:36 +11:00
Sebastian McKenzie
6696d5fcf4 fix rest parameters in arrow functions containing wrong arguments reference - fixes #11 2014-10-31 11:42:09 +11:00
Sebastian McKenzie
591f123670 update tests to work with new syntax 2014-10-31 11:38:52 +11:00
Sebastian McKenzie
1f7270720f add more type methods 2014-10-31 11:38:37 +11:00
Sebastian McKenzie
ec3a3cbbc9 more descriptive test helper method names 2014-10-31 11:38:18 +11:00
Sebastian McKenzie
8a1ea82e97 remove legacy generator options 2014-10-31 11:38:04 +11:00
Sebastian McKenzie
6953b6e8b6 remove start and end props from nodes in traverse.removeProperties 2014-10-31 11:37:49 +11:00
Sebastian McKenzie
378832d31b add comments with estraverse 2014-10-31 11:37:17 +11:00
Sebastian McKenzie
85703eb5b8 run internal transformers when using a whitelist 2014-10-31 11:37:04 +11:00
Sebastian McKenzie
d0fdd3bf41 remove comments transformer 2014-10-31 11:36:44 +11:00
Sebastian McKenzie
a7385bdf1b make CodeGenerators use static method calls instead of recursive string methods 2014-10-31 11:36:28 +11:00
Sebastian McKenzie
9c7c385ee8 add generation tests from escodegen 2014-10-31 11:35:57 +11:00
Sebastian McKenzie
7c84af2ba8 remove optional computed property in b.memberExpression 2014-10-30 17:38:05 +11:00
Sebastian McKenzie
009d063790 just return constructor if only a constructor exists in classes 2014-10-30 17:37:51 +11:00
Sebastian McKenzie
5483c4ef6f split up code generators 2014-10-30 17:30:05 +11:00
Sebastian McKenzie
5558f61518 add more feature detection to 6to5/register 2014-10-30 17:16:33 +11:00
Sebastian McKenzie
96bc95d6d9 add blacklist syntax feature checking to 6to5/register 2014-10-30 17:11:54 +11:00
Sebastian McKenzie
11dd13b7e0 remove invalid node types from generator and add todo ones 2014-10-30 17:11:31 +11:00
Sebastian McKenzie
976e6782a2 expose traverse.VISITOR_KEYS 2014-10-30 17:11:13 +11:00
Sebastian McKenzie
febc3062cc update traverse visitor keys to acorn ones 2014-10-30 17:11:05 +11:00
Sebastian McKenzie
efff5e5aab add generation completeness test 2014-10-30 17:10:54 +11:00
Sebastian McKenzie
eefab7f80f remove unused variables 2014-10-30 13:31:45 +11:00
Sebastian McKenzie
1a3d306949 Merge branch 'master' into code-generator
Conflicts:
	package.json
2014-10-30 13:29:05 +11:00
Sebastian McKenzie
e5ae2f8eaf fix linting errors 2014-10-30 13:26:13 +11:00
Sebastian McKenzie
e797be518f move some util and traverse methods into types 2014-10-30 13:26:06 +11:00
Sebastian McKenzie
45cb755845 better eval contexts in bin/6to5-node 2014-10-30 13:09:37 +11:00
Sebastian McKenzie
3b9a339c79 remove useless traverse.Delete 2014-10-30 13:09:23 +11:00
Sebastian McKenzie
ea7ac4cd2d change acorn-ast-types to internal builders 2014-10-30 13:09:12 +11:00
Sebastian McKenzie
e141a8b875 run 6to5-node repl in a context 2014-10-30 12:15:37 +11:00
Sebastian McKenzie
6768fc3800 add back regex.flags in unicode regex transformer 2014-10-30 12:15:12 +11:00
Sebastian McKenzie
0af5e00b5f update jsx empty test to new dom tags behaviour 2014-10-30 12:14:41 +11:00
Sebastian McKenzie
ecedc23892 v1.10.7 2014-10-29 20:59:35 +11:00
Sebastian McKenzie
163c68dd6a fix lint errors 2014-10-29 20:57:43 +11:00
Sebastian McKenzie
4dc6147348 update acorn-recast 2014-10-29 20:53:25 +11:00
Sebastian McKenzie
4b3ebc62b1 fix indentation 2014-10-29 20:52:31 +11:00
Sebastian McKenzie
cc094efe1b modify regex object instead of creating a new literal 2014-10-29 20:52:25 +11:00
Sebastian McKenzie
8f4a3f77a0 remove jsx known-tags and use the latest jsx known tag definition 2014-10-29 20:52:12 +11:00
Sebastian McKenzie
b31f3666c8 yank out acorn-recast and replace it with our own code generator 2014-10-29 20:51:52 +11:00
Sebastian McKenzie
b1495832d7 remove acorn-recast 2014-10-29 20:51:03 +11:00
Sebastian McKenzie
fa6e50ea28 Merge pull request #103 from eventualbuddha/remove-unused-vars
Remove unused vars & fix typo
2014-10-28 14:31:24 +11:00
Sebastian McKenzie
a72c839a73 add bin and benchmark directories to jshint test #103 2014-10-28 14:31:09 +11:00
Brian Donovan
32b5edb711 Remove unused requires. 2014-10-27 20:28:31 -07:00
Brian Donovan
8cbb121e3f Fix typo. 2014-10-27 20:28:08 -07:00
Sebastian McKenzie
75ece96475 v1.10.6 2014-10-28 13:18:47 +11:00
Sebastian McKenzie
b016fda8af add browser.js to .gitignore 2014-10-28 13:18:00 +11:00
Sebastian McKenzie
2cffad61fa more reliable destructuring building 2014-10-28 13:16:31 +11:00
Sebastian McKenzie
4e248c0a16 add member expression destructuring test 2014-10-28 13:16:21 +11:00
Sebastian McKenzie
4f5026101b fix cache-templates build script position - fixes #101 2014-10-28 13:16:08 +11:00
Sebastian McKenzie
4ce38eab37 v1.10.5 2014-10-28 10:59:28 +11:00
Sebastian McKenzie
0a7ce115ff remove browser.js in make publish 2014-10-28 10:58:29 +11:00
Sebastian McKenzie
21ed438fd8 alias functions in scope call wrapping - fixes #99 2014-10-28 10:58:20 +11:00
460 changed files with 6133 additions and 2161 deletions

4
.gitignore vendored
View File

@@ -4,5 +4,9 @@ test/tmp
*.log
*.cache
/templates.json
/tests.json
/browser.js
/polyfill.js
/runtime.js
coverage
dist

View File

@@ -17,5 +17,13 @@
"loopfunc": true,
"white": true,
"maxparams": 5,
"maxdepth": 4
"maxdepth": 4,
"globals": {
"window": true,
"suite": true,
"set": true,
"before": true,
"bench": true
}
}

View File

@@ -7,4 +7,5 @@ benchmark
Makefile
.*
dist
tests.json
!README.md

View File

@@ -3,10 +3,17 @@ node_js:
- "0.10"
- "0.11"
branches:
except:
- experimental
before_script: "npm install -g codeclimate-test-reporter"
script: "make test-travis"
addons:
code_climate:
repo_token:
secure: "PfP9sDUJzSznDb+ZEPO2cignXabSTXJxEVm5ESRPgEcFr+/4b0pt3hI8R9b+9mLtBEwtw3DLUq48MOeqEKnq29csQmpjPVcN6gT4uR2DdNa1JpVgDuwxT05NB3fBea9U2reM73iV8ylCgPHExr2uGR9/87JzR2beY/56EUL5NjY="
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/acf1870e9d223c65e8d5
on_success: always
on_failure: always
on_start: false

View File

@@ -109,10 +109,35 @@ export function bar() {
});
```
### Ignore
**In**
```javascript
import foo from "foo";
export function bar() {
return foo("foobar");
}
```
**Out**
```javascript
function bar() {
return foo("foobar");
}
```
## Custom
You can alternatively specify module names instead of one of the built-in types.
$ 6to5 --modules custom-module-formatter
**node_modules/custom-module-formatter/index.js**
```javascript
module.exports = ModuleFormatter;

View File

@@ -1,10 +1,12 @@
BROWSERIFY_CMD = node_modules/browserify/bin/cmd.js
ISTANBUL_CMD = node_modules/istanbul/lib/cli.js cover
UGLIFY_CMD = node_modules/uglify-js/bin/uglifyjs
JSHINT_CMD = node_modules/jshint/bin/jshint
MOCHA_CMD = node_modules/mocha/bin/_mocha
export NODE_ENV = test
.PHONY: clean test test-cov test-travis test-browser publish bench build
.PHONY: clean test test-cov tlint est-travis test-appveyor test-browser publish bench build
clean:
rm -rf coverage templates.json test/tmp dist
@@ -13,21 +15,32 @@ bench:
npm install es6-transpiler traceur esnext es6now jstransform
node node_modules/matcha/bin/_matcha
lint:
$(JSHINT_CMD) lib bin benchmark/index.js
test:
$(JSHINT_CMD) lib
make lint
$(MOCHA_CMD)
test-cov:
rm -rf coverage
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
test-travis:
test-appveyor:
node $(ISTANBUL_CMD) $(MOCHA_CMD) -- --reporter spec
test-travis:
make test-appveyor
if test -n "$$CODECLIMATE_REPO_TOKEN"; then codeclimate < coverage/lcov.info; fi
test-browser:
make build
node bin/generate-browser-test >dist/6to5-test.js
mkdir -p dist
node bin/cache-templates
node bin/cache-tests
node $(BROWSERIFY_CMD) -e test/_browser.js >dist/6to5-test.js
rm -rf templates.json tests.json
test -n "`which open`" && open test/browser.html
build:
@@ -35,8 +48,14 @@ build:
node bin/cache-templates
browserify lib/6to5/browser.js -s to5 >dist/6to5.js
uglifyjs dist/6to5.js >dist/6to5.min.js
node $(BROWSERIFY_CMD) -e lib/6to5/polyfill.js >dist/polyfill.js
node $(UGLIFY_CMD) dist/polyfill.js >dist/polyfill.min.js
node $(BROWSERIFY_CMD) lib/6to5/browser.js -s to5 >dist/6to5.js
node $(UGLIFY_CMD) dist/6to5.js >dist/6to5.min.js
node bin/6to5-runtime >dist/runtime.js
node $(UGLIFY_CMD) dist/runtime.js >dist/runtime.min.js
rm -rf templates.json
@@ -45,16 +64,18 @@ publish:
make test
make build
cp dist/6to5.min.js browser.js
cp dist/polyfill.min.js polyfill.js
cp dist/runtime.min.js runtime.js
node bin/cache-templates
test -f templates.json
make build
cp dist/6to5.js browser.js
read -p "Version: " version; \
npm version $$version --message "v%s"
npm publish
git push --follow-tags
rm -rf templates.json
rm -rf templates.json browser.js runtime.js polyfill.js

211
README.md
View File

@@ -1,22 +1,26 @@
<p align="center">
<img alt="6to5" src="http://i.imgur.com/hVl9KRw.png">
<img alt="6to5" src="https://raw.githubusercontent.com/6to5/logo/master/logo.png" width="546">
</p>
<p align="center">
<a href="https://travis-ci.org/sebmck/6to5">
<img alt="Travis Status" src="http://img.shields.io/travis/sebmck/6to5.svg?style=flat&amp;label=travis">
<a href="https://travis-ci.org/6to5/6to5">
<img alt="Travis Status" src="http://img.shields.io/travis/6to5/6to5.svg?branch=master&amp;style=flat&amp;label=travis">
</a>
<a href="https://codeclimate.com/github/sebmck/6to5">
<img alt="Code Climate Score" src="http://img.shields.io/codeclimate/github/sebmck/6to5.svg?style=flat">
<a href="https://ci.appveyor.com/project/sebmck/6to5">
<img alt="Appveyor Status" src="http://img.shields.io/appveyor/ci/sebmck/6to5.svg?style=flat&amp;label=appveyor">
</a>
<a href="https://codeclimate.com/github/sebmck/6to5">
<img alt="Coverage" src="http://img.shields.io/codeclimate/coverage/github/sebmck/6to5.svg?style=flat">
<a href="https://codeclimate.com/github/6to5/6to5">
<img alt="Code Climate Score" src="http://img.shields.io/codeclimate/github/6to5/6to5.svg?style=flat">
</a>
<a href="https://david-dm.org/sebmck/6to5">
<img alt="Dependency Status" src="http://img.shields.io/david/sebmck/6to5.svg?style=flat">
<a href="https://codeclimate.com/github/6to5/6to5">
<img alt="Coverage" src="http://img.shields.io/codeclimate/coverage/github/6to5/6to5.svg?style=flat">
</a>
<a href="https://david-dm.org/6to5/6to5">
<img alt="Dependency Status" src="http://img.shields.io/david/6to5/6to5.svg?style=flat">
</a>
</p>
@@ -43,6 +47,8 @@ It's as easy as:
- [Browser](#browser)
- [Modules](#modules)
- [Caveats](#caveats)
- [Polyfill](#polyfill)
- [Optional runtime](#optional-runtime)
- [Differences](#differences)
## [Features](FEATURES.md)
@@ -71,12 +77,14 @@ It's as easy as:
### Plugins
- [Broccoli](https://github.com/very-geek/broccoli-6to5-transpiler)
- [Browserify](https://github.com/sebmck/6to5-browserify)
- [Browserify](https://github.com/6to5/6to5-browserify)
- [Brunch](https://github.com/es128/6to5-brunch)
- [Connect](https://github.com/sebmck/6to5-connect)
- [Duo](https://github.com/bdo-labs/duo6to5)
- [Connect](https://github.com/6to5/6to5-connect)
- [Gulp](https://github.com/sindresorhus/gulp-6to5)
- [Grunt](https://github.com/sindresorhus/grunt-6to5)
- [Jade](https://github.com/Apoxx/jade-6to5)
- [Karma](https://github.com/shuhei/karma-6to5-preprocessor)
- [webpack](https://github.com/Couto/6to5-loader)
### CLI
@@ -103,6 +111,10 @@ Compile the entire `src` directory and output it to the `lib` directory.
$ 6to5 src --out-dir lib
Compile the entire `src` directory and output it to the one concatenated file.
$ 6to5 src --out-file script-compiled.js
Pipe a file in via stdin and output it to `script-compiled.js`
$ 6to5 --out-file script-compiled.js < script.js
@@ -171,7 +183,12 @@ to5.transformFile("filename.js", options, function (err, result) {
// Set `sources[0]` on returned source map.
// Default: `filename` option.
sourceFileName: "filename"
sourceFileName: "filename",
// Optionally replace all 6to5 helper declarations with a referenece to this
// variable. If set to `true` then the default namespace is used "to5Runtime".
// Default: false
runtime: true
}
```
@@ -189,24 +206,64 @@ require("6to5/register");
override this by passing an ignore regex via:
```javascript
require("6to5/register")(/regex/);
require("6to5/register")({
// This will override `node_modules` ignoring - you can alternatively pass
// a regex
ignore: false
});
```
You can also customise the file extensions that the require hook will use via:
##### Options
```javascript
require("6to5/register")({
// optional ignore regex
ignoreRegex: /regex/,
// Optional ignore regex - if any filenames **do** match this regex then they
// aren't compiled
ignore: /regex/,
// this will remove the currently hooked extensions of .es6 and .js so you'll
// have to add them back if you want them to be used again
// Optional only regex - if any filenames **don't** match this regex then they
// aren't compiled
only: /my_es6_folder/,
// See options above for usage
whitelist: [],
blacklist: [],
// This will remove the currently hooked extensions of .es6 and .js so you'll
// have to add them back if you want them to be used again.
extensions: [".js", ".es6"]
});
```
### Browser
A browser version of 6to5 is available from `browser.js` inside the 6to5
directory in an npm release.
#### Scripts
While it's not recommended for serious use, when the browser version is included
all scripts with the type `text/ecmascript-6` and `text/6to5` are automatically
compiled and ran.
For example:
```html
<script src="node_modules/6to5/browser.js"></script>
<script type="text/6to5">
class Test {
test() {
return "test";
}
}
var test = new Test;
test.test();
</script>
```
#### Build
You can build a browser version of the compiler by running the following in the
6to5 directory:
@@ -214,11 +271,10 @@ You can build a browser version of the compiler by running the following in the
This will output the files `dist/6to5.js` and `dist/6to5.min.js`.
Just include one of those in the browser and access the transform method via the
global `to5`.
#### API
```javascript
to5("class Test {}").code;
to5.transform("class Test {}").code;
```
#### Test
@@ -238,32 +294,6 @@ Alternatively see [Modules](MODULES.md) for all other supported module formattin
## Caveats
### Polyfill
6to5 does not include a runtime nor polyfill and it's up to the developer to
include one in compiled browser code.
#### Node
A polyfill is included with the 6to5 module that can be included in node like
so:
```javascript
require("6to5/polyfill");
```
This is simply a wrapper around the
[regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) and the
[es6-shim](https://github.com/paulmillr/es6-shim) and
[es6-symbol](https://github.com/medikoo/es6-symbol) polyfills.
#### Browser
If you're planning on using 6to5 output in the browser then it's up to you
to include polyfills. [es6-symbol](https://github.com/medikoo/es6-symbol#browser)
and [es6-shim](https://raw.githubusercontent.com/paulmillr/es6-shim/master/es6-shim.js)
fill the vast majority of polyfill concerns.
### For-of
A polyfill is required for for-of functionality that implements `Symbol` and
@@ -279,11 +309,98 @@ If you're inheriting from a class then static properties are inherited from it
via [\_\_proto\_\_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto),
this is widely supported but you may run into problems with much older browsers.
**NOTE:** `__proto__` is not supported on IE <= 9 so static properties
**will not** be inherited. A possible workaround is to use `super();`:
```javascript
class Foo {
static foo() {
}
}
class Bar extends Foo {
static foo() {
super();
}
}
```
### Generators
The [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js)
and an [ES6 polyfill](#polyfill) are required in order for generators to work.
## Polyfill
6to5 includes a polyfill that includes the
[regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) and the
[es6-shim](https://github.com/paulmillr/es6-shim) and
[es6-symbol](https://github.com/medikoo/es6-symbol) polyfills.
### Node
```javascript
require("6to5/polyfill");
```
### Browser
Available from the `polyfill.js` file within the 6to5 directory of an npm
release.
## Optional runtime
6to5 has a few helper functions that'll be placed at the top of the generated
code if needed so it's not inlined multiple times throughout that file. This may
become an issue if you have multiple files, especially when you're sending them
to the browser. gzip alleviates most of this concern but it's still not ideal.
You can tell 6to5 to not place any declarations at the top of your files and
instead just point them to a reference contained within the runtime.
Simply use the following option if you're using the [Node API](#node-1):
```javascript
{
runtime: true
}
```
or the following flag if you're using the [CLI](#cli):
$ 6to5 --runtime
Then just include the runtime before your generated code.
### Getting the runtime
You can get the runtime via either:
$ 6to5-runtime
or
```javascript
require("6to5").runtime();
```
or from an npm release in `runtime.js` from the 6to5 directory.
### Customising namespace
You can also customise the runtime namespace by passing an optional namespace
argument:
```javascript
require("6to5").runtime("myCustomNamespace");
```
$ 6to5-runtime myCustomNamespace
See [Options - runtime](#options) for documentation on changing the reference in
generated code.
## Differences
### Philosophy

17
appveyor.yml Normal file
View File

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

View File

@@ -7,13 +7,10 @@ var es6now = require("es6now");
var esnext = require("esnext");
var to5 = require("../lib/6to5");
var uglify = require("uglify-js");
//var uglify = require("uglify-js");
var matcha = require("matcha");
var stream = require("stream");
var path = require("path");
var zlib = require("zlib");
var fs = require("fs");
var vm = require("vm");
var _ = require("lodash");
var readResolve = function (filename) {
@@ -51,7 +48,7 @@ var compilers = {
traceur: {
runtime: readResolve("traceur/bin/traceur-runtime.js"),
compile: function (code, filename) {
compile: function (code) {
return traceur.compile(code, {
modules: "commonjs",
experimental: true
@@ -61,20 +58,20 @@ var compilers = {
esnext: {
runtime: readResolve("esnext/node_modules/regenerator/runtime.js") || readResolve("regenerator/runtime.js"),
compile: function (code, filename) {
compile: function (code) {
return esnext.compile(code).code;
}
},
es6now: {
runtime: readResolve("es6now/runtime/ES6.js"),
compile: function (code, filename) {
compile: function (code) {
return es6now.translate(code);
}
},
"es6-transpiler": {
compile: function (code, filename) {
compile: function (code) {
var result = es6tr.run({ src: code });
if (result.errors.length) throw new Error(result.join("; "));
return result.src;
@@ -82,7 +79,7 @@ var compilers = {
},
jstransform: {
compile: function (code, filename) {
compile: function (code) {
return jsTrans.transform(jsTransVisitors, code).code;
}
}
@@ -90,7 +87,7 @@ var compilers = {
// versions
var uglifyTitle = "uglify v" + getVersion("uglify-js");
//var uglifyTitle = "uglify v" + getVersion("uglify-js");
_.each(compilers, function (compiler, name) {
compiler.title = name + " v" + (compiler.version || getVersion(name));
@@ -162,7 +159,7 @@ _.each(fs.readdirSync(__dirname + "/fixtures"), function (name) {
});
});
_.each(compilers, function (compiler, name) {
_.each(compilers, function (compiler) {
bench(compiler.title, function () {
compiler.compile(code, loc);
});

View File

@@ -1,84 +1,56 @@
#!/usr/bin/env node
var commander = require("commander");
var Module = require("module");
var util = require("../lib/6to5/util");
var path = require("path");
var repl = require("repl");
var to5 = require("../lib/6to5");
var vm = require("vm");
var _ = require("lodash");
/**
* This tiny wrapper file checks for known node flags and appends them
* when found, before invoking the "real" _6to5-node(1) executable.
*/
commander.option("-e, --eval [script]", "evaluate script");
commander.option("-p, --print", "evaluate script and print result");
commander.option("-i, --ignore [regex]", "ignore all files that match this regex when using the require hook");
commander.option("-x, --extensions [extensions]", "list of extensions to hook into [.es6,.js]", util.list);
var spawn = require("child_process").spawn;
var args = ["--harmony", __dirname + "/_6to5-node"];
var pkg = require("../package.json");
commander.version(pkg.version);
commander.usage("[options] [ -e script | script.js ] [arguments]");
commander.parse(process.argv);
process.argv.slice(2).forEach(function(arg){
var flag = arg.split("=")[0];
//
var registerOpts = {};
if (commander.ignore) {
registerOpts.ignoreRegex = new RegExp(commander.ignore);
}
if (commander.extensions && commander.extensions.length) {
registerOpts.extensions = commander.extensions
}
to5.register(registerOpts);
//
var _eval = function (code, filename) {
code = to5.transform(code, { filename: filename }).code;
return vm.runInThisContext(code, filename);
};
if (commander.eval) {
var result = _eval(commander.eval, "eval");
if (commander.print) console.log(result);
} else {
var filenames = commander.args;
if (filenames.length) {
_.each(filenames, function (filename) {
if (!util.isAbsolute(filename)) {
filename = path.join(process.cwd(), filename);
}
require(require.resolve(filename));
});
} else {
replStart();
switch (flag) {
case "-d":
args.unshift("--debug");
args.push("--no-timeouts");
break;
case "debug":
case "--debug":
case "--debug-brk":
args.unshift(arg);
args.push("--no-timeouts");
break;
case "-gc":
case "--expose-gc":
args.unshift("--expose-gc");
break;
case "--gc-global":
case "--harmony":
case "--harmony-proxies":
case "--harmony-collections":
case "--harmony-generators":
case "--no-deprecation":
case "--prof":
case "--throw-deprecation":
case "--trace-deprecation":
args.unshift(arg);
break;
default:
if (0 == arg.indexOf("--trace")) args.unshift(arg);
else args.push(arg);
break;
}
}
});
function replStart() {
repl.start({
prompt: "> ",
input: process.stdin,
output: process.stdout,
eval: replEval,
useGlobal: true
var proc = spawn(process.argv[0], args, { stdio: "inherit" });
proc.on("exit", function (code, signal) {
process.on("exit", function (){
if (signal) {
process.kill(process.pid, signal);
} else {
process.exit(code);
}
});
}
function replEval(code, context, filename, callback) {
var err;
var result;
try {
code = code.slice(1, -2); // remove "(" and "\n)"
result = _eval(code, filename);
} catch (e) {
err = e;
}
callback(err, result);
}
});

4
bin/6to5-runtime Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
var runtime = require("../lib/6to5/runtime");
console.log(runtime(process.argv[2]));

View File

@@ -6,7 +6,7 @@ var util = require("./util");
var fs = require("fs");
var _ = require("lodash");
module.exports = function (commander, filenames, opts) {
module.exports = function (commander, filenames) {
var results = [];
var buildResult = function () {
@@ -48,7 +48,7 @@ module.exports = function (commander, filenames, opts) {
return {
map: map,
code: code
}
};
};
var output = function () {
@@ -100,8 +100,8 @@ module.exports = function (commander, filenames, opts) {
}
});
_.each(_filenames, function (filename, i) {
results.push(util.compile(filename, { _noStrict: i != 0 }));
_.each(_filenames, function (filename) {
results.push(util.compile(filename));
});
output();

View File

@@ -1,13 +1,8 @@
#!/usr/bin/env node
var commander = require("commander");
var sourceMap = require("source-map");
var transform = require("../../lib/6to5/transform");
var chokidar = require("chokidar");
var mkdirp = require("mkdirp");
var util2 = require("../../lib/6to5/util");
var util = require("./util");
var path = require("path");
var transform = require("../../lib/6to5/transformation/transform");
var util = require("../../lib/6to5/util");
var fs = require("fs");
var _ = require("lodash");
@@ -15,10 +10,11 @@ commander.option("-t, --source-maps-inline", "Append sourceMappingURL comment to
commander.option("-s, --source-maps", "Save source map alongside the compiled code");
commander.option("-f, --filename [filename]", "Filename to use when reading from stdin - this will be used in source-maps, errors etc [stdin]", "stdin");
commander.option("-w, --watch", "Recompile files on changes");
commander.option("-r, --runtime", "Replace 6to5 declarations with references to a runtime");
commander.option("-m, --modules [modules]", "Module formatter type to use [common]", "common");
commander.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ONLY use", util2.list);
commander.option("-b, --blacklist [blacklist]", "Blacklist of transformers to NOT use", util2.list);
commander.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ONLY use", util.list);
commander.option("-b, --blacklist [blacklist]", "Blacklist of transformers to NOT use", util.list);
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");
@@ -92,6 +88,7 @@ exports.opts = {
blacklist: commander.blacklist,
whitelist: commander.whitelist,
sourceMap: commander.sourceMaps || commander.sourceMapsInline,
runtime: commander.runtime,
modules: commander.modules
};

View File

@@ -6,7 +6,9 @@ var fs = require("fs");
var _ = require("lodash");
exports.readdirFilter = function (filename) {
return readdir(filename).filter(util.canCompile);
return readdir(filename).filter(function (filename) {
return util.canCompile(filename);
});
};
exports.transform = function (filename, code, opts) {

86
bin/_6to5-node Normal file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env node
var commander = require("commander");
var util = require("../lib/6to5/util");
var path = require("path");
var repl = require("repl");
var to5 = require("../lib/6to5");
var vm = require("vm");
var _ = require("lodash");
commander.option("-e, --eval [script]", "evaluate script");
commander.option("-p, --print", "evaluate script and print result");
commander.option("-i, --ignore [regex]", "ignore all files that match this regex when using the require hook");
commander.option("-x, --extensions [extensions]", "list of extensions to hook into [.es6,.js]", util.list);
var pkg = require("../package.json");
commander.version(pkg.version);
commander.usage("[options] [ -e script | script.js ] [arguments]");
commander.parse(process.argv);
//
var registerOpts = {};
if (commander.ignore) {
registerOpts.ignoreRegex = new RegExp(commander.ignore);
}
if (commander.extensions && commander.extensions.length) {
registerOpts.extensions = commander.extensions;
}
to5.register(registerOpts);
//
var _eval = function (code, filename) {
code = to5.transform(code, { filename: filename, blacklist: ["useStrict"] }).code;
return vm.runInThisContext(code, filename);
};
if (commander.eval) {
var result = _eval(commander.eval, "eval");
if (commander.print) console.log(result);
} else {
var filenames = commander.args;
if (filenames.length) {
_.each(filenames, function (filename) {
if (!util.isAbsolute(filename)) {
filename = path.join(process.cwd(), filename);
}
require(require.resolve(filename));
});
} else {
replStart();
}
}
function replStart() {
repl.start({
prompt: "> ",
input: process.stdin,
output: process.stdout,
eval: replEval,
useGlobal: true
});
}
function replEval(code, context, filename, callback) {
var err;
var result;
try {
if (/^\((.*?)\n\)$/.test(code)) {
code = code.slice(1, -2); // remove "(" and "\n)"
}
result = _eval(code, filename);
} catch (e) {
err = e;
}
callback(err, result);
}

5
bin/cache-tests Normal file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env node
var fs = require("fs");
var cache = require("../test/_helper").cache;
fs.writeFileSync("tests.json", JSON.stringify(cache));

View File

@@ -1,6 +0,0 @@
#!/usr/bin/env node
var helper = require("../test/_helper");
var util = require("../lib/6to5/util");
console.log("(" + helper.run + ")(" + JSON.stringify(helper.getTests()) + ", to5, proclaim)");

View File

@@ -1,3 +1,87 @@
var transform = require("./transform");
var transform = module.exports = require("./transformation/transform");
module.exports = transform;
transform.transform = transform;
transform.eval = function (code, opts) {
opts = opts || {};
opts.filename = opts.filename || "eval";
opts.sourceMap = "inline";
return eval(transform(code, opts).code);
};
transform.run = function (code, opts) {
opts = opts || {};
opts.sourceMap = "inline";
return new Function(transform(code, opts).code)();
};
transform.load = function (url, callback, opts, hold) {
opts = opts || {};
opts.filename = opts.filename || url;
var xhr = window.ActiveXObject ? new window.ActiveXObject("Microsoft.XMLHTTP") : new window.XMLHttpRequest();
xhr.open("GET", url, true);
if ("overrideMimeType" in xhr) xhr.overrideMimeType("text/plain");
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
var status = xhr.status;
if (status === 0 || status === 200) {
var param = [xhr.responseText, opts];
if (!hold) transform.run.apply(transform, param);
if (callback) callback(param);
} else {
throw new Error("Could not load " + url);
}
};
xhr.send(null);
};
var runScripts = function () {
var scripts = [];
var types = ["text/ecmascript-6", "text/6to5"];
var index = 0;
var exec = function () {
var param = scripts[index];
if (param instanceof Array) {
transform.run.apply(transform, param);
index++;
exec();
}
};
var run = function (script, i) {
var opts = {};
if (script.src) {
transform.load(script.src, function (param) {
scripts[i] = param;
exec();
}, opts, true);
} else {
opts.filename = "embedded";
scripts[i] = [script.innerHTML, opts];
}
};
var _scripts = window.document.getElementsByTagName("script");
for (var i in _scripts) {
var _script = _scripts[i];
if (types.indexOf(_script.type) >= 0) scripts.push(_script);
}
for (i in scripts) {
run(scripts[i], i);
}
exec();
};
if (window.addEventListener) {
window.addEventListener("DOMContentLoaded", runScripts, false);
} else {
window.attachEvent("onload", runScripts);
}

View File

@@ -2,30 +2,35 @@ module.exports = File;
var SHEBANG_REGEX = /^\#\!.*/;
var transform = require("./transform");
var recast = require("acorn-recast");
var transform = require("./transformation/transform");
var generate = require("./generation/generator");
var Scope = require("./traverse/scope");
var util = require("./util");
var b = require("acorn-ast-types").builders;
var t = require("./types");
var _ = require("lodash");
function File(opts) {
this.opts = File.normaliseOptions(opts);
this.moduleFormatter = this.getModuleFormatter(opts.modules);
this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
this.declarations = {};
this.uids = {};
this.ast = {};
}
File.declarations = ["extends", "class-props", "slice"];
File.normaliseOptions = function (opts) {
opts = opts || {};
opts = _.cloneDeep(opts || {});
_.defaults(opts, {
blacklist: [],
whitelist: [],
sourceMap: false,
filename: "unknown",
modules: "common"
whitespace: true,
blacklist: [],
whitelist: [],
sourceMap: false,
filename: "unknown",
modules: "common",
runtime: false
});
_.defaults(opts, {
@@ -33,6 +38,10 @@ File.normaliseOptions = function (opts) {
sourceMapName: opts.filename
});
if (opts.runtime === true) {
opts.runtime = "to5Runtime";
}
transform._ensureTransformerNames("blacklist", opts.blacklist);
transform._ensureTransformerNames("whitelist", opts.whitelist);
@@ -40,18 +49,18 @@ File.normaliseOptions = function (opts) {
};
File.prototype.getModuleFormatter = function (type) {
var ModuleLoader = transform.moduleFormatters[type];
var ModuleFormatter = transform.moduleFormatters[type];
if (!ModuleLoader) {
if (!ModuleFormatter) {
var loc = util.resolve(type);
if (loc) ModuleLoader = require(loc);
if (loc) ModuleFormatter = require(loc);
}
if (!ModuleLoader) {
if (!ModuleFormatter) {
throw new ReferenceError("unknown module formatter type " + type);
}
return new ModuleLoader(this);
return new ModuleFormatter(this);
};
File.prototype.parseShebang = function (code) {
@@ -67,20 +76,46 @@ File.prototype.parseShebang = function (code) {
};
File.prototype.addDeclaration = function (name) {
if (!_.contains(File.declarations, name)) {
throw new ReferenceError("unknown declaration " + name);
}
var declar = this.declarations[name];
if (declar) return declar.uid;
var uid = b.identifier(this.generateUid(name));
var ref;
var runtimeNamespace = this.opts.runtime;
if (runtimeNamespace) {
name = t.identifier(t.toIdentifier(name));
return t.memberExpression(t.identifier(runtimeNamespace), name);
} else {
ref = util.template(name);
}
var uid = t.identifier(this.generateUid(name));
this.declarations[name] = {
uid: uid,
node: util.template(name)
node: ref
};
return uid;
};
File.prototype.errorWithNode = function (node, msg, Error) {
Error = Error || SyntaxError;
var loc = node.loc.start;
var err = new Error("Line " + loc.line + ": " + msg);
err.loc = loc;
return err;
};
File.prototype.parse = function (code) {
code = (code || "") + "";
var self = this;
this.code = code;
code = this.parseShebang(code);
return util.parse(this.opts, code, function (tree) {
@@ -91,6 +126,7 @@ File.prototype.parse = function (code) {
File.prototype.transform = function (ast) {
this.ast = ast;
this.scope = new Scope(null, ast.program);
var self = this;
@@ -103,43 +139,33 @@ File.prototype.generate = function () {
var opts = this.opts;
var ast = this.ast;
var printOpts = { tabWidth: 2 };
if (opts.sourceMap) {
printOpts.sourceMapName = opts.sourceMapName;
}
var result = recast.print(ast, printOpts);
var code = result.code;
var result = generate(ast, opts, this.code);
if (this.shebang) {
// add back shebang
code = this.shebang + code;
result.code = this.shebang + result.code;
}
if (opts.sourceMap === "inline") {
code += "\n" + util.sourceMapToComment(result.map);
result.code += "\n" + util.sourceMapToComment(result.map);
}
return {
code: code,
map: result.map || null,
ast: ast
};
return result;
};
File.prototype.generateUid = function (name) {
// replace all non-valid identifiers with dashes
name = name.replace(/[^a-zA-Z0-9]/g, "-");
File.prototype.generateUid = function (name, scope) {
name = t.toIdentifier(name);
// remove all dashes and numbers from start of name
name = name.replace(/^[-0-9]+/, "");
scope = scope || this.scope;
// camel case
name = name.replace(/[-_\s]+(.)?/g, function (match, c) {
return c ? c.toUpperCase() : "";
});
var uid;
do {
uid = this._generateUid(name);
} while (scope.has(uid));
return uid;
};
File.prototype._generateUid = function (name) {
var uids = this.uids;
var i = uids[name] || 1;

View File

@@ -0,0 +1,396 @@
module.exports = function (ast, opts, code) {
var gen = new CodeGenerator(ast, opts, code);
return gen.generate();
};
module.exports.CodeGenerator = CodeGenerator;
var Whitespace = require("./whitespace");
var SourceMap = require("./source-map");
var Position = require("./position");
var util = require("../util");
var n = require("./node");
var t = require("../types");
var _ = require("lodash");
function CodeGenerator(ast, opts, code) {
opts = opts || {};
this.style = {
semicolons: true,
comments: true,
compact: false,
indent: {
char: " ",
width: 2
}
};
this.comments = ast.comments || [];
this.tokens = ast.tokens || [];
this.opts = opts;
this.ast = ast;
this.buf = "";
this._indent = 0;
this.whitespace = new Whitespace(this.tokens, this.comments);
this.position = new Position;
this.map = new SourceMap(this.position, opts, code);
}
CodeGenerator.generators = {
arrayComprehensions: require("./generators/array-comprehensions"),
templateLiterals: require("./generators/template-literals"),
expressions: require("./generators/expressions"),
statements: require("./generators/statements"),
classes: require("./generators/classes"),
methods: require("./generators/methods"),
modules: require("./generators/modules"),
types: require("./generators/types"),
base: require("./generators/base"),
jsx: require("./generators/jsx")
};
_.each(CodeGenerator.generators, function (generator) {
_.extend(CodeGenerator.prototype, generator);
});
CodeGenerator.prototype.newline = function (i, removeLast) {
if (!this.buf) return;
if (this.style.compact) return;
if (this.endsWith("{\n")) return;
if (_.isBoolean(i)) {
removeLast = i;
i = null;
}
if (_.isNumber(i)) {
var self = this;
_.times(i, function () {
self.newline(null, removeLast);
});
return;
}
if (removeLast && this.isLast("\n")) this.removeLast("\n");
this.removeLast(" ");
this.buf = this.buf.replace(/\n(\s+)$/, "\n");
this._push("\n");
};
CodeGenerator.prototype.removeLast = function (cha) {
if (!this.isLast(cha)) return;
this.buf = this.buf.slice(0, -1);
this.position.unshift(cha);
};
CodeGenerator.prototype.semicolon = function () {
if (this.style.semicolons) this.push(";");
};
CodeGenerator.prototype.ensureSemicolon = function () {
if (!this.isLast(";")) this.semicolon();
};
CodeGenerator.prototype.rightBrace = function () {
this.newline(true);
this.push("}");
};
CodeGenerator.prototype.keyword = function (name) {
this.push(name);
this.push(" ");
};
CodeGenerator.prototype.space = function () {
if (this.buf && !this.isLast([" ", "\n"])) {
this.push(" ");
}
};
CodeGenerator.prototype.push = function (str, noIndent) {
if (this._indent && !noIndent && str !== "\n") {
// we have an indent level and we aren't pushing a newline
var indent = this.getIndent();
// replace all newlines with newlines with the indentation
str = str.replace(/\n/g, "\n" + indent);
// we've got a newline before us so prepend on the indentation
if (this.isLast("\n")) str = indent + str;
}
this._push(str);
};
CodeGenerator.prototype._push = function (str) {
this.position.push(str);
this.buf += str;
};
CodeGenerator.prototype.endsWith = function (str) {
return this.buf.slice(-str.length) === str;
};
CodeGenerator.prototype.isLast = function (cha, trimRight) {
var buf = this.buf;
if (trimRight) buf = buf.trimRight();
var chars = [].concat(cha);
return _.contains(chars, _.last(buf));
};
CodeGenerator.prototype.getIndent = function () {
if (this.style.compact) {
return "";
} else {
return util.repeat(this.indentSize(), this.style.indent.char);
}
};
CodeGenerator.prototype.indentSize = function () {
return this._indent * this.style.indent.width;
};
CodeGenerator.prototype.indent = function () {
this._indent++;
};
CodeGenerator.prototype.dedent = function () {
this._indent--;
};
CodeGenerator.prototype.generate = function () {
var ast = this.ast;
this.print(ast);
this.buf = this.buf.trimRight();
return {
map: this.map.get(),
ast: ast,
code: this.buf
};
};
CodeGenerator.prototype.buildPrint = function (parent) {
var self = this;
var print = function (node, opts) {
return self.print(node, parent, opts);
};
print.sequence = function (nodes, opts) {
opts = opts || {};
opts.statement = true;
return self.printJoin(print, nodes, opts);
};
print.join = function (nodes, opts) {
return self.printJoin(print, nodes, opts);
};
print.block = function (node) {
return self.printBlock(print, node);
};
print.indentOnComments = function (node) {
return self.printAndIndentOnComments(print, node);
};
return print;
};
CodeGenerator.prototype.print = function (node, parent, opts) {
if (!node) return "";
var self = this;
opts = opts || {};
var newline = function (leading) {
var ignoreDuplicates = false;
if (!opts.statement && !n.isUserWhitespacable(node, parent)) {
return;
}
var lines = 0;
if (node.start != null) {
// user node
if (leading) {
lines = self.whitespace.getNewlinesBefore(node);
} else {
lines = self.whitespace.getNewlinesAfter(node);
}
} else {
// generated node
if (!leading) lines++; // always include at least a single line after
var needs = n.needsWhitespaceAfter;
if (leading) needs = n.needsWhitespaceBefore;
lines += needs(node, parent);
}
self.newline(lines, ignoreDuplicates);
};
if (this[node.type]) {
this.printLeadingComments(node, parent);
newline(true);
if (opts.before) opts.before();
this.map.mark(node, "start");
// only compute if this node needs parens if our parent has been changed
// since acorn would've wrapped us in a ParanthesizedExpression
var needsParens = parent !== node._parent && n.needsParens(node, parent);
if (needsParens) this.push("(");
this[node.type](node, this.buildPrint(node), parent);
if (needsParens) this.push(")");
this.map.mark(node, "end");
if (opts.after) opts.after();
newline(false);
this.printTrailingComments(node, parent);
} else {
throw new ReferenceError("unknown node " + node.type + " " + JSON.stringify(node));
}
};
CodeGenerator.prototype.printJoin = function (print, nodes, opts) {
opts = opts || {};
var self = this;
var len = nodes.length;
if (opts.indent) self.indent();
_.each(nodes, function (node, i) {
print(node, {
statement: opts.statement,
after: function () {
if (opts.iterator) {
opts.iterator(node, i);
}
if (opts.separator && i < len - 1) {
self.push(opts.separator);
}
}
});
});
if (opts.indent) self.dedent();
};
CodeGenerator.prototype.printAndIndentOnComments = function (print, node) {
var indent = !!node.leadingComments;
if (indent) this.indent();
print(node);
if (indent) this.dedent();
};
CodeGenerator.prototype.printBlock = function (print, node) {
if (t.isEmptyStatement(node)) {
this.semicolon();
} else {
this.push(" ");
print(node);
}
};
CodeGenerator.prototype.generateComment = function (comment) {
var val = comment.value;
if (comment.type === "Line") {
val = "//" + val;
} else {
val = "/*" + val + "*/";
}
return val;
};
CodeGenerator.prototype.printTrailingComments = function (node, parent) {
this._printComments(this.getComments("trailingComments", node, parent));
};
CodeGenerator.prototype.printLeadingComments = function (node, parent) {
this._printComments(this.getComments("leadingComments", node, parent));
};
CodeGenerator.prototype.getComments = function (key, node, parent) {
if (t.isExpressionStatement(parent)) {
return [];
}
var comments = [];
var nodes = [node];
var self = this;
if (t.isExpressionStatement(node)) {
nodes.push(node.argument);
}
_.each(nodes, function (node) {
comments = comments.concat(self._getComments(key, node));
});
return comments;
};
CodeGenerator.prototype._getComments = function (key, node) {
return (node && node[key]) || [];
};
CodeGenerator.prototype._printComments = function (comments) {
if (this.style.compact) return;
if (!this.style.comments) return;
if (!comments || !comments.length) return;
var self = this;
_.each(comments, function (comment) {
// whitespace before
self.newline(self.whitespace.getNewlinesBefore(comment));
var column = self.position.column;
var val = self.generateComment(comment);
if (column && !self.isLast(["\n", " ", "[", "{"])) {
self._push(" ");
column++;
}
//
var offset = comment.loc.start.column;
if (offset) {
var newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n");
}
var indent = Math.max(self.indentSize(), column);
val = val.replace(/\n/g, "\n" + util.repeat(indent));
if (column === 0) {
val = self.getIndent() + val;
}
//
self._push(val);
// whitespace after
self.newline(self.whitespace.getNewlinesAfter(comment));
});
};

View File

@@ -0,0 +1,25 @@
exports.ComprehensionBlock = function (node, print) {
this.keyword("for");
this.push("(");
print(node.left);
this.push(" of ");
print(node.right);
this.push(")");
};
exports.ComprehensionExpression = function (node, print) {
this.push("[");
print.join(node.blocks, { separator: " " });
this.space();
if (node.filter) {
this.keyword("if");
this.push("(");
print(node.filter);
this.push(")");
this.space();
}
print(node.body);
this.push("]");
};

View File

@@ -0,0 +1,19 @@
exports.File = function (node, print) {
print(node.program);
};
exports.Program = function (node, print) {
print.sequence(node.body);
};
exports.BlockStatement = function (node, print) {
if (node.body.length === 0) {
this.push("{}");
} else {
this.push("{");
this.newline();
print.sequence(node.body, { indent: true });
this.removeLast("\n");
this.rightBrace();
}
};

View File

@@ -0,0 +1,32 @@
exports.ClassExpression =
exports.ClassDeclaration = function (node, print) {
this.push("class");
if (node.id) {
this.space();
print(node.id);
}
if (node.superClass) {
this.push(" extends ");
print(node.superClass);
}
this.space();
print(node.body);
};
exports.ClassBody = function (node, print) {
if (node.body.length === 0) {
this.push("{}");
} else {
this.push("{");
this.newline();
this.indent();
print.sequence(node.body);
this.dedent();
this.rightBrace();
}
};

View File

@@ -0,0 +1,104 @@
var t = require("../../types");
exports.UnaryExpression = function (node, print) {
var hasSpace = /[a-z]$/.test(node.operator);
var arg = node.argument;
if (t.isUpdateExpression(arg) || t.isUnaryExpression(arg)) {
hasSpace = true;
}
if (t.isUnaryExpression(arg) && arg.operator === "!") {
hasSpace = false;
}
this.push(node.operator);
if (hasSpace) this.space();
print(node.argument);
};
exports.ParenthesizedExpression = function (node, print) {
this.push("(");
print(node.expression);
this.push(")");
};
exports.UpdateExpression = function (node, print) {
if (node.prefix) {
this.push(node.operator);
print(node.argument);
} else {
print(node.argument);
this.push(node.operator);
}
};
exports.ConditionalExpression = function (node, print) {
print(node.test);
this.push(" ? ");
print(node.consequent);
this.push(" : ");
print(node.alternate);
};
exports.NewExpression = function (node, print) {
this.push("new ");
print(node.callee);
this.push("(");
print.join(node.arguments, { separator: ", " });
this.push(")");
};
exports.SequenceExpression = function (node, print) {
print.join(node.expressions, { separator: ", " });
};
exports.ThisExpression = function () {
this.push("this");
};
exports.CallExpression = function (node, print) {
print(node.callee);
this.push("(");
print.join(node.arguments, { separator: ", " });
this.push(")");
};
exports.YieldExpression = function (node, print) {
this.push("yield");
if (node.delegate) this.push("*");
if (node.argument) {
this.space();
print(node.argument);
}
};
exports.EmptyStatement = function () {
this.semicolon();
};
exports.ExpressionStatement = function (node, print) {
print(node.expression);
this.semicolon();
};
exports.BinaryExpression =
exports.LogicalExpression =
exports.AssignmentExpression = function (node, print) {
print(node.left);
this.push(" " + node.operator + " ");
print(node.right);
};
exports.MemberExpression = function (node, print) {
print(node.object);
if (node.computed) {
this.push("[");
print(node.property);
this.push("]");
} else {
this.push(".");
print(node.property);
}
};

View File

@@ -0,0 +1,82 @@
var t = require("../../types");
var _ = require("lodash");
exports.XJSAttribute = function (node, print) {
print(node.name);
if (node.value) {
this.push("=");
print(node.value);
}
};
exports.XJSIdentifier = function (node) {
this.push(node.name);
};
exports.XJSNamespacedName = function (node, print) {
print(node.namespace);
this.push(":");
print(node.name);
};
exports.XJSMemberExpression = function (node, print) {
print(node.object);
this.push(".");
print(node.property);
};
exports.XJSSpreadAttribute = function (node, print) {
this.push("{...");
print(node.argument);
this.push("}");
};
exports.XJSExpressionContainer = function (node, print) {
this.push("{");
print(node.expression);
this.push("}");
};
exports.XJSElement = function (node, print) {
var self = this;
var open = node.openingElement;
print(open);
if (open.selfClosing) return;
this.indent();
_.each(node.children, function (child) {
if (t.isLiteral(child) && typeof child.value === "string") {
if (/\S/.test(child.value)) {
return self.push(child.value.replace(/^\s+|\s+$/g, ""));
} else if (/\n/.test(child.value)) {
return self.newline();
}
}
print(child);
});
this.dedent();
print(node.closingElement);
};
exports.XJSOpeningElement = function (node, print) {
this.push("<");
print(node.name);
if (node.attributes.length > 0) {
this.space();
print.join(node.attributes, { separator: " " });
}
this.push(node.selfClosing ? " />" : ">");
};
exports.XJSClosingElement = function (node, print) {
this.push("</");
print(node.name);
this.push(">");
};
exports.XJSEmptyExpression = function () {
this.push("null");
};

View File

@@ -0,0 +1,85 @@
var t = require("../../types");
exports._params = function (node, print) {
var self = this;
this.push("(");
print.join(node.params, {
separator: ", ",
iterator: function (param, i) {
var def = node.defaults && node.defaults[i];
if (def) {
self.push(" = ");
print(def);
}
}
});
if (node.rest) {
if (node.params.length) {
this.push(", ");
}
this.push("...");
print(node.rest);
}
this.push(")");
};
exports._method = function (node, print) {
var value = node.value;
var kind = node.kind;
var key = node.key;
if (!kind || kind === "init") {
if (value.generator) {
this.push("*");
}
} else {
this.push(kind + " ");
}
if (node.computed) {
this.push("[");
print(key);
this.push("]");
} else {
print(key);
}
this._params(value, print);
this.space();
print(value.body);
};
exports.MethodDefinition = function (node, print) {
if (node.static) {
this.push("static ");
}
this._method(node, print);
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, print) {
this.push("function");
if (node.generator) this.push("*");
this.space();
if (node.id) print(node.id);
this._params(node, print);
this.space();
print(node.body);
};
exports.ArrowFunctionExpression = function (node, print) {
if (node.params.length === 1 && !node.defaults.length && !node.rest && t.isIdentifier(node.params[0])) {
print(node.params[0]);
} else {
this._params(node, print);
}
this.push(" => ");
print(node.body);
};

View File

@@ -0,0 +1,86 @@
var t = require("../../types");
var _ = require("lodash");
exports.ImportSpecifier =
exports.ExportSpecifier = function (node, print) {
print(node.id);
if (node.name) {
this.push(" as ");
print(node.name);
}
};
exports.ExportBatchSpecifier = function () {
this.push("*");
};
exports.ExportDeclaration = function (node, print) {
this.push("export ");
var specifiers = node.specifiers;
if (node.default) {
this.push("default ");
}
if (node.declaration) {
print(node.declaration);
} else {
if (specifiers.length === 1 && t.isExportBatchSpecifier(specifiers[0])) {
this.push("*");
} else {
this.push("{");
if (specifiers.length) {
this.space();
print.join(specifiers, { separator: ", " });
this.space();
}
this.push("}");
}
if (node.source) {
this.push(" from ");
print(node.source);
}
}
this.ensureSemicolon();
};
exports.ImportDeclaration = function (node, print) {
var self = this;
this.push("import ");
var specfiers = node.specifiers;
if (specfiers && specfiers.length) {
var foundImportSpecifier = false;
_.each(node.specifiers, function (spec, i) {
if (+i > 0) {
self.push(", ");
}
if (!spec.default && spec.type !== "ImportBatchSpecifier" && !foundImportSpecifier) {
foundImportSpecifier = true;
self.push("{ ");
}
print(spec);
});
if (foundImportSpecifier) {
this.push(" }");
}
this.push(" from ");
}
print(node.source);
this.semicolon();
};
exports.ImportBatchSpecifier = function (node, print) {
this.push("* as ");
print(node.name);
};

View File

@@ -0,0 +1,188 @@
var t = require("../../types");
exports.WithStatement = function (node, print) {
this.keyword("with");
this.push("(");
print(node.object);
print.block(node.body);
};
exports.IfStatement = function (node, print) {
this.keyword("if");
this.push("(");
print(node.test);
this.push(") ");
print.indentOnComments(node.consequent);
if (node.alternate) {
if (this.isLast("}")) this.space();
this.keyword("else");
print.indentOnComments(node.alternate);
}
};
exports.ForStatement = function (node, print) {
this.keyword("for");
this.push("(");
print(node.init);
this.push(";");
if (node.test) {
this.space();
print(node.test);
}
this.push(";");
if (node.update) {
this.space();
print(node.update);
}
this.push(")");
print.block(node.body);
};
exports.WhileStatement = function (node, print) {
this.keyword("while");
this.push("(");
print(node.test);
this.push(")");
print.block(node.body);
};
var buildForXStatement = function (op) {
return function (node, print) {
this.keyword("for");
this.push("(");
print(node.left);
this.push(" " + op + " ");
print(node.right);
this.push(")");
print.block(node.body);
};
};
exports.ForInStatement = buildForXStatement("in");
exports.ForOfStatement = buildForXStatement("of");
exports.DoWhileStatement = function (node, print) {
this.keyword("do");
print(node.body);
this.space();
this.keyword("while");
this.push("(");
print(node.test);
this.push(");");
};
var buildLabelStatement = function (prefix, key) {
return function (node, print) {
this.push(prefix);
var label = node[key || "label"];
if (label) {
this.space();
print(label);
}
this.semicolon();
};
};
exports.ContinueStatement = buildLabelStatement("continue");
exports.ReturnStatement = buildLabelStatement("return", "argument");
exports.BreakStatement = buildLabelStatement("break");
exports.LabeledStatement = function (node, print) {
print(node.label);
this.push(": ");
print(node.body);
};
exports.TryStatement = function (node, print) {
this.keyword("try");
print(node.block);
this.space();
print(node.handler);
if (node.finalizer) {
this.space();
this.push("finally ");
print(node.finalizer);
}
};
exports.CatchClause = function (node, print) {
this.keyword("catch");
this.push("(");
print(node.param);
this.push(") ");
print(node.body);
};
exports.ThrowStatement = function (node, print) {
this.push("throw ");
print(node.argument);
this.semicolon();
};
exports.SwitchStatement = function (node, print) {
this.keyword("switch");
this.push("(");
print(node.discriminant);
this.push(") {");
print.sequence(node.cases, { indent: true });
this.push("}");
//if (node.cases.length) {
// this.newline();
// print.sequence(node.cases, { indent: true });
// this.newline();
// this.rightBrace();
//} else {
// this.push("}");
//}
};
exports.SwitchCase = function (node, print) {
if (node.test) {
this.push("case ");
print(node.test);
this.push(":");
} else {
this.push("default:");
}
if (node.consequent.length === 1) {
this.space();
print(node.consequent[0]);
} else if (node.consequent.length > 1) {
this.newline();
print.sequence(node.consequent, { indent: true });
}
};
exports.DebuggerStatement = function () {
this.push("debugger;");
};
exports.VariableDeclaration = function (node, print, parent) {
this.push(node.kind + " ");
print.join(node.declarations, { separator: ", " });
if (!t.isFor(parent)) {
this.semicolon();
}
};
exports.VariableDeclarator = function (node, print) {
if (node.init) {
print(node.id);
this.push(" = ");
print(node.init);
} else {
print(node.id);
}
};

View File

@@ -0,0 +1,30 @@
var _ = require("lodash");
exports.TaggedTemplateExpression = function (node, print) {
print(node.tag);
print(node.quasi);
};
exports.TemplateElement = function (node) {
this._push(node.value.raw);
};
exports.TemplateLiteral = function (node, print) {
this.push("`");
var quasis = node.quasis;
var self = this;
var len = quasis.length;
_.each(quasis, function (quasi, i) {
print(quasi);
if (i + 1 < len) {
self.push("${ ");
print(node.expressions[i]);
self.push(" }");
}
});
this._push("`");
};

View File

@@ -0,0 +1,86 @@
var _ = require("lodash");
exports.Identifier = function (node) {
this.push(node.name);
};
exports.SpreadElement = function (node, print) {
this.push("...");
print(node.argument);
};
exports.ObjectExpression =
exports.ObjectPattern = function (node, print) {
var props = node.properties;
if (props.length) {
this.push("{");
this.space();
print.join(props, { separator: ", ", indent: true });
this.space();
this.push("}");
} else {
this.push("{}");
}
};
exports.Property = function (node, print) {
if (node.method || node.kind === "get" || node.kind === "set") {
this._method(node, print);
} else {
if (node.computed) {
this.push("[");
print(node.key);
this.push("]");
} else {
print(node.key);
if (node.shorthand) return;
}
this.push(": ");
print(node.value);
}
};
exports.ArrayExpression =
exports.ArrayPattern = function (node, print) {
var elems = node.elements;
var self = this;
var len = elems.length;
this.push("[");
_.each(elems, function (elem, i) {
if (!elem) {
// If the array expression ends with a hole, that hole
// will be ignored by the interpreter, but if it ends with
// two (or more) holes, we need to write out two (or more)
// commas so that the resulting code is interpreted with
// both (all) of the holes.
self.push(",");
} else {
if (i > 0) self.push(" ");
print(elem);
if (i < len - 1) self.push(",");
}
});
this.push("]");
};
exports.Literal = function (node) {
var val = node.value;
var type = typeof val;
if (type === "boolean" || type === "number" || type === "string") {
this.push(JSON.stringify(val));
} else if (node.regex) {
this.push("/" + node.regex.pattern + "/" + node.regex.flags);
} else if (val === null) {
this.push("null");
} else if (node.raw) {
this.push(node.raw);
}
};

290
lib/6to5/generation/node.js Normal file
View File

@@ -0,0 +1,290 @@
module.exports = Node;
var t = require("../types");
var _ = require("lodash");
function Node(node, parent) {
this.parent = parent;
this.node = node;
}
//
Node.whitespace = {
FunctionExpression: 1,
FunctionStatement: 1,
ClassExpression: 1,
ClassStatement: 1,
ForOfStatement: 1,
ForInStatement: 1,
ForStatement: 1,
SwitchStatement: 1,
IfStatement: { before: 1 },
//Property: { before: 1 },
Literal: { after: 1 }
};
_.each(Node.whitespace, function (amounts, type) {
if (_.isNumber(amounts)) amounts = { after: amounts, before: amounts };
Node.whitespace[type] = amounts;
});
//
Node.PRECEDENCE = {};
_.each([
["||"],
["&&"],
["|"],
["^"],
["&"],
["==", "===", "!=", "!=="],
["<", ">", "<=", ">=", "in", "instanceof"],
[">>", "<<", ">>>"],
["+", "-"],
["*", "/", "%"]
], function (tier, i) {
_.each(tier, function (op) {
Node.PRECEDENCE[op] = i;
});
});
//
Node.prototype.isUserWhitespacable = function () {
//var parent = this.parent;
var node = this.node;
if (t.isUserWhitespacable(node)) {
return true;
}
//if (t.isArrayExpression(parent)) {
// return true;
//}
return false;
};
Node.prototype.needsWhitespace = function (type) {
var parent = this.parent;
var node = this.node;
if (!node) return 0;
if (t.isExpressionStatement(node)) {
node = node.expression;
}
if (type === "before") {
if (t.isProperty(node) && parent.properties[0] === node) {
return 1;
}
}
if (type === "after") {
if (t.isCallExpression(node)) {
return 1;
}
var exprs = [];
if (t.isVariableDeclaration(node)) {
exprs = _.map(node.declarations, "init");
}
if (t.isArrayExpression(node)) {
exprs = node.elements;
}
if (t.isObjectExpression(node)) {
exprs = node.properties;
}
var lines = 0;
_.each(exprs, function (expr) {
lines = Node.needsWhitespace(expr, node, type);
if (lines) return false;
});
if (lines) return lines;
}
if (t.isCallExpression(node) && t.isFunction(node.callee)) {
return 1;
}
var opts = Node.whitespace[node.type];
return (opts && opts[type]) || 0;
};
Node.prototype.needsWhitespaceBefore = function () {
return this.needsWhitespace("before");
};
Node.prototype.needsWhitespaceAfter = function () {
return this.needsWhitespace("after");
};
Node.prototype.needsParens = function () {
var parent = this.parent;
var node = this.node;
if (!parent) return false;
//
if (t.isUnaryLike(node)) {
return t.isMemberExpression(parent) && parent.object === node;
}
if (t.isBinary(node)) {
//
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
//
if (t.isUnaryLike(parent)) {
return true;
}
//
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
if (t.isBinary(parent)) {
var parentOp = parent.operator;
var parentPos = Node.PRECEDENCE[parentOp];
var nodeOp = node.operator;
var nodePos = Node.PRECEDENCE[nodeOp];
if (parentPos > nodePos) {
return true;
}
if (parentPos === nodePos && parent.right === node) {
return true;
}
}
}
if (t.isBinaryExpression(node) && node.operator === "in") {
// var i = (1 in []);
if (t.isVariableDeclarator(parent)) {
return true;
}
// for ((1 in []);;);
if (t.isFor(parent)) {
return true;
}
}
// (class {});
if (t.isClassExpression(node) && t.isExpressionStatement(parent)) {
return true;
}
if (t.isSequenceExpression(node)) {
if (t.isForStatement(parent)) {
// Although parentheses wouldn't hurt around sequence
// expressions in the head of for loops, traditional style
// dictates that e.g. i++, j++ should not be wrapped with
// parentheses.
return false;
}
if (t.isExpressionStatement(parent) && parent.expression === node) {
return false;
}
// Otherwise err on the side of overparenthesization, adding
// explicit exceptions above if this proves overzealous.
return true;
}
//
if (t.isYieldExpression(node)) {
return t.isBinary(parent) ||
t.isUnaryLike(parent) ||
t.isCallExpression(parent) ||
t.isMemberExpression(parent) ||
t.isNewExpression(parent) ||
t.isConditionalExpression(parent) ||
t.isYieldExpression(parent);
}
if (t.isNewExpression(parent) && parent.callee === node) {
return t.isCallExpression(node) || _.some(node, function (val) {
return t.isCallExpression(val);
});
}
// (1).valueOf()
if (t.isLiteral(node) && _.isNumber(node.value) && t.isMemberExpression(parent) && parent.object === node) {
return true;
}
if (t.isAssignmentExpression(node) || t.isConditionalExpression(node)) {
//
if (t.isUnaryLike(parent)) {
return true;
}
//
if (t.isBinary(parent)) {
return true;
}
//
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
//
if (t.isConditionalExpression(parent) && parent.test === node) {
return true;
}
//
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
}
if (t.isFunctionExpression(node)) {
// function () {};
if (t.isExpressionStatement(parent)) {
return true;
}
// (function test() {}).name;
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
// (function () {})();
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
}
// ({ x, y }) = { x: 5, y: 6 };
if (t.isObjectPattern(node) && t.isAssignmentExpression(parent) && parent.left == node) {
return true;
}
return false;
};
_.each(Node.prototype, function (fn, key) {
Node[key] = function (node, parent) {
var n = new Node(node, parent);
var args = _.toArray(arguments).slice(2);
return n[key].apply(n, args);
};
});

View File

@@ -0,0 +1,33 @@
module.exports = Position;
var _ = require("lodash");
function Position() {
this.line = 1;
this.column = 0;
}
Position.prototype.push = function (str) {
var self = this;
_.each(str, function (cha) {
if (cha === "\n") {
self.line++;
self.column = 0;
} else {
self.column++;
}
});
};
Position.prototype.unshift = function (str) {
var self = this;
_.each(str, function (cha) {
if (cha === "\n") {
self.line--;
} else {
self.column--;
}
});
};

View File

@@ -0,0 +1,55 @@
module.exports = SourceMap;
var sourceMap = require("source-map");
var t = require("../types");
function SourceMap(position, opts, code) {
this.position = position;
this.opts = opts;
if (opts.sourceMap) {
this.map = new sourceMap.SourceMapGenerator({
file: opts.sourceMapName
});
this.map.setSourceContent(opts.sourceFileName, code);
} else {
this.map = null;
}
}
SourceMap.prototype.get = function () {
var map = this.map;
if (map) {
return map.toJSON();
} else {
return map;
}
};
SourceMap.prototype.mark = function (node, type) {
var loc = node.loc;
if (!loc) return; // no location info
var map = this.map;
if (!map) return; // no source map
if (t.isProgram(node) || t.isFile(node)) return; // illegal mapping nodes
var position = this.position;
var generated = {
line: position.line,
column: position.column
};
var original = loc[type];
if (generated.line === original.line && generated.column === original.column) return; // nothing to map
map.addMapping({
source: this.opts.sourceFileName,
generated: generated,
original: original
});
};

View File

@@ -0,0 +1,58 @@
module.exports = Whitespace;
var _ = require("lodash");
function Whitespace(tokens, comments) {
this.tokens = _.sortBy(tokens.concat(comments), "start");
this.used = [];
}
Whitespace.prototype.getNewlinesBefore = function (node) {
var startToken;
var endToken;
var tokens = this.tokens;
_.each(tokens, function (token, i) {
// this is the token this node starts with
if (node.start === token.start) {
startToken = tokens[i - 1];
endToken = token;
return false;
}
});
return this.getNewlinesBetween(startToken, endToken);
};
Whitespace.prototype.getNewlinesAfter = function (node) {
var startToken;
var endToken;
var tokens = this.tokens;
_.each(tokens, function (token, i) {
// this is the token this node ends with
if (node.end === token.end) {
startToken = token;
endToken = tokens[i + 1];
return false;
}
});
return this.getNewlinesBetween(startToken, endToken);
};
Whitespace.prototype.getNewlinesBetween = function (startToken, endToken) {
var start = startToken ? startToken.loc.end.line : 1;
var end = endToken.loc.start.line;
var lines = 0;
for (var line = start; line < end; line++) {
if (!_.contains(this.used, line)) {
this.used.push(line);
lines++;
}
}
return lines;
};

View File

@@ -1,8 +1,9 @@
var transform = require("./transform");
var transform = require("./transformation/transform");
var util = require("./util");
var fs = require("fs");
var _ = require("lodash");
exports.util = require("./util");
exports.runtime = require("./runtime");
exports.register = function (opts) {
var register = require("./register");
@@ -14,6 +15,8 @@ exports.polyfill = function () {
require("./polyfill");
};
exports.canCompile = util.canCompile;
exports.transform = transform;
exports.transformFile = function (filename, opts, callback) {

28
lib/6to5/patch.js Normal file
View File

@@ -0,0 +1,28 @@
var t = require("./types");
var _ = require("lodash");
var types = require("ast-types");
var def = types.Type.def;
// Program wrapper
def("File")
.bases("Node")
.build("program")
.field("program", def("Program"));
// Non-standard Acorn type
def("ParenthesizedExpression")
.bases("Expression")
.build("expression")
.field("expression", def("Expression"));
// Same as ImportNamespaceSpecifier but `id` is `name`
def("ImportBatchSpecifier")
.bases("Specifier")
.build("name")
.field("name", def("Identifier"));
types.finalize();
var estraverse = require("estraverse");
_.extend(estraverse.VisitorKeys, t.VISITOR_KEYS);

View File

@@ -1,3 +1,6 @@
require("es6-symbol/implement");
if (typeof Symbol === "undefined") {
require("es6-symbol/implement");
}
require("es6-shim");
require("regenerator/runtime");
require("regenerator-6to5/runtime");

View File

@@ -6,7 +6,7 @@ var _ = require("lodash");
sourceMapSupport.install({
retrieveSourceMap: function (source) {
var map = maps[source];
var map = maps && maps[source];
if (map) {
return {
url: null,
@@ -20,17 +20,56 @@ sourceMapSupport.install({
//
var blacklist = [];
var blacklistTest = function (transformer, code) {
try {
if (_.isFunction(code)) {
code();
} else {
new Function(code);
}
blacklist.push(transformer);
} catch (err) {
if (err.name !== "SyntaxError") throw err;
}
};
blacklistTest("arrayComprehension", "var foo = [for (foo of bar) foo * foo];");
blacklistTest("arrowFunctions", "var foo = x => x * x;");
blacklistTest("classes", "class Foo {}");
blacklistTest("computedPropertyNames", "var foo = { [foo]: bar };");
//blacklistTest("constants", "const foo = 0;");
blacklistTest("defaultParamaters", "var foo = function (bar = 0) {};");
blacklistTest("destructuring", "var { x, y } = { x: 0, y: 0 };");
blacklistTest("forOf", "for (var foo of bar) {}");
blacklistTest("generators", "function* foo() {}");
blacklistTest("letScoping", "let foo = 0;");
blacklistTest("modules", 'import foo from "from";');
blacklistTest("propertyMethodAssignment", "{ get foo() {} }");
blacklistTest("propertyNameShorthand", "var foo = { x, y };");
blacklistTest("restParameters", "function foo(...bar) {}");
blacklistTest("spread", "foo(...bar);");
blacklistTest("templateLiterals", "var foo = `foo`;");
blacklistTest("unicodeRegex", function () { new RegExp("foo", "u"); });
//
var ignoreRegex = /node_modules/;
var onlyRegex;
var whitelist = [];
var exts = {};
var maps = {};
var old = require.extensions[".js"];
var loader = function (m, filename) {
if (ignoreRegex && ignoreRegex.test(filename)) {
if ((ignoreRegex && ignoreRegex.test(filename)) || (onlyRegex && !onlyRegex.test(filename))) {
return old.apply(this, arguments);
}
var result = to5.transformFileSync(filename, {
whitelist: whitelist,
blacklist: blacklist,
sourceMap: true
});
@@ -55,12 +94,16 @@ var hookExtensions = function (_exts) {
hookExtensions([".es6", ".js"]);
module.exports = function (opts) {
// normalise options
opts = opts || {};
if (_.isRegExp(opts)) opts = { ignoreRegex: opts };
if (_.isRegExp(opts)) opts = { ignore: opts };
if (opts.ignoreRegex != null) opts.ignore = opts.ignoreRegex;
if (opts.ignoreRegex != null) {
ignoreRegex = opts.ignoreRegex;
}
if (opts.only != null) onlyRegex = opts.only;
if (opts.ignore != null) ignoreRegex = opts.ignore;
if (opts.extensions) hookExtensions(opts.extensions);
if (opts.blacklist) blacklist = opts.blacklist;
if (opts.whitelist) whitelist = opts.whitelist;
};

31
lib/6to5/runtime.js Normal file
View File

@@ -0,0 +1,31 @@
var generator = require("./generation/generator");
var util = require("./util");
var File = require("./file");
var t = require("./types");
var _ = require("lodash");
module.exports = function (namespace) {
namespace = t.identifier(namespace || "to5Runtime");
var body = [];
var container = t.functionExpression(null, [], t.blockStatement(body));
var tree = t.program([t.expressionStatement(t.callExpression(container, []))]);
body.push(util.template("self-global", true));
body.push(t.variableDeclaration("var", [
t.variableDeclarator(
namespace,
t.assignmentExpression("=", t.memberExpression(t.identifier("self"), namespace), t.objectExpression([]))
)
]));
_.each(File.declarations, function (name) {
var key = t.identifier(t.toIdentifier(name));
body.push(t.expressionStatement(
t.assignmentExpression("=", t.memberExpression(namespace, key), util.template(name))
));
});
return generator(tree).code;
};

View File

@@ -0,0 +1,4 @@
(function (child, staticProps, instanceProps) {
if (staticProps) Object.defineProperties(child, staticProps);
if (instanceProps) Object.defineProperties(child.prototype, instanceProps);
})

View File

@@ -0,0 +1 @@
if (typeof RETURN === "object") return RETURN.v;

View File

@@ -0,0 +1 @@
var self = typeof global === "undefined" ? window : global;

View File

@@ -1,8 +1,8 @@
module.exports = AMDFormatter;
var CommonJSFormatter = require("./common");
var util = require("../util");
var b = require("acorn-ast-types").builders;
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
function AMDFormatter(file) {
@@ -18,21 +18,21 @@ AMDFormatter.prototype.transform = function (ast) {
// build an array of module names
var names = [b.literal("exports")];
var names = [t.literal("exports")];
_.each(this.ids, function (id, name) {
names.push(b.literal(name));
names.push(t.literal(name));
});
names = b.arrayExpression(names);
names = t.arrayExpression(names);
// build up define container
var params = _.values(this.ids);
params.unshift(b.identifier("exports"));
params.unshift(t.identifier("exports"));
var container = b.functionExpression(null, params, b.blockStatement(body));
var call = b.callExpression(b.identifier("define"), [names, container]);
var container = t.functionExpression(null, params, t.blockStatement(body));
var call = t.callExpression(t.identifier("define"), [names, container]);
program.body = [b.expressionStatement(call)];
program.body = [t.expressionStatement(call)];
};
AMDFormatter.prototype._push = function (node) {
@@ -42,7 +42,7 @@ AMDFormatter.prototype._push = function (node) {
if (ids[id]) {
return ids[id];
} else {
return this.ids[id] = b.identifier(this.file.generateUid(id));
return this.ids[id] = t.identifier(this.file.generateUid(id));
}
};
@@ -51,26 +51,26 @@ AMDFormatter.prototype.import = function (node) {
};
AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var key = util.getSpecifierName(specifier);
var key = t.getSpecifierName(specifier);
var id = specifier.id;
// import foo from "foo";
if (specifier.default) {
id = b.identifier("default");
id = t.identifier("default");
}
var ref;
if (specifier.type === "ImportBatchSpecifier") {
if (t.isImportBatchSpecifier(specifier)) {
// import * as bar from "foo";
ref = this._push(node);
} else {
// import foo from "foo";
ref = b.memberExpression(this._push(node), id, false);
ref = t.memberExpression(this._push(node), id, false);
}
nodes.push(b.variableDeclaration("var", [
b.variableDeclarator(key, ref)
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(key, ref)
]));
};

View File

@@ -1,7 +1,7 @@
module.exports = CommonJSFormatter;
var util = require("../util");
var b = require("acorn-ast-types").builders;
var util = require("../../util");
var t = require("../../types");
function CommonJSFormatter(file) {
this.file = file;
@@ -10,16 +10,18 @@ function CommonJSFormatter(file) {
CommonJSFormatter.prototype.import = function (node, nodes) {
// import "foo";
nodes.push(util.template("require", {
//inherits: node,
MODULE_NAME: node.source.raw
}, true));
};
CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var variableName = util.getSpecifierName(specifier);
var variableName = t.getSpecifierName(specifier);
// import foo from "foo";
if (specifier.default) {
specifier.id = b.identifier("default");
specifier.id = t.identifier("default");
}
var templateName = "require-assign";
@@ -28,6 +30,8 @@ CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes)
if (specifier.type !== "ImportBatchSpecifier") templateName += "-key";
nodes.push(util.template(templateName, {
//inherits: node.specifiers.length === 1 && node,
VARIABLE_NAME: variableName,
MODULE_NAME: node.source.raw,
KEY: specifier.id
@@ -38,44 +42,73 @@ CommonJSFormatter.prototype.export = function (node, nodes) {
var declar = node.declaration;
if (node.default) {
util.ensureExpressionType(declar);
var ref = declar;
if (t.isClass(ref) || t.isFunction(ref)) {
if (ref.id) {
nodes.push(t.toStatement(ref));
ref = ref.id;
}
}
nodes.push(util.template("exports-default", {
VALUE: declar
//inherits: node,
VALUE: ref
}, true));
} else {
var id = declar.id;
if (declar.type === "VariableDeclaration") {
id = declar.declarations[0].id;
var assign;
if (t.isVariableDeclaration(declar)) {
var decl = declar.declarations[0];
if (decl.init) {
decl.init = util.template("exports-assign", {
//inherits: node,
VALUE: decl.init,
KEY: decl.id
});
}
nodes.push(declar);
} else {
assign = util.template("exports-assign", {
//inherits: node,
VALUE: declar.id,
KEY: declar.id
}, true);
nodes.push(t.toStatement(declar));
nodes.push(assign);
if (t.isFunctionDeclaration(declar)) {
assign._blockHoist = true;
}
}
var assign = util.template("exports-assign", {
VALUE: id,
KEY: id
}, true);
nodes.push(declar);
if (declar.type === "FunctionDeclaration") {
assign._blockHoist = true;
}
nodes.push(assign);
}
};
CommonJSFormatter.prototype._exportSpecifier = function (getRef, specifier, node, nodes) {
var variableName = util.getSpecifierName(specifier);
var variableName = t.getSpecifierName(specifier);
var inherits = false;
if (node.specifiers.length === 1) inherits = node;
if (node.source) {
if (specifier.type === "ExportBatchSpecifier") {
if (t.isExportBatchSpecifier(specifier)) {
// export * from "foo";
nodes.push(util.template("exports-wildcard", {
//inherits: inherits,
OBJECT: getRef()
}, true));
} else {
// export { foo } from "test";
nodes.push(util.template("exports-assign-key", {
//inherits: inherits,
VARIABLE_NAME: variableName.name,
OBJECT: getRef(),
KEY: specifier.id
@@ -84,6 +117,8 @@ CommonJSFormatter.prototype._exportSpecifier = function (getRef, specifier, node
} else {
// export { foo };
nodes.push(util.template("exports-assign", {
//inherits: inherits,
VALUE: specifier.id,
KEY: variableName
}, true));
@@ -92,6 +127,6 @@ CommonJSFormatter.prototype._exportSpecifier = function (getRef, specifier, node
CommonJSFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
return this._exportSpecifier(function () {
return b.callExpression(b.identifier("require"), [node.source]);
return t.callExpression(t.identifier("require"), [node.source]);
}, specifier, node, nodes);
};

View File

@@ -0,0 +1,24 @@
module.exports = IgnoreFormatter;
var t = require("../../types");
function IgnoreFormatter() {
}
IgnoreFormatter.prototype.import = function () {
};
IgnoreFormatter.prototype.importSpecifier = function () {
};
IgnoreFormatter.prototype.export = function (node, nodes) {
var declar = t.toStatement(node.declaration, true);
if (declar) nodes.push(t.inherits(declar, node));
};
IgnoreFormatter.prototype.exportSpecifier = function () {
};

View File

@@ -1,8 +1,8 @@
module.exports = UMDFormatter;
var AMDFormatter = require("./amd");
var util = require("../util");
var b = require("acorn-ast-types").builders;
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
function UMDFormatter(file) {
@@ -20,28 +20,28 @@ UMDFormatter.prototype.transform = function (ast) {
var names = [];
_.each(this.ids, function (id, name) {
names.push(b.literal(name));
names.push(t.literal(name));
});
// factory
var ids = _.values(this.ids);
var args = [b.identifier("exports")].concat(ids);
var args = [t.identifier("exports")].concat(ids);
var factory = b.functionExpression(null, args, b.blockStatement(body));
var factory = t.functionExpression(null, args, t.blockStatement(body));
// runner
var runner = util.template("umd-runner-body", {
AMD_ARGUMENTS: b.arrayExpression([b.literal("exports")].concat(names)),
AMD_ARGUMENTS: t.arrayExpression([t.literal("exports")].concat(names)),
COMMON_ARGUMENTS: names.map(function (name) {
return b.callExpression(b.identifier("require"), [name]);
return t.callExpression(t.identifier("require"), [name]);
})
});
//
var call = b.callExpression(runner, [factory]);
program.body = [b.expressionStatement(call)];
var call = t.callExpression(runner, [factory]);
program.body = [t.expressionStatement(call)];
};

View File

@@ -1,74 +1,14 @@
module.exports = transform;
var Transformer = require("./transformer");
var sourceMap = require("source-map");
var recast = require("acorn-recast");
var File = require("./file");
var util = require("./util");
var File = require("../file");
var _ = require("lodash");
function transform(code, opts) {
opts = opts || {};
code = (code || "") + "";
var file = new File(opts);
return file.parse(code);
}
transform.test = function (task, assert) {
var actual = task.actual;
var expect = task.expect;
var opts = task.options;
var exec = task.exec;
var getOpts = function (filename) {
return _.merge({ filename: filename }, opts);
};
var execCode = exec.code.trim();
var result;
if (execCode) {
result = transform(execCode, getOpts(exec.filename));
execCode = result.code;
require("./polyfill");
var fn = new Function("assert", execCode);
fn(assert);
} else {
var actualCode = actual.code.trim();
var expectCode = expect.code.trim();
var printOpts = { tabWidth: 2 };
result = transform(actualCode, getOpts(actual.filename));
actualCode = recast.prettyPrint(result.ast, printOpts).code;
var expectAst = util.parse(expect, expectCode);
var expectResult = recast.prettyPrint(expectAst, printOpts);
expectCode = expectResult.code;
assert.equal(actualCode, expectCode);
}
if (task.sourceMap) {
assert.deepEqual(task.sourceMap, result.map);
}
if (task.sourceMappings) {
var consumer = new sourceMap.SourceMapConsumer(result.map);
_.each(task.sourceMappings, function (mapping, i) {
var generated = mapping.generated;
var original = mapping.original;
var pos = consumer.originalPositionFor(generated);
var msg = "source mapping " + i + " - generated: " + generated.line + ":" + generated.column;
assert.equal(pos.line + ":" + pos.column, original.line + ":" + original.column, msg);
});
}
};
transform._ensureTransformerNames = function (type, keys) {
_.each(keys, function (key) {
if (!_.has(transform.transformers, key)) {
@@ -77,24 +17,37 @@ transform._ensureTransformerNames = function (type, keys) {
});
};
transform.transformers = {
transform.transformers = {};
transform.moduleFormatters = {
common: require("./modules/common"),
ignore: require("./modules/ignore"),
amd: require("./modules/amd"),
umd: require("./modules/umd")
};
_.each({
modules: require("./transformers/modules"),
computedPropertyNames: require("./transformers/computed-property-names"),
propertyNameShorthand: require("./transformers/property-name-shorthand"),
constants: require("./transformers/constants"),
arrayComprehension: require("./transformers/array-comprehension"),
arrowFunctions: require("./transformers/arrow-functions"),
classes: require("./transformers/classes"),
_propertyLiterals: require("./transformers/_property-literals"),
computedPropertyNames: require("./transformers/computed-property-names"),
spread: require("./transformers/spread"),
templateLiterals: require("./transformers/template-literals"),
propertyMethodAssignment: require("./transformers/property-method-assignment"),
defaultParameters: require("./transformers/default-parameters"),
letScoping: require("./transformers/let-scoping"),
restParameters: require("./transformers/rest-parameters"),
destructuring: require("./transformers/destructuring"),
letScoping: require("./transformers/let-scoping"),
forOf: require("./transformers/for-of"),
unicodeRegex: require("./transformers/unicode-regex"),
generators: require("./transformers/generators"),
numericLiterals: require("./transformers/numeric-literals"),
react: require("./transformers/react"),
jsx: require("./transformers/jsx"),
@@ -102,17 +55,10 @@ transform.transformers = {
_aliasFunctions: require("./transformers/_alias-functions"),
_blockHoist: require("./transformers/_block-hoist"),
_declarations: require("./transformers/_declarations"),
_moduleFormatter: require("./transformers/_module-formatter"),
useStrict: require("./transformers/use-strict")
};
useStrict: require("./transformers/use-strict"),
transform.moduleFormatters = {
common: require("./modules/common"),
amd: require("./modules/amd"),
umd: require("./modules/umd")
};
_.each(transform.transformers, function (transformer, key) {
_moduleFormatter: require("./transformers/_module-formatter")
}, function (transformer, key) {
transform.transformers[key] = new Transformer(key, transformer);
});

View File

@@ -1,6 +1,7 @@
module.exports = Transformer;
var traverse = require("./traverse");
var traverse = require("../traverse");
var t = require("../types");
var _ = require("lodash");
function Transformer(key, transformer) {
@@ -27,14 +28,18 @@ Transformer.prototype.transform = function (file) {
var transformer = this.transformer;
var ast = file.ast;
if (transformer.ast && transformer.ast.enter) {
transformer.ast.enter(ast, file);
}
var astRun = function (key) {
if (transformer.ast && transformer.ast[key]) {
transformer.ast[key](ast, file);
}
};
astRun("enter");
var build = function (exit) {
return function (node, parent) {
return function (node, parent, scope) {
// add any node type aliases that exist
var types = [node.type].concat(traverse.aliases[node.type] || []);
var types = [node.type].concat(t.ALIAS_KEYS[node.type] || []);
var fns = transformer.all;
@@ -49,7 +54,7 @@ Transformer.prototype.transform = function (file) {
if (exit) fn = fns.exit;
if (!fn) return;
return fn(node, parent, file);
return fn(node, parent, file, scope);
};
};
@@ -58,19 +63,20 @@ Transformer.prototype.transform = function (file) {
exit: build(true)
});
if (transformer.ast && transformer.ast.exit) {
transformer.ast.exit(ast, file);
}
astRun("exit");
};
Transformer.prototype.canRun = function (file) {
var opts = file.opts;
var key = this.key;
var blacklist = opts.blacklist;
if (blacklist.length && _.contains(blacklist, this.key)) return false;
if (blacklist.length && _.contains(blacklist, key)) return false;
var whitelist = opts.whitelist;
if (whitelist.length && !_.contains(whitelist, this.key)) return false;
if (key[0] !== "_") {
var whitelist = opts.whitelist;
if (whitelist.length && !_.contains(whitelist, key)) return false;
}
return true;
};

View File

@@ -1,25 +1,24 @@
var traverse = require("../traverse");
var util = require("../util");
var b = require("acorn-ast-types").builders;
var traverse = require("../../traverse");
var t = require("../../types");
var go = function (getBody, node, file) {
var go = function (getBody, node, file, scope) {
var argumentsId;
var thisId;
var getArgumentsId = function () {
return argumentsId = argumentsId || b.identifier(file.generateUid("arguments"));
return argumentsId = argumentsId || t.identifier(file.generateUid("arguments", scope));
};
var getThisId = function () {
return thisId = thisId || b.identifier(file.generateUid("this"));
return thisId = thisId || t.identifier(file.generateUid("this", scope));
};
// traverse the function and find all alias functions so we can alias
// arguments and this if neccesary
// arguments and this if necessary
traverse(node, function (node) {
var _aliasFunction = node._aliasFunction;
if (!_aliasFunction) {
if (traverse.isFunction(node)) {
if (t.isFunction(node)) {
// stop traversal of this node as it'll be hit again by this transformer
return false;
} else {
@@ -30,22 +29,24 @@ var go = function (getBody, node, file) {
// traverse all child nodes of this function and find arguments and this
traverse(node, function (node, parent) {
if (_aliasFunction === "arrows") {
if (traverse.isFunction(node) && node._aliasFunction !== "arrows") {
if (t.isFunction(node) && node._aliasFunction !== "arrows") {
return false;
}
}
if (node._ignoreAliasFunctions) return;
var getId;
if (node.type === "Identifier" && node.name === "arguments") {
if (t.isIdentifier(node) && node.name === "arguments") {
getId = getArgumentsId;
} else if (node.type === "ThisExpression") {
} else if (t.isThisExpression(node)) {
getId = getThisId;
} else {
return;
}
if (util.isReferenced(node, parent)) return getId();
if (t.isReferenced(node, parent)) return getId();
});
return false;
@@ -55,30 +56,30 @@ var go = function (getBody, node, file) {
var pushDeclaration = function (id, init) {
body = body || getBody();
body.unshift(b.variableDeclaration("var", [
b.variableDeclarator(id, init)
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(id, init)
]));
};
if (argumentsId) {
pushDeclaration(argumentsId, b.identifier("arguments"));
pushDeclaration(argumentsId, t.identifier("arguments"));
}
if (thisId) {
pushDeclaration(thisId, b.identifier("this"));
pushDeclaration(thisId, t.identifier("this"));
}
};
exports.Program = function (node, parent, file) {
exports.Program = function (node, parent, file, scope) {
go(function () {
return node.body;
}, node, file);
}, node, file, scope);
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, file) {
exports.FunctionExpression = function (node, parent, file, scope) {
go(function () {
util.ensureBlock(node);
t.ensureBlock(node);
return node.body.body;
}, node, file);
}, node, file, scope);
};

View File

@@ -1,12 +1,12 @@
var b = require("acorn-ast-types").builders;
var t = require("../../types");
var _ = require("lodash");
module.exports = function (ast, file) {
var body = ast.program.body;
_.each(file.declarations, function (declar) {
body.unshift(b.variableDeclaration("var", [
b.variableDeclarator(declar.uid, declar.node)
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(declar.uid, declar.node)
]));
});
};

View File

@@ -0,0 +1,15 @@
var esutils = require("esutils");
var t = require("../../types");
var _ = require("lodash");
exports.Property = function (node) {
// ignore key literals that are valid identifiers
var key = node.key;
if (t.isLiteral(key) && _.isString(key.value) && esutils.keyword.isIdentifierName(key.value)) {
key.type = "Identifier";
key.name = key.value;
delete key.value;
node.computed = false;
}
};

View File

@@ -1,11 +1,11 @@
var util = require("../util");
var b = require("acorn-ast-types").builders;
var util = require("../../util");
var t = require("../../types");
var single = function (node) {
var singleArrayExpression = function (node) {
var block = node.blocks[0];
var templateName = "array-comprehension-map";
if (node.filter) templateName = "array-comprehension-filter";
var templateName = "array-expression-comprehension-map";
if (node.filter) templateName = "array-expression-comprehension-filter";
var result = util.template(templateName, {
STATEMENT: node.body,
@@ -25,7 +25,7 @@ var multiple = function (node, file) {
});
container._aliasFunction = true;
var block = container.callee.body;
var block = container.callee.expression.body;
var body = block.body;
var returnStatement = body.pop();
@@ -45,19 +45,15 @@ var multiple = function (node, file) {
// add a filter as this is our final stop
if (node.filter) {
child = b.ifStatement(node.filter, b.blockStatement([child]));
child = t.ifStatement(node.filter, t.blockStatement([child]));
}
}
var container2 = util.template("array-comprehension-for-each", {
ARRAY: self.right,
KEY: self.left
}, true);
// set function body
container2.expression.arguments[0].body.body = [child];
return container2;
return t.forOfStatement(
t.variableDeclaration("var", [t.variableDeclarator(self.left)]),
self.right,
t.blockStatement([child])
);
};
body.push(build());
@@ -67,8 +63,8 @@ var multiple = function (node, file) {
};
exports.ComprehensionExpression = function (node, parent, file) {
if (node.blocks.length === 1) {
return single(node);
if (node.blocks.length === 1 && t.isArrayExpression(node.blocks[0].right)) {
return singleArrayExpression(node);
} else {
return multiple(node, file);
}

View File

@@ -1,7 +1,7 @@
var util = require("../util");
var t = require("../../types");
exports.ArrowFunctionExpression = function (node) {
util.ensureBlock(node);
t.ensureBlock(node);
node._aliasFunction = "arrows";
node.expression = false;

View File

@@ -0,0 +1,209 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.ClassDeclaration = function (node, parent, file, scope) {
return t.variableDeclaration("var", [
t.variableDeclarator(node.id, buildClass(node, file, scope))
]);
};
exports.ClassExpression = function (node, parent, file, scope) {
return buildClass(node, file, scope);
};
var getMemberExpressionObject = function (node) {
while (t.isMemberExpression(node)) {
node = node.object;
}
return node;
};
var buildClass = function (node, file, scope) {
var superName = node.superClass;
var className = node.id || t.identifier(file.generateUid("class", scope));
var superClassArgument = node.superClass;
var superClassCallee = node.superClass;
if (superName) {
if (t.isMemberExpression(superName)) {
superClassArgument = superClassCallee = getMemberExpressionObject(superName);
} else if (!t.isIdentifier(superName)) {
superClassArgument = superName;
superClassCallee = superName = t.identifier(file.generateUid("ref", scope));
}
}
var container = util.template("class", {
CLASS_NAME: className
});
var block = container.callee.expression.body;
var body = block.body;
var constructor = body[0].declarations[0].init;
if (node.id) constructor.id = className;
var returnStatement = body.pop();
if (superName) {
body.push(t.expressionStatement(t.callExpression(file.addDeclaration("extends"), [className, superName])));
container.arguments.push(superClassArgument);
container.callee.expression.params.push(superClassCallee);
}
buildClassBody({
file: file,
body: body,
node: node,
className: className,
superName: superName,
constructor: constructor,
});
if (body.length === 1) {
// only a constructor so no need for a closure container
return constructor;
} else {
body.push(returnStatement);
return container;
}
};
var buildClassBody = function (opts) {
var file = opts.file;
var body = opts.body;
var node = opts.node;
var constructor = opts.constructor;
var className = opts.className;
var superName = opts.superName;
var instanceMutatorMap = {};
var staticMutatorMap = {};
var hasConstructor = false;
var classBody = node.body.body;
_.each(classBody, function (node) {
var methodName = node.key;
var method = node.value;
replaceInstanceSuperReferences(superName, node);
if (node.key.name === "constructor") {
if (node.kind === "") {
hasConstructor = true;
addConstructor(constructor, method);
} else {
throw file.errorWithNode(node, "illegal kind for constructor method");
}
} else {
var mutatorMap = instanceMutatorMap;
if (node.static) mutatorMap = staticMutatorMap;
var kind = node.kind;
if (kind === "") {
kind = "value";
util.pushMutatorMap(mutatorMap, methodName, "writable", t.identifier("true"));
}
util.pushMutatorMap(mutatorMap, methodName, kind, node);
}
});
if (!hasConstructor && superName) {
constructor.body.body.push(util.template("class-super-constructor-call", {
SUPER_NAME: superName
}, true));
}
var instanceProps;
var staticProps;
if (!_.isEmpty(instanceMutatorMap)) {
var protoId = util.template("prototype-identifier", {
CLASS_NAME: className
});
instanceProps = util.buildDefineProperties(instanceMutatorMap, protoId);
}
if (!_.isEmpty(staticMutatorMap)) {
staticProps = util.buildDefineProperties(staticMutatorMap, className);
}
if (instanceProps || staticProps) {
staticProps = staticProps || t.literal(null);
var args = [className, staticProps];
if (instanceProps) args.push(instanceProps);
body.push(t.expressionStatement(
t.callExpression(file.addDeclaration("class-props"), args)
));
}
};
var superIdentifier = function (superName, methodNode, node, parent) {
var methodName = methodNode.key;
if (parent.property === node) {
return;
} else if (t.isCallExpression(parent, { callee: node })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superName, t.identifier("call"));
} else {
node = superName;
// foo() { super(); }
if (!methodNode.static) {
node = t.memberExpression(node, t.identifier("prototype"));
}
node = t.memberExpression(node, methodName, methodNode.computed);
return t.memberExpression(node, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
return t.memberExpression(superName, t.identifier("prototype"));
} else {
return superName;
}
};
var replaceInstanceSuperReferences = function (superName, methodNode) {
var method = methodNode.value;
superName = superName || t.identifier("Function");
traverse(method, function (node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return superIdentifier(superName, methodNode, node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
callee.property.name = callee.property.name + ".call";
node.arguments.unshift(t.thisExpression());
}
});
};
var addConstructor = function (construct, method) {
construct.defaults = method.defaults;
construct.params = method.params;
construct.body = method.body;
construct.rest = method.rest;
t.inherits(construct, method);
};

View File

@@ -1,5 +1,5 @@
var util = require("../util");
var b = require("acorn-ast-types").builders;
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.ObjectExpression = function (node, parent, file) {
@@ -26,17 +26,17 @@ exports.ObjectExpression = function (node, parent, file) {
OBJECT: node
});
var containerCallee = container.callee;
var containerCallee = container.callee.expression;
var containerBody = containerCallee.body.body;
containerCallee._aliasFunction = "arrows";
_.each(computed, function (prop) {
containerBody.unshift(
b.expressionStatement(
b.assignmentExpression(
t.expressionStatement(
t.assignmentExpression(
"=",
b.memberExpression(objId, prop.key, true),
t.memberExpression(objId, prop.key, true),
prop.value
)
)

View File

@@ -0,0 +1,49 @@
var traverse = require("../../traverse");
var t = require("../../types");
var _ = require("lodash");
exports.Program =
exports.BlockStatement =
exports.ForInStatement =
exports.ForOfStatement =
exports.ForStatement = function (node, parent, file) {
var constants = [];
var check = function (node, names) {
_.each(names, function (name) {
if (constants.indexOf(name) >= 0) {
throw file.errorWithNode(node, name + " is read-only");
}
});
};
var getIds = function (node) {
return t.getIds(node, false, ["MemberExpression"]);
};
_.each(node.body, function (child) {
if (child && t.isVariableDeclaration(child, { kind: "const" })) {
_.each(child.declarations, function (declar) {
_.each(getIds(declar), function (name) {
check(declar, [name]);
constants.push(name);
});
declar._ignoreConstant = true;
});
child._ignoreConstant = true;
child.kind = "let";
}
});
if (!constants.length) return;
traverse(node, function (child) {
if (child._ignoreConstant) return;
if (t.isVariableDeclarator(child) || t.isDeclaration(child) || t.isAssignmentExpression(child)) {
check(child, getIds(child));
}
});
};

View File

@@ -1,9 +1,10 @@
var util = require("../util");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.Function = function (node) {
if (!node.defaults.length) return;
util.ensureBlock(node);
t.ensureBlock(node);
_.each(node.defaults, function (def, i) {
if (!def) return;

View File

@@ -0,0 +1,198 @@
var t = require("../../types");
var _ = require("lodash");
var buildVariableAssign = function (kind, id, init) {
if (kind === false) {
return t.expressionStatement(t.assignmentExpression("=", id, init));
} else {
return t.variableDeclaration(kind, [
t.variableDeclarator(id, init)
]);
}
};
var push = function (kind, nodes, elem, parentId) {
if (t.isObjectPattern(elem)) {
pushObjectPattern(kind, nodes, elem, parentId);
} else if (t.isArrayPattern(elem)) {
pushArrayPattern(kind, nodes, elem, parentId);
} else if (t.isMemberExpression(elem)) {
nodes.push(buildVariableAssign(false, elem, parentId));
} else {
nodes.push(buildVariableAssign(kind, elem, parentId));
}
};
var pushObjectPattern = function (kind, nodes, pattern, parentId) {
_.each(pattern.properties, function (prop) {
var pattern2 = prop.value;
var patternId2 = t.memberExpression(parentId, prop.key);
if (t.isPattern(pattern2)) {
push(kind, nodes, pattern2, patternId2);
} else {
nodes.push(buildVariableAssign(kind, pattern2, patternId2));
}
});
};
var pushArrayPattern = function (kind, nodes, pattern, parentId) {
_.each(pattern.elements, function (elem, i) {
if (!elem) return;
var newPatternId;
if (t.isSpreadElement(elem)) {
newPatternId = t.callExpression(t.memberExpression(parentId, t.identifier("slice")), [t.literal(i)]);
elem = elem.argument;
} else {
newPatternId = t.memberExpression(parentId, t.literal(i), true);
}
push(kind, nodes, elem, newPatternId);
});
};
var pushPattern = function (opts) {
var kind = opts.kind;
var nodes = opts.nodes;
var pattern = opts.pattern;
var parentId = opts.id;
var file = opts.file;
var scope = opts.scope;
if (!t.isMemberExpression(parentId) && !t.isIdentifier(parentId)) {
var key = t.identifier(file.generateUid("ref", scope));
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(key, parentId)
]));
parentId = key;
}
push(kind, nodes, pattern, parentId);
};
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, file, scope) {
var declar = node.left;
if (!t.isVariableDeclaration(declar)) return;
var pattern = declar.declarations[0].id;
if (!t.isPattern(pattern)) return;
var key = t.identifier(file.generateUid("ref", scope));
node.left = t.variableDeclaration(declar.kind, [
t.variableDeclarator(key, null)
]);
var nodes = [];
push(declar.kind, nodes, pattern, key);
t.ensureBlock(node);
var block = node.body;
block.body = nodes.concat(block.body);
};
exports.Function = function (node, parent, file, scope) {
var nodes = [];
var hasDestructuring = false;
node.params = node.params.map(function (pattern) {
if (!t.isPattern(pattern)) return pattern;
hasDestructuring = true;
var parentId = t.identifier(file.generateUid("ref", scope));
pushPattern({
kind: "var",
nodes: nodes,
pattern: pattern,
id: parentId,
file: file,
scope: scope
});
return parentId;
});
if (!hasDestructuring) return;
t.ensureBlock(node);
var block = node.body;
block.body = nodes.concat(block.body);
};
exports.ExpressionStatement = function (node, parent, file, scope) {
var expr = node.expression;
if (expr.type !== "AssignmentExpression") return;
if (!t.isPattern(expr.left)) return;
var nodes = [];
var ref = t.identifier(file.generateUid("ref", scope));
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(ref, expr.right)
]));
push(false, nodes, expr.left, ref);
return nodes;
};
exports.VariableDeclaration = function (node, parent, file, scope) {
if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;
var nodes = [];
var hasPattern = false;
_.each(node.declarations, function (declar) {
if (t.isPattern(declar.id)) {
hasPattern = true;
return false;
}
});
if (!hasPattern) return;
_.each(node.declarations, function (declar) {
var patternId = declar.init;
var pattern = declar.id;
if (t.isPattern(pattern) && patternId) {
pushPattern({
kind: node.kind,
nodes: nodes,
pattern: pattern,
id: patternId,
file: file,
scope: scope
});
} else {
nodes.push(buildVariableAssign(node.kind, declar.id, declar.init));
}
});
if (!t.isProgram(parent) && !t.isBlockStatement(parent)) {
var declar;
_.each(nodes, function (node) {
declar = declar || t.variableDeclaration(node.kind, []);
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
throw file.errorWithNode(node, "Cannot use this node within the current parent");
}
declar.declarations = declar.declarations.concat(node.declarations);
});
return declar;
}
return nodes;
};

View File

@@ -0,0 +1,34 @@
var util = require("../../util");
var t = require("../../types");
exports.ForOfStatement = function (node, parent, file, scope) {
var left = node.left;
var declar;
var stepKey = t.identifier(file.generateUid("step", scope));
var stepValueId = t.memberExpression(stepKey, t.identifier("value"));
if (t.isIdentifier(left)) {
declar = t.expressionStatement(t.assignmentExpression("=", left, stepValueId));
} else if (t.isVariableDeclaration(left)) {
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(left.declarations[0].id, stepValueId)
]);
} else {
return;
}
var node2 = util.template("for-of", {
ITERATOR_KEY: file.generateUid("iterator", scope),
STEP_KEY: stepKey,
OBJECT: node.right
});
t.ensureBlock(node);
var block = node2.body;
block.body.push(declar);
block.body = block.body.concat(node.body.body);
return node2;
};

View File

@@ -0,0 +1,3 @@
var regenerator = require("regenerator-6to5");
module.exports = regenerator.transform;

View File

@@ -2,26 +2,23 @@
// https://github.com/RReverser/jsx-transpiler
var esutils = require("esutils");
var b = require("acorn-ast-types").builders;
var t = require("../../types");
var _ = require("lodash");
var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/;
var KNOWN_TAGS = require("./known-tags");
exports.Program = function (node, parent, file) {
var jsx = "React.DOM";
// looking for namespace annotation
_.each(node.comments, function (comment) {
if (!comment.possiblyLeading) return;
_.each(node.leadingComments, function (comment) {
var matches = JSX_ANNOTATION_REGEX.exec(comment.value);
if (matches) jsx = matches[1];
});
// prebuilding AST node
file.jsx = jsx.split(".").map(b.identifier).reduce(function (object, property) {
return b.memberExpression(object, property, false);
file.jsx = jsx.split(".").map(t.identifier).reduce(function (object, property) {
return t.memberExpression(object, property);
});
};
@@ -29,7 +26,7 @@ exports.XJSIdentifier = function (node) {
if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return b.literal(node.name);
return t.literal(node.name);
}
};
@@ -39,26 +36,19 @@ exports.XJSNamespacedName = function () {
exports.XJSMemberExpression = {
exit: function (node) {
node.computed = node.property.type === "Literal";
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.XJSEmptyExpression = function (node) {
node.value = null;
node.type = "Literal";
};
exports.XJSExpressionContainer = function (node) {
return node.expression;
};
exports.XJSAttribute = {
exit: function (node) {
var value = node.value || b.literal(true);
var propNode = b.property("init", node.name, value);
propNode.loc = node.loc;
return propNode;
var value = node.value || t.literal(true);
return t.property("init", node.name, value);
}
};
@@ -66,18 +56,22 @@ exports.XJSOpeningElement = {
exit: function (node, parent, file) {
var tagExpr = node.name;
if (_.contains(KNOWN_TAGS, tagExpr.name)) {
tagExpr = b.memberExpression(file.jsx, tagExpr, false);
if (t.isIdentifier(tagExpr)) {
var tagName = tagExpr.name;
if (/[a-z]/.exec(tagName[0]) || _.contains(tagName, "-")) {
tagExpr = t.memberExpression(file.jsx, tagExpr);
}
}
var props = node.attributes;
if (props.length) {
props = b.objectExpression(props);
props = t.objectExpression(props);
} else {
props = b.literal(null);
props = t.literal(null);
}
return b.callExpression(tagExpr, [props]);
return t.callExpression(tagExpr, [props]);
}
};
@@ -87,11 +81,9 @@ exports.XJSElement = {
var children = node.children;
_.each(children, function (child) {
delete child.raw;
callExpr.arguments.push(child);
});
callExpr.loc = node.loc;
return callExpr;
return t.inherits(callExpr, node);
}
};

View File

@@ -0,0 +1,325 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
var isLet = function (node) {
if (!t.isVariableDeclaration(node)) return false;
if (node._let) return true;
if (node.kind !== "let") return false;
node._let = true;
node.kind = "var";
return true;
};
var isVar = function (node) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node);
};
exports.VariableDeclaration = function (node) {
isLet(node);
};
exports.For = function (node, parent, file, scope) {
var init = node.left || node.init;
if (isLet(init)) {
t.ensureBlock(node);
node.body._letDeclars = [init];
}
if (t.isLabeledStatement(parent)) {
// set label so `run` has access to it
node.label = parent.label;
}
run(node, node.body, parent, file, scope);
if (node.label && !t.isLabeledStatement(parent)) {
// we've been given a label so let's wrap ourselves
return t.labeledStatement(node.label, node);
}
};
exports.BlockStatement = function (block, parent, file, scope) {
if (!t.isFor(parent)) {
run(false, block, parent, file, scope);
}
};
var noClosure = function (letDeclars, block, replacements) {
standardiseLets(letDeclars);
if (_.isEmpty(replacements)) return;
traverse(block, function (node, parent) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
node.name = replacements[node.name] || node.name;
});
};
var standardiseLets = function (declars) {
_.each(declars, function (declar) {
delete declar._let;
});
};
var getInfo = function (block, file, scope) {
var opts = {
// array of `Identifier` names of let variables that appear lexically out of
// this scope but should be accessible - eg. `ForOfStatement`.left
outsideKeys: [],
// array of let `VariableDeclarator`s that are a part of this block
declarators: block._letDeclars || [],
// object of duplicate ids and their aliases - if there's an `Identifier`
// name that's used in an upper scope we generate a unique id and replace
// all references with it
duplicates: {},
// array of `Identifier` names of let variables that are accessible within
// the current block
keys: []
};
_.each(opts.declarators, function (declar) {
opts.declarators.push(declar);
var keys = t.getIds(declar);
opts.outsideKeys = opts.outsideKeys.concat(keys);
opts.keys = opts.keys.concat(keys);
});
_.each(block.body, function (declar) {
if (!isLet(declar)) return;
_.each(t.getIds(declar, true), function (id, key) {
var has = scope.parentGet(key);
if (has && has !== id) {
// there's a variable with this exact name in an upper scope so we need
// to generate a new name
opts.duplicates[key] = id.name = file.generateUid(key, scope);
}
opts.keys.push(key);
});
});
return opts;
};
var checkFor = function (forParent, block) {
var has = {
hasContinue: false,
hasReturn: false,
hasBreak: false,
};
if (forParent) {
traverse(block, function (node) {
var replace;
if (t.isFunction(node) || t.isFor(node)) {
return false;
} else if (t.isBreakStatement(node) && !node.label) {
has.hasBreak = true;
replace = t.returnStatement(t.literal("break"));
} else if (t.isContinueStatement(node) && !node.label) {
has.hasContinue = true;
replace = t.returnStatement(t.literal("continue"));
} else if (t.isReturnStatement(node)) {
has.hasReturn = true;
replace = t.returnStatement(t.objectExpression([
t.property("init", t.identifier("v"), node.argument)
]));
}
if (replace) return t.inherits(replace, node);
});
}
return has;
};
var hoistVarDeclarations = function (block, pushDeclar) {
traverse(block, function (node) {
if (t.isForStatement(node)) {
if (isVar(node.init)) {
node.init = t.sequenceExpression(pushDeclar(node.init));
}
} else if (t.isFor(node)) {
if (isVar(node.left)) {
node.left = node.left.declarations[0].id;
}
} else if (isVar(node)) {
return pushDeclar(node).map(t.expressionStatement);
} else if (t.isFunction(node)) {
return false;
}
});
};
var getParams = function (info, letReferences) {
var params = _.cloneDeep(letReferences);
_.each(params, function (param) {
param.name = info.duplicates[param.name] || param.name;
});
return params;
};
var getLetReferences = function (block, info, letReferences) {
var closurify = false;
// traverse through this block, stopping on functions and checking if they
// contain any outside let references
traverse(block, function (node, parent, scope) {
if (t.isFunction(node)) {
traverse(node, function (node, parent) {
// not an identifier so we have no use
if (!t.isIdentifier(node)) return;
// not a direct reference
if (!t.isReferenced(node, parent)) return;
// this scope has a variable with the same name so it couldn't belong
// to our let scope
if (scope.hasOwn(node.name)) return;
closurify = true;
// this key doesn't appear just outside our scope
if (!_.contains(info.outsideKeys, node.name)) return;
// push this badboy
letReferences[node.name] = node;
});
return false;
} else if (t.isFor(node)) {
return false;
}
});
return closurify;
};
var buildPushDeclar = function (body) {
return function (node) {
body.push(t.variableDeclaration(node.kind, node.declarations.map(function (declar) {
return t.variableDeclarator(declar.id);
})));
var replace = [];
_.each(node.declarations, function (declar) {
if (!declar.init) return;
var expr = t.assignmentExpression("=", declar.id, declar.init);
replace.push(t.inherits(expr, declar));
});
return replace;
};
};
var run = function (forParent, block, parent, file, scope) {
if (block._letDone) return;
block._letDone = true;
var info = getInfo(block, file, scope);
var declarators = info.declarators;
var letKeys = info.keys;
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(parent)) return;
// this block has no let references so let's clean up
if (!letKeys.length) return noClosure(declarators, block, info.duplicates);
// outside let references that we need to wrap
var letReferences = {};
// returns whether or not there are any outside let references within any
// functions
var closurify = getLetReferences(block, info, letReferences);
letReferences = _.values(letReferences);
// no need for a closure so let's clean up
if (!closurify) return noClosure(declarators, block, info.duplicates);
// if we're inside of a for loop then we search to see if there are any
// `break`s, `continue`s, `return`s etc
var has = checkFor(forParent, block);
var body = [];
// hoist a `VariableDeclaration` and add `AssignmentExpression`s in it's place
var pushDeclar = buildPushDeclar(body);
// hoist var references to retain scope
hoistVarDeclarations(block, pushDeclar);
// set let references to plain var references
standardiseLets(declarators);
// build the closure that we're going to wrap the block with
var fn = t.functionExpression(null, letReferences, t.blockStatement(block.body));
fn._aliasFunction = true;
// replace the current block body with the one we've built
block.body = body;
// change duplicate let references to their uid if they have one
var params = getParams(info, letReferences);
var call = t.callExpression(fn, params);
var ret = t.identifier(file.generateUid("ret", scope));
if (has.hasReturn || has.hasBreak || has.hasContinue) {
body.push(t.variableDeclaration("var", [
t.variableDeclarator(ret, call)
]));
var retCheck;
if (has.hasReturn) {
// typeof ret === "object"
retCheck = util.template("let-scoping-return", {
RETURN: ret,
});
// there's no `break` or `continue` so we can just push in the `if`
if (!has.hasBreak && !has.hasContinue) {
body.push(retCheck);
}
}
if (has.hasBreak || has.hasContinue) {
// ensure that the parent has a label as we're building a switch and we
// need to be able to access it
var label = forParent.label = forParent.label || t.identifier(file.generateUid("loop", scope));
var cases = [];
if (has.hasBreak) {
cases.push(t.switchCase(t.literal("break"), [t.breakStatement(label)]));
}
if (has.hasContinue) {
cases.push(t.switchCase(t.literal("continue"), [t.continueStatement(label)]));
}
if (has.hasReturn) {
cases.push(t.switchCase(null, [retCheck]));
}
body.push(t.switchStatement(ret, cases));
}
} else {
body.push(t.expressionStatement(call));
}
};

View File

@@ -0,0 +1,6 @@
var _ = require("lodash");
exports.Literal = function (node) {
// TODO: remove this when the new code generator is released
if (_.isNumber(node.value)) delete node.raw;
};

View File

@@ -1,4 +1,4 @@
var util = require("../util");
var util = require("../../util");
var _ = require("lodash");
exports.Property = function (node) {
@@ -10,7 +10,7 @@ exports.ObjectExpression = function (node, parent, file) {
node.properties = node.properties.filter(function (prop) {
if (prop.kind === "get" || prop.kind === "set") {
util.pushMutatorMap(mutatorMap, prop.key.name, prop.kind, prop.value);
util.pushMutatorMap(mutatorMap, prop.key, prop.kind, prop.value);
return false;
} else {
return true;
@@ -24,6 +24,9 @@ exports.ObjectExpression = function (node, parent, file) {
return util.template("object-define-properties-closure", {
KEY: objId,
OBJECT: node,
CONTENT: util.buildDefineProperties(mutatorMap, objId).expression
CONTENT: util.template("object-define-properties", {
OBJECT: objId,
PROPS: util.buildDefineProperties(mutatorMap)
})
});
};

View File

@@ -1,19 +1,19 @@
var b = require("acorn-ast-types").builders;
var t = require("../../types");
var _ = require("lodash");
var addDisplayName = function (id, call) {
if (!call || call.type !== "CallExpression") return;
if (!call || !t.isCallExpression(call)) return;
var callee = call.callee;
if (callee.type !== "MemberExpression") return;
if (!t.isMemberExpression(callee)) return;
// not React
var obj = callee.object;
if (obj.type !== "Identifier" || obj.name !== "React") return;
if (!t.isIdentifier(obj, { name: "React" })) return;
// not createClass
var prop = callee.property;
if (prop.type !== "Identifier" || prop.name !== "createClass") return;
if (!t.isIdentifier(prop, { name: "createClass" })) return;
// no arguments
var args = call.arguments;
@@ -21,19 +21,19 @@ var addDisplayName = function (id, call) {
// not an object
var first = args[0];
if (first.type !== "ObjectExpression") return;
if (!t.isObjectExpression(first)) return;
var props = first.properties;
var safe = true;
_.each(props, function (prop) {
if (prop.key.name === "displayName") {
if (t.isIdentifier(prop.key, { name: "displayName" })) {
return safe = false;
}
});
if (safe) {
props.unshift(b.property("init", b.identifier("displayName"), b.literal(id)));
props.unshift(t.property("init", t.identifier("displayName"), t.literal(id)));
}
};
@@ -42,22 +42,22 @@ exports.Property =
exports.VariableDeclarator = function (node) {
var left, right;
if (node.type === "AssignmentExpression") {
if (t.isAssignmentExpression(node)) {
left = node.left;
right = node.right;
} else if (node.type === "Property") {
} else if (t.isProperty(node)) {
left = node.key;
right = node.value;
} else if (node.type === "VariableDeclarator") {
} else if (t.isVariableDeclarator(node)) {
left = node.id;
right = node.init;
}
if (left && left.type === "MemberExpression") {
if (t.isMemberExpression(left)) {
left = left.property;
}
if (left && left.type === "Identifier") {
if (t.isIdentifier(left)) {
addDisplayName(left.name, right);
}
};

View File

@@ -0,0 +1,24 @@
var util = require("../../util");
var t = require("../../types");
exports.Function = function (node, parent, file) {
if (!node.rest) return;
var rest = node.rest;
delete node.rest;
var templateName = "arguments-slice-assign";
if (node.params.length) templateName += "-arg";
t.ensureBlock(node);
var template = util.template(templateName, {
SLICE_KEY: file.addDeclaration("slice"),
VARIABLE_NAME: rest,
SLICE_ARG: t.literal(node.params.length)
});
template.declarations[0].init.arguments[0]._ignoreAliasFunctions = true;
node.body.body.unshift(template);
};

View File

@@ -1,10 +1,10 @@
var util = require("../util");
var b = require("acorn-ast-types").builders;
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
var getSpreadLiteral = function (spread, file) {
var literal = spread.argument;
if (literal.type !== "ArrayExpression") {
if (!t.isArrayExpression(literal)) {
literal = util.template("call", {
OBJECT: file.addDeclaration("slice"),
CONTEXT: literal
@@ -16,7 +16,7 @@ var getSpreadLiteral = function (spread, file) {
var hasSpread = function (nodes) {
var has = false;
_.each(nodes, function (node) {
if (node.type === "SpreadElement") {
if (t.isSpreadElement(node)) {
has = true;
return false;
}
@@ -31,12 +31,12 @@ var build = function (props, file) {
var push = function () {
if (!_props.length) return;
nodes.push(b.arrayExpression(_props));
nodes.push(t.arrayExpression(_props));
_props = [];
};
_.each(props, function (prop) {
if (prop.type === "SpreadElement") {
if (t.isSpreadElement(prop)) {
push();
nodes.push(getSpreadLiteral(prop, file));
} else {
@@ -58,14 +58,14 @@ exports.ArrayExpression = function (node, parent, file) {
if (!nodes.length) return first;
return b.callExpression(b.memberExpression(first, b.identifier("concat"), false), nodes);
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
};
exports.CallExpression = function (node, parent, file) {
var args = node.arguments;
if (!hasSpread(args)) return;
var contextLiteral = b.literal(null);
var contextLiteral = t.literal(null);
node.arguments = [];
@@ -73,25 +73,25 @@ exports.CallExpression = function (node, parent, file) {
var first = nodes.shift();
if (nodes.length) {
node.arguments.push(b.callExpression(b.memberExpression(first, b.identifier("concat"), false), nodes));
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes));
} else {
node.arguments.push(first);
}
var callee = node.callee;
if (callee.type === "MemberExpression") {
if (t.isMemberExpression(callee)) {
contextLiteral = callee.object;
if (callee.computed) {
callee.object = b.memberExpression(callee.object, callee.property, true);
callee.property = b.identifier("apply");
callee.object = t.memberExpression(callee.object, callee.property, true);
callee.property = t.identifier("apply");
callee.computed = false;
} else {
callee.property = b.memberExpression(callee.property, b.identifier("apply"), false);
callee.property = t.memberExpression(callee.property, t.identifier("apply"));
}
} else {
node.callee = b.memberExpression(node.callee, b.identifier("apply"), false);
node.callee = t.memberExpression(node.callee, t.identifier("apply"));
}
node.arguments.unshift(contextLiteral);

View File

@@ -1,8 +1,8 @@
var b = require("acorn-ast-types").builders;
var t = require("../../types");
var _ = require("lodash");
var buildBinaryExpression = function (left, right) {
return b.binaryExpression("+", left, right);
return t.binaryExpression("+", left, right);
};
exports.TaggedTemplateExpression = function (node) {
@@ -10,31 +10,34 @@ exports.TaggedTemplateExpression = function (node) {
var quasi = node.quasi;
var strings = quasi.quasis.map(function (elem) {
return b.literal(elem.value.raw);
return t.literal(elem.value.raw);
});
args.push(b.arrayExpression(strings));
args.push(t.arrayExpression(strings));
_.each(quasi.expressions, function (expr) {
args.push(expr);
});
return b.callExpression(node.tag, args);
return t.callExpression(node.tag, args);
};
exports.TemplateLiteral = function (node) {
var nodes = [];
_.each(node.quasis, function (elem) {
nodes.push(b.literal(elem.value.raw));
nodes.push(t.literal(elem.value.raw));
var expr = node.expressions.shift();
if (expr) nodes.push(expr);
if (expr) {
if (t.isBinary(expr)) expr = t.parenthesizedExpression(expr);
nodes.push(expr);
}
});
if (nodes.length > 1) {
// remove redundant '' at the end of the expression
var last = _.last(nodes);
if (last.type === "Literal" && last.value === "") nodes.pop();
if (t.isLiteral(last, { value: "" })) nodes.pop();
var root = buildBinaryExpression(nodes.shift(), nodes.shift());

View File

@@ -1,5 +1,4 @@
var rewritePattern = require("regexpu/rewrite-pattern");
var b = require("acorn-ast-types").builders;
var _ = require("lodash");
exports.Literal = function (node) {
@@ -10,6 +9,6 @@ exports.Literal = function (node) {
if (!_.contains(regex.flags, "u")) return;
_.pull(flags, "u");
var pattern = rewritePattern(regex.pattern, regex.flags);
return b.literal(new RegExp(pattern, flags.join("")));
regex.pattern = rewritePattern(regex.pattern, regex.flags);
regex.flags = flags.join("");
};

View File

@@ -0,0 +1,12 @@
var t = require("../../types");
module.exports = function (ast) {
var body = ast.program.body;
var first = body[0];
var noStrict = !first || !t.isExpressionStatement(first) || !t.isLiteral(first.expression) || first.expression.value !== "use strict";
if (noStrict) {
body.unshift(t.expressionStatement(t.literal("use strict")));
}
};

View File

@@ -1,173 +0,0 @@
var traverse = require("../traverse");
var util = require("../util");
var b = require("acorn-ast-types").builders;
var _ = require("lodash");
exports.ClassDeclaration = function (node, parent, file) {
return b.variableDeclaration("var", [
b.variableDeclarator(node.id, buildClass(node, file))
]);
};
exports.ClassExpression = function (node, parent, file) {
return buildClass(node, file);
};
var getMemberExpressionObject = function (node) {
while (node.type === "MemberExpression") {
node = node.object;
}
return node;
};
var buildClass = function (node, file) {
var superName = node.superClass;
var className = node.id || b.identifier(file.generateUid("class"));
var superClassArgument = node.superClass;
var superClassCallee = node.superClass;
if (superName) {
if (superName.type === "MemberExpression") {
superClassArgument = superClassCallee = getMemberExpressionObject(superName);
} else if (superName.type !== "Identifier") {
superClassArgument = superName;
superClassCallee = superName = b.identifier(file.generateUid("ref"));
}
}
var container = util.template("class", {
CLASS_NAME: className
});
var block = container.callee.body;
var body = block.body;
if (node.id) {
body[0].declarations[0].init.id = className;
}
var returnStatement = body.pop();
if (superName) {
body.push(b.expressionStatement(b.callExpression(file.addDeclaration("extends"), [className, superName])));
container.arguments.push(superClassArgument);
container.callee.params.push(superClassCallee);
}
buildClassBody(body, className, superName, node);
body.push(returnStatement);
return container;
};
var buildClassBody = function (body, className, superName, node) {
var instanceMutatorMap = {};
var staticMutatorMap = {};
var hasConstructor = false;
var construct = body[0].declarations[0].init;
var classBody = node.body.body;
_.each(classBody, function (node) {
var methodName = node.key.name;
var method = node.value;
replaceInstanceSuperReferences(superName, method, node, methodName);
if (methodName === "constructor") {
if (node.kind === "") {
hasConstructor = true;
addConstructor(construct, method);
} else {
throw util.errorWithNode(node, "unknown kind for constructor method");
}
} else {
var mutatorMap = instanceMutatorMap;
if (node.static) mutatorMap = staticMutatorMap;
var kind = node.kind;
if (kind === "") {
kind = "value";
util.pushMutatorMap(mutatorMap, methodName, "writable", b.identifier("true"));
}
util.pushMutatorMap(mutatorMap, methodName, kind, node);
}
});
if (!hasConstructor && superName) {
construct.body.body.push(util.template("class-super-constructor-call", {
SUPER_NAME: superName
}, true));
}
if (!_.isEmpty(instanceMutatorMap)) {
var protoId = util.template("prototype-identifier", {
CLASS_NAME: className
});
body.push(util.buildDefineProperties(instanceMutatorMap, protoId));
}
if (!_.isEmpty(staticMutatorMap)) {
body.push(util.buildDefineProperties(staticMutatorMap, className));
}
};
var superIdentifier = function (superName, methodNode, methodName, node, parent) {
if (parent.property === node) {
return;
} else if (parent.type === "CallExpression" && parent.callee === node) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(b.thisExpression());
if (methodName === "constructor") {
// constructor() { super(); }
return b.memberExpression(superName, b.identifier("call"), false);
} else {
node = superName;
// foo() { super(); }
if (!methodNode.static) {
node = b.memberExpression(node, b.identifier("prototype"), false);
}
node = b.memberExpression(node, b.identifier(methodName), false);
return b.memberExpression(node, b.identifier("call"), false);
}
} else if (parent.type === "MemberExpression" && !methodNode.static) {
// super.test -> ClassName.prototype.test
return b.memberExpression(superName, b.identifier("prototype"), false);
} else {
return superName;
}
};
var replaceInstanceSuperReferences = function (superName, method, methodNode, methodName) {
superName = superName || b.identifier("Function");
traverse(method, function (node, parent) {
if (node.type === "Identifier" && node.name === "super") {
return superIdentifier(superName, methodNode, methodName, node, parent);
} else if (node.type === "CallExpression") {
var callee = node.callee;
if (callee.type !== "MemberExpression") return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
callee.property.name = callee.property.name + ".call";
node.arguments.unshift(b.thisExpression());
}
});
};
var addConstructor = function (construct, method) {
construct.defaults = method.defaults;
construct.params = method.params;
construct.body = method.body;
construct.rest = method.rest;
};

View File

@@ -1,45 +0,0 @@
var traverse = require("../traverse");
var util = require("../util");
var _ = require("lodash");
exports.Program =
exports.BlockStatement =
exports.ForInStatement =
exports.ForOfStatement =
exports.ForStatement = function (node) {
var constants = [];
var check = function (node, name) {
if (constants.indexOf(name) >= 0) {
throw util.errorWithNode(node, name + " is read-only");
}
};
_.each(node.body, function (child) {
if (child && child.type === "VariableDeclaration" && child.kind === "const") {
_.each(child.declarations, function (declar) {
_.each(util.getIds(declar.id), function (name) {
check(declar, name);
constants.push(name);
});
declar._ignoreConstant = true;
});
child.kind = "let";
}
});
if (!constants.length) return;
traverse(node, function (child) {
if (child._ignoreConstant) return;
if (child.type === "VariableDeclarator" ||
child.type === "FunctionDeclaration" ||
child.type === "ClassDeclaration") {
check(child, child.id.name);
} else if (child.type === "AssignmentExpression") {
check(child, child.left.name);
}
});
};

View File

@@ -1,155 +0,0 @@
var traverse = require("../traverse");
var util = require("../util");
var b = require("acorn-ast-types").builders;
var _ = require("lodash");
var buildVariableAssign = function (kind, id, init) {
if (kind === false) {
return b.expressionStatement(b.assignmentExpression("=", id, init));
} else {
return b.variableDeclaration(kind, [
b.variableDeclarator(id, init)
]);
}
};
var push = function (kind, nodes, pattern, parentId) {
if (pattern.type === "ObjectPattern") {
pushObjectPattern(kind, nodes, pattern, parentId);
} else if (pattern.type === "ArrayPattern") {
pushArrayPattern(kind, nodes, pattern, parentId);
}
};
var pushObjectPattern = function (kind, nodes, pattern, parentId) {
_.each(pattern.properties, function (prop) {
var pattern2 = prop.value;
var patternId2 = b.memberExpression(parentId, prop.key, false);
if (traverse.isPattern(pattern2)) {
push(kind, nodes, pattern2, patternId2);
} else {
nodes.push(buildVariableAssign(kind, pattern2, patternId2));
}
});
};
var pushArrayPattern = function (kind, nodes, pattern, parentId) {
_.each(pattern.elements, function (elem, i) {
if (!elem) return;
var newPatternId = b.memberExpression(parentId, b.literal(i), true);
if (elem.type === "Identifier") {
nodes.push(buildVariableAssign(kind, elem, newPatternId));
} else if (elem.type === "MemberExpression") {
nodes.push(buildVariableAssign(false, elem, newPatternId));
} else {
push(kind, nodes, elem, newPatternId);
}
});
};
var pushPattern = function (kind, nodes, pattern, parentId, file) {
if (parentId.type !== "MemberExpression" && parentId.type !== "Identifier") {
var key = b.identifier(file.generateUid("ref"));
nodes.push(b.variableDeclaration("var", [
b.variableDeclarator(key, parentId)
]));
parentId = key;
}
push(kind, nodes, pattern, parentId);
};
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, file) {
var declar = node.left;
if (declar.type !== "VariableDeclaration") return;
var pattern = declar.declarations[0].id;
if (!traverse.isPattern(pattern)) return;
var key = b.identifier(file.generateUid("ref"));
node.left = b.variableDeclaration(declar.kind, [
b.variableDeclarator(key, null)
]);
var nodes = [];
push(declar.kind, nodes, pattern, key);
util.ensureBlock(node);
var block = node.body;
block.body = nodes.concat(block.body);
};
exports.Function = function (node, parent, file) {
var nodes = [];
var hasDestructuring = false;
node.params = node.params.map(function (pattern) {
if (!traverse.isPattern(pattern)) return pattern;
hasDestructuring = true;
var parentId = b.identifier(file.generateUid("ref"));
pushPattern("var", nodes, pattern, parentId, file);
return parentId;
});
if (!hasDestructuring) return;
util.ensureBlock(node);
var block = node.body;
block.body = nodes.concat(block.body);
};
exports.ExpressionStatement = function (node, parent, file) {
var expr = node.expression;
if (expr.type !== "AssignmentExpression") return;
if (!traverse.isPattern(expr.left)) return;
var nodes = [];
var ref = b.identifier(file.generateUid("ref"));
nodes.push(b.variableDeclaration("var", [
b.variableDeclarator(ref, expr.right)
]));
push(false, nodes, expr.left, ref);
return nodes;
};
exports.VariableDeclaration = function (node, parent, file) {
if (parent.type === "ForInStatement") return;
var nodes = [];
var hasPattern = false;
_.each(node.declarations, function (declar) {
if (traverse.isPattern(declar.id)) {
hasPattern = true;
return false;
}
});
if (!hasPattern) return;
_.each(node.declarations, function (declar) {
var patternId = declar.init;
var pattern = declar.id;
if (traverse.isPattern(pattern) && patternId) {
pushPattern(node.kind, nodes, pattern, patternId, file);
} else {
nodes.push(buildVariableAssign(node.kind, declar.id, declar.init));
}
});
return nodes;
};

View File

@@ -1,34 +0,0 @@
var util = require("../util");
var b = require("acorn-ast-types").builders;
exports.ForOfStatement = function (node, parent, file) {
var left = node.left;
var declar;
var stepKey = b.identifier(file.generateUid("step"));
var stepValueId = b.memberExpression(stepKey, b.identifier("value"), false);
if (left.type === "Identifier") {
declar = b.expressionStatement(b.assignmentExpression("=", left, stepValueId));
} else if (left.type === "VariableDeclaration") {
declar = b.variableDeclaration(left.kind, [
b.variableDeclarator(left.declarations[0].id, stepValueId)
]);
} else {
return;
}
var node2 = util.template("for-of", {
ITERATOR_KEY: file.generateUid("iterator"),
STEP_KEY: stepKey,
OBJECT: node.right
});
util.ensureBlock(node);
var block = node2.body;
block.body.push(declar);
block.body = block.body.concat(node.body.body);
return node2;
};

View File

@@ -1,3 +0,0 @@
var regenerator = require("regenerator");
module.exports = regenerator.transform;

View File

@@ -1,132 +0,0 @@
[
"a",
"abbr",
"address",
"applet",
"area",
"article",
"aside",
"audio",
"b",
"base",
"bdi",
"bdo",
"big",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"circle",
"cite",
"code",
"col",
"colgroup",
"command",
"data",
"datalist",
"dd",
"defs",
"del",
"details",
"dfn",
"dialog",
"div",
"dl",
"dt",
"ellipse",
"em",
"embed",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"g",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hgroup",
"hr",
"html",
"i",
"iframe",
"img",
"input",
"ins",
"kbd",
"keygen",
"label",
"legend",
"li",
"line",
"linearGradient",
"link",
"main",
"map",
"mark",
"marquee",
"menu",
"menuitem",
"meta",
"meter",
"nav",
"noscript",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"param",
"path",
"polygon",
"polyline",
"pre",
"progress",
"q",
"radialGradient",
"rect",
"rp",
"rt",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"small",
"source",
"span",
"stop",
"strong",
"style",
"sub",
"summary",
"sup",
"svg",
"table",
"tbody",
"td",
"text",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"track",
"tspan",
"u",
"ul",
"var",
"video",
"wbr"
]

View File

@@ -1,58 +0,0 @@
var traverse = require("../traverse");
var util = require("../util");
var b = require("acorn-ast-types").builders;
var _ = require("lodash");
exports.VariableDeclaration = function (node, parent, file) {
if (node.kind !== "let") return;
node.kind = "var";
var ids = {};
_.each(node.declarations, function (declar) {
_.each(util.getIds(declar.id), function (id) {
ids[id] = b.identifier(file.generateUid(id));
});
});
var replaceId = function (node, parent) {
// not an identifier so we have no use for this node
if (node.type !== "Identifier") return;
// not a let reference
var id = ids[node.name];
if (!id) return;
if (util.isReferenced(node, parent)) return id;
};
var isProgram = parent.type === "Program";
var replace = function (node, parent) {
if (!isProgram && _.contains(traverse.FUNCTION_TYPES, node.type)) {
var letReferences = [];
traverse(node, function (node, parent) {
var id = replaceId(node, parent);
if (id && !_.contains(letReferences, id)) letReferences.push(id);
return id;
});
if (letReferences.length) {
if (node.type === "FunctionDeclaration") {
throw new Error("`FunctionDeclaration`s that use `let` and `constant` references aren't allowed outside of the root scope");
} else {
return b.callExpression(b.functionExpression(null, letReferences, b.blockStatement([
b.returnStatement(node)
])), letReferences);
}
} else {
return false;
}
}
return replaceId(node, parent);
};
traverse(parent, replace);
};

View File

@@ -1,19 +0,0 @@
var util = require("../util");
var b = require("acorn-ast-types").builders;
exports.Function = function (node, parent, file) {
if (!node.rest) return;
var rest = node.rest;
delete node.rest;
var templateName = "arguments-slice-assign";
if (node.params.length) templateName += "-arg";
util.ensureBlock(node);
node.body.body.unshift(util.template(templateName, {
SLICE_KEY: file.addDeclaration("slice"),
VARIABLE_NAME: rest,
SLICE_ARG: b.literal(node.params.length)
}));
};

View File

@@ -1,15 +0,0 @@
var b = require("acorn-ast-types").builders;
module.exports = function (ast, file) {
var body = ast.program.body;
var first = body[0];
var noStrict = !first || first.type !== "ExpressionStatement" || first.expression.type !== "Literal" || first.expression.value !== "use strict";
if (noStrict) {
if (file.opts._noStrict) return;
body.unshift(b.expressionStatement(b.literal("use strict")));
} else {
if (file.opts._noStrict) body.shift();
}
};

View File

@@ -1,24 +1,30 @@
var VISITOR_KEYS = require("./visitor-keys");
var _ = require("lodash");
module.exports = traverse;
var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
var Scope = require("./scope");
var t = require("../types");
var _ = require("lodash");
function traverse(parent, callbacks, opts) {
// falsy node
if (!parent) return;
// array of nodes
if (_.isArray(parent)) {
_.each(parent, function (node) {
traverse(node, callbacks, blacklistTypes);
traverse(node, callbacks, opts);
});
return;
}
// unknown node type to traverse
var keys = VISITOR_KEYS[parent.type];
var keys = t.VISITOR_KEYS[parent.type];
if (!keys) return;
opts = opts || {};
if (_.isArray(opts)) opts = { blacklist: opts };
// blacklist these node types from being traversed
blacklistTypes = blacklistTypes || [];
var blacklistTypes = opts.blacklist || [];
// normalise callbacks
if (_.isFunction(callbacks)) callbacks = { enter: callbacks };
@@ -38,12 +44,17 @@ var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
// replace node
var maybeReplace = function (result) {
if (result != null) obj[key] = result;
if (result === false) return;
if (result != null) node = obj[key] = result;
};
//
var opts2 = _.clone(opts);
if (t.isScope(node)) opts2.scope = new Scope(opts.scope, node);
// enter
if (callbacks.enter) {
result = callbacks.enter(node, parent, obj, key);
result = callbacks.enter(node, parent, opts2.scope);
// stop iteration
if (result === false) return;
@@ -52,11 +63,11 @@ var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
}
// traverse node
traverse(node, callbacks, blacklistTypes);
traverse(node, callbacks, opts2);
// exit
if (callbacks.exit) {
maybeReplace(callbacks.exit(node, parent, obj, key));
maybeReplace(callbacks.exit(node, parent, opts2.scope));
}
};
@@ -65,39 +76,39 @@ var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
handle(nodes, i);
});
// remove deleted nodes
parent[key] = _.flatten(parent[key]).filter(function (node) {
return node !== traverse.Delete;
});
parent[key] = _.flatten(parent[key]);
} else {
handle(parent, key);
if (parent[key] === traverse.Delete) {
throw new Error("trying to delete property " + key + " from " +
parent.type + " but can't because it's required");
}
}
});
}
traverse.removeProperties = function (tree) {
var clear = function (node) {
delete node.extendedRange;
delete node._scopeIds;
delete node._parent;
delete node.tokens;
delete node.range;
delete node.start;
delete node.end;
delete node.loc;
delete node.raw;
clearComments(node.trailingComments);
clearComments(node.leadingComments);
};
var clearComments = function (comments) {
_.each(comments, clear);
};
clear(tree);
traverse(tree, clear);
return tree;
};
traverse.FUNCTION_TYPES = ["ArrowFunctionExpression", "FunctionDeclaration", "FunctionExpression"];
traverse.aliases = {
ArrowFunctionExpression: ["Function"],
FunctionDeclaration: ["Function"],
FunctionExpression: ["Function"]
};
traverse.isFunction = function (node) {
return _.contains(traverse.FUNCTION_TYPES, node.type);
};
traverse.isPattern = function (node) {
return node.type === "ArrayPattern" || node.type === "ObjectPattern";
};
traverse.Delete = {};
traverse.hasType = function (tree, type, blacklistTypes) {
blacklistTypes = [].concat(blacklistTypes || []);
@@ -105,7 +116,7 @@ traverse.hasType = function (tree, type, blacklistTypes) {
if (_.isArray(tree)) {
// array of nodes, find the first
return !!_.find(tree, function (node) {
return tree.some(function (node) {
return traverse.hasType(node, type, blacklistTypes);
});
} else {
@@ -120,7 +131,7 @@ traverse.hasType = function (tree, type, blacklistTypes) {
has = true;
return false;
}
}, blacklistTypes);
}, { blacklist: blacklistTypes });
}
return has;

View File

@@ -0,0 +1,79 @@
module.exports = Scope;
var traverse = require("./index");
var t = require("../types");
var _ = require("lodash");
function Scope(parent, block) {
this.parent = parent;
this.block = block;
this.ids = this.getIds();
this.getIds();
}
Scope.prototype.getIds = function () {
var block = this.block;
if (block._scopeIds) return block._scopeIds;
var self = this;
var ids = block._scopeIds = {};
if (t.isBlockStatement(block)) {
_.each(block.body, function (node) {
if (t.isVariableDeclaration(node) && node.kind !== "var") {
self.add(node, ids);
}
});
} else if (t.isProgram(block) || t.isFunction(block)) {
traverse(block, function (node, parent) {
if (parent !== block && t.isVariableDeclaration(node) && node.kind !== "var") {
return;
}
if (t.isDeclaration(node)) {
self.add(node, ids);
} else if (t.isFunction(node)) {
return false;
}
});
} else if (t.isCatchClause(block)) {
self.add(block.param, ids);
}
if (t.isFunction(block)) {
_.each(block.params, function (param) {
self.add(param, ids);
});
}
return ids;
};
Scope.prototype.add = function (node, ids) {
_.merge(ids || this.ids, t.getIds(node, true));
};
Scope.prototype.get = function (id) {
return id && (this.getOwn(id) || this.parentGet(id));
};
Scope.prototype.getOwn = function (id) {
return _.has(this.ids, id) && this.ids[id];
};
Scope.prototype.parentGet = function (id) {
return this.parent && this.parent.get(id);
};
Scope.prototype.has = function (id) {
return id && (this.hasOwn(id) || this.parentHas(id));
};
Scope.prototype.hasOwn = function (id) {
return !!this.getOwn(id);
};
Scope.prototype.parentHas = function (id) {
return this.parent && this.parent.has(id);
};

View File

@@ -1,86 +0,0 @@
{
"ArrayExpression": ["elements"],
"ArrayPattern": ["elements"],
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
"AssignmentExpression": ["left", "right"],
"AwaitExpression": ["argument"],
"BinaryExpression": ["left", "right"],
"BlockStatement": ["body"],
"BreakStatement": ["label"],
"CallExpression": ["callee", "arguments"],
"CatchClause": ["param", "body"],
"ClassBody": ["body"],
"ClassDeclaration": ["id", "body", "superClass"],
"ClassExpression": ["id", "body", "superClass"],
"ClassProperty": ["key", "value"],
"ComprehensionBlock": ["left", "right", "body"],
"ComprehensionExpression": ["filter", "blocks", "body"],
"ConditionalExpression": ["test", "consequent", "alternate"],
"ContinueStatement": ["label"],
"DebuggerStatement": [],
"DoWhileStatement": ["body", "test"],
"EmptyStatement": [],
"ExportDeclaration": ["declaration", "specifiers", "source"],
"ExportBatchSpecifier": [],
"ExportSpecifier": ["id", "name"],
"ExpressionStatement": ["expression"],
"File": ["program"],
"ForInStatement": ["left", "right", "body"],
"ForOfStatement": ["left", "right", "body"],
"ForStatement": ["init", "test", "update", "body"],
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body"],
"FunctionExpression": ["id", "params", "defaults", "rest", "body"],
"Identifier": [],
"IfStatement": ["test", "consequent", "alternate"],
"ImportDeclaration": ["specifiers", "source"],
"ImportDefaultSpecifier": ["id"],
"ImportNamespaceSpecifier": ["id"],
"ImportSpecifier": ["id", "name"],
"LabeledStatement": ["label", "body"],
"Literal": [],
"LogicalExpression": ["left", "right"],
"MemberExpression": ["object", "property"],
"MethodDefinition": ["key", "value"],
"ModuleSpecifier": [],
"NewExpression": ["callee", "arguments"],
"ObjectExpression": ["properties"],
"ObjectPattern": ["properties"],
"ObjectTypeAnnotation": ["properties"],
"OptionalParameter": ["id"],
"ParametricTypeAnnotation": ["params"],
"ParametricallyTypedIdentifier": [],
"Program": ["body"],
"Property": ["key", "value"],
"ReturnStatement": ["argument"],
"SequenceExpression": ["expressions"],
"SpreadElement": ["argument"],
"SpreadProperty": ["argument"],
"SwitchCase": ["test", "consequent"],
"SwitchStatement": ["discriminant", "cases"],
"TaggedTemplateExpression": ["tag", "quasi"],
"TemplateElement": [],
"TemplateLiteral": ["quasis", "expressions"],
"ThisExpression": [],
"ThrowStatement": ["argument"],
"TryStatement": ["block", "handlers", "handler", "guardedHandlers", "finalizer"],
"TypeAnnotatedIdentifier": ["id", "annotation"],
"TypeAnnotation": ["id", "params", "returnType", "parametricType"],
"UnaryExpression": ["argument"],
"UpdateExpression": ["argument"],
"VariableDeclaration": ["declarations"],
"VariableDeclarator": ["id", "init"],
"VoidTypeAnnotation": [],
"WhileStatement": ["test", "body"],
"WithStatement": ["object", "body"],
"XJSIdentifier": [],
"XJSNamespacedName": ["namespace", "name"],
"XJSMemberExpression": ["object", "property"],
"XJSEmptyExpression": [],
"XJSExpressionContainer": ["expression"],
"XJSElement": ["openingElement", "closingElement", "children"],
"XJSClosingElement": ["name"],
"XJSOpeningElement": ["name", "attributes"],
"XJSAttribute": ["name", "value"],
"XJSText": [],
"YieldExpression": ["argument"]
}

View File

@@ -0,0 +1,46 @@
{
"ExpressionStatement": ["Statement"],
"BreakStatement": ["Statement"],
"ContinueStatement": ["Statement"],
"DebuggerStatement": ["Statement"],
"DoWhileStatement": ["Statement"],
"IfStatement": ["Statement"],
"ReturnStatement": ["Statement"],
"SwitchStatement": ["Statement"],
"ThrowStatement": ["Statement"],
"TryStatement": ["Statement"],
"WhileStatement": ["Statement"],
"WithStatement": ["Statement"],
"EmptyStatement": ["Statement"],
"LabeledStatement": ["Statement"],
"VariableDeclaration": ["Statement", "Declaration"],
"ExportDeclaration": ["Statement", "Declaration"],
"ImportDeclaration": ["Statement", "Declaration"],
"ArrowFunctionExpression": ["Scope", "Function"],
"FunctionDeclaration": ["Statement", "Declaration", "Scope", "Function"],
"FunctionExpression": ["Scope", "Function"],
"BlockStatement": ["Statement", "Scope"],
"Program": ["Scope"],
"CatchClause": ["Scope"],
"LogicalExpression": ["Binary"],
"BinaryExpression": ["Binary"],
"UnaryExpression": ["UnaryLike"],
"SpreadProperty": ["UnaryLike"],
"SpreadElement": ["UnaryLike"],
"ClassDeclaration": ["Statement", "Declaration", "Class"],
"ClassExpression": ["Class"],
"ForOfStatement": ["Statement", "For"],
"ForInStatement": ["Statement", "For"],
"ForStatement": ["Statement", "For"],
"ObjectPattern": ["Pattern"],
"ArrayPattern": ["Pattern"],
"Property": ["UserWhitespacable"]
}

View File

@@ -0,0 +1,24 @@
{
"ArrayExpression": ["elements"],
"AssignmentExpression": ["operator", "left", "right"],
"BinaryExpression": ["operator", "left", "right"],
"BlockStatement": ["body"],
"CallExpression": ["callee", "arguments"],
"ConditionalExpression": ["test", "consequent", "alternate"],
"ExpressionStatement": ["expression"],
"File": ["program", "comments", "tokens"],
"FunctionExpression": ["id", "params", "body"],
"Identifier": ["name"],
"IfStatement": ["test", "consequent", "alternate"],
"Literal": ["value"],
"MemberExpression": ["object", "property", "computed"],
"ObjectExpression": ["properties"],
"ParenthesizedExpression": ["expression"],
"Program": ["body"],
"Property": ["kind", "key", "value", "computed"],
"ReturnStatement": ["argument"],
"SequenceExpression": ["expressions"],
"UnaryExpression": ["operator", "argument", "prefix"],
"VariableDeclaration": ["kind", "declarations"],
"VariableDeclarator": ["id", "init"]
}

217
lib/6to5/types/index.js Normal file
View File

@@ -0,0 +1,217 @@
var _ = require("lodash");
var t = exports;
//
t.VISITOR_KEYS = require("./visitor-keys");
_.each(t.VISITOR_KEYS, function (keys, type) {
t["is" + type] = function (node, opts) {
return node && node.type === type && t.shallowEqual(node, opts);
};
});
//
t.BUILDER_KEYS = _.defaults(require("./builder-keys"), t.VISITOR_KEYS);
_.each(t.BUILDER_KEYS, function (keys, type) {
t[type[0].toLowerCase() + type.slice(1)] = function () {
var args = arguments;
var node = { type: type };
_.each(keys, function (key, i) {
node[key] = args[i];
});
return node;
};
});
//
t.ALIAS_KEYS = require("./alias-keys");
var _aliases = {};
_.each(t.ALIAS_KEYS, function (aliases, type) {
_.each(aliases, function (alias) {
var types = _aliases[alias] = _aliases[alias] || [];
types.push(type);
});
});
_.each(_aliases, function (types, type) {
t[type.toUpperCase() + "_TYPES"] = types;
t["is" + type] = function (node, opts) {
return node && _.contains(types, node.type) && t.shallowEqual(node, opts);
};
});
//
t.shallowEqual = function (actual, expected) {
var same = true;
if (expected) {
_.each(expected, function (val, key) {
if (actual[key] !== val) {
return same = false;
}
});
}
return same;
};
//
t.isReferenced = function (node, parent) {
// we're a property key so we aren't referenced
if (t.isProperty(parent) && parent.key === node) return false;
var isMemberExpression = t.isMemberExpression(parent);
// we're in a member expression and we're the computed property so we're referenced
var isComputedProperty = isMemberExpression && parent.property === node && parent.computed;
// we're in a member expression and we're the object so we're referenced
var isObject = isMemberExpression && parent.object === node;
// we are referenced
if (!isMemberExpression || isComputedProperty || isObject) return true;
return false;
};
t.toIdentifier = function (name) {
if (t.isIdentifier(name)) return name.name;
// replace all non-valid identifiers with dashes
name = name.replace(/[^a-zA-Z0-9]/g, "-");
// remove all dashes and numbers from start of name
name = name.replace(/^[-0-9]+/, "");
// camel case
name = name.replace(/[-_\s]+(.)?/g, function (match, c) {
return c ? c.toUpperCase() : "";
});
return name;
};
t.ensureBlock = function (node) {
node.body = t.toBlock(node.body, node);
};
t.toStatement = function (node, ignore) {
var mustHaveId = false;
var newType;
if (t.isClass(node)) {
mustHaveId = true;
newType = "ClassDeclaration";
} else if (t.isFunction(node)) {
mustHaveId = true;
newType = "FunctionDeclaration";
} else if (t.isStatement(node)) {
newType = node.type;
}
if (mustHaveId && !node.id) {
newType = false;
}
if (!newType) {
if (ignore) {
return false;
} else {
throw new Error("cannot turn " + node.type + " to a statement");
}
}
node.type = newType;
return node;
};
t.toBlock = function (node, parent) {
if (t.isBlockStatement(node)) {
return node;
}
if (!_.isArray(node)) {
if (!t.isStatement(node)) {
if (t.isFunction(parent)) {
node = t.returnStatement(node);
} else {
node = t.expressionStatement(node);
}
}
node = [node];
}
return t.blockStatement(node);
};
t.getIds = function (node, map, ignoreTypes) {
ignoreTypes = ignoreTypes || [];
var search = [node];
var ids = {};
while (search.length) {
var id = search.shift();
if (!id) continue;
if (_.contains(ignoreTypes, id.type)) continue;
var nodeKey = t.getIds.nodes[id.type];
var arrKey = t.getIds.arrays[id.type];
if (t.isIdentifier(id)) {
ids[id.name] = id;
} else if (nodeKey) {
if (id[nodeKey]) search.push(id[nodeKey]);
} else if (arrKey) {
search = search.concat(id[arrKey] || []);
}
}
if (!map) ids = _.keys(ids);
return ids;
};
t.getIds.nodes = {
AssignmentExpression: "left",
ImportSpecifier: "id",
ExportSpecifier: "id",
VariableDeclarator: "id",
FunctionDeclaration: "id",
ClassDeclaration: "id",
ParenthesizedExpression: "expression",
MemeberExpression: "object",
SpreadElement: "argument",
Property: "value"
};
t.getIds.arrays = {
ExportDeclaration: "specifiers",
ImportDeclaration: "specifiers",
VariableDeclaration: "declarations",
ArrayPattern: "elements",
ObjectPattern: "properties"
};
t.inherits = function (child, parent) {
child.loc = parent.loc;
child.end = parent.end;
child.range = parent.range;
child.start = parent.start;
return child;
};
t.getSpecifierName = function (specifier) {
return specifier.name || specifier.id;
};

View File

@@ -0,0 +1,75 @@
{
"ArrayExpression": ["elements"],
"ArrayPattern": ["elements"],
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
"AssignmentExpression": ["left", "right"],
"BinaryExpression": ["left", "right"],
"BlockStatement": ["body"],
"BreakStatement": ["label"],
"CallExpression": ["callee", "arguments"],
"CatchClause": ["param", "body"],
"ClassBody": ["body"],
"ClassDeclaration": ["id", "body", "superClass"],
"ClassExpression": ["id", "body", "superClass"],
"ComprehensionBlock": ["left", "right", "body"],
"ComprehensionExpression": ["filter", "blocks", "body"],
"ConditionalExpression": ["test", "consequent", "alternate"],
"ContinueStatement": ["label"],
"DebuggerStatement": [],
"DoWhileStatement": ["body", "test"],
"EmptyStatement": [],
"ExportBatchSpecifier": [],
"ExportDeclaration": ["declaration", "specifiers", "source"],
"ExportSpecifier": ["id", "name"],
"ExpressionStatement": ["expression"],
"File": ["program"],
"ForInStatement": ["left", "right", "body"],
"ForOfStatement": ["left", "right", "body"],
"ForStatement": ["init", "test", "update", "body"],
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body"],
"FunctionExpression": ["id", "params", "defaults", "rest", "body"],
"Identifier": [],
"IfStatement": ["test", "consequent", "alternate"],
"ImportBatchSpecifier": ["id"],
"ImportDeclaration": ["specifiers", "source"],
"ImportSpecifier": ["id", "name"],
"LabeledStatement": ["label", "body"],
"Literal": [],
"LogicalExpression": ["left", "right"],
"MemberExpression": ["object", "property"],
"MethodDefinition": ["key", "value"],
"NewExpression": ["callee", "arguments"],
"ObjectExpression": ["properties"],
"ObjectPattern": ["properties"],
"ParenthesizedExpression": ["expression"],
"Program": ["body"],
"Property": ["key", "value"],
"ReturnStatement": ["argument"],
"SequenceExpression": ["expressions"],
"SpreadElement": ["argument"],
"SwitchCase": ["test", "consequent"],
"SwitchStatement": ["discriminant", "cases"],
"TaggedTemplateExpression": ["tag", "quasi"],
"TemplateElement": [],
"TemplateLiteral": ["quasis", "expressions"],
"ThisExpression": [],
"ThrowStatement": ["argument"],
"TryStatement": ["block", "handlers", "handler", "guardedHandlers", "finalizer"],
"UnaryExpression": ["argument"],
"UpdateExpression": ["argument"],
"VariableDeclaration": ["declarations"],
"VariableDeclarator": ["id", "init"],
"WhileStatement": ["test", "body"],
"WithStatement": ["object", "body"],
"XJSAttribute": ["name", "value"],
"XJSClosingElement": ["name"],
"XJSElement": ["openingElement", "closingElement", "children"],
"XJSEmptyExpression": [],
"XJSExpressionContainer": ["expression"],
"XJSIdentifier": [],
"XJSMemberExpression": ["object", "property"],
"XJSNamespacedName": ["namespace", "name"],
"XJSOpeningElement": ["name", "attributes"],
"XJSSpreadAttribute": [],
"YieldExpression": ["argument"]
}

View File

@@ -1,26 +1,20 @@
var traverse = require("./traverse");
var astTypes = require("acorn-ast-types");
var recast = require("acorn-recast");
var path = require("path");
var util = require("util");
var fs = require("fs");
var _ = require("lodash");
require("./patch");
var n = astTypes.namedTypes;
var b = astTypes.builders;
var estraverse = require("estraverse");
var traverse = require("./traverse");
var acorn = require("acorn-6to5");
var path = require("path");
var util = require("util");
var fs = require("fs");
var t = require("./types");
var _ = require("lodash");
exports.inherits = util.inherits;
exports.ensureBlock = function (node) {
var block = node.body;
if (block.type === "BlockStatement") return;
if (!_.isArray(block)) {
if (!n.Statement.check(block)) block = b.returnStatement(block);
block = [block];
}
node.body = b.blockStatement(block);
exports.canCompile = function (filename, altExts) {
var exts = altExts || [".js", ".jsx", ".es6"];
var ext = path.extname(filename);
return _.contains(exts, ext);
};
exports.resolve = function (loc) {
@@ -35,34 +29,20 @@ exports.list = function (val) {
return val ? val.split(",") : [];
};
exports.getSpecifierName = function (specifier) {
return specifier.name || specifier.id;
};
exports.ensureExpressionType = function (node) {
node.type = {
FunctionDeclaration: "FunctionExpression",
ClassDeclaration: "ClassExpression"
}[node.type] || node.type;
return node;
};
exports.getUid = function (parent, file) {
var node;
if (parent.type === "AssignmentExpression") {
if (t.isAssignmentExpression(parent)) {
node = parent.left;
} else if (parent.type === "VariableDeclarator") {
} else if (t.isVariableDeclarator(parent)) {
node = parent.id;
}
var id = "ref";
if (node && node.type === "Identifier") {
id = node.name;
}
if (t.isIdentifier(node)) id = node.name;
return b.identifier(file.generateUid(id));
return t.identifier(file.generateUid(id));
};
exports.isAbsolute = function (loc) {
@@ -72,59 +52,6 @@ exports.isAbsolute = function (loc) {
return false;
};
exports.removeProperties = function (tree) {
var clear = function (node) {
delete node.tokens;
delete node.range;
delete node.loc;
};
clear(tree);
traverse(tree, clear);
return tree;
};
exports.getIds = function (node) {
var search = [node];
var ids = [];
while (search.length) {
var id = search.shift();
if (id.type === "Identifier") {
ids.push(id.name);
} else if (id.type === "ArrayPattern") {
_.each(id.elements, function (elem) {
search.push(elem);
});
} else if (id.type === "ObjectPattern") {
_.each(id.properties, function (prop) {
search.push(prop.value);
});
} else {
throw new Error("unknown node " + id.type);
}
}
return ids;
};
exports.errorWithNode = function (node, msg) {
var line = node.loc.start.line;
var col = node.loc.start.column;
var err = new SyntaxError("Line " + line + ": " + msg);
err.lineNumber = line;
err.column = col;
return err;
};
exports.canCompile = function (filename) {
var ext = path.extname(filename);
return _.contains([".js", ".es6"], ext);
};
exports.sourceMapToComment = function (map) {
var json = JSON.stringify(map);
var base64 = new Buffer(json).toString("base64");
@@ -132,98 +59,114 @@ exports.sourceMapToComment = function (map) {
};
exports.pushMutatorMap = function (mutatorMap, key, kind, method) {
var alias;
if (t.isIdentifier(key)) {
alias = key.name;
if (method.computed) alias = "computed:" + alias;
} else if (t.isLiteral(key)) {
alias = String(key.value);
} else {
alias = JSON.stringify(traverse.removeProperties(_.cloneDeep(key)));
}
var map;
if (_.has(mutatorMap, key)) {
map = mutatorMap[key];
if (_.has(mutatorMap, alias)) {
map = mutatorMap[alias];
} else {
map = {};
}
mutatorMap[key] = map;
mutatorMap[alias] = map;
if (map[kind]) {
throw new Error("a " + kind + " already exists for this property");
} else {
map[kind] = method;
map._key = key;
if (method.computed) {
map._computed = true;
}
map[kind] = method;
};
exports.buildDefineProperties = function (mutatorMap, keyNode) {
var objExpr = b.objectExpression([]);
exports.buildDefineProperties = function (mutatorMap) {
var objExpr = t.objectExpression([]);
_.each(mutatorMap, function (map, key) {
var mapNode = b.objectExpression([]);
_.each(mutatorMap, function (map) {
var mapNode = t.objectExpression([]);
var propNode = b.property("init", b.identifier(key), mapNode);
var propNode = t.property("init", map._key, mapNode, map._computed);
_.each(map, function (node, key) {
if (key[0] === "_") return;
node = _.clone(node);
if (node.type === "MethodDefinition") node = node.value;
mapNode.properties.push(b.property("init", b.identifier(key), node));
if (t.isMethodDefinition(node)) node = node.value;
mapNode.properties.push(t.property("init", t.identifier(key), node));
});
objExpr.properties.push(propNode);
});
return exports.template("object-define-properties", {
OBJECT: keyNode,
PROPS: objExpr
}, true);
return objExpr;
};
exports.template = function (name, nodes, keepExpression) {
var template = exports.templates[name];
if (!template) throw new ReferenceError("unknown template " + name);
if (nodes === true) {
keepExpression = true;
nodes = null;
}
template = _.cloneDeep(template);
if (!_.isEmpty(nodes)) {
traverse(template, function (node) {
if (node.type === "Identifier" && _.has(nodes, node.name)) {
var newNode = nodes[node.name];
if (_.isString(newNode)) {
node.name = newNode;
} else {
return newNode;
var inherits = false;
if (nodes) {
inherits = nodes.inherits;
delete nodes.inherits;
if (!_.isEmpty(nodes)) {
traverse(template, function (node) {
if (t.isIdentifier(node) && _.has(nodes, node.name)) {
var newNode = nodes[node.name];
if (_.isString(newNode)) {
node.name = newNode;
} else {
return newNode;
}
}
}
});
});
}
}
var node = template.body[0];
if (!keepExpression && node.type === "ExpressionStatement") {
return node.expression;
} else {
return node;
if (!keepExpression && t.isExpressionStatement(node)) {
node = node.expression;
if (t.isParenthesizedExpression(node)) node = node.expression;
}
};
exports.isReferenced = function (node, parent) {
// we're a property key
if (parent.type === "Property" && parent.key === node) return false;
if (inherits) {
node = t.inherits(node, inherits);
}
var isMemberExpression = parent.type === "MemberExpression";
// we're in a member expression and we're the computed property so we're referenced
var isComputedProperty = isMemberExpression && parent.property === node && parent.computed;
// we're in a member expression and we're the object so we're referenced
var isObject = isMemberExpression && parent.object === node;
// we are referenced
if (!isMemberExpression || isComputedProperty || isObject) return true;
return false;
return node;
};
exports.codeFrame = function (lines, lineNumber, colNumber) {
colNumber = Math.max(colNumber, 0);
lines = lines.split("\n");
var start = Math.max(lineNumber - 3, 0);
var end = Math.min(lines.length, lineNumber + 3);
var width = (end + "").length;
if (!lineNumber && !colNumber) {
start = 0;
end = lines.length;
}
return "\n" + lines.slice(start, end).map(function (line, i) {
var curr = i + start + 1;
@@ -251,14 +194,27 @@ exports.repeat = function (width, cha) {
exports.parse = function (opts, code, callback) {
try {
var recastOpts = {};
var comments = [];
var tokens = [];
if (opts.sourceMap) {
recastOpts.sourceFileName = opts.sourceFileName;
recastOpts.sourceRoot = opts.sourceRoot;
}
var ast = acorn.parse(code, {
allowReturnOutsideFunction: true,
preserveParens: true,
ecmaVersion: Infinity,
strictMode: true,
onComment: comments,
locations: true,
onToken: tokens,
ranges: true
});
var ast = recast.parse(code, recastOpts);
estraverse.attachComments(ast, comments, tokens);
ast = t.file(ast, comments, tokens);
traverse(ast, function (node, parent) {
node._parent = parent;
});
if (callback) {
return callback(ast);
@@ -270,12 +226,13 @@ exports.parse = function (opts, code, callback) {
err._6to5 = true;
var message = opts.filename + ": " + err.message;
if (err.loc) {
var frame = exports.codeFrame(code, err.loc.line, err.loc.column);
var loc = err.loc;
if (loc) {
var frame = exports.codeFrame(code, loc.line, loc.column);
message += frame;
}
err.stack = err.stack.replace(err.message, message);
if (err.stack) err.stack = err.stack.replace(err.message, message);
err.message = message;
}
@@ -285,21 +242,17 @@ exports.parse = function (opts, code, callback) {
exports.parseNoProperties = function (loc, code) {
var ast = exports.parse({ filename: loc }, code).program;
return exports.removeProperties(ast);
return traverse.removeProperties(ast);
};
try {
exports.templates = require("../../templates.json");
} catch (err) {
if (err.code !== "MODULE_NOT_FOUND") throw err;
exports.templates = {};
var loadTemplates = function () {
var templates = {};
var templatesLoc = __dirname + "/templates";
if (!fs.existsSync(templatesLoc)) {
throw new Error("no templates directory - this is most likely the result" +
" of a broken `npm publish`. Please report to " +
"https://github.com/sebmck/6to5/issues");
throw new Error("no templates directory - this is most likely the " +
"result of a broken `npm publish`. Please report to " +
"https://githut.com/6to5/6to5/issues");
}
_.each(fs.readdirSync(templatesLoc), function (name) {
@@ -309,6 +262,20 @@ try {
var loc = templatesLoc + "/" + name;
var code = fs.readFileSync(loc, "utf8");
exports.templates[key] = exports.parseNoProperties(loc, code);
templates[key] = exports.parseNoProperties(loc, code);
});
return templates;
};
try {
exports.templates = require("../../templates.json");
} catch (err) {
if (err.code !== "MODULE_NOT_FOUND") throw err;
Object.defineProperty(exports, "templates", {
get: function () {
return exports.templates = loadTemplates();
}
});
}

View File

@@ -1,21 +1,22 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "1.10.4",
"version": "1.11.10",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://github.com/sebmck/6to5",
"homepage": "https://github.com/6to5/6to5",
"repository": {
"type": "git",
"url": "https://github.com/sebmck/6to5.git"
"url": "https://github.com/6to5/6to5.git"
},
"bugs": {
"url": "https://github.com/sebmck/6to5/issues"
"url": "https://github.com/6to5/6to5/issues"
},
"preferGlobal": true,
"main": "lib/6to5/index.js",
"bin": {
"6to5": "./bin/6to5/index.js",
"6to5-node": "./bin/6to5-node"
"6to5-node": "./bin/6to5-node",
"6to5-runtime": "./bin/6to5-runtime"
},
"keywords": [
"harmony",
@@ -34,31 +35,30 @@
"test": "make test"
},
"dependencies": {
"commander": "2.4.0",
"ast-types": "~0.6.0",
"commander": "2.5.0",
"fs-readdir-recursive": "0.0.2",
"lodash": "2.4.1",
"mkdirp": "0.5.0",
"es6-shim": "0.18.0",
"es6-shim": "0.20.2",
"es6-symbol": "0.1.1",
"regexpu": "0.3.0",
"recast": "0.8.0",
"source-map": "0.1.40",
"regenerator": "0.6.7",
"chokidar": "0.10.0",
"source-map-support": "0.2.7",
"regenerator-6to5": "https://github.com/6to5/regenerator-6to5/archive/37798b2311c46975bc199ff595fe1b1f28bee94c.tar.gz",
"chokidar": "0.10.5",
"source-map-support": "0.2.8",
"esutils": "1.1.4",
"acorn-jsx": "https://github.com/sebmck/acorn-jsx/archive/master.tar.gz",
"acorn-recast": "0.8.0-3",
"acorn-ast-types": "0.5.3-1"
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/0384a0d51f630f66ed591769c1765581a17d2124.tar.gz",
"estraverse": "^1.7.0"
},
"devDependencies": {
"istanbul": "0.3.2",
"matcha": "0.5.0",
"mocha": "1.21.5",
"mocha": "2.0.1",
"uglify-js": "2.4.15",
"browserify": "6.1.0",
"proclaim": "2.0.0",
"browserify": "6.2.0",
"rimraf": "2.2.8",
"jshint": "2.5.6"
"jshint": "2.5.10",
"chai": "^1.9.2"
}
}

View File

@@ -1 +0,0 @@
require("./lib/6to5/polyfill");

7
test/_browser.js Normal file
View File

@@ -0,0 +1,7 @@
if (process.browser) {
require("../lib/6to5/browser");
require("./generation");
require("./transformation");
require("./traverse");
require("./util");
}

View File

@@ -1,56 +1,32 @@
var fs = require("fs");
var _ = require("lodash");
var fixturesDir = __dirname + "/fixtures/transformation";
var humanise = function (val) {
return val.replace(/-/g, " ");
};
var readFile = function (filename) {
if (fs.existsSync(filename)) {
return fs.readFileSync(filename, "utf8");
return fs.readFileSync(filename, "utf8").trim();
} else {
return "";
}
};
exports.run = function (suites, transform, assert) {
_.each(suites, function (testSuite) {
suite("transformation/" + testSuite.title, function () {
_.each(testSuite.tests, function (task) {
test(task.title, function () {
var run = function () {
transform.test(task, assert);
};
exports.get = function (entryName) {
if (exports.cache[entryName]) return exports.cache[entryName];
var throwMsg = task.options.throws;
if (throwMsg) {
// internal api doesn't have this option but it's best not to pollute
// the options object with useless options
delete task.options.throws;
assert.throws(run, new RegExp(throwMsg));
} else {
run();
}
});
});
});
});
};
exports.getTests = function () {
var suites = [];
var entryLoc = __dirname + "/fixtures/" + entryName;
_.each(fs.readdirSync(fixturesDir), function (suiteName) {
_.each(fs.readdirSync(entryLoc), function (suiteName) {
if (suiteName[0] === ".") return;
var suite = {
options: {},
tests: [],
title: humanise(suiteName),
filename: fixturesDir + "/" + suiteName
filename: entryLoc + "/" + suiteName
};
suites.push(suite);
@@ -87,10 +63,12 @@ exports.getTests = function () {
filename: execLocAlias,
},
actual: {
loc: actualLoc,
code: readFile(actualLoc),
filename: actualLocAlias,
},
expect: {
loc: expectLoc,
code: readFile(expectLoc),
filename: expectLocAlias
}
@@ -112,5 +90,15 @@ exports.getTests = function () {
});
});
return suites;
return exports.cache[entryName] = suites;
};
try {
exports.cache = require("../tests.json");
} catch (err) {
if (err.code !== "MODULE_NOT_FOUND") throw err;
var cache = exports.cache = {};
cache.transformation = exports.get("transformation");
cache.generation = exports.get("generation");
}

View File

@@ -4,6 +4,7 @@ var rimraf = require("rimraf");
var mkdirp = require("mkdirp");
var child = require("child_process");
var path = require("path");
var chai = require("chai");
var fs = require("fs");
var _ = require("lodash");
@@ -42,7 +43,7 @@ var assertTest = function (stdout, stderr, opts) {
if (opts.stderrContains) {
assert.ok(_.contains(stderr, expectStderr), "stderr " + JSON.stringify(stderr) + " didn't contain " + JSON.stringify(expectStderr));
} else {
assert.equal(stderr, expectStderr, "stderr didn't match");
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
}
} else if (stderr) {
throw new Error("stderr: " + JSON.stringify(stderr));
@@ -55,7 +56,7 @@ var assertTest = function (stdout, stderr, opts) {
if (opts.stdoutContains) {
assert.ok(_.contains(stdout, expectStdout), "stdout " + JSON.stringify(stdout) + " didn't contain " + JSON.stringify(expectStdout));
} else {
assert.equal(stdout, expectStdout, "stdout didn't match");
chai.expect(stdout).to.equal(expectStdout, "stdout didn't match");
}
} else if (stdout) {
throw new Error("stdout: " + JSON.stringify(stdout));
@@ -63,7 +64,7 @@ var assertTest = function (stdout, stderr, opts) {
_.each(opts.outFiles, function (expect, filename) {
var actual = readFile(filename);
assert.equal(actual, expect, "out-file " + filename);
chai.expect(actual).to.equal(expect, "out-file " + filename);
});
};

View File

@@ -6,10 +6,8 @@
</head>
<body>
<div id="mocha"></div>
<script src="../node_modules/proclaim/lib/proclaim.js"></script>
<script src="../node_modules/lodash/lodash.js"></script>
<script src="../node_modules/mocha/mocha.js"></script>
<script src="../dist/6to5.js"></script>
<script>mocha.setup("tdd");</script>
<script src="../dist/6to5-test.js"></script>
<script>

View File

@@ -1,2 +1,3 @@
"use strict";
arr.map(x => x * MULTIPLIER);

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