Compare commits
755 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8ec4c965c | ||
|
|
d2aff67c6c | ||
|
|
3353de225d | ||
|
|
203ebeef20 | ||
|
|
032cf990c3 | ||
|
|
16cdb43c67 | ||
|
|
6f622033c5 | ||
|
|
531d4f1937 | ||
|
|
f155bc249c | ||
|
|
452d0ef30e | ||
|
|
005754ba98 | ||
|
|
c3c4cf17e3 | ||
|
|
0866e5a403 | ||
|
|
15f5e658fc | ||
|
|
574e6da132 | ||
|
|
da6d27ed16 | ||
|
|
4e87809ff9 | ||
|
|
f4267aaab0 | ||
|
|
4f255d103a | ||
|
|
502cc13aed | ||
|
|
0a1154e6fd | ||
|
|
f5b3d72730 | ||
|
|
e9bcccffbd | ||
|
|
aaf4cbf06f | ||
|
|
5080534974 | ||
|
|
02cb397873 | ||
|
|
d9169a87ad | ||
|
|
f3b6f2fc61 | ||
|
|
04cc24ee82 | ||
|
|
f32079ef42 | ||
|
|
d1b69656ae | ||
|
|
09453a490b | ||
|
|
e2e7627f0f | ||
|
|
4fe24a9a3b | ||
|
|
d26e7ad577 | ||
|
|
571cb4928f | ||
|
|
c12e8122f8 | ||
|
|
92e7a01d14 | ||
|
|
b9ca9d42dc | ||
|
|
479c3e477a | ||
|
|
2c3d3d8105 | ||
|
|
ea03f67505 | ||
|
|
ee0c88a070 | ||
|
|
98206df864 | ||
|
|
1066a42fb2 | ||
|
|
062175586c | ||
|
|
0dc6b582a6 | ||
|
|
d8d70ba137 | ||
|
|
f23c916520 | ||
|
|
8ae4601177 | ||
|
|
9a466d3ef9 | ||
|
|
713845d14c | ||
|
|
471d60e5cd | ||
|
|
43864e0686 | ||
|
|
4c2ae5dd19 | ||
|
|
a540cbe801 | ||
|
|
34cc577fa2 | ||
|
|
c855b55133 | ||
|
|
16c86c25b7 | ||
|
|
4345f7945b | ||
|
|
f44c93add2 | ||
|
|
09e45c51a4 | ||
|
|
1a42b72b15 | ||
|
|
d30415d74a | ||
|
|
616ef8d840 | ||
|
|
56437f94bc | ||
|
|
881fa6430b | ||
|
|
b7971690f3 | ||
|
|
c01d0abbd3 | ||
|
|
7043119346 | ||
|
|
b5325df57f | ||
|
|
0fc958e0fc | ||
|
|
9cb16711dd | ||
|
|
04766b13f5 | ||
|
|
433d704739 | ||
|
|
30204d2ee6 | ||
|
|
374b7cca2c | ||
|
|
152ae388f0 | ||
|
|
04344026bb | ||
|
|
cfffaf6cdb | ||
|
|
2952d94e60 | ||
|
|
0276c3ae81 | ||
|
|
c00f8dce3f | ||
|
|
4e24ae39cf | ||
|
|
12bd6494b7 | ||
|
|
e35c7550fe | ||
|
|
e7046abe72 | ||
|
|
affa7f0c6f | ||
|
|
be650ffc61 | ||
|
|
3078d48178 | ||
|
|
0be93563dd | ||
|
|
3e55980145 | ||
|
|
470ebf3a46 | ||
|
|
b695369126 | ||
|
|
f4611469b4 | ||
|
|
68bfafe745 | ||
|
|
f72782b71c | ||
|
|
0f1f5e3565 | ||
|
|
dfe126f3d4 | ||
|
|
4c9cb957a9 | ||
|
|
8f997f8825 | ||
|
|
d789a6e7aa | ||
|
|
4007148d9f | ||
|
|
998f1d544e | ||
|
|
deed48a3db | ||
|
|
00c0a958db | ||
|
|
1511dcbd73 | ||
|
|
12fef25803 | ||
|
|
fd30eb1839 | ||
|
|
63344eb0a4 | ||
|
|
6e4e11a365 | ||
|
|
e330efe058 | ||
|
|
ce86eca8b0 | ||
|
|
03dbaa3e0e | ||
|
|
2bd35fac6e | ||
|
|
cdca4e50d9 | ||
|
|
bb041c1bd6 | ||
|
|
a36c1b4a92 | ||
|
|
b760daca21 | ||
|
|
ff63d8f60c | ||
|
|
74f04ed6a1 | ||
|
|
74d880bf18 | ||
|
|
5ce38cacaa | ||
|
|
829f642ad8 | ||
|
|
80a4b95da4 | ||
|
|
dc2a20dbcd | ||
|
|
f6278e43ce | ||
|
|
30bc80000b | ||
|
|
ef56042c93 | ||
|
|
b6498103db | ||
|
|
7af4302d07 | ||
|
|
543770960c | ||
|
|
a2975a72cc | ||
|
|
beb3fd51d8 | ||
|
|
9360860601 | ||
|
|
7d4ecea8fb | ||
|
|
a44831b3fa | ||
|
|
8357f3900f | ||
|
|
6b1c5bc358 | ||
|
|
3564309a77 | ||
|
|
c9518bb60d | ||
|
|
0f1215e33e | ||
|
|
d7b0b5bec0 | ||
|
|
3e5af404ab | ||
|
|
1818094577 | ||
|
|
6d712b3d14 | ||
|
|
11389fe165 | ||
|
|
0ee9531db3 | ||
|
|
1622d2498d | ||
|
|
b76e6f8e5b | ||
|
|
beac006832 | ||
|
|
20d7603c0b | ||
|
|
24b13c5e49 | ||
|
|
9e21074e88 | ||
|
|
9a825bced7 | ||
|
|
fcb78436c6 | ||
|
|
bb30a64f8d | ||
|
|
b483c16fe2 | ||
|
|
569f046045 | ||
|
|
4e969d3d92 | ||
|
|
0bca1de285 | ||
|
|
3a5bd06a7e | ||
|
|
66a908aaa7 | ||
|
|
cd0ed08237 | ||
|
|
dd84b554e6 | ||
|
|
b51411f090 | ||
|
|
4cc843ded3 | ||
|
|
47d253c732 | ||
|
|
09901274ab | ||
|
|
35196e20c7 | ||
|
|
35af771a29 | ||
|
|
dee80caa09 | ||
|
|
46b7cc0a72 | ||
|
|
3b189e22b7 | ||
|
|
6ca565d7fb | ||
|
|
64f5480f96 | ||
|
|
828fdc8769 | ||
|
|
6763c4415e | ||
|
|
fb30e79e03 | ||
|
|
85fb4304b0 | ||
|
|
c2da77d7ec | ||
|
|
c54c3d3c15 | ||
|
|
2a7c954155 | ||
|
|
3fb7f7c7cc | ||
|
|
c4b2818336 | ||
|
|
061561bfd8 | ||
|
|
d4944d606b | ||
|
|
736b689c3b | ||
|
|
e12b377014 | ||
|
|
5fd5b815ab | ||
|
|
92db8312f6 | ||
|
|
e080fe547d | ||
|
|
b967ecf063 | ||
|
|
365b7285d2 | ||
|
|
a40d532b0e | ||
|
|
0487bf911d | ||
|
|
57c72d1cd0 | ||
|
|
335bdffec2 | ||
|
|
e1d76a1dfe | ||
|
|
a4845323a2 | ||
|
|
792951b489 | ||
|
|
5adda836af | ||
|
|
4c2c3098c3 | ||
|
|
087c714098 | ||
|
|
5a33e4fe05 | ||
|
|
5f8667eaa7 | ||
|
|
31b4468514 | ||
|
|
2be9678bbe | ||
|
|
b5210877cf | ||
|
|
658dde768e | ||
|
|
8df1d81ca4 | ||
|
|
a505e4a121 | ||
|
|
71eafdcac7 | ||
|
|
65060b0c97 | ||
|
|
09883962f1 | ||
|
|
1583262807 | ||
|
|
04c7cd5c0c | ||
|
|
3f6969f4f8 | ||
|
|
23db842cb8 | ||
|
|
41c82e00f9 | ||
|
|
766099e783 | ||
|
|
53bc54b3b2 | ||
|
|
bb70f37123 | ||
|
|
8a0317132e | ||
|
|
f598c70841 | ||
|
|
61b57ea055 | ||
|
|
a971ad7fd2 | ||
|
|
27b6f804ce | ||
|
|
8ab79f3a72 | ||
|
|
0c2bf2f5a2 | ||
|
|
7e1a4be085 | ||
|
|
bbc951dfe1 | ||
|
|
b3e4aefe12 | ||
|
|
26b5174dfa | ||
|
|
652d3c7320 | ||
|
|
edc2cd320c | ||
|
|
274a6e01dc | ||
|
|
3561efdb86 | ||
|
|
1a30f1aafc | ||
|
|
e362512af3 | ||
|
|
cf5d2429b4 | ||
|
|
72098036b2 | ||
|
|
7905f48280 | ||
|
|
aba2d1c23c | ||
|
|
5326e0543d | ||
|
|
1360c93e4b | ||
|
|
235cbc18cf | ||
|
|
98c5255b91 | ||
|
|
2a9777cc20 | ||
|
|
a8702be756 | ||
|
|
0995cc3f4e | ||
|
|
1cfca745a4 | ||
|
|
a3459deecf | ||
|
|
070152f6c1 | ||
|
|
719fdf5ca1 | ||
|
|
f2460c6173 | ||
|
|
155c640409 | ||
|
|
7de4718b27 | ||
|
|
4e6aed0408 | ||
|
|
3be8ccf68d | ||
|
|
704b31f44f | ||
|
|
1a9f193841 | ||
|
|
7ff67589a7 | ||
|
|
80f109efeb | ||
|
|
77c72bb5a6 | ||
|
|
6c5e0e6590 | ||
|
|
83324b977d | ||
|
|
5feab11d3f | ||
|
|
7b4172ce7b | ||
|
|
84439384c0 | ||
|
|
c9e7c306cc | ||
|
|
1e398e45ff | ||
|
|
475324c4b5 | ||
|
|
407daf4bac | ||
|
|
4155590cd8 | ||
|
|
0be6fd7abe | ||
|
|
cf51bf1395 | ||
|
|
06a31c419a | ||
|
|
da566110c0 | ||
|
|
c12c4a5c39 | ||
|
|
d114349890 | ||
|
|
8d6ae0e1eb | ||
|
|
cb8b47ee2f | ||
|
|
daf24c5c59 | ||
|
|
cdb2784e75 | ||
|
|
93feabb82e | ||
|
|
982c142bf6 | ||
|
|
de5520a94f | ||
|
|
c239d06f10 | ||
|
|
a5fed376d8 | ||
|
|
e99fd77d89 | ||
|
|
1374863b9c | ||
|
|
e88c28f88b | ||
|
|
7a0fd26f56 | ||
|
|
17583e4807 | ||
|
|
37dd5137ff | ||
|
|
24fced406e | ||
|
|
0ab1362893 | ||
|
|
96506f4249 | ||
|
|
ed747f88bd | ||
|
|
3987545b4f | ||
|
|
148aa3f96d | ||
|
|
0cb5a7c91e | ||
|
|
fc34d5a9b0 | ||
|
|
f8d56d9612 | ||
|
|
737be0e95e | ||
|
|
26e2b392e8 | ||
|
|
708cdfb993 | ||
|
|
8cb3aabefa | ||
|
|
4a87b35d20 | ||
|
|
543554b258 | ||
|
|
afd95cf663 | ||
|
|
87ce4b9cd8 | ||
|
|
6b76f26ed8 | ||
|
|
c2776e63ae | ||
|
|
3f2fe363d1 | ||
|
|
8de28098f4 | ||
|
|
584532cc2c | ||
|
|
9a28f3fdb1 | ||
|
|
88941b3270 | ||
|
|
3a768db2bf | ||
|
|
320a39f4c4 | ||
|
|
dc98ac7c93 | ||
|
|
6e456f0ec1 | ||
|
|
793090628d | ||
|
|
9ed251cb08 | ||
|
|
480fa7f4e0 | ||
|
|
3e642dfa1b | ||
|
|
d9cbce1862 | ||
|
|
4bd19da3c2 | ||
|
|
7c710a0378 | ||
|
|
56335409d3 | ||
|
|
91d78afc67 | ||
|
|
54c6339f20 | ||
|
|
fdcf64265e | ||
|
|
ffdfb491eb | ||
|
|
eedd431f2b | ||
|
|
db9ed0235f | ||
|
|
6c98d39937 | ||
|
|
20651df3ce | ||
|
|
f3155919fe | ||
|
|
0ac8330899 | ||
|
|
67201e9698 | ||
|
|
c715d96e46 | ||
|
|
b7a08100a6 | ||
|
|
5f91ee8a1a | ||
|
|
bc1abb5103 | ||
|
|
4b9207e5df | ||
|
|
e847f3685f | ||
|
|
d64c2c0c45 | ||
|
|
76d0fb4ba6 | ||
|
|
0f33b7bfbc | ||
|
|
630224e504 | ||
|
|
62980ab6b4 | ||
|
|
d34480b42b | ||
|
|
306de2edbf | ||
|
|
c33e84730d | ||
|
|
20f28aba64 | ||
|
|
9c312607d1 | ||
|
|
33659711c3 | ||
|
|
b154af48a7 | ||
|
|
bad877946f | ||
|
|
dff3751e7f | ||
|
|
23038dcfff | ||
|
|
7c7a7ee17f | ||
|
|
9f467ef7c0 | ||
|
|
a52f9ab346 | ||
|
|
5ccbed585b | ||
|
|
f7c7da7526 | ||
|
|
ed58c80c64 | ||
|
|
d7fb9f67df | ||
|
|
eef6002324 | ||
|
|
32bcf4c3a5 | ||
|
|
86060cb0ce | ||
|
|
66a836d435 | ||
|
|
ecc14c2a31 | ||
|
|
7e9b60fba5 | ||
|
|
313f1e755a | ||
|
|
8c7ef0a2c9 | ||
|
|
8f79010b16 | ||
|
|
022e6f26aa | ||
|
|
138fa6c9f8 | ||
|
|
c07704cc80 | ||
|
|
bf811ea34a | ||
|
|
8af3ea1c43 | ||
|
|
5fbe147a5e | ||
|
|
a9e214b1db | ||
|
|
6812fca7a9 | ||
|
|
ebc42f5ce0 | ||
|
|
b12a97ddd6 | ||
|
|
e8daad38a7 | ||
|
|
c6c0bc07e2 | ||
|
|
c60f3f0e34 | ||
|
|
07078138f3 | ||
|
|
cb0026edfe | ||
|
|
ab55ec4ea2 | ||
|
|
e164123ce9 | ||
|
|
f42bacf4f6 | ||
|
|
46adb07d41 | ||
|
|
e10bdf7c5b | ||
|
|
83eea2acc7 | ||
|
|
8bdd4cc559 | ||
|
|
15d31b5608 | ||
|
|
9ed6a7b650 | ||
|
|
01a2aa7dd1 | ||
|
|
33fde5f143 | ||
|
|
682c775a97 | ||
|
|
4846b89931 | ||
|
|
25312396a5 | ||
|
|
cfff7aa6fb | ||
|
|
f88a4147a6 | ||
|
|
3c343adf33 | ||
|
|
269587cde5 | ||
|
|
121ba8c381 | ||
|
|
563a427b69 | ||
|
|
658164a0d2 | ||
|
|
135ba84abb | ||
|
|
76573093bd | ||
|
|
22b88487ee | ||
|
|
3686951dc1 | ||
|
|
f43ca32ff5 | ||
|
|
424a59a856 | ||
|
|
5f159853d5 | ||
|
|
f9c56c6dd7 | ||
|
|
613e77cd50 | ||
|
|
27c97aab34 | ||
|
|
ad857dddd1 | ||
|
|
d9762e9049 | ||
|
|
088846a347 | ||
|
|
7fc28cb63f | ||
|
|
3323e0f3a5 | ||
|
|
8c09a2198a | ||
|
|
eeb5b8d0c3 | ||
|
|
19e8274e79 | ||
|
|
6353abfd1b | ||
|
|
ee14770a5c | ||
|
|
d3b9b7251e | ||
|
|
3f7f89a6b9 | ||
|
|
7476b8c6a3 | ||
|
|
1ef41b6f32 | ||
|
|
6bc2bfce7d | ||
|
|
153e81261c | ||
|
|
b8f2a27e90 | ||
|
|
2f25c3bd17 | ||
|
|
59e07b65dd | ||
|
|
769f7fb81d | ||
|
|
7895857624 | ||
|
|
80fed5f395 | ||
|
|
1c7fabdd6d | ||
|
|
12f8fa229d | ||
|
|
c6546264d2 | ||
|
|
86cc5875cf | ||
|
|
9ea999b261 | ||
|
|
f81e841283 | ||
|
|
c14ffb8319 | ||
|
|
b9f4fe86f1 | ||
|
|
56ada634b4 | ||
|
|
c4d68897b3 | ||
|
|
1641caedc4 | ||
|
|
3d6e722fc7 | ||
|
|
253493a43f | ||
|
|
66471f044a | ||
|
|
5fa227eb73 | ||
|
|
f3b50f0bb9 | ||
|
|
92bba76bd5 | ||
|
|
46462e3e69 | ||
|
|
bc155f956c | ||
|
|
dc1ba58705 | ||
|
|
99e274921f | ||
|
|
862bd6d92a | ||
|
|
46d991e3e9 | ||
|
|
8e1b6df970 | ||
|
|
f9c8d7d1fd | ||
|
|
eb2f61e43f | ||
|
|
afe8792ba4 | ||
|
|
42a2430d2c | ||
|
|
c4d260231b | ||
|
|
ca5daca5dd | ||
|
|
3952eefd01 | ||
|
|
52c6fe2bc1 | ||
|
|
6a698f7ae4 | ||
|
|
2b0c07c2e7 | ||
|
|
e27e7facac | ||
|
|
0dd32e7d9c | ||
|
|
286ae68da2 | ||
|
|
e26f994075 | ||
|
|
94f005e324 | ||
|
|
93e37aaaf1 | ||
|
|
e4db93f6a5 | ||
|
|
c9243e8e97 | ||
|
|
bbba374783 | ||
|
|
7d95fddbed | ||
|
|
617ed09227 | ||
|
|
6d7887cfe2 | ||
|
|
b8e9171aaa | ||
|
|
22118c0be0 | ||
|
|
3754f7615f | ||
|
|
b54901018b | ||
|
|
121b9ca063 | ||
|
|
4988a27b6c | ||
|
|
e0297e08b8 | ||
|
|
79005d2f03 | ||
|
|
5cce8c32a4 | ||
|
|
95b1accddc | ||
|
|
6149e6325f | ||
|
|
4c9d4d0378 | ||
|
|
2e599bef4f | ||
|
|
885da177f9 | ||
|
|
463112517f | ||
|
|
8f10dc5c39 | ||
|
|
0f99bbe293 | ||
|
|
0a5d2c098f | ||
|
|
dcf4381e26 | ||
|
|
543582ef47 | ||
|
|
a4db58ccaa | ||
|
|
d3971e0874 | ||
|
|
ad98186afc | ||
|
|
df251fbfff | ||
|
|
dfbcf95b0e | ||
|
|
07646475d9 | ||
|
|
9bc67c28e3 | ||
|
|
c2990d3548 | ||
|
|
803f8a3bbc | ||
|
|
ee6efee4f8 | ||
|
|
3f144e6e74 | ||
|
|
afedfe15ae | ||
|
|
b522294d3c | ||
|
|
954af72476 | ||
|
|
de42a6f796 | ||
|
|
06a58f228c | ||
|
|
7a44576c26 | ||
|
|
eaa3865427 | ||
|
|
b83907cc67 | ||
|
|
a3620a58f8 | ||
|
|
67a12f03fa | ||
|
|
c49871d33c | ||
|
|
c828688d21 | ||
|
|
bd052aea50 | ||
|
|
ed74ccaa7d | ||
|
|
f3c9551b75 | ||
|
|
710a7f882d | ||
|
|
902ebd3fe7 | ||
|
|
23c20cc47c | ||
|
|
9b627ace5d | ||
|
|
4fa17341f5 | ||
|
|
1e019c0f16 | ||
|
|
ce25ebacbf | ||
|
|
daecec2a86 | ||
|
|
238f9c2e7e | ||
|
|
bc5f2b9be6 | ||
|
|
5390715705 | ||
|
|
aa1333123c | ||
|
|
048f9acc55 | ||
|
|
ed6421876a | ||
|
|
e60c9fba6a | ||
|
|
902db03e96 | ||
|
|
de88b28988 | ||
|
|
0ee230d13c | ||
|
|
c12cfe3ed0 | ||
|
|
1376f2f18f | ||
|
|
972c621f59 | ||
|
|
5c41a33e41 | ||
|
|
bc6d01d6fc | ||
|
|
01463faf36 | ||
|
|
b234603e24 | ||
|
|
ca79fff0c4 | ||
|
|
3c8f3cb521 | ||
|
|
c9974a42ea | ||
|
|
a87f6f6fdd | ||
|
|
3d28ce7903 | ||
|
|
e04ecc79c7 | ||
|
|
3e26511fb2 | ||
|
|
9c3493e02f | ||
|
|
a14e979897 | ||
|
|
a4ce653bed | ||
|
|
70d068226a | ||
|
|
30b1c0154d | ||
|
|
a602873281 | ||
|
|
c8b88182f6 | ||
|
|
64f1c114c1 | ||
|
|
4ac1a856ae | ||
|
|
0e68b6ca11 | ||
|
|
2dccc8c919 | ||
|
|
fdea18a289 | ||
|
|
c3bdecbd25 | ||
|
|
ee63fb52b7 | ||
|
|
8575392606 | ||
|
|
d28583bea1 | ||
|
|
b166f35218 | ||
|
|
0914378bba | ||
|
|
660d764390 | ||
|
|
27206d6b7c | ||
|
|
34dc56b435 | ||
|
|
d919d7837c | ||
|
|
b49cf4e779 | ||
|
|
e30dd7042b | ||
|
|
16d8d928e8 | ||
|
|
4966028397 | ||
|
|
82e04fffac | ||
|
|
a46313903d | ||
|
|
68340b1288 | ||
|
|
6a1b33b443 | ||
|
|
df7524d909 | ||
|
|
2c39d406d1 | ||
|
|
2ff1a5d98b | ||
|
|
7f9fe4af15 | ||
|
|
977290c7e4 | ||
|
|
ebbdb95278 | ||
|
|
9b586c7587 | ||
|
|
4b5ba6c8c6 | ||
|
|
67efb1b427 | ||
|
|
bc9c1ab61e | ||
|
|
65ffe07551 | ||
|
|
b606cc79ca | ||
|
|
0e7fd0741d | ||
|
|
276cafaae1 | ||
|
|
4f00de50d6 | ||
|
|
b07341a1f7 | ||
|
|
ec526f9224 | ||
|
|
76301a7713 | ||
|
|
67ac91815b | ||
|
|
976e8c1cfd | ||
|
|
4d965b0f46 | ||
|
|
b495370740 | ||
|
|
b1c5915ed3 | ||
|
|
d94bb2e048 | ||
|
|
25fa10e592 | ||
|
|
8d3a7acbd1 | ||
|
|
29d33dd31a | ||
|
|
4afd0f553e | ||
|
|
1fb877e9f5 | ||
|
|
866d3a8eab | ||
|
|
76e1f0dd9f | ||
|
|
1bbe52a022 | ||
|
|
cc0f43813c | ||
|
|
b13b4bbfba | ||
|
|
1c6ac0a07a | ||
|
|
5a319fd553 | ||
|
|
a8cedf813b | ||
|
|
9f037fa75e | ||
|
|
8681a78618 | ||
|
|
2d72d423b3 | ||
|
|
280964eafe | ||
|
|
5ee9b3c37e | ||
|
|
9676056f08 | ||
|
|
080a844457 | ||
|
|
1f9f57a2a6 | ||
|
|
056b7fc634 | ||
|
|
547ecc2f73 | ||
|
|
a1ab8fa0c1 | ||
|
|
9e61a307d4 | ||
|
|
d4d18f4230 | ||
|
|
f4ce216d1c | ||
|
|
d71c72de3c | ||
|
|
b1c21b8d4d | ||
|
|
e9b0005cf5 | ||
|
|
63bac550cd | ||
|
|
d0b6aa9882 | ||
|
|
0e877acfdf | ||
|
|
b670ee18df | ||
|
|
24807120bf | ||
|
|
33f7c0b67e | ||
|
|
c23b47f796 | ||
|
|
2871d8a710 | ||
|
|
3172b5de5d | ||
|
|
2c05303813 | ||
|
|
75dda10057 | ||
|
|
12664c6cd6 | ||
|
|
581f70c803 | ||
|
|
a00d2c33d8 | ||
|
|
c906bd3edc | ||
|
|
27fc574e9f | ||
|
|
a3b1fcc79c | ||
|
|
491cb26c1f | ||
|
|
7c3d052714 | ||
|
|
4971d0c7f0 | ||
|
|
eb4922b1ec | ||
|
|
bb26183b44 | ||
|
|
4b066f7f1b | ||
|
|
41a8257005 | ||
|
|
b44ba25d11 | ||
|
|
40a111abbf | ||
|
|
9cff51915d | ||
|
|
3cd110a7c9 | ||
|
|
a7f9e035a4 | ||
|
|
146b9e6708 | ||
|
|
0953c48620 | ||
|
|
056b90831d | ||
|
|
8ba276b209 | ||
|
|
8eaa9d29e3 | ||
|
|
6212791356 | ||
|
|
d436d32d82 | ||
|
|
2a29f70bba | ||
|
|
6ccb8957bd | ||
|
|
dc45415ee0 | ||
|
|
98ca541fde | ||
|
|
8328f638c2 | ||
|
|
5586ce280f | ||
|
|
0ca71f5e15 | ||
|
|
212776e220 | ||
|
|
4a95a9ec8f | ||
|
|
45953ffc8a | ||
|
|
9c79290bb2 | ||
|
|
cfdf6b7385 | ||
|
|
907e0e0f86 | ||
|
|
f3bd9cbcb8 | ||
|
|
3bd14f9e07 | ||
|
|
102b4b3d1e | ||
|
|
6564f1ff76 | ||
|
|
58d7a5e069 | ||
|
|
f5db53cebe | ||
|
|
2da010fcae | ||
|
|
52b99bdf93 | ||
|
|
9d7e953451 | ||
|
|
b1252b865b | ||
|
|
068b1341d9 | ||
|
|
20eb143915 | ||
|
|
1302a86bf2 | ||
|
|
b7831f1d7b | ||
|
|
e46cabb21f | ||
|
|
fff06a047e | ||
|
|
6b0320fc83 | ||
|
|
5dde63fa0a | ||
|
|
672118149a | ||
|
|
5e0236d9a7 | ||
|
|
5101664e7d | ||
|
|
2d684a06d3 | ||
|
|
e31bad8f42 | ||
|
|
644b4373fc | ||
|
|
62f37c1e62 | ||
|
|
fc0e89463b | ||
|
|
56b6a795a4 | ||
|
|
17b34a2959 | ||
|
|
c4da0253c5 | ||
|
|
5f2df40f6d | ||
|
|
7d20a9b882 | ||
|
|
ee0ac9f149 | ||
|
|
c5d3f42d8a | ||
|
|
d162919a53 | ||
|
|
d1f712344d | ||
|
|
e985912b54 | ||
|
|
97a21e4a34 | ||
|
|
d8fb7812f7 | ||
|
|
bfe63f5885 | ||
|
|
44ca6873a3 | ||
|
|
2f66ea7338 | ||
|
|
70967cf53c | ||
|
|
dc117a74ae | ||
|
|
b0f32a822d | ||
|
|
fd99ea1749 | ||
|
|
572129542d | ||
|
|
6f53980bfc | ||
|
|
348af1990d | ||
|
|
bd5f350728 | ||
|
|
958fa282f4 |
8
.babelrc
8
.babelrc
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"experimental": true,
|
||||
"playground": true,
|
||||
"loose": true,
|
||||
"blacklist": ["es6.tailCall"]
|
||||
"stage": 0,
|
||||
"loose": ["all"],
|
||||
"blacklist": ["es6.tailCall"],
|
||||
"optional": ["optimisation.flow.forOf"]
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ root = true
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
|
||||
[*.{js,json}]
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
test/tmp
|
||||
test/core/tmp
|
||||
*.log
|
||||
*.cache
|
||||
/templates.json
|
||||
@@ -11,6 +11,7 @@ test/tmp
|
||||
coverage
|
||||
dist
|
||||
.package.json
|
||||
packages/babel-runtime/*.js
|
||||
packages/babel-runtime/core-js
|
||||
packages/babel-runtime/helpers/*.js
|
||||
packages/babel-runtime/regenerator/*.js
|
||||
lib
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,12 +1,6 @@
|
||||
[submodule "vendor/traceur"]
|
||||
path = vendor/traceur
|
||||
url = https://github.com/google/traceur-compiler
|
||||
[submodule "vendor/regenerator"]
|
||||
path = vendor/regenerator
|
||||
url = https://github.com/babel/regenerator-babel
|
||||
[submodule "vendor/test262"]
|
||||
path = vendor/test262
|
||||
url = https://github.com/tc39/test262
|
||||
[submodule "vendor/compat-table"]
|
||||
path = vendor/compat-table
|
||||
url = https://github.com/kangax/compat-table
|
||||
|
||||
25
.npmignore
25
.npmignore
@@ -1,16 +1,15 @@
|
||||
node_modules
|
||||
*.log
|
||||
*.cache
|
||||
lib/babel/transformation/templates
|
||||
test
|
||||
benchmark
|
||||
Makefile
|
||||
.*
|
||||
dist
|
||||
tests.json
|
||||
CHANGELOG.md
|
||||
.package.json
|
||||
coverage
|
||||
vendor
|
||||
packages
|
||||
src
|
||||
/lib/babel/transformation/templates
|
||||
/test
|
||||
/benchmark
|
||||
/Makefile
|
||||
/dist
|
||||
/tests.json
|
||||
/CHANGELOG.md
|
||||
/.package.json
|
||||
/coverage
|
||||
/vendor
|
||||
/packages
|
||||
/src
|
||||
|
||||
10
.travis.yml
10
.travis.yml
@@ -1,14 +1,12 @@
|
||||
sudo: false
|
||||
#sudo: false
|
||||
language: node_js
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "iojs"
|
||||
|
||||
branches:
|
||||
except:
|
||||
- experimental
|
||||
|
||||
before_script: "npm install -g codeclimate-test-reporter"
|
||||
script: "make test-travis"
|
||||
|
||||
|
||||
374
CHANGELOG.md
374
CHANGELOG.md
@@ -13,6 +13,380 @@ _Note: Gaps between patch versions are faulty/broken releases._
|
||||
|
||||
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
|
||||
|
||||
## 5.2.5
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix `parse` API not adding all the correct pipeline transformers.
|
||||
|
||||
## 5.2.4
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix race condition with the Node API being loaded awkwardly and not being able to initialise itself when used in the browser.
|
||||
* **Internal**
|
||||
* Expose `transform.pipeline`.
|
||||
|
||||
## 5.2.3
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix plugin containers being called with an undefined import. Thanks [@timbur](https://github.com/timbur)!
|
||||
* Allow Flow object separators to be commas. Thanks [@monsanto](https://github.com/monsanto)!
|
||||
* Add missing `Statement` and `Declaration` node aliases to flow types.
|
||||
|
||||
## 5.2.2
|
||||
|
||||
* **Internal**
|
||||
* Allow `util.arrayify` to take arbitrary types and coerce it into an array.
|
||||
|
||||
## 5.2.1
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix regression in `node/register` that caused `node_modules` to not be ignored.
|
||||
|
||||
## 5.2.0
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix plugin strings splitting arbitrarily on `:` which caused full paths on Windows to fail as they include `:` after the drive letter.
|
||||
* Call class property `initializer`s with their target instead of their descriptor.
|
||||
* Fix `ignore` and `only` not properly working on Windows path separators. Thanks [@stagas](https://github.com/stagas)!
|
||||
* Fix `resolveRc` running on files twice causing issues. Thanks [@lukescott](https://github.com/lukescott)!
|
||||
* Fix shorthand properties not correctly being target for `isReferenced` checks. Thanks [@monsanto](https://github.com/monsanto)!
|
||||
* **Polish**
|
||||
* Allow passing an array of globs to `babel/register` `only` and `ignore` options. Thanks [@Mark-Simulacrum](https://github.com/Mark-Simulacrum)!
|
||||
* When inferring function names that collide with upper bindings, instead of doing the wrapper, instead rename them.
|
||||
* Consider constant-like variable declaration functions to always refer to themselves so TOC can be performed.
|
||||
* Process globs manually when using `$ babel` as some shells such as Windows don't explode them. Thanks [@jden](https://github.com/jden)!
|
||||
* Add alternative way to execute plugins via a closure that's called with the current Babel instance.
|
||||
* **Internal**
|
||||
* Remove multiple internal transformers in favor of directly doing things when we need to. Previously, declarations such as `_ref` that we needed to create in specific scopes were done at the very end via the `_declarations` transformer. Now, they're done and added to the scope **right** when they're needed. This gets rid of the crappy `_declarations` property on scope nodes and fixes the crappy regenerator bug where it was creating a new `BlockStatement` so the declarations were being lost.
|
||||
* Rework transformer traversal optimisation. Turns out that calling a `check` function for **every single node** in the AST is ridiculously expensive. 300,000 nodes timesed by ~30 transformers meant that it took tens of seconds to perform while it's quicker to just do the unnecessary traversal. Seems obvious in hindsight.
|
||||
* **New Feature**
|
||||
* Add `jscript` transformer that turns named function expressions into function declarations to get around [JScript's horribly broken function expression semantics](https://kangax.github.io/nfe/#jscript-bugs). Thanks [@kondi](https://github.com/kondi)!
|
||||
* Add `@@hasInstance` support to objects when using the `es6.spec.symbols` transformer.
|
||||
* Add `retainLines` option that retains the line (but not the columns!) of the input code.
|
||||
|
||||
## 5.1.13
|
||||
|
||||
* **Polish**
|
||||
* Remove symbol check from `defineProperty` helper.
|
||||
|
||||
## 5.1.12
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix `resolveModuleSource` not being ran on `ExportAllDeclaration`s.
|
||||
* Fix `.babelrc` being resolved multiple times when using the require hook.
|
||||
* Fix parse error on spread properties in assignment position.
|
||||
* Fix `externalHelpers` option being incorrectly listed as type `string`.
|
||||
* **Internal**
|
||||
* Upgrade `core-js` to `0.9.0`.
|
||||
* **Spec Compliancy**
|
||||
* Fix object decorators not using the `initializer` pattern.
|
||||
* Remove property initializer descriptor reflection.
|
||||
|
||||
## 5.1.11
|
||||
|
||||
* **Bug Fix**
|
||||
* Memoise and bind member expression decorators.
|
||||
* Move JSX children cleaning to opening element visitor. Fixes elements not being cleaned in certain scenarios.
|
||||
* Consider `SwitchStatement`s to be `Scopable`.
|
||||
* Fix `bluebirdCoroutines` calling `interopRequireWildcard` before it's defined.
|
||||
* Add space to `do...while` code generation.
|
||||
* Validate `super` use before `this` on `super` exit rather than entrance.
|
||||
* **Polish**
|
||||
* Add Babel name to logger.
|
||||
|
||||
## 5.1.10
|
||||
|
||||
* **Bug Fix**
|
||||
* Remove `makePredicate` from acorn in favor of an `indexOf`.
|
||||
* Remove statements to expression explosion when inserting a block statement.
|
||||
* **Internal**
|
||||
* Remove runtime compatibility check.
|
||||
|
||||
## 5.1.9
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix class property initializers with `undefined` values not being correctly writable.
|
||||
* Fix self inferring generators incorrectly causing a stack error.
|
||||
* Fix default export specifiers not triggering AMD `module` argument inclusion.
|
||||
* Fix assignments not having their module references properly remapped.
|
||||
* **Internal**
|
||||
* Upgrade to latest `acorn`.
|
||||
* **Polish**
|
||||
* Make invalid LHS pattern error messages nicer.
|
||||
|
||||
## 5.1.8
|
||||
|
||||
* **Bug Fix**
|
||||
* Only make parenthesized object pattern LHS illegal.
|
||||
|
||||
## 5.1.7
|
||||
|
||||
* **Internal**
|
||||
* Add `parse` node API.
|
||||
|
||||
## 5.1.6
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix `runtime` built-in catchall not properly checking for local variables.
|
||||
|
||||
## 5.1.5
|
||||
|
||||
* **Internal**
|
||||
* Bump `core-js` version.
|
||||
|
||||
## 5.1.4
|
||||
|
||||
* **Polish**
|
||||
* Add missing `Reflect` methods to runtime transformer.
|
||||
|
||||
## 5.1.3
|
||||
|
||||
* **Internal**
|
||||
* Switch entirely to vanilla regenerator.
|
||||
* Clean up and make the parsing of decorators stateless.
|
||||
* **Bug Fix**
|
||||
* Don't do TCO on generators and async functions.
|
||||
* Add missing `core-js` runtime definitions.
|
||||
|
||||
## 5.1.2
|
||||
|
||||
* **Bug Fix**
|
||||
* Add `getIterator` and `isIterable` to `babel-runtime` build script.
|
||||
|
||||
## 5.1.1
|
||||
|
||||
* **Bug Fix**
|
||||
* Add missing runtime symbol definitions.
|
||||
|
||||
## 5.1.0
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix super reference when using decorators.
|
||||
* Don't do array unpack optimisation when member expressions are present.
|
||||
* Add missing descriptors for undecorated class properties.
|
||||
* Don't consider `arguments` and `eval` valid function names when doing function name inferrence.
|
||||
* Fix scope tracking of constants in loop heads.
|
||||
* Parse `AwaitExpression` as a unary instead of an assignment.
|
||||
* Fix regex evaluation when attempting static evaluation.
|
||||
* Don't emit tokens when doing a lookahead.
|
||||
* Add missing `test` declaration to `utility.deadCodeElimination` transformer.
|
||||
* **Internal**
|
||||
* Upgrade `regenerator` to the latest and use my branch with the hope of eventually switching to vanilla regenerator.
|
||||
* Add support for the replacement of for loop `init`s with statements.
|
||||
* Upgrade dependencies.
|
||||
* **Polish**
|
||||
* When adding the scope IIFE when using default parameters, don't shadow the function expression, just `apply` `this` and `arguments` if necessary.
|
||||
* Use path basename as non-default import fallback.
|
||||
* **New Feature**
|
||||
* Add [trailing function comma proposal](https://github.com/jeffmo/es-trailing-function-commas). Thanks [@AluisioASG](https://github.com/AluisioASG)!
|
||||
* Add support for object literal decorators.
|
||||
* Make core-js modular when using the `runtime` transformer.
|
||||
|
||||
## 5.0.12
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix incorrect remapping of module references inside of a function id redirection container.
|
||||
|
||||
## 5.0.11
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix new `for...of` loops not properly inheriting their original loop.
|
||||
* **Internal**
|
||||
* Disable scope instance cache.
|
||||
* **Polish**
|
||||
* Allow comments in `.babelrc` JSON.
|
||||
|
||||
## 5.0.9
|
||||
|
||||
* **Polish**
|
||||
* Use `moduleId` for UMD global name if available.
|
||||
* **Bug Fix**
|
||||
* Fix UMD global `module` variable shadowing the `amd`/`common` `module` variable.
|
||||
* Fix Flow param type annotation regression.
|
||||
* Fix function name collision `toString` wrapper. Thanks [@alawatthe](https://github.com/alawatthe)!
|
||||
|
||||
## 5.0.8
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix falsy static class properties not being writable.
|
||||
* Fix block scoping collisions not properly detecting modules and function clashes.
|
||||
* Skip `this` before `super` for derived constructors on functions.
|
||||
|
||||
## 5.0.7
|
||||
|
||||
* **New Feature**
|
||||
* Add `--ignore` and `--only` support to the CLI.
|
||||
* **Bug Fix**
|
||||
* Remove `HOMEPATH` environment variable from home resolution in `babel/register` cache.
|
||||
* **Internal**
|
||||
* Disable WIP path resolution introducing infinite recursion in some code examples.
|
||||
* **Polish**
|
||||
* Add live binding to CommonJS default imports.
|
||||
|
||||
## 5.0.6
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix mangling of import references that collide with properties on `Object.prototype`.
|
||||
* Fix duplicate declarations incorrectly being reported for `var`.
|
||||
|
||||
## 5.0.5
|
||||
|
||||
* **Internal**
|
||||
* Upgrade `core-js`.
|
||||
* **Bug Fix**
|
||||
* Fix arrays not being supported in `util.list`.
|
||||
|
||||
## 5.0.4
|
||||
|
||||
* **Polish**
|
||||
* Check for top level `breakConfig` in `resolveRc`.
|
||||
|
||||
## 5.0.3
|
||||
|
||||
* **Bug Fix**
|
||||
* Make relative location absolute before calling `resolveRc`.
|
||||
* **Internal**
|
||||
* Switch to global UID registry.
|
||||
* Add `breakConfig` option to prevent Babel from erroring when hitting that option.
|
||||
|
||||
## 5.0.1
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix duplicate declaration regression.
|
||||
* Fix not being able to call non-writable methods.
|
||||
|
||||
## 5.0.0
|
||||
|
||||
* **New Feature**
|
||||
* Decorators based on [@wycat's](https://github.com/wycats) [stage 1 proposal](https://github.com/wycats/javascript-decorators).
|
||||
* Class property initializers based on [@jeffmo's](https://github.com/jeffmo) [stage 0 proposal](https://gist.github.com/jeffmo/054df782c05639da2adb).
|
||||
* Export extensions based on [@leebyron's](https://github.com/leebyron) [stage 1 proposal](https://github.com/leebyron/ecmascript-more-export-from).
|
||||
* UMD module formatter now supports globals.
|
||||
* Add `es3.runtime`, `optimisation.react.inlineElements` and `optimisation.react.constantElements` transformers.
|
||||
* Add stage option that replaces the experimental one.
|
||||
* Allow ES7 transformer to be enabled via `optional` instead of only via `stage`.
|
||||
* Infer string quotes to use in the code generator.
|
||||
* Consider `export { foo as default };` to be the same as `export default foo;`.
|
||||
* Add `nonStandard` option that can be set to `false` to remove parser support for JSX and Flow.
|
||||
* Add `jsxPragma` option.
|
||||
* Automatically generate CLI options based on internal API options.
|
||||
* Add support for `.babelrc` on absolute paths.
|
||||
* Plugin API!
|
||||
* **Internal**
|
||||
* Export `options` in browser API.
|
||||
* Rewritten parser.
|
||||
* Don't block hoist when runtime transformer is enabled in system module formatter.
|
||||
* Rewritten the internal traversal and node replacement API to use "paths" that abstracts out node relationships.
|
||||
* **Polish**
|
||||
* JSX output is now more inline with the official JSX transformer.
|
||||
* Hoist block scoping IIFE - this improves memory usage and performance.
|
||||
* Better IIFE detection - references are now checked to see if they're referencing the binding we're searching for.
|
||||
* Check for import reassignments in constants transformer.
|
||||
* Make method definitions with expression bodies illegal.
|
||||
* Save register cache on tick instead of `SIGINT`.
|
||||
* Enable strict mode on babel-node eval flag.
|
||||
* **Bug Fixes**
|
||||
* Add support for live bindings. This change also increases the reliablity of export specifier renaming.
|
||||
* Add support for super update and non equals assignment expressions.
|
||||
* Rename shadow constructor binding in classes.
|
||||
* Seed next iteration bindings with previous fresh bindings when reassinging loop block scoped variables.
|
||||
* Fix new expression spread referencing the wrong constructor.
|
||||
* Call `resolveModuleSource` on dynamic imports.
|
||||
* Added `param` to list of duplicate declaration kinds.
|
||||
* **Breaking Changes**
|
||||
* The Babel playground has been removed.
|
||||
* ES7 Abstract References have been removed.
|
||||
* Experimental option has been removed in favor of a stage option.
|
||||
* Rename `returnUsedHelpers` to `metadataUsedHelpers`.
|
||||
|
||||
## 4.7.16
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix constructor spreading of typed arrays.
|
||||
* Fix break/continue/return aliasing of non-loops in block scoping transformer.
|
||||
|
||||
## 4.7.15
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix constructor spreading of collections.
|
||||
|
||||
## 4.7.14
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix constructor spreading of `Promise`.
|
||||
* **Internal**
|
||||
* Deprecate remaining playground transformers and abstract references.
|
||||
|
||||
## 4.7.13
|
||||
|
||||
* **Bug Fix**
|
||||
* Handle comments on use strict directives.
|
||||
* Fix assignment patterns with a left side pattern.
|
||||
* **Polish**
|
||||
* Special case `this` when doing expression memoisation.
|
||||
|
||||
## 4.7.12
|
||||
|
||||
* **Bug Fix**
|
||||
* Deprecate `playground.methodBinding`.
|
||||
|
||||
## 4.7.11
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix unicode regexes stripping their unicode flag before being passed on two `regexpu`.
|
||||
|
||||
## 4.7.10
|
||||
|
||||
* **Internal**
|
||||
* Deprecate `playground.methodBinding` and `playground.objectGetterMemoization`.
|
||||
* **Bug Fix**
|
||||
* Fix `inputSourceMap` option. Thanks [@Rich-Harris](https://github.com/Rich-Harris)!
|
||||
|
||||
## 4.7.9
|
||||
|
||||
* **Polish**
|
||||
* Allow `inputSourceMap` to be set to `false` to skip the source map inference.
|
||||
* Infer computed literal property names.
|
||||
* **Bug Fix**
|
||||
* Fix nested labeled for-ofs.
|
||||
* Fix block scoping `break` colliding with the parent switch case.
|
||||
* **Internal**
|
||||
* Upgrade `acorn-babel`.
|
||||
|
||||
## 4.7.8
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix computed classes not properly setting symbols.
|
||||
|
||||
## 4.7.7
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix `types` API exposure.
|
||||
|
||||
## 4.7.6
|
||||
|
||||
* **Bug Fix**
|
||||
* Fix non-Identifier/Literal computed class methods.
|
||||
* **Polish**
|
||||
* Add a fallback if `stack` on an error is unconfigurable.
|
||||
* Hoist `esModule` module declarations to the top of the file to handle circular dependencies better.
|
||||
|
||||
## 4.7.5
|
||||
|
||||
* **Bug Fix**
|
||||
* Don't remap` break`s to call the iterator return.
|
||||
* **Polish**
|
||||
* Use a different helper for computed classes for much nicer output. Also fixes a bug in symbols being non-enumerable so they wouldn't be set on the class.
|
||||
|
||||
## 4.7.4
|
||||
|
||||
* **Bug Fix**
|
||||
* Rewrite named function expressions in optional async function transformers.
|
||||
* Hoist directives.
|
||||
* Remove `Number` from the list of valid `runtime` constructors.
|
||||
* **Internal**
|
||||
* `spec.typeofSymbol` transformer has been renamed to `es6.symbols`.
|
||||
|
||||
## 4.7.2
|
||||
|
||||
* **New Feature**
|
||||
|
||||
108
CONTRIBUTING.md
108
CONTRIBUTING.md
@@ -1,9 +1,24 @@
|
||||
<p align="center">
|
||||
<strong><a href="#setup">Setup</a></strong>
|
||||
|
|
||||
<strong><a href="#running-tests">Running tests</a></strong>
|
||||
|
|
||||
<strong><a href="#workflow">Workflow</a></strong>
|
||||
|
|
||||
<strong><a href="#dependencies">Dependencies</a></strong>
|
||||
|
|
||||
<strong><a href="#code-standards">Code Standards</a></strong>
|
||||
</p>
|
||||
|
||||
----
|
||||
|
||||
# Contributing
|
||||
|
||||
Contributions are always welcome, no matter how large or small. Before
|
||||
contributing, please read the
|
||||
[code of conduct](https://github.com/babel/babel/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
|
||||
## Developing
|
||||
|
||||
#### Setup
|
||||
@@ -14,14 +29,19 @@ $ cd babel
|
||||
$ make bootstrap
|
||||
```
|
||||
|
||||
Then you need to run:
|
||||
Then you can either run:
|
||||
|
||||
```sh
|
||||
$ make build-core
|
||||
```
|
||||
|
||||
to build Babel **once** or:
|
||||
|
||||
```sh
|
||||
$ make watch-core
|
||||
```
|
||||
|
||||
This will compile babel and then sit in the background and on file modification
|
||||
recompile the necessary files.
|
||||
to have Babel build itself then incrementally build files on change.
|
||||
|
||||
#### Running tests
|
||||
|
||||
@@ -31,15 +51,24 @@ You can run tests via:
|
||||
$ make test
|
||||
```
|
||||
|
||||
This will usually take around two minutes as it's compiling the entire
|
||||
[test262](https://github.com/tc39/test262) test suite and validating it's AST.
|
||||
This is mostly overkill and you can limit the tests to a select few by directly
|
||||
running them with `mocha`:
|
||||
|
||||
```sh
|
||||
$ mocha test/transformation.js
|
||||
$ mocha test/core/transformation.js
|
||||
```
|
||||
|
||||
Use mocha's `--grep` option to run a subset of tests by name:
|
||||
|
||||
```sh
|
||||
$ mocha test/core/transformation.js --grep es7
|
||||
```
|
||||
|
||||
If you don't have `mocha` installed globally, you can still use it from Babel's
|
||||
dependencies in `node_modules`, but make sure `node_modules/.bin` is added to
|
||||
your [`$PATH`](http://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path) environment variable.
|
||||
|
||||
|
||||
#### Workflow
|
||||
|
||||
* Fork the repository
|
||||
@@ -50,24 +79,91 @@ $ mocha test/transformation.js
|
||||
* Ensure the test are passing (`make test`)
|
||||
* Create new pull request explaining your proposed change or reference an issue in your commit message
|
||||
|
||||
|
||||
#### Dependencies
|
||||
|
||||
+ [ast-types](http://ghub.io/ast-types) This is required to monkeypatch regenerators AST definitions. Could be improved in the future.
|
||||
|
||||
+ [chalk](http://ghub.io/chalk) This is used for terminal color highlighting for syntax errors.
|
||||
|
||||
+ [convert-source-map](http://ghub.io/convert-source-map) Turns a source map object into a comment etc.
|
||||
|
||||
+ [core-js](http://ghub.io/core-js) Used for the polyfill.
|
||||
|
||||
+ [debug](http://ghub.io/debug) Used to output debugging information when NODE_DEBUG is set to babel.
|
||||
|
||||
+ [detect-indent](http://ghub.io/detect-indent) This is used in the code generator so it can infer indentation.
|
||||
|
||||
+ [estraverse](http://ghub.io/estraverse) The only method on this is attachComments. I'd like to implement our own comment attachment algorithm eventually though.
|
||||
|
||||
+ [esutils](http://ghub.io/esutils) Various ES related utilities. Check whether something is a keyword etc.
|
||||
|
||||
+ [fs-readdir-recursive](http://ghub.io/fs-readdir-recursive) Recursively search a directory for.
|
||||
|
||||
+ [globals](http://ghub.io/globals) A list of JavaScript global variables. This is used by the scope tracking to check for colliding variables.
|
||||
|
||||
+ [is-integer](http://ghub.io/is-integer) Checks if something is an integer.
|
||||
|
||||
+ [js-tokens](http://ghub.io/js-tokens) This is used to get tokens for syntax error highlighting.
|
||||
|
||||
+ [leven](http://ghub.io/leven) A levenstein algorithm to determine how close a word is to another. This is used to offer suggestions when using the utility.undeclaredVariableCheck transformer.
|
||||
|
||||
+ [line-numbers](http://ghub.io/line-numbers) Used to produce the code frames in syntax errors.
|
||||
|
||||
+ [lodash](http://ghub.io/lodash) Used for various utilities.
|
||||
|
||||
+ [minimatch](http://ghub.io/minimatch) This is used to match glob-style ignore/only filters.
|
||||
|
||||
+ [output-file-sync](http://ghub.io/output-file-sync) Synchronously writes a file and create its ancestor directories if needed.
|
||||
|
||||
+ [path-is-absolute](http://ghub.io/path-is-absolute) Checks if a path is absolute. C:\foo and \foo are considered absolute.
|
||||
|
||||
+ [regenerator](http://ghub.io/regenerator) This is used to transform generators/async functions.
|
||||
|
||||
+ [regexpu](http://ghub.io/regexpu) Used to transform unicode regex patterns.
|
||||
|
||||
+ [repeating](http://ghub.io/repeating) Repeats a string.
|
||||
|
||||
+ [shebang-regex](http://ghub.io/shebang-regex) Literally just a regex that matches shebangs.
|
||||
|
||||
+ [slash](http://ghub.io/slash) Normalises path separators.
|
||||
|
||||
+ [source-map](http://ghub.io/source-map) Generates sourcemaps.
|
||||
|
||||
+ [source-map-support](http://ghub.io/source-map-support) Adds source map support to babel-node/babel/register.
|
||||
|
||||
+ [strip-json-comments](http://ghub.io/strip-json-comments) Remove comments from a JSON string. This is used for .babelrc files.
|
||||
|
||||
+ [to-fast-properties](http://ghub.io/to-fast-properties) A V8 trick to put an object into fast properties mode.
|
||||
|
||||
+ [trim-right](http://ghub.io/trim-right) Trims the rightside whitespace.
|
||||
|
||||
+ [user-home](http://ghub.io/user-home) Gets the users home directory. This is used to resolve the babel-node/babel/register cache.
|
||||
|
||||
|
||||
#### Code Standards
|
||||
|
||||
* **General**
|
||||
* Max of five arguments for functions
|
||||
* Max depth of four nested blocks
|
||||
* 2-spaced soft tabs
|
||||
|
||||
* **Naming**
|
||||
* CamelCase all class names
|
||||
* camelBack all variable names
|
||||
|
||||
* **Spacing**
|
||||
* Spaces after all keywords
|
||||
* Spaces before all left curly braces
|
||||
|
||||
* **Comments**
|
||||
* Use JSDoc-style comments for methods
|
||||
* Single-line comments for ambiguous code
|
||||
|
||||
* **Quotes**
|
||||
* Always use double quotes
|
||||
* Only use single quotes when the string contains a double quote
|
||||
|
||||
* **Declaration**
|
||||
* No unused variables
|
||||
* No pollution of global variables and prototypes
|
||||
|
||||
60
Makefile
60
Makefile
@@ -1,3 +1,4 @@
|
||||
MAKEFLAGS = -j1
|
||||
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
|
||||
@@ -8,14 +9,20 @@ BABEL_CMD = node_modules/babel/bin/babel
|
||||
|
||||
export NODE_ENV = test
|
||||
|
||||
.PHONY: clean test test-cov test-clean test-travis test-simple test-all test-browser publish build bootstrap publish-core publish-runtime build-core watch-core
|
||||
.PHONY: clean test test-cov test-clean test-travis test-simple test-all test-browser test-parser publish build bootstrap publish-core publish-runtime build-core watch-core build-core-test clean-core
|
||||
|
||||
build-core:
|
||||
build-core: clean-core
|
||||
node $(BABEL_CMD) src --out-dir lib --copy-files
|
||||
|
||||
watch-core:
|
||||
build-core-test: clean-core
|
||||
node $(BABEL_CMD) src --out-dir lib --copy-files --auxiliary-comment "istanbul ignore next"
|
||||
|
||||
watch-core: clean-core
|
||||
node $(BABEL_CMD) src --out-dir lib --watch --copy-files
|
||||
|
||||
clean-core:
|
||||
rm -rf lib
|
||||
|
||||
build:
|
||||
mkdir -p dist
|
||||
make build-core
|
||||
@@ -28,45 +35,41 @@ build:
|
||||
node $(BROWSERIFY_CMD) lib/babel/api/browser.js -s babel >dist/babel.js
|
||||
node $(UGLIFY_CMD) dist/babel.js >dist/babel.min.js
|
||||
|
||||
node bin/babel-external-helpers >dist/external-helpers.js
|
||||
node packages/babel-cli/bin/babel-external-helpers >dist/external-helpers.js
|
||||
node $(UGLIFY_CMD) dist/external-helpers.js >dist/external-helpers.min.js
|
||||
|
||||
rm -rf templates.json
|
||||
|
||||
clean:
|
||||
rm -rf coverage templates.json test/tmp dist
|
||||
rm -rf coverage templates.json test/tmp dist lib
|
||||
|
||||
test-clean:
|
||||
rm -rf test/tmp
|
||||
|
||||
test:
|
||||
$(MOCHA_CMD)
|
||||
test: test-parser
|
||||
node $(MOCHA_CMD) test/core
|
||||
make test-clean
|
||||
|
||||
test-simple:
|
||||
# excludes test262
|
||||
export SIMPLE_BABEL_TESTS=1; \
|
||||
make test
|
||||
|
||||
test-all:
|
||||
export ALL_BABEL_TESTS=1; \
|
||||
make test
|
||||
|
||||
test-cov:
|
||||
rm -rf coverage
|
||||
export SIMPLE_BABEL_TESTS=1; \
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
|
||||
make build-core-test
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) -- test/core
|
||||
|
||||
test-travis: bootstrap build
|
||||
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
|
||||
if test -n "$$CODECLIMATE_REPO_TOKEN"; then codeclimate < coverage/lcov.info; fi
|
||||
test-parser:
|
||||
node test/acorn/run.js
|
||||
|
||||
test-travis: bootstrap build test
|
||||
|
||||
test-browser:
|
||||
mkdir -p dist
|
||||
|
||||
node tools/cache-templates
|
||||
node tools/cache-tests
|
||||
node $(BROWSERIFY_CMD) -e test/_browser.js >dist/babel-test.js
|
||||
node tools/build-tests
|
||||
node $(BROWSERIFY_CMD) -e test/core/_browser.js >dist/babel-test.js
|
||||
rm -rf templates.json tests.json
|
||||
|
||||
test -n "`which open`" && open test/browser.html
|
||||
@@ -91,7 +94,7 @@ publish:
|
||||
|
||||
git push --follow-tags
|
||||
|
||||
make publish-core
|
||||
make publish-cli
|
||||
make publish-runtime
|
||||
|
||||
rm -rf templates.json browser.js browser-polyfill.js external-helpers.js
|
||||
@@ -102,18 +105,17 @@ publish-runtime:
|
||||
cd babel-runtime; \
|
||||
npm publish
|
||||
|
||||
publish-core:
|
||||
tools/generate-core-package-json >package2.json
|
||||
mv package.json .package.json
|
||||
mv package2.json package.json
|
||||
|
||||
publish-cli:
|
||||
cd packages; \
|
||||
node build-cli.js; \
|
||||
cd babel-cli; \
|
||||
npm publish
|
||||
|
||||
rm -rf package.json
|
||||
mv .package.json package.json
|
||||
|
||||
bootstrap:
|
||||
npm list --global --depth 1 babel >/dev/null 2>&1 && npm uninstall -g babel || true
|
||||
npm install
|
||||
npm link
|
||||
cd packages/babel-cli && npm install && npm link && npm link babel-core
|
||||
git submodule update --init
|
||||
cd vendor/regenerator && npm install
|
||||
cd vendor/compat-table && npm install object-assign
|
||||
make build
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<strong>Babel</strong> is a transpiler for writing next generation JavaScript.
|
||||
<strong>Babel</strong> is a compiler for writing next generation JavaScript.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
For questions and support please visit the <a href="https://gitter.im/babel/babel">gitter room</a> before creating an issue.
|
||||
For questions and support please visit the <a href="https://gitter.im/babel/babel">gitter room</a> or <a href="http://stackoverflow.com/questions/tagged/babeljs">StackOverflow</a>. The Babel issue tracker is <strong>exclusively</strong> for bug reports and feature requests.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* This tiny wrapper file checks for known node flags and appends them
|
||||
* when found, before invoking the "real" _babel-node(1) executable.
|
||||
*/
|
||||
|
||||
var args = [__dirname + "/_babel-node"];
|
||||
|
||||
var babelArgs = process.argv.slice(2);
|
||||
var userArgs;
|
||||
|
||||
// separate node arguments from script arguments
|
||||
var argSeparator = babelArgs.indexOf("--");
|
||||
if (argSeparator > -1) {
|
||||
userArgs = babelArgs.slice(argSeparator); // including the --
|
||||
babelArgs = babelArgs.slice(0, argSeparator);
|
||||
}
|
||||
|
||||
babelArgs.forEach(function(arg){
|
||||
var flag = arg.split("=")[0];
|
||||
|
||||
switch (flag) {
|
||||
case "-d":
|
||||
args.unshift("--debug");
|
||||
break;
|
||||
|
||||
case "debug":
|
||||
case "--debug":
|
||||
case "--debug-brk":
|
||||
args.unshift(arg);
|
||||
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":
|
||||
case "--use-strict":
|
||||
args.unshift(arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (arg.indexOf("--trace") === 0) {
|
||||
args.unshift(arg);
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// append arguments passed after --
|
||||
if (argSeparator > -1) {
|
||||
args = args.concat(userArgs);
|
||||
}
|
||||
|
||||
try {
|
||||
var kexec = require("kexec");
|
||||
kexec(process.argv[0], args);
|
||||
} catch (err) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
|
||||
var child_process = require("child_process");
|
||||
var proc = child_process.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);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var commander = require("commander");
|
||||
var transform = require("../../lib/babel/transformation");
|
||||
var util = require("../../lib/babel/util");
|
||||
var fs = require("fs");
|
||||
var each = require("lodash/collection/each");
|
||||
var keys = require("lodash/object/keys");
|
||||
|
||||
commander.option("-t, --source-maps-inline", "Append sourceMappingURL comment to bottom of code");
|
||||
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, --external-helpers", "Replace helpers with references to a `babelHelpers` global");
|
||||
commander.option("-e, --experimental", "Enable experimental support for proposed ES7 features");
|
||||
commander.option("-p, --playground", "Enable playground support");
|
||||
|
||||
commander.option("-c, --compact [mode]", "When set to \"auto\" compact is `true` when the input size exceeds 100KB. (auto|true|false)", "auto");
|
||||
commander.option("-m, --modules [modules]", "Module formatter type to use [common]", "common");
|
||||
commander.option("-l, --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("-i, --optional [list]", "List of optional transformers to enable", util.list);
|
||||
commander.option("-L, --loose [list]", "List of transformers to enable loose mode ON", 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");
|
||||
commander.option("-c, --remove-comments", "Remove comments from the compiled code", false);
|
||||
commander.option("-M, --module-ids", "Insert module id in modules", false);
|
||||
commander.option("-R, --react-compat", "Makes the react transformer produce pre-v0.12 code");
|
||||
commander.option("--keep-module-id-extensions", "Keep extensions when generating module ids", false);
|
||||
commander.option("-a, --auxiliary-comment [comment]", "Comment text to prepend to all auxiliary code");
|
||||
commander.option("-D, --copy-files", "When compiling a directory copy over non-compilable files");
|
||||
|
||||
commander.on("--help", function () {
|
||||
var outKeys = function (title, obj) {
|
||||
console.log(" " + title + ":");
|
||||
console.log();
|
||||
|
||||
each(keys(obj).sort(), function (key) {
|
||||
if (key[0] === "_") return;
|
||||
|
||||
if (obj[key].optional) {
|
||||
key = "[" + key + "]";
|
||||
}
|
||||
|
||||
console.log(" - " + key);
|
||||
});
|
||||
|
||||
console.log();
|
||||
};
|
||||
|
||||
outKeys("Transformers", transform.transformers);
|
||||
outKeys("Module formatters", transform.moduleFormatters);
|
||||
});
|
||||
|
||||
var pkg = require("../../package.json");
|
||||
commander.version(pkg.version);
|
||||
commander.usage("[options] <files ...>");
|
||||
commander.parse(process.argv);
|
||||
|
||||
//
|
||||
|
||||
var errors = [];
|
||||
|
||||
var filenames = commander.args;
|
||||
|
||||
each(filenames, function (filename) {
|
||||
if (!fs.existsSync(filename)) {
|
||||
errors.push(filename + " doesn't exist");
|
||||
}
|
||||
});
|
||||
|
||||
if (commander.outDir && !filenames.length) {
|
||||
errors.push("filenames required for --out-dir");
|
||||
}
|
||||
|
||||
if (commander.outFile && commander.outDir) {
|
||||
errors.push("cannot have --out-file and --out-dir");
|
||||
}
|
||||
|
||||
if (commander.watch) {
|
||||
if (!commander.outFile && !commander.outDir) {
|
||||
errors.push("--watch requires --out-file or --out-dir");
|
||||
}
|
||||
|
||||
if (!filenames.length) {
|
||||
errors.push("--watch requires filenames");
|
||||
}
|
||||
}
|
||||
|
||||
if (commander.sourceMaps) {
|
||||
if (!commander.outFile && !commander.outDir) {
|
||||
errors.push("--source-maps requires --out-file or --out-dir");
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
console.error(errors.join(". "));
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
exports.opts = {
|
||||
keepModuleIdExtensions: commander.keepModuleIdExtensions,
|
||||
auxiliaryComment: commander.auxiliaryComment,
|
||||
externalHelpers: commander.externalHelpers,
|
||||
sourceMapName: commander.outFile,
|
||||
experimental: commander.experimental,
|
||||
reactCompat: commander.reactCompat,
|
||||
playground: commander.playground,
|
||||
moduleIds: commander.moduleIds,
|
||||
blacklist: commander.blacklist,
|
||||
whitelist: commander.whitelist,
|
||||
sourceMap: commander.sourceMaps || commander.sourceMapsInline,
|
||||
optional: commander.optional,
|
||||
comments: !commander.removeComments,
|
||||
modules: commander.modules,
|
||||
compact: commander.compact,
|
||||
loose: commander.loose
|
||||
};
|
||||
|
||||
var fn;
|
||||
|
||||
if (commander.outDir) {
|
||||
fn = require("./dir");
|
||||
} else {
|
||||
fn = require("./file");
|
||||
}
|
||||
|
||||
fn(commander, filenames, exports.opts);
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
console.error("`6to5` has been renamed to `babel`");
|
||||
require("../babel");
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
console.error("`6to5-node` has been renamed to `babel-node`");
|
||||
require("../_babel-node");
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
console.error("`6to5-runtime` has been renamed to `babel-external-helpers`");
|
||||
require("../babel-external-helpers");
|
||||
53
package.json
53
package.json
@@ -1,23 +1,14 @@
|
||||
{
|
||||
"name": "babel",
|
||||
"name": "babel-core",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "4.7.2",
|
||||
"version": "5.2.5",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
"repository": "babel/babel",
|
||||
"preferGlobal": true,
|
||||
"main": "lib/babel/api/node.js",
|
||||
"browser": {
|
||||
"./lib/babel/api/register/node.js": "./lib/babel/api/register/browser.js"
|
||||
},
|
||||
"bin": {
|
||||
"6to5": "./bin/deprecated/6to5",
|
||||
"6to5-node": "./bin/deprecated/6to5-node",
|
||||
"6to5-runtime": "./bin/deprecated/6to5-runtime",
|
||||
"babel": "./bin/babel/index.js",
|
||||
"babel-node": "./bin/babel-node",
|
||||
"babel-external-helpers": "./bin/babel-external-helpers"
|
||||
},
|
||||
"keywords": [
|
||||
"harmony",
|
||||
"classes",
|
||||
@@ -36,48 +27,50 @@
|
||||
"test": "make test"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn-babel": "0.11.1-37",
|
||||
"ast-types": "~0.7.0",
|
||||
"bluebird": "^2.9.25",
|
||||
"chalk": "^1.0.0",
|
||||
"chokidar": "^0.12.6",
|
||||
"commander": "^2.6.0",
|
||||
"convert-source-map": "^0.5.0",
|
||||
"core-js": "^0.6.1",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"core-js": "^0.9.0",
|
||||
"debug": "^2.1.1",
|
||||
"detect-indent": "^3.0.0",
|
||||
"estraverse": "^1.9.1",
|
||||
"esutils": "^1.1.6",
|
||||
"estraverse": "^3.0.0",
|
||||
"esutils": "^2.0.0",
|
||||
"fs-readdir-recursive": "^0.1.0",
|
||||
"globals": "^6.2.0",
|
||||
"globals": "^6.4.0",
|
||||
"is-integer": "^1.0.4",
|
||||
"js-tokens": "1.0.0",
|
||||
"leven": "^1.0.1",
|
||||
"line-numbers": "0.2.0",
|
||||
"lodash": "^3.2.0",
|
||||
"lodash": "^3.6.0",
|
||||
"minimatch": "^2.0.3",
|
||||
"output-file-sync": "^1.1.0",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"private": "^0.1.6",
|
||||
"regenerator-babel": "0.8.13-2",
|
||||
"regenerator": "^0.8.20",
|
||||
"regexpu": "^1.1.2",
|
||||
"repeating": "^1.1.2",
|
||||
"resolve": "^1.1.6",
|
||||
"shebang-regex": "^1.0.0",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.4.0",
|
||||
"source-map-support": "^0.2.9",
|
||||
"source-map-support": "^0.2.10",
|
||||
"strip-json-comments": "^1.0.2",
|
||||
"to-fast-properties": "^1.0.0",
|
||||
"trim-right": "^1.0.0"
|
||||
"trim-right": "^1.0.0",
|
||||
"user-home": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "4.6.0",
|
||||
"browserify": "^9.0.3",
|
||||
"chai": "^2.0.0",
|
||||
"eslint": "^0.15.1",
|
||||
"babel-eslint": "^1.0.1",
|
||||
"babel": "5.1.13",
|
||||
"browserify": "^9.0.8",
|
||||
"chai": "^2.2.0",
|
||||
"eslint": "^0.18.0",
|
||||
"babel-eslint": "^2.0.0",
|
||||
"esvalid": "^1.1.0",
|
||||
"istanbul": "^0.3.5",
|
||||
"matcha": "^0.6.0",
|
||||
"mocha": "^2.1.0",
|
||||
"rimraf": "^2.2.8",
|
||||
"mocha": "2.2.0",
|
||||
"rimraf": "^2.3.2",
|
||||
"uglify-js": "^2.4.16"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# What is this?
|
||||
|
||||
This is a folder containing additional packages that are built whenever
|
||||
a new version of babel is released.
|
||||
|
||||
**TODO:** Move `babel-core` into here.
|
||||
5
packages/babel-cli/README.md
Normal file
5
packages/babel-cli/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# babel-cli
|
||||
|
||||
Babel CLI
|
||||
|
||||
For more information please look at [babel](https://github.com/babel/babel).
|
||||
@@ -3,10 +3,11 @@
|
||||
var pathIsAbsolute = require("path-is-absolute");
|
||||
var commander = require("commander");
|
||||
var Module = require("module");
|
||||
var babel = require("../lib/babel/api/node");
|
||||
var babel = require("babel-core");
|
||||
var inspect = require("util").inspect;
|
||||
var path = require("path");
|
||||
var repl = require("repl");
|
||||
var util = require("../lib/babel/util");
|
||||
var util = require("babel-core").util;
|
||||
var vm = require("vm");
|
||||
var _ = require("lodash");
|
||||
|
||||
@@ -16,8 +17,7 @@ program.option("-e, --eval [script]", "Evaluate script");
|
||||
program.option("-p, --print [code]", "Evaluate script and print result");
|
||||
program.option("-i, --ignore [regex]", "Ignore all files that match this regex when using the require hook");
|
||||
program.option("-x, --extensions [extensions]", "List of extensions to hook into [.es6,.js,.es,.jsx]");
|
||||
program.option("-r, --experimental", "Enable experimental support for proposed ES7 features");
|
||||
program.option("-g, --playground", "Enable playground support");
|
||||
program.option("-r, --stage [stage]", "Enable support for specific ECMAScript stages");
|
||||
program.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ONLY use", util.list);
|
||||
program.option("-b, --blacklist [blacklist]", "Blacklist of transformers to NOT use", util.list);
|
||||
program.option("-o, --optional [optional]", "List of optional transformers to enable", util.list);
|
||||
@@ -30,25 +30,25 @@ program.parse(process.argv);
|
||||
//
|
||||
|
||||
babel.register({
|
||||
experimental: program.experimental,
|
||||
extensions: program.extensions,
|
||||
playground: program.playground,
|
||||
blacklist: program.blacklist,
|
||||
whitelist: program.whitelist,
|
||||
optional: program.optional,
|
||||
ignore: program.ignore
|
||||
ignore: program.ignore,
|
||||
stage: program.stage,
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
var _eval = function (code, filename) {
|
||||
if (!code) return undefined;
|
||||
|
||||
code = babel.transform(code, {
|
||||
filename: filename,
|
||||
blacklist: ["useStrict"].concat(program.blacklist || []),
|
||||
blacklist: program.blacklist,
|
||||
whitelist: program.whitelist,
|
||||
optional: program.optional,
|
||||
experimental: program.experimental,
|
||||
playground: program.playground
|
||||
stage: program.stage
|
||||
}).code;
|
||||
|
||||
return vm.runInThisContext(code, {
|
||||
@@ -72,7 +72,10 @@ if (program.eval || program.print) {
|
||||
global.require = module.require.bind(module);
|
||||
|
||||
var result = _eval(code, global.__filename);
|
||||
if (program.print) console.log(result);
|
||||
if (program.print) {
|
||||
var output = _.isString(result) ? result : inspect(result);
|
||||
process.stdout.write(output + "\n");
|
||||
}
|
||||
} else {
|
||||
if (program.args.length) {
|
||||
// slice all arguments up to the first filename since they're babel args that we handle
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var commander = require("commander");
|
||||
var util = require("../lib/babel/util");
|
||||
var runtime = require("../lib/babel/build-external-helpers");
|
||||
var util = require("babel-core").util;
|
||||
var runtime = require("babel-core").buildExternalHelpers;
|
||||
|
||||
commander.option("-l, --whitelist [whitelist]", "Whitelist of helpers to ONLY include", util.list);
|
||||
commander.option("-t, --output-type [type]", "Type of output (global|umd|var)", "global");
|
||||
448
packages/babel-cli/bin/babel-node
Executable file
448
packages/babel-cli/bin/babel-node
Executable file
@@ -0,0 +1,448 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* This tiny wrapper file checks for known node flags and appends them
|
||||
* when found, before invoking the "real" _babel-node(1) executable.
|
||||
*/
|
||||
|
||||
var args = [__dirname + "/_babel-node"];
|
||||
|
||||
var babelArgs = process.argv.slice(2);
|
||||
var userArgs;
|
||||
|
||||
// separate node arguments from script arguments
|
||||
var argSeparator = babelArgs.indexOf("--");
|
||||
if (argSeparator > -1) {
|
||||
userArgs = babelArgs.slice(argSeparator); // including the --
|
||||
babelArgs = babelArgs.slice(0, argSeparator);
|
||||
}
|
||||
|
||||
babelArgs.forEach(function(arg){
|
||||
var flag = arg.split("=")[0];
|
||||
|
||||
switch (flag) {
|
||||
case "-d":
|
||||
args.unshift("--debug");
|
||||
break;
|
||||
|
||||
case "debug":
|
||||
case "--debug":
|
||||
case "--debug-brk":
|
||||
args.unshift(arg);
|
||||
break;
|
||||
|
||||
case "-gc":
|
||||
case "--expose-gc":
|
||||
args.unshift("--expose-gc");
|
||||
break;
|
||||
|
||||
case "--use_strict":
|
||||
case "--es_staging":
|
||||
case "--harmony":
|
||||
case "--harmony_shipping":
|
||||
case "--harmony_modules":
|
||||
case "--harmony_arrays":
|
||||
case "--harmony_array_includes":
|
||||
case "--harmony_regexps":
|
||||
case "--harmony_arrow_functions":
|
||||
case "--harmony_proxies":
|
||||
case "--harmony_sloppy":
|
||||
case "--harmony_unicode":
|
||||
case "--harmony_tostring":
|
||||
case "--harmony_numeric_literals":
|
||||
case "--harmony_strings":
|
||||
case "--harmony_scoping":
|
||||
case "--harmony_classes":
|
||||
case "--harmony_object_literals":
|
||||
case "--harmony_templates":
|
||||
case "--compiled_keyed_generic_loads":
|
||||
case "--pretenuring_call_new":
|
||||
case "--allocation_site_pretenuring":
|
||||
case "--trace_pretenuring":
|
||||
case "--trace_pretenuring_statistics":
|
||||
case "--track_fields":
|
||||
case "--track_double_fields":
|
||||
case "--track_heap_object_fields":
|
||||
case "--track_computed_fields":
|
||||
case "--track_field_types":
|
||||
case "--smi_binop":
|
||||
case "--vector_ics":
|
||||
case "--optimize_for_size":
|
||||
case "--unbox_double_arrays":
|
||||
case "--string_slices":
|
||||
case "--crankshaft":
|
||||
case "--hydrogen_filter":
|
||||
case "--use_gvn":
|
||||
case "--gvn_iterations":
|
||||
case "--use_canonicalizing":
|
||||
case "--use_inlining":
|
||||
case "--use_escape_analysis":
|
||||
case "--use_allocation_folding":
|
||||
case "--use_local_allocation_folding":
|
||||
case "--use_write_barrier_elimination":
|
||||
case "--max_inlining_levels":
|
||||
case "--max_inlined_source_size":
|
||||
case "--max_inlined_nodes":
|
||||
case "--max_inlined_nodes_cumulative":
|
||||
case "--loop_invariant_code_motion":
|
||||
case "--fast_math":
|
||||
case "--collect_megamorphic_maps_from_stub_cache":
|
||||
case "--hydrogen_stats":
|
||||
case "--trace_check_elimination":
|
||||
case "--trace_hydrogen":
|
||||
case "--trace_hydrogen_filter":
|
||||
case "--trace_hydrogen_stubs":
|
||||
case "--trace_hydrogen_file":
|
||||
case "--trace_phase":
|
||||
case "--trace_inlining":
|
||||
case "--trace_load_elimination":
|
||||
case "--trace_store_elimination":
|
||||
case "--trace_alloc":
|
||||
case "--trace_all_uses":
|
||||
case "--trace_range":
|
||||
case "--trace_gvn":
|
||||
case "--trace_representation":
|
||||
case "--trace_removable_simulates":
|
||||
case "--trace_escape_analysis":
|
||||
case "--trace_allocation_folding":
|
||||
case "--trace_track_allocation_sites":
|
||||
case "--trace_migration":
|
||||
case "--trace_generalization":
|
||||
case "--stress_pointer_maps":
|
||||
case "--stress_environments":
|
||||
case "--deopt_every_n_times":
|
||||
case "--deopt_every_n_garbage_collections":
|
||||
case "--print_deopt_stress":
|
||||
case "--trap_on_deopt":
|
||||
case "--trap_on_stub_deopt":
|
||||
case "--deoptimize_uncommon_cases":
|
||||
case "--polymorphic_inlining":
|
||||
case "--use_osr":
|
||||
case "--array_bounds_checks_elimination":
|
||||
case "--trace_bce":
|
||||
case "--array_bounds_checks_hoisting":
|
||||
case "--array_index_dehoisting":
|
||||
case "--analyze_environment_liveness":
|
||||
case "--load_elimination":
|
||||
case "--check_elimination":
|
||||
case "--store_elimination":
|
||||
case "--dead_code_elimination":
|
||||
case "--fold_constants":
|
||||
case "--trace_dead_code_elimination":
|
||||
case "--unreachable_code_elimination":
|
||||
case "--trace_osr":
|
||||
case "--stress_runs":
|
||||
case "--lookup_sample_by_shared":
|
||||
case "--cache_optimized_code":
|
||||
case "--flush_optimized_code_cache":
|
||||
case "--inline_construct":
|
||||
case "--inline_arguments":
|
||||
case "--inline_accessors":
|
||||
case "--escape_analysis_iterations":
|
||||
case "--optimize_for_in":
|
||||
case "--concurrent_recompilation":
|
||||
case "--job_based_recompilation":
|
||||
case "--trace_concurrent_recompilation":
|
||||
case "--concurrent_recompilation_queue_length":
|
||||
case "--concurrent_recompilation_delay":
|
||||
case "--block_concurrent_recompilation":
|
||||
case "--concurrent_osr":
|
||||
case "--omit_map_checks_for_leaf_maps":
|
||||
case "--turbo_filter":
|
||||
case "--trace_turbo":
|
||||
case "--trace_turbo_graph":
|
||||
case "--trace_turbo_cfg_file":
|
||||
case "--trace_turbo_types":
|
||||
case "--trace_turbo_scheduler":
|
||||
case "--trace_turbo_reduction":
|
||||
case "--trace_turbo_jt":
|
||||
case "--turbo_asm":
|
||||
case "--turbo_verify":
|
||||
case "--turbo_stats":
|
||||
case "--turbo_types":
|
||||
case "--turbo_source_positions":
|
||||
case "--context_specialization":
|
||||
case "--turbo_deoptimization":
|
||||
case "--turbo_inlining":
|
||||
case "--turbo_inlining_intrinsics":
|
||||
case "--trace_turbo_inlining":
|
||||
case "--loop_assignment_analysis":
|
||||
case "--turbo_profiling":
|
||||
case "--turbo_reuse_spill_slots":
|
||||
case "--turbo_delay_ssa_decon":
|
||||
case "--turbo_move_optimization":
|
||||
case "--turbo_jt":
|
||||
case "--typed_array_max_size_in_heap":
|
||||
case "--frame_count":
|
||||
case "--interrupt_budget":
|
||||
case "--type_info_threshold":
|
||||
case "--generic_ic_threshold":
|
||||
case "--self_opt_count":
|
||||
case "--trace_opt_verbose":
|
||||
case "--debug_code":
|
||||
case "--code_comments":
|
||||
case "--enable_sse3":
|
||||
case "--enable_sse4_1":
|
||||
case "--enable_sahf":
|
||||
case "--enable_avx":
|
||||
case "--enable_fma3":
|
||||
case "--enable_vfp3":
|
||||
case "--enable_armv7":
|
||||
case "--enable_armv8":
|
||||
case "--enable_neon":
|
||||
case "--enable_sudiv":
|
||||
case "--enable_mls":
|
||||
case "--enable_movw_movt":
|
||||
case "--enable_unaligned_accesses":
|
||||
case "--enable_32dregs":
|
||||
case "--enable_vldr_imm":
|
||||
case "--force_long_branches":
|
||||
case "--expose_natives_as":
|
||||
case "--expose_debug_as":
|
||||
case "--expose_free_buffer":
|
||||
case "--expose_gc":
|
||||
case "--expose_gc_as":
|
||||
case "--expose_externalize_string":
|
||||
case "--expose_trigger_failure":
|
||||
case "--stack_trace_limit":
|
||||
case "--builtins_in_stack_traces":
|
||||
case "--disable_native_files":
|
||||
case "--inline_new":
|
||||
case "--trace_codegen":
|
||||
case "--trace":
|
||||
case "--mask_constants_with_cookie":
|
||||
case "--lazy":
|
||||
case "--trace_opt":
|
||||
case "--trace_opt_stats":
|
||||
case "--opt":
|
||||
case "--always_opt":
|
||||
case "--always_osr":
|
||||
case "--prepare_always_opt":
|
||||
case "--trace_deopt":
|
||||
case "--trace_stub_failures":
|
||||
case "--serialize_toplevel":
|
||||
case "--serialize_inner":
|
||||
case "--trace_serializer":
|
||||
case "--min_preparse_length":
|
||||
case "--max_opt_count":
|
||||
case "--compilation_cache":
|
||||
case "--cache_prototype_transitions":
|
||||
case "--cpu_profiler_sampling_interval":
|
||||
case "--trace_debug_json":
|
||||
case "--trace_js_array_abuse":
|
||||
case "--trace_external_array_abuse":
|
||||
case "--trace_array_abuse":
|
||||
case "--enable_liveedit":
|
||||
case "--hard_abort":
|
||||
case "--stack_size":
|
||||
case "--max_stack_trace_source_length":
|
||||
case "--always_inline_smi_code":
|
||||
case "--min_semi_space_size":
|
||||
case "--target_semi_space_size":
|
||||
case "--max_semi_space_size":
|
||||
case "--semi_space_growth_factor":
|
||||
case "--experimental_new_space_growth_heuristic":
|
||||
case "--max_old_space_size":
|
||||
case "--initial_old_space_size":
|
||||
case "--max_executable_size":
|
||||
case "--gc_global":
|
||||
case "--gc_interval":
|
||||
case "--trace_gc":
|
||||
case "--trace_gc_nvp":
|
||||
case "--trace_gc_ignore_scavenger":
|
||||
case "--trace_idle_notification":
|
||||
case "--trace_idle_notification_verbose":
|
||||
case "--print_cumulative_gc_stat":
|
||||
case "--print_max_heap_committed":
|
||||
case "--trace_gc_verbose":
|
||||
case "--trace_fragmentation":
|
||||
case "--collect_maps":
|
||||
case "--weak_embedded_maps_in_optimized_code":
|
||||
case "--weak_embedded_objects_in_optimized_code":
|
||||
case "--flush_code":
|
||||
case "--flush_code_incrementally":
|
||||
case "--trace_code_flushing":
|
||||
case "--age_code":
|
||||
case "--incremental_marking":
|
||||
case "--incremental_marking_steps":
|
||||
case "--concurrent_sweeping":
|
||||
case "--trace_incremental_marking":
|
||||
case "--track_gc_object_stats":
|
||||
case "--heap_profiler_trace_objects":
|
||||
case "--use_idle_notification":
|
||||
case "--use_ic":
|
||||
case "--trace_ic":
|
||||
case "--native_code_counters":
|
||||
case "--always_compact":
|
||||
case "--never_compact":
|
||||
case "--compact_code_space":
|
||||
case "--incremental_code_compaction":
|
||||
case "--cleanup_code_caches_at_gc":
|
||||
case "--use_marking_progress_bar":
|
||||
case "--zap_code_space":
|
||||
case "--random_seed":
|
||||
case "--trace_weak_arrays":
|
||||
case "--track_prototype_users":
|
||||
case "--use_verbose_printer":
|
||||
case "--allow_natives_syntax":
|
||||
case "--trace_parse":
|
||||
case "--trace_sim":
|
||||
case "--debug_sim":
|
||||
case "--check_icache":
|
||||
case "--stop_sim_at":
|
||||
case "--sim_stack_alignment":
|
||||
case "--sim_stack_size":
|
||||
case "--log_regs_modified":
|
||||
case "--log_colour":
|
||||
case "--ignore_asm_unimplemented_break":
|
||||
case "--trace_sim_messages":
|
||||
case "--stack_trace_on_illegal":
|
||||
case "--abort_on_uncaught_exception":
|
||||
case "--randomize_hashes":
|
||||
case "--hash_seed":
|
||||
case "--profile_deserialization":
|
||||
case "--regexp_optimization":
|
||||
case "--testing_bool_flag":
|
||||
case "--testing_maybe_bool_flag":
|
||||
case "--testing_int_flag":
|
||||
case "--testing_float_flag":
|
||||
case "--testing_string_flag":
|
||||
case "--testing_prng_seed":
|
||||
case "--testing_serialization_file":
|
||||
case "--startup_blob":
|
||||
case "--profile_hydrogen_code_stub_compilation":
|
||||
case "--predictable":
|
||||
case "--help":
|
||||
case "--dump_counters":
|
||||
case "--debugger":
|
||||
case "--map_counters":
|
||||
case "--js_arguments":
|
||||
case "--gdbjit":
|
||||
case "--gdbjit_full":
|
||||
case "--gdbjit_dump":
|
||||
case "--gdbjit_dump_filter":
|
||||
case "--force_marking_deque_overflows":
|
||||
case "--stress_compaction":
|
||||
case "--log":
|
||||
case "--log_all":
|
||||
case "--log_api":
|
||||
case "--log_code":
|
||||
case "--log_gc":
|
||||
case "--log_handles":
|
||||
case "--log_snapshot_positions":
|
||||
case "--log_suspect":
|
||||
case "--prof":
|
||||
case "--prof_browser_mode":
|
||||
case "--log_regexp":
|
||||
case "--logfile":
|
||||
case "--logfile_per_isolate":
|
||||
case "--ll_prof":
|
||||
case "--perf_basic_prof":
|
||||
case "--perf_jit_prof":
|
||||
case "--gc_fake_mmap":
|
||||
case "--log_internal_timer_events":
|
||||
case "--log_timer_events":
|
||||
case "--log_instruction_stats":
|
||||
case "--log_instruction_file":
|
||||
case "--log_instruction_period":
|
||||
case "--redirect_code_traces":
|
||||
case "--redirect_code_traces_to":
|
||||
case "--hydrogen_track_positions":
|
||||
case "--trace_elements_transitions":
|
||||
case "--trace_creation_allocation_sites":
|
||||
case "--print_code_stubs":
|
||||
case "--test_secondary_stub_cache":
|
||||
case "--test_primary_stub_cache":
|
||||
case "--print_code":
|
||||
case "--print_opt_code":
|
||||
case "--print_unopt_code":
|
||||
case "--print_code_verbose":
|
||||
case "--print_builtin_code":
|
||||
case "--sodium":
|
||||
case "--print_all_code":
|
||||
case "--es5_readonly":
|
||||
case "--es52_globals":
|
||||
case "--harmony_typeof":
|
||||
case "--harmony_collections":
|
||||
case "--packed_arrays":
|
||||
case "--smi_only_arrays":
|
||||
case "--clever_optimizations":
|
||||
case "--use_range":
|
||||
case "--eliminate_dead_phis":
|
||||
case "--optimize_closures":
|
||||
case "--loop_weight":
|
||||
case "--opt_safe_uint32_operations":
|
||||
case "--parallel_recompilation":
|
||||
case "--trace_parallel_recompilation":
|
||||
case "--parallel_recompilation_queue_length":
|
||||
case "--experimental_profiler":
|
||||
case "--watch_ic_patching":
|
||||
case "--self_optimization":
|
||||
case "--direct_self_opt":
|
||||
case "--retry_self_opt":
|
||||
case "--count_based_interrupts":
|
||||
case "--interrupt_at_exit":
|
||||
case "--weighted_back_edges":
|
||||
case "--debug_code (generate extra code":
|
||||
case "--enable_sse2":
|
||||
case "--enable_cmov":
|
||||
case "--enable_rdtsc":
|
||||
case "--enable_vfp2":
|
||||
case "--enable_fpu":
|
||||
case "--stack_trace_on_abort":
|
||||
case "--always_full_compiler":
|
||||
case "--debugger_auto_break":
|
||||
case "--break_on_abort":
|
||||
case "--max_new_space_size":
|
||||
case "--trace_external_memory":
|
||||
case "--lazy_sweeping":
|
||||
case "--trace_exception":
|
||||
case "--preallocate_message_memory":
|
||||
case "--preemption":
|
||||
case "--extra_code":
|
||||
case "--remote_debugger":
|
||||
case "--debugger_agent":
|
||||
case "--debugger_port":
|
||||
case "--debug_compile_events":
|
||||
case "--debug_script_collected_events":
|
||||
case "--gdbjit":
|
||||
case "--log_runtime":
|
||||
case "--prof_auto":
|
||||
case "--prof_lazy":
|
||||
case "--sliding_state_window":
|
||||
args.unshift(arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (arg.indexOf("--trace") === 0) {
|
||||
args.unshift(arg);
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// append arguments passed after --
|
||||
if (argSeparator > -1) {
|
||||
args = args.concat(userArgs);
|
||||
}
|
||||
|
||||
try {
|
||||
var kexec = require("kexec");
|
||||
kexec(process.argv[0], args);
|
||||
} catch (err) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
|
||||
var child_process = require("child_process");
|
||||
var proc = child_process.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);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -6,10 +6,6 @@ var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
|
||||
module.exports = function (commander, filenames, opts) {
|
||||
if (commander.sourceMapsInline) {
|
||||
opts.sourceMap = "inline";
|
||||
}
|
||||
|
||||
var write = function (src, relative) {
|
||||
// remove extension and then append back on .js
|
||||
relative = relative.replace(/\.(\w*?)$/, "") + ".js";
|
||||
@@ -20,7 +16,7 @@ module.exports = function (commander, filenames, opts) {
|
||||
sourceFileName: path.relative(dest + "/..", src)
|
||||
});
|
||||
|
||||
if (commander.sourceMaps) {
|
||||
if (commander.sourceMaps && commander.sourceMaps !== "inline") {
|
||||
var mapLoc = dest + ".map";
|
||||
data.code = util.addSourceMappingUrl(data.code, mapLoc);
|
||||
outputFileSync(mapLoc, JSON.stringify(data.map));
|
||||
@@ -32,6 +28,8 @@ module.exports = function (commander, filenames, opts) {
|
||||
};
|
||||
|
||||
var handleFile = function (src, filename) {
|
||||
if (util.shouldIgnore(src)) return;
|
||||
|
||||
if (util.canCompile(filename)) {
|
||||
write(src, filename);
|
||||
} else if (commander.copyFiles) {
|
||||
@@ -6,7 +6,11 @@ var util = require("./util");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
|
||||
module.exports = function (commander, filenames) {
|
||||
module.exports = function (commander, filenames, opts) {
|
||||
if (commander.sourceMaps === "inline") {
|
||||
opts.sourceMaps = true;
|
||||
}
|
||||
|
||||
var results = [];
|
||||
|
||||
var buildResult = function () {
|
||||
@@ -41,7 +45,7 @@ module.exports = function (commander, filenames) {
|
||||
}
|
||||
});
|
||||
|
||||
if (commander.sourceMapsInline || (!commander.outFile && commander.sourceMaps)) {
|
||||
if (commander.sourceMaps === "inline" || (!commander.outFile && commander.sourceMaps)) {
|
||||
code += "\n" + convertSourceMap.fromObject(map).toComment();
|
||||
}
|
||||
|
||||
@@ -55,7 +59,7 @@ module.exports = function (commander, filenames) {
|
||||
var result = buildResult();
|
||||
|
||||
if (commander.outFile) {
|
||||
if (commander.sourceMaps) {
|
||||
if (commander.sourceMaps && commander.sourceMaps !== "inline") {
|
||||
var mapLoc = commander.outFile + ".map";
|
||||
result.code = util.addSourceMappingUrl(result.code, mapLoc);
|
||||
fs.writeFileSync(mapLoc, JSON.stringify(result.map));
|
||||
@@ -103,6 +107,8 @@ module.exports = function (commander, filenames) {
|
||||
});
|
||||
|
||||
_.each(_filenames, function (filename) {
|
||||
if (util.shouldIgnore(filename)) return;
|
||||
|
||||
results.push(util.compile(filename));
|
||||
});
|
||||
|
||||
125
packages/babel-cli/bin/babel/index.js
Executable file
125
packages/babel-cli/bin/babel/index.js
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var commander = require("commander");
|
||||
var transform = require("babel-core").transform;
|
||||
var kebabCase = require("lodash/string/kebabCase");
|
||||
var options = require("babel-core").options;
|
||||
var util = require("babel-core").util;
|
||||
var each = require("lodash/collection/each");
|
||||
var keys = require("lodash/object/keys");
|
||||
var fs = require("fs");
|
||||
var glob = require("glob");
|
||||
|
||||
each(options, function (option, key) {
|
||||
if (option.hidden) return;
|
||||
|
||||
var arg = kebabCase(key);
|
||||
|
||||
if (option.type !== "boolean") {
|
||||
arg += " [" + (option.type || "string") + "]";
|
||||
}
|
||||
|
||||
if (option.type === "boolean" && option.default === true) {
|
||||
arg = "no-" + arg;
|
||||
}
|
||||
|
||||
arg = "--" + arg;
|
||||
|
||||
if (option.shorthand) {
|
||||
arg = "-" + option.shorthand + ", " + arg;
|
||||
}
|
||||
|
||||
var desc = [];
|
||||
if (option.deprecated) desc.push("[DEPRECATED] " + option.deprecated);
|
||||
if (option.description) desc.push(option.description);
|
||||
|
||||
commander.option(arg, desc.join(" "));
|
||||
})
|
||||
|
||||
commander.option("-w, --watch", "Recompile files on changes");
|
||||
commander.option("-o, --out-file [out]", "Compile all input files into a single file");
|
||||
commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory");
|
||||
commander.option("-D, --copy-files", "When compiling a directory copy over non-compilable files");
|
||||
|
||||
commander.on("--help", function () {
|
||||
var outKeys = function (title, obj) {
|
||||
console.log(" " + title + ":");
|
||||
console.log();
|
||||
|
||||
each(keys(obj).sort(), function (key) {
|
||||
if (key[0] === "_") return;
|
||||
|
||||
if (obj[key].optional) key = "[" + key + "]";
|
||||
|
||||
console.log(" - " + key);
|
||||
});
|
||||
|
||||
console.log();
|
||||
};
|
||||
|
||||
outKeys("Transformers", transform.transformers);
|
||||
outKeys("Module formatters", transform.moduleFormatters);
|
||||
});
|
||||
|
||||
var pkg = require("../../package.json");
|
||||
commander.version(pkg.version);
|
||||
commander.usage("[options] <files ...>");
|
||||
commander.parse(process.argv);
|
||||
|
||||
//
|
||||
|
||||
var errors = [];
|
||||
|
||||
var filenames = commander.args.reduce(function (globbed, input) {
|
||||
return globbed.concat(glob.sync(input));
|
||||
}, []);
|
||||
|
||||
each(filenames, function (filename) {
|
||||
if (!fs.existsSync(filename)) {
|
||||
errors.push(filename + " doesn't exist");
|
||||
}
|
||||
});
|
||||
|
||||
if (commander.outDir && !filenames.length) {
|
||||
errors.push("filenames required for --out-dir");
|
||||
}
|
||||
|
||||
if (commander.outFile && commander.outDir) {
|
||||
errors.push("cannot have --out-file and --out-dir");
|
||||
}
|
||||
|
||||
if (commander.watch) {
|
||||
if (!commander.outFile && !commander.outDir) {
|
||||
errors.push("--watch requires --out-file or --out-dir");
|
||||
}
|
||||
|
||||
if (!filenames.length) {
|
||||
errors.push("--watch requires filenames");
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
console.error(errors.join(". "));
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var opts = exports.opts = {};
|
||||
|
||||
each(options, function (opt, key) {
|
||||
opts[key] = commander[key];
|
||||
});
|
||||
|
||||
opts.ignore = util.arrayify(opts.ignore, util.regexify);
|
||||
opts.only = util.arrayify(opts.only, util.regexify);
|
||||
|
||||
var fn;
|
||||
|
||||
if (commander.outDir) {
|
||||
fn = require("./dir");
|
||||
} else {
|
||||
fn = require("./file");
|
||||
}
|
||||
|
||||
fn(commander, filenames, exports.opts);
|
||||
@@ -1,11 +1,10 @@
|
||||
var resolveRc = require("../../lib/babel/api/register/resolve-rc");
|
||||
var readdir = require("fs-readdir-recursive");
|
||||
var index = require("./index");
|
||||
var babel = require("../../lib/babel/api/node");
|
||||
var util = require("../../lib/babel/util");
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
var readdir = require("fs-readdir-recursive");
|
||||
var index = require("./index");
|
||||
var babel = require("babel-core");
|
||||
var util = require("babel-core").util;
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.readdirFilter = function (filename) {
|
||||
return readdir(filename).filter(function (filename) {
|
||||
@@ -17,6 +16,10 @@ exports.readdir = readdir;
|
||||
|
||||
exports.canCompile = util.canCompile;
|
||||
|
||||
exports.shouldIgnore = function (loc) {
|
||||
return util.shouldIgnore(loc, index.opts.ignore, index.opts.only);
|
||||
};
|
||||
|
||||
exports.addSourceMappingUrl = function (code, loc) {
|
||||
return code + "\n//# sourceMappingURL=" + path.basename(loc);
|
||||
};
|
||||
@@ -24,7 +27,8 @@ exports.addSourceMappingUrl = function (code, loc) {
|
||||
exports.transform = function (filename, code, opts) {
|
||||
opts = _.defaults(opts || {}, index.opts);
|
||||
opts.filename = filename;
|
||||
resolveRc(filename, opts);
|
||||
opts.ignore = null;
|
||||
opts.only = null;
|
||||
|
||||
var result = babel.transform(code, opts);
|
||||
result.filename = filename;
|
||||
1
packages/babel-cli/index.js
Normal file
1
packages/babel-cli/index.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("babel-core");
|
||||
26
packages/babel-cli/package.json
Normal file
26
packages/babel-cli/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "babel",
|
||||
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
|
||||
"version": "5.2.4",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
"repository": "babel/babel",
|
||||
"preferGlobal": true,
|
||||
"dependencies": {
|
||||
"babel-core": "^5.2.4",
|
||||
"chokidar": "^1.0.0",
|
||||
"commander": "^2.6.0",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"fs-readdir-recursive": "^0.1.0",
|
||||
"glob": "^5.0.5",
|
||||
"lodash": "^3.2.0",
|
||||
"output-file-sync": "^1.1.0",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"source-map": "^0.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"babel": "./bin/babel/index.js",
|
||||
"babel-node": "./bin/babel-node",
|
||||
"babel-external-helpers": "./bin/babel-external-helpers"
|
||||
}
|
||||
}
|
||||
1
packages/babel-cli/polyfill.js
Normal file
1
packages/babel-cli/polyfill.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("babel-core/polyfill");
|
||||
1
packages/babel-cli/register-without-polyfill.js
Normal file
1
packages/babel-cli/register-without-polyfill.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("babel-core/register-without-polyfill");
|
||||
1
packages/babel-cli/register.js
Normal file
1
packages/babel-cli/register.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("babel-core/register");
|
||||
4
packages/babel-runtime/core-js.js
Normal file
4
packages/babel-runtime/core-js.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
"default": require("core-js/library"),
|
||||
__esModule: true
|
||||
};
|
||||
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"name": "babel-runtime",
|
||||
"description": "babel selfContained runtime",
|
||||
"version": "4.7.1",
|
||||
"version": "5.2.4",
|
||||
"repository": "babel/babel",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>"
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"dependencies": {
|
||||
"core-js": "^0.9.0"
|
||||
}
|
||||
}
|
||||
11
packages/build-cli.js
Normal file
11
packages/build-cli.js
Normal file
@@ -0,0 +1,11 @@
|
||||
var outputFile = require("output-file-sync");
|
||||
|
||||
var pkgLoc = __dirname + "/babel-cli/package.json";
|
||||
var pkg = require(pkgLoc);
|
||||
|
||||
var mainPkg = require("../package.json");
|
||||
|
||||
pkg.version = mainPkg.version;
|
||||
pkg.dependencies["babel-core"] = "^" + mainPkg.version;
|
||||
|
||||
outputFile(pkgLoc, JSON.stringify(pkg, null, 2));
|
||||
@@ -1,61 +1,98 @@
|
||||
"use strict";
|
||||
|
||||
var transform = require("../lib/babel/transformation");
|
||||
var buildHelpers = require("../lib/babel/build-helpers");
|
||||
var util = require("../lib/babel/util");
|
||||
var fs = require("fs");
|
||||
var t = require("../lib/babel/types");
|
||||
var _ = require("lodash");
|
||||
var outputFile = require("output-file-sync");
|
||||
var transform = require("../lib/babel/transformation");
|
||||
var each = require("lodash/collection/each");
|
||||
var File = require("../lib/babel/transformation/file");
|
||||
var util = require("../lib/babel/util");
|
||||
var fs = require("fs");
|
||||
var t = require("../lib/babel/types");
|
||||
var _ = require("lodash");
|
||||
|
||||
var relative = function (filename) {
|
||||
function relative(filename) {
|
||||
return __dirname + "/babel-runtime/" + filename;
|
||||
};
|
||||
}
|
||||
|
||||
var writeFile = function (filename, content) {
|
||||
filename = relative(filename);
|
||||
console.log(filename);
|
||||
fs.writeFileSync(filename, content);
|
||||
};
|
||||
|
||||
var readFile = function (filename, defaultify) {
|
||||
function readFile(filename, shouldDefaultify) {
|
||||
var file = fs.readFileSync(require.resolve(filename), "utf8");
|
||||
|
||||
if (defaultify) {
|
||||
file += '\nmodule.exports = { "default": module.exports, __esModule: true };\n';
|
||||
if (shouldDefaultify) {
|
||||
file += "\n" + defaultify("module.exports") + "\n";
|
||||
}
|
||||
|
||||
return file;
|
||||
};
|
||||
}
|
||||
|
||||
var updatePackage = function () {
|
||||
function defaultify(name) {
|
||||
return 'module.exports = { "default": ' + name + ', __esModule: true };';
|
||||
}
|
||||
|
||||
function updatePackage() {
|
||||
var pkgLoc = relative("package.json");
|
||||
var pkg = require(pkgLoc);
|
||||
|
||||
var mainPkg = require("../package.json");
|
||||
pkg.version = mainPkg.version;
|
||||
|
||||
writeFile("package.json", JSON.stringify(pkg, null, 2));
|
||||
};
|
||||
writeRootFile("package.json", JSON.stringify(pkg, null, 2));
|
||||
}
|
||||
|
||||
var selfContainify = function (code) {
|
||||
function writeRootFile(filename, content) {
|
||||
filename = relative(filename);
|
||||
console.log(filename);
|
||||
outputFile(filename, content);
|
||||
}
|
||||
|
||||
|
||||
function writeFile(filename, content) {
|
||||
return writeRootFile(filename, content);
|
||||
}
|
||||
|
||||
function selfContainify(code) {
|
||||
return transform(code, {
|
||||
optional: ["selfContained"]
|
||||
optional: ["runtime"]
|
||||
}).code;
|
||||
};
|
||||
}
|
||||
|
||||
var buildHelpers2 = function () {
|
||||
var body = util.template("self-contained-helpers-head");
|
||||
var tree = t.program(body);
|
||||
|
||||
buildHelpers(body, t.identifier("helpers"));
|
||||
function buildHelper(helperName) {
|
||||
var tree = t.program(
|
||||
util.template("self-contained-helpers-head", {
|
||||
HELPER: util.template("helper-" + helperName)
|
||||
})
|
||||
);
|
||||
|
||||
return transform.fromAst(tree, null, {
|
||||
optional: ["selfContained"]
|
||||
optional: ["runtime"]
|
||||
}).code;
|
||||
};
|
||||
}
|
||||
|
||||
each(File.helpers, function (helperName) {
|
||||
writeFile("helpers/" + helperName + ".js", buildHelper(helperName));
|
||||
});
|
||||
|
||||
writeFile("regenerator/index.js", readFile("regenerator/runtime-module", true));
|
||||
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator/runtime")));
|
||||
|
||||
//
|
||||
|
||||
var coreDefinitions = require("../lib/babel/transformation/transformers/other/runtime/definitions");
|
||||
|
||||
var paths = ["is-iterable", "get-iterator"];
|
||||
|
||||
each(coreDefinitions.builtins, function (path) {
|
||||
paths.push(path);
|
||||
});
|
||||
|
||||
each(coreDefinitions.methods, function (props) {
|
||||
each(props, function (path) {
|
||||
paths.push(path);
|
||||
});
|
||||
});
|
||||
|
||||
each(paths, function (path) {
|
||||
writeFile("core-js/" + path + ".js", defaultify('require("core-js/library/fn/' + path + '")'));
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
writeFile("helpers.js", buildHelpers2());
|
||||
writeFile("core-js.js", readFile("core-js/library", true));
|
||||
writeFile("regenerator/index.js", readFile("regenerator-babel/runtime-module", true));
|
||||
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-babel/runtime")));
|
||||
updatePackage();
|
||||
|
||||
1
register-without-polyfill.js
Normal file
1
register-without-polyfill.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("./lib/babel/api/register/node");
|
||||
@@ -1 +1 @@
|
||||
module.exports = require("./lib/babel/api/register/node");
|
||||
module.exports = require("./lib/babel/api/register/node-polyfill");
|
||||
|
||||
32
src/acorn/AUTHORS
Executable file
32
src/acorn/AUTHORS
Executable file
@@ -0,0 +1,32 @@
|
||||
List of Acorn contributors. Updated before every release.
|
||||
|
||||
Alistair Braidwood
|
||||
Aparajita Fishman
|
||||
Arian Stolwijk
|
||||
Artem Govorov
|
||||
Brandon Mills
|
||||
Charles Hughes
|
||||
Conrad Irwin
|
||||
David Bonnet
|
||||
impinball
|
||||
Ingvar Stepanyan
|
||||
Jiaxing Wang
|
||||
Johannes Herr
|
||||
Jürg Lehni
|
||||
keeyipchan
|
||||
krator
|
||||
Marijn Haverbeke
|
||||
Martin Carlberg
|
||||
Mathias Bynens
|
||||
Mathieu 'p01' Henri
|
||||
Max Schaefer
|
||||
Mihai Bazon
|
||||
Mike Rennie
|
||||
Oskar Schöldström
|
||||
Paul Harper
|
||||
Peter Rust
|
||||
PlNG
|
||||
r-e-d
|
||||
Rich Harris
|
||||
Sebastian McKenzie
|
||||
zsjforcn
|
||||
19
src/acorn/LICENSE
Executable file
19
src/acorn/LICENSE
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2012-2014 by various contributors (see AUTHORS)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
3
src/acorn/index.js
Normal file
3
src/acorn/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./src/index";
|
||||
import "./plugins/flow";
|
||||
import "./plugins/jsx";
|
||||
44
src/acorn/package.json
Executable file
44
src/acorn/package.json
Executable file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "acorn",
|
||||
"description": "ECMAScript parser",
|
||||
"homepage": "https://github.com/marijnh/acorn",
|
||||
"main": "index.js",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijnh@gmail.com",
|
||||
"web": "http://marijnhaverbeke.nl"
|
||||
},
|
||||
{
|
||||
"name": "Ingvar Stepanyan",
|
||||
"email": "me@rreverser.com",
|
||||
"web": "http://rreverser.com/"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/marijnh/acorn.git"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://raw.githubusercontent.com/marijnh/acorn/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "node test/run.js",
|
||||
"prepublish": "node bin/prepublish.sh"
|
||||
},
|
||||
"bin": {
|
||||
"acorn": "./bin/acorn"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babelify": "^5.0.4",
|
||||
"browserify": "^9.0.3",
|
||||
"unicode-7.0.0": "~0.1.5"
|
||||
}
|
||||
}
|
||||
831
src/acorn/plugins/flow.js
Normal file
831
src/acorn/plugins/flow.js
Normal file
@@ -0,0 +1,831 @@
|
||||
var acorn = require("../src/index")
|
||||
|
||||
var pp = acorn.Parser.prototype
|
||||
var tt = acorn.tokTypes
|
||||
|
||||
pp.isRelational = function (op) {
|
||||
return this.type === tt.relational && this.value === op
|
||||
}
|
||||
|
||||
pp.expectRelational = function (op) {
|
||||
if (this.isRelational(op)) {
|
||||
this.next()
|
||||
} else {
|
||||
this.unexpected()
|
||||
}
|
||||
}
|
||||
|
||||
pp.flow_parseDeclareClass = function (node) {
|
||||
this.next()
|
||||
this.flow_parseInterfaceish(node, true)
|
||||
return this.finishNode(node, "DeclareClass")
|
||||
}
|
||||
|
||||
pp.flow_parseDeclareFunction = function (node) {
|
||||
this.next()
|
||||
|
||||
var id = node.id = this.parseIdent()
|
||||
|
||||
var typeNode = this.startNode()
|
||||
var typeContainer = this.startNode()
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
typeNode.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
} else {
|
||||
typeNode.typeParameters = null
|
||||
}
|
||||
|
||||
this.expect(tt.parenL)
|
||||
var tmp = this.flow_parseFunctionTypeParams()
|
||||
typeNode.params = tmp.params
|
||||
typeNode.rest = tmp.rest
|
||||
this.expect(tt.parenR)
|
||||
|
||||
this.expect(tt.colon)
|
||||
typeNode.returnType = this.flow_parseType()
|
||||
|
||||
typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation")
|
||||
id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation")
|
||||
|
||||
this.finishNode(id, id.type)
|
||||
|
||||
this.semicolon()
|
||||
|
||||
return this.finishNode(node, "DeclareFunction")
|
||||
}
|
||||
|
||||
pp.flow_parseDeclare = function (node) {
|
||||
if (this.type === tt._class) {
|
||||
return this.flow_parseDeclareClass(node)
|
||||
} else if (this.type === tt._function) {
|
||||
return this.flow_parseDeclareFunction(node)
|
||||
} else if (this.type === tt._var) {
|
||||
return this.flow_parseDeclareVariable(node)
|
||||
} else if (this.isContextual("module")) {
|
||||
return this.flow_parseDeclareModule(node)
|
||||
} else {
|
||||
this.unexpected()
|
||||
}
|
||||
}
|
||||
|
||||
pp.flow_parseDeclareVariable = function (node) {
|
||||
this.next()
|
||||
node.id = this.flow_parseTypeAnnotatableIdentifier()
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "DeclareVariable")
|
||||
}
|
||||
|
||||
pp.flow_parseDeclareModule = function (node) {
|
||||
this.next()
|
||||
|
||||
if (this.type === tt.string) {
|
||||
node.id = this.parseExprAtom()
|
||||
} else {
|
||||
node.id = this.parseIdent()
|
||||
}
|
||||
|
||||
var bodyNode = node.body = this.startNode()
|
||||
var body = bodyNode.body = []
|
||||
this.expect(tt.braceL)
|
||||
while (this.type !== tt.braceR) {
|
||||
var node2 = this.startNode()
|
||||
|
||||
// todo: declare check
|
||||
this.next()
|
||||
|
||||
body.push(this.flow_parseDeclare(node2))
|
||||
}
|
||||
this.expect(tt.braceR)
|
||||
|
||||
this.finishNode(bodyNode, "BlockStatement")
|
||||
return this.finishNode(node, "DeclareModule")
|
||||
}
|
||||
|
||||
|
||||
// Interfaces
|
||||
|
||||
pp.flow_parseInterfaceish = function (node, allowStatic) {
|
||||
node.id = this.parseIdent()
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
} else {
|
||||
node.typeParameters = null
|
||||
}
|
||||
|
||||
node.extends = []
|
||||
|
||||
if (this.eat(tt._extends)) {
|
||||
do {
|
||||
node.extends.push(this.flow_parseInterfaceExtends())
|
||||
} while(this.eat(tt.comma))
|
||||
}
|
||||
|
||||
node.body = this.flow_parseObjectType(allowStatic)
|
||||
}
|
||||
|
||||
pp.flow_parseInterfaceExtends = function () {
|
||||
var node = this.startNode()
|
||||
|
||||
node.id = this.parseIdent()
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterInstantiation()
|
||||
} else {
|
||||
node.typeParameters = null
|
||||
}
|
||||
|
||||
return this.finishNode(node, "InterfaceExtends")
|
||||
}
|
||||
|
||||
pp.flow_parseInterface = function (node) {
|
||||
this.flow_parseInterfaceish(node, false)
|
||||
return this.finishNode(node, "InterfaceDeclaration")
|
||||
}
|
||||
|
||||
// Type aliases
|
||||
|
||||
pp.flow_parseTypeAlias = function (node) {
|
||||
node.id = this.parseIdent()
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
} else {
|
||||
node.typeParameters = null
|
||||
}
|
||||
|
||||
this.expect(tt.eq)
|
||||
|
||||
node.right = this.flow_parseType()
|
||||
|
||||
this.semicolon()
|
||||
|
||||
return this.finishNode(node, "TypeAlias")
|
||||
}
|
||||
|
||||
// Type annotations
|
||||
|
||||
pp.flow_parseTypeParameterDeclaration = function () {
|
||||
var node = this.startNode()
|
||||
node.params = []
|
||||
|
||||
this.expectRelational("<")
|
||||
while (!this.isRelational(">")) {
|
||||
node.params.push(this.flow_parseTypeAnnotatableIdentifier())
|
||||
if (!this.isRelational(">")) {
|
||||
this.expect(tt.comma)
|
||||
}
|
||||
}
|
||||
this.expectRelational(">")
|
||||
|
||||
return this.finishNode(node, "TypeParameterDeclaration")
|
||||
}
|
||||
|
||||
pp.flow_parseTypeParameterInstantiation = function () {
|
||||
var node = this.startNode(), oldInType = this.inType
|
||||
node.params = []
|
||||
|
||||
this.inType = true
|
||||
|
||||
this.expectRelational("<")
|
||||
while (!this.isRelational(">")) {
|
||||
node.params.push(this.flow_parseType())
|
||||
if (!this.isRelational(">")) {
|
||||
this.expect(tt.comma)
|
||||
}
|
||||
}
|
||||
this.expectRelational(">")
|
||||
|
||||
this.inType = oldInType
|
||||
|
||||
return this.finishNode(node, "TypeParameterInstantiation")
|
||||
}
|
||||
|
||||
pp.flow_parseObjectPropertyKey = function () {
|
||||
return (this.type === tt.num || this.type === tt.string) ? this.parseExprAtom() : this.parseIdent(true)
|
||||
}
|
||||
|
||||
pp.flow_parseObjectTypeIndexer = function (node, isStatic) {
|
||||
node.static = isStatic
|
||||
|
||||
this.expect(tt.bracketL)
|
||||
node.id = this.flow_parseObjectPropertyKey()
|
||||
this.expect(tt.colon)
|
||||
node.key = this.flow_parseType()
|
||||
this.expect(tt.bracketR)
|
||||
this.expect(tt.colon)
|
||||
node.value = this.flow_parseType()
|
||||
|
||||
this.flow_objectTypeSemicolon()
|
||||
return this.finishNode(node, "ObjectTypeIndexer")
|
||||
}
|
||||
|
||||
pp.flow_parseObjectTypeMethodish = function (node) {
|
||||
node.params = []
|
||||
node.rest = null
|
||||
node.typeParameters = null
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
}
|
||||
|
||||
this.expect(tt.parenL)
|
||||
while (this.type === tt.name) {
|
||||
node.params.push(this.flow_parseFunctionTypeParam())
|
||||
if (this.type !== tt.parenR) {
|
||||
this.expect(tt.comma)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.eat(tt.ellipsis)) {
|
||||
node.rest = this.flow_parseFunctionTypeParam()
|
||||
}
|
||||
this.expect(tt.parenR)
|
||||
this.expect(tt.colon)
|
||||
node.returnType = this.flow_parseType()
|
||||
|
||||
return this.finishNode(node, "FunctionTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseObjectTypeMethod = function (start, isStatic, key) {
|
||||
var node = this.startNodeAt(start)
|
||||
node.value = this.flow_parseObjectTypeMethodish(this.startNodeAt(start))
|
||||
node.static = isStatic
|
||||
node.key = key
|
||||
node.optional = false
|
||||
this.flow_objectTypeSemicolon()
|
||||
return this.finishNode(node, "ObjectTypeProperty")
|
||||
}
|
||||
|
||||
pp.flow_parseObjectTypeCallProperty = function (node, isStatic) {
|
||||
var valueNode = this.startNode()
|
||||
node.static = isStatic
|
||||
node.value = this.flow_parseObjectTypeMethodish(valueNode)
|
||||
this.flow_objectTypeSemicolon()
|
||||
return this.finishNode(node, "ObjectTypeCallProperty")
|
||||
}
|
||||
|
||||
pp.flow_parseObjectType = function (allowStatic) {
|
||||
var nodeStart = this.startNode()
|
||||
var node
|
||||
var optional = false
|
||||
var property
|
||||
var propertyKey
|
||||
var propertyTypeAnnotation
|
||||
var token
|
||||
var isStatic
|
||||
|
||||
nodeStart.callProperties = []
|
||||
nodeStart.properties = []
|
||||
nodeStart.indexers = []
|
||||
|
||||
this.expect(tt.braceL)
|
||||
|
||||
while (this.type !== tt.braceR) {
|
||||
var start = this.markPosition()
|
||||
node = this.startNode()
|
||||
if (allowStatic && this.isContextual("static")) {
|
||||
this.next()
|
||||
isStatic = true
|
||||
}
|
||||
|
||||
if (this.type === tt.bracketL) {
|
||||
nodeStart.indexers.push(this.flow_parseObjectTypeIndexer(node, isStatic))
|
||||
} else if (this.type === tt.parenL || this.isRelational("<")) {
|
||||
nodeStart.callProperties.push(this.flow_parseObjectTypeCallProperty(node, allowStatic))
|
||||
} else {
|
||||
if (isStatic && this.type === tt.colon) {
|
||||
propertyKey = this.parseIdent()
|
||||
} else {
|
||||
propertyKey = this.flow_parseObjectPropertyKey()
|
||||
}
|
||||
if (this.isRelational("<") || this.type === tt.parenL) {
|
||||
// This is a method property
|
||||
nodeStart.properties.push(this.flow_parseObjectTypeMethod(start, isStatic, propertyKey))
|
||||
} else {
|
||||
if (this.eat(tt.question)) {
|
||||
optional = true
|
||||
}
|
||||
this.expect(tt.colon)
|
||||
node.key = propertyKey
|
||||
node.value = this.flow_parseType()
|
||||
node.optional = optional
|
||||
node.static = isStatic
|
||||
this.flow_objectTypeSemicolon()
|
||||
nodeStart.properties.push(this.finishNode(node, "ObjectTypeProperty"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.expect(tt.braceR)
|
||||
|
||||
return this.finishNode(nodeStart, "ObjectTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_objectTypeSemicolon = function () {
|
||||
if (!this.eat(tt.semi) && !this.eat(tt.comma) && this.type !== tt.braceR) {
|
||||
this.unexpected()
|
||||
}
|
||||
}
|
||||
|
||||
pp.flow_parseGenericType = function (start, id) {
|
||||
var node = this.startNodeAt(start)
|
||||
|
||||
node.typeParameters = null
|
||||
node.id = id
|
||||
|
||||
while (this.eat(tt.dot)) {
|
||||
var node2 = this.startNodeAt(start)
|
||||
node2.qualification = node.id
|
||||
node2.id = this.parseIdent()
|
||||
node.id = this.finishNode(node2, "QualifiedTypeIdentifier")
|
||||
}
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterInstantiation()
|
||||
}
|
||||
|
||||
return this.finishNode(node, "GenericTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseVoidType = function () {
|
||||
var node = this.startNode()
|
||||
this.expect(tt._void)
|
||||
return this.finishNode(node, "VoidTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseTypeofType = function () {
|
||||
var node = this.startNode()
|
||||
this.expect(tt._typeof)
|
||||
node.argument = this.flow_parsePrimaryType()
|
||||
return this.finishNode(node, "TypeofTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseTupleType = function () {
|
||||
var node = this.startNode()
|
||||
node.types = []
|
||||
this.expect(tt.bracketL)
|
||||
// We allow trailing commas
|
||||
while (this.pos < this.input.length && this.type !== tt.bracketR) {
|
||||
node.types.push(this.flow_parseType())
|
||||
if (this.type === tt.bracketR) break
|
||||
this.expect(tt.comma)
|
||||
}
|
||||
this.expect(tt.bracketR)
|
||||
return this.finishNode(node, "TupleTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseFunctionTypeParam = function () {
|
||||
var optional = false
|
||||
var node = this.startNode()
|
||||
node.name = this.parseIdent()
|
||||
if (this.eat(tt.question)) {
|
||||
optional = true
|
||||
}
|
||||
this.expect(tt.colon)
|
||||
node.optional = optional
|
||||
node.typeAnnotation = this.flow_parseType()
|
||||
return this.finishNode(node, "FunctionTypeParam")
|
||||
}
|
||||
|
||||
pp.flow_parseFunctionTypeParams = function () {
|
||||
var ret = { params: [], rest: null }
|
||||
while (this.type === tt.name) {
|
||||
ret.params.push(this.flow_parseFunctionTypeParam())
|
||||
if (this.type !== tt.parenR) {
|
||||
this.expect(tt.comma)
|
||||
}
|
||||
}
|
||||
if (this.eat(tt.ellipsis)) {
|
||||
ret.rest = this.flow_parseFunctionTypeParam()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
pp.flow_identToTypeAnnotation = function (start, node, id) {
|
||||
switch (id.name) {
|
||||
case "any":
|
||||
return this.finishNode(node, "AnyTypeAnnotation")
|
||||
|
||||
case "bool":
|
||||
case "boolean":
|
||||
return this.finishNode(node, "BooleanTypeAnnotation")
|
||||
|
||||
case "number":
|
||||
return this.finishNode(node, "NumberTypeAnnotation")
|
||||
|
||||
case "string":
|
||||
return this.finishNode(node, "StringTypeAnnotation")
|
||||
|
||||
default:
|
||||
return this.flow_parseGenericType(start, id)
|
||||
}
|
||||
}
|
||||
|
||||
// The parsing of types roughly parallels the parsing of expressions, and
|
||||
// primary types are kind of like primary expressions...they're the
|
||||
// primitives with which other types are constructed.
|
||||
pp.flow_parsePrimaryType = function () {
|
||||
var typeIdentifier = null
|
||||
var params = null
|
||||
var returnType = null
|
||||
var start = this.markPosition()
|
||||
var node = this.startNode()
|
||||
var rest = null
|
||||
var tmp
|
||||
var typeParameters
|
||||
var token
|
||||
var type
|
||||
var isGroupedType = false
|
||||
|
||||
switch (this.type) {
|
||||
case tt.name:
|
||||
return this.flow_identToTypeAnnotation(start, node, this.parseIdent())
|
||||
|
||||
case tt.braceL:
|
||||
return this.flow_parseObjectType()
|
||||
|
||||
case tt.bracketL:
|
||||
return this.flow_parseTupleType()
|
||||
|
||||
case tt.relational:
|
||||
if (this.value === "<") {
|
||||
node.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
this.expect(tt.parenL)
|
||||
tmp = this.flow_parseFunctionTypeParams()
|
||||
node.params = tmp.params
|
||||
node.rest = tmp.rest
|
||||
this.expect(tt.parenR)
|
||||
|
||||
this.expect(tt.arrow)
|
||||
|
||||
node.returnType = this.flow_parseType()
|
||||
|
||||
return this.finishNode(node, "FunctionTypeAnnotation")
|
||||
}
|
||||
|
||||
case tt.parenL:
|
||||
this.next()
|
||||
|
||||
// Check to see if this is actually a grouped type
|
||||
if (this.type !== tt.parenR && this.type !== tt.ellipsis) {
|
||||
if (this.type === tt.name) {
|
||||
var token = this.lookahead().type
|
||||
isGroupedType = token !== tt.question && token !== tt.colon
|
||||
} else {
|
||||
isGroupedType = true
|
||||
}
|
||||
}
|
||||
|
||||
if (isGroupedType) {
|
||||
type = this.flow_parseType()
|
||||
this.expect(tt.parenR)
|
||||
|
||||
// If we see a => next then someone was probably confused about
|
||||
// function types, so we can provide a better error message
|
||||
if (this.eat(tt.arrow)) {
|
||||
this.raise(node,
|
||||
"Unexpected token =>. It looks like " +
|
||||
"you are trying to write a function type, but you ended up " +
|
||||
"writing a grouped type followed by an =>, which is a syntax " +
|
||||
"error. Remember, function type parameters are named so function " +
|
||||
"types look like (name1: type1, name2: type2) => returnType. You " +
|
||||
"probably wrote (type1) => returnType"
|
||||
)
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
tmp = this.flow_parseFunctionTypeParams()
|
||||
node.params = tmp.params
|
||||
node.rest = tmp.rest
|
||||
|
||||
this.expect(tt.parenR)
|
||||
|
||||
this.expect(tt.arrow)
|
||||
|
||||
node.returnType = this.flow_parseType()
|
||||
node.typeParameters = null
|
||||
|
||||
return this.finishNode(node, "FunctionTypeAnnotation")
|
||||
|
||||
case tt.string:
|
||||
node.value = this.value
|
||||
node.raw = this.input.slice(this.start, this.end)
|
||||
this.next()
|
||||
return this.finishNode(node, "StringLiteralTypeAnnotation")
|
||||
|
||||
default:
|
||||
if (this.type.keyword) {
|
||||
switch (this.type.keyword) {
|
||||
case "void":
|
||||
return this.flow_parseVoidType()
|
||||
|
||||
case "typeof":
|
||||
return this.flow_parseTypeofType()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.unexpected()
|
||||
}
|
||||
|
||||
pp.flow_parsePostfixType = function () {
|
||||
var node = this.startNode()
|
||||
var type = node.elementType = this.flow_parsePrimaryType()
|
||||
if (this.type === tt.bracketL) {
|
||||
this.expect(tt.bracketL)
|
||||
this.expect(tt.bracketR)
|
||||
return this.finishNode(node, "ArrayTypeAnnotation")
|
||||
}
|
||||
return type
|
||||
}
|
||||
|
||||
pp.flow_parsePrefixType = function () {
|
||||
var node = this.startNode()
|
||||
if (this.eat(tt.question)) {
|
||||
node.typeAnnotation = this.flow_parsePrefixType()
|
||||
return this.finishNode(node, "NullableTypeAnnotation")
|
||||
}
|
||||
return this.flow_parsePostfixType()
|
||||
}
|
||||
|
||||
pp.flow_parseIntersectionType = function () {
|
||||
var node = this.startNode()
|
||||
var type = this.flow_parsePrefixType()
|
||||
node.types = [type]
|
||||
while (this.eat(tt.bitwiseAND)) {
|
||||
node.types.push(this.flow_parsePrefixType())
|
||||
}
|
||||
return node.types.length === 1 ? type : this.finishNode(node, "IntersectionTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseUnionType = function () {
|
||||
var node = this.startNode()
|
||||
var type = this.flow_parseIntersectionType()
|
||||
node.types = [type]
|
||||
while (this.eat(tt.bitwiseOR)) {
|
||||
node.types.push(this.flow_parseIntersectionType())
|
||||
}
|
||||
return node.types.length === 1 ? type : this.finishNode(node, "UnionTypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseType = function () {
|
||||
var oldInType = this.inType
|
||||
this.inType = true
|
||||
var type = this.flow_parseUnionType()
|
||||
this.inType = oldInType
|
||||
return type
|
||||
}
|
||||
|
||||
pp.flow_parseTypeAnnotation = function () {
|
||||
var node = this.startNode()
|
||||
|
||||
var oldInType = this.inType
|
||||
this.inType = true
|
||||
this.expect(tt.colon)
|
||||
node.typeAnnotation = this.flow_parseType()
|
||||
this.inType = oldInType
|
||||
|
||||
return this.finishNode(node, "TypeAnnotation")
|
||||
}
|
||||
|
||||
pp.flow_parseTypeAnnotatableIdentifier = function (requireTypeAnnotation, canBeOptionalParam) {
|
||||
var node = this.startNode()
|
||||
var ident = this.parseIdent()
|
||||
var isOptionalParam = false
|
||||
|
||||
if (canBeOptionalParam && this.eat(tt.question)) {
|
||||
this.expect(tt.question)
|
||||
isOptionalParam = true
|
||||
}
|
||||
|
||||
if (requireTypeAnnotation || this.type === tt.colon) {
|
||||
ident.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
this.finishNode(ident, ident.type)
|
||||
}
|
||||
|
||||
if (isOptionalParam) {
|
||||
ident.optional = true
|
||||
this.finishNode(ident, ident.type)
|
||||
}
|
||||
|
||||
return ident
|
||||
}
|
||||
|
||||
acorn.plugins.flow = function (instance) {
|
||||
// function name(): string {}
|
||||
instance.extend("parseFunctionBody", function (inner) {
|
||||
return function (node, allowExpression) {
|
||||
if (this.type === tt.colon) {
|
||||
node.returnType = this.flow_parseTypeAnnotation()
|
||||
}
|
||||
|
||||
return inner.call(this, node, allowExpression)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseStatement", function (inner) {
|
||||
return function(declaration, topLevel) {
|
||||
// strict mode handling of `interface` since it's a reserved word
|
||||
if (this.strict && this.type === tt.name && this.value === "interface") {
|
||||
var node = this.startNode()
|
||||
this.next()
|
||||
return this.flow_parseInterface(node)
|
||||
} else {
|
||||
return inner.call(this, declaration, topLevel)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseExpressionStatement", function (inner) {
|
||||
return function (node, expr) {
|
||||
if (expr.type === "Identifier") {
|
||||
if (expr.name === "declare") {
|
||||
if (this.type === tt._class || this.type === tt.name || this.type === tt._function || this.type === tt._var) {
|
||||
return this.flow_parseDeclare(node)
|
||||
}
|
||||
} else if (this.type === tt.name) {
|
||||
if (expr.name === "interface") {
|
||||
return this.flow_parseInterface(node)
|
||||
} else if (expr.name === "type") {
|
||||
return this.flow_parseTypeAlias(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inner.call(this, node, expr)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("shouldParseExportDeclaration", function (inner) {
|
||||
return function () {
|
||||
return this.isContextual("type") || inner.call(this)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseParenItem", function (inner) {
|
||||
return function (node, start) {
|
||||
if (this.type === tt.colon) {
|
||||
var typeCastNode = this.startNodeAt(start)
|
||||
typeCastNode.expression = node
|
||||
typeCastNode.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
return this.finishNode(typeCastNode, "TypeCastExpression")
|
||||
} else {
|
||||
return node
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseClassId", function (inner) {
|
||||
return function (node, isStatement) {
|
||||
inner.call(this, node, isStatement)
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("readToken", function (inner) {
|
||||
return function(code) {
|
||||
if (this.inType && (code === 62 || code === 60)) {
|
||||
return this.finishOp(tt.relational, 1)
|
||||
} else {
|
||||
return inner.call(this, code)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("jsx_readToken", function (inner) {
|
||||
return function () {
|
||||
if (!this.inType) return inner.call(this)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseParenArrowList", function (inner) {
|
||||
return function (start, exprList, isAsync) {
|
||||
for (var i = 0; i < exprList.length; i++) {
|
||||
var listItem = exprList[i]
|
||||
if (listItem.type === "TypeCastExpression") {
|
||||
var expr = listItem.expression
|
||||
expr.typeAnnotation = listItem.typeAnnotation
|
||||
exprList[i] = expr
|
||||
}
|
||||
}
|
||||
return inner.call(this, start, exprList, isAsync)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseClassProperty", function (inner) {
|
||||
return function (node) {
|
||||
if (this.type === tt.colon) {
|
||||
node.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
}
|
||||
return inner.call(this, node)
|
||||
}
|
||||
})
|
||||
instance.extend("isClassProperty", function (inner) {
|
||||
return function () {
|
||||
return this.type === tt.colon || inner.call(this)
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseClassMethod", function (inner) {
|
||||
return function (classBody, method, isGenerator, isAsync) {
|
||||
var typeParameters
|
||||
if (this.isRelational("<")) {
|
||||
typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
}
|
||||
method.value = this.parseMethod(isGenerator, isAsync)
|
||||
method.value.typeParameters = typeParameters
|
||||
classBody.body.push(this.finishNode(method, "MethodDefinition"))
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseClassSuper", function (inner) {
|
||||
return function (node, isStatement) {
|
||||
inner.call(this, node, isStatement)
|
||||
if (node.superClass && this.isRelational("<")) {
|
||||
node.superTypeParameters = this.flow_parseTypeParameterInstantiation()
|
||||
}
|
||||
if (this.isContextual("implements")) {
|
||||
this.next()
|
||||
var implemented = node.implements = []
|
||||
do {
|
||||
var node = this.startNode()
|
||||
node.id = this.parseIdent()
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterInstantiation()
|
||||
} else {
|
||||
node.typeParameters = null
|
||||
}
|
||||
implemented.push(this.finishNode(node, "ClassImplements"))
|
||||
} while(this.eat(tt.comma))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseObjPropValue", function (inner) {
|
||||
return function (prop) {
|
||||
var typeParameters
|
||||
if (this.isRelational("<")) {
|
||||
typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
if (this.type !== tt.parenL) this.unexpected()
|
||||
}
|
||||
inner.apply(this, arguments)
|
||||
prop.value.typeParameters = typeParameters
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseAssignableListItemTypes", function (inner) {
|
||||
return function (param) {
|
||||
if (this.eat(tt.question)) {
|
||||
param.optional = true
|
||||
}
|
||||
if (this.type === tt.colon) {
|
||||
param.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
}
|
||||
this.finishNode(param, param.type)
|
||||
return param
|
||||
}
|
||||
})
|
||||
|
||||
instance.extend("parseImportSpecifiers", function (inner) {
|
||||
return function (node) {
|
||||
node.isType = false
|
||||
if (this.isContextual("type")) {
|
||||
var start = this.markPosition()
|
||||
var typeId = this.parseIdent()
|
||||
if ((this.type === tt.name && this.value !== "from") || this.type === tt.braceL || this.type === tt.star) {
|
||||
node.isType = true
|
||||
} else {
|
||||
node.specifiers.push(this.parseImportSpecifierDefault(typeId, start))
|
||||
if (this.isContextual("from")) return
|
||||
this.eat(tt.comma)
|
||||
}
|
||||
}
|
||||
inner.call(this, node)
|
||||
}
|
||||
})
|
||||
|
||||
// function foo<T>() {}
|
||||
instance.extend("parseFunctionParams", function (inner) {
|
||||
return function (node) {
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.flow_parseTypeParameterDeclaration()
|
||||
}
|
||||
inner.call(this, node)
|
||||
}
|
||||
})
|
||||
|
||||
// var foo: string = bar
|
||||
instance.extend("parseVarHead", function (inner) {
|
||||
return function (decl) {
|
||||
inner.call(this, decl)
|
||||
if (this.type === tt.colon) {
|
||||
decl.id.typeAnnotation = this.flow_parseTypeAnnotation()
|
||||
this.finishNode(decl.id, decl.id.type)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
658
src/acorn/plugins/jsx.js
Normal file
658
src/acorn/plugins/jsx.js
Normal file
@@ -0,0 +1,658 @@
|
||||
var acorn = require("../src/index")
|
||||
|
||||
var tt = acorn.tokTypes;
|
||||
var tc = acorn.tokContexts;
|
||||
|
||||
tc.j_oTag = new acorn.TokContext("<tag", false);
|
||||
tc.j_cTag = new acorn.TokContext("</tag", false);
|
||||
tc.j_expr = new acorn.TokContext("<tag>...</tag>", true, true);
|
||||
|
||||
tt.jsxName = new acorn.TokenType("jsxName");
|
||||
tt.jsxText = new acorn.TokenType("jsxText", {beforeExpr: true});
|
||||
tt.jsxTagStart = new acorn.TokenType("jsxTagStart");
|
||||
tt.jsxTagEnd = new acorn.TokenType("jsxTagEnd");
|
||||
|
||||
tt.jsxTagStart.updateContext = function() {
|
||||
this.context.push(tc.j_expr); // treat as beginning of JSX expression
|
||||
this.context.push(tc.j_oTag); // start opening tag context
|
||||
this.exprAllowed = false;
|
||||
};
|
||||
tt.jsxTagEnd.updateContext = function(prevType) {
|
||||
var out = this.context.pop();
|
||||
if (out === tc.j_oTag && prevType === tt.slash || out === tc.j_cTag) {
|
||||
this.context.pop();
|
||||
this.exprAllowed = this.curContext() === tc.j_expr;
|
||||
} else {
|
||||
this.exprAllowed = true;
|
||||
}
|
||||
};
|
||||
|
||||
var pp = acorn.Parser.prototype;
|
||||
|
||||
// Reads inline JSX contents token.
|
||||
|
||||
pp.jsx_readToken = function() {
|
||||
var out = "", chunkStart = this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, "Unterminated JSX contents");
|
||||
var ch = this.input.charCodeAt(this.pos);
|
||||
|
||||
switch (ch) {
|
||||
case 60: // '<'
|
||||
case 123: // '{'
|
||||
if (this.pos === this.start) {
|
||||
if (ch === 60 && this.exprAllowed) {
|
||||
++this.pos;
|
||||
return this.finishToken(tt.jsxTagStart);
|
||||
}
|
||||
return this.getTokenFromCode(ch);
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
return this.finishToken(tt.jsxText, out);
|
||||
|
||||
case 38: // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (acorn.isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
++this.pos;
|
||||
if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
|
||||
++this.pos;
|
||||
out += "\n";
|
||||
} else {
|
||||
out += String.fromCharCode(ch);
|
||||
}
|
||||
if (this.options.locations) {
|
||||
++this.curLine;
|
||||
this.lineStart = this.pos;
|
||||
}
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pp.jsx_readString = function(quote) {
|
||||
var out = "", chunkStart = ++this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, "Unterminated string constant");
|
||||
var ch = this.input.charCodeAt(this.pos);
|
||||
if (ch === quote) break;
|
||||
if (ch === 38) { // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos++);
|
||||
return this.finishToken(tt.string, out);
|
||||
};
|
||||
|
||||
var XHTMLEntities = {
|
||||
quot: '\u0022',
|
||||
amp: '&',
|
||||
apos: '\u0027',
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
nbsp: '\u00A0',
|
||||
iexcl: '\u00A1',
|
||||
cent: '\u00A2',
|
||||
pound: '\u00A3',
|
||||
curren: '\u00A4',
|
||||
yen: '\u00A5',
|
||||
brvbar: '\u00A6',
|
||||
sect: '\u00A7',
|
||||
uml: '\u00A8',
|
||||
copy: '\u00A9',
|
||||
ordf: '\u00AA',
|
||||
laquo: '\u00AB',
|
||||
not: '\u00AC',
|
||||
shy: '\u00AD',
|
||||
reg: '\u00AE',
|
||||
macr: '\u00AF',
|
||||
deg: '\u00B0',
|
||||
plusmn: '\u00B1',
|
||||
sup2: '\u00B2',
|
||||
sup3: '\u00B3',
|
||||
acute: '\u00B4',
|
||||
micro: '\u00B5',
|
||||
para: '\u00B6',
|
||||
middot: '\u00B7',
|
||||
cedil: '\u00B8',
|
||||
sup1: '\u00B9',
|
||||
ordm: '\u00BA',
|
||||
raquo: '\u00BB',
|
||||
frac14: '\u00BC',
|
||||
frac12: '\u00BD',
|
||||
frac34: '\u00BE',
|
||||
iquest: '\u00BF',
|
||||
Agrave: '\u00C0',
|
||||
Aacute: '\u00C1',
|
||||
Acirc: '\u00C2',
|
||||
Atilde: '\u00C3',
|
||||
Auml: '\u00C4',
|
||||
Aring: '\u00C5',
|
||||
AElig: '\u00C6',
|
||||
Ccedil: '\u00C7',
|
||||
Egrave: '\u00C8',
|
||||
Eacute: '\u00C9',
|
||||
Ecirc: '\u00CA',
|
||||
Euml: '\u00CB',
|
||||
Igrave: '\u00CC',
|
||||
Iacute: '\u00CD',
|
||||
Icirc: '\u00CE',
|
||||
Iuml: '\u00CF',
|
||||
ETH: '\u00D0',
|
||||
Ntilde: '\u00D1',
|
||||
Ograve: '\u00D2',
|
||||
Oacute: '\u00D3',
|
||||
Ocirc: '\u00D4',
|
||||
Otilde: '\u00D5',
|
||||
Ouml: '\u00D6',
|
||||
times: '\u00D7',
|
||||
Oslash: '\u00D8',
|
||||
Ugrave: '\u00D9',
|
||||
Uacute: '\u00DA',
|
||||
Ucirc: '\u00DB',
|
||||
Uuml: '\u00DC',
|
||||
Yacute: '\u00DD',
|
||||
THORN: '\u00DE',
|
||||
szlig: '\u00DF',
|
||||
agrave: '\u00E0',
|
||||
aacute: '\u00E1',
|
||||
acirc: '\u00E2',
|
||||
atilde: '\u00E3',
|
||||
auml: '\u00E4',
|
||||
aring: '\u00E5',
|
||||
aelig: '\u00E6',
|
||||
ccedil: '\u00E7',
|
||||
egrave: '\u00E8',
|
||||
eacute: '\u00E9',
|
||||
ecirc: '\u00EA',
|
||||
euml: '\u00EB',
|
||||
igrave: '\u00EC',
|
||||
iacute: '\u00ED',
|
||||
icirc: '\u00EE',
|
||||
iuml: '\u00EF',
|
||||
eth: '\u00F0',
|
||||
ntilde: '\u00F1',
|
||||
ograve: '\u00F2',
|
||||
oacute: '\u00F3',
|
||||
ocirc: '\u00F4',
|
||||
otilde: '\u00F5',
|
||||
ouml: '\u00F6',
|
||||
divide: '\u00F7',
|
||||
oslash: '\u00F8',
|
||||
ugrave: '\u00F9',
|
||||
uacute: '\u00FA',
|
||||
ucirc: '\u00FB',
|
||||
uuml: '\u00FC',
|
||||
yacute: '\u00FD',
|
||||
thorn: '\u00FE',
|
||||
yuml: '\u00FF',
|
||||
OElig: '\u0152',
|
||||
oelig: '\u0153',
|
||||
Scaron: '\u0160',
|
||||
scaron: '\u0161',
|
||||
Yuml: '\u0178',
|
||||
fnof: '\u0192',
|
||||
circ: '\u02C6',
|
||||
tilde: '\u02DC',
|
||||
Alpha: '\u0391',
|
||||
Beta: '\u0392',
|
||||
Gamma: '\u0393',
|
||||
Delta: '\u0394',
|
||||
Epsilon: '\u0395',
|
||||
Zeta: '\u0396',
|
||||
Eta: '\u0397',
|
||||
Theta: '\u0398',
|
||||
Iota: '\u0399',
|
||||
Kappa: '\u039A',
|
||||
Lambda: '\u039B',
|
||||
Mu: '\u039C',
|
||||
Nu: '\u039D',
|
||||
Xi: '\u039E',
|
||||
Omicron: '\u039F',
|
||||
Pi: '\u03A0',
|
||||
Rho: '\u03A1',
|
||||
Sigma: '\u03A3',
|
||||
Tau: '\u03A4',
|
||||
Upsilon: '\u03A5',
|
||||
Phi: '\u03A6',
|
||||
Chi: '\u03A7',
|
||||
Psi: '\u03A8',
|
||||
Omega: '\u03A9',
|
||||
alpha: '\u03B1',
|
||||
beta: '\u03B2',
|
||||
gamma: '\u03B3',
|
||||
delta: '\u03B4',
|
||||
epsilon: '\u03B5',
|
||||
zeta: '\u03B6',
|
||||
eta: '\u03B7',
|
||||
theta: '\u03B8',
|
||||
iota: '\u03B9',
|
||||
kappa: '\u03BA',
|
||||
lambda: '\u03BB',
|
||||
mu: '\u03BC',
|
||||
nu: '\u03BD',
|
||||
xi: '\u03BE',
|
||||
omicron: '\u03BF',
|
||||
pi: '\u03C0',
|
||||
rho: '\u03C1',
|
||||
sigmaf: '\u03C2',
|
||||
sigma: '\u03C3',
|
||||
tau: '\u03C4',
|
||||
upsilon: '\u03C5',
|
||||
phi: '\u03C6',
|
||||
chi: '\u03C7',
|
||||
psi: '\u03C8',
|
||||
omega: '\u03C9',
|
||||
thetasym: '\u03D1',
|
||||
upsih: '\u03D2',
|
||||
piv: '\u03D6',
|
||||
ensp: '\u2002',
|
||||
emsp: '\u2003',
|
||||
thinsp: '\u2009',
|
||||
zwnj: '\u200C',
|
||||
zwj: '\u200D',
|
||||
lrm: '\u200E',
|
||||
rlm: '\u200F',
|
||||
ndash: '\u2013',
|
||||
mdash: '\u2014',
|
||||
lsquo: '\u2018',
|
||||
rsquo: '\u2019',
|
||||
sbquo: '\u201A',
|
||||
ldquo: '\u201C',
|
||||
rdquo: '\u201D',
|
||||
bdquo: '\u201E',
|
||||
dagger: '\u2020',
|
||||
Dagger: '\u2021',
|
||||
bull: '\u2022',
|
||||
hellip: '\u2026',
|
||||
permil: '\u2030',
|
||||
prime: '\u2032',
|
||||
Prime: '\u2033',
|
||||
lsaquo: '\u2039',
|
||||
rsaquo: '\u203A',
|
||||
oline: '\u203E',
|
||||
frasl: '\u2044',
|
||||
euro: '\u20AC',
|
||||
image: '\u2111',
|
||||
weierp: '\u2118',
|
||||
real: '\u211C',
|
||||
trade: '\u2122',
|
||||
alefsym: '\u2135',
|
||||
larr: '\u2190',
|
||||
uarr: '\u2191',
|
||||
rarr: '\u2192',
|
||||
darr: '\u2193',
|
||||
harr: '\u2194',
|
||||
crarr: '\u21B5',
|
||||
lArr: '\u21D0',
|
||||
uArr: '\u21D1',
|
||||
rArr: '\u21D2',
|
||||
dArr: '\u21D3',
|
||||
hArr: '\u21D4',
|
||||
forall: '\u2200',
|
||||
part: '\u2202',
|
||||
exist: '\u2203',
|
||||
empty: '\u2205',
|
||||
nabla: '\u2207',
|
||||
isin: '\u2208',
|
||||
notin: '\u2209',
|
||||
ni: '\u220B',
|
||||
prod: '\u220F',
|
||||
sum: '\u2211',
|
||||
minus: '\u2212',
|
||||
lowast: '\u2217',
|
||||
radic: '\u221A',
|
||||
prop: '\u221D',
|
||||
infin: '\u221E',
|
||||
ang: '\u2220',
|
||||
and: '\u2227',
|
||||
or: '\u2228',
|
||||
cap: '\u2229',
|
||||
cup: '\u222A',
|
||||
'int': '\u222B',
|
||||
there4: '\u2234',
|
||||
sim: '\u223C',
|
||||
cong: '\u2245',
|
||||
asymp: '\u2248',
|
||||
ne: '\u2260',
|
||||
equiv: '\u2261',
|
||||
le: '\u2264',
|
||||
ge: '\u2265',
|
||||
sub: '\u2282',
|
||||
sup: '\u2283',
|
||||
nsub: '\u2284',
|
||||
sube: '\u2286',
|
||||
supe: '\u2287',
|
||||
oplus: '\u2295',
|
||||
otimes: '\u2297',
|
||||
perp: '\u22A5',
|
||||
sdot: '\u22C5',
|
||||
lceil: '\u2308',
|
||||
rceil: '\u2309',
|
||||
lfloor: '\u230A',
|
||||
rfloor: '\u230B',
|
||||
lang: '\u2329',
|
||||
rang: '\u232A',
|
||||
loz: '\u25CA',
|
||||
spades: '\u2660',
|
||||
clubs: '\u2663',
|
||||
hearts: '\u2665',
|
||||
diams: '\u2666'
|
||||
};
|
||||
|
||||
var hexNumber = /^[\da-fA-F]+$/;
|
||||
var decimalNumber = /^\d+$/;
|
||||
|
||||
pp.jsx_readEntity = function() {
|
||||
var str = "", count = 0, entity;
|
||||
var ch = this.input[this.pos];
|
||||
if (ch !== "&")
|
||||
this.raise(this.pos, "Entity must start with an ampersand");
|
||||
var startPos = ++this.pos;
|
||||
while (this.pos < this.input.length && count++ < 10) {
|
||||
ch = this.input[this.pos++];
|
||||
if (ch === ";") {
|
||||
if (str[0] === "#") {
|
||||
if (str[1] === "x") {
|
||||
str = str.substr(2);
|
||||
if (hexNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 16));
|
||||
} else {
|
||||
str = str.substr(1);
|
||||
if (decimalNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 10));
|
||||
}
|
||||
} else {
|
||||
entity = XHTMLEntities[str];
|
||||
}
|
||||
break;
|
||||
}
|
||||
str += ch;
|
||||
}
|
||||
if (!entity) {
|
||||
this.pos = startPos;
|
||||
return "&";
|
||||
}
|
||||
return entity;
|
||||
};
|
||||
|
||||
|
||||
// Read a JSX identifier (valid tag or attribute name).
|
||||
//
|
||||
// Optimized version since JSX identifiers can't contain
|
||||
// escape characters and so can be read as single slice.
|
||||
// Also assumes that first character was already checked
|
||||
// by isIdentifierStart in readToken.
|
||||
|
||||
pp.jsx_readWord = function() {
|
||||
var ch, start = this.pos;
|
||||
do {
|
||||
ch = this.input.charCodeAt(++this.pos);
|
||||
} while (acorn.isIdentifierChar(ch) || ch === 45); // '-'
|
||||
return this.finishToken(tt.jsxName, this.input.slice(start, this.pos));
|
||||
};
|
||||
|
||||
// Transforms JSX element name to string.
|
||||
|
||||
function getQualifiedJSXName(object) {
|
||||
if (object.type === "JSXIdentifier")
|
||||
return object.name;
|
||||
|
||||
if (object.type === "JSXNamespacedName")
|
||||
return object.namespace.name + ':' + object.name.name;
|
||||
|
||||
if (object.type === "JSXMemberExpression")
|
||||
return getQualifiedJSXName(object.object) + '.' +
|
||||
getQualifiedJSXName(object.property);
|
||||
}
|
||||
|
||||
// Parse next token as JSX identifier
|
||||
|
||||
pp.jsx_parseIdentifier = function() {
|
||||
var node = this.startNode();
|
||||
if (this.type === tt.jsxName)
|
||||
node.name = this.value;
|
||||
else if (this.type.keyword)
|
||||
node.name = this.type.keyword;
|
||||
else
|
||||
this.unexpected();
|
||||
this.next();
|
||||
return this.finishNode(node, "JSXIdentifier");
|
||||
};
|
||||
|
||||
// Parse namespaced identifier.
|
||||
|
||||
pp.jsx_parseNamespacedName = function() {
|
||||
var start = this.markPosition();
|
||||
var name = this.jsx_parseIdentifier();
|
||||
if (!this.eat(tt.colon)) return name;
|
||||
var node = this.startNodeAt(start);
|
||||
node.namespace = name;
|
||||
node.name = this.jsx_parseIdentifier();
|
||||
return this.finishNode(node, "JSXNamespacedName");
|
||||
};
|
||||
|
||||
// Parses element name in any form - namespaced, member
|
||||
// or single identifier.
|
||||
|
||||
pp.jsx_parseElementName = function() {
|
||||
var start = this.markPosition();
|
||||
var node = this.jsx_parseNamespacedName();
|
||||
while (this.eat(tt.dot)) {
|
||||
var newNode = this.startNodeAt(start);
|
||||
newNode.object = node;
|
||||
newNode.property = this.jsx_parseIdentifier();
|
||||
node = this.finishNode(newNode, "JSXMemberExpression");
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
// Parses any type of JSX attribute value.
|
||||
|
||||
pp.jsx_parseAttributeValue = function() {
|
||||
switch (this.type) {
|
||||
case tt.braceL:
|
||||
var node = this.jsx_parseExpressionContainer();
|
||||
if (node.expression.type === "JSXEmptyExpression")
|
||||
this.raise(node.start, "JSX attributes must only be assigned a non-empty expression");
|
||||
return node;
|
||||
|
||||
case tt.jsxTagStart:
|
||||
case tt.string:
|
||||
return this.parseExprAtom();
|
||||
|
||||
default:
|
||||
this.raise(this.start, "JSX value should be either an expression or a quoted JSX text");
|
||||
}
|
||||
};
|
||||
|
||||
// JSXEmptyExpression is unique type since it doesn't actually parse anything,
|
||||
// and so it should start at the end of last read token (left brace) and finish
|
||||
// at the beginning of the next one (right brace).
|
||||
|
||||
pp.jsx_parseEmptyExpression = function() {
|
||||
var tmp = this.start;
|
||||
this.start = this.lastTokEnd;
|
||||
this.lastTokEnd = tmp;
|
||||
|
||||
tmp = this.startLoc;
|
||||
this.startLoc = this.lastTokEndLoc;
|
||||
this.lastTokEndLoc = tmp;
|
||||
|
||||
return this.finishNode(this.startNode(), "JSXEmptyExpression");
|
||||
};
|
||||
|
||||
// Parses JSX expression enclosed into curly brackets.
|
||||
|
||||
|
||||
pp.jsx_parseExpressionContainer = function() {
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
node.expression = this.type === tt.braceR
|
||||
? this.jsx_parseEmptyExpression()
|
||||
: this.parseExpression();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, "JSXExpressionContainer");
|
||||
};
|
||||
|
||||
// Parses following JSX attribute name-value pair.
|
||||
|
||||
pp.jsx_parseAttribute = function() {
|
||||
var node = this.startNode();
|
||||
if (this.eat(tt.braceL)) {
|
||||
this.expect(tt.ellipsis);
|
||||
node.argument = this.parseMaybeAssign();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, "JSXSpreadAttribute");
|
||||
}
|
||||
node.name = this.jsx_parseNamespacedName();
|
||||
node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
|
||||
return this.finishNode(node, "JSXAttribute");
|
||||
};
|
||||
|
||||
// Parses JSX opening tag starting after '<'.
|
||||
|
||||
pp.jsx_parseOpeningElementAt = function(start) {
|
||||
var node = this.startNodeAt(start);
|
||||
node.attributes = [];
|
||||
node.name = this.jsx_parseElementName();
|
||||
while (this.type !== tt.slash && this.type !== tt.jsxTagEnd)
|
||||
node.attributes.push(this.jsx_parseAttribute());
|
||||
node.selfClosing = this.eat(tt.slash);
|
||||
this.expect(tt.jsxTagEnd);
|
||||
return this.finishNode(node, "JSXOpeningElement");
|
||||
};
|
||||
|
||||
// Parses JSX closing tag starting after '</'.
|
||||
|
||||
pp.jsx_parseClosingElementAt = function(start) {
|
||||
var node = this.startNodeAt(start);
|
||||
node.name = this.jsx_parseElementName();
|
||||
this.expect(tt.jsxTagEnd);
|
||||
return this.finishNode(node, "JSXClosingElement");
|
||||
};
|
||||
|
||||
// Parses entire JSX element, including it's opening tag
|
||||
// (starting after '<'), attributes, contents and closing tag.
|
||||
|
||||
pp.jsx_parseElementAt = function(start) {
|
||||
var node = this.startNodeAt(start);
|
||||
var children = [];
|
||||
var openingElement = this.jsx_parseOpeningElementAt(start);
|
||||
var closingElement = null;
|
||||
|
||||
if (!openingElement.selfClosing) {
|
||||
contents: for (;;) {
|
||||
switch (this.type) {
|
||||
case tt.jsxTagStart:
|
||||
start = this.markPosition();
|
||||
this.next();
|
||||
if (this.eat(tt.slash)) {
|
||||
closingElement = this.jsx_parseClosingElementAt(start);
|
||||
break contents;
|
||||
}
|
||||
children.push(this.jsx_parseElementAt(start));
|
||||
break;
|
||||
|
||||
case tt.jsxText:
|
||||
children.push(this.parseExprAtom());
|
||||
break;
|
||||
|
||||
case tt.braceL:
|
||||
children.push(this.jsx_parseExpressionContainer());
|
||||
break;
|
||||
|
||||
default:
|
||||
this.unexpected();
|
||||
}
|
||||
}
|
||||
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name))
|
||||
this.raise(
|
||||
closingElement.start,
|
||||
"Expected corresponding JSX closing tag for <" + getQualifiedJSXName(openingElement.name) + ">");
|
||||
}
|
||||
|
||||
node.openingElement = openingElement;
|
||||
node.closingElement = closingElement;
|
||||
node.children = children;
|
||||
return this.finishNode(node, "JSXElement");
|
||||
};
|
||||
|
||||
// Parses entire JSX element from current position.
|
||||
|
||||
pp.jsx_parseElement = function() {
|
||||
var start = this.markPosition();
|
||||
this.next();
|
||||
return this.jsx_parseElementAt(start);
|
||||
};
|
||||
|
||||
acorn.plugins.jsx = function(instance) {
|
||||
instance.extend("parseExprAtom", function(inner) {
|
||||
return function(refShortHandDefaultPos) {
|
||||
if (this.type === tt.jsxText)
|
||||
return this.parseLiteral(this.value);
|
||||
else if (this.type === tt.jsxTagStart)
|
||||
return this.jsx_parseElement();
|
||||
else
|
||||
return inner.call(this, refShortHandDefaultPos);
|
||||
};
|
||||
});
|
||||
|
||||
instance.extend("readToken", function(inner) {
|
||||
return function(code) {
|
||||
var context = this.curContext();
|
||||
|
||||
if (context === tc.j_expr) return this.jsx_readToken();
|
||||
|
||||
if (context === tc.j_oTag || context === tc.j_cTag) {
|
||||
if (acorn.isIdentifierStart(code)) return this.jsx_readWord();
|
||||
|
||||
if (code == 62) {
|
||||
++this.pos;
|
||||
return this.finishToken(tt.jsxTagEnd);
|
||||
}
|
||||
|
||||
if ((code === 34 || code === 39) && context == tc.j_oTag)
|
||||
return this.jsx_readString(code);
|
||||
}
|
||||
|
||||
if (code === 60 && this.exprAllowed) {
|
||||
++this.pos;
|
||||
return this.finishToken(tt.jsxTagStart);
|
||||
}
|
||||
return inner.call(this, code);
|
||||
};
|
||||
});
|
||||
|
||||
instance.extend("updateContext", function(inner) {
|
||||
return function(prevType) {
|
||||
if (this.type == tt.braceL) {
|
||||
var curContext = this.curContext();
|
||||
if (curContext == tc.j_oTag) this.context.push(tc.b_expr);
|
||||
else if (curContext == tc.j_expr) this.context.push(tc.b_tmpl);
|
||||
else inner.call(this, prevType);
|
||||
this.exprAllowed = true;
|
||||
} else if (this.type === tt.slash && prevType === tt.jsxTagStart) {
|
||||
this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
|
||||
this.context.push(tc.j_cTag); // reconsider as closing tag context
|
||||
this.exprAllowed = false;
|
||||
} else {
|
||||
return inner.call(this, prevType);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
783
src/acorn/src/expression.js
Executable file
783
src/acorn/src/expression.js
Executable file
@@ -0,0 +1,783 @@
|
||||
// A recursive descent parser operates by defining functions for all
|
||||
// syntactic elements, and recursively calling those, each function
|
||||
// advancing the input stream and returning an AST node. Precedence
|
||||
// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
|
||||
// instead of `(!x)[1]` is handled by the fact that the parser
|
||||
// function that parses unary prefix operators is called first, and
|
||||
// in turn calls the function that parses `[]` subscripts — that
|
||||
// way, it'll receive the node for `x[1]` already parsed, and wraps
|
||||
// *that* in the unary operator node.
|
||||
//
|
||||
// Acorn uses an [operator precedence parser][opp] to handle binary
|
||||
// operator precedence, because it is much more compact than using
|
||||
// the technique outlined above, which uses different, nesting
|
||||
// functions to specify precedence, for all of the ten binary
|
||||
// precedence levels that JavaScript defines.
|
||||
//
|
||||
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
|
||||
|
||||
import {types as tt} from "./tokentype"
|
||||
import {Parser} from "./state"
|
||||
import {reservedWords} from "./identifier"
|
||||
import {has} from "./util"
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
// Check if property name clashes with already added.
|
||||
// Object/class getters and setters are not allowed to clash —
|
||||
// either with each other or with an init property — and in
|
||||
// strict mode, init properties are also not allowed to be repeated.
|
||||
|
||||
pp.checkPropClash = function(prop, propHash) {
|
||||
if (this.options.ecmaVersion >= 6) return
|
||||
let key = prop.key, name
|
||||
switch (key.type) {
|
||||
case "Identifier": name = key.name; break
|
||||
case "Literal": name = String(key.value); break
|
||||
default: return
|
||||
}
|
||||
let kind = prop.kind || "init", other
|
||||
if (has(propHash, name)) {
|
||||
other = propHash[name]
|
||||
let isGetSet = kind !== "init"
|
||||
if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
|
||||
this.raise(key.start, "Redefinition of property")
|
||||
} else {
|
||||
other = propHash[name] = {
|
||||
init: false,
|
||||
get: false,
|
||||
set: false
|
||||
}
|
||||
}
|
||||
other[kind] = true
|
||||
}
|
||||
|
||||
// ### Expression parsing
|
||||
|
||||
// These nest, from the most general expression type at the top to
|
||||
// 'atomic', nondivisible expression types at the bottom. Most of
|
||||
// the functions will simply let the function(s) below them parse,
|
||||
// and, *if* the syntactic construct they handle is present, wrap
|
||||
// the AST node that the inner parser gave them in another node.
|
||||
|
||||
// Parse a full expression. The optional arguments are used to
|
||||
// forbid the `in` operator (in for loops initalization expressions)
|
||||
// and provide reference for storing '=' operator inside shorthand
|
||||
// property assignment in contexts where both object expression
|
||||
// and object pattern might appear (so it's possible to raise
|
||||
// delayed syntax error at correct position).
|
||||
|
||||
pp.parseExpression = function(noIn, refShorthandDefaultPos) {
|
||||
let start = this.markPosition()
|
||||
let expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos)
|
||||
if (this.type === tt.comma) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.expressions = [expr]
|
||||
while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos))
|
||||
return this.finishNode(node, "SequenceExpression")
|
||||
}
|
||||
return expr
|
||||
}
|
||||
|
||||
// Parse an assignment expression. This includes applications of
|
||||
// operators like `+=`.
|
||||
|
||||
pp.parseMaybeAssign = function(noIn, refShorthandDefaultPos, afterLeftParse) {
|
||||
if (this.type == tt._yield && this.inGenerator) return this.parseYield()
|
||||
|
||||
let failOnShorthandAssign
|
||||
if (!refShorthandDefaultPos) {
|
||||
refShorthandDefaultPos = {start: 0}
|
||||
failOnShorthandAssign = true
|
||||
} else {
|
||||
failOnShorthandAssign = false
|
||||
}
|
||||
let start = this.markPosition()
|
||||
if (this.type == tt.parenL || this.type == tt.name)
|
||||
this.potentialArrowAt = this.start
|
||||
let left = this.parseMaybeConditional(noIn, refShorthandDefaultPos)
|
||||
if (afterLeftParse) left = afterLeftParse.call(this, left, start)
|
||||
if (this.type.isAssign) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.operator = this.value
|
||||
node.left = this.type === tt.eq ? this.toAssignable(left) : left
|
||||
refShorthandDefaultPos.start = 0 // reset because shorthand default was used correctly
|
||||
this.checkLVal(left)
|
||||
if (left.parenthesizedExpression) {
|
||||
let errorMsg
|
||||
if (left.type === "ObjectPattern") {
|
||||
errorMsg = "`({a}) = 0` use `({a} = 0)`"
|
||||
} else if (left.type === "ArrayPattern") {
|
||||
errorMsg = "`([a]) = 0` use `([a] = 0)`"
|
||||
}
|
||||
if (errorMsg) {
|
||||
this.raise(left.start, `You're trying to assign to a parenthesized expression, eg. instead of ${errorMsg}`)
|
||||
}
|
||||
}
|
||||
this.next()
|
||||
node.right = this.parseMaybeAssign(noIn)
|
||||
return this.finishNode(node, "AssignmentExpression")
|
||||
} else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
|
||||
this.unexpected(refShorthandDefaultPos.start)
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
// Parse a ternary conditional (`?:`) operator.
|
||||
|
||||
pp.parseMaybeConditional = function(noIn, refShorthandDefaultPos) {
|
||||
let start = this.markPosition()
|
||||
let expr = this.parseExprOps(noIn, refShorthandDefaultPos)
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr
|
||||
if (this.eat(tt.question)) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.test = expr
|
||||
node.consequent = this.parseMaybeAssign()
|
||||
this.expect(tt.colon)
|
||||
node.alternate = this.parseMaybeAssign(noIn)
|
||||
return this.finishNode(node, "ConditionalExpression")
|
||||
}
|
||||
return expr
|
||||
}
|
||||
|
||||
// Start the precedence parser.
|
||||
|
||||
pp.parseExprOps = function(noIn, refShorthandDefaultPos) {
|
||||
let start = this.markPosition()
|
||||
let expr = this.parseMaybeUnary(refShorthandDefaultPos)
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr
|
||||
return this.parseExprOp(expr, start, -1, noIn)
|
||||
}
|
||||
|
||||
// Parse binary operators with the operator precedence parsing
|
||||
// algorithm. `left` is the left-hand side of the operator.
|
||||
// `minPrec` provides context that allows the function to stop and
|
||||
// defer further parser to one of its callers when it encounters an
|
||||
// operator that has a lower precedence than the set it is parsing.
|
||||
|
||||
pp.parseExprOp = function(left, leftStart, minPrec, noIn) {
|
||||
let prec = this.type.binop
|
||||
if (prec != null && (!noIn || this.type !== tt._in)) {
|
||||
if (prec > minPrec) {
|
||||
let node = this.startNodeAt(leftStart)
|
||||
node.left = left
|
||||
node.operator = this.value
|
||||
let op = this.type
|
||||
this.next()
|
||||
let start = this.markPosition()
|
||||
node.right = this.parseExprOp(this.parseMaybeUnary(), start, op.rightAssociative ? (prec - 1) : prec, noIn)
|
||||
this.finishNode(node, (op === tt.logicalOR || op === tt.logicalAND) ? "LogicalExpression" : "BinaryExpression")
|
||||
return this.parseExprOp(node, leftStart, minPrec, noIn)
|
||||
}
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
// Parse unary operators, both prefix and postfix.
|
||||
|
||||
pp.parseMaybeUnary = function(refShorthandDefaultPos) {
|
||||
if (this.type.prefix) {
|
||||
let node = this.startNode(), update = this.type === tt.incDec
|
||||
node.operator = this.value
|
||||
node.prefix = true
|
||||
this.next()
|
||||
node.argument = this.parseMaybeUnary()
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start)
|
||||
if (update) this.checkLVal(node.argument)
|
||||
else if (this.strict && node.operator === "delete" &&
|
||||
node.argument.type === "Identifier")
|
||||
this.raise(node.start, "Deleting local variable in strict mode")
|
||||
return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression")
|
||||
}
|
||||
let start = this.markPosition()
|
||||
let expr = this.parseExprSubscripts(refShorthandDefaultPos)
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr
|
||||
while (this.type.postfix && !this.canInsertSemicolon()) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.operator = this.value
|
||||
node.prefix = false
|
||||
node.argument = expr
|
||||
this.checkLVal(expr)
|
||||
this.next()
|
||||
expr = this.finishNode(node, "UpdateExpression")
|
||||
}
|
||||
return expr
|
||||
}
|
||||
|
||||
// Parse call, dot, and `[]`-subscript expressions.
|
||||
|
||||
pp.parseExprSubscripts = function(refShorthandDefaultPos) {
|
||||
let start = this.markPosition()
|
||||
let expr = this.parseExprAtom(refShorthandDefaultPos)
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr
|
||||
return this.parseSubscripts(expr, start)
|
||||
}
|
||||
|
||||
pp.parseSubscripts = function(base, start, noCalls) {
|
||||
if (this.eat(tt.dot)) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.object = base
|
||||
node.property = this.parseIdent(true)
|
||||
node.computed = false
|
||||
return this.parseSubscripts(this.finishNode(node, "MemberExpression"), start, noCalls)
|
||||
} else if (this.eat(tt.bracketL)) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.object = base
|
||||
node.property = this.parseExpression()
|
||||
node.computed = true
|
||||
this.expect(tt.bracketR)
|
||||
return this.parseSubscripts(this.finishNode(node, "MemberExpression"), start, noCalls)
|
||||
} else if (!noCalls && this.eat(tt.parenL)) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.callee = base
|
||||
node.arguments = this.parseExprList(tt.parenR, this.options.features["es7.trailingFunctionCommas"])
|
||||
return this.parseSubscripts(this.finishNode(node, "CallExpression"), start, noCalls)
|
||||
} else if (this.type === tt.backQuote) {
|
||||
let node = this.startNodeAt(start)
|
||||
node.tag = base
|
||||
node.quasi = this.parseTemplate()
|
||||
return this.parseSubscripts(this.finishNode(node, "TaggedTemplateExpression"), start, noCalls)
|
||||
} return base
|
||||
}
|
||||
|
||||
// Parse an atomic expression — either a single token that is an
|
||||
// expression, an expression started by a keyword like `function` or
|
||||
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
|
||||
// or `{}`.
|
||||
|
||||
pp.parseExprAtom = function(refShorthandDefaultPos) {
|
||||
let node, canBeArrow = this.potentialArrowAt == this.start
|
||||
switch (this.type) {
|
||||
case tt._this:
|
||||
case tt._super:
|
||||
let type = this.type === tt._this ? "ThisExpression" : "Super"
|
||||
node = this.startNode()
|
||||
this.next()
|
||||
return this.finishNode(node, type)
|
||||
|
||||
case tt._yield:
|
||||
if (this.inGenerator) this.unexpected()
|
||||
|
||||
case tt._do:
|
||||
if (this.options.features["es7.doExpressions"]) {
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
node.body = this.parseBlock()
|
||||
return this.finishNode(node, "DoExpression")
|
||||
}
|
||||
|
||||
case tt.name:
|
||||
let start = this.markPosition()
|
||||
node = this.startNode()
|
||||
let id = this.parseIdent(this.type !== tt.name)
|
||||
|
||||
//
|
||||
if (this.options.features["es7.asyncFunctions"]) {
|
||||
// async functions!
|
||||
if (id.name === "async") {
|
||||
// arrow functions
|
||||
if (this.type === tt.parenL) {
|
||||
let expr = this.parseParenAndDistinguishExpression(start, true, true)
|
||||
if (expr && expr.type === "ArrowFunctionExpression") {
|
||||
return expr
|
||||
} else {
|
||||
node.callee = id
|
||||
if (!expr) {
|
||||
node.arguments = []
|
||||
} else if (expr.type === "SequenceExpression") {
|
||||
node.arguments = expr.expressions
|
||||
} else {
|
||||
node.arguments = [expr]
|
||||
}
|
||||
return this.parseSubscripts(this.finishNode(node, "CallExpression"), start)
|
||||
}
|
||||
} else if (this.type === tt.name) {
|
||||
id = this.parseIdent()
|
||||
this.expect(tt.arrow)
|
||||
return this.parseArrowExpression(node, [id], true)
|
||||
}
|
||||
|
||||
// normal functions
|
||||
if (this.type === tt._function && !this.canInsertSemicolon()) {
|
||||
this.next()
|
||||
return this.parseFunction(node, false, false, true)
|
||||
}
|
||||
} else if (id.name === "await") {
|
||||
if (this.inAsync) return this.parseAwait(node)
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow))
|
||||
return this.parseArrowExpression(this.startNodeAt(start), [id])
|
||||
return id
|
||||
|
||||
case tt.regexp:
|
||||
let value = this.value
|
||||
node = this.parseLiteral(value.value)
|
||||
node.regex = {pattern: value.pattern, flags: value.flags}
|
||||
return node
|
||||
|
||||
case tt.num: case tt.string:
|
||||
return this.parseLiteral(this.value)
|
||||
|
||||
case tt._null: case tt._true: case tt._false:
|
||||
node = this.startNode()
|
||||
node.value = this.type === tt._null ? null : this.type === tt._true
|
||||
node.raw = this.type.keyword
|
||||
this.next()
|
||||
return this.finishNode(node, "Literal")
|
||||
|
||||
case tt.parenL:
|
||||
return this.parseParenAndDistinguishExpression(null, null, canBeArrow)
|
||||
|
||||
case tt.bracketL:
|
||||
node = this.startNode()
|
||||
this.next()
|
||||
// check whether this is array comprehension or regular array
|
||||
if ((this.options.ecmaVersion >= 7 || this.options.features["es7.comprehensions"]) && this.type === tt._for) {
|
||||
return this.parseComprehension(node, false)
|
||||
}
|
||||
node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos)
|
||||
return this.finishNode(node, "ArrayExpression")
|
||||
|
||||
case tt.braceL:
|
||||
return this.parseObj(false, refShorthandDefaultPos)
|
||||
|
||||
case tt._function:
|
||||
node = this.startNode()
|
||||
this.next()
|
||||
return this.parseFunction(node, false)
|
||||
|
||||
case tt.at:
|
||||
this.parseDecorators()
|
||||
|
||||
case tt._class:
|
||||
node = this.startNode()
|
||||
this.takeDecorators(node)
|
||||
return this.parseClass(node, false)
|
||||
|
||||
case tt._new:
|
||||
return this.parseNew()
|
||||
|
||||
case tt.backQuote:
|
||||
return this.parseTemplate()
|
||||
|
||||
default:
|
||||
this.unexpected()
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseLiteral = function(value) {
|
||||
let node = this.startNode()
|
||||
node.value = value
|
||||
node.raw = this.input.slice(this.start, this.end)
|
||||
this.next()
|
||||
return this.finishNode(node, "Literal")
|
||||
}
|
||||
|
||||
pp.parseParenExpression = function() {
|
||||
this.expect(tt.parenL)
|
||||
let val = this.parseExpression()
|
||||
this.expect(tt.parenR)
|
||||
return val
|
||||
}
|
||||
|
||||
pp.parseParenAndDistinguishExpression = function(start, isAsync, canBeArrow) {
|
||||
start = start || this.markPosition()
|
||||
let val
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
this.next()
|
||||
|
||||
if ((this.options.features["es7.comprehensions"] || this.options.ecmaVersion >= 7) && this.type === tt._for) {
|
||||
return this.parseComprehension(this.startNodeAt(start), true)
|
||||
}
|
||||
|
||||
let innerStart = this.markPosition(), exprList = [], first = true
|
||||
let refShorthandDefaultPos = {start: 0}, spreadStart, innerParenStart
|
||||
while (this.type !== tt.parenR) {
|
||||
first ? first = false : this.expect(tt.comma)
|
||||
if (this.type === tt.ellipsis) {
|
||||
let spreadNodeStart = this.markPosition()
|
||||
spreadStart = this.start
|
||||
exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStart))
|
||||
break
|
||||
} else {
|
||||
if (this.type === tt.parenL && !innerParenStart) {
|
||||
innerParenStart = this.start
|
||||
}
|
||||
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem))
|
||||
}
|
||||
}
|
||||
let innerEnd = this.markPosition()
|
||||
this.expect(tt.parenR)
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||
if (innerParenStart) this.unexpected(innerParenStart)
|
||||
return this.parseParenArrowList(start, exprList, isAsync)
|
||||
}
|
||||
|
||||
if (!exprList.length) {
|
||||
if (isAsync) {
|
||||
return
|
||||
} else {
|
||||
this.unexpected(this.lastTokStart)
|
||||
}
|
||||
}
|
||||
if (spreadStart) this.unexpected(spreadStart)
|
||||
if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start)
|
||||
|
||||
if (exprList.length > 1) {
|
||||
val = this.startNodeAt(innerStart)
|
||||
val.expressions = exprList
|
||||
this.finishNodeAt(val, "SequenceExpression", innerEnd)
|
||||
} else {
|
||||
val = exprList[0]
|
||||
}
|
||||
} else {
|
||||
val = this.parseParenExpression()
|
||||
}
|
||||
|
||||
if (this.options.preserveParens) {
|
||||
let par = this.startNodeAt(start)
|
||||
par.expression = val
|
||||
return this.finishNode(par, "ParenthesizedExpression")
|
||||
} else {
|
||||
val.parenthesizedExpression = true
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseParenArrowList = function(start, exprList, isAsync) {
|
||||
return this.parseArrowExpression(this.startNodeAt(start), exprList, isAsync)
|
||||
}
|
||||
|
||||
pp.parseParenItem = function(node, start) {
|
||||
return node
|
||||
}
|
||||
|
||||
// New's precedence is slightly tricky. It must allow its argument
|
||||
// to be a `[]` or dot subscript expression, but not a call — at
|
||||
// least, not without wrapping it in parentheses. Thus, it uses the
|
||||
|
||||
const empty = []
|
||||
|
||||
pp.parseNew = function() {
|
||||
let node = this.startNode()
|
||||
let meta = this.parseIdent(true)
|
||||
if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {
|
||||
node.meta = meta
|
||||
node.property = this.parseIdent(true)
|
||||
if (node.property.name !== "target")
|
||||
this.raise(node.property.start, "The only valid meta property for new is new.target")
|
||||
return this.finishNode(node, "MetaProperty")
|
||||
}
|
||||
let start = this.markPosition()
|
||||
node.callee = this.parseSubscripts(this.parseExprAtom(), start, true)
|
||||
if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, false)
|
||||
else node.arguments = empty
|
||||
return this.finishNode(node, "NewExpression")
|
||||
}
|
||||
|
||||
// Parse template expression.
|
||||
|
||||
pp.parseTemplateElement = function() {
|
||||
let elem = this.startNode()
|
||||
elem.value = {
|
||||
raw: this.input.slice(this.start, this.end),
|
||||
cooked: this.value
|
||||
}
|
||||
this.next()
|
||||
elem.tail = this.type === tt.backQuote
|
||||
return this.finishNode(elem, "TemplateElement")
|
||||
}
|
||||
|
||||
pp.parseTemplate = function() {
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
node.expressions = []
|
||||
let curElt = this.parseTemplateElement()
|
||||
node.quasis = [curElt]
|
||||
while (!curElt.tail) {
|
||||
this.expect(tt.dollarBraceL)
|
||||
node.expressions.push(this.parseExpression())
|
||||
this.expect(tt.braceR)
|
||||
node.quasis.push(curElt = this.parseTemplateElement())
|
||||
}
|
||||
this.next()
|
||||
return this.finishNode(node, "TemplateLiteral")
|
||||
}
|
||||
|
||||
// Parse an object literal or binding pattern.
|
||||
|
||||
pp.parseObj = function(isPattern, refShorthandDefaultPos) {
|
||||
let node = this.startNode(), first = true, propHash = {}
|
||||
node.properties = []
|
||||
let decorators = []
|
||||
this.next()
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma)
|
||||
if (this.afterTrailingComma(tt.braceR)) break
|
||||
} else first = false
|
||||
while (this.type === tt.at) {
|
||||
decorators.push(this.parseDecorator())
|
||||
}
|
||||
let prop = this.startNode(), isGenerator = false, isAsync = false, start
|
||||
if (decorators.length) {
|
||||
prop.decorators = decorators
|
||||
decorators = []
|
||||
}
|
||||
if (this.options.features["es7.objectRestSpread"] && this.type === tt.ellipsis) {
|
||||
prop = this.parseSpread()
|
||||
prop.type = "SpreadProperty"
|
||||
node.properties.push(prop)
|
||||
continue
|
||||
}
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
prop.method = false
|
||||
prop.shorthand = false
|
||||
if (isPattern || refShorthandDefaultPos)
|
||||
start = this.markPosition()
|
||||
if (!isPattern)
|
||||
isGenerator = this.eat(tt.star)
|
||||
}
|
||||
if (this.options.features["es7.asyncFunctions"] && this.isContextual("async")) {
|
||||
if (isGenerator || isPattern) this.unexpected()
|
||||
var asyncId = this.parseIdent()
|
||||
if (this.type === tt.colon || this.type === tt.parenL) {
|
||||
prop.key = asyncId
|
||||
} else {
|
||||
isAsync = true
|
||||
this.parsePropertyName(prop)
|
||||
}
|
||||
} else {
|
||||
this.parsePropertyName(prop)
|
||||
}
|
||||
this.parseObjPropValue(prop, start, isGenerator, isAsync, isPattern, refShorthandDefaultPos);
|
||||
this.checkPropClash(prop, propHash)
|
||||
node.properties.push(this.finishNode(prop, "Property"))
|
||||
}
|
||||
if (decorators.length) {
|
||||
this.raise(this.start, "You have trailing decorators with no property");
|
||||
}
|
||||
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
|
||||
}
|
||||
|
||||
pp.parseObjPropValue = function (prop, start, isGenerator, isAsync, isPattern, refShorthandDefaultPos) {
|
||||
if (this.eat(tt.colon)) {
|
||||
prop.value = isPattern ? this.parseMaybeDefault() : this.parseMaybeAssign(false, refShorthandDefaultPos)
|
||||
prop.kind = "init"
|
||||
} else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) {
|
||||
if (isPattern) this.unexpected()
|
||||
prop.kind = "init"
|
||||
prop.method = true
|
||||
prop.value = this.parseMethod(isGenerator, isAsync)
|
||||
} else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
|
||||
(prop.key.name === "get" || prop.key.name === "set") &&
|
||||
(this.type != tt.comma && this.type != tt.braceR)) {
|
||||
if (isGenerator || isAsync || isPattern) this.unexpected()
|
||||
prop.kind = prop.key.name
|
||||
this.parsePropertyName(prop)
|
||||
prop.value = this.parseMethod(false)
|
||||
} else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
|
||||
prop.kind = "init"
|
||||
if (isPattern) {
|
||||
if (this.isKeyword(prop.key.name) ||
|
||||
(this.strict && (reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name))) ||
|
||||
(!this.options.allowReserved && this.isReservedWord(prop.key.name)))
|
||||
this.raise(prop.key.start, "Binding " + prop.key.name)
|
||||
prop.value = this.parseMaybeDefault(start, prop.key)
|
||||
} else if (this.type === tt.eq && refShorthandDefaultPos) {
|
||||
if (!refShorthandDefaultPos.start)
|
||||
refShorthandDefaultPos.start = this.start
|
||||
prop.value = this.parseMaybeDefault(start, prop.key)
|
||||
} else {
|
||||
prop.value = prop.key
|
||||
}
|
||||
prop.shorthand = true
|
||||
} else this.unexpected()
|
||||
}
|
||||
|
||||
pp.parsePropertyName = function(prop) {
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
if (this.eat(tt.bracketL)) {
|
||||
prop.computed = true
|
||||
prop.key = this.parseMaybeAssign()
|
||||
this.expect(tt.bracketR)
|
||||
return
|
||||
} else {
|
||||
prop.computed = false
|
||||
}
|
||||
}
|
||||
prop.key = (this.type === tt.num || this.type === tt.string) ? this.parseExprAtom() : this.parseIdent(true)
|
||||
}
|
||||
|
||||
// Initialize empty function node.
|
||||
|
||||
pp.initFunction = function(node, isAsync) {
|
||||
node.id = null
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
node.generator = false
|
||||
node.expression = false
|
||||
}
|
||||
if (this.options.features["es7.asyncFunctions"]) {
|
||||
node.async = !!isAsync
|
||||
}
|
||||
}
|
||||
|
||||
// Parse object or class method.
|
||||
|
||||
pp.parseMethod = function(isGenerator, isAsync) {
|
||||
let node = this.startNode()
|
||||
this.initFunction(node, isAsync)
|
||||
this.expect(tt.parenL)
|
||||
node.params = this.parseBindingList(tt.parenR, false, false)
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
node.generator = isGenerator
|
||||
}
|
||||
this.parseFunctionBody(node)
|
||||
return this.finishNode(node, "FunctionExpression")
|
||||
}
|
||||
|
||||
// Parse arrow function expression with given parameters.
|
||||
|
||||
pp.parseArrowExpression = function(node, params, isAsync) {
|
||||
this.initFunction(node, isAsync)
|
||||
node.params = this.toAssignableList(params, true)
|
||||
this.parseFunctionBody(node, true)
|
||||
return this.finishNode(node, "ArrowFunctionExpression")
|
||||
}
|
||||
|
||||
// Parse function body and check parameters.
|
||||
|
||||
pp.parseFunctionBody = function(node, allowExpression) {
|
||||
let isExpression = allowExpression && this.type !== tt.braceL
|
||||
|
||||
var oldInAsync = this.inAsync
|
||||
this.inAsync = node.async
|
||||
if (isExpression) {
|
||||
node.body = this.parseMaybeAssign()
|
||||
node.expression = true
|
||||
} else {
|
||||
// Start a new scope with regard to labels and the `inFunction`
|
||||
// flag (restore them to their old value afterwards).
|
||||
let oldInFunc = this.inFunction, oldInGen = this.inGenerator, oldLabels = this.labels
|
||||
this.inFunction = true; this.inGenerator = node.generator; this.labels = []
|
||||
node.body = this.parseBlock(true)
|
||||
node.expression = false
|
||||
this.inFunction = oldInFunc; this.inGenerator = oldInGen; this.labels = oldLabels
|
||||
}
|
||||
this.inAsync = oldInAsync
|
||||
|
||||
// If this is a strict mode function, verify that argument names
|
||||
// are not repeated, and it does not try to bind the words `eval`
|
||||
// or `arguments`.
|
||||
if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) {
|
||||
let nameHash = {}, oldStrict = this.strict
|
||||
this.strict = true
|
||||
if (node.id)
|
||||
this.checkLVal(node.id, true)
|
||||
for (let i = 0; i < node.params.length; i++)
|
||||
this.checkLVal(node.params[i], true, nameHash)
|
||||
this.strict = oldStrict
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a comma-separated list of expressions, and returns them as
|
||||
// an array. `close` is the token type that ends the list, and
|
||||
// `allowEmpty` can be turned on to allow subsequent commas with
|
||||
// nothing in between them to be parsed as `null` (which is needed
|
||||
// for array literals).
|
||||
|
||||
pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) {
|
||||
let elts = [], first = true
|
||||
while (!this.eat(close)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma)
|
||||
if (allowTrailingComma && this.afterTrailingComma(close)) break
|
||||
} else first = false
|
||||
|
||||
if (allowEmpty && this.type === tt.comma) {
|
||||
elts.push(null)
|
||||
} else {
|
||||
if (this.type === tt.ellipsis)
|
||||
elts.push(this.parseSpread(refShorthandDefaultPos))
|
||||
else
|
||||
elts.push(this.parseMaybeAssign(false, refShorthandDefaultPos))
|
||||
}
|
||||
}
|
||||
return elts
|
||||
}
|
||||
|
||||
// Parse the next token as an identifier. If `liberal` is true (used
|
||||
// when parsing properties), it will also convert keywords into
|
||||
// identifiers.
|
||||
|
||||
pp.parseIdent = function(liberal) {
|
||||
let node = this.startNode()
|
||||
if (liberal && this.options.allowReserved == "never") liberal = false
|
||||
if (this.type === tt.name) {
|
||||
if (!liberal &&
|
||||
((!this.options.allowReserved && this.isReservedWord(this.value)) ||
|
||||
(this.strict && reservedWords.strict(this.value)) &&
|
||||
(this.options.ecmaVersion >= 6 ||
|
||||
this.input.slice(this.start, this.end).indexOf("\\") == -1)))
|
||||
this.raise(this.start, "The keyword '" + this.value + "' is reserved")
|
||||
node.name = this.value
|
||||
} else if (liberal && this.type.keyword) {
|
||||
node.name = this.type.keyword
|
||||
} else {
|
||||
this.unexpected()
|
||||
}
|
||||
this.next()
|
||||
return this.finishNode(node, "Identifier")
|
||||
}
|
||||
|
||||
// Parses await expression inside async function.
|
||||
|
||||
pp.parseAwait = function (node) {
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
|
||||
this.unexpected()
|
||||
}
|
||||
node.all = this.eat(tt.star)
|
||||
node.argument = this.parseMaybeUnary()
|
||||
return this.finishNode(node, "AwaitExpression")
|
||||
};
|
||||
|
||||
// Parses yield expression inside generator.
|
||||
|
||||
pp.parseYield = function() {
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) {
|
||||
node.delegate = false
|
||||
node.argument = null
|
||||
} else {
|
||||
node.delegate = this.eat(tt.star)
|
||||
node.argument = this.parseMaybeAssign()
|
||||
}
|
||||
return this.finishNode(node, "YieldExpression")
|
||||
}
|
||||
|
||||
// Parses array and generator comprehensions.
|
||||
|
||||
pp.parseComprehension = function(node, isGenerator) {
|
||||
node.blocks = []
|
||||
while (this.type === tt._for) {
|
||||
let block = this.startNode()
|
||||
this.next()
|
||||
this.expect(tt.parenL)
|
||||
block.left = this.parseBindingAtom()
|
||||
this.checkLVal(block.left, true)
|
||||
this.expectContextual("of")
|
||||
block.right = this.parseExpression()
|
||||
this.expect(tt.parenR)
|
||||
node.blocks.push(this.finishNode(block, "ComprehensionBlock"))
|
||||
}
|
||||
node.filter = this.eat(tt._if) ? this.parseParenExpression() : null
|
||||
node.body = this.parseExpression()
|
||||
this.expect(isGenerator ? tt.parenR : tt.bracketR)
|
||||
node.generator = isGenerator
|
||||
return this.finishNode(node, "ComprehensionExpression")
|
||||
}
|
||||
97
src/acorn/src/identifier.js
Executable file
97
src/acorn/src/identifier.js
Executable file
@@ -0,0 +1,97 @@
|
||||
// This is a trick taken from Esprima. It turns out that, on
|
||||
// non-Chrome browsers, to check whether a string is in a set, a
|
||||
// predicate containing a big ugly `switch` statement is faster than
|
||||
// a regular expression, and on Chrome the two are about on par.
|
||||
// This function uses `eval` (non-lexical) to produce such a
|
||||
// predicate from a space-separated string of words.
|
||||
//
|
||||
// It starts by sorting the words by length.
|
||||
|
||||
function makePredicate(words) {
|
||||
words = words.split(" ")
|
||||
return function(str) {
|
||||
return words.indexOf(str) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
// Reserved word lists for various dialects of the language
|
||||
|
||||
export const reservedWords = {
|
||||
3: makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"),
|
||||
5: makePredicate("class enum extends super const export import"),
|
||||
6: makePredicate("enum await"),
|
||||
strict: makePredicate("implements interface let package private protected public static yield"),
|
||||
strictBind: makePredicate("eval arguments")
|
||||
}
|
||||
|
||||
// And the keywords
|
||||
|
||||
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"
|
||||
|
||||
export const keywords = {
|
||||
5: makePredicate(ecma5AndLessKeywords),
|
||||
6: makePredicate(ecma5AndLessKeywords + " let const class extends export import yield super")
|
||||
}
|
||||
|
||||
// ## Character categories
|
||||
|
||||
// Big ugly regular expressions that match characters in the
|
||||
// whitespace, identifier, and identifier-start categories. These
|
||||
// are only applied when a character is found to actually have a
|
||||
// code point above 128.
|
||||
// Generated by `tools/generate-identifier-regex.js`.
|
||||
|
||||
let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b2\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua7ad\ua7b0\ua7b1\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab5f\uab64\uab65\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"
|
||||
let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2d\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"
|
||||
|
||||
const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]")
|
||||
const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]")
|
||||
|
||||
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null
|
||||
|
||||
// These are a run-length and offset encoded representation of the
|
||||
// >0xffff code points that are a valid part of identifiers. The
|
||||
// offset starts at 0x10000, and each pair of numbers represents an
|
||||
// offset to the next range, and then a size of the range. They were
|
||||
// generated by tools/generate-identifier-regex.js
|
||||
var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,99,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,98,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,955,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,38,17,2,24,133,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,32,4,287,47,21,1,2,0,185,46,82,47,21,0,60,42,502,63,32,0,449,56,1288,920,104,110,2962,1070,13266,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,16481,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,1340,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,16355,541]
|
||||
var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,16,9,83,11,168,11,6,9,8,2,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,316,19,13,9,214,6,3,8,112,16,16,9,82,12,9,9,535,9,20855,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,4305,6,792618,239]
|
||||
|
||||
// This has a complexity linear to the value of the code. The
|
||||
// assumption is that looking up astral identifier characters is
|
||||
// rare.
|
||||
function isInAstralSet(code, set) {
|
||||
let pos = 0x10000
|
||||
for (let i = 0; i < set.length; i += 2) {
|
||||
pos += set[i]
|
||||
if (pos > code) return false
|
||||
pos += set[i + 1]
|
||||
if (pos >= code) return true
|
||||
}
|
||||
}
|
||||
|
||||
// Test whether a given character code starts an identifier.
|
||||
|
||||
export function isIdentifierStart(code, astral) {
|
||||
if (code < 65) return code === 36
|
||||
if (code < 91) return true
|
||||
if (code < 97) return code === 95
|
||||
if (code < 123) return true
|
||||
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code))
|
||||
if (astral === false) return false
|
||||
return isInAstralSet(code, astralIdentifierStartCodes)
|
||||
}
|
||||
|
||||
// Test whether a given character is part of an identifier.
|
||||
|
||||
export function isIdentifierChar(code, astral) {
|
||||
if (code < 48) return code === 36
|
||||
if (code < 58) return true
|
||||
if (code < 65) return false
|
||||
if (code < 91) return true
|
||||
if (code < 97) return code === 95
|
||||
if (code < 123) return true
|
||||
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code))
|
||||
if (astral === false) return false
|
||||
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
|
||||
}
|
||||
79
src/acorn/src/index.js
Executable file
79
src/acorn/src/index.js
Executable file
@@ -0,0 +1,79 @@
|
||||
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
|
||||
//
|
||||
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
|
||||
// various contributors and released under an MIT license.
|
||||
//
|
||||
// Git repositories for Acorn are available at
|
||||
//
|
||||
// http://marijnhaverbeke.nl/git/acorn
|
||||
// https://github.com/marijnh/acorn.git
|
||||
//
|
||||
// Please use the [github bug tracker][ghbt] to report issues.
|
||||
//
|
||||
// [ghbt]: https://github.com/marijnh/acorn/issues
|
||||
//
|
||||
// This file defines the main parser interface. The library also comes
|
||||
// with a [error-tolerant parser][dammit] and an
|
||||
// [abstract syntax tree walker][walk], defined in other files.
|
||||
//
|
||||
// [dammit]: acorn_loose.js
|
||||
// [walk]: util/walk.js
|
||||
|
||||
import {Parser} from "./state"
|
||||
import {getOptions} from "./options"
|
||||
import "./parseutil"
|
||||
import "./statement"
|
||||
import "./lval"
|
||||
import "./expression"
|
||||
import "./lookahead"
|
||||
|
||||
export {Parser, plugins} from "./state"
|
||||
export {defaultOptions} from "./options"
|
||||
export {SourceLocation} from "./location"
|
||||
export {getLineInfo} from "./location"
|
||||
export {Node} from "./node"
|
||||
export {TokenType, types as tokTypes} from "./tokentype"
|
||||
export {TokContext, types as tokContexts} from "./tokencontext"
|
||||
export {isIdentifierChar, isIdentifierStart} from "./identifier"
|
||||
export {Token} from "./tokenize"
|
||||
export {isNewLine, lineBreak, lineBreakG} from "./whitespace"
|
||||
|
||||
export const version = "1.0.0"
|
||||
|
||||
// The main exported interface (under `self.acorn` when in the
|
||||
// browser) is a `parse` function that takes a code string and
|
||||
// returns an abstract syntax tree as specified by [Mozilla parser
|
||||
// API][api].
|
||||
//
|
||||
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
|
||||
|
||||
export function parse(input, options) {
|
||||
let p = parser(options, input)
|
||||
let startPos = p.options.locations ? [p.pos, p.curPosition()] : p.pos
|
||||
p.nextToken()
|
||||
return p.parseTopLevel(p.options.program || p.startNodeAt(startPos))
|
||||
}
|
||||
|
||||
// This function tries to parse a single expression at a given
|
||||
// offset in a string. Useful for parsing mixed-language formats
|
||||
// that embed JavaScript expressions.
|
||||
|
||||
export function parseExpressionAt(input, pos, options) {
|
||||
let p = parser(options, input, pos)
|
||||
p.nextToken()
|
||||
return p.parseExpression()
|
||||
}
|
||||
|
||||
// Acorn is organized as a tokenizer and a recursive-descent parser.
|
||||
// The `tokenize` export provides an interface to the tokenizer.
|
||||
// Because the tokenizer is optimized for being efficiently used by
|
||||
// the Acorn parser itself, this interface is somewhat crude and not
|
||||
// very modular.
|
||||
|
||||
export function tokenizer(input, options) {
|
||||
return parser(options, input)
|
||||
}
|
||||
|
||||
function parser(options, input) {
|
||||
return new Parser(getOptions(options), String(input))
|
||||
}
|
||||
67
src/acorn/src/location.js
Executable file
67
src/acorn/src/location.js
Executable file
@@ -0,0 +1,67 @@
|
||||
import {Parser} from "./state"
|
||||
import {lineBreakG} from "./whitespace"
|
||||
|
||||
// These are used when `options.locations` is on, for the
|
||||
// `startLoc` and `endLoc` properties.
|
||||
|
||||
export class Position {
|
||||
constructor(line, col) {
|
||||
this.line = line
|
||||
this.column = col
|
||||
}
|
||||
|
||||
offset(n) {
|
||||
return new Position(this.line, this.column + n)
|
||||
}
|
||||
}
|
||||
|
||||
export class SourceLocation {
|
||||
constructor(p, start, end) {
|
||||
this.start = start
|
||||
this.end = end
|
||||
if (p.sourceFile !== null) this.source = p.sourceFile
|
||||
}
|
||||
}
|
||||
|
||||
// The `getLineInfo` function is mostly useful when the
|
||||
// `locations` option is off (for performance reasons) and you
|
||||
// want to find the line/column position for a given character
|
||||
// offset. `input` should be the code string that the offset refers
|
||||
// into.
|
||||
|
||||
export function getLineInfo(input, offset) {
|
||||
for (let line = 1, cur = 0;;) {
|
||||
lineBreakG.lastIndex = cur
|
||||
let match = lineBreakG.exec(input)
|
||||
if (match && match.index < offset) {
|
||||
++line
|
||||
cur = match.index + match[0].length
|
||||
} else {
|
||||
return new Position(line, offset - cur)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
// This function is used to raise exceptions on parse errors. It
|
||||
// takes an offset integer (into the current `input`) to indicate
|
||||
// the location of the error, attaches the position to the end
|
||||
// of the error message, and then raises a `SyntaxError` with that
|
||||
// message.
|
||||
|
||||
pp.raise = function(pos, message) {
|
||||
let loc = getLineInfo(this.input, pos)
|
||||
message += " (" + loc.line + ":" + loc.column + ")"
|
||||
let err = new SyntaxError(message)
|
||||
err.pos = pos; err.loc = loc; err.raisedAt = this.pos
|
||||
throw err
|
||||
}
|
||||
|
||||
pp.curPosition = function() {
|
||||
return new Position(this.curLine, this.pos - this.lineStart)
|
||||
}
|
||||
|
||||
pp.markPosition = function() {
|
||||
return this.options.locations ? [this.start, this.startLoc] : this.start
|
||||
}
|
||||
37
src/acorn/src/lookahead.js
Normal file
37
src/acorn/src/lookahead.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import {Parser} from "./state"
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
var STATE_KEYS = [
|
||||
"lastTokStartLoc",
|
||||
"lastTokEndLoc",
|
||||
"lastTokStart",
|
||||
"lastTokEnd",
|
||||
"lineStart",
|
||||
"startLoc",
|
||||
"endLoc",
|
||||
"start",
|
||||
"pos",
|
||||
"end",
|
||||
"type",
|
||||
"value"
|
||||
];
|
||||
|
||||
pp.getState = function () {
|
||||
var state = {}
|
||||
for (var i = 0; i < STATE_KEYS.length; i++) {
|
||||
var key = STATE_KEYS[i]
|
||||
state[key] = this[key]
|
||||
}
|
||||
return state
|
||||
};
|
||||
|
||||
pp.lookahead = function() {
|
||||
var old = this.getState();
|
||||
this.isLookahead = true
|
||||
this.next()
|
||||
this.isLookahead = false
|
||||
var curr = this.getState();
|
||||
for (var key in old) this[key] = old[key];
|
||||
return curr;
|
||||
};
|
||||
200
src/acorn/src/lval.js
Executable file
200
src/acorn/src/lval.js
Executable file
@@ -0,0 +1,200 @@
|
||||
import {types as tt} from "./tokentype"
|
||||
import {Parser} from "./state"
|
||||
import {reservedWords} from "./identifier"
|
||||
import {has} from "./util"
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
// Convert existing expression atom to assignable pattern
|
||||
// if possible.
|
||||
|
||||
pp.toAssignable = function(node, isBinding) {
|
||||
if (this.options.ecmaVersion >= 6 && node) {
|
||||
switch (node.type) {
|
||||
case "Identifier":
|
||||
case "ObjectPattern":
|
||||
case "ArrayPattern":
|
||||
case "AssignmentPattern":
|
||||
break
|
||||
|
||||
case "ObjectExpression":
|
||||
node.type = "ObjectPattern"
|
||||
for (let i = 0; i < node.properties.length; i++) {
|
||||
let prop = node.properties[i]
|
||||
if (prop.type === "SpreadProperty") continue;
|
||||
if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter")
|
||||
this.toAssignable(prop.value, isBinding)
|
||||
}
|
||||
break
|
||||
|
||||
case "ArrayExpression":
|
||||
node.type = "ArrayPattern"
|
||||
this.toAssignableList(node.elements, isBinding)
|
||||
break
|
||||
|
||||
case "AssignmentExpression":
|
||||
if (node.operator === "=") {
|
||||
node.type = "AssignmentPattern"
|
||||
} else {
|
||||
this.raise(node.left.end, "Only '=' operator can be used for specifying default value.")
|
||||
}
|
||||
break
|
||||
|
||||
case "MemberExpression":
|
||||
if (!isBinding) break
|
||||
|
||||
default:
|
||||
this.raise(node.start, "Assigning to rvalue")
|
||||
}
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// Convert list of expression atoms to binding list.
|
||||
|
||||
pp.toAssignableList = function(exprList, isBinding) {
|
||||
let end = exprList.length
|
||||
if (end) {
|
||||
let last = exprList[end - 1]
|
||||
if (last && last.type == "RestElement") {
|
||||
--end
|
||||
} else if (last && last.type == "SpreadElement") {
|
||||
last.type = "RestElement"
|
||||
let arg = last.argument
|
||||
this.toAssignable(arg, isBinding)
|
||||
if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern")
|
||||
this.unexpected(arg.start)
|
||||
--end
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < end; i++) {
|
||||
let elt = exprList[i]
|
||||
if (elt) this.toAssignable(elt, isBinding)
|
||||
}
|
||||
return exprList
|
||||
}
|
||||
|
||||
// Parses spread element.
|
||||
|
||||
pp.parseSpread = function(refShorthandDefaultPos) {
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
node.argument = this.parseMaybeAssign(refShorthandDefaultPos)
|
||||
return this.finishNode(node, "SpreadElement")
|
||||
}
|
||||
|
||||
pp.parseRest = function() {
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected()
|
||||
return this.finishNode(node, "RestElement")
|
||||
}
|
||||
|
||||
// Parses lvalue (assignable) atom.
|
||||
|
||||
pp.parseBindingAtom = function() {
|
||||
if (this.options.ecmaVersion < 6) return this.parseIdent()
|
||||
switch (this.type) {
|
||||
case tt.name:
|
||||
return this.parseIdent()
|
||||
|
||||
case tt.bracketL:
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
node.elements = this.parseBindingList(tt.bracketR, true, true)
|
||||
return this.finishNode(node, "ArrayPattern")
|
||||
|
||||
case tt.braceL:
|
||||
return this.parseObj(true)
|
||||
|
||||
default:
|
||||
this.unexpected()
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
|
||||
var elts = [], first = true
|
||||
while (!this.eat(close)) {
|
||||
if (first) first = false
|
||||
else this.expect(tt.comma)
|
||||
if (allowEmpty && this.type === tt.comma) {
|
||||
elts.push(null)
|
||||
} else if (allowTrailingComma && this.afterTrailingComma(close)) {
|
||||
break
|
||||
} else if (this.type === tt.ellipsis) {
|
||||
elts.push(this.parseAssignableListItemTypes(this.parseRest()))
|
||||
this.expect(close)
|
||||
break
|
||||
} else {
|
||||
var left = this.parseMaybeDefault()
|
||||
this.parseAssignableListItemTypes(left)
|
||||
elts.push(this.parseMaybeDefault(null, left))
|
||||
}
|
||||
}
|
||||
return elts
|
||||
}
|
||||
|
||||
pp.parseAssignableListItemTypes = function(param) {
|
||||
return param
|
||||
}
|
||||
|
||||
// Parses assignment pattern around given atom if possible.
|
||||
|
||||
pp.parseMaybeDefault = function(startPos, left) {
|
||||
startPos = startPos || this.markPosition()
|
||||
left = left || this.parseBindingAtom()
|
||||
if (!this.eat(tt.eq)) return left
|
||||
let node = this.startNodeAt(startPos)
|
||||
node.operator = "="
|
||||
node.left = left
|
||||
node.right = this.parseMaybeAssign()
|
||||
return this.finishNode(node, "AssignmentPattern")
|
||||
}
|
||||
|
||||
// Verify that a node is an lval — something that can be assigned
|
||||
// to.
|
||||
|
||||
pp.checkLVal = function(expr, isBinding, checkClashes) {
|
||||
switch (expr.type) {
|
||||
case "Identifier":
|
||||
if (this.strict && (reservedWords.strictBind(expr.name) || reservedWords.strict(expr.name)))
|
||||
this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode")
|
||||
if (checkClashes) {
|
||||
if (has(checkClashes, expr.name))
|
||||
this.raise(expr.start, "Argument name clash in strict mode")
|
||||
checkClashes[expr.name] = true
|
||||
}
|
||||
break
|
||||
|
||||
case "MemberExpression":
|
||||
if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression")
|
||||
break
|
||||
|
||||
case "ObjectPattern":
|
||||
for (let i = 0; i < expr.properties.length; i++) {
|
||||
var prop = expr.properties[i];
|
||||
if (prop.type === "Property") prop = prop.value;
|
||||
this.checkLVal(prop, isBinding, checkClashes)
|
||||
}
|
||||
break
|
||||
|
||||
case "ArrayPattern":
|
||||
for (let i = 0; i < expr.elements.length; i++) {
|
||||
let elem = expr.elements[i]
|
||||
if (elem) this.checkLVal(elem, isBinding, checkClashes)
|
||||
}
|
||||
break
|
||||
|
||||
case "AssignmentPattern":
|
||||
this.checkLVal(expr.left, isBinding, checkClashes)
|
||||
break
|
||||
|
||||
case "SpreadProperty":
|
||||
case "RestElement":
|
||||
this.checkLVal(expr.argument, isBinding, checkClashes)
|
||||
break
|
||||
|
||||
default:
|
||||
this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue")
|
||||
}
|
||||
}
|
||||
57
src/acorn/src/node.js
Executable file
57
src/acorn/src/node.js
Executable file
@@ -0,0 +1,57 @@
|
||||
import {Parser} from "./state"
|
||||
import {SourceLocation} from "./location"
|
||||
|
||||
// Start an AST node, attaching a start offset.
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
export class Node {}
|
||||
|
||||
pp.startNode = function() {
|
||||
let node = new Node
|
||||
node.start = this.start
|
||||
if (this.options.locations)
|
||||
node.loc = new SourceLocation(this, this.startLoc)
|
||||
if (this.options.directSourceFile)
|
||||
node.sourceFile = this.options.directSourceFile
|
||||
if (this.options.ranges)
|
||||
node.range = [this.start, 0]
|
||||
return node
|
||||
}
|
||||
|
||||
pp.startNodeAt = function(pos) {
|
||||
let node = new Node, start = pos
|
||||
if (this.options.locations) {
|
||||
node.loc = new SourceLocation(this, start[1])
|
||||
start = pos[0]
|
||||
}
|
||||
node.start = start
|
||||
if (this.options.directSourceFile)
|
||||
node.sourceFile = this.options.directSourceFile
|
||||
if (this.options.ranges)
|
||||
node.range = [start, 0]
|
||||
return node
|
||||
}
|
||||
|
||||
// Finish an AST node, adding `type` and `end` properties.
|
||||
|
||||
pp.finishNode = function(node, type) {
|
||||
node.type = type
|
||||
node.end = this.lastTokEnd
|
||||
if (this.options.locations)
|
||||
node.loc.end = this.lastTokEndLoc
|
||||
if (this.options.ranges)
|
||||
node.range[1] = this.lastTokEnd
|
||||
return node
|
||||
}
|
||||
|
||||
// Finish node at given position
|
||||
|
||||
pp.finishNodeAt = function(node, type, pos) {
|
||||
if (this.options.locations) { node.loc.end = pos[1]; pos = pos[0] }
|
||||
node.type = type
|
||||
node.end = pos
|
||||
if (this.options.ranges)
|
||||
node.range[1] = pos
|
||||
return node
|
||||
}
|
||||
122
src/acorn/src/options.js
Executable file
122
src/acorn/src/options.js
Executable file
@@ -0,0 +1,122 @@
|
||||
import {has, isArray} from "./util"
|
||||
import {SourceLocation} from "./location"
|
||||
|
||||
// A second optional argument can be given to further configure
|
||||
// the parser process. These options are recognized:
|
||||
|
||||
export const defaultOptions = {
|
||||
// `ecmaVersion` indicates the ECMAScript version to parse. Must
|
||||
// be either 3, or 5, or 6. This influences support for strict
|
||||
// mode, the set of reserved words, support for getters and
|
||||
// setters and other features.
|
||||
ecmaVersion: 5,
|
||||
// Source type ("script" or "module") for different semantics
|
||||
sourceType: "script",
|
||||
// `onInsertedSemicolon` can be a callback that will be called
|
||||
// when a semicolon is automatically inserted. It will be passed
|
||||
// th position of the comma as an offset, and if `locations` is
|
||||
// enabled, it is given the location as a `{line, column}` object
|
||||
// as second argument.
|
||||
onInsertedSemicolon: null,
|
||||
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
|
||||
// trailing commas.
|
||||
onTrailingComma: null,
|
||||
// By default, reserved words are not enforced. Disable
|
||||
// `allowReserved` to enforce them. When this option has the
|
||||
// value "never", reserved words and keywords can also not be
|
||||
// used as property names.
|
||||
allowReserved: true,
|
||||
// When enabled, a return at the top level is not considered an
|
||||
// error.
|
||||
allowReturnOutsideFunction: false,
|
||||
// When enabled, import/export statements are not constrained to
|
||||
// appearing at the top of the program.
|
||||
allowImportExportEverywhere: false,
|
||||
// When enabled, hashbang directive in the beginning of file
|
||||
// is allowed and treated as a line comment.
|
||||
allowHashBang: false,
|
||||
// When `locations` is on, `loc` properties holding objects with
|
||||
// `start` and `end` properties in `{line, column}` form (with
|
||||
// line being 1-based and column 0-based) will be attached to the
|
||||
// nodes.
|
||||
locations: false,
|
||||
// A function can be passed as `onToken` option, which will
|
||||
// cause Acorn to call that function with object in the same
|
||||
// format as tokenize() returns. Note that you are not
|
||||
// allowed to call the parser from the callback—that will
|
||||
// corrupt its internal state.
|
||||
onToken: null,
|
||||
// A function can be passed as `onComment` option, which will
|
||||
// cause Acorn to call that function with `(block, text, start,
|
||||
// end)` parameters whenever a comment is skipped. `block` is a
|
||||
// boolean indicating whether this is a block (`/* */`) comment,
|
||||
// `text` is the content of the comment, and `start` and `end` are
|
||||
// character offsets that denote the start and end of the comment.
|
||||
// When the `locations` option is on, two more parameters are
|
||||
// passed, the full `{line, column}` locations of the start and
|
||||
// end of the comments. Note that you are not allowed to call the
|
||||
// parser from the callback—that will corrupt its internal state.
|
||||
onComment: null,
|
||||
// Nodes have their start and end characters offsets recorded in
|
||||
// `start` and `end` properties (directly on the node, rather than
|
||||
// the `loc` object, which holds line/column data. To also add a
|
||||
// [semi-standardized][range] `range` property holding a `[start,
|
||||
// end]` array with the same numbers, set the `ranges` option to
|
||||
// `true`.
|
||||
//
|
||||
// [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
|
||||
ranges: false,
|
||||
// It is possible to parse multiple files into a single AST by
|
||||
// passing the tree produced by parsing the first file as
|
||||
// `program` option in subsequent parses. This will add the
|
||||
// toplevel forms of the parsed file to the `Program` (top) node
|
||||
// of an existing parse tree.
|
||||
program: null,
|
||||
// When `locations` is on, you can pass this to record the source
|
||||
// file in every node's `loc` object.
|
||||
sourceFile: null,
|
||||
// This value, if given, is stored in every node, whether
|
||||
// `locations` is on or off.
|
||||
directSourceFile: null,
|
||||
// When enabled, parenthesized expressions are represented by
|
||||
// (non-standard) ParenthesizedExpression nodes
|
||||
preserveParens: false,
|
||||
plugins: {},
|
||||
// Babel-specific options
|
||||
features: {},
|
||||
strictMode: null
|
||||
}
|
||||
|
||||
// Interpret and default an options object
|
||||
|
||||
export function getOptions(opts) {
|
||||
let options = {}
|
||||
for (let opt in defaultOptions)
|
||||
options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]
|
||||
|
||||
if (isArray(options.onToken)) {
|
||||
let tokens = options.onToken
|
||||
options.onToken = (token) => tokens.push(token)
|
||||
}
|
||||
if (isArray(options.onComment))
|
||||
options.onComment = pushComment(options, options.onComment)
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function pushComment(options, array) {
|
||||
return function (block, text, start, end, startLoc, endLoc) {
|
||||
let comment = {
|
||||
type: block ? 'Block' : 'Line',
|
||||
value: text,
|
||||
start: start,
|
||||
end: end
|
||||
}
|
||||
if (options.locations)
|
||||
comment.loc = new SourceLocation(this, startLoc, endLoc)
|
||||
if (options.ranges)
|
||||
comment.range = [start, end]
|
||||
array.push(comment)
|
||||
}
|
||||
}
|
||||
|
||||
89
src/acorn/src/parseutil.js
Executable file
89
src/acorn/src/parseutil.js
Executable file
@@ -0,0 +1,89 @@
|
||||
import {types as tt} from "./tokentype"
|
||||
import {Parser} from "./state"
|
||||
import {lineBreak} from "./whitespace"
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
// ## Parser utilities
|
||||
|
||||
// Test whether a statement node is the string literal `"use strict"`.
|
||||
|
||||
pp.isUseStrict = function(stmt) {
|
||||
return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" &&
|
||||
stmt.expression.type === "Literal" && stmt.expression.value === "use strict"
|
||||
}
|
||||
|
||||
// Predicate that tests whether the next token is of the given
|
||||
// type, and if yes, consumes it as a side effect.
|
||||
|
||||
pp.eat = function(type) {
|
||||
if (this.type === type) {
|
||||
this.next()
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Tests whether parsed token is a contextual keyword.
|
||||
|
||||
pp.isContextual = function(name) {
|
||||
return this.type === tt.name && this.value === name
|
||||
}
|
||||
|
||||
// Consumes contextual keyword if possible.
|
||||
|
||||
pp.eatContextual = function(name) {
|
||||
return this.value === name && this.eat(tt.name)
|
||||
}
|
||||
|
||||
// Asserts that following token is given contextual keyword.
|
||||
|
||||
pp.expectContextual = function(name) {
|
||||
if (!this.eatContextual(name)) this.unexpected()
|
||||
}
|
||||
|
||||
// Test whether a semicolon can be inserted at the current position.
|
||||
|
||||
pp.canInsertSemicolon = function() {
|
||||
return this.type === tt.eof ||
|
||||
this.type === tt.braceR ||
|
||||
lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
|
||||
}
|
||||
|
||||
pp.insertSemicolon = function() {
|
||||
if (this.canInsertSemicolon()) {
|
||||
if (this.options.onInsertedSemicolon)
|
||||
this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Consume a semicolon, or, failing that, see if we are allowed to
|
||||
// pretend that there is a semicolon at this position.
|
||||
|
||||
pp.semicolon = function() {
|
||||
if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected()
|
||||
}
|
||||
|
||||
pp.afterTrailingComma = function(tokType) {
|
||||
if (this.type == tokType) {
|
||||
if (this.options.onTrailingComma)
|
||||
this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc)
|
||||
this.next()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Expect a token of a given type. If found, consume it, otherwise,
|
||||
// raise an unexpected token error.
|
||||
|
||||
pp.expect = function(type) {
|
||||
this.eat(type) || this.unexpected()
|
||||
}
|
||||
|
||||
// Raise an unexpected token error.
|
||||
|
||||
pp.unexpected = function(pos) {
|
||||
this.raise(pos != null ? pos : this.start, "Unexpected token")
|
||||
}
|
||||
78
src/acorn/src/state.js
Executable file
78
src/acorn/src/state.js
Executable file
@@ -0,0 +1,78 @@
|
||||
import {reservedWords, keywords} from "./identifier"
|
||||
import {types as tt, lineBreak} from "./tokentype"
|
||||
|
||||
export function Parser(options, input, startPos) {
|
||||
this.options = options
|
||||
this.loadPlugins(this.options.plugins)
|
||||
this.sourceFile = this.options.sourceFile || null
|
||||
this.isKeyword = keywords[this.options.ecmaVersion >= 6 ? 6 : 5]
|
||||
this.isReservedWord = reservedWords[this.options.ecmaVersion]
|
||||
this.input = input
|
||||
|
||||
// Set up token state
|
||||
|
||||
// The current position of the tokenizer in the input.
|
||||
if (startPos) {
|
||||
this.pos = startPos
|
||||
this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos))
|
||||
this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length
|
||||
} else {
|
||||
this.pos = this.lineStart = 0
|
||||
this.curLine = 1
|
||||
}
|
||||
|
||||
// Properties of the current token:
|
||||
// Its type
|
||||
this.type = tt.eof
|
||||
// For tokens that include more information than their type, the value
|
||||
this.value = null
|
||||
// Its start and end offset
|
||||
this.start = this.end = this.pos
|
||||
// And, if locations are used, the {line, column} object
|
||||
// corresponding to those offsets
|
||||
this.startLoc = this.endLoc = null
|
||||
|
||||
// Position information for the previous token
|
||||
this.lastTokEndLoc = this.lastTokStartLoc = null
|
||||
this.lastTokStart = this.lastTokEnd = this.pos
|
||||
|
||||
// The context stack is used to superficially track syntactic
|
||||
// context to predict whether a regular expression is allowed in a
|
||||
// given position.
|
||||
this.context = this.initialContext()
|
||||
this.exprAllowed = true
|
||||
|
||||
// Figure out if it's a module code.
|
||||
this.inModule = this.options.sourceType === "module"
|
||||
this.strict = this.options.strictMode === false ? false : this.inModule
|
||||
|
||||
// Used to signify the start of a potential arrow function
|
||||
this.potentialArrowAt = -1
|
||||
|
||||
// Flags to track whether we are in a function, a generator.
|
||||
this.inFunction = this.inGenerator = false
|
||||
// Labels in scope.
|
||||
this.labels = []
|
||||
|
||||
this.decorators = []
|
||||
|
||||
// If enabled, skip leading hashbang line.
|
||||
if (this.pos === 0 && this.options.allowHashBang && this.input.slice(0, 2) === '#!')
|
||||
this.skipLineComment(2)
|
||||
}
|
||||
|
||||
Parser.prototype.extend = function(name, f) {
|
||||
this[name] = f(this[name])
|
||||
}
|
||||
|
||||
// Registered plugins
|
||||
|
||||
export const plugins = {}
|
||||
|
||||
Parser.prototype.loadPlugins = function(plugins) {
|
||||
for (let name in plugins) {
|
||||
let plugin = exports.plugins[name]
|
||||
if (!plugin) throw new Error("Plugin '" + name + "' not found")
|
||||
plugin(this, plugins[name])
|
||||
}
|
||||
}
|
||||
743
src/acorn/src/statement.js
Executable file
743
src/acorn/src/statement.js
Executable file
@@ -0,0 +1,743 @@
|
||||
import {types as tt} from "./tokentype"
|
||||
import {Parser} from "./state"
|
||||
import {lineBreak} from "./whitespace"
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
// ### Statement parsing
|
||||
|
||||
// Parse a program. Initializes the parser, reads any number of
|
||||
// statements, and wraps them in a Program node. Optionally takes a
|
||||
// `program` argument. If present, the statements will be appended
|
||||
// to its body instead of creating a new node.
|
||||
|
||||
pp.parseTopLevel = function(node) {
|
||||
let first = true
|
||||
if (!node.body) node.body = []
|
||||
while (this.type !== tt.eof) {
|
||||
let stmt = this.parseStatement(true, true)
|
||||
node.body.push(stmt)
|
||||
if (first && this.isUseStrict(stmt)) this.setStrict(true)
|
||||
first = false
|
||||
}
|
||||
this.next()
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
node.sourceType = this.options.sourceType
|
||||
}
|
||||
return this.finishNode(node, "Program")
|
||||
}
|
||||
|
||||
const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}
|
||||
|
||||
// Parse a single statement.
|
||||
//
|
||||
// If expecting a statement and finding a slash operator, parse a
|
||||
// regular expression literal. This is to handle cases like
|
||||
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
|
||||
// does not help.
|
||||
|
||||
pp.parseStatement = function(declaration, topLevel) {
|
||||
if (this.type === tt.at) {
|
||||
this.parseDecorators(true)
|
||||
}
|
||||
|
||||
let starttype = this.type, node = this.startNode()
|
||||
|
||||
// Most types of statements are recognized by the keyword they
|
||||
// start with. Many are trivial to parse, some require a bit of
|
||||
// complexity.
|
||||
|
||||
switch (starttype) {
|
||||
case tt._break: case tt._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
|
||||
case tt._debugger: return this.parseDebuggerStatement(node)
|
||||
case tt._do: return this.parseDoStatement(node)
|
||||
case tt._for: return this.parseForStatement(node)
|
||||
case tt._function:
|
||||
if (!declaration && this.options.ecmaVersion >= 6) this.unexpected()
|
||||
return this.parseFunctionStatement(node)
|
||||
|
||||
case tt._class:
|
||||
if (!declaration) this.unexpected()
|
||||
this.takeDecorators(node)
|
||||
return this.parseClass(node, true)
|
||||
|
||||
case tt._if: return this.parseIfStatement(node)
|
||||
case tt._return: return this.parseReturnStatement(node)
|
||||
case tt._switch: return this.parseSwitchStatement(node)
|
||||
case tt._throw: return this.parseThrowStatement(node)
|
||||
case tt._try: return this.parseTryStatement(node)
|
||||
case tt._let: case tt._const: if (!declaration) this.unexpected() // NOTE: falls through to _var
|
||||
case tt._var: return this.parseVarStatement(node, starttype)
|
||||
case tt._while: return this.parseWhileStatement(node)
|
||||
case tt._with: return this.parseWithStatement(node)
|
||||
case tt.braceL: return this.parseBlock()
|
||||
case tt.semi: return this.parseEmptyStatement(node)
|
||||
case tt._export:
|
||||
case tt._import:
|
||||
if (!this.options.allowImportExportEverywhere) {
|
||||
if (!topLevel)
|
||||
this.raise(this.start, "'import' and 'export' may only appear at the top level")
|
||||
if (!this.inModule)
|
||||
this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'")
|
||||
}
|
||||
return starttype === tt._import ? this.parseImport(node) : this.parseExport(node)
|
||||
|
||||
case tt.name:
|
||||
if (this.options.features["es7.asyncFunctions"] && this.value === "async" && this.lookahead().type === tt._function) {
|
||||
this.next();
|
||||
this.expect(tt._function);
|
||||
return this.parseFunction(node, true, false, true);
|
||||
}
|
||||
|
||||
// If the statement does not start with a statement keyword or a
|
||||
// brace, it's an ExpressionStatement or LabeledStatement. We
|
||||
// simply start parsing an expression, and afterwards, if the
|
||||
// next token is a colon and the expression was a simple
|
||||
// Identifier node, we switch to interpreting it as a label.
|
||||
default:
|
||||
let maybeName = this.value, expr = this.parseExpression()
|
||||
if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon))
|
||||
return this.parseLabeledStatement(node, maybeName, expr)
|
||||
else return this.parseExpressionStatement(node, expr)
|
||||
}
|
||||
}
|
||||
|
||||
pp.takeDecorators = function(node) {
|
||||
if (this.decorators.length) {
|
||||
node.decorators = this.decorators
|
||||
this.decorators = []
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseDecorators = function(allowExport) {
|
||||
while (this.type === tt.at) {
|
||||
this.decorators.push(this.parseDecorator());
|
||||
}
|
||||
|
||||
if (allowExport && this.type === tt._export) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.type !== tt._class) {
|
||||
this.raise(this.start, "Leading decorators must be attached to a class declaration");
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseDecorator = function(allowExport) {
|
||||
if (!this.options.features["es7.decorators"]) {
|
||||
this.unexpected()
|
||||
}
|
||||
let node = this.startNode()
|
||||
this.next()
|
||||
node.expression = this.parseMaybeAssign()
|
||||
return this.finishNode(node, "Decorator")
|
||||
}
|
||||
|
||||
pp.parseBreakContinueStatement = function(node, keyword) {
|
||||
let isBreak = keyword == "break"
|
||||
this.next()
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null
|
||||
else if (this.type !== tt.name) this.unexpected()
|
||||
else {
|
||||
node.label = this.parseIdent()
|
||||
this.semicolon()
|
||||
}
|
||||
|
||||
// Verify that there is an actual destination to break or
|
||||
// continue to.
|
||||
for (var i = 0; i < this.labels.length; ++i) {
|
||||
let lab = this.labels[i]
|
||||
if (node.label == null || lab.name === node.label.name) {
|
||||
if (lab.kind != null && (isBreak || lab.kind === "loop")) break
|
||||
if (node.label && isBreak) break
|
||||
}
|
||||
}
|
||||
if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword)
|
||||
return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
|
||||
}
|
||||
|
||||
pp.parseDebuggerStatement = function(node) {
|
||||
this.next()
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "DebuggerStatement")
|
||||
}
|
||||
|
||||
pp.parseDoStatement = function(node) {
|
||||
let start = this.markPosition()
|
||||
this.next()
|
||||
this.labels.push(loopLabel)
|
||||
node.body = this.parseStatement(false)
|
||||
this.labels.pop()
|
||||
if (this.options.features["es7.doExpressions"] && this.type !== tt._while) {
|
||||
let container = this.startNodeAt(start)
|
||||
container.expression = this.finishNode(node, "DoExpression")
|
||||
this.semicolon()
|
||||
return this.finishNode(container, "ExpressionStatement")
|
||||
}
|
||||
this.expect(tt._while)
|
||||
node.test = this.parseParenExpression()
|
||||
if (this.options.ecmaVersion >= 6)
|
||||
this.eat(tt.semi)
|
||||
else
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "DoWhileStatement")
|
||||
}
|
||||
|
||||
// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
|
||||
// loop is non-trivial. Basically, we have to parse the init `var`
|
||||
// statement or expression, disallowing the `in` operator (see
|
||||
// the second parameter to `parseExpression`), and then check
|
||||
// whether the next token is `in` or `of`. When there is no init
|
||||
// part (semicolon immediately after the opening parenthesis), it
|
||||
// is a regular `for` loop.
|
||||
|
||||
pp.parseForStatement = function(node) {
|
||||
this.next()
|
||||
this.labels.push(loopLabel)
|
||||
this.expect(tt.parenL)
|
||||
if (this.type === tt.semi) return this.parseFor(node, null)
|
||||
if (this.type === tt._var || this.type === tt._let || this.type === tt._const) {
|
||||
let init = this.startNode(), varKind = this.type
|
||||
this.next()
|
||||
this.parseVar(init, true, varKind)
|
||||
this.finishNode(init, "VariableDeclaration")
|
||||
if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 &&
|
||||
!(varKind !== tt._var && init.declarations[0].init))
|
||||
return this.parseForIn(node, init)
|
||||
return this.parseFor(node, init)
|
||||
}
|
||||
let refShorthandDefaultPos = {start: 0}
|
||||
let init = this.parseExpression(true, refShorthandDefaultPos)
|
||||
if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
|
||||
this.toAssignable(init)
|
||||
this.checkLVal(init)
|
||||
return this.parseForIn(node, init)
|
||||
} else if (refShorthandDefaultPos.start) {
|
||||
this.unexpected(refShorthandDefaultPos.start)
|
||||
}
|
||||
return this.parseFor(node, init)
|
||||
}
|
||||
|
||||
pp.parseFunctionStatement = function(node) {
|
||||
this.next()
|
||||
return this.parseFunction(node, true)
|
||||
}
|
||||
|
||||
pp.parseIfStatement = function(node) {
|
||||
this.next()
|
||||
node.test = this.parseParenExpression()
|
||||
node.consequent = this.parseStatement(false)
|
||||
node.alternate = this.eat(tt._else) ? this.parseStatement(false) : null
|
||||
return this.finishNode(node, "IfStatement")
|
||||
}
|
||||
|
||||
pp.parseReturnStatement = function(node) {
|
||||
if (!this.inFunction && !this.options.allowReturnOutsideFunction)
|
||||
this.raise(this.start, "'return' outside of function")
|
||||
this.next()
|
||||
|
||||
// In `return` (and `break`/`continue`), the keywords with
|
||||
// optional arguments, we eagerly look for a semicolon or the
|
||||
// possibility to insert one.
|
||||
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null
|
||||
else { node.argument = this.parseExpression(); this.semicolon() }
|
||||
return this.finishNode(node, "ReturnStatement")
|
||||
}
|
||||
|
||||
pp.parseSwitchStatement = function(node) {
|
||||
this.next()
|
||||
node.discriminant = this.parseParenExpression()
|
||||
node.cases = []
|
||||
this.expect(tt.braceL)
|
||||
this.labels.push(switchLabel)
|
||||
|
||||
// Statements under must be grouped (by label) in SwitchCase
|
||||
// nodes. `cur` is used to keep the node that we are currently
|
||||
// adding statements to.
|
||||
|
||||
for (var cur, sawDefault; this.type != tt.braceR;) {
|
||||
if (this.type === tt._case || this.type === tt._default) {
|
||||
let isCase = this.type === tt._case
|
||||
if (cur) this.finishNode(cur, "SwitchCase")
|
||||
node.cases.push(cur = this.startNode())
|
||||
cur.consequent = []
|
||||
this.next()
|
||||
if (isCase) {
|
||||
cur.test = this.parseExpression()
|
||||
} else {
|
||||
if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses")
|
||||
sawDefault = true
|
||||
cur.test = null
|
||||
}
|
||||
this.expect(tt.colon)
|
||||
} else {
|
||||
if (!cur) this.unexpected()
|
||||
cur.consequent.push(this.parseStatement(true))
|
||||
}
|
||||
}
|
||||
if (cur) this.finishNode(cur, "SwitchCase")
|
||||
this.next() // Closing brace
|
||||
this.labels.pop()
|
||||
return this.finishNode(node, "SwitchStatement")
|
||||
}
|
||||
|
||||
pp.parseThrowStatement = function(node) {
|
||||
this.next()
|
||||
if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
|
||||
this.raise(this.lastTokEnd, "Illegal newline after throw")
|
||||
node.argument = this.parseExpression()
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "ThrowStatement")
|
||||
}
|
||||
|
||||
// Reused empty array added for node fields that are always empty.
|
||||
|
||||
const empty = []
|
||||
|
||||
pp.parseTryStatement = function(node) {
|
||||
this.next()
|
||||
node.block = this.parseBlock()
|
||||
node.handler = null
|
||||
if (this.type === tt._catch) {
|
||||
let clause = this.startNode()
|
||||
this.next()
|
||||
this.expect(tt.parenL)
|
||||
clause.param = this.parseBindingAtom()
|
||||
this.checkLVal(clause.param, true)
|
||||
this.expect(tt.parenR)
|
||||
clause.guard = null
|
||||
clause.body = this.parseBlock()
|
||||
node.handler = this.finishNode(clause, "CatchClause")
|
||||
}
|
||||
node.guardedHandlers = empty
|
||||
node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null
|
||||
if (!node.handler && !node.finalizer)
|
||||
this.raise(node.start, "Missing catch or finally clause")
|
||||
return this.finishNode(node, "TryStatement")
|
||||
}
|
||||
|
||||
pp.parseVarStatement = function(node, kind) {
|
||||
this.next()
|
||||
this.parseVar(node, false, kind)
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "VariableDeclaration")
|
||||
}
|
||||
|
||||
pp.parseWhileStatement = function(node) {
|
||||
this.next()
|
||||
node.test = this.parseParenExpression()
|
||||
this.labels.push(loopLabel)
|
||||
node.body = this.parseStatement(false)
|
||||
this.labels.pop()
|
||||
return this.finishNode(node, "WhileStatement")
|
||||
}
|
||||
|
||||
pp.parseWithStatement = function(node) {
|
||||
if (this.strict) this.raise(this.start, "'with' in strict mode")
|
||||
this.next()
|
||||
node.object = this.parseParenExpression()
|
||||
node.body = this.parseStatement(false)
|
||||
return this.finishNode(node, "WithStatement")
|
||||
}
|
||||
|
||||
pp.parseEmptyStatement = function(node) {
|
||||
this.next()
|
||||
return this.finishNode(node, "EmptyStatement")
|
||||
}
|
||||
|
||||
pp.parseLabeledStatement = function(node, maybeName, expr) {
|
||||
for (let i = 0; i < this.labels.length; ++i)
|
||||
if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared")
|
||||
let kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null
|
||||
this.labels.push({name: maybeName, kind: kind})
|
||||
node.body = this.parseStatement(true)
|
||||
this.labels.pop()
|
||||
node.label = expr
|
||||
return this.finishNode(node, "LabeledStatement")
|
||||
}
|
||||
|
||||
pp.parseExpressionStatement = function(node, expr) {
|
||||
node.expression = expr
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "ExpressionStatement")
|
||||
}
|
||||
|
||||
// Parse a semicolon-enclosed block of statements, handling `"use
|
||||
// strict"` declarations when `allowStrict` is true (used for
|
||||
// function bodies).
|
||||
|
||||
pp.parseBlock = function(allowStrict) {
|
||||
let node = this.startNode(), first = true, oldStrict
|
||||
node.body = []
|
||||
this.expect(tt.braceL)
|
||||
while (!this.eat(tt.braceR)) {
|
||||
let stmt = this.parseStatement(true)
|
||||
node.body.push(stmt)
|
||||
if (first && allowStrict && this.isUseStrict(stmt)) {
|
||||
oldStrict = this.strict
|
||||
this.setStrict(this.strict = true)
|
||||
}
|
||||
first = false
|
||||
}
|
||||
if (oldStrict === false) this.setStrict(false)
|
||||
return this.finishNode(node, "BlockStatement")
|
||||
}
|
||||
|
||||
// Parse a regular `for` loop. The disambiguation code in
|
||||
// `parseStatement` will already have parsed the init statement or
|
||||
// expression.
|
||||
|
||||
pp.parseFor = function(node, init) {
|
||||
node.init = init
|
||||
this.expect(tt.semi)
|
||||
node.test = this.type === tt.semi ? null : this.parseExpression()
|
||||
this.expect(tt.semi)
|
||||
node.update = this.type === tt.parenR ? null : this.parseExpression()
|
||||
this.expect(tt.parenR)
|
||||
node.body = this.parseStatement(false)
|
||||
this.labels.pop()
|
||||
return this.finishNode(node, "ForStatement")
|
||||
}
|
||||
|
||||
// Parse a `for`/`in` and `for`/`of` loop, which are almost
|
||||
// same from parser's perspective.
|
||||
|
||||
pp.parseForIn = function(node, init) {
|
||||
let type = this.type === tt._in ? "ForInStatement" : "ForOfStatement"
|
||||
this.next()
|
||||
node.left = init
|
||||
node.right = this.parseExpression()
|
||||
this.expect(tt.parenR)
|
||||
node.body = this.parseStatement(false)
|
||||
this.labels.pop()
|
||||
return this.finishNode(node, type)
|
||||
}
|
||||
|
||||
// Parse a list of variable declarations.
|
||||
|
||||
pp.parseVar = function(node, isFor, kind) {
|
||||
node.declarations = []
|
||||
node.kind = kind.keyword
|
||||
for (;;) {
|
||||
let decl = this.startNode()
|
||||
this.parseVarHead(decl)
|
||||
if (this.eat(tt.eq)) {
|
||||
decl.init = this.parseMaybeAssign(isFor)
|
||||
} else if (kind === tt._const && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
|
||||
this.unexpected()
|
||||
} else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) {
|
||||
this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value")
|
||||
} else {
|
||||
decl.init = null
|
||||
}
|
||||
node.declarations.push(this.finishNode(decl, "VariableDeclarator"))
|
||||
if (!this.eat(tt.comma)) break
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
pp.parseVarHead = function (decl) {
|
||||
decl.id = this.parseBindingAtom()
|
||||
this.checkLVal(decl.id, true)
|
||||
}
|
||||
|
||||
// Parse a function declaration or literal (depending on the
|
||||
// `isStatement` parameter).
|
||||
|
||||
pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
|
||||
this.initFunction(node, isAsync)
|
||||
if (this.options.ecmaVersion >= 6)
|
||||
node.generator = this.eat(tt.star)
|
||||
if (isStatement || this.type === tt.name)
|
||||
node.id = this.parseIdent()
|
||||
this.parseFunctionParams(node);
|
||||
this.parseFunctionBody(node, allowExpressionBody)
|
||||
return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
|
||||
}
|
||||
|
||||
pp.parseFunctionParams = function(node) {
|
||||
this.expect(tt.parenL)
|
||||
node.params = this.parseBindingList(tt.parenR, false, this.options.features["es7.trailingFunctionCommas"])
|
||||
}
|
||||
|
||||
// Parse a class declaration or literal (depending on the
|
||||
// `isStatement` parameter).
|
||||
|
||||
pp.parseClass = function(node, isStatement) {
|
||||
this.next()
|
||||
this.parseClassId(node, isStatement)
|
||||
this.parseClassSuper(node)
|
||||
var classBody = this.startNode()
|
||||
classBody.body = []
|
||||
this.expect(tt.braceL)
|
||||
let decorators = []
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (this.eat(tt.semi)) continue
|
||||
if (this.type === tt.at) {
|
||||
decorators.push(this.parseDecorator())
|
||||
continue
|
||||
}
|
||||
var method = this.startNode()
|
||||
if (decorators.length) {
|
||||
method.decorators = decorators
|
||||
decorators = []
|
||||
}
|
||||
var isGenerator = this.eat(tt.star), isAsync = false
|
||||
this.parsePropertyName(method)
|
||||
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
|
||||
method.key.name === "static") {
|
||||
if (isGenerator) this.unexpected()
|
||||
method['static'] = true
|
||||
isGenerator = this.eat(tt.star)
|
||||
this.parsePropertyName(method)
|
||||
} else {
|
||||
method['static'] = false
|
||||
}
|
||||
if (!isGenerator && method.key.type === "Identifier" && !method.computed && this.isClassProperty()) {
|
||||
classBody.body.push(this.parseClassProperty(method))
|
||||
continue
|
||||
}
|
||||
if (this.options.features["es7.asyncFunctions"] && this.type !== tt.parenL &&
|
||||
!method.computed && method.key.type === "Identifier" && method.key.name === "async") {
|
||||
isAsync = true
|
||||
this.parsePropertyName(method)
|
||||
}
|
||||
method.kind = "method"
|
||||
if (!method.computed && !isGenerator) {
|
||||
if (method.key.type === "Identifier") {
|
||||
if (this.type !== tt.parenL && (method.key.name === "get" || method.key.name === "set")) {
|
||||
method.kind = method.key.name
|
||||
this.parsePropertyName(method)
|
||||
} else if (!method['static'] && method.key.name === "constructor") {
|
||||
method.kind = "constructor"
|
||||
}
|
||||
} else if (!method['static'] && method.key.type === "Literal" && method.key.value === "constructor") {
|
||||
method.kind = "constructor"
|
||||
}
|
||||
}
|
||||
if (method.kind === "constructor" && method.decorators) {
|
||||
this.raise(method.start, "You can't attach decorators to a class constructor")
|
||||
}
|
||||
this.parseClassMethod(classBody, method, isGenerator, isAsync)
|
||||
}
|
||||
if (decorators.length) {
|
||||
this.raise(this.start, "You have trailing decorators with no method");
|
||||
}
|
||||
node.body = this.finishNode(classBody, "ClassBody")
|
||||
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
|
||||
}
|
||||
|
||||
pp.isClassProperty = function() {
|
||||
return this.type === tt.eq || (this.type === tt.semi || this.canInsertSemicolon())
|
||||
}
|
||||
|
||||
pp.parseClassProperty = function(node) {
|
||||
if (this.type === tt.eq) {
|
||||
if (!this.options.features["es7.classProperties"]) this.unexpected()
|
||||
this.next()
|
||||
node.value = this.parseMaybeAssign();
|
||||
} else {
|
||||
node.value = null;
|
||||
}
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "ClassProperty")
|
||||
}
|
||||
|
||||
pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
|
||||
method.value = this.parseMethod(isGenerator, isAsync)
|
||||
classBody.body.push(this.finishNode(method, "MethodDefinition"))
|
||||
}
|
||||
|
||||
pp.parseClassId = function(node, isStatement) {
|
||||
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null
|
||||
}
|
||||
|
||||
pp.parseClassSuper = function(node) {
|
||||
node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null
|
||||
}
|
||||
|
||||
// Parses module export declaration.
|
||||
|
||||
pp.parseExport = function(node) {
|
||||
this.next()
|
||||
// export * from '...'
|
||||
if (this.type === tt.star) {
|
||||
let specifier = this.startNode()
|
||||
this.next()
|
||||
if (this.options.features["es7.exportExtensions"] && this.eatContextual("as")) {
|
||||
specifier.exported = this.parseIdent()
|
||||
node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")]
|
||||
this.parseExportSpecifiersMaybe(node)
|
||||
this.parseExportFrom(node)
|
||||
} else {
|
||||
this.parseExportFrom(node)
|
||||
return this.finishNode(node, "ExportAllDeclaration")
|
||||
}
|
||||
} else if (this.isExportDefaultSpecifier()) {
|
||||
let specifier = this.startNode()
|
||||
specifier.exported = this.parseIdent(true)
|
||||
node.specifiers = [this.finishNode(specifier, "ExportDefaultSpecifier")]
|
||||
if (this.type === tt.comma && this.lookahead().type === tt.star) {
|
||||
this.expect(tt.comma)
|
||||
let specifier = this.startNode()
|
||||
this.expect(tt.star)
|
||||
this.expectContextual("as")
|
||||
specifier.exported = this.parseIdent()
|
||||
node.specifiers.push(this.finishNode(specifier, "ExportNamespaceSpecifier"))
|
||||
} else {
|
||||
this.parseExportSpecifiersMaybe(node)
|
||||
}
|
||||
this.parseExportFrom(node)
|
||||
} else if (this.eat(tt._default)) { // export default ...
|
||||
let expr = this.parseMaybeAssign()
|
||||
let needsSemi = true
|
||||
if (expr.type == "FunctionExpression" ||
|
||||
expr.type == "ClassExpression") {
|
||||
needsSemi = false
|
||||
if (expr.id) {
|
||||
expr.type = expr.type == "FunctionExpression"
|
||||
? "FunctionDeclaration"
|
||||
: "ClassDeclaration"
|
||||
}
|
||||
}
|
||||
node.declaration = expr
|
||||
if (needsSemi) this.semicolon()
|
||||
this.checkExport(node)
|
||||
return this.finishNode(node, "ExportDefaultDeclaration")
|
||||
} else if (this.type.keyword || this.shouldParseExportDeclaration()) {
|
||||
node.declaration = this.parseStatement(true)
|
||||
node.specifiers = []
|
||||
node.source = null
|
||||
} else { // export { x, y as z } [from '...']
|
||||
node.declaration = null
|
||||
node.specifiers = this.parseExportSpecifiers()
|
||||
if (this.eatContextual("from")) {
|
||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected()
|
||||
} else {
|
||||
node.source = null
|
||||
}
|
||||
this.semicolon()
|
||||
}
|
||||
this.checkExport(node)
|
||||
return this.finishNode(node, "ExportNamedDeclaration")
|
||||
}
|
||||
|
||||
pp.isExportDefaultSpecifier = function () {
|
||||
if (this.type === tt.name) {
|
||||
return this.value !== "type" && this.value !== "async"
|
||||
}
|
||||
|
||||
if (this.type !== tt._default) {
|
||||
return false
|
||||
}
|
||||
|
||||
var lookahead = this.lookahead()
|
||||
return lookahead.type === tt.comma || (lookahead.type === tt.name && lookahead.value === "from")
|
||||
}
|
||||
|
||||
pp.parseExportSpecifiersMaybe = function (node) {
|
||||
if (this.eat(tt.comma)) {
|
||||
node.specifiers = node.specifiers.concat(this.parseExportSpecifiers())
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseExportFrom = function(node) {
|
||||
this.expectContextual("from")
|
||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected()
|
||||
this.semicolon()
|
||||
this.checkExport(node)
|
||||
}
|
||||
|
||||
pp.shouldParseExportDeclaration = function() {
|
||||
return this.options.features["es7.asyncFunctions"] && this.isContextual("async")
|
||||
}
|
||||
|
||||
pp.checkExport = function(node) {
|
||||
if (this.decorators.length) {
|
||||
var isClass = node.declaration && (node.declaration.type === "ClassDeclaration" || node.declaration.type === "ClassExpression")
|
||||
if (!node.declaration || !isClass) {
|
||||
this.raise(node.start, "You can only use decorators on an export when exporting a class");
|
||||
}
|
||||
this.takeDecorators(node.declaration)
|
||||
}
|
||||
}
|
||||
|
||||
// Parses a comma-separated list of module exports.
|
||||
|
||||
pp.parseExportSpecifiers = function() {
|
||||
let nodes = [], first = true
|
||||
// export { x, y as z } [from '...']
|
||||
this.expect(tt.braceL)
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma)
|
||||
if (this.afterTrailingComma(tt.braceR)) break
|
||||
} else first = false
|
||||
|
||||
let node = this.startNode()
|
||||
node.local = this.parseIdent(this.type === tt._default)
|
||||
node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local
|
||||
nodes.push(this.finishNode(node, "ExportSpecifier"))
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Parses import declaration.
|
||||
|
||||
pp.parseImport = function(node) {
|
||||
this.next()
|
||||
// import '...'
|
||||
if (this.type === tt.string) {
|
||||
node.specifiers = empty
|
||||
node.source = this.parseExprAtom()
|
||||
} else {
|
||||
node.specifiers = []
|
||||
this.parseImportSpecifiers(node)
|
||||
this.expectContextual("from")
|
||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected()
|
||||
}
|
||||
this.semicolon()
|
||||
return this.finishNode(node, "ImportDeclaration")
|
||||
}
|
||||
|
||||
// Parses a comma-separated list of module imports.
|
||||
|
||||
pp.parseImportSpecifiers = function(node) {
|
||||
var first = true
|
||||
if (this.type === tt.name) {
|
||||
// import defaultObj, { x, y as z } from '...'
|
||||
var start = this.markPosition()
|
||||
node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdent(), start))
|
||||
if (!this.eat(tt.comma)) return
|
||||
}
|
||||
if (this.type === tt.star) {
|
||||
var specifier = this.startNode()
|
||||
this.next()
|
||||
this.expectContextual("as")
|
||||
specifier.local = this.parseIdent()
|
||||
this.checkLVal(specifier.local, true)
|
||||
node.specifiers.push(this.finishNode(specifier, "ImportNamespaceSpecifier"))
|
||||
return
|
||||
}
|
||||
this.expect(tt.braceL)
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma)
|
||||
if (this.afterTrailingComma(tt.braceR)) break
|
||||
} else first = false
|
||||
|
||||
var specifier = this.startNode()
|
||||
specifier.imported = this.parseIdent(true)
|
||||
specifier.local = this.eatContextual("as") ? this.parseIdent() : specifier.imported
|
||||
this.checkLVal(specifier.local, true)
|
||||
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"))
|
||||
}
|
||||
}
|
||||
|
||||
pp.parseImportSpecifierDefault = function (id, start) {
|
||||
var node = this.startNodeAt(start)
|
||||
node.local = id
|
||||
this.checkLVal(node.local, true)
|
||||
return this.finishNode(node, "ImportDefaultSpecifier")
|
||||
}
|
||||
107
src/acorn/src/tokencontext.js
Executable file
107
src/acorn/src/tokencontext.js
Executable file
@@ -0,0 +1,107 @@
|
||||
// The algorithm used to determine whether a regexp can appear at a
|
||||
// given point in the program is loosely based on sweet.js' approach.
|
||||
// See https://github.com/mozilla/sweet.js/wiki/design
|
||||
|
||||
import {Parser} from "./state"
|
||||
import {types as tt} from "./tokentype"
|
||||
import {lineBreak} from "./whitespace"
|
||||
|
||||
export class TokContext {
|
||||
constructor(token, isExpr, preserveSpace, override) {
|
||||
this.token = token
|
||||
this.isExpr = isExpr
|
||||
this.preserveSpace = preserveSpace
|
||||
this.override = override
|
||||
}
|
||||
}
|
||||
|
||||
export const types = {
|
||||
b_stat: new TokContext("{", false),
|
||||
b_expr: new TokContext("{", true),
|
||||
b_tmpl: new TokContext("${", true),
|
||||
p_stat: new TokContext("(", false),
|
||||
p_expr: new TokContext("(", true),
|
||||
q_tmpl: new TokContext("`", true, true, p => p.readTmplToken()),
|
||||
f_expr: new TokContext("function", true)
|
||||
}
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
pp.initialContext = function() {
|
||||
return [types.b_stat]
|
||||
}
|
||||
|
||||
pp.braceIsBlock = function(prevType) {
|
||||
let parent
|
||||
if (prevType === tt.colon && (parent = this.curContext()).token == "{")
|
||||
return !parent.isExpr
|
||||
if (prevType === tt._return)
|
||||
return lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
|
||||
if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof)
|
||||
return true
|
||||
if (prevType == tt.braceL)
|
||||
return this.curContext() === types.b_stat
|
||||
return !this.exprAllowed
|
||||
}
|
||||
|
||||
pp.updateContext = function(prevType) {
|
||||
let update, type = this.type
|
||||
if (type.keyword && prevType == tt.dot)
|
||||
this.exprAllowed = false
|
||||
else if (update = type.updateContext)
|
||||
update.call(this, prevType)
|
||||
else
|
||||
this.exprAllowed = type.beforeExpr
|
||||
}
|
||||
|
||||
// Token-specific context update code
|
||||
|
||||
tt.parenR.updateContext = tt.braceR.updateContext = function() {
|
||||
if (this.context.length == 1) {
|
||||
this.exprAllowed = true
|
||||
return
|
||||
}
|
||||
let out = this.context.pop()
|
||||
if (out === types.b_stat && this.curContext() === types.f_expr) {
|
||||
this.context.pop()
|
||||
this.exprAllowed = false
|
||||
} else if (out === types.b_tmpl) {
|
||||
this.exprAllowed = true
|
||||
} else {
|
||||
this.exprAllowed = !out.isExpr
|
||||
}
|
||||
}
|
||||
|
||||
tt.braceL.updateContext = function(prevType) {
|
||||
this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr)
|
||||
this.exprAllowed = true
|
||||
}
|
||||
|
||||
tt.dollarBraceL.updateContext = function() {
|
||||
this.context.push(types.b_tmpl)
|
||||
this.exprAllowed = true
|
||||
}
|
||||
|
||||
tt.parenL.updateContext = function(prevType) {
|
||||
let statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while
|
||||
this.context.push(statementParens ? types.p_stat : types.p_expr)
|
||||
this.exprAllowed = true
|
||||
}
|
||||
|
||||
tt.incDec.updateContext = function() {
|
||||
// tokExprAllowed stays unchanged
|
||||
}
|
||||
|
||||
tt._function.updateContext = function() {
|
||||
if (this.curContext() !== types.b_stat)
|
||||
this.context.push(types.f_expr)
|
||||
this.exprAllowed = false
|
||||
}
|
||||
|
||||
tt.backQuote.updateContext = function() {
|
||||
if (this.curContext() === types.q_tmpl)
|
||||
this.context.pop()
|
||||
else
|
||||
this.context.push(types.q_tmpl)
|
||||
this.exprAllowed = false
|
||||
}
|
||||
681
src/acorn/src/tokenize.js
Executable file
681
src/acorn/src/tokenize.js
Executable file
@@ -0,0 +1,681 @@
|
||||
import {isIdentifierStart, isIdentifierChar} from "./identifier"
|
||||
import {types as tt, keywords as keywordTypes} from "./tokentype"
|
||||
import {Parser} from "./state"
|
||||
import {SourceLocation} from "./location"
|
||||
import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace"
|
||||
|
||||
// Object type used to represent tokens. Note that normally, tokens
|
||||
// simply exist as properties on the parser object. This is only
|
||||
// used for the onToken callback and the external tokenizer.
|
||||
|
||||
export class Token {
|
||||
constructor(p) {
|
||||
this.type = p.type
|
||||
this.value = p.value
|
||||
this.start = p.start
|
||||
this.end = p.end
|
||||
if (p.options.locations)
|
||||
this.loc = new SourceLocation(p, p.startLoc, p.endLoc)
|
||||
if (p.options.ranges)
|
||||
this.range = [p.start, p.end]
|
||||
}
|
||||
}
|
||||
|
||||
// ## Tokenizer
|
||||
|
||||
const pp = Parser.prototype
|
||||
|
||||
// Move to the next token
|
||||
|
||||
pp.next = function() {
|
||||
if (this.options.onToken && !this.isLookahead)
|
||||
this.options.onToken(new Token(this))
|
||||
|
||||
this.lastTokEnd = this.end
|
||||
this.lastTokStart = this.start
|
||||
this.lastTokEndLoc = this.endLoc
|
||||
this.lastTokStartLoc = this.startLoc
|
||||
this.nextToken()
|
||||
}
|
||||
|
||||
pp.getToken = function() {
|
||||
this.next()
|
||||
return new Token(this)
|
||||
}
|
||||
|
||||
// If we're in an ES6 environment, make parsers iterable
|
||||
if (typeof Symbol !== "undefined")
|
||||
pp[Symbol.iterator] = function () {
|
||||
let self = this
|
||||
return {next: function () {
|
||||
let token = self.getToken()
|
||||
return {
|
||||
done: token.type === tt.eof,
|
||||
value: token
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
// Toggle strict mode. Re-reads the next number or string to please
|
||||
// pedantic tests (`"use strict"; 010;` should fail).
|
||||
|
||||
pp.setStrict = function(strict) {
|
||||
this.strict = strict
|
||||
if (this.type !== tt.num && this.type !== tt.string) return
|
||||
this.pos = this.start
|
||||
if (this.options.locations) {
|
||||
while (this.pos < this.lineStart) {
|
||||
this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1
|
||||
--this.curLine
|
||||
}
|
||||
}
|
||||
this.nextToken()
|
||||
}
|
||||
|
||||
pp.curContext = function() {
|
||||
return this.context[this.context.length - 1]
|
||||
}
|
||||
|
||||
// Read a single token, updating the parser object's token-related
|
||||
// properties.
|
||||
|
||||
pp.nextToken = function() {
|
||||
let curContext = this.curContext()
|
||||
if (!curContext || !curContext.preserveSpace) this.skipSpace()
|
||||
|
||||
this.start = this.pos
|
||||
if (this.options.locations) this.startLoc = this.curPosition()
|
||||
if (this.pos >= this.input.length) return this.finishToken(tt.eof)
|
||||
|
||||
if (curContext.override) return curContext.override(this)
|
||||
else this.readToken(this.fullCharCodeAtPos())
|
||||
}
|
||||
|
||||
pp.readToken = function(code) {
|
||||
// Identifier or keyword. '\uXXXX' sequences are allowed in
|
||||
// identifiers, so '\' also dispatches to that.
|
||||
if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
|
||||
return this.readWord()
|
||||
|
||||
return this.getTokenFromCode(code)
|
||||
}
|
||||
|
||||
pp.fullCharCodeAtPos = function() {
|
||||
let code = this.input.charCodeAt(this.pos)
|
||||
if (code <= 0xd7ff || code >= 0xe000) return code
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
return (code << 10) + next - 0x35fdc00
|
||||
}
|
||||
|
||||
pp.skipBlockComment = function() {
|
||||
let startLoc = this.options.onComment && this.options.locations && this.curPosition()
|
||||
let start = this.pos, end = this.input.indexOf("*/", this.pos += 2)
|
||||
if (end === -1) this.raise(this.pos - 2, "Unterminated comment")
|
||||
this.pos = end + 2
|
||||
if (this.options.locations) {
|
||||
lineBreakG.lastIndex = start
|
||||
let match
|
||||
while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
|
||||
++this.curLine
|
||||
this.lineStart = match.index + match[0].length
|
||||
}
|
||||
}
|
||||
if (this.options.onComment)
|
||||
this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
|
||||
startLoc, this.options.locations && this.curPosition())
|
||||
}
|
||||
|
||||
pp.skipLineComment = function(startSkip) {
|
||||
let start = this.pos
|
||||
let startLoc = this.options.onComment && this.options.locations && this.curPosition()
|
||||
let ch = this.input.charCodeAt(this.pos+=startSkip)
|
||||
while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
|
||||
++this.pos
|
||||
ch = this.input.charCodeAt(this.pos)
|
||||
}
|
||||
if (this.options.onComment)
|
||||
this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
|
||||
startLoc, this.options.locations && this.curPosition())
|
||||
}
|
||||
|
||||
// Called at the start of the parse and after every token. Skips
|
||||
// whitespace and comments, and.
|
||||
|
||||
pp.skipSpace = function() {
|
||||
while (this.pos < this.input.length) {
|
||||
let ch = this.input.charCodeAt(this.pos)
|
||||
if (ch === 32) { // ' '
|
||||
++this.pos
|
||||
} else if (ch === 13) {
|
||||
++this.pos
|
||||
let next = this.input.charCodeAt(this.pos)
|
||||
if (next === 10) {
|
||||
++this.pos
|
||||
}
|
||||
if (this.options.locations) {
|
||||
++this.curLine
|
||||
this.lineStart = this.pos
|
||||
}
|
||||
} else if (ch === 10 || ch === 8232 || ch === 8233) {
|
||||
++this.pos
|
||||
if (this.options.locations) {
|
||||
++this.curLine
|
||||
this.lineStart = this.pos
|
||||
}
|
||||
} else if (ch > 8 && ch < 14) {
|
||||
++this.pos
|
||||
} else if (ch === 47) { // '/'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next === 42) { // '*'
|
||||
this.skipBlockComment()
|
||||
} else if (next === 47) { // '/'
|
||||
this.skipLineComment(2)
|
||||
} else break
|
||||
} else if (ch === 160) { // '\xa0'
|
||||
++this.pos
|
||||
} else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
|
||||
++this.pos
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called at the end of every token. Sets `end`, `val`, and
|
||||
// maintains `context` and `exprAllowed`, and skips the space after
|
||||
// the token, so that the next one's `start` will point at the
|
||||
// right position.
|
||||
|
||||
pp.finishToken = function(type, val) {
|
||||
this.end = this.pos
|
||||
if (this.options.locations) this.endLoc = this.curPosition()
|
||||
let prevType = this.type
|
||||
this.type = type
|
||||
this.value = val
|
||||
|
||||
this.updateContext(prevType)
|
||||
}
|
||||
|
||||
// ### Token reading
|
||||
|
||||
// This is the function that is called to fetch the next token. It
|
||||
// is somewhat obscure, because it works in character codes rather
|
||||
// than characters, and because operator parsing has been inlined
|
||||
// into it.
|
||||
//
|
||||
// All in the name of speed.
|
||||
//
|
||||
pp.readToken_dot = function() {
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next >= 48 && next <= 57) return this.readNumber(true)
|
||||
let next2 = this.input.charCodeAt(this.pos + 2)
|
||||
if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
|
||||
this.pos += 3
|
||||
return this.finishToken(tt.ellipsis)
|
||||
} else {
|
||||
++this.pos
|
||||
return this.finishToken(tt.dot)
|
||||
}
|
||||
}
|
||||
|
||||
pp.readToken_slash = function() { // '/'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (this.exprAllowed) {++this.pos; return this.readRegexp();}
|
||||
if (next === 61) return this.finishOp(tt.assign, 2)
|
||||
return this.finishOp(tt.slash, 1)
|
||||
}
|
||||
|
||||
pp.readToken_mult_modulo = function(code) { // '%*'
|
||||
var type = code === 42 ? tt.star : tt.modulo
|
||||
var width = 1
|
||||
var next = this.input.charCodeAt(this.pos + 1)
|
||||
|
||||
if (next === 42) { // '*'
|
||||
width++
|
||||
next = this.input.charCodeAt(this.pos + 2)
|
||||
type = tt.exponent
|
||||
}
|
||||
|
||||
if (next === 61) {
|
||||
width++
|
||||
type = tt.assign
|
||||
}
|
||||
|
||||
return this.finishOp(type, width)
|
||||
}
|
||||
|
||||
pp.readToken_pipe_amp = function(code) { // '|&'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2)
|
||||
if (next === 61) return this.finishOp(tt.assign, 2)
|
||||
return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1)
|
||||
}
|
||||
|
||||
pp.readToken_caret = function() { // '^'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next === 61) return this.finishOp(tt.assign, 2)
|
||||
return this.finishOp(tt.bitwiseXOR, 1)
|
||||
}
|
||||
|
||||
pp.readToken_plus_min = function(code) { // '+-'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next === code) {
|
||||
if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 &&
|
||||
lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) {
|
||||
// A `-->` line comment
|
||||
this.skipLineComment(3)
|
||||
this.skipSpace()
|
||||
return this.nextToken()
|
||||
}
|
||||
return this.finishOp(tt.incDec, 2)
|
||||
}
|
||||
if (next === 61) return this.finishOp(tt.assign, 2)
|
||||
return this.finishOp(tt.plusMin, 1)
|
||||
}
|
||||
|
||||
pp.readToken_lt_gt = function(code) { // '<>'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
let size = 1
|
||||
if (next === code) {
|
||||
size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2
|
||||
if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1)
|
||||
return this.finishOp(tt.bitShift, size)
|
||||
}
|
||||
if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 &&
|
||||
this.input.charCodeAt(this.pos + 3) == 45) {
|
||||
if (this.inModule) unexpected()
|
||||
// `<!--`, an XML-style comment that should be interpreted as a line comment
|
||||
this.skipLineComment(4)
|
||||
this.skipSpace()
|
||||
return this.nextToken()
|
||||
}
|
||||
if (next === 61)
|
||||
size = this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2
|
||||
return this.finishOp(tt.relational, size)
|
||||
}
|
||||
|
||||
pp.readToken_eq_excl = function(code) { // '=!'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next === 61) return this.finishOp(tt.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2)
|
||||
if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
|
||||
this.pos += 2
|
||||
return this.finishToken(tt.arrow)
|
||||
}
|
||||
return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1)
|
||||
}
|
||||
|
||||
pp.getTokenFromCode = function(code) {
|
||||
switch (code) {
|
||||
// The interpretation of a dot depends on whether it is followed
|
||||
// by a digit or another two dots.
|
||||
case 46: // '.'
|
||||
return this.readToken_dot()
|
||||
|
||||
// Punctuation tokens.
|
||||
case 40: ++this.pos; return this.finishToken(tt.parenL)
|
||||
case 41: ++this.pos; return this.finishToken(tt.parenR)
|
||||
case 59: ++this.pos; return this.finishToken(tt.semi)
|
||||
case 44: ++this.pos; return this.finishToken(tt.comma)
|
||||
case 91: ++this.pos; return this.finishToken(tt.bracketL)
|
||||
case 93: ++this.pos; return this.finishToken(tt.bracketR)
|
||||
case 123: ++this.pos; return this.finishToken(tt.braceL)
|
||||
case 125: ++this.pos; return this.finishToken(tt.braceR)
|
||||
case 58: ++this.pos; return this.finishToken(tt.colon)
|
||||
case 63: ++this.pos; return this.finishToken(tt.question)
|
||||
case 64: ++this.pos; return this.finishToken(tt.at)
|
||||
|
||||
case 96: // '`'
|
||||
if (this.options.ecmaVersion < 6) break
|
||||
++this.pos
|
||||
return this.finishToken(tt.backQuote)
|
||||
|
||||
case 48: // '0'
|
||||
let next = this.input.charCodeAt(this.pos + 1)
|
||||
if (next === 120 || next === 88) return this.readRadixNumber(16); // '0x', '0X' - hex number
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
if (next === 111 || next === 79) return this.readRadixNumber(8); // '0o', '0O' - octal number
|
||||
if (next === 98 || next === 66) return this.readRadixNumber(2); // '0b', '0B' - binary number
|
||||
}
|
||||
// Anything else beginning with a digit is an integer, octal
|
||||
// number, or float.
|
||||
case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
|
||||
return this.readNumber(false)
|
||||
|
||||
// Quotes produce strings.
|
||||
case 34: case 39: // '"', "'"
|
||||
return this.readString(code)
|
||||
|
||||
// Operators are parsed inline in tiny state machines. '=' (61) is
|
||||
// often referred to. `finishOp` simply skips the amount of
|
||||
// characters it is given as second argument, and returns a token
|
||||
// of the type given by its first argument.
|
||||
|
||||
case 47: // '/'
|
||||
return this.readToken_slash()
|
||||
|
||||
case 37: case 42: // '%*'
|
||||
return this.readToken_mult_modulo(code)
|
||||
|
||||
case 124: case 38: // '|&'
|
||||
return this.readToken_pipe_amp(code)
|
||||
|
||||
case 94: // '^'
|
||||
return this.readToken_caret()
|
||||
|
||||
case 43: case 45: // '+-'
|
||||
return this.readToken_plus_min(code)
|
||||
|
||||
case 60: case 62: // '<>'
|
||||
return this.readToken_lt_gt(code)
|
||||
|
||||
case 61: case 33: // '=!'
|
||||
return this.readToken_eq_excl(code)
|
||||
|
||||
case 126: // '~'
|
||||
return this.finishOp(tt.prefix, 1)
|
||||
}
|
||||
|
||||
this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'")
|
||||
}
|
||||
|
||||
pp.finishOp = function(type, size) {
|
||||
let str = this.input.slice(this.pos, this.pos + size)
|
||||
this.pos += size
|
||||
return this.finishToken(type, str)
|
||||
}
|
||||
|
||||
var regexpUnicodeSupport = false
|
||||
try { new RegExp("\uffff", "u"); regexpUnicodeSupport = true }
|
||||
catch(e) {}
|
||||
|
||||
// Parse a regular expression. Some context-awareness is necessary,
|
||||
// since a '/' inside a '[]' set does not end the expression.
|
||||
|
||||
pp.readRegexp = function() {
|
||||
let escaped, inClass, start = this.pos
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length) this.raise(start, "Unterminated regular expression")
|
||||
let ch = this.input.charAt(this.pos)
|
||||
if (lineBreak.test(ch)) this.raise(start, "Unterminated regular expression")
|
||||
if (!escaped) {
|
||||
if (ch === "[") inClass = true
|
||||
else if (ch === "]" && inClass) inClass = false
|
||||
else if (ch === "/" && !inClass) break
|
||||
escaped = ch === "\\"
|
||||
} else escaped = false
|
||||
++this.pos
|
||||
}
|
||||
let content = this.input.slice(start, this.pos)
|
||||
++this.pos
|
||||
// Need to use `readWord1` because '\uXXXX' sequences are allowed
|
||||
// here (don't ask).
|
||||
let mods = this.readWord1()
|
||||
let tmp = content
|
||||
if (mods) {
|
||||
let validFlags = /^[gmsiy]*$/
|
||||
if (this.options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/
|
||||
if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag")
|
||||
if (mods.indexOf('u') >= 0 && !regexpUnicodeSupport) {
|
||||
// Replace each astral symbol and every Unicode escape sequence that
|
||||
// possibly represents an astral symbol or a paired surrogate with a
|
||||
// single ASCII symbol to avoid throwing on regular expressions that
|
||||
// are only valid in combination with the `/u` flag.
|
||||
// Note: replacing with the ASCII symbol `x` might cause false
|
||||
// negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
|
||||
// perfectly valid pattern that is equivalent to `[a-b]`, but it would
|
||||
// be replaced by `[x-b]` which throws an error.
|
||||
tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|\\u\{([0-9a-fA-F]+)\}|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x")
|
||||
}
|
||||
}
|
||||
// Detect invalid regular expressions.
|
||||
try {
|
||||
new RegExp(tmp)
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) this.raise(start, "Error parsing regular expression: " + e.message)
|
||||
this.raise(e)
|
||||
}
|
||||
// Get a regular expression object for this pattern-flag pair, or `null` in
|
||||
// case the current environment doesn't support the flags it uses.
|
||||
let value
|
||||
try {
|
||||
value = new RegExp(content, mods)
|
||||
} catch (err) {
|
||||
value = null
|
||||
}
|
||||
return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value})
|
||||
}
|
||||
|
||||
// Read an integer in the given radix. Return null if zero digits
|
||||
// were read, the integer value otherwise. When `len` is given, this
|
||||
// will return `null` unless the integer has exactly `len` digits.
|
||||
|
||||
pp.readInt = function(radix, len) {
|
||||
let start = this.pos, total = 0
|
||||
for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {
|
||||
let code = this.input.charCodeAt(this.pos), val
|
||||
if (code >= 97) val = code - 97 + 10; // a
|
||||
else if (code >= 65) val = code - 65 + 10; // A
|
||||
else if (code >= 48 && code <= 57) val = code - 48; // 0-9
|
||||
else val = Infinity
|
||||
if (val >= radix) break
|
||||
++this.pos
|
||||
total = total * radix + val
|
||||
}
|
||||
if (this.pos === start || len != null && this.pos - start !== len) return null
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
pp.readRadixNumber = function(radix) {
|
||||
this.pos += 2; // 0x
|
||||
let val = this.readInt(radix)
|
||||
if (val == null) this.raise(this.start + 2, "Expected number in radix " + radix)
|
||||
if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number")
|
||||
return this.finishToken(tt.num, val)
|
||||
}
|
||||
|
||||
// Read an integer, octal integer, or floating-point number.
|
||||
|
||||
pp.readNumber = function(startsWithDot) {
|
||||
let start = this.pos, isFloat = false, octal = this.input.charCodeAt(this.pos) === 48
|
||||
if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number")
|
||||
if (this.input.charCodeAt(this.pos) === 46) {
|
||||
++this.pos
|
||||
this.readInt(10)
|
||||
isFloat = true
|
||||
}
|
||||
let next = this.input.charCodeAt(this.pos)
|
||||
if (next === 69 || next === 101) { // 'eE'
|
||||
next = this.input.charCodeAt(++this.pos)
|
||||
if (next === 43 || next === 45) ++this.pos; // '+-'
|
||||
if (this.readInt(10) === null) this.raise(start, "Invalid number")
|
||||
isFloat = true
|
||||
}
|
||||
if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number")
|
||||
|
||||
let str = this.input.slice(start, this.pos), val
|
||||
if (isFloat) val = parseFloat(str)
|
||||
else if (!octal || str.length === 1) val = parseInt(str, 10)
|
||||
else if (/[89]/.test(str) || this.strict) this.raise(start, "Invalid number")
|
||||
else val = parseInt(str, 8)
|
||||
return this.finishToken(tt.num, val)
|
||||
}
|
||||
|
||||
// Read a string value, interpreting backslash-escapes.
|
||||
|
||||
pp.readCodePoint = function() {
|
||||
let ch = this.input.charCodeAt(this.pos), code
|
||||
|
||||
if (ch === 123) {
|
||||
if (this.options.ecmaVersion < 6) this.unexpected()
|
||||
++this.pos
|
||||
code = this.readHexChar(this.input.indexOf('}', this.pos) - this.pos)
|
||||
++this.pos
|
||||
if (code > 0x10FFFF) this.unexpected()
|
||||
} else {
|
||||
code = this.readHexChar(4)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
function codePointToString(code) {
|
||||
// UTF-16 Decoding
|
||||
if (code <= 0xFFFF) return String.fromCharCode(code)
|
||||
return String.fromCharCode(((code - 0x10000) >> 10) + 0xD800,
|
||||
((code - 0x10000) & 1023) + 0xDC00)
|
||||
}
|
||||
|
||||
pp.readString = function(quote) {
|
||||
let out = "", chunkStart = ++this.pos
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length) this.raise(this.start, "Unterminated string constant")
|
||||
let ch = this.input.charCodeAt(this.pos)
|
||||
if (ch === quote) break
|
||||
if (ch === 92) { // '\'
|
||||
out += this.input.slice(chunkStart, this.pos)
|
||||
out += this.readEscapedChar()
|
||||
chunkStart = this.pos
|
||||
} else {
|
||||
if (isNewLine(ch)) this.raise(this.start, "Unterminated string constant")
|
||||
++this.pos
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos++)
|
||||
return this.finishToken(tt.string, out)
|
||||
}
|
||||
|
||||
// Reads template string tokens.
|
||||
|
||||
pp.readTmplToken = function() {
|
||||
let out = "", chunkStart = this.pos
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length) this.raise(this.start, "Unterminated template")
|
||||
let ch = this.input.charCodeAt(this.pos)
|
||||
if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
|
||||
if (this.pos === this.start && this.type === tt.template) {
|
||||
if (ch === 36) {
|
||||
this.pos += 2
|
||||
return this.finishToken(tt.dollarBraceL)
|
||||
} else {
|
||||
++this.pos
|
||||
return this.finishToken(tt.backQuote)
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos)
|
||||
return this.finishToken(tt.template, out)
|
||||
}
|
||||
if (ch === 92) { // '\'
|
||||
out += this.input.slice(chunkStart, this.pos)
|
||||
out += this.readEscapedChar()
|
||||
chunkStart = this.pos
|
||||
} else if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos)
|
||||
++this.pos
|
||||
if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
|
||||
++this.pos
|
||||
out += "\n"
|
||||
} else {
|
||||
out += String.fromCharCode(ch)
|
||||
}
|
||||
if (this.options.locations) {
|
||||
++this.curLine
|
||||
this.lineStart = this.pos
|
||||
}
|
||||
chunkStart = this.pos
|
||||
} else {
|
||||
++this.pos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used to read escaped characters
|
||||
|
||||
pp.readEscapedChar = function() {
|
||||
let ch = this.input.charCodeAt(++this.pos)
|
||||
let octal = /^[0-7]+/.exec(this.input.slice(this.pos, this.pos + 3))
|
||||
if (octal) octal = octal[0]
|
||||
while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1)
|
||||
if (octal === "0") octal = null
|
||||
++this.pos
|
||||
if (octal) {
|
||||
if (this.strict) this.raise(this.pos - 2, "Octal literal in strict mode")
|
||||
this.pos += octal.length - 1
|
||||
return String.fromCharCode(parseInt(octal, 8))
|
||||
} else {
|
||||
switch (ch) {
|
||||
case 110: return "\n"; // 'n' -> '\n'
|
||||
case 114: return "\r"; // 'r' -> '\r'
|
||||
case 120: return String.fromCharCode(this.readHexChar(2)); // 'x'
|
||||
case 117: return codePointToString(this.readCodePoint()); // 'u'
|
||||
case 116: return "\t"; // 't' -> '\t'
|
||||
case 98: return "\b"; // 'b' -> '\b'
|
||||
case 118: return "\u000b"; // 'v' -> '\u000b'
|
||||
case 102: return "\f"; // 'f' -> '\f'
|
||||
case 48: return "\0"; // 0 -> '\0'
|
||||
case 13: if (this.input.charCodeAt(this.pos) === 10) ++this.pos; // '\r\n'
|
||||
case 10: // ' \n'
|
||||
if (this.options.locations) { this.lineStart = this.pos; ++this.curLine }
|
||||
return ""
|
||||
default: return String.fromCharCode(ch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used to read character escape sequences ('\x', '\u', '\U').
|
||||
|
||||
pp.readHexChar = function(len) {
|
||||
let n = this.readInt(16, len)
|
||||
if (n === null) this.raise(this.start, "Bad character escape sequence")
|
||||
return n
|
||||
}
|
||||
|
||||
// Used to signal to callers of `readWord1` whether the word
|
||||
// contained any escape sequences. This is needed because words with
|
||||
// escape sequences must not be interpreted as keywords.
|
||||
|
||||
var containsEsc
|
||||
|
||||
// Read an identifier, and return it as a string. Sets `containsEsc`
|
||||
// to whether the word contained a '\u' escape.
|
||||
//
|
||||
// Incrementally adds only escaped chars, adding other chunks as-is
|
||||
// as a micro-optimization.
|
||||
|
||||
pp.readWord1 = function() {
|
||||
containsEsc = false
|
||||
let word = "", first = true, chunkStart = this.pos
|
||||
let astral = this.options.ecmaVersion >= 6
|
||||
while (this.pos < this.input.length) {
|
||||
let ch = this.fullCharCodeAtPos()
|
||||
if (isIdentifierChar(ch, astral)) {
|
||||
this.pos += ch <= 0xffff ? 1 : 2
|
||||
} else if (ch === 92) { // "\"
|
||||
containsEsc = true
|
||||
word += this.input.slice(chunkStart, this.pos)
|
||||
let escStart = this.pos
|
||||
if (this.input.charCodeAt(++this.pos) != 117) // "u"
|
||||
this.raise(this.pos, "Expecting Unicode escape sequence \\uXXXX")
|
||||
++this.pos
|
||||
let esc = this.readCodePoint()
|
||||
if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
|
||||
this.raise(escStart, "Invalid Unicode escape")
|
||||
word += codePointToString(esc)
|
||||
chunkStart = this.pos
|
||||
} else {
|
||||
break
|
||||
}
|
||||
first = false
|
||||
}
|
||||
return word + this.input.slice(chunkStart, this.pos)
|
||||
}
|
||||
|
||||
// Read an identifier or keyword token. Will check for reserved
|
||||
// words when necessary.
|
||||
|
||||
pp.readWord = function() {
|
||||
let word = this.readWord1()
|
||||
let type = tt.name
|
||||
if ((this.options.ecmaVersion >= 6 || !containsEsc) && this.isKeyword(word))
|
||||
type = keywordTypes[word]
|
||||
return this.finishToken(type, word)
|
||||
}
|
||||
145
src/acorn/src/tokentype.js
Executable file
145
src/acorn/src/tokentype.js
Executable file
@@ -0,0 +1,145 @@
|
||||
// ## Token types
|
||||
|
||||
// The assignment of fine-grained, information-carrying type objects
|
||||
// allows the tokenizer to store the information it has about a
|
||||
// token in a way that is very cheap for the parser to look up.
|
||||
|
||||
// All token type variables start with an underscore, to make them
|
||||
// easy to recognize.
|
||||
|
||||
// The `beforeExpr` property is used to disambiguate between regular
|
||||
// expressions and divisions. It is set on all token types that can
|
||||
// be followed by an expression (thus, a slash after them would be a
|
||||
// regular expression).
|
||||
//
|
||||
// `isLoop` marks a keyword as starting a loop, which is important
|
||||
// to know when parsing a label, in order to allow or disallow
|
||||
// continue jumps to that label.
|
||||
|
||||
export class TokenType {
|
||||
constructor(label, conf = {}) {
|
||||
this.label = label
|
||||
this.keyword = conf.keyword
|
||||
this.beforeExpr = !!conf.beforeExpr
|
||||
this.startsExpr = !!conf.startsExpr
|
||||
this.rightAssociative = !!conf.rightAssociative
|
||||
this.isLoop = !!conf.isLoop
|
||||
this.isAssign = !!conf.isAssign
|
||||
this.prefix = !!conf.prefix
|
||||
this.postfix = !!conf.postfix
|
||||
this.binop = conf.binop || null
|
||||
this.updateContext = null
|
||||
}
|
||||
}
|
||||
|
||||
function binop(name, prec) {
|
||||
return new TokenType(name, {beforeExpr: true, binop: prec})
|
||||
}
|
||||
const beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}
|
||||
|
||||
export const types = {
|
||||
num: new TokenType("num", startsExpr),
|
||||
regexp: new TokenType("regexp", startsExpr),
|
||||
string: new TokenType("string", startsExpr),
|
||||
name: new TokenType("name", startsExpr),
|
||||
eof: new TokenType("eof"),
|
||||
|
||||
// Punctuation token types.
|
||||
bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
|
||||
bracketR: new TokenType("]"),
|
||||
braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
|
||||
braceR: new TokenType("}"),
|
||||
parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
|
||||
parenR: new TokenType(")"),
|
||||
comma: new TokenType(",", beforeExpr),
|
||||
semi: new TokenType(";", beforeExpr),
|
||||
colon: new TokenType(":", beforeExpr),
|
||||
dot: new TokenType("."),
|
||||
question: new TokenType("?", beforeExpr),
|
||||
arrow: new TokenType("=>", beforeExpr),
|
||||
template: new TokenType("template"),
|
||||
ellipsis: new TokenType("...", beforeExpr),
|
||||
backQuote: new TokenType("`", startsExpr),
|
||||
dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
|
||||
at: new TokenType("@"),
|
||||
|
||||
// Operators. These carry several kinds of properties to help the
|
||||
// parser use them properly (the presence of these properties is
|
||||
// what categorizes them as operators).
|
||||
//
|
||||
// `binop`, when present, specifies that this operator is a binary
|
||||
// operator, and will refer to its precedence.
|
||||
//
|
||||
// `prefix` and `postfix` mark the operator as a prefix or postfix
|
||||
// unary operator.
|
||||
//
|
||||
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
|
||||
// binary operators with a very low precedence, that should result
|
||||
// in AssignmentExpression nodes.
|
||||
|
||||
eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
|
||||
assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
|
||||
incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
|
||||
prefix: new TokenType("prefix", {beforeExpr: true, prefix: true, startsExpr: true}),
|
||||
logicalOR: binop("||", 1),
|
||||
logicalAND: binop("&&", 2),
|
||||
bitwiseOR: binop("|", 3),
|
||||
bitwiseXOR: binop("^", 4),
|
||||
bitwiseAND: binop("&", 5),
|
||||
equality: binop("==/!=", 6),
|
||||
relational: binop("</>", 7),
|
||||
bitShift: binop("<</>>", 8),
|
||||
plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
|
||||
modulo: binop("%", 10),
|
||||
star: binop("*", 10),
|
||||
slash: binop("/", 10),
|
||||
exponent: new TokenType("**", {beforeExpr: true, binop: 11, rightAssociative: true})
|
||||
}
|
||||
|
||||
// Map keyword names to token types.
|
||||
|
||||
export const keywords = {}
|
||||
|
||||
// Succinct definitions of keyword token types
|
||||
function kw(name, options = {}) {
|
||||
options.keyword = name
|
||||
keywords[name] = types["_" + name] = new TokenType(name, options)
|
||||
}
|
||||
|
||||
kw("break")
|
||||
kw("case", beforeExpr)
|
||||
kw("catch")
|
||||
kw("continue")
|
||||
kw("debugger")
|
||||
kw("default")
|
||||
kw("do", {isLoop: true})
|
||||
kw("else", beforeExpr)
|
||||
kw("finally")
|
||||
kw("for", {isLoop: true})
|
||||
kw("function", startsExpr)
|
||||
kw("if")
|
||||
kw("return", beforeExpr)
|
||||
kw("switch")
|
||||
kw("throw", beforeExpr)
|
||||
kw("try")
|
||||
kw("var")
|
||||
kw("let")
|
||||
kw("const")
|
||||
kw("while", {isLoop: true})
|
||||
kw("with")
|
||||
kw("new", {beforeExpr: true, startsExpr: true})
|
||||
kw("this", startsExpr)
|
||||
kw("super", startsExpr)
|
||||
kw("class")
|
||||
kw("extends", beforeExpr)
|
||||
kw("export")
|
||||
kw("import")
|
||||
kw("yield", {beforeExpr: true, startsExpr: true})
|
||||
kw("null", startsExpr)
|
||||
kw("true", startsExpr)
|
||||
kw("false", startsExpr)
|
||||
kw("in", {beforeExpr: true, binop: 7})
|
||||
kw("instanceof", {beforeExpr: true, binop: 7})
|
||||
kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true})
|
||||
kw("void", {beforeExpr: true, prefix: true, startsExpr: true})
|
||||
kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
|
||||
9
src/acorn/src/util.js
Executable file
9
src/acorn/src/util.js
Executable file
@@ -0,0 +1,9 @@
|
||||
export function isArray(obj) {
|
||||
return Object.prototype.toString.call(obj) === "[object Array]"
|
||||
}
|
||||
|
||||
// Checks if an object has a property.
|
||||
|
||||
export function has(obj, propName) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, propName)
|
||||
}
|
||||
12
src/acorn/src/whitespace.js
Executable file
12
src/acorn/src/whitespace.js
Executable file
@@ -0,0 +1,12 @@
|
||||
// Matches a whole line break (where CRLF is considered a single
|
||||
// line break). Used to count lines.
|
||||
|
||||
export const lineBreak = /\r\n?|\n|\u2028|\u2029/
|
||||
export const lineBreakG = new RegExp(lineBreak.source, "g")
|
||||
|
||||
export function isNewLine(code) {
|
||||
return code === 10 || code === 13 || code === 0x2028 || code == 0x2029
|
||||
}
|
||||
|
||||
export const nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
require("./node");
|
||||
var transform = module.exports = require("../transformation");
|
||||
|
||||
transform.options = require("../transformation/file/options");
|
||||
transform.version = require("../../../package").version;
|
||||
|
||||
transform.transform = transform;
|
||||
|
||||
transform.run = function (code, opts = {}) {
|
||||
opts.sourceMap = "inline";
|
||||
opts.sourceMaps = "inline";
|
||||
return new Function(transform(code, opts).code)();
|
||||
};
|
||||
|
||||
transform.load = function (url, callback, opts = {}, hold) {
|
||||
opts.filename ||= url;
|
||||
opts.filename = opts.filename || url;
|
||||
|
||||
var xhr = global.ActiveXObject ? new global.ActiveXObject("Microsoft.XMLHTTP") : new global.XMLHttpRequest();
|
||||
xhr.open("GET", url, true);
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import transform from "../transformation";
|
||||
import * as acorn from "../../acorn";
|
||||
import * as util from "../util";
|
||||
import fs from "fs";
|
||||
|
||||
import * as util from "../util";
|
||||
export { util as _util };
|
||||
export { util, acorn, transform };
|
||||
export { pipeline } from "../transformation";
|
||||
export { canCompile } from "../util";
|
||||
|
||||
export { default as acorn } from "acorn-babel";
|
||||
export { default as transform } from "../transformation";
|
||||
export { default as options } from "../transformation/file/options";
|
||||
export { default as Transformer } from "../transformation/transformer";
|
||||
export { default as Pipeline } from "../transformation/transformer-pipeline";
|
||||
export { default as traverse } from "../traversal";
|
||||
export { default as buildExternalHelpers } from "../build-external-helpers";
|
||||
export { default as types } from "../types";
|
||||
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
|
||||
export { version } from "../../../package";
|
||||
|
||||
export function register(opts) {
|
||||
var callback = require("./register/node");
|
||||
import * as t from "../types";
|
||||
export { t as types };
|
||||
|
||||
export function register(opts?: Object) {
|
||||
var callback = require("./register/node-polyfill");
|
||||
if (opts != null) callback(opts);
|
||||
return callback;
|
||||
}
|
||||
@@ -23,7 +28,7 @@ export function polyfill() {
|
||||
require("../polyfill");
|
||||
}
|
||||
|
||||
export function transformFile(filename, opts, callback) {
|
||||
export function transformFile(filename: string, opts?: Object, callback: Function) {
|
||||
if (isFunction(opts)) {
|
||||
callback = opts;
|
||||
opts = {};
|
||||
@@ -46,7 +51,23 @@ export function transformFile(filename, opts, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
export function transformFileSync(filename, opts = {}) {
|
||||
export function transformFileSync(filename: string, opts?: Object = {}) {
|
||||
opts.filename = filename;
|
||||
return transform(fs.readFileSync(filename), opts);
|
||||
}
|
||||
|
||||
export function parse(code, opts = {}) {
|
||||
opts.sourceType = "module";
|
||||
opts.ecmaVersion = Infinity;
|
||||
opts.plugins = {
|
||||
flow: true,
|
||||
jsx: true
|
||||
};
|
||||
opts.features = {};
|
||||
|
||||
for (var key in transform.pipeline.transformers) {
|
||||
opts.features[key] = true;
|
||||
}
|
||||
|
||||
return acorn.parse(code, opts);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import fs from "fs";
|
||||
import userHome from "user-home";
|
||||
|
||||
var FILENAME = process.env.BABEL_CACHE_PATH || path.join(os.tmpdir(), "babel.json");
|
||||
const FILENAME = process.env.BABEL_CACHE_PATH || path.join(userHome || os.tmpdir(), ".babel.json");
|
||||
var data = {};
|
||||
|
||||
export function save() {
|
||||
@@ -13,14 +14,7 @@ export function load() {
|
||||
if (process.env.BABEL_DISABLE_CACHE) return;
|
||||
|
||||
process.on("exit", save);
|
||||
|
||||
var sigint = function () {
|
||||
process.removeListener("SIGINT", sigint);
|
||||
save();
|
||||
process.kill(process.pid, "SIGINT");
|
||||
};
|
||||
|
||||
process.on("SIGINT", sigint);
|
||||
process.nextTick(save);
|
||||
|
||||
if (!fs.existsSync(FILENAME)) return;
|
||||
|
||||
|
||||
2
src/babel/api/register/node-polyfill.js
Normal file
2
src/babel/api/register/node-polyfill.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import "../../polyfill";
|
||||
export { default } from "./node";
|
||||
@@ -1,12 +1,12 @@
|
||||
import "../../polyfill";
|
||||
import sourceMapSupport from "source-map-support";
|
||||
import * as registerCache from "./cache";
|
||||
import resolveRc from "./resolve-rc";
|
||||
import resolveRc from "../../tools/resolve-rc";
|
||||
import extend from "lodash/object/extend";
|
||||
import * as babel from "../node";
|
||||
import each from "lodash/collection/each";
|
||||
import * as util from "../../util";
|
||||
import fs from "fs";
|
||||
import slash from "slash";
|
||||
|
||||
sourceMapSupport.install({
|
||||
handleUncaughtExceptions: false,
|
||||
@@ -31,8 +31,10 @@ var cache = registerCache.get();
|
||||
//
|
||||
|
||||
var transformOpts = {};
|
||||
var ignoreRegex = /node_modules/;
|
||||
var onlyRegex;
|
||||
|
||||
var ignore;
|
||||
var only;
|
||||
|
||||
var oldHandlers = {};
|
||||
var maps = {};
|
||||
|
||||
@@ -44,9 +46,12 @@ var compile = function (filename) {
|
||||
var result;
|
||||
|
||||
var opts = extend({}, transformOpts);
|
||||
|
||||
// this will be done when the file is transformed anyway but we need all
|
||||
// the options so we can generate the cache key
|
||||
resolveRc(filename, opts);
|
||||
|
||||
var cacheKey = `${filename}:${JSON.stringify(opts)}`;
|
||||
var cacheKey = `${filename}:${JSON.stringify(opts)}:${babel.version}`;
|
||||
|
||||
if (cache) {
|
||||
var cached = cache[cacheKey];
|
||||
@@ -73,7 +78,11 @@ var compile = function (filename) {
|
||||
};
|
||||
|
||||
var shouldIgnore = function (filename) {
|
||||
return (ignoreRegex && ignoreRegex.test(filename)) || (onlyRegex && !onlyRegex.test(filename));
|
||||
if (!ignore && !only) {
|
||||
return /node_modules/.test(filename);
|
||||
} else {
|
||||
return util.shouldIgnore(filename, ignore || [], only || []);
|
||||
}
|
||||
};
|
||||
|
||||
var istanbulMonkey = {};
|
||||
@@ -139,8 +148,8 @@ var hookExtensions = function (_exts) {
|
||||
hookExtensions(util.canCompile.EXTENSIONS);
|
||||
|
||||
export default function (opts = {}) {
|
||||
if (opts.only != null) onlyRegex = util.regexify(opts.only);
|
||||
if (opts.ignore != null) ignoreRegex = util.regexify(opts.ignore);
|
||||
if (opts.only != null) only = util.arrayify(opts.only, util.regexify);
|
||||
if (opts.ignore != null) ignore = util.arrayify(opts.ignore, util.regexify);
|
||||
|
||||
if (opts.extensions) hookExtensions(util.arrayify(opts.extensions));
|
||||
|
||||
@@ -153,16 +162,3 @@ export default function (opts = {}) {
|
||||
|
||||
extend(transformOpts, opts);
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
try {
|
||||
var runtimePackage = require("babel-runtime/package");
|
||||
var version = require("../../package").version;
|
||||
if (runtimePackage.version !== version) {
|
||||
throw new ReferenceError(`The verison of babel-runtime of ${runtimePackage.runtime} that you have installed does not match the babel verison of ${version}`);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import File from "./transformation/file";
|
||||
import * as util from "./util";
|
||||
import each from "lodash/collection/each";
|
||||
import t from "./types";
|
||||
|
||||
export default function (body, namespace, whitelist = []) {
|
||||
each(File.helpers, function (name) {
|
||||
if (whitelist.length && whitelist.indexOf(name) === -1) return;
|
||||
|
||||
var key = t.identifier(t.toIdentifier(name));
|
||||
body.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", t.memberExpression(namespace, key), util.template(name))
|
||||
));
|
||||
});
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
import SYNTAX_KEYS from "./syntax-keys";
|
||||
import traverse from "../traversal";
|
||||
|
||||
var visitors = traverse.explode(require("./visitors"));
|
||||
|
||||
export default function (ast) {
|
||||
var stats = {
|
||||
syntax: {},
|
||||
builtins: {}
|
||||
};
|
||||
|
||||
var detectedSyntax = function (name) {
|
||||
stats.syntax[name] = true;
|
||||
};
|
||||
|
||||
traverse(ast, {
|
||||
enter(node, parent) {
|
||||
if (SYNTAX_KEYS[node.type]) {
|
||||
detectedSyntax(SYNTAX_KEYS[node.type]);
|
||||
}
|
||||
|
||||
var visitor = visitors[node.type];
|
||||
if (visitor) visitor(node, parent, detectedSyntax);
|
||||
}
|
||||
});
|
||||
|
||||
return stats;
|
||||
};
|
||||
@@ -1,84 +0,0 @@
|
||||
{
|
||||
"ArrowFunctionExpression": "es6.arrowFunctions",
|
||||
|
||||
"AwaitExpression": "es7.asyncFunctions",
|
||||
|
||||
"ClassBody": "es6.classes",
|
||||
"ClassDeclaration": "es6.classes",
|
||||
"ClassExpression": "es6.classes",
|
||||
"MethodDefinition": "es6.classes",
|
||||
|
||||
"ComprehensionBlock": "es7.comprehensions",
|
||||
"ComprehensionExpression": "es7.comprehensions",
|
||||
|
||||
"ForOfStatement": "es6.forOf",
|
||||
|
||||
"ExportBatchSpecifier": "es6.modules",
|
||||
"ExportDeclaration": "es6.modules",
|
||||
"ExportSpecifier": "es6.modules",
|
||||
"ImportBatchSpecifier": "es6.modules",
|
||||
"ImportDeclaration": "es6.modules",
|
||||
"ImportSpecifier": "es6.modules",
|
||||
|
||||
"ArrayPattern": "es6.destructuring",
|
||||
"AssignmentPattern": "es6.destructuring",
|
||||
"ObjectPattern": "es6.destructuring",
|
||||
|
||||
"RestElement": "es6.parameters.rest",
|
||||
|
||||
"SpreadElement": "es6.spread",
|
||||
|
||||
"SpreadProperty": "es7.objectSpread",
|
||||
|
||||
"TaggedTemplateExpression": "es6.templateLiterals",
|
||||
"TemplateElement": "es6.templateLiterals",
|
||||
"TemplateLiteral": "es6.templateLiterals",
|
||||
|
||||
"VirtualPropertyExpression": "es7.abstractReferences",
|
||||
"PrivateDeclaration": "es7.abstractReferences",
|
||||
|
||||
"YieldExpression": "es6.generators",
|
||||
|
||||
"AnyTypeAnnotation": "flow",
|
||||
"ArrayTypeAnnotation": "flow",
|
||||
"BooleanTypeAnnotation": "flow",
|
||||
"ClassProperty": "flow",
|
||||
"DeclareClass": "flow",
|
||||
"DeclareFunction": "flow",
|
||||
"DeclareModule": "flow",
|
||||
"DeclareVariable": "flow",
|
||||
"FunctionTypeAnnotation": "flow",
|
||||
"FunctionTypeParam": "flow",
|
||||
"GenericTypeAnnotation": "flow",
|
||||
"InterfaceExtends": "flow",
|
||||
"InterfaceDeclaration": "flow",
|
||||
"IntersectionTypeAnnotation": "flow",
|
||||
"NullableTypeAnnotation": "flow",
|
||||
"NumberTypeAnnotation": "flow",
|
||||
"StringLiteralTypeAnnotation": "flow",
|
||||
"StringTypeAnnotation": "flow",
|
||||
"TupleTypeAnnotation": "flow",
|
||||
"TypeofTypeAnnotation": "flow",
|
||||
"TypeAlias": "flow",
|
||||
"TypeAnnotation": "flow",
|
||||
"TypeParameterDeclaration": "flow",
|
||||
"TypeParameterInstantiation": "flow",
|
||||
"ObjectTypeAnnotation": "flow",
|
||||
"ObjectTypeCallProperty": "flow",
|
||||
"ObjectTypeIndexer": "flow",
|
||||
"ObjectTypeProperty": "flow",
|
||||
"QualifiedTypeIdentifier": "flow",
|
||||
"UnionTypeAnnotation": "flow",
|
||||
"VoidTypeAnnotation": "flow",
|
||||
|
||||
"JSXAttribute": "jsx",
|
||||
"JSXClosingElement": "jsx",
|
||||
"JSXElement": "jsx",
|
||||
"JSXEmptyExpression": "jsx",
|
||||
"JSXExpressionContainer": "jsx",
|
||||
"JSXIdentifier": "jsx",
|
||||
"JSXMemberExpression": "jsx",
|
||||
"JSXNamespacedName": "jsx",
|
||||
"JSXOpeningElement": "jsx",
|
||||
"JSXSpreadAttribute": "jsx"
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import includes from "lodash/collection/includes";
|
||||
import t from "../types";
|
||||
|
||||
export function AssignmentExpression(node, parent, detected) {
|
||||
if (node.operator === "**=") {
|
||||
detected("es6.exponentation");
|
||||
}
|
||||
}
|
||||
|
||||
export function BinaryExpression(node, parent, detected) {
|
||||
if (node.operator === "**") {
|
||||
detected("es6.exponentation");
|
||||
}
|
||||
}
|
||||
|
||||
export function VariableDeclaration(node, parent, detected) {
|
||||
if (node.kind === "let" || node.kind === "const") {
|
||||
detected("es6.blockScoping");
|
||||
}
|
||||
|
||||
if (node.kind === "const") {
|
||||
detected("es6.constants");
|
||||
}
|
||||
}
|
||||
|
||||
export function Property(node, parent, detected) {
|
||||
if (node.shorthand || node.method) {
|
||||
detected("es6.properties.shorthand");
|
||||
}
|
||||
|
||||
if (node.kind === "set" || node.kind === "get") {
|
||||
detected("es5.properties.mutators");
|
||||
}
|
||||
|
||||
if (node.computed) {
|
||||
detected("es6.properties.computed");
|
||||
}
|
||||
}
|
||||
|
||||
export function AssignmentPattern(node, parent, detected) {
|
||||
if (t.isFunction(parent) && includes(parent.params, node)) {
|
||||
detected("es6.parameters.default");
|
||||
}
|
||||
}
|
||||
|
||||
exports.Function = function (node, parent, detected) {
|
||||
if (node.generator) {
|
||||
detected("es6.generators");
|
||||
}
|
||||
|
||||
if (node.async) {
|
||||
detected("es7.asyncFunctions");
|
||||
}
|
||||
};
|
||||
@@ -70,14 +70,14 @@ export default class Buffer {
|
||||
}
|
||||
|
||||
newline(i, removeLast) {
|
||||
if (this.format.compact) return;
|
||||
if (this.format.compact || this.format.retainLines) return;
|
||||
|
||||
if (this.format.concise) {
|
||||
this.space();
|
||||
return;
|
||||
}
|
||||
|
||||
removeLast ||= false;
|
||||
removeLast = removeLast || false;
|
||||
|
||||
if (isNumber(i)) {
|
||||
i = Math.min(2, i);
|
||||
|
||||
@@ -13,7 +13,7 @@ export function BlockStatement(node, print) {
|
||||
this.push("{");
|
||||
this.newline();
|
||||
print.sequence(node.body, { indent: true });
|
||||
this.removeLast("\n");
|
||||
if (!this.format.retainLines) this.removeLast("\n");
|
||||
this.rightBrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export function ClassDeclaration(node, print) {
|
||||
print.list(node.decorators);
|
||||
this.push("class");
|
||||
|
||||
if (node.id) {
|
||||
@@ -40,7 +41,25 @@ export function ClassBody(node, print) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function ClassProperty(node, print) {
|
||||
print.list(node.decorators);
|
||||
|
||||
if (node.static) this.push("static ");
|
||||
print(node.key);
|
||||
print(node.typeAnnotation);
|
||||
if (node.value) {
|
||||
this.space();
|
||||
this.push("=");
|
||||
this.space();
|
||||
print(node.value);
|
||||
}
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function MethodDefinition(node, print) {
|
||||
print.list(node.decorators);
|
||||
|
||||
if (node.static) {
|
||||
this.push("static ");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import isInteger from "is-integer";
|
||||
import isNumber from "lodash/lang/isNumber";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export function UnaryExpression(node, print) {
|
||||
var hasSpace = /[a-z]$/.test(node.operator);
|
||||
@@ -19,6 +19,12 @@ export function UnaryExpression(node, print) {
|
||||
print(node.argument);
|
||||
}
|
||||
|
||||
export function DoExpression(node, print) {
|
||||
this.push("do");
|
||||
this.space();
|
||||
print(node.body);
|
||||
}
|
||||
|
||||
export function UpdateExpression(node, print) {
|
||||
if (node.prefix) {
|
||||
this.push(node.operator);
|
||||
@@ -57,6 +63,15 @@ export function ThisExpression() {
|
||||
this.push("this");
|
||||
}
|
||||
|
||||
export function Super() {
|
||||
this.push("super");
|
||||
}
|
||||
|
||||
export function Decorator(node, print) {
|
||||
this.push("@");
|
||||
print(node.expression);
|
||||
}
|
||||
|
||||
export function CallExpression(node, print) {
|
||||
print(node.callee);
|
||||
|
||||
@@ -153,3 +168,9 @@ export function MemberExpression(node, print) {
|
||||
print(node.property);
|
||||
}
|
||||
}
|
||||
|
||||
export function MetaProperty(node, print) {
|
||||
print(node.meta);
|
||||
this.push(".");
|
||||
print(node.property);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export function AnyTypeAnnotation() {
|
||||
this.push("any");
|
||||
@@ -14,13 +14,6 @@ export function BooleanTypeAnnotation(node) {
|
||||
this.push("bool");
|
||||
}
|
||||
|
||||
export function ClassProperty(node, print) {
|
||||
if (node.static) this.push("static ");
|
||||
print(node.key);
|
||||
print(node.typeAnnotation);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function DeclareClass(node, print) {
|
||||
this.push("declare class ");
|
||||
this._interfaceish(node, print);
|
||||
@@ -167,11 +160,24 @@ export { TypeParameterInstantiation as TypeParameterDeclaration };
|
||||
export function ObjectTypeAnnotation(node, print) {
|
||||
this.push("{");
|
||||
var props = node.properties.concat(node.callProperties, node.indexers);
|
||||
|
||||
if (props.length) {
|
||||
this.space();
|
||||
print.list(props, { indent: true, separator: "; " });
|
||||
|
||||
print.list(props, {
|
||||
separator: false,
|
||||
indent: true,
|
||||
iterator: () => {
|
||||
if (props.length !== 1) {
|
||||
this.semicolon();
|
||||
this.space();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.space();
|
||||
}
|
||||
|
||||
this.push("}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export function JSXAttribute(node, print) {
|
||||
print(node.name);
|
||||
@@ -45,7 +45,7 @@ export function JSXElement(node, print) {
|
||||
this.indent();
|
||||
each(node.children, (child) => {
|
||||
if (t.isLiteral(child)) {
|
||||
this.push(child.value);
|
||||
this.push(child.value, true);
|
||||
} else {
|
||||
print(child);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export function _params(node, print) {
|
||||
print(node.typeParameters);
|
||||
@@ -21,11 +21,13 @@ export function _method(node, print) {
|
||||
var kind = node.kind;
|
||||
var key = node.key;
|
||||
|
||||
if (!kind || kind === "init") {
|
||||
if (kind === "method" || kind === "init") {
|
||||
if (value.generator) {
|
||||
this.push("*");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (kind === "get" || kind === "set") {
|
||||
this.push(kind + " ");
|
||||
}
|
||||
|
||||
@@ -73,5 +75,16 @@ export function ArrowFunctionExpression(node, print) {
|
||||
}
|
||||
|
||||
this.push(" => ");
|
||||
|
||||
const bodyNeedsParens = t.isObjectExpression(node.body);
|
||||
|
||||
if (bodyNeedsParens) {
|
||||
this.push("(");
|
||||
}
|
||||
|
||||
print(node.body);
|
||||
|
||||
if (bodyNeedsParens) {
|
||||
this.push(")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,75 @@
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export function ImportSpecifier(node, print) {
|
||||
if (t.isSpecifierDefault(node)) {
|
||||
print(t.getSpecifierName(node));
|
||||
} else {
|
||||
return ExportSpecifier.apply(this, arguments);
|
||||
print(node.imported);
|
||||
if (node.local && node.local !== node.imported) {
|
||||
this.push(" as ");
|
||||
print(node.local);
|
||||
}
|
||||
}
|
||||
|
||||
export function ImportDefaultSpecifier(node, print) {
|
||||
print(node.local);
|
||||
}
|
||||
|
||||
export function ExportDefaultSpecifier(node, print) {
|
||||
print(node.exported);
|
||||
}
|
||||
|
||||
export function ExportSpecifier(node, print) {
|
||||
print(node.id);
|
||||
if (node.name) {
|
||||
print(node.local);
|
||||
if (node.exported && node.local !== node.exported) {
|
||||
this.push(" as ");
|
||||
print(node.name);
|
||||
print(node.exported);
|
||||
}
|
||||
}
|
||||
|
||||
export function ExportBatchSpecifier() {
|
||||
this.push("*");
|
||||
export function ExportNamespaceSpecifier(node, print) {
|
||||
this.push("* as ");
|
||||
print(node.exported);
|
||||
}
|
||||
|
||||
export function ExportDeclaration(node, print) {
|
||||
this.push("export ");
|
||||
export function ExportAllDeclaration(node, print) {
|
||||
this.push("export *");
|
||||
if (node.exported) {
|
||||
this.push(" as ");
|
||||
print(node.exported);
|
||||
}
|
||||
this.push(" from ");
|
||||
print(node.source);
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function ExportNamedDeclaration(node, print) {
|
||||
this.push("export ");
|
||||
ExportDeclaration.call(this, node, print);
|
||||
}
|
||||
|
||||
export function ExportDefaultDeclaration(node, print) {
|
||||
this.push("export default ");
|
||||
ExportDeclaration.call(this, node, print);
|
||||
}
|
||||
|
||||
function ExportDeclaration(node, print) {
|
||||
var specifiers = node.specifiers;
|
||||
|
||||
if (node.default) {
|
||||
this.push("default ");
|
||||
}
|
||||
|
||||
if (node.declaration) {
|
||||
print(node.declaration);
|
||||
if (t.isStatement(node.declaration)) return;
|
||||
var declar = node.declaration;
|
||||
print(declar);
|
||||
if (t.isStatement(declar) || t.isFunction(declar) || t.isClass(declar)) return;
|
||||
} else {
|
||||
if (specifiers.length === 1 && t.isExportBatchSpecifier(specifiers[0])) {
|
||||
print(specifiers[0]);
|
||||
} else {
|
||||
var first = specifiers[0];
|
||||
var hasSpecial = false;
|
||||
if (t.isExportDefaultSpecifier(first) || t.isExportNamespaceSpecifier(first)) {
|
||||
hasSpecial = true;
|
||||
print(specifiers.shift());
|
||||
if (specifiers.length) {
|
||||
this.push(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (specifiers.length || (!specifiers.length && !hasSpecial)) {
|
||||
this.push("{");
|
||||
if (specifiers.length) {
|
||||
this.space();
|
||||
@@ -64,25 +97,20 @@ export function ImportDeclaration(node, print) {
|
||||
|
||||
var specfiers = node.specifiers;
|
||||
if (specfiers && specfiers.length) {
|
||||
var foundImportSpecifier = false;
|
||||
|
||||
each(node.specifiers, (spec, i) => {
|
||||
if (+i > 0) {
|
||||
var first = node.specifiers[0];
|
||||
if (t.isImportDefaultSpecifier(first) || t.isImportNamespaceSpecifier(first)) {
|
||||
print(node.specifiers.shift());
|
||||
if (node.specifiers.length) {
|
||||
this.push(", ");
|
||||
}
|
||||
}
|
||||
|
||||
var isDefault = t.isSpecifierDefault(spec);
|
||||
|
||||
if (!isDefault && spec.type !== "ImportBatchSpecifier" && !foundImportSpecifier) {
|
||||
foundImportSpecifier = true;
|
||||
this.push("{ ");
|
||||
}
|
||||
|
||||
print(spec);
|
||||
});
|
||||
|
||||
if (foundImportSpecifier) {
|
||||
this.push(" }");
|
||||
if (node.specifiers.length) {
|
||||
this.push("{");
|
||||
this.space()
|
||||
print.join(node.specifiers, { separator: ", " });
|
||||
this.space()
|
||||
this.push("}");
|
||||
}
|
||||
|
||||
this.push(" from ");
|
||||
@@ -92,7 +120,7 @@ export function ImportDeclaration(node, print) {
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
export function ImportBatchSpecifier(node, print) {
|
||||
export function ImportNamespaceSpecifier(node, print) {
|
||||
this.push("* as ");
|
||||
print(node.name);
|
||||
print(node.local);
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import each from "lodash/collection/each";
|
||||
|
||||
each(["BindMemberExpression", "BindFunctionExpression"], function (type) {
|
||||
exports[type] = function () {
|
||||
throw new ReferenceError(`Trying to render non-standard playground node ${JSON.stringify(type)}`);
|
||||
};
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import repeating from "repeating";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export function WithStatement(node, print) {
|
||||
this.keyword("with");
|
||||
@@ -71,7 +71,7 @@ export var ForInStatement = buildForXStatement("in");
|
||||
export var ForOfStatement = buildForXStatement("of");
|
||||
|
||||
export function DoWhileStatement(node, print) {
|
||||
this.keyword("do");
|
||||
this.push("do ");
|
||||
print(node.body);
|
||||
this.space();
|
||||
this.keyword("while");
|
||||
@@ -199,14 +199,10 @@ export function VariableDeclaration(node, print, parent) {
|
||||
|
||||
print.list(node.declarations, { separator: sep });
|
||||
|
||||
if (!t.isFor(parent)) {
|
||||
this.semicolon();
|
||||
if (t.isFor(parent)) {
|
||||
if (parent.left === node || parent.init === node) return;
|
||||
}
|
||||
}
|
||||
|
||||
export function PrivateDeclaration(node, print) {
|
||||
this.push("private ");
|
||||
print.join(node.declarations, { separator: ", " });
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,6 @@ export function RestElement(node, print) {
|
||||
|
||||
export { RestElement as SpreadElement, RestElement as SpreadProperty };
|
||||
|
||||
export function VirtualPropertyExpression(node, print) {
|
||||
print(node.object);
|
||||
this.push("::");
|
||||
print(node.property);
|
||||
}
|
||||
|
||||
export function ObjectExpression(node, print) {
|
||||
var props = node.properties;
|
||||
|
||||
@@ -105,5 +99,12 @@ export function _stringLiteral(val) {
|
||||
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
|
||||
if (this.format.quotes === "single") {
|
||||
val = val.slice(1, -1);
|
||||
val = val.replace(/\\"/g, '"');
|
||||
val = val.replace(/'/g, "\\'");
|
||||
val = `'${val}'`;
|
||||
}
|
||||
|
||||
this.push(val);
|
||||
}
|
||||
|
||||
@@ -8,15 +8,15 @@ import Buffer from "./buffer";
|
||||
import extend from "lodash/object/extend";
|
||||
import each from "lodash/collection/each";
|
||||
import n from "./node";
|
||||
import t from "../types";
|
||||
import * as t from "../types";
|
||||
|
||||
class CodeGenerator {
|
||||
constructor(ast, opts, code) {
|
||||
opts ||= {};
|
||||
opts = opts || {};
|
||||
|
||||
this.comments = ast.comments || [];
|
||||
this.tokens = ast.tokens || [];
|
||||
this.format = CodeGenerator.normalizeOptions(code, opts);
|
||||
this.format = CodeGenerator.normalizeOptions(code, opts, this.tokens);
|
||||
this.opts = opts;
|
||||
this.ast = ast;
|
||||
|
||||
@@ -26,7 +26,7 @@ class CodeGenerator {
|
||||
this.buffer = new Buffer(this.position, this.format);
|
||||
}
|
||||
|
||||
static normalizeOptions(code, opts) {
|
||||
static normalizeOptions(code, opts, tokens) {
|
||||
var style = " ";
|
||||
if (code) {
|
||||
var indent = detectIndent(code).indent;
|
||||
@@ -34,8 +34,10 @@ class CodeGenerator {
|
||||
}
|
||||
|
||||
var format = {
|
||||
retainLines: opts.retainLines,
|
||||
comments: opts.comments == null || opts.comments,
|
||||
compact: opts.compact,
|
||||
quotes: CodeGenerator.findCommonStringDelimiter(code, tokens),
|
||||
indent: {
|
||||
adjustMultilineComment: true,
|
||||
style: style,
|
||||
@@ -47,19 +49,48 @@ class CodeGenerator {
|
||||
format.compact = code.length > 100000; // 100KB
|
||||
|
||||
if (format.compact) {
|
||||
console.error(messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "100KB"));
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static findCommonStringDelimiter(code, tokens) {
|
||||
var occurences = {
|
||||
single: 0,
|
||||
double: 0
|
||||
};
|
||||
|
||||
var checked = 0;
|
||||
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
if (token.type.label !== "string") continue;
|
||||
if (checked >= 3) continue;
|
||||
|
||||
var raw = code.slice(token.start, token.end);
|
||||
if (raw[0] === "'") {
|
||||
occurences.single++;
|
||||
} else {
|
||||
occurences.double++;
|
||||
}
|
||||
|
||||
checked++;
|
||||
}
|
||||
|
||||
if (occurences.single > occurences.double) {
|
||||
return "single";
|
||||
} else {
|
||||
return "double";
|
||||
}
|
||||
}
|
||||
|
||||
static generators = {
|
||||
templateLiterals: require("./generators/template-literals"),
|
||||
comprehensions: require("./generators/comprehensions"),
|
||||
expressions: require("./generators/expressions"),
|
||||
statements: require("./generators/statements"),
|
||||
playground: require("./generators/playground"),
|
||||
classes: require("./generators/classes"),
|
||||
methods: require("./generators/methods"),
|
||||
modules: require("./generators/modules"),
|
||||
@@ -101,7 +132,7 @@ class CodeGenerator {
|
||||
};
|
||||
|
||||
print.list = function (items, opts = {}) {
|
||||
opts.separator ||= ", ";
|
||||
if (opts.separator == null) opts.separator = ", ";
|
||||
print.join(items, opts);
|
||||
};
|
||||
|
||||
@@ -116,6 +147,22 @@ class CodeGenerator {
|
||||
return print;
|
||||
}
|
||||
|
||||
catchUp(node, parent) {
|
||||
// catch up to this nodes newline if we're behind
|
||||
if (node.loc && this.format.retainLines && this.buffer.buf) {
|
||||
var needsParens = false;
|
||||
if (parent && this.position.line < node.loc.start.line && t.isTerminatorless(parent)) {
|
||||
needsParens = true;
|
||||
this._push("(");
|
||||
}
|
||||
while (this.position.line < node.loc.start.line) {
|
||||
this._push("\n");
|
||||
}
|
||||
return needsParens;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
print(node, parent, opts = {}) {
|
||||
if (!node) return;
|
||||
|
||||
@@ -167,6 +214,8 @@ class CodeGenerator {
|
||||
|
||||
this.printLeadingComments(node, parent);
|
||||
|
||||
var needsParensFromCatchup = this.catchUp(node, parent);
|
||||
|
||||
newline(true);
|
||||
|
||||
if (opts.before) opts.before();
|
||||
@@ -178,7 +227,7 @@ class CodeGenerator {
|
||||
this.newline();
|
||||
this.dedent();
|
||||
}
|
||||
if (needsParens) this.push(")");
|
||||
if (needsParens || needsParensFromCatchup) this.push(")");
|
||||
|
||||
this.map.mark(node, "end");
|
||||
if (opts.after) opts.after();
|
||||
@@ -298,6 +347,8 @@ class CodeGenerator {
|
||||
|
||||
if (skip) return;
|
||||
|
||||
this.catchUp(comment);
|
||||
|
||||
// whitespace before
|
||||
this.newline(this.whitespace.getNewlinesBefore(comment));
|
||||
|
||||
@@ -310,7 +361,6 @@ class CodeGenerator {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (comment.type === "Block" && this.format.indent.adjustMultilineComment) {
|
||||
var offset = comment.loc.start.column;
|
||||
if (offset) {
|
||||
@@ -326,8 +376,13 @@ class CodeGenerator {
|
||||
val = this.getIndent() + val;
|
||||
}
|
||||
|
||||
//
|
||||
// force a newline for line comments when retainLines is set in case the next printed node
|
||||
// doesn't catch up
|
||||
if (this.format.retainLines && comment.type === "Line") {
|
||||
val += "\n";
|
||||
}
|
||||
|
||||
//
|
||||
this._push(val);
|
||||
|
||||
// whitespace after
|
||||
|
||||
@@ -2,7 +2,7 @@ import whitespace from "./whitespace";
|
||||
import * as parens from "./parentheses";
|
||||
import each from "lodash/collection/each";
|
||||
import some from "lodash/collection/some";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
var find = function (obj, node, parent) {
|
||||
if (!obj) return;
|
||||
@@ -85,16 +85,7 @@ export default class Node {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t.isYieldExpression(parent) || t.isAwaitExpression(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.isContinueStatement(parent) || t.isBreakStatement(parent) ||
|
||||
t.isReturnStatement(parent) || t.isThrowStatement(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return t.isTerminatorless(parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
var PRECEDENCE = {};
|
||||
const PRECEDENCE = {};
|
||||
|
||||
each([
|
||||
["||"],
|
||||
@@ -171,4 +171,10 @@ export function ConditionalExpression(node, parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export { ConditionalExpression as AssignmentExpression };
|
||||
export function AssignmentExpression(node) {
|
||||
if (t.isObjectPattern(node.left)) {
|
||||
return true;
|
||||
} else {
|
||||
return ConditionalExpression(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import isBoolean from "lodash/lang/isBoolean";
|
||||
import each from "lodash/collection/each";
|
||||
import map from "lodash/collection/map";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
function crawl(node, state = {}) {
|
||||
if (t.isMemberExpression(node)) {
|
||||
@@ -16,7 +16,7 @@ function crawl(node, state = {}) {
|
||||
} else if (t.isFunction(node)) {
|
||||
state.hasFunction = true;
|
||||
} else if (t.isIdentifier(node)) {
|
||||
state.hasHelper ||= isHelper(node.callee);
|
||||
state.hasHelper = state.hasHelper || isHelper(node.callee);
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import sourceMap from "source-map";
|
||||
import t from "../types";
|
||||
import * as t from "../types";
|
||||
|
||||
export default class SourceMap {
|
||||
constructor(position, opts, code) {
|
||||
this.position = position;
|
||||
this.opts = opts;
|
||||
|
||||
if (opts.sourceMap) {
|
||||
if (opts.sourceMaps) {
|
||||
this.map = new sourceMap.SourceMapGenerator({
|
||||
file: opts.sourceMapName,
|
||||
sourceRoot: opts.sourceRoot
|
||||
|
||||
@@ -81,7 +81,7 @@ export default class Whitespace {
|
||||
}
|
||||
}
|
||||
|
||||
if (endToken && endToken.type.type === "eof") {
|
||||
if (endToken && endToken.type.label === "eof") {
|
||||
return 1;
|
||||
} else {
|
||||
var lines = this.getNewlinesBetween(startToken, endToken);
|
||||
|
||||
@@ -3,15 +3,13 @@ import repeating from "repeating";
|
||||
import jsTokens from "js-tokens";
|
||||
import esutils from "esutils";
|
||||
import chalk from "chalk";
|
||||
import ary from "lodash/function/ary";
|
||||
|
||||
var defs = {
|
||||
string: chalk.red,
|
||||
punctuator: chalk.white.bold,
|
||||
punctuator: chalk.bold,
|
||||
curly: chalk.green,
|
||||
parens: chalk.blue.bold,
|
||||
square: chalk.yellow,
|
||||
name: chalk.white,
|
||||
keyword: chalk.cyan,
|
||||
number: chalk.magenta,
|
||||
regex: chalk.magenta,
|
||||
@@ -19,50 +17,51 @@ var defs = {
|
||||
invalid: chalk.inverse
|
||||
};
|
||||
|
||||
var newline = /\r\n|[\n\r\u2028\u2029]/;
|
||||
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
||||
|
||||
var highlight = function (text) {
|
||||
var tokenType = function (match) {
|
||||
var token = jsTokens.matchToToken(match);
|
||||
if (token.type === "name" && esutils.keyword.isReservedWordES6(token.value)) {
|
||||
return "keyword";
|
||||
function getTokenType(match) {
|
||||
var token = jsTokens.matchToToken(match);
|
||||
if (token.type === "name" && esutils.keyword.isReservedWordES6(token.value)) {
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
if (token.type === "punctuator") {
|
||||
switch (token.value) {
|
||||
case "{":
|
||||
case "}":
|
||||
return "curly";
|
||||
case "(":
|
||||
case ")":
|
||||
return "parens";
|
||||
case "[":
|
||||
case "]":
|
||||
return "square";
|
||||
}
|
||||
}
|
||||
|
||||
if (token.type === "punctuator") {
|
||||
switch (token.value) {
|
||||
case "{":
|
||||
case "}":
|
||||
return "curly";
|
||||
case "(":
|
||||
case ")":
|
||||
return "parens";
|
||||
case "[":
|
||||
case "]":
|
||||
return "square";
|
||||
}
|
||||
return token.type;
|
||||
}
|
||||
|
||||
function highlight(text) {
|
||||
return text.replace(jsTokens, function (...args) {
|
||||
var type = getTokenType(args);
|
||||
var colorize = defs[type];
|
||||
if (colorize) {
|
||||
return args[0].split(NEWLINE).map(str => colorize(str)).join("\n");
|
||||
} else {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
return token.type;
|
||||
};
|
||||
|
||||
return text.replace(jsTokens, function (match) {
|
||||
var type = tokenType(arguments);
|
||||
if (type in defs) {
|
||||
var colorize = ary(defs[type], 1);
|
||||
return match.split(newline).map(colorize).join("\n");
|
||||
}
|
||||
return match;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default function (lines, lineNumber, colNumber) {
|
||||
export default function (lines: number, lineNumber: number, colNumber: number, opts = {}): string {
|
||||
colNumber = Math.max(colNumber, 0);
|
||||
|
||||
if (chalk.supportsColor) {
|
||||
if (opts.highlightCode && chalk.supportsColor) {
|
||||
lines = highlight(lines);
|
||||
}
|
||||
|
||||
lines = lines.split(newline);
|
||||
lines = lines.split(NEWLINE);
|
||||
|
||||
var start = Math.max(lineNumber - 3, 0);
|
||||
var end = Math.min(lines.length, lineNumber + 3);
|
||||
@@ -72,7 +71,7 @@ export default function (lines, lineNumber, colNumber) {
|
||||
end = lines.length;
|
||||
}
|
||||
|
||||
return "\n" + lineNumbers(lines.slice(start, end), {
|
||||
return lineNumbers(lines.slice(start, end), {
|
||||
start: start + 1,
|
||||
before: " ",
|
||||
after: " | ",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import t from "../types";
|
||||
import * as t from "../types";
|
||||
|
||||
export default function (ast, comments, tokens) {
|
||||
if (ast && ast.type === "Program") {
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
import normalizeAst from "./normalize-ast";
|
||||
import estraverse from "estraverse";
|
||||
import codeFrame from "./code-frame";
|
||||
import acorn from "acorn-babel";
|
||||
import * as acorn from "../../acorn";
|
||||
|
||||
export default function (opts, code, callback) {
|
||||
try {
|
||||
var comments = [];
|
||||
var tokens = [];
|
||||
|
||||
var ast = acorn.parse(code, {
|
||||
allowImportExportEverywhere: opts.allowImportExportEverywhere,
|
||||
allowReturnOutsideFunction: !opts._anal,
|
||||
ecmaVersion: opts.experimental ? 7 : 6,
|
||||
playground: opts.playground,
|
||||
var parseOpts = {
|
||||
allowImportExportEverywhere: opts.looseModules,
|
||||
allowReturnOutsideFunction: opts.looseModules,
|
||||
ecmaVersion: 6,
|
||||
strictMode: opts.strictMode,
|
||||
sourceType: opts.sourceType,
|
||||
onComment: comments,
|
||||
locations: true,
|
||||
features: opts.features || {},
|
||||
plugins: opts.plugins || {},
|
||||
onToken: tokens,
|
||||
ranges: true
|
||||
});
|
||||
};
|
||||
|
||||
if (opts.nonStandard) {
|
||||
parseOpts.plugins.jsx = true;
|
||||
parseOpts.plugins.flow = true;
|
||||
}
|
||||
|
||||
var ast = acorn.parse(code, parseOpts);
|
||||
|
||||
estraverse.attachComments(ast, comments, tokens);
|
||||
|
||||
@@ -32,16 +41,23 @@ export default function (opts, code, callback) {
|
||||
} catch (err) {
|
||||
if (!err._babel) {
|
||||
err._babel = true;
|
||||
var message = `${opts.filename}: ${err.message}`;
|
||||
|
||||
var message = err.message = `${opts.filename}: ${err.message}`;
|
||||
|
||||
var loc = err.loc;
|
||||
if (loc) {
|
||||
var frame = codeFrame(code, loc.line, loc.column + 1);
|
||||
message += frame;
|
||||
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, opts);
|
||||
message += "\n" + err.codeFrame;
|
||||
}
|
||||
|
||||
if (err.stack) err.stack = err.stack.replace(err.message, message);
|
||||
err.message = message;
|
||||
if (err.stack) {
|
||||
var newStack = err.stack.replace(err.message, message);
|
||||
try {
|
||||
err.stack = newStack;
|
||||
} catch (e) {
|
||||
// `err.stack` may be a readonly property in some environments
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as util from "util";
|
||||
|
||||
export var messages = {
|
||||
export const MESSAGES = {
|
||||
tailCallReassignmentDeopt: "Function reference has been reassigned so it's probably be dereferenced so we can't optimise this with confidence",
|
||||
JSXNamespacedTags: "Namespace tags are not supported. ReactJSX is not XML.",
|
||||
classesIllegalBareSuper: "Illegal use of bare super",
|
||||
@@ -21,17 +21,26 @@ export var messages = {
|
||||
evalInStrictMode: "eval is not allowed in strict mode",
|
||||
codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.",
|
||||
missingTemplatesDirectory: "no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues",
|
||||
unsupportedOutputType: "Unsupported output type $1"
|
||||
unsupportedOutputType: "Unsupported output type $1",
|
||||
illegalMethodName: "Illegal method name $1",
|
||||
traverseNeedsParent: "Must pass a scope and parentPath unless traversing a Program/File got a $1 node",
|
||||
traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?",
|
||||
traverseVerifyVisitorFunction: "Hey! You passed \`traverse()\` a visitor object with the key $1 that's a straight up `Function` instead of `{ enter: Function }`. You need to normalise it with `traverse.explode(visitor)`.",
|
||||
traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2",
|
||||
|
||||
pluginIllegalKind: "Illegal kind $1 for plugin $2",
|
||||
pluginIllegalPosition: "Illegal position $1 for plugin $2",
|
||||
pluginKeyCollision: "The plugin $1 collides with another of the same name",
|
||||
pluginNotTransformer: "The plugin $1 didn't export a Transformer instance",
|
||||
pluginUnknown: "Unknown plugin $1",
|
||||
|
||||
transformerNotFile: "Transformer $1 is resolving to a different Babel version to what is doing the actual transformation..."
|
||||
};
|
||||
|
||||
export function get(key) {
|
||||
var msg = messages[key];
|
||||
export function get(key: String, ...args) {
|
||||
var msg = MESSAGES[key];
|
||||
if (!msg) throw new ReferenceError(`Unknown message ${JSON.stringify(key)}`);
|
||||
|
||||
var args = [];
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
args = parseArgs(args);
|
||||
|
||||
return msg.replace(/\$(\d+)/g, function (str, i) {
|
||||
@@ -39,7 +48,7 @@ export function get(key) {
|
||||
});
|
||||
}
|
||||
|
||||
export function parseArgs(args) {
|
||||
export function parseArgs(args: Array<any>) {
|
||||
return args.map(function (val) {
|
||||
if (val != null && val.inspect) {
|
||||
return val.inspect();
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import estraverse from "estraverse";
|
||||
import extend from "lodash/object/extend";
|
||||
import types from "ast-types";
|
||||
import t from "./types";
|
||||
import * as t from "./types";
|
||||
|
||||
// estraverse
|
||||
|
||||
extend(estraverse.VisitorKeys, t.VISITOR_KEYS);
|
||||
|
||||
// regenerator-babel/ast-types
|
||||
// regenerator/ast-types
|
||||
|
||||
var def = types.Type.def;
|
||||
var or = types.Type.or;
|
||||
var def = types.Type.def;
|
||||
var or = types.Type.or;
|
||||
|
||||
def("File")
|
||||
.bases("Node")
|
||||
.build("program")
|
||||
.field("program", def("Program"));
|
||||
//def("File")
|
||||
// .bases("Node")
|
||||
// .build("program")
|
||||
// .field("program", def("Program"));
|
||||
|
||||
def("AssignmentPattern")
|
||||
.bases("Pattern")
|
||||
@@ -23,41 +23,50 @@ def("AssignmentPattern")
|
||||
.field("left", def("Pattern"))
|
||||
.field("right", def("Expression"));
|
||||
|
||||
// Acorn - Same as ImportNamespaceSpecifier but `id` is `name`
|
||||
def("ImportBatchSpecifier")
|
||||
.bases("Specifier")
|
||||
.build("name")
|
||||
.field("name", def("Identifier"));
|
||||
|
||||
def("RestElement")
|
||||
.bases("Pattern")
|
||||
.build("argument")
|
||||
.field("argument", def("expression"));
|
||||
|
||||
// Abstract references
|
||||
def("VirtualPropertyExpression")
|
||||
def("DoExpression")
|
||||
.bases("Expression")
|
||||
.build("object", "property")
|
||||
.field("object", def("Expression"))
|
||||
.field("property", or(def("Identifier"), def("Expression")));
|
||||
.build("body")
|
||||
.field("body", [def("Statement")]);
|
||||
|
||||
def("PrivateDeclaration")
|
||||
def("ExportDefaultDeclaration")
|
||||
.bases("Declaration")
|
||||
.build("declarations")
|
||||
.field("declarations", [def("Identifier")]);
|
||||
.build("declaration")
|
||||
.field("declaration", or(
|
||||
def("Declaration"),
|
||||
def("Expression"),
|
||||
null
|
||||
));
|
||||
|
||||
// Playground
|
||||
def("BindMemberExpression")
|
||||
.bases("Expression")
|
||||
.build("object", "property", "arguments")
|
||||
.field("object", def("Expression"))
|
||||
.field("property", or(def("Identifier"), def("Expression")))
|
||||
.field("arguments", [def("Expression")]);
|
||||
def("ExportNamedDeclaration")
|
||||
.bases("Declaration")
|
||||
.build("declaration")
|
||||
.field("declaration", or(
|
||||
def("Declaration"),
|
||||
def("Expression"),
|
||||
null
|
||||
))
|
||||
.field("specifiers", [or(
|
||||
def("ExportSpecifier")
|
||||
)])
|
||||
.field("source", or(def("ModuleSpecifier"), null));
|
||||
|
||||
def("BindFunctionExpression")
|
||||
.bases("Expression")
|
||||
.build("callee", "arguments")
|
||||
.field("callee", def("Expression"))
|
||||
.field("arguments", [def("Expression")]);
|
||||
def("ExportNamespaceSpecifier")
|
||||
.bases("Specifier")
|
||||
.field("exported", def("Identifier"));
|
||||
|
||||
def("ExportDefaultSpecifier")
|
||||
.bases("Specifier")
|
||||
.field("exported", def("Identifier"));
|
||||
|
||||
def("ExportAllDeclaration")
|
||||
.bases("Declaration")
|
||||
.build("exported", "source")
|
||||
.field("exported", def("Identifier"))
|
||||
.field("source", def("Literal"));
|
||||
|
||||
types.finalize();
|
||||
|
||||
@@ -4,4 +4,4 @@ if (global._babelPolyfill) {
|
||||
global._babelPolyfill = true;
|
||||
|
||||
import "core-js/shim";
|
||||
import "regenerator-babel/runtime";
|
||||
import "regenerator/runtime";
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import buildHelpers from "./build-helpers";
|
||||
import generator from "./generation";
|
||||
import * as messages from "./messages";
|
||||
import * as util from "./util";
|
||||
import t from "./types";
|
||||
import generator from "../generation";
|
||||
import * as messages from "../messages";
|
||||
import * as util from "../util";
|
||||
import File from "../transformation/file";
|
||||
import each from "lodash/collection/each";
|
||||
import * as t from "../types";
|
||||
|
||||
function buildGlobal(namespace, builder) {
|
||||
var body = [];
|
||||
var container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
|
||||
var tree = t.program([t.expressionStatement(t.callExpression(container, [util.template("self-global")]))]);
|
||||
var tree = t.program([t.expressionStatement(t.callExpression(container, [util.template("helper-self-global")]))]);
|
||||
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
@@ -49,8 +50,20 @@ function buildVar(namespace, builder) {
|
||||
return t.program(body);
|
||||
}
|
||||
|
||||
function buildHelpers(body, namespace, whitelist) {
|
||||
each(File.helpers, function (name) {
|
||||
if (whitelist && whitelist.indexOf(name) === -1) return;
|
||||
|
||||
var key = t.identifier(t.toIdentifier(name));
|
||||
body.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", t.memberExpression(namespace, key), util.template("helper-" + name))
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
export default function (whitelist, outputType = "global") {
|
||||
var namespace = t.identifier("babelHelpers");
|
||||
|
||||
var builder = function (body) {
|
||||
return buildHelpers(body, namespace, whitelist);
|
||||
};
|
||||
@@ -1,10 +1,14 @@
|
||||
import stripJsonComments from "strip-json-comments";
|
||||
import merge from "lodash/object/merge";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
var cache = {};
|
||||
var jsons = {};
|
||||
|
||||
function exists(filename) {
|
||||
if (!fs.existsSync) return false;
|
||||
|
||||
var cached = cache[filename];
|
||||
if (cached != null) return cached;
|
||||
return cache[filename] = fs.existsSync(filename);
|
||||
@@ -13,24 +17,40 @@ function exists(filename) {
|
||||
export default function (loc, opts = {}) {
|
||||
var rel = ".babelrc";
|
||||
|
||||
if (!opts.babelrc) {
|
||||
opts.babelrc = [];
|
||||
}
|
||||
|
||||
function find(start, rel) {
|
||||
var file = path.join(start, rel);
|
||||
|
||||
if (opts.babelrc.indexOf(file) >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (exists(file)) {
|
||||
var content = fs.readFileSync(file, "utf8");
|
||||
var json;
|
||||
|
||||
try {
|
||||
json = JSON.parse(content);
|
||||
json = jsons[content] = jsons[content] || JSON.parse(stripJsonComments(content));
|
||||
} catch (err) {
|
||||
err.message = `${file}: ${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
|
||||
opts.babelrc.push(file);
|
||||
|
||||
if (json.breakConfig) return;
|
||||
merge(opts, json, function(a, b) {
|
||||
if (Array.isArray(a)) {
|
||||
return a.concat(b);
|
||||
var c = a.slice(0);
|
||||
for (var v of b) {
|
||||
if (a.indexOf(v) < 0) {
|
||||
c.push(v);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -41,7 +61,9 @@ export default function (loc, opts = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
find(loc, rel);
|
||||
if (opts.babelrc.indexOf(loc) < 0 && opts.breakConfig !== true) {
|
||||
find(loc, rel);
|
||||
}
|
||||
|
||||
return opts;
|
||||
};
|
||||
@@ -1,540 +0,0 @@
|
||||
import convertSourceMap from "convert-source-map";
|
||||
import shebangRegex from "shebang-regex";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import sourceMap from "source-map";
|
||||
import transform from "./index";
|
||||
import generate from "../generation";
|
||||
import defaults from "lodash/object/defaults";
|
||||
import includes from "lodash/collection/includes";
|
||||
import assign from "lodash/object/assign";
|
||||
import parse from "../helpers/parse";
|
||||
import Scope from "../traversal/scope";
|
||||
import slash from "slash";
|
||||
import * as util from "../util";
|
||||
import path from "path";
|
||||
import each from "lodash/collection/each";
|
||||
import t from "../types";
|
||||
|
||||
var checkTransformerVisitor = {
|
||||
enter(node, parent, scope, state) {
|
||||
checkNode(state.stack, node, scope);
|
||||
}
|
||||
};
|
||||
|
||||
function checkNode(stack, node, scope) {
|
||||
each(stack, function (pass) {
|
||||
if (pass.shouldRun) return;
|
||||
pass.checkNode(node, scope);
|
||||
});
|
||||
}
|
||||
|
||||
export default class File {
|
||||
constructor(opts) {
|
||||
this.dynamicImportedNoDefault = [];
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImported = [];
|
||||
this.dynamicImports = [];
|
||||
|
||||
this.usedHelpers = {};
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
|
||||
this.lastStatements = [];
|
||||
this.opts = this.normalizeOptions(opts);
|
||||
this.ast = {};
|
||||
|
||||
this.buildTransformers();
|
||||
}
|
||||
|
||||
static helpers = [
|
||||
"inherits",
|
||||
"defaults",
|
||||
"create-class",
|
||||
"apply-constructor",
|
||||
"tagged-template-literal",
|
||||
"tagged-template-literal-loose",
|
||||
"interop-require",
|
||||
"to-array",
|
||||
"to-consumable-array",
|
||||
"sliced-to-array",
|
||||
"object-without-properties",
|
||||
"has-own",
|
||||
"slice",
|
||||
"bind",
|
||||
"define-property",
|
||||
"async-to-generator",
|
||||
"interop-require-wildcard",
|
||||
"typeof",
|
||||
"extends",
|
||||
"get",
|
||||
"set",
|
||||
"class-call-check",
|
||||
"object-destructuring-empty",
|
||||
"temporal-undefined",
|
||||
"temporal-assert-defined",
|
||||
"self-global"
|
||||
];
|
||||
|
||||
static validOptions = [
|
||||
"filename",
|
||||
"filenameRelative",
|
||||
|
||||
"blacklist",
|
||||
"whitelist",
|
||||
"optional",
|
||||
|
||||
"loose",
|
||||
"playground",
|
||||
"experimental",
|
||||
|
||||
"modules",
|
||||
"moduleIds",
|
||||
"moduleId",
|
||||
"resolveModuleSource",
|
||||
"keepModuleIdExtensions",
|
||||
|
||||
"code",
|
||||
"ast",
|
||||
|
||||
"comments",
|
||||
"compact",
|
||||
|
||||
"auxiliaryComment",
|
||||
"externalHelpers",
|
||||
"returnUsedHelpers",
|
||||
|
||||
"inputSourceMap",
|
||||
"sourceMap",
|
||||
"sourceMapName",
|
||||
"sourceFileName",
|
||||
"sourceRoot",
|
||||
"moduleRoot",
|
||||
|
||||
// legacy
|
||||
"format",
|
||||
"reactCompat",
|
||||
|
||||
// these are used by plugins
|
||||
"ignore",
|
||||
"only",
|
||||
"extensions",
|
||||
"accept"
|
||||
];
|
||||
|
||||
normalizeOptions(opts) {
|
||||
opts = assign({}, opts);
|
||||
|
||||
for (var key in opts) {
|
||||
if (key[0] !== "_" && File.validOptions.indexOf(key) < 0) {
|
||||
throw new ReferenceError(`Unknown option: ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
defaults(opts, {
|
||||
keepModuleIdExtensions: false,
|
||||
resolveModuleSource: null,
|
||||
returnUsedHelpers: false,
|
||||
externalHelpers: false,
|
||||
auxilaryComment: "",
|
||||
inputSourceMap: false,
|
||||
experimental: false,
|
||||
reactCompat: false,
|
||||
playground: false,
|
||||
moduleIds: false,
|
||||
blacklist: [],
|
||||
whitelist: [],
|
||||
sourceMap: false,
|
||||
optional: [],
|
||||
comments: true,
|
||||
filename: "unknown",
|
||||
modules: "common",
|
||||
compact: "auto",
|
||||
loose: [],
|
||||
code: true,
|
||||
ast: true
|
||||
});
|
||||
|
||||
if (opts.inputSourceMap) {
|
||||
opts.sourceMap = true;
|
||||
}
|
||||
|
||||
// normalize windows path separators to unix
|
||||
opts.filename = slash(opts.filename);
|
||||
if (opts.sourceRoot) {
|
||||
opts.sourceRoot = slash(opts.sourceRoot);
|
||||
}
|
||||
|
||||
if (opts.moduleId) {
|
||||
opts.moduleIds = true;
|
||||
}
|
||||
|
||||
opts.basename = path.basename(opts.filename, path.extname(opts.filename));
|
||||
|
||||
opts.blacklist = util.arrayify(opts.blacklist);
|
||||
opts.whitelist = util.arrayify(opts.whitelist);
|
||||
opts.optional = util.arrayify(opts.optional);
|
||||
opts.compact = util.booleanify(opts.compact);
|
||||
opts.loose = util.arrayify(opts.loose);
|
||||
|
||||
if (includes(opts.loose, "all") || includes(opts.loose, true)) {
|
||||
opts.loose = Object.keys(transform.transformers);
|
||||
}
|
||||
|
||||
defaults(opts, {
|
||||
moduleRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceRoot: opts.moduleRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
filenameRelative: opts.filename
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceFileName: opts.filenameRelative,
|
||||
sourceMapName: opts.filenameRelative
|
||||
});
|
||||
|
||||
if (opts.playground) {
|
||||
opts.experimental = true;
|
||||
}
|
||||
|
||||
if (opts.externalHelpers) {
|
||||
this.set("helpersNamespace", t.identifier("babelHelpers"));
|
||||
}
|
||||
|
||||
opts.blacklist = transform._ensureTransformerNames("blacklist", opts.blacklist);
|
||||
opts.whitelist = transform._ensureTransformerNames("whitelist", opts.whitelist);
|
||||
opts.optional = transform._ensureTransformerNames("optional", opts.optional);
|
||||
opts.loose = transform._ensureTransformerNames("loose", opts.loose);
|
||||
|
||||
if (opts.reactCompat) {
|
||||
opts.optional.push("reactCompat");
|
||||
console.error("The reactCompat option has been moved into the optional transformer `reactCompat`");
|
||||
}
|
||||
|
||||
var ensureEnabled = function (key) {
|
||||
var namespace = transform.transformerNamespaces[key];
|
||||
if (namespace === "es7") opts.experimental = true;
|
||||
if (namespace === "playground") opts.playground = true;
|
||||
};
|
||||
|
||||
each(opts.whitelist, ensureEnabled);
|
||||
each(opts.optional, ensureEnabled);
|
||||
|
||||
return opts;
|
||||
};
|
||||
|
||||
isLoose(key) {
|
||||
return includes(this.opts.loose, key);
|
||||
}
|
||||
|
||||
buildTransformers() {
|
||||
var file = this;
|
||||
|
||||
var transformers = {};
|
||||
|
||||
var secondaryStack = [];
|
||||
var stack = [];
|
||||
|
||||
each(transform.transformers, function (transformer, key) {
|
||||
var pass = transformers[key] = transformer.buildPass(file);
|
||||
|
||||
if (pass.canRun(file)) {
|
||||
stack.push(pass);
|
||||
|
||||
if (transformer.secondPass) {
|
||||
secondaryStack.push(pass);
|
||||
}
|
||||
|
||||
if (transformer.manipulateOptions) {
|
||||
transformer.manipulateOptions(file.opts, file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.transformerStack = stack.concat(secondaryStack);
|
||||
this.transformers = transformers;
|
||||
}
|
||||
|
||||
debug(msg) {
|
||||
var parts = this.opts.filename;
|
||||
if (msg) parts += `: ${msg}`;
|
||||
util.debug(parts);
|
||||
}
|
||||
|
||||
getModuleFormatter(type) {
|
||||
var ModuleFormatter = isFunction(type) ? type : transform.moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolve(type);
|
||||
if (loc) ModuleFormatter = require(loc);
|
||||
}
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
throw new ReferenceError(`Unknown module formatter type ${JSON.stringify(type)}`);
|
||||
}
|
||||
|
||||
return new ModuleFormatter(this);
|
||||
}
|
||||
|
||||
parseInputSourceMap(code) {
|
||||
var opts = this.opts;
|
||||
|
||||
var inputMap = convertSourceMap.fromSource(code);
|
||||
if (inputMap) {
|
||||
opts.inputSourceMap = inputMap.toObject();
|
||||
code = convertSourceMap.removeComments(code);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
parseShebang(code) {
|
||||
var shebangMatch = shebangRegex.exec(code);
|
||||
|
||||
if (shebangMatch) {
|
||||
this.shebang = shebangMatch[0];
|
||||
|
||||
// remove shebang
|
||||
code = code.replace(shebangRegex, "");
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
set(key, val) {
|
||||
return this.data[key] = val;
|
||||
};
|
||||
|
||||
setDynamic(key, fn) {
|
||||
this.dynamicData[key] = fn;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
var data = this.data[key];
|
||||
if (data) {
|
||||
return data;
|
||||
} else {
|
||||
var dynamic = this.dynamicData[key];
|
||||
if (dynamic) {
|
||||
return this.set(key, dynamic());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addImport(source, name, noDefault) {
|
||||
name ||= source;
|
||||
var id = this.dynamicImportIds[name];
|
||||
|
||||
if (!id) {
|
||||
id = this.dynamicImportIds[name] = this.scope.generateUidIdentifier(name);
|
||||
|
||||
var specifiers = [t.importSpecifier(t.identifier("default"), id)];
|
||||
var declar = t.importDeclaration(specifiers, t.literal(source));
|
||||
declar._blockHoist = 3;
|
||||
|
||||
this.dynamicImported.push(declar);
|
||||
if (noDefault) this.dynamicImportedNoDefault.push(declar);
|
||||
|
||||
if (this.transformers["es6.modules"].canRun()) {
|
||||
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);
|
||||
} else {
|
||||
this.dynamicImports.push(declar);
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
isConsequenceExpressionStatement(node) {
|
||||
return t.isExpressionStatement(node) && this.lastStatements.indexOf(node) >= 0;
|
||||
}
|
||||
|
||||
attachAuxiliaryComment(node) {
|
||||
var comment = this.opts.auxiliaryComment;
|
||||
if (comment) {
|
||||
node.leadingComments ||= [];
|
||||
node.leadingComments.push({
|
||||
type: "Line",
|
||||
value: " " + comment
|
||||
});
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
addHelper(name) {
|
||||
if (!includes(File.helpers, name)) {
|
||||
throw new ReferenceError(`Unknown helper ${name}`);
|
||||
}
|
||||
|
||||
var program = this.ast.program;
|
||||
|
||||
var declar = program._declarations && program._declarations[name];
|
||||
if (declar) return declar.id;
|
||||
|
||||
this.usedHelpers[name] = true;
|
||||
|
||||
var runtime = this.get("helpersNamespace");
|
||||
if (runtime) {
|
||||
name = t.identifier(t.toIdentifier(name));
|
||||
return t.memberExpression(runtime, name);
|
||||
} else {
|
||||
var ref = util.template(name);
|
||||
ref._compact = true;
|
||||
var uid = this.scope.generateUidIdentifier(name);
|
||||
this.scope.push({
|
||||
key: name,
|
||||
id: uid,
|
||||
init: ref
|
||||
});
|
||||
return uid;
|
||||
}
|
||||
}
|
||||
|
||||
logDeopt() {
|
||||
// todo, (node, msg)
|
||||
}
|
||||
|
||||
errorWithNode(node, msg, Error = SyntaxError) {
|
||||
var loc = node.loc.start;
|
||||
var err = new Error(`Line ${loc.line}: ${msg}`);
|
||||
err.loc = loc;
|
||||
return err;
|
||||
}
|
||||
|
||||
addCode(code) {
|
||||
code = (code || "") + "";
|
||||
code = this.parseInputSourceMap(code);
|
||||
this.code = code;
|
||||
return this.parseShebang(code);
|
||||
}
|
||||
|
||||
parse(code) {
|
||||
code = this.addCode(code);
|
||||
|
||||
var opts = this.opts;
|
||||
|
||||
opts.allowImportExportEverywhere = this.isLoose("es6.modules");
|
||||
opts.strictMode = this.transformers.strict.canRun();
|
||||
|
||||
return parse(opts, code, (tree) => {
|
||||
this.transform(tree);
|
||||
return this.generate();
|
||||
});
|
||||
}
|
||||
|
||||
transform(ast) {
|
||||
this.debug();
|
||||
|
||||
this.ast = ast;
|
||||
this.lastStatements = t.getLastStatements(ast.program);
|
||||
this.scope = new Scope(ast.program, ast, null, this);
|
||||
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canRun()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
|
||||
this.checkNode(ast);
|
||||
|
||||
this.call("pre");
|
||||
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
|
||||
this.call("post");
|
||||
}
|
||||
|
||||
call(key) {
|
||||
var stack = this.transformerStack;
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var transformer = stack[i].transformer;
|
||||
if (transformer[key]) {
|
||||
transformer[key](this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkNode(node, scope) {
|
||||
if (Array.isArray(node)) {
|
||||
for (var i = 0; i < node.length; i++) {
|
||||
this.checkNode(node[i], scope);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var stack = this.transformerStack;
|
||||
scope ||= this.scope;
|
||||
|
||||
checkNode(stack, node, scope);
|
||||
|
||||
scope.traverse(node, checkTransformerVisitor, {
|
||||
stack: stack
|
||||
});
|
||||
}
|
||||
|
||||
mergeSourceMap(map) {
|
||||
var opts = this.opts;
|
||||
|
||||
var inputMap = opts.inputSourceMap;
|
||||
|
||||
if (inputMap) {
|
||||
map.sources[0] = inputMap.file;
|
||||
|
||||
var inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap);
|
||||
var outputMapConsumer = new sourceMap.SourceMapConsumer(map);
|
||||
var outputMapGenerator = sourceMap.SourceMapGenerator.fromSourceMap(outputMapConsumer);
|
||||
outputMapGenerator.applySourceMap(inputMapConsumer);
|
||||
|
||||
var mergedMap = outputMapGenerator.toJSON();
|
||||
mergedMap.sources = inputMap.sources
|
||||
mergedMap.file = inputMap.file;
|
||||
return mergedMap;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
generate() {
|
||||
var opts = this.opts;
|
||||
var ast = this.ast;
|
||||
|
||||
var result = {
|
||||
code: "",
|
||||
map: null,
|
||||
ast: null
|
||||
};
|
||||
|
||||
if (this.opts.returnUsedHelpers) {
|
||||
result.usedHelpers = Object.keys(this.usedHelpers);
|
||||
}
|
||||
|
||||
if (opts.ast) result.ast = ast;
|
||||
if (!opts.code) return result;
|
||||
|
||||
var _result = generate(ast, opts, this.code);
|
||||
result.code = _result.code;
|
||||
result.map = _result.map;
|
||||
|
||||
if (this.shebang) {
|
||||
// add back shebang
|
||||
result.code = `${this.shebang}\n${result.code}`;
|
||||
}
|
||||
|
||||
result.map = this.mergeSourceMap(result.map);
|
||||
|
||||
if (opts.sourceMap === "inline" || opts.sourceMap === "both") {
|
||||
result.code += "\n" + convertSourceMap.fromObject(result.map).toComment();
|
||||
}
|
||||
|
||||
if (opts.sourceMap === "both") {
|
||||
result.map = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
583
src/babel/transformation/file/index.js
Normal file
583
src/babel/transformation/file/index.js
Normal file
@@ -0,0 +1,583 @@
|
||||
import convertSourceMap from "convert-source-map";
|
||||
import * as optionParsers from "./option-parsers";
|
||||
import moduleFormatters from "../modules";
|
||||
import PluginManager from "./plugin-manager";
|
||||
import shebangRegex from "shebang-regex";
|
||||
import TraversalPath from "../../traversal/path";
|
||||
import isFunction from "lodash/lang/isFunction";
|
||||
import isAbsolute from "path-is-absolute";
|
||||
import resolveRc from "../../tools/resolve-rc";
|
||||
import sourceMap from "source-map";
|
||||
import transform from "./../index";
|
||||
import generate from "../../generation";
|
||||
import defaults from "lodash/object/defaults";
|
||||
import includes from "lodash/collection/includes";
|
||||
import traverse from "../../traversal";
|
||||
import assign from "lodash/object/assign";
|
||||
import Logger from "./logger";
|
||||
import parse from "../../helpers/parse";
|
||||
import Scope from "../../traversal/scope";
|
||||
import slash from "slash";
|
||||
import clone from "lodash/lang/clone";
|
||||
import * as util from "../../util";
|
||||
import * as api from "../../api/node";
|
||||
import path from "path";
|
||||
import each from "lodash/collection/each";
|
||||
import * as t from "../../types";
|
||||
|
||||
var checkTransformerVisitor = {
|
||||
exit(node, parent, scope, state) {
|
||||
checkPath(state.stack, this);
|
||||
}
|
||||
};
|
||||
|
||||
function checkPath(stack, path) {
|
||||
each(stack, function (pass) {
|
||||
if (pass.shouldRun || pass.ran) return;
|
||||
pass.checkPath(path);
|
||||
});
|
||||
}
|
||||
|
||||
export default class File {
|
||||
constructor(opts = {}, pipeline) {
|
||||
this.dynamicImportTypes = {};
|
||||
this.dynamicImportIds = {};
|
||||
this.dynamicImports = [];
|
||||
|
||||
this.declarations = {};
|
||||
this.usedHelpers = {};
|
||||
this.dynamicData = {};
|
||||
this.data = {};
|
||||
this.uids = {};
|
||||
|
||||
this.pipeline = pipeline;
|
||||
this.log = new Logger(this, opts.filename || "unknown");
|
||||
this.opts = this.normalizeOptions(opts);
|
||||
this.ast = {};
|
||||
|
||||
this.buildTransformers();
|
||||
}
|
||||
|
||||
static helpers = [
|
||||
"inherits",
|
||||
"defaults",
|
||||
"create-class",
|
||||
"create-decorated-class",
|
||||
"create-decorated-object",
|
||||
"define-decorated-property-descriptor",
|
||||
"tagged-template-literal",
|
||||
"tagged-template-literal-loose",
|
||||
"to-array",
|
||||
"to-consumable-array",
|
||||
"sliced-to-array",
|
||||
"sliced-to-array-loose",
|
||||
"object-without-properties",
|
||||
"has-own",
|
||||
"slice",
|
||||
"bind",
|
||||
"define-property",
|
||||
"async-to-generator",
|
||||
"interop-require-wildcard",
|
||||
"interop-require-default",
|
||||
"typeof",
|
||||
"extends",
|
||||
"get",
|
||||
"set",
|
||||
"class-call-check",
|
||||
"object-destructuring-empty",
|
||||
"temporal-undefined",
|
||||
"temporal-assert-defined",
|
||||
"self-global",
|
||||
"default-props",
|
||||
"instanceof",
|
||||
|
||||
// legacy
|
||||
"interop-require",
|
||||
];
|
||||
|
||||
static soloHelpers = [
|
||||
"ludicrous-proxy-create",
|
||||
"ludicrous-proxy-directory"
|
||||
];
|
||||
|
||||
static options = require("./options");
|
||||
|
||||
normalizeOptions(opts: Object) {
|
||||
opts = assign({}, opts);
|
||||
|
||||
if (opts.filename) {
|
||||
var rcFilename = opts.filename;
|
||||
if (!isAbsolute(rcFilename)) rcFilename = path.join(process.cwd(), rcFilename);
|
||||
opts = resolveRc(rcFilename, opts);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (let key in opts) {
|
||||
if (key[0] === "_") continue;
|
||||
|
||||
let option = File.options[key];
|
||||
if (!option) this.log.error(`Unknown option: ${key}`, ReferenceError);
|
||||
}
|
||||
|
||||
for (let key in File.options) {
|
||||
let option = File.options[key];
|
||||
|
||||
var val = opts[key];
|
||||
if (!val && option.optional) continue;
|
||||
|
||||
if (val && option.deprecated) {
|
||||
throw new Error("Deprecated option " + key + ": " + option.deprecated);
|
||||
}
|
||||
|
||||
if (val == null) {
|
||||
val = clone(option.default);
|
||||
}
|
||||
|
||||
var optionParser = optionParsers[option.type];
|
||||
if (optionParser) val = optionParser(key, val, this.pipeline);
|
||||
|
||||
if (option.alias) {
|
||||
opts[option.alias] = opts[option.alias] || val;
|
||||
} else {
|
||||
opts[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.inputSourceMap) {
|
||||
opts.sourceMaps = true;
|
||||
}
|
||||
|
||||
// normalize windows path separators to unix
|
||||
opts.filename = slash(opts.filename);
|
||||
if (opts.sourceRoot) {
|
||||
opts.sourceRoot = slash(opts.sourceRoot);
|
||||
}
|
||||
|
||||
if (opts.moduleId) {
|
||||
opts.moduleIds = true;
|
||||
}
|
||||
|
||||
opts.basename = path.basename(opts.filename, path.extname(opts.filename));
|
||||
|
||||
opts.ignore = util.arrayify(opts.ignore, util.regexify);
|
||||
opts.only = util.arrayify(opts.only, util.regexify);
|
||||
|
||||
defaults(opts, {
|
||||
moduleRoot: opts.sourceRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceRoot: opts.moduleRoot
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
filenameRelative: opts.filename
|
||||
});
|
||||
|
||||
defaults(opts, {
|
||||
sourceFileName: opts.filenameRelative,
|
||||
sourceMapName: opts.filenameRelative
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
if (opts.externalHelpers) {
|
||||
this.set("helpersNamespace", t.identifier("babelHelpers"));
|
||||
}
|
||||
|
||||
return opts;
|
||||
};
|
||||
|
||||
isLoose(key: string) {
|
||||
return includes(this.opts.loose, key);
|
||||
}
|
||||
|
||||
buildTransformers() {
|
||||
var file = this;
|
||||
|
||||
var transformers = this.transformers = {};
|
||||
|
||||
var secondaryStack = [];
|
||||
var stack = [];
|
||||
|
||||
// build internal transformers
|
||||
each(this.pipeline.transformers, function (transformer, key) {
|
||||
var pass = transformers[key] = transformer.buildPass(file);
|
||||
|
||||
if (pass.canTransform()) {
|
||||
stack.push(pass);
|
||||
|
||||
if (transformer.metadata.secondPass) {
|
||||
secondaryStack.push(pass);
|
||||
}
|
||||
|
||||
if (transformer.manipulateOptions) {
|
||||
transformer.manipulateOptions(file.opts, file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// init plugins!
|
||||
var beforePlugins = [];
|
||||
var afterPlugins = [];
|
||||
var pluginManager = new PluginManager({
|
||||
file: this,
|
||||
transformers: this.transformers,
|
||||
before: beforePlugins,
|
||||
after: afterPlugins
|
||||
});
|
||||
for (var i = 0; i < file.opts.plugins.length; i++) {
|
||||
pluginManager.add(file.opts.plugins[i]);
|
||||
}
|
||||
stack = beforePlugins.concat(stack, afterPlugins);
|
||||
|
||||
// register
|
||||
this.transformerStack = stack.concat(secondaryStack);
|
||||
}
|
||||
|
||||
getModuleFormatter(type: string) {
|
||||
var ModuleFormatter = isFunction(type) ? type : moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolveRelative(type);
|
||||
if (loc) ModuleFormatter = require(loc);
|
||||
}
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
throw new ReferenceError(`Unknown module formatter type ${JSON.stringify(type)}`);
|
||||
}
|
||||
|
||||
return new ModuleFormatter(this);
|
||||
}
|
||||
|
||||
parseInputSourceMap(code: string) {
|
||||
var opts = this.opts;
|
||||
|
||||
if (opts.inputSourceMap !== false) {
|
||||
var inputMap = convertSourceMap.fromSource(code);
|
||||
if (inputMap) {
|
||||
opts.inputSourceMap = inputMap.toObject();
|
||||
code = convertSourceMap.removeComments(code);
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
parseShebang(code: string) {
|
||||
var shebangMatch = shebangRegex.exec(code);
|
||||
|
||||
if (shebangMatch) {
|
||||
this.shebang = shebangMatch[0];
|
||||
|
||||
// remove shebang
|
||||
code = code.replace(shebangRegex, "");
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
set(key: string, val): any {
|
||||
return this.data[key] = val;
|
||||
};
|
||||
|
||||
setDynamic(key: string, fn: Function) {
|
||||
this.dynamicData[key] = fn;
|
||||
}
|
||||
|
||||
get(key: string): any {
|
||||
var data = this.data[key];
|
||||
if (data) {
|
||||
return data;
|
||||
} else {
|
||||
var dynamic = this.dynamicData[key];
|
||||
if (dynamic) {
|
||||
return this.set(key, dynamic());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolveModuleSource(source: string): string {
|
||||
var resolveModuleSource = this.opts.resolveModuleSource;
|
||||
if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename);
|
||||
return source;
|
||||
}
|
||||
|
||||
addImport(source: string, name?: string, type?: string): Object {
|
||||
name = name || source;
|
||||
var id = this.dynamicImportIds[name];
|
||||
|
||||
if (!id) {
|
||||
source = this.resolveModuleSource(source);
|
||||
id = this.dynamicImportIds[name] = this.scope.generateUidIdentifier(name);
|
||||
|
||||
var specifiers = [t.importDefaultSpecifier(id)];
|
||||
var declar = t.importDeclaration(specifiers, t.literal(source));
|
||||
declar._blockHoist = 3;
|
||||
|
||||
if (type) {
|
||||
var modules = this.dynamicImportTypes[type] = this.dynamicImportTypes[type] || [];
|
||||
modules.push(declar);
|
||||
}
|
||||
|
||||
if (this.transformers["es6.modules"].canTransform()) {
|
||||
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);
|
||||
this.moduleFormatter.hasLocalImports = true;
|
||||
} else {
|
||||
this.dynamicImports.push(declar);
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
attachAuxiliaryComment(node: Object): Object {
|
||||
var comment = this.opts.auxiliaryComment;
|
||||
if (comment) {
|
||||
node.leadingComments = node.leadingComments || [];
|
||||
node.leadingComments.push({
|
||||
type: "Line",
|
||||
value: " " + comment
|
||||
});
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
addHelper(name: string): Object {
|
||||
var isSolo = includes(File.soloHelpers, name);
|
||||
|
||||
if (!isSolo && !includes(File.helpers, name)) {
|
||||
throw new ReferenceError(`Unknown helper ${name}`);
|
||||
}
|
||||
|
||||
var program = this.ast.program;
|
||||
|
||||
var declar = this.declarations[name];
|
||||
if (declar) return declar;
|
||||
|
||||
this.usedHelpers[name] = true;
|
||||
|
||||
if (!isSolo) {
|
||||
var generator = this.get("helperGenerator");
|
||||
var runtime = this.get("helpersNamespace");
|
||||
if (generator) {
|
||||
return generator(name);
|
||||
} else if (runtime) {
|
||||
var id = t.identifier(t.toIdentifier(name));
|
||||
return t.memberExpression(runtime, id);
|
||||
}
|
||||
}
|
||||
|
||||
var ref = util.template("helper-" + name);
|
||||
ref._compact = true;
|
||||
var uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
|
||||
this.scope.push({
|
||||
id: uid,
|
||||
init: ref,
|
||||
unique: true
|
||||
});
|
||||
return uid;
|
||||
}
|
||||
|
||||
errorWithNode(node, msg, Error = SyntaxError) {
|
||||
var loc = node.loc.start;
|
||||
var err = new Error(`Line ${loc.line}: ${msg}`);
|
||||
err.loc = loc;
|
||||
return err;
|
||||
}
|
||||
|
||||
addCode(code: string) {
|
||||
code = (code || "") + "";
|
||||
code = this.parseInputSourceMap(code);
|
||||
this.code = code;
|
||||
return this.parseShebang(code);
|
||||
}
|
||||
|
||||
shouldIgnore() {
|
||||
var opts = this.opts;
|
||||
return util.shouldIgnore(opts.filename, opts.ignore, opts.only);
|
||||
}
|
||||
|
||||
parse(code: string) {
|
||||
if (this.shouldIgnore()) {
|
||||
return {
|
||||
metadata: {},
|
||||
code: code,
|
||||
map: null,
|
||||
ast: null
|
||||
};
|
||||
}
|
||||
|
||||
code = this.addCode(code);
|
||||
|
||||
var opts = this.opts;
|
||||
|
||||
//
|
||||
|
||||
var parseOpts = {
|
||||
highlightCode: opts.highlightCode,
|
||||
nonStandard: opts.nonStandard,
|
||||
filename: opts.filename,
|
||||
plugins: {}
|
||||
};
|
||||
|
||||
var features = parseOpts.features = {};
|
||||
for (var key in this.transformers) {
|
||||
var transformer = this.transformers[key];
|
||||
features[key] = transformer.canTransform();
|
||||
}
|
||||
|
||||
parseOpts.looseModules = this.isLoose("es6.modules");
|
||||
parseOpts.strictMode = features.strict;
|
||||
parseOpts.sourceType = "module";
|
||||
|
||||
this.log.debug("Parse start");
|
||||
|
||||
//
|
||||
|
||||
return parse(parseOpts, code, (tree) => {
|
||||
this.log.debug("Parse stop");
|
||||
this.transform(tree);
|
||||
return this.generate();
|
||||
});
|
||||
}
|
||||
|
||||
setAst(ast) {
|
||||
this.path = TraversalPath.get(null, null, ast, ast, "program", this);
|
||||
this.scope = this.path.scope;
|
||||
this.ast = ast;
|
||||
|
||||
this.path.traverse({
|
||||
enter(node, parent, scope) {
|
||||
if (this.isScope()) {
|
||||
for (var key in scope.bindings) {
|
||||
scope.bindings[key].setTypeAnnotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
transform(ast) {
|
||||
this.log.debug("Start set AST");
|
||||
this.setAst(ast);
|
||||
this.log.debug("End set AST");
|
||||
|
||||
this.log.debug("Start prepass");
|
||||
this.checkPath(this.path);
|
||||
this.log.debug("End prepass");
|
||||
|
||||
this.log.debug("Start module formatter init");
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canTransform()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
this.log.debug("End module formatter init");
|
||||
|
||||
this.call("pre");
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
this.call("post");
|
||||
}
|
||||
|
||||
call(key: string) {
|
||||
var stack = this.transformerStack;
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var transformer = stack[i].transformer;
|
||||
var fn = transformer[key];
|
||||
if (fn) fn(this);
|
||||
}
|
||||
}
|
||||
|
||||
checkPath(path) {
|
||||
if (Array.isArray(path)) {
|
||||
for (var i = 0; i < path.length; i++) {
|
||||
this.checkPath(path[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var stack = this.transformerStack;
|
||||
|
||||
checkPath(stack, path);
|
||||
|
||||
path.traverse(checkTransformerVisitor, {
|
||||
stack: stack
|
||||
});
|
||||
}
|
||||
|
||||
mergeSourceMap(map: Object) {
|
||||
var opts = this.opts;
|
||||
|
||||
var inputMap = opts.inputSourceMap;
|
||||
|
||||
if (inputMap) {
|
||||
map.sources[0] = inputMap.file;
|
||||
|
||||
var inputMapConsumer = new sourceMap.SourceMapConsumer(inputMap);
|
||||
var outputMapConsumer = new sourceMap.SourceMapConsumer(map);
|
||||
var outputMapGenerator = sourceMap.SourceMapGenerator.fromSourceMap(outputMapConsumer);
|
||||
outputMapGenerator.applySourceMap(inputMapConsumer);
|
||||
|
||||
var mergedMap = outputMapGenerator.toJSON();
|
||||
mergedMap.sources = inputMap.sources
|
||||
mergedMap.file = inputMap.file;
|
||||
return mergedMap;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
generate(): {
|
||||
usedHelpers?: Array<string>;
|
||||
code: string;
|
||||
map?: Object;
|
||||
ast?: Object;
|
||||
} {
|
||||
var opts = this.opts;
|
||||
var ast = this.ast;
|
||||
|
||||
var result = {
|
||||
metadata: {},
|
||||
code: "",
|
||||
map: null,
|
||||
ast: null
|
||||
};
|
||||
|
||||
if (this.opts.metadataUsedHelpers) {
|
||||
result.metadata.usedHelpers = Object.keys(this.usedHelpers);
|
||||
}
|
||||
|
||||
if (opts.ast) result.ast = ast;
|
||||
if (!opts.code) return result;
|
||||
|
||||
this.log.debug("Generation start");
|
||||
|
||||
var _result = generate(ast, opts, this.code);
|
||||
result.code = _result.code;
|
||||
result.map = _result.map;
|
||||
|
||||
this.log.debug("Generation end");
|
||||
|
||||
if (this.shebang) {
|
||||
// add back shebang
|
||||
result.code = `${this.shebang}\n${result.code}`;
|
||||
}
|
||||
|
||||
if (result.map) {
|
||||
result.map = this.mergeSourceMap(result.map);
|
||||
}
|
||||
|
||||
if (opts.sourceMaps === "inline" || opts.sourceMaps === "both") {
|
||||
result.code += "\n" + convertSourceMap.fromObject(result.map).toComment();
|
||||
}
|
||||
|
||||
if (opts.sourceMaps === "inline") {
|
||||
result.map = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
32
src/babel/transformation/file/logger.js
Normal file
32
src/babel/transformation/file/logger.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as util from "../../util";
|
||||
|
||||
export default class Logger {
|
||||
constructor(file: File, filename: string) {
|
||||
this.filename = filename;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
_buildMessage(msg: string): string {
|
||||
var parts = `[BABEL] ${this.filename}`;
|
||||
if (msg) parts += `: ${msg}`;
|
||||
return parts;
|
||||
}
|
||||
|
||||
error(msg: string, Constructor = Error) {
|
||||
throw new Constructor(this._buildMessage(msg));
|
||||
}
|
||||
|
||||
deprecate(msg) {
|
||||
if (!this.file.opts.suppressDeprecationMessages) {
|
||||
console.error(this._buildMessage(msg));
|
||||
}
|
||||
}
|
||||
|
||||
debug(msg: string) {
|
||||
util.debug(this._buildMessage(msg));
|
||||
}
|
||||
|
||||
deopt(node: Object, msg: string) {
|
||||
util.debug(this._buildMessage(msg));
|
||||
}
|
||||
}
|
||||
27
src/babel/transformation/file/option-parsers.js
Normal file
27
src/babel/transformation/file/option-parsers.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as util from "../../util";
|
||||
|
||||
export function transformerList(key, val, pipeline) {
|
||||
val = util.arrayify(val);
|
||||
|
||||
if (val.indexOf("all") >= 0 || val.indexOf(true) >= 0) {
|
||||
val = Object.keys(pipeline.transformers);
|
||||
}
|
||||
|
||||
return pipeline._ensureTransformerNames(key, val);
|
||||
}
|
||||
|
||||
export function number(key, val) {
|
||||
return +val;
|
||||
}
|
||||
|
||||
export function boolean(key, val) {
|
||||
return !!val;
|
||||
}
|
||||
|
||||
export function booleanString(key, val) {
|
||||
return util.booleanify(val);
|
||||
}
|
||||
|
||||
export function list(key, val) {
|
||||
return util.list(val);
|
||||
}
|
||||
222
src/babel/transformation/file/options.json
Normal file
222
src/babel/transformation/file/options.json
Normal file
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"description": "filename to use when reading from stdin - this will be used in source-maps, errors etc",
|
||||
"default": "unknown",
|
||||
"shorthand": "f"
|
||||
},
|
||||
|
||||
"filenameRelative": {
|
||||
"hidden": true,
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"inputSourceMap": {
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"extra": {
|
||||
"hidden": true,
|
||||
"default": {}
|
||||
},
|
||||
|
||||
"moduleId": {
|
||||
"description": "specify a custom name for module ids",
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"retainLines": {
|
||||
"hidden": true,
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "retain line numbers - will result in really ugly code"
|
||||
},
|
||||
|
||||
"nonStandard": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "enable support for JSX and Flow"
|
||||
},
|
||||
|
||||
"experimental": {
|
||||
"deprecated": "use `--stage 0`/`{ stage: 0 }` instead"
|
||||
},
|
||||
|
||||
"highlightCode": {
|
||||
"description": "ANSI syntax highlight code frames",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
|
||||
"suppressDeprecationMessages": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"resolveModuleSource": {
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"stage": {
|
||||
"description": "ECMAScript proposal stage version to allow [0-4]",
|
||||
"shorthand": "e",
|
||||
"type": "number",
|
||||
"default": 2
|
||||
},
|
||||
|
||||
"blacklist": {
|
||||
"type": "transformerList",
|
||||
"description": "blacklist of transformers to NOT use",
|
||||
"shorthand": "b"
|
||||
},
|
||||
|
||||
"whitelist": {
|
||||
"type": "transformerList",
|
||||
"optional": true,
|
||||
"description": "whitelist of transformers to ONLY use",
|
||||
"shorthand": "l"
|
||||
},
|
||||
|
||||
"optional": {
|
||||
"type": "transformerList",
|
||||
"description": "list of optional transformers to enable"
|
||||
},
|
||||
|
||||
"modules": {
|
||||
"type": "string",
|
||||
"description": "module formatter type to use [common]",
|
||||
"default": "common",
|
||||
"shorthand": "m"
|
||||
},
|
||||
|
||||
"moduleIds": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"shorthand": "M",
|
||||
"description": "insert an explicit id for modules"
|
||||
},
|
||||
|
||||
"loose": {
|
||||
"type": "transformerList",
|
||||
"description": "list of transformers to enable loose mode ON",
|
||||
"shorthand": "L"
|
||||
},
|
||||
|
||||
"jsxPragma": {
|
||||
"type": "string",
|
||||
"description": "custom pragma to use with JSX (same functionality as @jsx comments)",
|
||||
"default": "React.createElement",
|
||||
"shorthand": "P"
|
||||
},
|
||||
|
||||
"plugins": {
|
||||
"type": "list",
|
||||
"description": ""
|
||||
},
|
||||
|
||||
"ignore": {
|
||||
"type": "list",
|
||||
"description": "list of glob paths to **not** compile"
|
||||
},
|
||||
|
||||
"only": {
|
||||
"type": "list",
|
||||
"description": "list of glob paths to **only** compile"
|
||||
},
|
||||
|
||||
"code": {
|
||||
"hidden": true,
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
"ast": {
|
||||
"hidden": true,
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
"comments": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "output comments in generated output"
|
||||
},
|
||||
|
||||
"compact": {
|
||||
"type": "booleanString",
|
||||
"default": "auto",
|
||||
"description": "do not include superfluous whitespace characters and line terminators [true|false|auto]"
|
||||
},
|
||||
|
||||
"keepModuleIdExtensions": {
|
||||
"type": "boolean",
|
||||
"description": "keep extensions when generating module ids",
|
||||
"default": false,
|
||||
"shorthand": "k"
|
||||
},
|
||||
|
||||
"auxiliaryComment": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"shorthand": "a",
|
||||
"description": "attach a comment before all helper declarations and auxiliary code"
|
||||
},
|
||||
|
||||
"externalHelpers": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"shorthand": "r",
|
||||
"description": "uses a reference to `babelHelpers` instead of placing helpers at the top of your code."
|
||||
},
|
||||
|
||||
"metadataUsedHelpers": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"sourceMap": {
|
||||
"alias": "sourceMaps",
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"sourceMaps": {
|
||||
"type": "booleanString",
|
||||
"description": "[true|false|inline]",
|
||||
"default": false,
|
||||
"shorthand": "s"
|
||||
},
|
||||
|
||||
"sourceMapName": {
|
||||
"type": "string",
|
||||
"description": "set `file` on returned source map"
|
||||
},
|
||||
|
||||
"sourceFileName": {
|
||||
"type": "string",
|
||||
"description": "set `sources[0]` on returned source map"
|
||||
},
|
||||
|
||||
"sourceRoot": {
|
||||
"type": "string",
|
||||
"description": "the root from which all sources are relative"
|
||||
},
|
||||
|
||||
"moduleRoot": {
|
||||
"type": "string",
|
||||
"description": "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions"
|
||||
},
|
||||
|
||||
"breakConfig": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"hidden": true,
|
||||
"description": "stop trying to load .babelrc files"
|
||||
},
|
||||
|
||||
"babelrc": {
|
||||
"hidden": true,
|
||||
"description": "do not load the same .babelrc file twice"
|
||||
}
|
||||
}
|
||||
105
src/babel/transformation/file/plugin-manager.js
Normal file
105
src/babel/transformation/file/plugin-manager.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import * as node from "../../api/node";
|
||||
import * as messages from "../../messages";
|
||||
import * as util from "../../util";
|
||||
|
||||
export default class PluginManager {
|
||||
static memoisedPlugins = [];
|
||||
|
||||
static memoisePluginContainer(fn) {
|
||||
for (var i = 0; i < PluginManager.memoisedPlugins.length; i++) {
|
||||
var plugin = PluginManager.memoisedPlugins[i];
|
||||
if (plugin.container === fn) return plugin.transformer;
|
||||
}
|
||||
|
||||
var transformer = fn(node);
|
||||
PluginManager.memoisedPlugins.push({
|
||||
container: fn,
|
||||
transformer: transformer
|
||||
});
|
||||
return transformer;
|
||||
}
|
||||
|
||||
static positions = ["before", "after"];
|
||||
|
||||
constructor({ file, transformers, before, after } = { transformers: {}, before: [], after: [] }) {
|
||||
this.transformers = transformers;
|
||||
this.file = file;
|
||||
this.before = before;
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
subnormaliseString(name, position) {
|
||||
// this is a plugin in the form of "foobar" or "foobar:after"
|
||||
// where the optional colon is the delimiter for plugin position in the transformer stack
|
||||
|
||||
var match = name.match(/^(.*?):(after|before)$/);
|
||||
if (match) [, name, position] = match;
|
||||
|
||||
var loc = util.resolveRelative(name) || util.resolveRelative(`babel-plugin-${name}`);
|
||||
if (loc) {
|
||||
return {
|
||||
position: position,
|
||||
plugin: require(loc)
|
||||
};
|
||||
} else {
|
||||
throw new ReferenceError(messages.get("pluginUnknown", name));
|
||||
}
|
||||
}
|
||||
|
||||
validate(name, plugin) {
|
||||
// validate transformer key
|
||||
var key = plugin.key;
|
||||
if (this.transformers[key]) {
|
||||
throw new ReferenceError(messages.get("pluginKeyCollision", key));
|
||||
}
|
||||
|
||||
// validate Transformer instance
|
||||
if (!plugin.buildPass || plugin.constructor.name !== "Transformer") {
|
||||
throw new TypeError(messages.get("pluginNotTransformer", name));
|
||||
}
|
||||
}
|
||||
|
||||
add(name) {
|
||||
var position;
|
||||
var plugin;
|
||||
|
||||
if (name) {
|
||||
if (typeof name === "object" && name.transformer) {
|
||||
({ plugin: name, position } = name);
|
||||
} else if (typeof name !== "string") {
|
||||
// not a string so we'll just assume that it's a direct Transformer instance, if not then
|
||||
// the checks later on will complain
|
||||
plugin = name;
|
||||
}
|
||||
|
||||
if (typeof name === "string") {
|
||||
({ plugin, position } = this.subnormaliseString(name, position));
|
||||
}
|
||||
} else {
|
||||
throw new TypeError(messages.get("pluginIllegalKind", typeof name, name));
|
||||
}
|
||||
|
||||
// default position
|
||||
position = position || "before";
|
||||
|
||||
// validate position
|
||||
if (PluginManager.positions.indexOf(position) < 0) {
|
||||
throw new TypeError(messages.get("pluginIllegalPosition", position, name));
|
||||
}
|
||||
|
||||
// allow plugin containers to be specified so they don't have to manually require
|
||||
if (typeof plugin === "function") {
|
||||
plugin = PluginManager.memoisePluginContainer(plugin);
|
||||
}
|
||||
|
||||
//
|
||||
this.validate(name, plugin);
|
||||
|
||||
// build!
|
||||
var pass = this.transformers[plugin.key] = plugin.buildPass(this.file);
|
||||
if (pass.canTransform()) {
|
||||
var stack = position === "before" ? this.before : this.after;
|
||||
stack.push(pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import explode from "./explode-assignable-expression";
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export default function (exports, opts) {
|
||||
var isAssignment = function (node) {
|
||||
@@ -10,9 +10,13 @@ export default function (exports, opts) {
|
||||
return t.assignmentExpression("=", left, right);
|
||||
};
|
||||
|
||||
exports.shouldVisit = function (node) {
|
||||
return node.operator && (node.operator === opts.operator || node.operator === opts.operator + "=");
|
||||
};
|
||||
|
||||
exports.ExpressionStatement = function (node, parent, scope, file) {
|
||||
// hit the `AssignmentExpression` one below
|
||||
if (file.isConsequenceExpressionStatement(node)) return;
|
||||
if (this.isCompletionRecord()) return;
|
||||
|
||||
var expr = node.expression;
|
||||
if (!isAssignment(expr)) return;
|
||||
@@ -33,8 +37,7 @@ export default function (exports, opts) {
|
||||
var nodes = [];
|
||||
var exploded = explode(node.left, nodes, file, scope);
|
||||
nodes.push(buildAssignment(exploded.ref, opts.build(exploded.uid, node.right)));
|
||||
|
||||
return t.toSequenceExpression(nodes, scope);
|
||||
return nodes;
|
||||
};
|
||||
|
||||
exports.BinaryExpression = function (node) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import t from "../../types";
|
||||
import * as t from "../../types";
|
||||
|
||||
export default function build(node, buildBody) {
|
||||
var self = node.blocks.shift();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user