Compare commits
385 Commits
v7.0.0-alp
...
v7.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b82b65a31e | ||
|
|
5e7fce3fe0 | ||
|
|
84580cc2d1 | ||
|
|
d70603ffa9 | ||
|
|
d79a7920a1 | ||
|
|
2846e06db1 | ||
|
|
beff7809ea | ||
|
|
0a4f1b0a6e | ||
|
|
75861fac87 | ||
|
|
b2b3d7944a | ||
|
|
827d84536a | ||
|
|
3e487f89ab | ||
|
|
40805894c5 | ||
|
|
95dd16aeeb | ||
|
|
ac6eda2709 | ||
|
|
960151c876 | ||
|
|
7795750862 | ||
|
|
2d8fdf3045 | ||
|
|
a70cda812c | ||
|
|
4b297907d1 | ||
|
|
48c114169f | ||
|
|
68786c4f0f | ||
|
|
1ef5871300 | ||
|
|
c3e8715010 | ||
|
|
d8b4073536 | ||
|
|
3c4f19a28d | ||
|
|
2db0c3ad1d | ||
|
|
4577bd1b7c | ||
|
|
93cf26abca | ||
|
|
62c22c7b5d | ||
|
|
63baaa7148 | ||
|
|
7e726a81e6 | ||
|
|
9e4e64dac9 | ||
|
|
3569cb9922 | ||
|
|
c6a094a9d2 | ||
|
|
6ab3b4c0e3 | ||
|
|
70ab2e0620 | ||
|
|
0d16499fc0 | ||
|
|
77bbe20352 | ||
|
|
bd569433c4 | ||
|
|
fffa604023 | ||
|
|
e08ff8e650 | ||
|
|
b660f61b92 | ||
|
|
5fb282f73f | ||
|
|
7cc5580c71 | ||
|
|
2eaff3d01c | ||
|
|
b684699f79 | ||
|
|
4ca686b7be | ||
|
|
b84f8e9234 | ||
|
|
9e51038ad9 | ||
|
|
777a8e2bb4 | ||
|
|
ad1f87cf07 | ||
|
|
a04c18af71 | ||
|
|
0538c3cd8c | ||
|
|
cd66657f34 | ||
|
|
9243c78ea2 | ||
|
|
218f191a59 | ||
|
|
3154c2c114 | ||
|
|
4fdd75695b | ||
|
|
9c91e35ce4 | ||
|
|
3a55e1326c | ||
|
|
370559c62f | ||
|
|
a74b307752 | ||
|
|
b41fe4efb1 | ||
|
|
68d2f8d161 | ||
|
|
1c1ce5a9e4 | ||
|
|
ab76cb6b53 | ||
|
|
009d7f0b76 | ||
|
|
f667f07d82 | ||
|
|
94f54da30b | ||
|
|
d85c642617 | ||
|
|
79f4956948 | ||
|
|
7f92e1d9dd | ||
|
|
e37a5eb5eb | ||
|
|
66ec5263a4 | ||
|
|
13d931c417 | ||
|
|
47a9ba3440 | ||
|
|
a1debae8f0 | ||
|
|
30c4d6b456 | ||
|
|
0e58007264 | ||
|
|
577173cc02 | ||
|
|
8c457e9283 | ||
|
|
2a83867436 | ||
|
|
9dd65c809f | ||
|
|
af5f34ace5 | ||
|
|
57da9bdbed | ||
|
|
d86ae2fb84 | ||
|
|
18084db7cf | ||
|
|
8e19a5b057 | ||
|
|
95882d4e5a | ||
|
|
99ab2b206c | ||
|
|
77cfa94682 | ||
|
|
79c6814d65 | ||
|
|
d479673074 | ||
|
|
6630ae9794 | ||
|
|
6bb1486405 | ||
|
|
75808a2d14 | ||
|
|
4e9a25e34a | ||
|
|
0f823beeb1 | ||
|
|
829c75a866 | ||
|
|
9d7c82d869 | ||
|
|
21eeed8a8c | ||
|
|
889f4e7791 | ||
|
|
c5e81516dd | ||
|
|
6d965c0926 | ||
|
|
e32042f353 | ||
|
|
c1d07fd6db | ||
|
|
f83c83d49c | ||
|
|
605adc922d | ||
|
|
593cbc1d53 | ||
|
|
5c45753cd6 | ||
|
|
1563221171 | ||
|
|
b242e0d946 | ||
|
|
9322fd0458 | ||
|
|
f01438e9b1 | ||
|
|
ce5d1d0f59 | ||
|
|
7f1cd44d60 | ||
|
|
2841945095 | ||
|
|
76060bb2c7 | ||
|
|
84dfa659e7 | ||
|
|
e0b4543601 | ||
|
|
248743e6c5 | ||
|
|
9a1b8ea443 | ||
|
|
55aea26f13 | ||
|
|
fb9a752262 | ||
|
|
4a35243118 | ||
|
|
9fc910d8c0 | ||
|
|
51a293601b | ||
|
|
19c4dd2d8c | ||
|
|
2225892348 | ||
|
|
677160385c | ||
|
|
9b04cbbc4f | ||
|
|
4aca487b6d | ||
|
|
5afe40b095 | ||
|
|
b081f68e87 | ||
|
|
c9ed159a18 | ||
|
|
b9ed9919c1 | ||
|
|
04b4e414ad | ||
|
|
0b890ced19 | ||
|
|
c60bf9a897 | ||
|
|
245c78dcdc | ||
|
|
8a98141b60 | ||
|
|
78544417fc | ||
|
|
c6edce115c | ||
|
|
579499c66d | ||
|
|
827c70e015 | ||
|
|
8a5488e59f | ||
|
|
63204ae51e | ||
|
|
28ae47a174 | ||
|
|
aa684d1b0c | ||
|
|
1fdec955f8 | ||
|
|
213ad1ed7a | ||
|
|
797fb3c2e4 | ||
|
|
9d612e717e | ||
|
|
e919c6e6eb | ||
|
|
d82afb407e | ||
|
|
b858d7ce5e | ||
|
|
b83e0ec7b0 | ||
|
|
a0f0411abf | ||
|
|
8decefe8bc | ||
|
|
650cd43096 | ||
|
|
03f249430a | ||
|
|
8460b4c62f | ||
|
|
4710b8a5ba | ||
|
|
465c087ac0 | ||
|
|
bc123ad02a | ||
|
|
e170e6d760 | ||
|
|
960e1708a1 | ||
|
|
2ce5f166d7 | ||
|
|
a7a9e7ae17 | ||
|
|
51ff4dd936 | ||
|
|
628061c501 | ||
|
|
003b8918c2 | ||
|
|
58ec149c52 | ||
|
|
b3372a572d | ||
|
|
bc29145465 | ||
|
|
ed0de70656 | ||
|
|
9a75916012 | ||
|
|
a4080dc095 | ||
|
|
4e50b2d9d9 | ||
|
|
e4b35f680d | ||
|
|
93cc22dae1 | ||
|
|
89d8f70fcd | ||
|
|
f363ec6b99 | ||
|
|
b3183b1198 | ||
|
|
892377ae57 | ||
|
|
95b3c8a16a | ||
|
|
12e39116f0 | ||
|
|
0005b9e4cf | ||
|
|
1fb3d5b0f6 | ||
|
|
bd9e1860d0 | ||
|
|
692e51609c | ||
|
|
bb5528b414 | ||
|
|
033bad3098 | ||
|
|
2cfd01aeb6 | ||
|
|
ddba7ba89f | ||
|
|
851d2cb6e0 | ||
|
|
a330cf2b09 | ||
|
|
b6b69c615a | ||
|
|
4fdff567c6 | ||
|
|
622672d397 | ||
|
|
1ea3b0601c | ||
|
|
5492fe130a | ||
|
|
8a4ab088e4 | ||
|
|
ba671d0a66 | ||
|
|
4595729cbb | ||
|
|
5387d9f903 | ||
|
|
05726a976e | ||
|
|
070662e381 | ||
|
|
cdca54aed3 | ||
|
|
4081f3e23e | ||
|
|
cce83a0cea | ||
|
|
f1303aa54c | ||
|
|
ac33b1be27 | ||
|
|
36ab72f095 | ||
|
|
9b05b0df5c | ||
|
|
119d5c5871 | ||
|
|
0740e61131 | ||
|
|
97d0ab78cb | ||
|
|
f537fc7da7 | ||
|
|
462825b15a | ||
|
|
9e91ac54d3 | ||
|
|
54d9732d0b | ||
|
|
d92309f0db | ||
|
|
faa6c9f708 | ||
|
|
6cc2f5dc78 | ||
|
|
a62cb9281e | ||
|
|
ef87acc389 | ||
|
|
1f22ac353a | ||
|
|
0e5f597ee6 | ||
|
|
899634d20b | ||
|
|
b048bff77d | ||
|
|
9ce797dd34 | ||
|
|
acdd3637bc | ||
|
|
85b6b4b1b2 | ||
|
|
5fe4803562 | ||
|
|
30ee87159d | ||
|
|
2a496890ff | ||
|
|
3fae121460 | ||
|
|
750b03a22f | ||
|
|
98487b5a15 | ||
|
|
a9d8040c0f | ||
|
|
3faca62a77 | ||
|
|
cc6959e1fa | ||
|
|
6bd3bf4d2f | ||
|
|
ed15443dba | ||
|
|
64ff5a080d | ||
|
|
72259ca5d3 | ||
|
|
00f58b9bfa | ||
|
|
5cc1cbf3bc | ||
|
|
8df5514083 | ||
|
|
123dce5fcd | ||
|
|
b0524427c1 | ||
|
|
53e3f0dbdc | ||
|
|
c4fd05c0c2 | ||
|
|
1e55653ac1 | ||
|
|
272209ace5 | ||
|
|
7e739f954d | ||
|
|
bf9b434736 | ||
|
|
819056e94a | ||
|
|
c5bad22767 | ||
|
|
68ed633175 | ||
|
|
ce976bba2a | ||
|
|
c142bbc429 | ||
|
|
a6273a92ec | ||
|
|
1d7d090bf0 | ||
|
|
f58f4ac351 | ||
|
|
63b7137dac | ||
|
|
5393a49349 | ||
|
|
defde165ed | ||
|
|
3783429a96 | ||
|
|
3a6fdca069 | ||
|
|
d34d2b1305 | ||
|
|
5fbe8edfb9 | ||
|
|
517ecdae65 | ||
|
|
2579c5b6e9 | ||
|
|
30defbe436 | ||
|
|
3477e740e1 | ||
|
|
0df3e3d6eb | ||
|
|
f0d7d580d5 | ||
|
|
4ae39239b5 | ||
|
|
9e2ef0cf9e | ||
|
|
9b44cef691 | ||
|
|
ce2335604c | ||
|
|
8abe061fab | ||
|
|
bf9baa182b | ||
|
|
ee389384bc | ||
|
|
72d83acc07 | ||
|
|
cfe0a84e2b | ||
|
|
4ce24c041a | ||
|
|
3563823870 | ||
|
|
9d95b3faae | ||
|
|
f8f2ead450 | ||
|
|
32c4cdf016 | ||
|
|
afe85c11a7 | ||
|
|
01d5d5ebc7 | ||
|
|
8772e7fb89 | ||
|
|
889a505ffd | ||
|
|
6c6ee74eb0 | ||
|
|
48ce5bcf1c | ||
|
|
ec596604bc | ||
|
|
d365dad341 | ||
|
|
853b9f8ece | ||
|
|
6620612b66 | ||
|
|
c6eab0c206 | ||
|
|
83232bb4ff | ||
|
|
6928695735 | ||
|
|
943fa8aa73 | ||
|
|
58216f5022 | ||
|
|
8cd4a62c02 | ||
|
|
c474fd48e1 | ||
|
|
2788a914f6 | ||
|
|
09229db794 | ||
|
|
a52d34023c | ||
|
|
8facda4505 | ||
|
|
943b7371a1 | ||
|
|
0667160b11 | ||
|
|
ce6f67216e | ||
|
|
486563152c | ||
|
|
11539e219b | ||
|
|
086cdfc705 | ||
|
|
899a754bef | ||
|
|
5633e3c4f6 | ||
|
|
6646707e01 | ||
|
|
14584c218c | ||
|
|
d5aa6d3ff8 | ||
|
|
86a53773f1 | ||
|
|
79c1eed8c1 | ||
|
|
c307bbb3a9 | ||
|
|
526a7d20ef | ||
|
|
c3e8cc8ad6 | ||
|
|
7ca81700f7 | ||
|
|
685006433b | ||
|
|
48de6b32de | ||
|
|
925b6448e0 | ||
|
|
8895828bc3 | ||
|
|
b4f3d943b2 | ||
|
|
505d639da7 | ||
|
|
9a576ca932 | ||
|
|
fce92fa1ad | ||
|
|
a18ee8a9a5 | ||
|
|
446ee06680 | ||
|
|
8434f89bc0 | ||
|
|
14ed03127c | ||
|
|
0eae6a432c | ||
|
|
6af8e64711 | ||
|
|
c46ef658b5 | ||
|
|
62375cdf12 | ||
|
|
d1d812edff | ||
|
|
25ae8c8554 | ||
|
|
2b86d353d6 | ||
|
|
c59e9f5f0e | ||
|
|
1c078e5a76 | ||
|
|
6a478c48fb | ||
|
|
28831c144d | ||
|
|
ad250ef10a | ||
|
|
ccbb2eb8d4 | ||
|
|
2774cb7d42 | ||
|
|
911027f289 | ||
|
|
2163acd6c2 | ||
|
|
a2f334b9e9 | ||
|
|
3146b245ed | ||
|
|
d1c954b36f | ||
|
|
248c240998 | ||
|
|
d7e10a3adc | ||
|
|
d16991054e | ||
|
|
e13320ef73 | ||
|
|
adb903fd4b | ||
|
|
75847306fd | ||
|
|
1fecf286c6 | ||
|
|
ac5c13c1c8 | ||
|
|
258e82ca13 | ||
|
|
86fc4fbc4f | ||
|
|
ded4ca48cd | ||
|
|
2ea3338b8e | ||
|
|
cd9bb7ba10 | ||
|
|
769eddc788 | ||
|
|
216cbf5bd6 | ||
|
|
0b917c00d6 | ||
|
|
2a874dff8c | ||
|
|
f0dc710a46 | ||
|
|
452f8f150c | ||
|
|
abcbb07357 | ||
|
|
4276462a07 | ||
|
|
95c65ec1cb |
28
.babelrc.js
28
.babelrc.js
@@ -6,12 +6,28 @@ let envOpts = {
|
||||
|
||||
module.exports = {
|
||||
comments: false,
|
||||
plugins: [
|
||||
// temp until next release
|
||||
function() {
|
||||
return {
|
||||
visitor: {
|
||||
"Function": function(path) {
|
||||
const node = path.node;
|
||||
for (let i = 0; i < node.params.length; i++) {
|
||||
const param = node.params[i];
|
||||
if (param.type === "AssignmentPattern") {
|
||||
param.left.optional = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
"env", envOpts
|
||||
],
|
||||
["env", envOpts],
|
||||
"stage-0",
|
||||
"flow",
|
||||
"flow"
|
||||
],
|
||||
env: {
|
||||
cov: {
|
||||
@@ -21,9 +37,9 @@ module.exports = {
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.BABEL_ENV === 'development') {
|
||||
if (process.env.BABEL_ENV === "development") {
|
||||
envOpts.targets = {
|
||||
node: "current"
|
||||
};
|
||||
envOpts.debug = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,3 +7,9 @@ packages/*/lib
|
||||
packages/*/dist
|
||||
packages/*/test/fixtures
|
||||
packages/*/test/tmp
|
||||
packages/babel-standalone/babel.js
|
||||
packages/babel-standalone/babel.min.js
|
||||
|
||||
# Prettier tries to insert trailing commas in function calls, which Node.js
|
||||
# doesn't natively support. This causes an error when loading the Gulp tasks.
|
||||
packages/babel-standalone/src/gulpTasks.js
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"extends": "babel",
|
||||
"plugins": [
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"curly": ["error", "multi-line"],
|
||||
"func-call-spacing": "error",
|
||||
"key-spacing": "error",
|
||||
"no-multi-spaces": "error"
|
||||
"prettier/prettier": ["error", { "trailingComma": "es5" }]
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[ignore]
|
||||
.*/packages/.*/lib
|
||||
.*/packages/.*/test
|
||||
.*/node_modules/conventional-changelog-core/
|
||||
|
||||
[include]
|
||||
packages/*/src
|
||||
@@ -9,8 +10,8 @@ packages/*/src
|
||||
lib/file.js
|
||||
lib/parser.js
|
||||
lib/types.js
|
||||
lib/third-party-libs.js.flow
|
||||
|
||||
[options]
|
||||
strip_root=true
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FlowIssue
|
||||
|
||||
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,20 +2,19 @@
|
||||
Before making a PR please make sure to read our contributing guidelines
|
||||
https://github.com/babel/babel/blob/master/CONTRIBUTING.md
|
||||
|
||||
For any issue references: Add a comma-separated list of a [closing word](https://help.github.com/articles/closing-issues-via-commit-messages/) followed by the ticket number fixed by the PR
|
||||
For any issue references: Add a comma-separated list of a [closing word](https://help.github.com/articles/closing-issues-via-commit-messages/) followed by the ticket number fixed by the PR. It should be underlined in the preview if done correctly.
|
||||
-->
|
||||
|
||||
| Q | A <!--(yes/no) -->
|
||||
| Q | A <!--(can use an emoji 👍 ) -->
|
||||
| ------------------------ | ---
|
||||
| Fixed Issues | `Fixes #1, Fixes #2` <!-- rm the quotes to link the issues -->
|
||||
| Patch: Bug Fix? |
|
||||
| Major: Breaking Change? |
|
||||
| Minor: New Feature? |
|
||||
| Deprecations? |
|
||||
| Spec Compliancy? |
|
||||
| Tests Added/Pass? |
|
||||
| Fixed Tickets | `Fixes #1, Fixes #2` <!-- rm the quotes to link the issues -->
|
||||
| Spec Compliancy? |
|
||||
| License | MIT
|
||||
| Doc PR | <!-- if yes, add `[skip ci]` to your commit message to skip CI builds -->
|
||||
| Dependency Changes |
|
||||
| Doc PR | <!-- if yes, can add `[skip ci]` to your commit message to skip CI builds -->
|
||||
| Any Dependency Changes? |
|
||||
|
||||
<!-- Describe your changes below in as much detail as possible -->
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/node_modules
|
||||
/packages/*/node_modules
|
||||
*.log
|
||||
*.cache
|
||||
/.eslintcache
|
||||
@@ -9,6 +10,7 @@ node_modules
|
||||
/coverage
|
||||
dist
|
||||
/.package.json
|
||||
package-lock.json
|
||||
/packages/babel-runtime/core-js/**/*.js
|
||||
!/packages/babel-runtime/core-js/map.js
|
||||
/packages/babel-runtime/helpers/*.js
|
||||
@@ -20,6 +22,10 @@ dist
|
||||
/packages/babel-runtime/helpers/es6/*.js
|
||||
!/packages/babel-runtime/helpers/es6/toArray.js
|
||||
/packages/babel-register/test/.babel
|
||||
/packages/babel-cli/test/tmp
|
||||
/packages/babel-node/test/tmp
|
||||
/packages/*/lib
|
||||
.nyc_output
|
||||
/babel.sublime-workspace
|
||||
packages/babel-standalone/babel.js
|
||||
packages/babel-standalone/babel.min.js
|
||||
|
||||
12
.travis.yml
12
.travis.yml
@@ -7,14 +7,22 @@ cache:
|
||||
directories:
|
||||
- node_modules
|
||||
node_js:
|
||||
- '7'
|
||||
- '8'
|
||||
- '6'
|
||||
- '4'
|
||||
|
||||
env:
|
||||
- JOB=test
|
||||
global:
|
||||
- PATH=$HOME/.yarn/bin:$PATH
|
||||
- JOB=test
|
||||
|
||||
before_install:
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.28.1
|
||||
|
||||
script:
|
||||
# Babel doesn't build correctly with npm v2 (which comes bundled with Node v4)
|
||||
# so we manually upgrade to a known working npm version.
|
||||
- npm install --global npm@4
|
||||
- 'if [ "$JOB" = "test" ]; then make test-ci; fi'
|
||||
- 'if [ "$JOB" = "lint" ]; then make lint && make flow; fi'
|
||||
|
||||
|
||||
@@ -27,24 +27,24 @@ Contributions are always welcome, no matter how large or small.
|
||||
|
||||
- If you aren't just making a documentation change, you'll probably want to learn a bit about a few topics.
|
||||
- [ASTs](https://en.wikipedia.org/wiki/Abstract_syntax_tree) (Abstract Syntax Tree): The Babel AST [spec](https://github.com/babel/babylon/blob/master/ast/spec.md) is a bit different from [ESTree](https://github.com/estree/estree). The differences are listed [here](https://github.com/babel/babylon#output).
|
||||
- This repository's [`/doc`](https://github.com/babel/babel/tree/master/doc) directory for notes on Babel's internals
|
||||
- Check out [`/doc`](https://github.com/babel/babel/tree/master/doc) for information about Babel's internals
|
||||
- Check out [the Babel Plugin Handbook](https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-plugin-handbook) - core plugins are written the same way as any other plugin!
|
||||
- Check out [AST Explorer](http://astexplorer.net/#/scUfOmVOG5) to learn more about ASTs or make your own plugin in the browser
|
||||
- When you feel ready to finally jump into the babel source code a good start is to look out for issues which are labeled with [help-wanted](https://github.com/babel/babel/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) and/or [beginner-friendly](https://github.com/babel/babel/issues?q=is%3Aissue+is%3Aopen+label%3A%22beginner-friendly%22).
|
||||
- When you feel ready to jump into the Babel source code, a good place to start is to look for issues tagged with [help-wanted](https://github.com/babel/babel/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) and/or [beginner-friendly](https://github.com/babel/babel/issues?q=is%3Aissue+is%3Aopen+label%3A%22beginner-friendly%22).
|
||||
- Follow along with what we are working on by joining our Slack, following our annoucements on [Twitter](https://twitter.com/babeljs), and reading (or participating!) in our [meeting notes](https://github.com/babel/notes).
|
||||
- Check out our [website](http://babeljs.io/) and the [repo](https://github.com/babel/website)
|
||||
|
||||
## Chat
|
||||
|
||||
Feel free to check out the `#discussion`/`#development` channels on our [slack](https://slack.babeljs.io). Some of us are always online to chat!
|
||||
Feel free to check out the `#discussion`/`#development` channels on our [Slack](https://slack.babeljs.io). Some of us are always online to chat!
|
||||
|
||||
## Developing
|
||||
|
||||
**Note:** Versions `< 5.1.10` can't be built.
|
||||
|
||||
Babel is built for node 4 and up but we develop using node 6. Make sure you are on npm 3.
|
||||
Babel is built for Node 4 and up but we develop using Node 8 and yarn. You can check this with `node -v`.
|
||||
|
||||
You can check this with `node -v` and `npm -v`.
|
||||
|
||||
In addition, make sure that Yarn is installed.
|
||||
Make sure that Yarn is installed with version >= `0.28.0`.
|
||||
Installation instructions can be found here: https://yarnpkg.com/en/docs/install.
|
||||
|
||||
### Setup
|
||||
@@ -114,18 +114,33 @@ To run tests for a specific package in [packages](https://github.com/babel/babel
|
||||
$ TEST_ONLY=babel-cli make test
|
||||
```
|
||||
|
||||
`TEST_ONLY` will also match substrings of the package name:
|
||||
|
||||
```sh
|
||||
# Run tests for the babel-plugin-transform-es2015-classes package.
|
||||
$ TEST_ONLY=es2015-class make test
|
||||
```
|
||||
|
||||
Use the `TEST_GREP` variable to run a subset of tests by name:
|
||||
|
||||
```sh
|
||||
$ TEST_GREP=transformation make test
|
||||
```
|
||||
|
||||
To enable the node debugger added in v6.3.0, set the `TEST_DEBUG` environment variable:
|
||||
Substitute spaces for hyphens and forward slashes when targeting specific test names:
|
||||
|
||||
```sh
|
||||
$ TEST_GREP="arrow functions destructuring parameters" make test
|
||||
```
|
||||
|
||||
To enable the Node.js debugger added in v6.3.0, set the `TEST_DEBUG` environment variable:
|
||||
|
||||
```sh
|
||||
$ TEST_DEBUG=true make test
|
||||
```
|
||||
|
||||
You can combine `TEST_DEBUG` with `TEST_GREP` or `TEST_ONLY` to debug a subset of tests. If you plan to stay long in the debugger (which you'll likely do!), you may increase the test timeout by editing [test/mocha.opts](https://github.com/babel/babel/blob/master/test/mocha.opts).
|
||||
|
||||
To test the code coverage, use:
|
||||
|
||||
```sh
|
||||
@@ -133,6 +148,18 @@ $ BABEL_ENV=cov make build
|
||||
$ ./scripts/test-cov.sh
|
||||
```
|
||||
|
||||
|
||||
#### Troubleshooting Tests
|
||||
|
||||
In case you're not able to reproduce an error on CI locally, it may be due to
|
||||
|
||||
- Node Version: Travis CI runs the tests against all major node versions. If your tests use JavaScript features unsupported by lower versions of node, then use [minNodeVersion option](#writing-tests) in options.json.
|
||||
- Timeout: Check the CI log and if the only errors are timeout errors and you are sure that it's not related to the changes you made, ask someone in the slack channel to trigger rebuild on the CI build and it might be resolved
|
||||
|
||||
In case you're locally getting errors which are not on the CI, it may be due to
|
||||
|
||||
- Updates in Dependencies: Make sure you run `make bootstrap` before you run `make build` or `make watch` before you run the tests.
|
||||
|
||||
### Writing tests
|
||||
|
||||
Most packages in [`/packages`](https://github.com/babel/babel/tree/master/packages) have a `test` folder, however some tests might be in other packages or in [`/packages/babel-core`](https://github.com/babel/babel/tree/master/packages/babel-core/test/fixtures).
|
||||
@@ -186,6 +213,15 @@ If you need to check for an error that is thrown you can add to the `options.jso
|
||||
}
|
||||
```
|
||||
|
||||
If the test requires a minimum Node version, you can add `minNodeVersion` (must be in semver format).
|
||||
|
||||
```js
|
||||
// options.json example
|
||||
{
|
||||
"minNodeVersion": "5.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
#### Bootstrapping expected output
|
||||
|
||||
For both `babel-plugin-x` and `babylon`, you can easily generate an `expected.js`/`expected.json` automatically by just providing `actual.js` and running the tests as you usually would.
|
||||
|
||||
53
Gulpfile.js
53
Gulpfile.js
@@ -21,32 +21,41 @@ function swapSrcWithLib(srcPath) {
|
||||
|
||||
gulp.task("default", ["build"]);
|
||||
|
||||
gulp.task("build", function () {
|
||||
return gulp.src(scripts, { base: base })
|
||||
.pipe(plumber({
|
||||
errorHandler: function (err) {
|
||||
gutil.log(err.stack);
|
||||
},
|
||||
}))
|
||||
.pipe(newer({
|
||||
dest: base,
|
||||
map: swapSrcWithLib,
|
||||
}))
|
||||
.pipe(through.obj(function (file, enc, callback) {
|
||||
gutil.log("Compiling", "'" + chalk.cyan(file.relative) + "'...");
|
||||
callback(null, file);
|
||||
}))
|
||||
gulp.task("build", function() {
|
||||
return gulp
|
||||
.src(scripts, { base: base })
|
||||
.pipe(
|
||||
plumber({
|
||||
errorHandler: function(err) {
|
||||
gutil.log(err.stack);
|
||||
},
|
||||
})
|
||||
)
|
||||
.pipe(
|
||||
newer({
|
||||
dest: base,
|
||||
map: swapSrcWithLib,
|
||||
})
|
||||
)
|
||||
.pipe(
|
||||
through.obj(function(file, enc, callback) {
|
||||
gutil.log("Compiling", "'" + chalk.cyan(file.relative) + "'...");
|
||||
callback(null, file);
|
||||
})
|
||||
)
|
||||
.pipe(babel())
|
||||
.pipe(through.obj(function (file, enc, callback) {
|
||||
// Passing 'file.relative' because newer() above uses a relative path and this keeps it consistent.
|
||||
file.path = path.resolve(file.base, swapSrcWithLib(file.relative));
|
||||
callback(null, file);
|
||||
}))
|
||||
.pipe(
|
||||
through.obj(function(file, enc, callback) {
|
||||
// Passing 'file.relative' because newer() above uses a relative path and this keeps it consistent.
|
||||
file.path = path.resolve(file.base, swapSrcWithLib(file.relative));
|
||||
callback(null, file);
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(base));
|
||||
});
|
||||
|
||||
gulp.task("watch", ["build"], function () {
|
||||
watch(scripts, { debounceDelay: 200 }, function () {
|
||||
gulp.task("watch", ["build"], function() {
|
||||
watch(scripts, { debounceDelay: 200 }, function() {
|
||||
gulp.start("build");
|
||||
});
|
||||
});
|
||||
|
||||
24
Makefile
24
Makefile
@@ -2,10 +2,20 @@ MAKEFLAGS = -j1
|
||||
|
||||
export NODE_ENV = test
|
||||
|
||||
# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
|
||||
export FORCE_COLOR = true
|
||||
|
||||
.PHONY: build build-dist watch lint fix clean test-clean test-only test test-ci publish bootstrap
|
||||
|
||||
build: clean
|
||||
rm -rf packages/*/lib
|
||||
./node_modules/.bin/gulp build
|
||||
ifneq ($(BABEL_ENV), "cov")
|
||||
make build-standalone
|
||||
endif
|
||||
|
||||
build-standalone:
|
||||
./node_modules/.bin/gulp build-babel-standalone --cwd=packages/babel-standalone/
|
||||
|
||||
build-dist: build
|
||||
cd packages/babel-polyfill; \
|
||||
@@ -19,13 +29,13 @@ watch: clean
|
||||
BABEL_ENV=development ./node_modules/.bin/gulp watch
|
||||
|
||||
lint:
|
||||
./node_modules/.bin/eslint scripts packages *.js --format=codeframe
|
||||
./node_modules/.bin/eslint scripts packages *.js --format=codeframe --rulesdir="./eslint_rules"
|
||||
|
||||
flow:
|
||||
./node_modules/.bin/flow check
|
||||
./node_modules/.bin/flow check --strip-root
|
||||
|
||||
fix:
|
||||
./node_modules/.bin/eslint scripts packages *.js --format=codeframe --fix
|
||||
./node_modules/.bin/eslint scripts packages *.js --format=codeframe --fix --rulesdir="./eslint_rules"
|
||||
|
||||
clean: test-clean
|
||||
rm -rf packages/babel-polyfill/browser*
|
||||
@@ -40,8 +50,11 @@ test-clean:
|
||||
rm -rf packages/*/test-fixtures.json
|
||||
|
||||
clean-all:
|
||||
rm -rf packages/*/lib
|
||||
rm -rf node_modules
|
||||
rm -rf packages/*/node_modules
|
||||
rm -rf package-lock.json
|
||||
rm -rf packages/*/package-lock.json
|
||||
make clean
|
||||
|
||||
test-only:
|
||||
@@ -54,10 +67,11 @@ test-ci:
|
||||
make bootstrap
|
||||
make test-only
|
||||
|
||||
test-ci-coverage: SHELL:=/bin/bash
|
||||
test-ci-coverage:
|
||||
BABEL_ENV=cov make bootstrap
|
||||
./scripts/test-cov.sh
|
||||
./node_modules/.bin/codecov -f coverage/coverage-final.json
|
||||
bash <(curl -s https://codecov.io/bash) -f coverage/coverage-final.json
|
||||
|
||||
publish:
|
||||
git pull --rebase
|
||||
@@ -66,7 +80,7 @@ publish:
|
||||
make test
|
||||
# not using lerna independent mode atm, so only update packages that have changed since we use ^
|
||||
# --only-explicit-updates
|
||||
./node_modules/.bin/lerna publish --npm-tag=next --exact --skip-temp-tag
|
||||
./node_modules/.bin/lerna publish --force-publish=* --npm-tag=next --exact --skip-temp-tag
|
||||
make clean
|
||||
|
||||
bootstrap:
|
||||
|
||||
108
README.md
108
README.md
@@ -9,17 +9,22 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://medium.com/friendship-dot-js/i-peeked-into-my-node-modules-directory-and-you-wont-believe-what-happened-next-b89f63d21558"><img alt="Business Strategy Status" src="https://img.shields.io/badge/Business%20Model-flavortown-green.svg"></a>
|
||||
<a href="https://travis-ci.org/babel/babel"><img alt="Travis Status" src="https://img.shields.io/travis/babel/babel/master.svg?label=travis&maxAge=43200"></a>
|
||||
<a href="https://circleci.com/gh/babel/babel"><img alt="CircleCI Status" src="https://img.shields.io/circleci/project/github/babel/babel/master.svg?label=circle&maxAge=43200"></a>
|
||||
<a href="https://codecov.io/github/babel/babel"><img alt="Coverage Status" src="https://img.shields.io/codecov/c/github/babel/babel/master.svg?maxAge=43200"></a>
|
||||
<a href="https://slack.babeljs.io/"><img alt="Slack Status" src="https://slack.babeljs.io/badge.svg"></a>
|
||||
<a href="https://www.npmjs.com/package/babel-core"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/babel-core.svg?maxAge=43200"></a>
|
||||
<a href="https://www.npmjs.com/package/babel-core"><img alt="npm Downloads" src="https://img.shields.io/npm/dm/babel-core.svg?maxAge=43200"></a>
|
||||
</p>
|
||||
|
||||
Babel is a community-driven tool that helps you write the latest version of JavaScript.
|
||||
<p align="center">
|
||||
<a href="#backers"><img alt="Backers on Open Collective" src="https://opencollective.com/babel/backers/badge.svg" /></a>
|
||||
<a href="#sponsors"><img alt="Sponsors on Open Collective" src="https://opencollective.com/babel/sponsors/badge.svg" /></a>
|
||||
<a href="https://medium.com/friendship-dot-js/i-peeked-into-my-node-modules-directory-and-you-wont-believe-what-happened-next-b89f63d21558"><img alt="Business Strategy Status" src="https://img.shields.io/badge/business%20model-flavortown-green.svg"></a>
|
||||
</p>
|
||||
|
||||
When your supported environments don't support certain features natively, it will help you compile it down to a supported version.
|
||||
Babel is a community-driven tool that helps you write code in the latest version of JavaScript.
|
||||
|
||||
When your supported environments don't support certain features natively, Babel will help you compile those features down to a supported version.
|
||||
|
||||
**In**
|
||||
|
||||
@@ -66,25 +71,26 @@ Bugs and feature requests can be posted at https://github.com/babel/babel/issues
|
||||
|
||||
> We've moved our issues from phabricator back to github issues!
|
||||
|
||||
Former phabricator issue urls now automatically redirect to their corresponding Github issue:
|
||||
Former phabricator issue URLs now automatically redirect to their corresponding Github issue:
|
||||
|
||||
https://phabricator.babeljs.io/T2168 mostly corresponds to https://github.com/babel/babel/issues/2168.
|
||||
|
||||
## Want to report an issue with [babeljs.io](https://babeljs.io) (the website)?
|
||||
|
||||
For documentation and website issues please visit the [babel/babel.github.io](https://github.com/babel/babel.github.io) repo.
|
||||
For documentation and website issues please visit the [babel/website](https://github.com/babel/website) repo.
|
||||
|
||||
## Want to contribute to Babel?
|
||||
|
||||
Check out our [CONTRIBUTING.md](https://github.com/babel/babel/blob/master/CONTRIBUTING.md). If you have already joined slack, join our [#development](https://babeljs.slack.com/messages/development) channel!
|
||||
Check out our [CONTRIBUTING.md](https://github.com/babel/babel/blob/master/CONTRIBUTING.md). If you have already joined Slack, join our [#development](https://babeljs.slack.com/messages/development) channel!
|
||||
|
||||
You can also start by checking out the issues with the [help-wanted](https://github.com/babel/babel/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label.
|
||||
|
||||
Our discussions/notes/roadmap: [babel/notes](https://github.com/babel/notes)
|
||||
Our progress on TC39 proposals: [babel/proposals](https://github.com/babel/proposals)
|
||||
|
||||
## Packages
|
||||
|
||||
The Babel repo is managed as a [monorepo](https://github.com/babel/babel/blob/master/doc/design/monorepo.md); it's composed of many npm packages.
|
||||
The Babel repo is managed as a [monorepo](https://github.com/babel/babel/blob/master/doc/design/monorepo.md) that is composed of many npm packages.
|
||||
|
||||
### Core Packages
|
||||
|
||||
@@ -123,19 +129,19 @@ Check out the [`babel-handbook`](https://github.com/thejameskyle/babel-handbook/
|
||||
| [`babel-code-frame`](/packages/babel-code-frame) | [](https://www.npmjs.com/package/babel-code-frame) | [](https://david-dm.org/babel/babel?path=packages/babel-code-frame) |
|
||||
|
||||
- [`babel-cli`](/packages/babel-cli) is the CLI tool that runs `babel-core` and helps with outputting to a directory, a file, stdout and more (also includes `babel-node`). Check out the [docs](https://babeljs.io/docs/usage/cli/).
|
||||
- [`babel-types`](/packages/babel-types) is used to validate, build, change AST nodes.
|
||||
- [`babel-types`](/packages/babel-types) is used to validate, build and change AST nodes.
|
||||
- [`babel-polyfill`](/packages/babel-polyfill) is [literally a wrapper](https://github.com/babel/babel/blob/master/packages/babel-polyfill/src/index.js) around [`core-js`](https://github.com/zloirock/core-js) and [regenerator-runtime](https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime). Check out the [docs](https://babeljs.io/docs/usage/polyfill/).
|
||||
- [`babel-runtime`](/packages/babel-runtime) is similar to the polyfill except that it doesn't modify the global scope and is to be used with [`babel-plugin-transform-runtime`](/packages/babel-plugin-transform-runtime) (usually in library/plugin code). Check out the [docs](https://babeljs.io/docs/plugins/transform-runtime/).
|
||||
- [`babel-register`](/packages/babel-register) is a way to automatically compile files with babel on the fly by binding to node's require. Check out the [docs](http://babeljs.io/docs/usage/require/).
|
||||
- [`babel-template`](/packages/babel-template) is a helper function to make AST nodes. Instead you can pass a string representing the code you want to create rather than tediously building them using `babel-types`.
|
||||
- [`babel-helpers`](/packages/babel-helpers) is a set of premade `babel-template` functions that are used in some babel plugins.
|
||||
- [`babel-code-frame`](/packages/babel-code-frame) is a standalone package used to generate errors that prints the source code and points to error locations.
|
||||
- [`babel-register`](/packages/babel-register) is a way to automatically compile files with Babel on the fly by binding to Node.js `require`. Check out the [docs](http://babeljs.io/docs/usage/require/).
|
||||
- [`babel-template`](/packages/babel-template) is a helper function that allows constructing AST nodes from a string presentation of the code; this eliminates the tedium of using `babel-types` for building AST nodes.
|
||||
- [`babel-helpers`](/packages/babel-helpers) is a set of pre-made `babel-template` functions that are used in some Babel plugins.
|
||||
- [`babel-code-frame`](/packages/babel-code-frame) is a standalone package used to generate errors that print the source code and point to error locations.
|
||||
|
||||
### [Presets](http://babeljs.io/docs/plugins/#presets)
|
||||
|
||||
After Babel 6, the default transforms were removed; if you don't specify any plugins/presets it will just return the original source code.
|
||||
After Babel 6, the default transforms were removed; if you don't specify any plugins/presets, Babel will just return the original source code.
|
||||
|
||||
The transformer[s] used in Babel are the independent pieces of code that transform specific things. For example: the [`es2015-arrow-functions`](/packages/babel-plugin-transform-es2015-arrow-functions) transform specifically changes arrow functions into a regular function. Presets are just simply an array of plugins that make it easier to run a whole a set of transforms without specifying each one manually.
|
||||
The transformer[s] used in Babel are the independent pieces of code that transform specific things. For example: the [`es2015-arrow-functions`](/packages/babel-plugin-transform-es2015-arrow-functions) transform specifically changes arrow functions into regular functions. A preset is simply an array of plugins that make it easier to run a whole a set of transforms without specifying each one manually.
|
||||
|
||||
| Package | Version | Dependencies | Description |
|
||||
|--------|-------|------------|---|
|
||||
@@ -201,7 +207,77 @@ Amjad Masad | James Kyle | Jesse McCarthy | Sebastian McKenzie |
|
||||
[@amasad](https://github.com/amasad) | [@thejameskyle](https://github.com/thejameskyle) | [@jmm](https://github.com/jmm) | [@sebmck](https://twitter.com/sebmck) |
|
||||
| [@amasad](https://twitter.com/amasad) | [@thejameskyle](https://twitter.com/thejameskyle) | [@mccjm](https://twitter.com/mccjm) | [@kittens](https://github.com/kittens)
|
||||
|
||||
|
||||
# Backers
|
||||
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/babel#backer)]
|
||||
|
||||
<a href="https://opencollective.com/babel/backer/0/website" target="_blank"><img src="https://opencollective.com/babel/backer/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/1/website" target="_blank"><img src="https://opencollective.com/babel/backer/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/2/website" target="_blank"><img src="https://opencollective.com/babel/backer/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/3/website" target="_blank"><img src="https://opencollective.com/babel/backer/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/4/website" target="_blank"><img src="https://opencollective.com/babel/backer/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/5/website" target="_blank"><img src="https://opencollective.com/babel/backer/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/6/website" target="_blank"><img src="https://opencollective.com/babel/backer/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/7/website" target="_blank"><img src="https://opencollective.com/babel/backer/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/8/website" target="_blank"><img src="https://opencollective.com/babel/backer/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/9/website" target="_blank"><img src="https://opencollective.com/babel/backer/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/10/website" target="_blank"><img src="https://opencollective.com/babel/backer/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/11/website" target="_blank"><img src="https://opencollective.com/babel/backer/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/12/website" target="_blank"><img src="https://opencollective.com/babel/backer/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/13/website" target="_blank"><img src="https://opencollective.com/babel/backer/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/14/website" target="_blank"><img src="https://opencollective.com/babel/backer/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/15/website" target="_blank"><img src="https://opencollective.com/babel/backer/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/16/website" target="_blank"><img src="https://opencollective.com/babel/backer/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/17/website" target="_blank"><img src="https://opencollective.com/babel/backer/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/18/website" target="_blank"><img src="https://opencollective.com/babel/backer/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/19/website" target="_blank"><img src="https://opencollective.com/babel/backer/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/20/website" target="_blank"><img src="https://opencollective.com/babel/backer/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/21/website" target="_blank"><img src="https://opencollective.com/babel/backer/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/22/website" target="_blank"><img src="https://opencollective.com/babel/backer/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/23/website" target="_blank"><img src="https://opencollective.com/babel/backer/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/24/website" target="_blank"><img src="https://opencollective.com/babel/backer/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/25/website" target="_blank"><img src="https://opencollective.com/babel/backer/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/26/website" target="_blank"><img src="https://opencollective.com/babel/backer/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/27/website" target="_blank"><img src="https://opencollective.com/babel/backer/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/28/website" target="_blank"><img src="https://opencollective.com/babel/backer/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/backer/29/website" target="_blank"><img src="https://opencollective.com/babel/backer/29/avatar.svg"></a>
|
||||
|
||||
# Sponsors
|
||||
|
||||
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/babel#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/babel/sponsor/0/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/1/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/2/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/3/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/4/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/5/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/6/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/7/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/8/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/9/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/10/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/11/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/12/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/13/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/14/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/15/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/16/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/17/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/18/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/19/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/20/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/21/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/22/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/23/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/24/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/25/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/26/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/27/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/28/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/babel/sponsor/29/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/29/avatar.svg"></a>
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/babel/babel/blob/master/LICENSE)
|
||||
|
||||
|
||||
16
circle.yml
16
circle.yml
@@ -1,11 +1,17 @@
|
||||
general:
|
||||
artifacts:
|
||||
- "packages/babel-standalone/babel.js"
|
||||
- "packages/babel-standalone/babel.min.js"
|
||||
|
||||
machine:
|
||||
node:
|
||||
version:
|
||||
6
|
||||
8
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||
# Version number can be removed once 0.28.x or higher is released as stable
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.28.4
|
||||
cache_directories:
|
||||
- ~/.yarn-cache
|
||||
override:
|
||||
@@ -14,3 +20,9 @@ dependencies:
|
||||
test:
|
||||
override:
|
||||
- make test-ci-coverage
|
||||
# Builds babel-standalone with the regular Babel config
|
||||
- make build
|
||||
# test-ci-coverage doesn't test babel-standalone, as trying to gather coverage
|
||||
# data for a JS file that's several megabytes large is bound to fail. Here,
|
||||
# we just run the babel-standalone test separately.
|
||||
- ./node_modules/mocha/bin/_mocha packages/babel-standalone/test/ --opts test/mocha.opts
|
||||
|
||||
@@ -2,3 +2,9 @@ coverage:
|
||||
parsers:
|
||||
javascript:
|
||||
enable_partials: yes
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: "80%"
|
||||
patch:
|
||||
enabled: false
|
||||
|
||||
@@ -21,7 +21,6 @@ This is quite taboo but let's look at the pros and cons:
|
||||
|
||||
* Codebase looks more intimidating.
|
||||
* Repo is bigger in size.
|
||||
* Lower ranking in [npms](https://npms.io/) results. At least until [npms-io/npms-analyzer#83](https://github.com/npms-io/npms-analyzer/issues/83) is fixed.
|
||||
* ???
|
||||
|
||||
## This is dumb! Nobody in open source does this!
|
||||
|
||||
46
eslint_rules/no-undefined-identifier.js
Normal file
46
eslint_rules/no-undefined-identifier.js
Normal file
@@ -0,0 +1,46 @@
|
||||
"use strict";
|
||||
|
||||
function argumentsIsUndefinedString(argumentsArray) {
|
||||
return (
|
||||
argumentsArray.length === 1 &&
|
||||
argumentsArray[0].type === "Literal" &&
|
||||
argumentsArray[0].value === "undefined"
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
schema: [],
|
||||
},
|
||||
create: function(context) {
|
||||
if (context.getFilename().indexOf("packages/babel-plugin-") === -1) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
CallExpression: function(node) {
|
||||
const callee = node.callee;
|
||||
|
||||
if (
|
||||
callee.type === "MemberExpression" &&
|
||||
argumentsIsUndefinedString(node.arguments)
|
||||
) {
|
||||
const object = callee.object,
|
||||
property = callee.property;
|
||||
|
||||
if (
|
||||
object.type === "Identifier" &&
|
||||
object.name === "t" &&
|
||||
property.type === "Identifier" &&
|
||||
property.name === "identifier"
|
||||
) {
|
||||
context.report(
|
||||
node,
|
||||
"Use path.scope.buildUndefinedNode() to create an undefined identifier directly."
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
11
lerna.json
11
lerna.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"lerna": "2.0.0-beta.38",
|
||||
"version": "7.0.0-alpha.7",
|
||||
"lerna": "2.0.0-rc.4",
|
||||
"version": "7.0.0-alpha.20",
|
||||
"changelog": {
|
||||
"repo": "babel/babel",
|
||||
"labels": {
|
||||
@@ -21,5 +21,10 @@
|
||||
"test/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true
|
||||
}
|
||||
|
||||
33
lib/third-party-libs.js.flow
Normal file
33
lib/third-party-libs.js.flow
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Basic declarations for the npm modules we use.
|
||||
*/
|
||||
|
||||
declare module "micromatch" {
|
||||
declare function exports(Array<string>, Array<string>, ?{
|
||||
nocase: boolean,
|
||||
}): Array<string>;
|
||||
}
|
||||
|
||||
declare module "resolve" {
|
||||
declare export default {
|
||||
sync: (string, {| basedir: string |}) => string;
|
||||
};
|
||||
}
|
||||
|
||||
declare module "json5" {
|
||||
declare export default {
|
||||
parse: (string) => mixed,
|
||||
};
|
||||
}
|
||||
|
||||
declare module "lodash/defaults" {
|
||||
declare export default <T: Object>(T, Object) => T;
|
||||
}
|
||||
|
||||
declare module "lodash/clone" {
|
||||
declare export default <T>(obj: T) => T;
|
||||
}
|
||||
|
||||
declare module "lodash/merge" {
|
||||
declare export default <T: Object>(T, Object) => T;
|
||||
}
|
||||
790
lib/types.js
790
lib/types.js
File diff suppressed because it is too large
Load Diff
67
package.json
67
package.json
@@ -3,58 +3,75 @@
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "make test",
|
||||
"build": "make build",
|
||||
"fix": "make fix",
|
||||
"lint": "make lint",
|
||||
"fix": "make fix"
|
||||
"precommit": "lint-staged",
|
||||
"test": "make test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^1.5.0",
|
||||
"babel-core": "^7.0.0-alpha.6",
|
||||
"babel-eslint": "^7.0.0",
|
||||
"babel-plugin-istanbul": "^2.0.1",
|
||||
"babel-preset-env": "^2.0.0-alpha.3",
|
||||
"babel-preset-flow": "^7.0.0-alpha.3",
|
||||
"babel-preset-stage-0": "^7.0.0-alpha.3",
|
||||
"babel-register": "^7.0.0-alpha.6",
|
||||
"babel-cli": "7.0.0-alpha.18",
|
||||
"babel-core": "7.0.0-alpha.18",
|
||||
"babel-eslint": "8.0.0-alpha.15",
|
||||
"babel-plugin-istanbul": "^4.1.4",
|
||||
"babel-preset-env": "2.0.0-alpha.18",
|
||||
"babel-preset-flow": "7.0.0-alpha.18",
|
||||
"babel-preset-stage-0": "7.0.0-alpha.18",
|
||||
"babel-register": "7.0.0-alpha.18",
|
||||
"babylon": "7.0.0-beta.18",
|
||||
"browserify": "^13.1.1",
|
||||
"bundle-collapser": "^1.2.1",
|
||||
"chai": "^3.5.0",
|
||||
"chalk": "1.1.1",
|
||||
"codecov": "^1.0.1",
|
||||
"chai": "^4.1.0",
|
||||
"chalk": "^2.0.0",
|
||||
"derequire": "^2.0.2",
|
||||
"eslint": "^3.9.0",
|
||||
"eslint-config-babel": "^6.0.0",
|
||||
"eslint": "^3.14.1",
|
||||
"eslint-config-babel": "^7.0.2",
|
||||
"eslint-plugin-flowtype": "^2.20.0",
|
||||
"flow-bin": "^0.41.0",
|
||||
"eslint-plugin-prettier": "^2.1.2",
|
||||
"flow-bin": "^0.52.0",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-babel": "babel/gulp-babel#b7-alpha",
|
||||
"gulp-babel": "^7.0.0",
|
||||
"gulp-newer": "^1.0.0",
|
||||
"gulp-plumber": "^1.0.1",
|
||||
"gulp-util": "^3.0.7",
|
||||
"gulp-watch": "^4.3.5",
|
||||
"lerna": "^2.0.0-beta.38",
|
||||
"lerna-changelog": "^0.2.0",
|
||||
"husky": "^0.13.2",
|
||||
"lerna": "2.0.0",
|
||||
"lerna-changelog": "^0.5.0",
|
||||
"lint-staged": "^3.6.1",
|
||||
"lodash": "^4.2.0",
|
||||
"mocha": "^3.0.0",
|
||||
"nyc": "^10.0.0",
|
||||
"output-file-sync": "^1.1.1",
|
||||
"nyc": "^11.0.3",
|
||||
"output-file-sync": "^2.0.0",
|
||||
"prettier": "^1.5.0",
|
||||
"rimraf": "^2.4.3",
|
||||
"semver": "^5.0.0",
|
||||
"through2": "^2.0.0",
|
||||
"uglify-js": "^2.4.16"
|
||||
},
|
||||
"devEngines": {
|
||||
"node": ">= 4.x <= 7.x",
|
||||
"npm": "2.x || 3.x || 4.x"
|
||||
"engines": {
|
||||
"node": ">= 4.x <= 8.x",
|
||||
"npm": ">= 2.x <= 5.x",
|
||||
"yarn": ">=0.27.5 || >=1.0.0-20170811"
|
||||
},
|
||||
"nyc": {
|
||||
"all": true,
|
||||
"exclude": [
|
||||
"scripts/*.js",
|
||||
"packages/*/test/**"
|
||||
"packages/*/test/**",
|
||||
"packages/babel-standalone/**"
|
||||
],
|
||||
"sourceMap": false,
|
||||
"instrument": false
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"eslint --format=codeframe --fix --rulesdir='./eslint_rules'",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
]
|
||||
}
|
||||
|
||||
6
packages/.eslintrc
Normal file
6
packages/.eslintrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"rules": {
|
||||
"prettier/prettier": ["error", { "trailingComma": "all" }],
|
||||
"no-undefined-identifier": 2
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "babel-cli",
|
||||
"version": "7.0.0-alpha.7",
|
||||
"version": "7.0.0-alpha.20",
|
||||
"description": "Babel command line.",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -16,24 +16,24 @@
|
||||
"compiler"
|
||||
],
|
||||
"dependencies": {
|
||||
"babel-core": "7.0.0-alpha.7",
|
||||
"babel-register": "7.0.0-alpha.7",
|
||||
"babel-polyfill": "7.0.0-alpha.7",
|
||||
"babel-core": "7.0.0-alpha.20",
|
||||
"babel-polyfill": "7.0.0-alpha.20",
|
||||
"babel-register": "7.0.0-alpha.20",
|
||||
"commander": "^2.8.1",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"fs-readdir-recursive": "^1.0.0",
|
||||
"glob": "^7.0.0",
|
||||
"lodash": "^4.2.0",
|
||||
"output-file-sync": "^1.1.0",
|
||||
"output-file-sync": "^2.0.0",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.5.0",
|
||||
"v8flags": "^2.0.10"
|
||||
"v8flags": "^3.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"chokidar": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-helper-fixtures": "^7.0.0-alpha.3"
|
||||
"babel-helper-fixtures": "7.0.0-alpha.20"
|
||||
},
|
||||
"bin": {
|
||||
"babel-doctor": "./bin/babel-doctor.js",
|
||||
|
||||
@@ -24,9 +24,21 @@ function collect(value, previousValue): Array<string> {
|
||||
/* eslint-disable max-len */
|
||||
program.option("-e, --eval [script]", "Evaluate script");
|
||||
program.option("-p, --print [code]", "Evaluate script and print result");
|
||||
program.option("-o, --only [globs]", "A comma-separated list of glob patterns to compile", collect);
|
||||
program.option("-i, --ignore [globs]", "A comma-separated list of glob patterns to skip compiling", collect);
|
||||
program.option("-x, --extensions [extensions]", "List of extensions to hook into [.es6,.js,.es,.jsx]", collect);
|
||||
program.option(
|
||||
"-o, --only [globs]",
|
||||
"A comma-separated list of glob patterns to compile",
|
||||
collect,
|
||||
);
|
||||
program.option(
|
||||
"-i, --ignore [globs]",
|
||||
"A comma-separated list of glob patterns to skip compiling",
|
||||
collect,
|
||||
);
|
||||
program.option(
|
||||
"-x, --extensions [extensions]",
|
||||
"List of extensions to hook into [.es6,.js,.es,.jsx,.mjs]",
|
||||
collect,
|
||||
);
|
||||
program.option("-w, --plugins [string]", "", collect);
|
||||
program.option("-b, --presets [string]", "", collect);
|
||||
/* eslint-enable max-len */
|
||||
@@ -55,23 +67,28 @@ const replPlugin = ({ types: t }) => ({
|
||||
|
||||
VariableDeclaration(path) {
|
||||
if (path.node.kind !== "var") {
|
||||
throw path.buildCodeFrameError("Only `var` variables are supported in the REPL");
|
||||
throw path.buildCodeFrameError(
|
||||
"Only `var` variables are supported in the REPL",
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
Program(path) {
|
||||
if (path.get("body").some((child) => child.isExpressionStatement())) return;
|
||||
if (path.get("body").some(child => child.isExpressionStatement())) return;
|
||||
|
||||
// If the executed code doesn't evaluate to a value,
|
||||
// prevent implicit strict mode from printing 'use strict'.
|
||||
path.pushContainer("body", t.expressionStatement(t.identifier("undefined")));
|
||||
path.pushContainer(
|
||||
"body",
|
||||
t.expressionStatement(t.identifier("undefined")),
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
const _eval = function (code, filename) {
|
||||
const _eval = function(code, filename) {
|
||||
code = code.trim();
|
||||
if (!code) return undefined;
|
||||
|
||||
@@ -113,7 +130,7 @@ if (program.eval || program.print) {
|
||||
|
||||
let i = 0;
|
||||
let ignoreNext = false;
|
||||
args.some(function (arg, i2) {
|
||||
args.some(function(arg, i2) {
|
||||
if (ignoreNext) {
|
||||
ignoreNext = false;
|
||||
return;
|
||||
@@ -133,7 +150,9 @@ if (program.eval || program.print) {
|
||||
|
||||
// make the filename absolute
|
||||
const filename = args[0];
|
||||
if (!path.isAbsolute(filename)) args[0] = path.join(process.cwd(), filename);
|
||||
if (!path.isAbsolute(filename)) {
|
||||
args[0] = path.join(process.cwd(), filename);
|
||||
}
|
||||
|
||||
// add back on node and concat the sliced args
|
||||
process.argv = ["node"].concat(args);
|
||||
|
||||
@@ -10,8 +10,16 @@ function collect(value, previousValue): Array<string> {
|
||||
return previousValue ? previousValue.concat(values) : values;
|
||||
}
|
||||
|
||||
commander.option("-l, --whitelist [whitelist]", "Whitelist of helpers to ONLY include", collect);
|
||||
commander.option("-t, --output-type [type]", "Type of output (global|umd|var)", "global");
|
||||
commander.option(
|
||||
"-l, --whitelist [whitelist]",
|
||||
"Whitelist of helpers to ONLY include",
|
||||
collect,
|
||||
);
|
||||
commander.option(
|
||||
"-t, --output-type [type]",
|
||||
"Type of output (global|umd|var)",
|
||||
"global",
|
||||
);
|
||||
|
||||
commander.usage("[options]");
|
||||
commander.parse(process.argv);
|
||||
|
||||
@@ -33,7 +33,7 @@ function getNormalizedV8Flag(arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
getV8Flags(function (err, v8Flags) {
|
||||
getV8Flags(function(err, v8Flags) {
|
||||
babelArgs.forEach(function(arg) {
|
||||
const flag = arg.split("=")[0];
|
||||
|
||||
@@ -46,6 +46,7 @@ getV8Flags(function (err, v8Flags) {
|
||||
case "--debug":
|
||||
case "--debug-brk":
|
||||
case "--inspect":
|
||||
case "--inspect-brk":
|
||||
args.unshift(arg);
|
||||
break;
|
||||
|
||||
@@ -58,7 +59,10 @@ getV8Flags(function (err, v8Flags) {
|
||||
break;
|
||||
|
||||
default:
|
||||
if (v8Flags.indexOf(getNormalizedV8Flag(flag)) >= 0 || arg.indexOf("--trace") === 0) {
|
||||
if (
|
||||
v8Flags.indexOf(getNormalizedV8Flag(flag)) >= 0 ||
|
||||
arg.indexOf("--trace") === 0
|
||||
) {
|
||||
args.unshift(arg);
|
||||
} else {
|
||||
args.push(arg);
|
||||
@@ -79,9 +83,11 @@ getV8Flags(function (err, v8Flags) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
|
||||
const child_process = require("child_process");
|
||||
const proc = child_process.spawn(process.argv[0], args, { stdio: "inherit" });
|
||||
proc.on("exit", function (code, signal) {
|
||||
process.on("exit", function () {
|
||||
const 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 {
|
||||
@@ -89,5 +95,10 @@ getV8Flags(function (err, v8Flags) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
process.on("SIGINT", () => {
|
||||
proc.kill("SIGINT");
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,19 +6,27 @@ import fs from "fs";
|
||||
|
||||
import * as util from "./util";
|
||||
|
||||
export default function (commander, filenames, opts) {
|
||||
export default function(commander, filenames, opts) {
|
||||
function write(src, relative) {
|
||||
if (!util.isCompilableExtension(relative, commander.extensions)) return false;
|
||||
if (!util.isCompilableExtension(relative, commander.extensions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove extension and then append back on .js
|
||||
relative = relative.replace(/\.(\w*?)$/, "") + ".js";
|
||||
|
||||
const dest = path.join(commander.outDir, relative);
|
||||
|
||||
const data = util.compile(src, defaults({
|
||||
sourceFileName: slash(path.relative(dest + "/..", src)),
|
||||
sourceMapTarget: path.basename(relative),
|
||||
}, opts));
|
||||
const data = util.compile(
|
||||
src,
|
||||
defaults(
|
||||
{
|
||||
sourceFileName: slash(path.relative(dest + "/..", src)),
|
||||
sourceMapTarget: path.basename(relative),
|
||||
},
|
||||
opts,
|
||||
),
|
||||
);
|
||||
|
||||
if (!data) return false;
|
||||
|
||||
@@ -55,7 +63,7 @@ export default function (commander, filenames, opts) {
|
||||
if (stat.isDirectory(filename)) {
|
||||
const dirname = filename;
|
||||
|
||||
util.readdir(dirname).forEach(function (filename) {
|
||||
util.readdir(dirname).forEach(function(filename) {
|
||||
const src = path.join(dirname, filename);
|
||||
handleFile(src, filename);
|
||||
});
|
||||
@@ -71,7 +79,7 @@ export default function (commander, filenames, opts) {
|
||||
if (commander.watch) {
|
||||
const chokidar = util.requireChokidar();
|
||||
|
||||
filenames.forEach(function (dirname) {
|
||||
filenames.forEach(function(dirname) {
|
||||
const watcher = chokidar.watch(dirname, {
|
||||
persistent: true,
|
||||
ignoreInitial: true,
|
||||
@@ -81,8 +89,8 @@ export default function (commander, filenames, opts) {
|
||||
},
|
||||
});
|
||||
|
||||
["add", "change"].forEach(function (type) {
|
||||
watcher.on(type, function (filename) {
|
||||
["add", "change"].forEach(function(type) {
|
||||
watcher.on(type, function(filename) {
|
||||
const relative = path.relative(dirname, filename) || filename;
|
||||
try {
|
||||
handleFile(filename, relative);
|
||||
|
||||
@@ -7,14 +7,14 @@ import fs from "fs";
|
||||
|
||||
import * as util from "./util";
|
||||
|
||||
export default function (commander, filenames, opts) {
|
||||
export default function(commander, filenames, opts) {
|
||||
if (commander.sourceMaps === "inline") {
|
||||
opts.sourceMaps = true;
|
||||
}
|
||||
|
||||
let results = [];
|
||||
|
||||
const buildResult = function () {
|
||||
const buildResult = function() {
|
||||
const map = new sourceMap.SourceMapGenerator({
|
||||
file: path.basename(commander.outFile || "") || "stdout",
|
||||
sourceRoot: opts.sourceRoot,
|
||||
@@ -23,14 +23,14 @@ export default function (commander, filenames, opts) {
|
||||
let code = "";
|
||||
let offset = 0;
|
||||
|
||||
results.forEach(function (result) {
|
||||
results.forEach(function(result) {
|
||||
code += result.code + "\n";
|
||||
|
||||
if (result.map) {
|
||||
const consumer = new sourceMap.SourceMapConsumer(result.map);
|
||||
const sources = new Set();
|
||||
|
||||
consumer.eachMapping(function (mapping) {
|
||||
consumer.eachMapping(function(mapping) {
|
||||
if (mapping.source != null) sources.add(mapping.source);
|
||||
|
||||
map.addMapping({
|
||||
@@ -39,14 +39,17 @@ export default function (commander, filenames, opts) {
|
||||
column: mapping.generatedColumn,
|
||||
},
|
||||
source: mapping.source,
|
||||
original: mapping.source == null ? null : {
|
||||
line: mapping.originalLine,
|
||||
column: mapping.originalColumn,
|
||||
},
|
||||
original:
|
||||
mapping.source == null
|
||||
? null
|
||||
: {
|
||||
line: mapping.originalLine,
|
||||
column: mapping.originalColumn,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
sources.forEach((source) => {
|
||||
sources.forEach(source => {
|
||||
const content = consumer.sourceContentFor(source, true);
|
||||
if (content !== null) {
|
||||
map.setSourceContent(source, content);
|
||||
@@ -59,7 +62,10 @@ export default function (commander, filenames, opts) {
|
||||
|
||||
// add the inline sourcemap comment if we've either explicitly asked for inline source
|
||||
// maps, or we've requested them without any output file
|
||||
if (commander.sourceMaps === "inline" || (!commander.outFile && commander.sourceMaps)) {
|
||||
if (
|
||||
commander.sourceMaps === "inline" ||
|
||||
(!commander.outFile && commander.sourceMaps)
|
||||
) {
|
||||
code += "\n" + convertSourceMap.fromObject(map).toComment();
|
||||
}
|
||||
|
||||
@@ -69,7 +75,7 @@ export default function (commander, filenames, opts) {
|
||||
};
|
||||
};
|
||||
|
||||
const output = function () {
|
||||
const output = function() {
|
||||
const result = buildResult();
|
||||
|
||||
if (commander.outFile) {
|
||||
@@ -86,36 +92,45 @@ export default function (commander, filenames, opts) {
|
||||
}
|
||||
};
|
||||
|
||||
const stdin = function () {
|
||||
const stdin = function() {
|
||||
let code = "";
|
||||
|
||||
process.stdin.setEncoding("utf8");
|
||||
|
||||
process.stdin.on("readable", function () {
|
||||
process.stdin.on("readable", function() {
|
||||
const chunk = process.stdin.read();
|
||||
if (chunk !== null) code += chunk;
|
||||
});
|
||||
|
||||
process.stdin.on("end", function () {
|
||||
results.push(util.transform(commander.filename, code, defaults({
|
||||
sourceFileName: "stdin",
|
||||
}, opts)));
|
||||
process.stdin.on("end", function() {
|
||||
results.push(
|
||||
util.transform(
|
||||
commander.filename,
|
||||
code,
|
||||
defaults(
|
||||
{
|
||||
sourceFileName: "stdin",
|
||||
},
|
||||
opts,
|
||||
),
|
||||
),
|
||||
);
|
||||
output();
|
||||
});
|
||||
};
|
||||
|
||||
const walk = function () {
|
||||
const walk = function() {
|
||||
const _filenames = [];
|
||||
results = [];
|
||||
|
||||
filenames.forEach(function (filename) {
|
||||
filenames.forEach(function(filename) {
|
||||
if (!fs.existsSync(filename)) return;
|
||||
|
||||
const stat = fs.statSync(filename);
|
||||
if (stat.isDirectory()) {
|
||||
const dirname = filename;
|
||||
|
||||
util.readdirFilter(filename).forEach(function (filename) {
|
||||
util.readdirFilter(filename).forEach(function(filename) {
|
||||
_filenames.push(path.join(dirname, filename));
|
||||
});
|
||||
} else {
|
||||
@@ -123,16 +138,25 @@ export default function (commander, filenames, opts) {
|
||||
}
|
||||
});
|
||||
|
||||
_filenames.forEach(function (filename) {
|
||||
_filenames.forEach(function(filename) {
|
||||
let sourceFilename = filename;
|
||||
if (commander.outFile) {
|
||||
sourceFilename = path.relative(path.dirname(commander.outFile), sourceFilename);
|
||||
sourceFilename = path.relative(
|
||||
path.dirname(commander.outFile),
|
||||
sourceFilename,
|
||||
);
|
||||
}
|
||||
sourceFilename = slash(sourceFilename);
|
||||
|
||||
const data = util.compile(filename, defaults({
|
||||
sourceFileName: sourceFilename,
|
||||
}, opts));
|
||||
const data = util.compile(
|
||||
filename,
|
||||
defaults(
|
||||
{
|
||||
sourceFileName: sourceFilename,
|
||||
},
|
||||
opts,
|
||||
),
|
||||
);
|
||||
|
||||
if (!data) return;
|
||||
|
||||
@@ -142,33 +166,36 @@ export default function (commander, filenames, opts) {
|
||||
output();
|
||||
};
|
||||
|
||||
const files = function () {
|
||||
|
||||
const files = function() {
|
||||
if (!commander.skipInitialBuild) {
|
||||
walk();
|
||||
}
|
||||
|
||||
if (commander.watch) {
|
||||
const chokidar = util.requireChokidar();
|
||||
chokidar.watch(filenames, {
|
||||
persistent: true,
|
||||
ignoreInitial: true,
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: 50,
|
||||
pollInterval: 10,
|
||||
},
|
||||
}).on("all", function (type, filename) {
|
||||
if (!util.isCompilableExtension(filename, commander.extensions)) return;
|
||||
|
||||
if (type === "add" || type === "change") {
|
||||
util.log(type + " " + filename);
|
||||
try {
|
||||
walk();
|
||||
} catch (err) {
|
||||
console.error(err.stack);
|
||||
chokidar
|
||||
.watch(filenames, {
|
||||
persistent: true,
|
||||
ignoreInitial: true,
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: 50,
|
||||
pollInterval: 10,
|
||||
},
|
||||
})
|
||||
.on("all", function(type, filename) {
|
||||
if (!util.isCompilableExtension(filename, commander.extensions)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (type === "add" || type === "change") {
|
||||
util.log(type + " " + filename);
|
||||
try {
|
||||
walk();
|
||||
} catch (err) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -34,45 +34,118 @@ function collect(value, previousValue): Array<string> {
|
||||
|
||||
/* eslint-disable max-len */
|
||||
// Standard Babel input configs.
|
||||
commander.option("-f, --filename [filename]", "filename to use when reading from stdin - this will be used in source-maps, errors etc");
|
||||
commander.option("--presets [list]", "comma-separated list of preset names", collect);
|
||||
commander.option("--plugins [list]", "comma-separated list of plugin names", collect);
|
||||
commander.option(
|
||||
"-f, --filename [filename]",
|
||||
"filename to use when reading from stdin - this will be used in source-maps, errors etc",
|
||||
);
|
||||
commander.option(
|
||||
"--presets [list]",
|
||||
"comma-separated list of preset names",
|
||||
collect,
|
||||
);
|
||||
commander.option(
|
||||
"--plugins [list]",
|
||||
"comma-separated list of plugin names",
|
||||
collect,
|
||||
);
|
||||
commander.option("--config-file [path]", "Path a to .babelrc file to use");
|
||||
|
||||
// Basic file input configuration.
|
||||
commander.option("--source-type [script|module]", "");
|
||||
commander.option("--no-babelrc", "Whether or not to look up .babelrc and .babelignore files");
|
||||
commander.option("--ignore [list]", "list of glob paths to **not** compile", collect);
|
||||
commander.option("--only [list]", "list of glob paths to **only** compile", collect);
|
||||
commander.option(
|
||||
"--no-babelrc",
|
||||
"Whether or not to look up .babelrc and .babelignore files",
|
||||
);
|
||||
commander.option(
|
||||
"--ignore [list]",
|
||||
"list of glob paths to **not** compile",
|
||||
collect,
|
||||
);
|
||||
commander.option(
|
||||
"--only [list]",
|
||||
"list of glob paths to **only** compile",
|
||||
collect,
|
||||
);
|
||||
|
||||
// Misc babel config.
|
||||
commander.option("--no-highlight-code", "enable/disable ANSI syntax highlighting of code frames (on by default)");
|
||||
commander.option(
|
||||
"--no-highlight-code",
|
||||
"enable/disable ANSI syntax highlighting of code frames (on by default)",
|
||||
);
|
||||
|
||||
// General output formatting.
|
||||
commander.option("--no-comments", "write comments to generated output (true by default)");
|
||||
commander.option("--retain-lines", "retain line numbers - will result in really ugly code");
|
||||
commander.option("--compact [true|false|auto]", "do not include superfluous whitespace characters and line terminators", booleanify);
|
||||
commander.option(
|
||||
"--no-comments",
|
||||
"write comments to generated output (true by default)",
|
||||
);
|
||||
commander.option(
|
||||
"--retain-lines",
|
||||
"retain line numbers - will result in really ugly code",
|
||||
);
|
||||
commander.option(
|
||||
"--compact [true|false|auto]",
|
||||
"do not include superfluous whitespace characters and line terminators",
|
||||
booleanify,
|
||||
);
|
||||
commander.option("--minified", "save as much bytes when printing [true|false]");
|
||||
commander.option("--auxiliary-comment-before [string]", "print a comment before any injected non-user code");
|
||||
commander.option("--auxiliary-comment-after [string]", "print a comment after any injected non-user code");
|
||||
commander.option(
|
||||
"--auxiliary-comment-before [string]",
|
||||
"print a comment before any injected non-user code",
|
||||
);
|
||||
commander.option(
|
||||
"--auxiliary-comment-after [string]",
|
||||
"print a comment after any injected non-user code",
|
||||
);
|
||||
|
||||
// General soucemap formatting.
|
||||
commander.option("-s, --source-maps [true|false|inline|both]", "", booleanify);
|
||||
commander.option("--source-map-target [string]", "set `file` on returned source map");
|
||||
commander.option("--source-file-name [string]", "set `sources[0]` on returned source map");
|
||||
commander.option("--source-root [filename]", "the root from which all sources are relative");
|
||||
commander.option(
|
||||
"--source-map-target [string]",
|
||||
"set `file` on returned source map",
|
||||
);
|
||||
commander.option(
|
||||
"--source-file-name [string]",
|
||||
"set `sources[0]` on returned source map",
|
||||
);
|
||||
commander.option(
|
||||
"--source-root [filename]",
|
||||
"the root from which all sources are relative",
|
||||
);
|
||||
|
||||
// Config params for certain module output formats.
|
||||
commander.option("--module-root [filename]", "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions");
|
||||
commander.option(
|
||||
"--module-root [filename]",
|
||||
"optional prefix for the AMD module formatter that will be prepend to the filename on module definitions",
|
||||
);
|
||||
commander.option("-M, --module-ids", "insert an explicit id for modules");
|
||||
commander.option("--module-id [string]", "specify a custom name for module ids");
|
||||
commander.option(
|
||||
"--module-id [string]",
|
||||
"specify a custom name for module ids",
|
||||
);
|
||||
|
||||
// "babel" command specific arguments that are not passed to babel-core.
|
||||
commander.option("-x, --extensions [extensions]", "List of extensions to compile when a directory has been input [.es6,.js,.es,.jsx]", collect);
|
||||
commander.option(
|
||||
"-x, --extensions [extensions]",
|
||||
"List of extensions to compile when a directory has been input [.es6,.js,.es,.jsx,.mjs]",
|
||||
collect,
|
||||
);
|
||||
commander.option("-w, --watch", "Recompile files on changes");
|
||||
commander.option("--skip-initial-build", "Do not compile files before watching");
|
||||
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.option(
|
||||
"--skip-initial-build",
|
||||
"Do not compile files before watching",
|
||||
);
|
||||
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.option("-q, --quiet", "Don't log anything");
|
||||
/* eslint-enable max-len */
|
||||
|
||||
@@ -84,7 +157,7 @@ commander.parse(process.argv);
|
||||
|
||||
const errors = [];
|
||||
|
||||
let filenames = commander.args.reduce(function (globbed, input) {
|
||||
let filenames = commander.args.reduce(function(globbed, input) {
|
||||
let files = glob.sync(input);
|
||||
if (!files.length) files = [input];
|
||||
return globbed.concat(files);
|
||||
@@ -92,7 +165,7 @@ let filenames = commander.args.reduce(function (globbed, input) {
|
||||
|
||||
filenames = uniq(filenames);
|
||||
|
||||
filenames.forEach(function (filename) {
|
||||
filenames.forEach(function(filename) {
|
||||
if (!fs.existsSync(filename)) {
|
||||
errors.push(filename + " doesn't exist");
|
||||
}
|
||||
@@ -128,6 +201,10 @@ if (errors.length) {
|
||||
//
|
||||
|
||||
const opts = commander.opts();
|
||||
//the configFile CLI option maps to the extends option in the node API
|
||||
if (opts.configFile) {
|
||||
opts.extends = opts.configFile;
|
||||
}
|
||||
|
||||
// Delete options that are specific to babel-cli and shouldn't be passed to babel-core.
|
||||
delete opts.version;
|
||||
@@ -138,6 +215,7 @@ delete opts.outFile;
|
||||
delete opts.outDir;
|
||||
delete opts.copyFiles;
|
||||
delete opts.quiet;
|
||||
delete opts.configFile;
|
||||
|
||||
// Commander will default the "--no-" arguments to true, but we want to leave them undefined so that
|
||||
// babel-core can handle the default-assignment logic on its own.
|
||||
|
||||
@@ -10,8 +10,8 @@ export function chmod(src, dest) {
|
||||
}
|
||||
|
||||
export function readdirFilter(filename) {
|
||||
return readdir(filename).filter(function (filename) {
|
||||
return babel.util.isCompilableExtension(filename);
|
||||
return readdir(filename).filter(function(filename) {
|
||||
return isCompilableExtension(filename);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,7 +20,10 @@ export { readdir };
|
||||
/**
|
||||
* Test if a filename ends with a compilable extension.
|
||||
*/
|
||||
export function isCompilableExtension(filename: string, altExts?: Array<string>): boolean {
|
||||
export function isCompilableExtension(
|
||||
filename: string,
|
||||
altExts?: Array<string>,
|
||||
): boolean {
|
||||
const exts = altExts || babel.DEFAULT_EXTENSIONS;
|
||||
const ext = path.extname(filename);
|
||||
return includes(exts, ext);
|
||||
@@ -63,7 +66,7 @@ function toErrorStack(err) {
|
||||
}
|
||||
}
|
||||
|
||||
process.on("uncaughtException", function (err) {
|
||||
process.on("uncaughtException", function(err) {
|
||||
console.error(toErrorStack(err));
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -74,7 +77,7 @@ export function requireChokidar() {
|
||||
} catch (err) {
|
||||
console.error(
|
||||
"The optional dependency chokidar failed to install and is required for " +
|
||||
"--watch. Chokidar is likely not supported on your platform."
|
||||
"--watch. Chokidar is likely not supported on your platform.",
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
|
||||
3
packages/babel-cli/test/.othername_babelrc
Normal file
3
packages/babel-cli/test/.othername_babelrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"comments": false
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"args": ["--expose-debug-as=customDebug", "--eval", "console.log(customDebug.Debug.DebugEvent.Break)"],
|
||||
"stdout": "1"
|
||||
"args": ["--expose-gc-as=garbageCollector", "--eval", "console.log(typeof global.garbageCollector)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"args": ["--expose_debug_as=customDebug", "--eval", "console.log(customDebug.Debug.DebugEvent.Break)"],
|
||||
"stdout": "1"
|
||||
"args": ["--expose_gc_as=garbageCollector", "--eval", "console.log(typeof global.garbageCollector)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
|
||||
3
packages/babel-cli/test/fixtures/babel/--config-file babelrc nocomment/options.json
vendored
Normal file
3
packages/babel-cli/test/fixtures/babel/--config-file babelrc nocomment/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"args": ["--config-file", "../.othername_babelrc"]
|
||||
}
|
||||
7
packages/babel-cli/test/fixtures/babel/--config-file babelrc nocomment/stdin.txt
vendored
Normal file
7
packages/babel-cli/test/fixtures/babel/--config-file babelrc nocomment/stdin.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
Test comment
|
||||
*/
|
||||
|
||||
arr.map(x => x * MULTIPLIER);
|
||||
|
||||
// END OF FILE
|
||||
5
packages/babel-cli/test/fixtures/babel/--config-file babelrc nocomment/stdout.txt
vendored
Normal file
5
packages/babel-cli/test/fixtures/babel/--config-file babelrc nocomment/stdout.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
arr.map(function (x) {
|
||||
return x * MULTIPLIER;
|
||||
});
|
||||
@@ -3,9 +3,6 @@
|
||||
/*
|
||||
Test comment
|
||||
*/
|
||||
|
||||
arr.map(function (x) {
|
||||
return x * MULTIPLIER;
|
||||
});
|
||||
|
||||
// END OF FILE
|
||||
}); // END OF FILE
|
||||
|
||||
@@ -27,34 +27,39 @@ const pluginLocs = [
|
||||
path.join(__dirname, "/../../babel-plugin-transform-es2015-modules-commonjs"),
|
||||
].join(",");
|
||||
|
||||
const readDir = function (loc, filter) {
|
||||
const readDir = function(loc, filter) {
|
||||
const files = {};
|
||||
if (fs.existsSync(loc)) {
|
||||
readdir(loc, filter).forEach(function (filename) {
|
||||
readdir(loc, filter).forEach(function(filename) {
|
||||
files[filename] = helper.readFile(path.join(loc, filename));
|
||||
});
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
const saveInFiles = function (files) {
|
||||
const saveInFiles = function(files) {
|
||||
// Place an empty .babelrc in each test so tests won't unexpectedly get to repo-level config.
|
||||
outputFileSync(".babelrc", "{}");
|
||||
|
||||
Object.keys(files).forEach(function (filename) {
|
||||
Object.keys(files).forEach(function(filename) {
|
||||
const content = files[filename];
|
||||
outputFileSync(filename, content);
|
||||
});
|
||||
};
|
||||
|
||||
const assertTest = function (stdout, stderr, opts) {
|
||||
const assertTest = function(stdout, stderr, opts) {
|
||||
const expectStderr = opts.stderr.trim();
|
||||
stderr = stderr.trim();
|
||||
|
||||
if (opts.stderr) {
|
||||
if (opts.stderrContains) {
|
||||
assert.ok(includes(stderr, expectStderr), "stderr " + JSON.stringify(stderr) +
|
||||
" didn't contain " + JSON.stringify(expectStderr));
|
||||
assert.ok(
|
||||
includes(stderr, expectStderr),
|
||||
"stderr " +
|
||||
JSON.stringify(stderr) +
|
||||
" didn't contain " +
|
||||
JSON.stringify(expectStderr),
|
||||
);
|
||||
} else {
|
||||
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
|
||||
}
|
||||
@@ -68,8 +73,13 @@ const assertTest = function (stdout, stderr, opts) {
|
||||
|
||||
if (opts.stdout) {
|
||||
if (opts.stdoutContains) {
|
||||
assert.ok(includes(stdout, expectStdout), "stdout " + JSON.stringify(stdout) +
|
||||
" didn't contain " + JSON.stringify(expectStdout));
|
||||
assert.ok(
|
||||
includes(stdout, expectStdout),
|
||||
"stdout " +
|
||||
JSON.stringify(stdout) +
|
||||
" didn't contain " +
|
||||
JSON.stringify(expectStdout),
|
||||
);
|
||||
} else {
|
||||
chai.expect(stdout).to.equal(expectStdout, "stdout didn't match");
|
||||
}
|
||||
@@ -80,30 +90,34 @@ const assertTest = function (stdout, stderr, opts) {
|
||||
if (opts.outFiles) {
|
||||
const actualFiles = readDir(path.join(tmpLoc));
|
||||
|
||||
Object.keys(actualFiles).forEach(function (filename) {
|
||||
Object.keys(actualFiles).forEach(function(filename) {
|
||||
if (!opts.inFiles.hasOwnProperty(filename)) {
|
||||
const expect = opts.outFiles[filename];
|
||||
const actual = actualFiles[filename];
|
||||
|
||||
chai.expect(expect, "Output is missing: " + filename).to.not.be.undefined;
|
||||
chai.expect(expect, "Output is missing: " + filename).to.not.be
|
||||
.undefined;
|
||||
|
||||
if (expect) {
|
||||
chai.expect(actual).to.equal(expect, "Compiled output does not match: " + filename);
|
||||
chai
|
||||
.expect(actual)
|
||||
.to.equal(expect, "Compiled output does not match: " + filename);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(opts.outFiles).forEach(function(filename) {
|
||||
chai.expect(actualFiles, "Extraneous file in output: " + filename)
|
||||
chai
|
||||
.expect(actualFiles, "Extraneous file in output: " + filename)
|
||||
.to.contain.key(filename);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const buildTest = function (binName, testName, opts) {
|
||||
const buildTest = function(binName, testName, opts) {
|
||||
const binLoc = path.join(__dirname, "../lib", binName);
|
||||
|
||||
return function (callback) {
|
||||
return function(callback) {
|
||||
clear();
|
||||
saveInFiles(opts.inFiles);
|
||||
|
||||
@@ -124,15 +138,15 @@ const buildTest = function (binName, testName, opts) {
|
||||
let stderr = "";
|
||||
let stdout = "";
|
||||
|
||||
spawn.stderr.on("data", function (chunk) {
|
||||
spawn.stderr.on("data", function(chunk) {
|
||||
stderr += chunk;
|
||||
});
|
||||
|
||||
spawn.stdout.on("data", function (chunk) {
|
||||
spawn.stdout.on("data", function(chunk) {
|
||||
stdout += chunk;
|
||||
});
|
||||
|
||||
spawn.on("close", function () {
|
||||
spawn.on("close", function() {
|
||||
let err;
|
||||
|
||||
try {
|
||||
@@ -142,7 +156,8 @@ const buildTest = function (binName, testName, opts) {
|
||||
}
|
||||
|
||||
if (err) {
|
||||
err.message = args.map((arg) => `"${ arg }"`).join(" ") + ": " + err.message;
|
||||
err.message =
|
||||
args.map(arg => `"${arg}"`).join(" ") + ": " + err.message;
|
||||
}
|
||||
|
||||
callback(err);
|
||||
@@ -155,19 +170,19 @@ const buildTest = function (binName, testName, opts) {
|
||||
};
|
||||
};
|
||||
|
||||
const clear = function () {
|
||||
const clear = function() {
|
||||
process.chdir(__dirname);
|
||||
if (fs.existsSync(tmpLoc)) rimraf.sync(tmpLoc);
|
||||
fs.mkdirSync(tmpLoc);
|
||||
process.chdir(tmpLoc);
|
||||
};
|
||||
|
||||
fs.readdirSync(fixtureLoc).forEach(function (binName) {
|
||||
fs.readdirSync(fixtureLoc).forEach(function(binName) {
|
||||
if (binName[0] === ".") return;
|
||||
|
||||
const suiteLoc = path.join(fixtureLoc, binName);
|
||||
describe("bin/" + binName, function () {
|
||||
fs.readdirSync(suiteLoc).forEach(function (testName) {
|
||||
describe("bin/" + binName, function() {
|
||||
fs.readdirSync(suiteLoc).forEach(function(testName) {
|
||||
if (testName[0] === ".") return;
|
||||
|
||||
const testLoc = path.join(suiteLoc, testName);
|
||||
@@ -179,7 +194,7 @@ fs.readdirSync(fixtureLoc).forEach(function (binName) {
|
||||
const optionsLoc = path.join(testLoc, "options.json");
|
||||
if (fs.existsSync(optionsLoc)) merge(opts, require(optionsLoc));
|
||||
|
||||
["stdout", "stdin", "stderr"].forEach(function (key) {
|
||||
["stdout", "stdin", "stderr"].forEach(function(key) {
|
||||
const loc = path.join(testLoc, key + ".txt");
|
||||
if (fs.existsSync(loc)) {
|
||||
opts[key] = helper.readFile(loc);
|
||||
|
||||
@@ -11,27 +11,54 @@ npm install --save-dev babel-code-frame
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import codeFrame from 'babel-code-frame';
|
||||
import { codeFrameColumns } from 'babel-code-frame';
|
||||
|
||||
const rawLines = `class Foo {
|
||||
constructor()
|
||||
}`;
|
||||
const lineNumber = 2;
|
||||
const colNumber = 16;
|
||||
const location = { start: { line: 2, column: 16 } };
|
||||
|
||||
const result = codeFrame(rawLines, lineNumber, colNumber, { /* options */ });
|
||||
const result = codeFrameColumns(rawLines, location, { /* options */ });
|
||||
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
```sh
|
||||
```
|
||||
1 | class Foo {
|
||||
> 2 | constructor()
|
||||
| ^
|
||||
3 | }
|
||||
```
|
||||
|
||||
If the column number is not known, you may pass `null` instead.
|
||||
If the column number is not known, you may omit it.
|
||||
|
||||
You can also pass an `end` hash in `location`.
|
||||
|
||||
```js
|
||||
import { codeFrameColumns } from 'babel-code-frame';
|
||||
|
||||
const rawLines = `class Foo {
|
||||
constructor() {
|
||||
console.log("hello");
|
||||
}
|
||||
}`;
|
||||
const location = { start: { line: 2, column: 17 }, end: { line: 4, column: 3 } };
|
||||
|
||||
const result = codeFrameColumns(rawLines, location, { /* options */ });
|
||||
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
```
|
||||
1 | class Foo {
|
||||
> 2 | constructor() {
|
||||
| ^
|
||||
> 3 | console.log("hello");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
> 4 | }
|
||||
| ^^^
|
||||
5 | };
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
@@ -58,3 +85,42 @@ Adjust the number of lines to show below the error.
|
||||
`boolean`, defaults to `false`.
|
||||
|
||||
Enable this to forcibly syntax highlight the code as JavaScript (for non-terminals); overrides `highlightCode`.
|
||||
|
||||
## Upgrading from prior versions
|
||||
|
||||
Prior to version 7, the only API exposed by this module was for a single line and optional column pointer. The old API will now log a deprecation warning.
|
||||
|
||||
The new API takes a `location` object, similar to what is available in an AST.
|
||||
|
||||
This is an example of the deprecated (but still available) API:
|
||||
|
||||
```js
|
||||
import codeFrame from 'babel-code-frame';
|
||||
|
||||
const rawLines = `class Foo {
|
||||
constructor()
|
||||
}`;
|
||||
const lineNumber = 2;
|
||||
const colNumber = 16;
|
||||
|
||||
const result = codeFrame(rawLines, lineNumber, colNumber, { /* options */ });
|
||||
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
To get the same highlighting using the new API:
|
||||
|
||||
```js
|
||||
import { codeFrameColumns } from 'babel-code-frame';
|
||||
|
||||
const rawLines = `class Foo {
|
||||
constructor() {
|
||||
console.log("hello");
|
||||
}
|
||||
}`;
|
||||
const location = { start: { line: 2, column: 16 } };
|
||||
|
||||
const result = codeFrameColumns(rawLines, location, { /* options */ });
|
||||
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "babel-code-frame",
|
||||
"version": "7.0.0-alpha.3",
|
||||
"version": "7.0.0-alpha.20",
|
||||
"description": "Generate errors that contain a code frame that point to source locations.",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -8,8 +8,11 @@
|
||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-code-frame",
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"chalk": "^1.1.0",
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strip-ansi": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,18 @@ import jsTokens, { matchToToken } from "js-tokens";
|
||||
import esutils from "esutils";
|
||||
import Chalk from "chalk";
|
||||
|
||||
let deprecationWarningShown = false;
|
||||
|
||||
type Location = {
|
||||
column: number,
|
||||
line: number,
|
||||
};
|
||||
|
||||
type NodeLocation = {
|
||||
end: Location,
|
||||
start: Location,
|
||||
};
|
||||
|
||||
/**
|
||||
* Chalk styles for token types.
|
||||
*/
|
||||
@@ -78,11 +90,11 @@ function getTokenType(match) {
|
||||
*/
|
||||
|
||||
function highlight(defs: Object, text: string) {
|
||||
return text.replace(jsTokens, function (...args) {
|
||||
return text.replace(jsTokens, function(...args) {
|
||||
const type = getTokenType(args);
|
||||
const colorize = defs[type];
|
||||
if (colorize) {
|
||||
return args[0].split(NEWLINE).map((str) => colorize(str)).join("\n");
|
||||
return args[0].split(NEWLINE).map(str => colorize(str)).join("\n");
|
||||
} else {
|
||||
return args[0];
|
||||
}
|
||||
@@ -90,18 +102,82 @@ function highlight(defs: Object, text: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a code frame, adding line numbers, code highlighting, and pointing to a given position.
|
||||
* Extract what lines should be marked and highlighted.
|
||||
*/
|
||||
|
||||
export default function (
|
||||
function getMarkerLines(
|
||||
loc: NodeLocation,
|
||||
source: Array<string>,
|
||||
opts: Object,
|
||||
): { start: number, end: number, markerLines: Object } {
|
||||
const startLoc: Location = Object.assign(
|
||||
{},
|
||||
{ column: 0, line: -1 },
|
||||
loc.start,
|
||||
);
|
||||
const endLoc: Location = Object.assign({}, startLoc, loc.end);
|
||||
const linesAbove = opts.linesAbove || 2;
|
||||
const linesBelow = opts.linesBelow || 3;
|
||||
|
||||
const startLine = startLoc.line;
|
||||
const startColumn = startLoc.column;
|
||||
const endLine = endLoc.line;
|
||||
const endColumn = endLoc.column;
|
||||
|
||||
let start = Math.max(startLine - (linesAbove + 1), 0);
|
||||
let end = Math.min(source.length, endLine + linesBelow);
|
||||
|
||||
if (startLine === -1) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (endLine === -1) {
|
||||
end = source.length;
|
||||
}
|
||||
|
||||
const lineDiff = endLine - startLine;
|
||||
const markerLines = {};
|
||||
|
||||
if (lineDiff) {
|
||||
for (let i = 0; i <= lineDiff; i++) {
|
||||
const lineNumber = i + startLine;
|
||||
|
||||
if (!startColumn) {
|
||||
markerLines[lineNumber] = true;
|
||||
} else if (i === 0) {
|
||||
const sourceLength = source[lineNumber - 1].length;
|
||||
|
||||
markerLines[lineNumber] = [startColumn, sourceLength - startColumn];
|
||||
} else if (i === lineDiff) {
|
||||
markerLines[lineNumber] = [0, endColumn];
|
||||
} else {
|
||||
const sourceLength = source[lineNumber - i].length;
|
||||
|
||||
markerLines[lineNumber] = [0, sourceLength];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (startColumn === endColumn) {
|
||||
if (startColumn) {
|
||||
markerLines[startLine] = [startColumn, 0];
|
||||
} else {
|
||||
markerLines[startLine] = true;
|
||||
}
|
||||
} else {
|
||||
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
||||
}
|
||||
}
|
||||
|
||||
return { start, end, markerLines };
|
||||
}
|
||||
|
||||
export function codeFrameColumns(
|
||||
rawLines: string,
|
||||
lineNumber: number,
|
||||
colNumber: ?number,
|
||||
loc: NodeLocation,
|
||||
opts: Object = {},
|
||||
): string {
|
||||
colNumber = Math.max(colNumber, 0);
|
||||
|
||||
const highlighted = (opts.highlightCode && Chalk.supportsColor) || opts.forceColor;
|
||||
const highlighted =
|
||||
(opts.highlightCode && Chalk.supportsColor) || opts.forceColor;
|
||||
let chalk = Chalk;
|
||||
if (opts.forceColor) {
|
||||
chalk = new Chalk.constructor({ enabled: true });
|
||||
@@ -112,45 +188,44 @@ export default function (
|
||||
const defs = getDefs(chalk);
|
||||
if (highlighted) rawLines = highlight(defs, rawLines);
|
||||
|
||||
const linesAbove = opts.linesAbove || 2;
|
||||
const linesBelow = opts.linesBelow || 3;
|
||||
|
||||
const lines = rawLines.split(NEWLINE);
|
||||
let start = Math.max(lineNumber - (linesAbove + 1), 0);
|
||||
let end = Math.min(lines.length, lineNumber + linesBelow);
|
||||
|
||||
if (!lineNumber && !colNumber) {
|
||||
start = 0;
|
||||
end = lines.length;
|
||||
}
|
||||
const { start, end, markerLines } = getMarkerLines(loc, lines, opts);
|
||||
|
||||
const numberMaxWidth = String(end).length;
|
||||
|
||||
const frame = lines.slice(start, end).map((line, index) => {
|
||||
const number = start + 1 + index;
|
||||
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
|
||||
const gutter = ` ${paddedNumber} | `;
|
||||
if (number === lineNumber) {
|
||||
let markerLine = "";
|
||||
if (colNumber) {
|
||||
const markerSpacing = line.slice(0, colNumber - 1).replace(/[^\t]/g, " ");
|
||||
markerLine = [
|
||||
"\n ",
|
||||
maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")),
|
||||
markerSpacing,
|
||||
maybeHighlight(defs.marker, "^"),
|
||||
const frame = lines
|
||||
.slice(start, end)
|
||||
.map((line, index) => {
|
||||
const number = start + 1 + index;
|
||||
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
|
||||
const gutter = ` ${paddedNumber} | `;
|
||||
const hasMarker = markerLines[number];
|
||||
if (hasMarker) {
|
||||
let markerLine = "";
|
||||
if (Array.isArray(hasMarker)) {
|
||||
const markerSpacing = line
|
||||
.slice(0, Math.max(hasMarker[0] - 1, 0))
|
||||
.replace(/[^\t]/g, " ");
|
||||
const numberOfMarkers = hasMarker[1] || 1;
|
||||
|
||||
markerLine = [
|
||||
"\n ",
|
||||
maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")),
|
||||
markerSpacing,
|
||||
maybeHighlight(defs.marker, "^").repeat(numberOfMarkers),
|
||||
].join("");
|
||||
}
|
||||
return [
|
||||
maybeHighlight(defs.marker, ">"),
|
||||
maybeHighlight(defs.gutter, gutter),
|
||||
line,
|
||||
markerLine,
|
||||
].join("");
|
||||
} else {
|
||||
return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
|
||||
}
|
||||
return [
|
||||
maybeHighlight(defs.marker, ">"),
|
||||
maybeHighlight(defs.gutter, gutter),
|
||||
line,
|
||||
markerLine,
|
||||
].join("");
|
||||
} else {
|
||||
return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
|
||||
}
|
||||
}).join("\n");
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
if (highlighted) {
|
||||
return chalk.reset(frame);
|
||||
@@ -158,3 +233,37 @@ export default function (
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a code frame, adding line numbers, code highlighting, and pointing to a given position.
|
||||
*/
|
||||
|
||||
export default function(
|
||||
rawLines: string,
|
||||
lineNumber: number,
|
||||
colNumber: ?number,
|
||||
opts: Object = {},
|
||||
): string {
|
||||
if (!deprecationWarningShown) {
|
||||
deprecationWarningShown = true;
|
||||
|
||||
const deprecationError = new Error(
|
||||
"Passing lineNumber and colNumber is deprecated to babel-code-frame. Please use `codeFrameColumns`.",
|
||||
);
|
||||
deprecationError.name = "DeprecationWarning";
|
||||
|
||||
if (process.emitWarning) {
|
||||
process.emitWarning(deprecationError);
|
||||
} else {
|
||||
console.warn(deprecationError);
|
||||
}
|
||||
}
|
||||
|
||||
colNumber = Math.max(colNumber, 0);
|
||||
|
||||
const location: NodeLocation = {
|
||||
start: { column: colNumber, line: lineNumber },
|
||||
};
|
||||
|
||||
return codeFrameColumns(rawLines, location, opts);
|
||||
}
|
||||
|
||||
@@ -1,49 +1,31 @@
|
||||
import assert from "assert";
|
||||
import chalk from "chalk";
|
||||
import codeFrame from "..";
|
||||
import stripAnsi from "strip-ansi";
|
||||
import codeFrame, { codeFrameColumns } from "..";
|
||||
|
||||
describe("babel-code-frame", function () {
|
||||
it("basic usage", function () {
|
||||
const rawLines = [
|
||||
"class Foo {",
|
||||
" constructor()",
|
||||
"};",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 2, 16), [
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor()",
|
||||
" | ^",
|
||||
" 3 | };",
|
||||
].join("\n"));
|
||||
describe("babel-code-frame", function() {
|
||||
it("basic usage", function() {
|
||||
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 2, 16),
|
||||
[
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor()",
|
||||
" | ^",
|
||||
" 3 | };",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("optional column number", function () {
|
||||
const rawLines = [
|
||||
"class Foo {",
|
||||
" constructor()",
|
||||
"};",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 2, null), [
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor()",
|
||||
" 3 | };",
|
||||
].join("\n"));
|
||||
it("optional column number", function() {
|
||||
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 2, null),
|
||||
[" 1 | class Foo {", "> 2 | constructor()", " 3 | };"].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("optional column number", function () {
|
||||
const rawLines = [
|
||||
"class Foo {",
|
||||
" constructor()",
|
||||
"};",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 2, null), [
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor()",
|
||||
" 3 | };",
|
||||
].join("\n"));
|
||||
});
|
||||
|
||||
it("maximum context lines and padding", function () {
|
||||
it("maximum context lines and padding", function() {
|
||||
const rawLines = [
|
||||
"/**",
|
||||
" * Sums two numbers.",
|
||||
@@ -57,18 +39,21 @@ describe("babel-code-frame", function () {
|
||||
" return a + b",
|
||||
"}",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 7, 2), [
|
||||
" 5 | * @param b Number",
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
" 9 | function sum(a, b) {",
|
||||
" 10 | return a + b",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 7, 2),
|
||||
[
|
||||
" 5 | * @param b Number",
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
" 9 | function sum(a, b) {",
|
||||
" 10 | return a + b",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("no unnecessary padding due to one-off errors", function () {
|
||||
it("no unnecessary padding due to one-off errors", function() {
|
||||
const rawLines = [
|
||||
"/**",
|
||||
" * Sums two numbers.",
|
||||
@@ -82,43 +67,49 @@ describe("babel-code-frame", function () {
|
||||
" return a + b",
|
||||
"}",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 6, 2), [
|
||||
" 4 | * @param a Number",
|
||||
" 5 | * @param b Number",
|
||||
"> 6 | * @returns Number",
|
||||
" | ^",
|
||||
" 7 | */",
|
||||
" 8 | ",
|
||||
" 9 | function sum(a, b) {",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 6, 2),
|
||||
[
|
||||
" 4 | * @param a Number",
|
||||
" 5 | * @param b Number",
|
||||
"> 6 | * @returns Number",
|
||||
" | ^",
|
||||
" 7 | */",
|
||||
" 8 | ",
|
||||
" 9 | function sum(a, b) {",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("tabs", function () {
|
||||
it("tabs", function() {
|
||||
const rawLines = [
|
||||
"\tclass Foo {",
|
||||
"\t \t\t constructor\t(\t)",
|
||||
"\t};",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 2, 25), [
|
||||
" 1 | \tclass Foo {",
|
||||
"> 2 | \t \t\t constructor\t(\t)",
|
||||
" | \t \t\t \t \t ^",
|
||||
" 3 | \t};",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 2, 25),
|
||||
[
|
||||
" 1 | \tclass Foo {",
|
||||
"> 2 | \t \t\t constructor\t(\t)",
|
||||
" | \t \t\t \t \t ^",
|
||||
" 3 | \t};",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("opts.highlightCode", function () {
|
||||
it("opts.highlightCode", function() {
|
||||
const rawLines = "console.log('babel')";
|
||||
const result = codeFrame(rawLines, 1, 9, { highlightCode: true });
|
||||
const stripped = chalk.stripColor(result);
|
||||
const stripped = stripAnsi(result);
|
||||
assert.ok(result.length > stripped.length);
|
||||
assert.equal(stripped, [
|
||||
"> 1 | console.log('babel')",
|
||||
" | ^",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
stripped,
|
||||
["> 1 | console.log('babel')", " | ^"].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("opts.linesAbove", function () {
|
||||
it("opts.linesAbove", function() {
|
||||
const rawLines = [
|
||||
"/**",
|
||||
" * Sums two numbers.",
|
||||
@@ -132,17 +123,20 @@ describe("babel-code-frame", function () {
|
||||
" return a + b",
|
||||
"}",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 7, 2, { linesAbove: 1 }), [
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
" 9 | function sum(a, b) {",
|
||||
" 10 | return a + b",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 7, 2, { linesAbove: 1 }),
|
||||
[
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
" 9 | function sum(a, b) {",
|
||||
" 10 | return a + b",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("opts.linesBelow", function () {
|
||||
it("opts.linesBelow", function() {
|
||||
const rawLines = [
|
||||
"/**",
|
||||
" * Sums two numbers.",
|
||||
@@ -156,16 +150,19 @@ describe("babel-code-frame", function () {
|
||||
" return a + b",
|
||||
"}",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 7, 2, { linesBelow: 1 }), [
|
||||
" 5 | * @param b Number",
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 7, 2, { linesBelow: 1 }),
|
||||
[
|
||||
" 5 | * @param b Number",
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("opts.linesAbove and opts.linesBelow", function () {
|
||||
it("opts.linesAbove and opts.linesBelow", function() {
|
||||
const rawLines = [
|
||||
"/**",
|
||||
" * Sums two numbers.",
|
||||
@@ -179,30 +176,127 @@ describe("babel-code-frame", function () {
|
||||
" return a + b",
|
||||
"}",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 7, 2, { linesAbove: 1, linesBelow: 1 }), [
|
||||
" 6 | * @returns Number",
|
||||
"> 7 | */",
|
||||
" | ^",
|
||||
" 8 | ",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 7, 2, { linesAbove: 1, linesBelow: 1 }),
|
||||
[" 6 | * @returns Number", "> 7 | */", " | ^", " 8 | "].join(
|
||||
"\n",
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("opts.forceColor", function() {
|
||||
const marker = chalk.red.bold;
|
||||
const gutter = chalk.grey;
|
||||
|
||||
const rawLines = ["", "", "", ""].join("\n");
|
||||
assert.equal(
|
||||
codeFrame(rawLines, 3, null, {
|
||||
linesAbove: 1,
|
||||
linesBelow: 1,
|
||||
forceColor: true,
|
||||
}),
|
||||
chalk.reset(
|
||||
[
|
||||
" " + gutter(" 2 | "),
|
||||
marker(">") + gutter(" 3 | "),
|
||||
" " + gutter(" 4 | "),
|
||||
].join("\n"),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("basic usage, new API", function() {
|
||||
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
|
||||
assert.equal(
|
||||
codeFrameColumns(rawLines, { start: { line: 2, column: 16 } }),
|
||||
[
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor()",
|
||||
" | ^",
|
||||
" 3 | };",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("mark multiple columns", function() {
|
||||
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
|
||||
assert.equal(
|
||||
codeFrameColumns(rawLines, {
|
||||
start: { line: 2, column: 3 },
|
||||
end: { line: 2, column: 16 },
|
||||
}),
|
||||
[
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor()",
|
||||
" | ^^^^^^^^^^^^^",
|
||||
" 3 | };",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("mark multiple columns across lines", function() {
|
||||
const rawLines = ["class Foo {", " constructor() {", " }", "};"].join(
|
||||
"\n",
|
||||
);
|
||||
assert.equal(
|
||||
codeFrameColumns(rawLines, {
|
||||
start: { line: 2, column: 17 },
|
||||
end: { line: 3, column: 3 },
|
||||
}),
|
||||
[
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor() {",
|
||||
" | ^",
|
||||
"> 3 | }",
|
||||
" | ^^^",
|
||||
" 4 | };",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("mark multiple columns across multiple lines", function() {
|
||||
const rawLines = [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"class Foo {",
|
||||
" constructor() {",
|
||||
" console.log(arguments);",
|
||||
" }",
|
||||
"};",
|
||||
].join("\n");
|
||||
assert.equal(codeFrame(rawLines, 3, null, { linesAbove: 1, linesBelow: 1, forceColor: true }),
|
||||
chalk.reset([
|
||||
" " + gutter(" 2 | "),
|
||||
marker(">") + gutter(" 3 | "),
|
||||
" " + gutter(" 4 | "),
|
||||
].join("\n"))
|
||||
assert.equal(
|
||||
codeFrameColumns(rawLines, {
|
||||
start: { line: 2, column: 17 },
|
||||
end: { line: 4, column: 3 },
|
||||
}),
|
||||
[
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor() {",
|
||||
" | ^",
|
||||
"> 3 | console.log(arguments);",
|
||||
" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^",
|
||||
"> 4 | }",
|
||||
" | ^^^",
|
||||
" 5 | };",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("mark across multiple lines without columns", function() {
|
||||
const rawLines = [
|
||||
"class Foo {",
|
||||
" constructor() {",
|
||||
" console.log(arguments);",
|
||||
" }",
|
||||
"};",
|
||||
].join("\n");
|
||||
assert.equal(
|
||||
codeFrameColumns(rawLines, { start: { line: 2 }, end: { line: 4 } }),
|
||||
[
|
||||
" 1 | class Foo {",
|
||||
"> 2 | constructor() {",
|
||||
"> 3 | console.log(arguments);",
|
||||
"> 4 | }",
|
||||
" 5 | };",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
```javascript
|
||||
var babel = require("babel-core");
|
||||
import { transform } from 'babel-core';
|
||||
import * as babel from 'babel-core';
|
||||
import { transform } from "babel-core";
|
||||
import * as babel from "babel-core";
|
||||
```
|
||||
|
||||
All transformations will use your local configuration files (.babelrc or in package.json). See [options](#options) to disable it.
|
||||
All transformations will use your local configuration files (`.babelrc` or in `package.json`). See [options](#options) to disable it.
|
||||
|
||||
## babel.transform(code: string, [options?](#options): Object)
|
||||
|
||||
@@ -62,12 +62,12 @@ babel.transformFileSync("filename.js", options).code;
|
||||
|
||||
## babel.transformFromAst(ast: Object, code?: string, [options?](#options): Object)
|
||||
|
||||
Given, an [AST](https://astexplorer.net/), transform it.
|
||||
Given an [AST](https://astexplorer.net/), transform it.
|
||||
|
||||
```js
|
||||
const code = "if (true) return;";
|
||||
const ast = babylon.parse(code, { allowReturnOutsideFunction: true });
|
||||
const { code, map, ast } = babel.transformFromAst(ast, code, options);
|
||||
const sourceCode = "if (true) return;";
|
||||
const parsedAst = babylon.parse(sourceCode, { allowReturnOutsideFunction: true });
|
||||
const { code, map, ast } = babel.transformFromAst(parsedAst, sourceCode, options);
|
||||
```
|
||||
|
||||
## Options
|
||||
@@ -87,35 +87,35 @@ Following is a table of the options you can use:
|
||||
| Option | Default | Description |
|
||||
| ------------------------ | -------------------- | ------------------------------- |
|
||||
| `ast` | `true` | Include the AST in the returned object |
|
||||
| `auxiliaryCommentAfter` | `null` | Attach a comment after all non-user injected code. |
|
||||
| `auxiliaryCommentBefore` | `null` | Attach a comment before all non-user injected code. |
|
||||
| `babelrc` | `true` | Specify whether or not to use .babelrc and .babelignore files. Not available when using the CLI, [use `--no-babelrc` instead](https://babeljs.io/docs/usage/cli/#babel-ignoring-babelrc). |
|
||||
| `auxiliaryCommentAfter` | `null` | Attach a comment after all non-user injected code |
|
||||
| `auxiliaryCommentBefore` | `null` | Attach a comment before all non-user injected code |
|
||||
| `babelrc` | `true` | Specify whether or not to use .babelrc and .babelignore files. Not available when using the CLI, [use `--no-babelrc` instead](https://babeljs.io/docs/usage/cli/#babel-ignoring-babelrc) |
|
||||
| `code` | `true` | Enable code generation |
|
||||
| `comments` | `true` | Output comments in generated output. |
|
||||
| `compact` | `"auto"` | Do not include superfluous whitespace characters and line terminators. When set to `"auto"` compact is set to `true` on input sizes of >500KB. |
|
||||
| `comments` | `true` | Output comments in generated output |
|
||||
| `compact` | `"auto"` | Do not include superfluous whitespace characters and line terminators. When set to `"auto"` compact is set to `true` on input sizes of >500KB |
|
||||
| `env` | `{}` | This is an object of keys that represent different environments. For example, you may have: `{ env: { production: { /* specific options */ } } }` which will use those options when the environment variable `BABEL_ENV` is set to `"production"`. If `BABEL_ENV` isn't set then `NODE_ENV` will be used, if it's not set then it defaults to `"development"` |
|
||||
| `extends` | `null` | A path to an `.babelrc` file to extend |
|
||||
| `filename` | `"unknown"` | Filename for use in errors etc. |
|
||||
| `filenameRelative` | `(filename)` | Filename relative to `sourceRoot`. |
|
||||
| `extends` | `null` | A path to a `.babelrc` file to extend |
|
||||
| `filename` | `"unknown"` | Filename for use in errors etc |
|
||||
| `filenameRelative` | `(filename)` | Filename relative to `sourceRoot` |
|
||||
| `generatorOpts` | `{}` | An object containing the options to be passed down to the babel code generator, babel-generator |
|
||||
| `getModuleId` | `null` | Specify a custom callback to generate a module id with. Called as `getModuleId(moduleName)`. If falsy value is returned then the generated module id is used. |
|
||||
| `getModuleId` | `null` | Specify a custom callback to generate a module id with. Called as `getModuleId(moduleName)`. If falsy value is returned then the generated module id is used |
|
||||
| `highlightCode` | `true` | ANSI highlight syntax error code frames |
|
||||
| `ignore` | `null` | Opposite to the `only` option. `ignore` is disregarded if `only` is specified. |
|
||||
| `inputSourceMap` | `null` | A source map object that the output source map will be based on. |
|
||||
| `ignore` | `null` | Opposite to the `only` option. `ignore` is disregarded if `only` is specified |
|
||||
| `inputSourceMap` | `null` | A source map object that the output source map will be based on |
|
||||
| `minified` | `false` | Should the output be minified (not printing last semicolons in blocks, printing literal string values instead of escaped ones, stripping `()` from `new` when safe) |
|
||||
| `moduleId` | `null` | Specify a custom name for module ids. |
|
||||
| `moduleId` | `null` | Specify a custom name for module ids |
|
||||
| `moduleIds` | `false` | If truthy, insert an explicit id for modules. By default, all modules are anonymous. (Not available for `common` modules) |
|
||||
| `moduleRoot` | `(sourceRoot)` | Optional prefix for the AMD module formatter that will be prepend to the filename on module definitions. |
|
||||
| `only` | `null` | A [glob](https://github.com/isaacs/minimatch), regex, or mixed array of both, matching paths to **only** compile. Can also be an array of arrays containing paths to explicitly match. When attempting to compile a non-matching file it's returned verbatim. |
|
||||
| `moduleRoot` | `(sourceRoot)` | Optional prefix for the AMD module formatter that will be prepend to the filename on module definitions |
|
||||
| `only` | `null` | A [glob](https://github.com/isaacs/minimatch), regex, or mixed array of both, matching paths to **only** compile. Can also be an array of arrays containing paths to explicitly match. When attempting to compile a non-matching file it's returned verbatim |
|
||||
| `parserOpts` | `{}` | An object containing the options to be passed down to the babel parser, babylon |
|
||||
| `plugins` | `[]` | List of [plugins](https://babeljs.io/docs/plugins/) to load and use. |
|
||||
| `presets` | `[]` | List of [presets](https://babeljs.io/docs/plugins/#presets) (a set of plugins) to load and use. |
|
||||
| `plugins` | `[]` | List of [plugins](https://babeljs.io/docs/plugins/) to load and use |
|
||||
| `presets` | `[]` | List of [presets](https://babeljs.io/docs/plugins/#presets) (a set of plugins) to load and use |
|
||||
| `retainLines` | `false` | Retain line numbers. This will lead to wacky code but is handy for scenarios where you can't use source maps. (**NOTE:** This will not retain the columns) |
|
||||
| `resolveModuleSource` | `null` | Resolve a module source ie. `import "SOURCE";` to a custom value. Called as `resolveModuleSource(source, filename)`. |
|
||||
| `shouldPrintComment` | `null` | An optional callback that controls whether a comment should be output or not. Called as `shouldPrintComment(commentContents)`. **NOTE:** This overrides the `comment` option when used. |
|
||||
| `sourceFileName` | `(filenameRelative)` | Set `sources[0]` on returned source map. |
|
||||
| `sourceMaps` | `false` | If truthy, adds a `map` property to returned output. If set to `"inline"`, a comment with a sourceMappingURL directive is added to the bottom of the returned code. If set to `"both"` then a `map` property is returned as well as a source map comment appended. **This does not emit sourcemap files by itself!** To have sourcemaps emitted using the CLI, you must pass it the `--source-maps` option. |
|
||||
| `sourceMapTarget` | `(filenameRelative)` | Set `file` on returned source map. |
|
||||
| `sourceRoot` | `(moduleRoot)` | The root from which all sources are relative. |
|
||||
| `sourceType` | `"module"` | Indicate the mode the code should be parsed in. Can be either "script" or "module". |
|
||||
| `resolveModuleSource` | `null` | Resolve a module source ie. `import "SOURCE";` to a custom value. Called as `resolveModuleSource(source, filename)` |
|
||||
| `shouldPrintComment` | `null` | An optional callback that controls whether a comment should be output or not. Called as `shouldPrintComment(commentContents)`. **NOTE:** This overrides the `comment` option when used |
|
||||
| `sourceFileName` | `(filenameRelative)` | Set `sources[0]` on returned source map |
|
||||
| `sourceMaps` | `false` | If truthy, adds a `map` property to returned output. If set to `"inline"`, a comment with a sourceMappingURL directive is added to the bottom of the returned code. If set to `"both"` then a `map` property is returned as well as a source map comment appended. **This does not emit sourcemap files by itself!** To have sourcemaps emitted using the CLI, you must pass it the `--source-maps` option |
|
||||
| `sourceMapTarget` | `(filenameRelative)` | Set `file` on returned source map |
|
||||
| `sourceRoot` | `(moduleRoot)` | The root from which all sources are relative |
|
||||
| `sourceType` | `"module"` | Indicate the mode the code should be parsed in. Can be either "script" or "module" |
|
||||
| `wrapPluginVisitorMethod`| `null` | An optional callback that can be used to wrap visitor methods. **NOTE:** This is useful for things like introspection, and not really needed for implementing anything. Called as `wrapPluginVisitorMethod(pluginAlias, visitorType, callback)`.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "babel-core",
|
||||
"version": "7.0.0-alpha.7",
|
||||
"version": "7.0.0-alpha.20",
|
||||
"description": "Babel compiler core.",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -25,28 +25,24 @@
|
||||
"./lib/config/loading/files/index.js": "./lib/config/loading/files/index-browser.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-code-frame": "7.0.0-alpha.3",
|
||||
"babel-generator": "7.0.0-alpha.7",
|
||||
"babel-helpers": "7.0.0-alpha.7",
|
||||
"babel-messages": "7.0.0-alpha.3",
|
||||
"babel-template": "7.0.0-alpha.7",
|
||||
"babel-traverse": "7.0.0-alpha.7",
|
||||
"babel-types": "7.0.0-alpha.7",
|
||||
"babylon": "7.0.0-beta.8",
|
||||
"babel-code-frame": "7.0.0-alpha.20",
|
||||
"babel-generator": "7.0.0-alpha.20",
|
||||
"babel-helpers": "7.0.0-alpha.20",
|
||||
"babel-messages": "7.0.0-alpha.20",
|
||||
"babel-template": "7.0.0-alpha.20",
|
||||
"babel-traverse": "7.0.0-alpha.20",
|
||||
"babel-types": "7.0.0-alpha.20",
|
||||
"babylon": "7.0.0-beta.22",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"debug": "^2.1.1",
|
||||
"json5": "^0.5.0",
|
||||
"lodash": "^4.2.0",
|
||||
"micromatch": "^2.3.11",
|
||||
"private": "^0.1.6",
|
||||
"resolve": "^1.3.2",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-helper-fixtures": "^7.0.0-alpha.3",
|
||||
"babel-helper-transform-fixture-test-runner": "7.0.0-alpha.7",
|
||||
"babel-polyfill": "7.0.0-alpha.7",
|
||||
"babel-register": "7.0.0-alpha.7"
|
||||
"babel-helper-transform-fixture-test-runner": "7.0.0-alpha.20",
|
||||
"babel-register": "7.0.0-alpha.20"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
import * as babel from "../index";
|
||||
// @flow
|
||||
|
||||
import { getEnv } from "./helpers/environment";
|
||||
import path from "path";
|
||||
import micromatch from "micromatch";
|
||||
import buildDebug from "debug";
|
||||
|
||||
const debug = buildDebug("babel:config:config-chain");
|
||||
|
||||
import { findConfigs, loadConfig } from "./loading/files";
|
||||
|
||||
export default function buildConfigChain(opts: Object = {}) {
|
||||
type ConfigItem = {
|
||||
type: "options" | "arguments",
|
||||
options: {},
|
||||
dirname: string,
|
||||
alias: string,
|
||||
loc: string,
|
||||
};
|
||||
|
||||
export default function buildConfigChain(opts: {}): Array<ConfigItem> | null {
|
||||
if (typeof opts.filename !== "string" && opts.filename != null) {
|
||||
throw new Error(".filename must be a string, null, or undefined");
|
||||
}
|
||||
|
||||
const filename = opts.filename ? path.resolve(opts.filename) : null;
|
||||
const builder = new ConfigChainBuilder(filename);
|
||||
|
||||
@@ -17,7 +34,7 @@ export default function buildConfigChain(opts: Object = {}) {
|
||||
});
|
||||
|
||||
// resolve all .babelrc files
|
||||
if (opts.babelrc !== false) {
|
||||
if (opts.babelrc !== false && filename) {
|
||||
builder.findConfigs(filename);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -30,6 +47,10 @@ export default function buildConfigChain(opts: Object = {}) {
|
||||
}
|
||||
|
||||
class ConfigChainBuilder {
|
||||
filename: string | null;
|
||||
configs: Array<ConfigItem>;
|
||||
possibleDirs: null | Array<string>;
|
||||
|
||||
constructor(filename) {
|
||||
this.configs = [];
|
||||
this.filename = filename;
|
||||
@@ -39,32 +60,43 @@ class ConfigChainBuilder {
|
||||
/**
|
||||
* Tests if a filename should be ignored based on "ignore" and "only" options.
|
||||
*/
|
||||
shouldIgnore(
|
||||
ignore: Array<string | RegExp | Function>,
|
||||
only?: Array<string | RegExp | Function>,
|
||||
dirname: string,
|
||||
): boolean {
|
||||
shouldIgnore(ignore: mixed, only: mixed, dirname: string): boolean {
|
||||
if (!this.filename) return false;
|
||||
|
||||
if (ignore) {
|
||||
if (!Array.isArray(ignore)) {
|
||||
throw new Error(`.ignore should be an array, was ${JSON.stringify(ignore)}`);
|
||||
throw new Error(
|
||||
`.ignore should be an array, ${JSON.stringify(ignore)} given`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const pattern of ignore) {
|
||||
if (this.matchesPattern(pattern, dirname)) return true;
|
||||
if (this.matchesPatterns(ignore, dirname)) {
|
||||
debug(
|
||||
"Ignored %o because it matched one of %O from %o",
|
||||
this.filename,
|
||||
ignore,
|
||||
dirname,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (only) {
|
||||
if (!Array.isArray(only)) {
|
||||
throw new Error(`.only should be an array, was ${JSON.stringify(only)}`);
|
||||
throw new Error(
|
||||
`.only should be an array, ${JSON.stringify(only)} given`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const pattern of only) {
|
||||
if (this.matchesPattern(pattern, dirname)) return false;
|
||||
if (!this.matchesPatterns(only, dirname)) {
|
||||
debug(
|
||||
"Ignored %o because it failed to match one of %O from %o",
|
||||
this.filename,
|
||||
only,
|
||||
dirname,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -74,44 +106,67 @@ class ConfigChainBuilder {
|
||||
* Returns result of calling function with filename if pattern is a function.
|
||||
* Otherwise returns result of matching pattern Regex with filename.
|
||||
*/
|
||||
matchesPattern(pattern: string | Function | RegExp, dirname: string) {
|
||||
if (typeof pattern === "string") {
|
||||
matchesPatterns(patterns: Array<mixed>, dirname: string) {
|
||||
const filename = this.filename;
|
||||
if (!filename) {
|
||||
throw new Error("Assertion failure: .filename should always exist here");
|
||||
}
|
||||
|
||||
const res = [];
|
||||
const strings = [];
|
||||
const fns = [];
|
||||
|
||||
patterns.forEach(pattern => {
|
||||
if (typeof pattern === "string") strings.push(pattern);
|
||||
else if (typeof pattern === "function") fns.push(pattern);
|
||||
else if (pattern instanceof RegExp) res.push(pattern);
|
||||
else {
|
||||
throw new Error(
|
||||
"Patterns must be a string, function, or regular expression",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (res.some(re => re.test(filename))) return true;
|
||||
if (fns.some(fn => fn(filename))) return true;
|
||||
|
||||
if (strings.length > 0) {
|
||||
let possibleDirs = this.possibleDirs;
|
||||
// Lazy-init so we don't initialize this for files that have no glob patterns.
|
||||
if (!this.possibleDirs) {
|
||||
this.possibleDirs = [];
|
||||
if (!possibleDirs) {
|
||||
possibleDirs = this.possibleDirs = [];
|
||||
|
||||
if (this.filename) {
|
||||
this.possibleDirs.push(this.filename);
|
||||
possibleDirs.push(filename);
|
||||
|
||||
let current = this.filename;
|
||||
while (true) {
|
||||
const previous = current;
|
||||
current = path.dirname(current);
|
||||
if (previous === current) break;
|
||||
let current = filename;
|
||||
while (true) {
|
||||
const previous = current;
|
||||
current = path.dirname(current);
|
||||
if (previous === current) break;
|
||||
|
||||
this.possibleDirs.push(current);
|
||||
}
|
||||
possibleDirs.push(current);
|
||||
}
|
||||
}
|
||||
|
||||
return this.possibleDirs.some(micromatch.filter(path.resolve(dirname, pattern), {
|
||||
nocase: true,
|
||||
nonegate: true,
|
||||
}));
|
||||
} else if (typeof pattern === "function") {
|
||||
return pattern(this.filename);
|
||||
} else {
|
||||
return pattern.test(this.filename);
|
||||
const absolutePatterns = strings.map(pattern => {
|
||||
// Preserve the "!" prefix so that micromatch can use it for negation.
|
||||
const negate = pattern[0] === "!";
|
||||
if (negate) pattern = pattern.slice(1);
|
||||
|
||||
return (negate ? "!" : "") + path.resolve(dirname, pattern);
|
||||
});
|
||||
|
||||
if (
|
||||
micromatch(possibleDirs, absolutePatterns, { nocase: true }).length > 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
findConfigs(loc: string) {
|
||||
if (!loc) return;
|
||||
|
||||
if (!path.isAbsolute(loc)) {
|
||||
loc = path.join(process.cwd(), loc);
|
||||
}
|
||||
|
||||
findConfigs(path.dirname(loc)).forEach(({ filepath, dirname, options }) => {
|
||||
this.mergeConfig({
|
||||
type: "options",
|
||||
@@ -122,33 +177,41 @@ class ConfigChainBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
mergeConfig({
|
||||
type,
|
||||
options,
|
||||
alias,
|
||||
loc,
|
||||
dirname,
|
||||
}) {
|
||||
if (!options) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mergeConfig({ type, options: rawOpts, alias, dirname }) {
|
||||
// Bail out ASAP if this file is ignored so that we run as little logic as possible on ignored files.
|
||||
if (this.filename && this.shouldIgnore(options.ignore, options.only, dirname)) {
|
||||
if (
|
||||
this.filename &&
|
||||
this.shouldIgnore(rawOpts.ignore || null, rawOpts.only || null, dirname)
|
||||
) {
|
||||
// TODO(logan): This is a really cross way to bail out. Avoid this in rewrite.
|
||||
throw Object.assign(new Error("This file has been ignored."), { code: "BABEL_IGNORED_FILE" });
|
||||
throw Object.assign((new Error("This file has been ignored."): any), {
|
||||
code: "BABEL_IGNORED_FILE",
|
||||
});
|
||||
}
|
||||
|
||||
options = Object.assign({}, options);
|
||||
const options = Object.assign({}, rawOpts);
|
||||
delete options.env;
|
||||
delete options.extends;
|
||||
|
||||
loc = loc || alias;
|
||||
const envKey = getEnv();
|
||||
|
||||
// env
|
||||
const envKey = babel.getEnv();
|
||||
if (options.env) {
|
||||
const envOpts = options.env[envKey];
|
||||
delete options.env;
|
||||
if (
|
||||
rawOpts.env != null &&
|
||||
(typeof rawOpts.env !== "object" || Array.isArray(rawOpts.env))
|
||||
) {
|
||||
throw new Error(".env block must be an object, null, or undefined");
|
||||
}
|
||||
|
||||
const envOpts = rawOpts.env && rawOpts.env[envKey];
|
||||
|
||||
if (
|
||||
envOpts != null &&
|
||||
(typeof envOpts !== "object" || Array.isArray(envOpts))
|
||||
) {
|
||||
throw new Error(".env[...] block must be an object, null, or undefined");
|
||||
}
|
||||
|
||||
if (envOpts) {
|
||||
this.mergeConfig({
|
||||
type,
|
||||
options: envOpts,
|
||||
@@ -161,15 +224,18 @@ class ConfigChainBuilder {
|
||||
type,
|
||||
options,
|
||||
alias,
|
||||
loc,
|
||||
loc: alias,
|
||||
dirname,
|
||||
});
|
||||
|
||||
// add extends clause
|
||||
if (options.extends) {
|
||||
const extendsConfig = loadConfig(options.extends, dirname);
|
||||
if (rawOpts.extends) {
|
||||
if (typeof rawOpts.extends !== "string") {
|
||||
throw new Error(".extends must be a string");
|
||||
}
|
||||
|
||||
const existingConfig = this.configs.some((config) => {
|
||||
const extendsConfig = loadConfig(rawOpts.extends, dirname);
|
||||
|
||||
const existingConfig = this.configs.some(config => {
|
||||
return config.alias === extendsConfig.filepath;
|
||||
});
|
||||
if (!existingConfig) {
|
||||
@@ -180,8 +246,6 @@ class ConfigChainBuilder {
|
||||
dirname: extendsConfig.dirname,
|
||||
});
|
||||
}
|
||||
delete options.extends;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
220
packages/babel-core/src/config/caching.js
Normal file
220
packages/babel-core/src/config/caching.js
Normal file
@@ -0,0 +1,220 @@
|
||||
// @flow
|
||||
|
||||
type CacheConfigurator = CacheConfiguratorFn & CacheConfiguratorObj;
|
||||
|
||||
type CacheConfiguratorFn = {
|
||||
(boolean): void,
|
||||
<T>(handler: () => T): T,
|
||||
};
|
||||
type CacheConfiguratorObj = {
|
||||
forever: () => void,
|
||||
never: () => void,
|
||||
using: <T>(handler: () => T) => T,
|
||||
invalidate: <T>(handler: () => T) => T,
|
||||
};
|
||||
|
||||
type CacheEntry<ResultT> = Array<[ResultT, () => boolean]>;
|
||||
|
||||
/**
|
||||
* Given a function with a single argument, cache its results based on its argument and how it
|
||||
* configures its caching behavior. Cached values are stored strongly.
|
||||
*/
|
||||
export function makeStrongCache<ArgT, ResultT>(
|
||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
||||
autoPermacache?: boolean,
|
||||
): ArgT => ResultT {
|
||||
return makeCachedFunction(new Map(), handler, autoPermacache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a function with a single argument, cache its results based on its argument and how it
|
||||
* configures its caching behavior. Cached values are stored weakly and the function argument must be
|
||||
* an object type.
|
||||
*/
|
||||
export function makeWeakCache<ArgT: {}, ResultT>(
|
||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
||||
autoPermacache?: boolean,
|
||||
): ArgT => ResultT {
|
||||
return makeCachedFunction(new WeakMap(), handler, autoPermacache);
|
||||
}
|
||||
|
||||
type CacheMap<ArgT, ResultT> =
|
||||
| Map<ArgT, CacheEntry<ResultT>>
|
||||
| WeakMap<ArgT, CacheEntry<ResultT>>;
|
||||
|
||||
function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
|
||||
callCache: Cache,
|
||||
handler: (ArgT, CacheConfigurator) => ResultT,
|
||||
autoPermacache: boolean = true,
|
||||
): ArgT => ResultT {
|
||||
return function cachedFunction(arg) {
|
||||
let cachedValue: CacheEntry<ResultT> | void = callCache.get(arg);
|
||||
|
||||
if (cachedValue) {
|
||||
for (const [value, valid] of cachedValue) {
|
||||
if (valid()) return value;
|
||||
}
|
||||
}
|
||||
|
||||
const { cache, result, deactivate } = makeCacheConfig();
|
||||
|
||||
const value = handler(arg, cache);
|
||||
|
||||
if (autoPermacache && !result.configured) cache.forever();
|
||||
|
||||
deactivate();
|
||||
|
||||
if (!result.configured) {
|
||||
// eslint-disable-next-line max-len
|
||||
throw new Error(
|
||||
[
|
||||
"Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured",
|
||||
"for various types of caching, using the first param of their handler functions:",
|
||||
"",
|
||||
"module.exports = function(api) {",
|
||||
" // The API exposes the following:",
|
||||
"",
|
||||
" // Cache the returned value forever and don't call this function again.",
|
||||
" api.cache(true);",
|
||||
"",
|
||||
" // Don't cache at all. Not recommended because it will be very slow.",
|
||||
" api.cache(false);",
|
||||
"",
|
||||
" // Cached based on the value of some function. If this function returns a value different from",
|
||||
" // a previously-encountered value, the plugins will re-evaluate.",
|
||||
" var env = api.cache(() => process.env.NODE_ENV);",
|
||||
"",
|
||||
" // If testing for a specific env, we recommend specifics to avoid instantiating a plugin for",
|
||||
" // any possible NODE_ENV value that might come up during plugin execution.",
|
||||
' var isProd = api.cache(() => process.env.NODE_ENV === "production");',
|
||||
"",
|
||||
" // .cache(fn) will perform a linear search though instances to find the matching plugin based",
|
||||
" // based on previous instantiated plugins. If you want to recreate the plugin and discard the",
|
||||
" // previous instance whenever something changes, you may use:",
|
||||
' var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production");',
|
||||
"",
|
||||
" // Note, we also expose the following more-verbose versions of the above examples:",
|
||||
" api.cache.forever(); // api.cache(true)",
|
||||
" api.cache.never(); // api.cache(false)",
|
||||
" api.cache.using(fn); // api.cache(fn)",
|
||||
"",
|
||||
" // Return the value that will be cached.",
|
||||
" return { };",
|
||||
"};",
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
|
||||
if (!result.never) {
|
||||
if (result.forever) {
|
||||
cachedValue = [[value, () => true]];
|
||||
} else if (result.invalidate) {
|
||||
cachedValue = [[value, result.valid]];
|
||||
} else {
|
||||
cachedValue = cachedValue || [];
|
||||
cachedValue.push([value, result.valid]);
|
||||
}
|
||||
callCache.set(arg, cachedValue);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
function makeCacheConfig(): {
|
||||
cache: CacheConfigurator,
|
||||
result: *,
|
||||
deactivate: () => void,
|
||||
} {
|
||||
const pairs = [];
|
||||
|
||||
const result = {
|
||||
configured: false,
|
||||
never: false,
|
||||
forever: false,
|
||||
invalidate: false,
|
||||
valid: () => pairs.every(([key, fn]) => key === fn()),
|
||||
};
|
||||
|
||||
let active = true;
|
||||
const deactivate = () => {
|
||||
active = false;
|
||||
};
|
||||
|
||||
const cache: CacheConfigurator = Object.assign(
|
||||
(function cacheFn(val) {
|
||||
if (typeof val === "boolean") {
|
||||
if (val) cache.forever();
|
||||
else cache.never();
|
||||
return;
|
||||
}
|
||||
|
||||
return cache.using(val);
|
||||
}: any),
|
||||
({
|
||||
forever() {
|
||||
if (!active) {
|
||||
throw new Error(
|
||||
"Cannot change caching after evaluation has completed.",
|
||||
);
|
||||
}
|
||||
if (result.never) {
|
||||
throw new Error("Caching has already been configured with .never()");
|
||||
}
|
||||
result.forever = true;
|
||||
result.configured = true;
|
||||
},
|
||||
never() {
|
||||
if (!active) {
|
||||
throw new Error(
|
||||
"Cannot change caching after evaluation has completed.",
|
||||
);
|
||||
}
|
||||
if (result.forever) {
|
||||
throw new Error(
|
||||
"Caching has already been configured with .forever()",
|
||||
);
|
||||
}
|
||||
result.never = true;
|
||||
result.configured = true;
|
||||
},
|
||||
using<T>(handler: () => T): T {
|
||||
if (!active) {
|
||||
throw new Error(
|
||||
"Cannot change caching after evaluation has completed.",
|
||||
);
|
||||
}
|
||||
if (result.never || result.forever) {
|
||||
throw new Error(
|
||||
"Caching has already been configured with .never or .forever()",
|
||||
);
|
||||
}
|
||||
result.configured = true;
|
||||
|
||||
const key = handler();
|
||||
pairs.push([key, handler]);
|
||||
return key;
|
||||
},
|
||||
invalidate<T>(handler: () => T): T {
|
||||
if (!active) {
|
||||
throw new Error(
|
||||
"Cannot change caching after evaluation has completed.",
|
||||
);
|
||||
}
|
||||
if (result.never || result.forever) {
|
||||
throw new Error(
|
||||
"Caching has already been configured with .never or .forever()",
|
||||
);
|
||||
}
|
||||
result.invalidate = true;
|
||||
result.configured = true;
|
||||
|
||||
const key = handler();
|
||||
pairs.push([key, handler]);
|
||||
return key;
|
||||
},
|
||||
}: CacheConfiguratorObj),
|
||||
);
|
||||
|
||||
return { cache, result, deactivate };
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
export function getEnv(defaultValue = "development") {
|
||||
// @flow
|
||||
|
||||
return process.env.BABEL_ENV
|
||||
|| process.env.NODE_ENV
|
||||
|| defaultValue;
|
||||
export function getEnv(defaultValue: string = "development"): string {
|
||||
return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import mergeWith from "lodash/mergeWith";
|
||||
|
||||
export default function (dest?: Object, src?: Object): ?Object {
|
||||
if (!dest || !src) return;
|
||||
|
||||
return mergeWith(dest, src, function (a, b) {
|
||||
if (b && Array.isArray(a)) {
|
||||
const newArray = b.slice(0);
|
||||
|
||||
for (const item of a) {
|
||||
if (newArray.indexOf(item) < 0) {
|
||||
newArray.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return newArray;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,30 +1,20 @@
|
||||
// @flow
|
||||
|
||||
import type Plugin from "./plugin";
|
||||
import OptionManager from "./option-manager";
|
||||
import manageOptions from "./option-manager";
|
||||
|
||||
export type ResolvedConfig = {
|
||||
options: Object,
|
||||
passes: Array<Array<Plugin>>,
|
||||
passes: Array<Array<[Plugin, ?{}]>>,
|
||||
};
|
||||
|
||||
/**
|
||||
* Standard API for loading Babel configuration data. Not for public consumption.
|
||||
*/
|
||||
export default function loadConfig(opts: Object): ResolvedConfig|null {
|
||||
const mergedOpts = new OptionManager().init(opts);
|
||||
if (!mergedOpts) return null;
|
||||
|
||||
let passes = [];
|
||||
if (mergedOpts.plugins) {
|
||||
passes.push(mergedOpts.plugins);
|
||||
export default function loadConfig(opts: mixed): ResolvedConfig | null {
|
||||
if (opts != null && typeof opts !== "object") {
|
||||
throw new Error("Babel options must be an object, null, or undefined");
|
||||
}
|
||||
|
||||
// With "passPerPreset" enabled there may still be presets in the options.
|
||||
if (mergedOpts.presets) {
|
||||
passes = passes.concat(mergedOpts.presets.map((preset) => preset.plugins).filter(Boolean));
|
||||
}
|
||||
|
||||
return {
|
||||
options: mergedOpts,
|
||||
passes,
|
||||
};
|
||||
return manageOptions(opts || {});
|
||||
}
|
||||
|
||||
@@ -1,33 +1,26 @@
|
||||
// @flow
|
||||
|
||||
import buildDebug from "debug";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import json5 from "json5";
|
||||
import resolve from "resolve";
|
||||
import { getEnv } from "../../helpers/environment";
|
||||
import { makeStrongCache } from "../../caching";
|
||||
|
||||
const debug = buildDebug("babel:config:loading:files:configuration");
|
||||
|
||||
type ConfigFile = {
|
||||
filepath: string,
|
||||
dirname: string,
|
||||
options: Object,
|
||||
options: {},
|
||||
};
|
||||
|
||||
const existsCache = {};
|
||||
const jsonCache = {};
|
||||
|
||||
const BABELRC_FILENAME = ".babelrc";
|
||||
const BABELRC_JS_FILENAME = ".babelrc.js";
|
||||
const PACKAGE_FILENAME = "package.json";
|
||||
const BABELIGNORE_FILENAME = ".babelignore";
|
||||
|
||||
function exists(filename) {
|
||||
const cached = existsCache[filename];
|
||||
if (cached == null) {
|
||||
return existsCache[filename] = fs.existsSync(filename);
|
||||
} else {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
export function findConfigs(dirname: string): Array<ConfigFile> {
|
||||
let foundConfig = false;
|
||||
let foundIgnore = false;
|
||||
@@ -41,6 +34,7 @@ export function findConfigs(dirname: string): Array<ConfigFile> {
|
||||
const ignore = readIgnoreConfig(ignoreLoc);
|
||||
|
||||
if (ignore) {
|
||||
debug("Found ignore %o from %o.", ignore.filepath, dirname);
|
||||
confs.push(ignore);
|
||||
foundIgnore = true;
|
||||
}
|
||||
@@ -51,19 +45,23 @@ export function findConfigs(dirname: string): Array<ConfigFile> {
|
||||
BABELRC_FILENAME,
|
||||
BABELRC_JS_FILENAME,
|
||||
PACKAGE_FILENAME,
|
||||
].reduce((previousConfig: ConfigFile|null, name) => {
|
||||
].reduce((previousConfig: ConfigFile | null, name) => {
|
||||
const filepath = path.join(loc, name);
|
||||
const config = readConfig(filepath);
|
||||
|
||||
if (config && previousConfig) {
|
||||
throw new Error(`Multiple configuration files found. Please remove one:\n- ${
|
||||
path.basename(previousConfig.filepath)}\n- ${name}\nfrom ${loc}`);
|
||||
throw new Error(
|
||||
`Multiple configuration files found. Please remove one:\n- ${path.basename(
|
||||
previousConfig.filepath,
|
||||
)}\n- ${name}\nfrom ${loc}`,
|
||||
);
|
||||
}
|
||||
|
||||
return config || previousConfig;
|
||||
}, null);
|
||||
|
||||
if (conf) {
|
||||
debug("Found configuration %o from %o.", conf.filepath, dirname);
|
||||
confs.push(conf);
|
||||
foundConfig = true;
|
||||
}
|
||||
@@ -83,8 +81,11 @@ export function loadConfig(name: string, dirname: string): ConfigFile {
|
||||
const filepath = resolve.sync(name, { basedir: dirname });
|
||||
|
||||
const conf = readConfig(filepath);
|
||||
if (!conf) throw new Error(`Config file ${filepath} contains no configuration data`);
|
||||
if (!conf) {
|
||||
throw new Error(`Config file ${filepath} contains no configuration data`);
|
||||
}
|
||||
|
||||
debug("Loaded config %o from $o.", name, dirname);
|
||||
return conf;
|
||||
}
|
||||
|
||||
@@ -93,41 +94,63 @@ export function loadConfig(name: string, dirname: string): ConfigFile {
|
||||
* throw if there are parsing errors while loading a config.
|
||||
*/
|
||||
function readConfig(filepath) {
|
||||
return (path.extname(filepath) === ".js") ? readConfigJS(filepath) : readConfigFile(filepath);
|
||||
return path.extname(filepath) === ".js"
|
||||
? readConfigJS(filepath)
|
||||
: readConfigFile(filepath);
|
||||
}
|
||||
|
||||
function readIgnoreConfig(filepath) {
|
||||
if (!exists(filepath)) return null;
|
||||
const LOADING_CONFIGS = new Set();
|
||||
const readConfigJS = makeStrongCache((filepath, cache) => {
|
||||
if (!fs.existsSync(filepath)) {
|
||||
cache.forever();
|
||||
return null;
|
||||
}
|
||||
|
||||
const file = fs.readFileSync(filepath, "utf8");
|
||||
let lines = file.split("\n");
|
||||
// The `require()` call below can make this code reentrant if a require hook like babel-register has been
|
||||
// loaded into the system. That would cause Babel to attempt to compile the `.babelrc.js` file as it loads
|
||||
// below. To cover this case, we auto-ignore re-entrant config processing.
|
||||
if (LOADING_CONFIGS.has(filepath)) {
|
||||
cache.never();
|
||||
|
||||
lines = lines
|
||||
.map((line) => line.replace(/#(.*?)$/, "").trim())
|
||||
.filter((line) => !!line);
|
||||
|
||||
return {
|
||||
filepath,
|
||||
dirname: path.dirname(filepath),
|
||||
options: { ignore: lines },
|
||||
};
|
||||
}
|
||||
|
||||
function readConfigJS(filepath) {
|
||||
if (!exists(filepath)) return null;
|
||||
debug("Auto-ignoring usage of config %o.", filepath);
|
||||
return {
|
||||
filepath,
|
||||
dirname: path.dirname(filepath),
|
||||
options: {},
|
||||
};
|
||||
}
|
||||
|
||||
let options;
|
||||
try {
|
||||
LOADING_CONFIGS.add(filepath);
|
||||
|
||||
// $FlowIssue
|
||||
const configModule = (require(filepath): mixed);
|
||||
options = configModule && configModule.__esModule ? (configModule.default || undefined) : configModule;
|
||||
options =
|
||||
configModule && configModule.__esModule
|
||||
? configModule.default || undefined
|
||||
: configModule;
|
||||
} catch (err) {
|
||||
err.message = `${filepath}: Error while loading config - ${err.message}`;
|
||||
throw err;
|
||||
} finally {
|
||||
LOADING_CONFIGS.delete(filepath);
|
||||
}
|
||||
|
||||
if (typeof options === "function") {
|
||||
options = options({
|
||||
cache,
|
||||
// Expose ".env()" so people can easily get the same env that we expose using the "env" key.
|
||||
env: () => cache.using(() => getEnv()),
|
||||
});
|
||||
} else {
|
||||
cache.forever();
|
||||
}
|
||||
|
||||
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
||||
throw new Error(`${filepath}: Configuration should be an exported JavaScript object.`);
|
||||
throw new Error(
|
||||
`${filepath}: Configuration should be an exported JavaScript object.`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -135,19 +158,13 @@ function readConfigJS(filepath) {
|
||||
dirname: path.dirname(filepath),
|
||||
options,
|
||||
};
|
||||
}
|
||||
|
||||
function readConfigFile(filepath) {
|
||||
if (!exists(filepath)) return null;
|
||||
|
||||
const content = fs.readFileSync(filepath, "utf8");
|
||||
}, false /* autoPermacache */);
|
||||
|
||||
const readConfigFile = makeStaticFileCache((filepath, content) => {
|
||||
let options;
|
||||
if (path.basename(filepath) === PACKAGE_FILENAME) {
|
||||
try {
|
||||
const json = jsonCache[content] = jsonCache[content] || JSON.parse(content);
|
||||
|
||||
options = json.babel;
|
||||
options = JSON.parse(content).babel;
|
||||
} catch (err) {
|
||||
err.message = `${filepath}: Error while parsing JSON - ${err.message}`;
|
||||
throw err;
|
||||
@@ -155,7 +172,7 @@ function readConfigFile(filepath) {
|
||||
if (!options) return null;
|
||||
} else {
|
||||
try {
|
||||
options = jsonCache[content] = jsonCache[content] || json5.parse(content);
|
||||
options = json5.parse(content);
|
||||
} catch (err) {
|
||||
err.message = `${filepath}: Error while parsing config - ${err.message}`;
|
||||
throw err;
|
||||
@@ -164,12 +181,50 @@ function readConfigFile(filepath) {
|
||||
if (!options) throw new Error(`${filepath}: No config detected`);
|
||||
}
|
||||
|
||||
if (typeof options !== "object") throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
|
||||
if (Array.isArray(options)) throw new Error(`${filepath}: Expected config object but found array`);
|
||||
if (typeof options !== "object") {
|
||||
throw new Error(`${filepath}: Config returned typeof ${typeof options}`);
|
||||
}
|
||||
if (Array.isArray(options)) {
|
||||
throw new Error(`${filepath}: Expected config object but found array`);
|
||||
}
|
||||
|
||||
return {
|
||||
filepath,
|
||||
dirname: path.dirname(filepath),
|
||||
options,
|
||||
};
|
||||
});
|
||||
|
||||
const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
|
||||
const ignore = content
|
||||
.split("\n")
|
||||
.map(line => line.replace(/#(.*?)$/, "").trim())
|
||||
.filter(line => !!line);
|
||||
|
||||
return {
|
||||
filepath,
|
||||
dirname: path.dirname(filepath),
|
||||
options: { ignore },
|
||||
};
|
||||
});
|
||||
|
||||
function makeStaticFileCache<T>(fn: (string, string) => T): string => T | null {
|
||||
return makeStrongCache((filepath, cache) => {
|
||||
if (cache.invalidate(() => fileMtime(filepath)) === null) {
|
||||
cache.forever();
|
||||
return null;
|
||||
}
|
||||
|
||||
return fn(filepath, fs.readFileSync(filepath, "utf8"));
|
||||
});
|
||||
}
|
||||
|
||||
function fileMtime(filepath: string): number | null {
|
||||
try {
|
||||
return +fs.statSync(filepath).mtime;
|
||||
} catch (e) {
|
||||
if (e.code !== "ENOENT") throw e;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
type ConfigFile = {
|
||||
filepath: string,
|
||||
dirname: string,
|
||||
options: Object,
|
||||
options: {},
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@@ -16,27 +16,47 @@ export function loadConfig(name: string, dirname: string): ConfigFile {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export function resolvePlugin(name: string, dirname: string): string|null {
|
||||
export function resolvePlugin(name: string, dirname: string): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export function resolvePreset(name: string, dirname: string): string|null {
|
||||
export function resolvePreset(name: string, dirname: string): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function loadPlugin(name: string, dirname: string): { filepath: string, plugin: mixed } {
|
||||
throw new Error(`Cannot load plugin ${name} relative to ${dirname} in a browser`);
|
||||
export function loadPlugin(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
throw new Error(
|
||||
`Cannot load plugin ${name} relative to ${dirname} in a browser`,
|
||||
);
|
||||
}
|
||||
|
||||
export function loadPreset(name: string, dirname: string): { filepath: string, preset: mixed } {
|
||||
throw new Error(`Cannot load preset ${name} relative to ${dirname} in a browser`);
|
||||
export function loadPreset(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
throw new Error(
|
||||
`Cannot load preset ${name} relative to ${dirname} in a browser`,
|
||||
);
|
||||
}
|
||||
|
||||
export function loadParser(name: string, dirname: string): { filepath: string, parser: Function } {
|
||||
throw new Error(`Cannot load parser ${name} relative to ${dirname} in a browser`);
|
||||
export function loadParser(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: Function } {
|
||||
throw new Error(
|
||||
`Cannot load parser ${name} relative to ${dirname} in a browser`,
|
||||
);
|
||||
}
|
||||
|
||||
export function loadGenerator(name: string, dirname: string): { filepath: string, generator: Function } {
|
||||
throw new Error(`Cannot load generator ${name} relative to ${dirname} in a browser`);
|
||||
export function loadGenerator(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: Function } {
|
||||
throw new Error(
|
||||
`Cannot load generator ${name} relative to ${dirname} in a browser`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import typeof * as indexType from "./index";
|
||||
|
||||
// Kind of gross, but essentially asserting that the exports of this module are the same as the
|
||||
// exports of index-browser, since this file may be replaced at bundle time with index-browser.
|
||||
((({}: any) : $Exact<indexBrowserType>): $Exact<indexType>);
|
||||
((({}: any): $Exact<indexBrowserType>): $Exact<indexType>);
|
||||
|
||||
export * from "./configuration";
|
||||
export * from "./plugins";
|
||||
|
||||
@@ -4,108 +4,211 @@
|
||||
* This file handles all logic for converting string-based configuration references into loaded objects.
|
||||
*/
|
||||
|
||||
import buildDebug from "debug";
|
||||
import resolve from "resolve";
|
||||
import path from "path";
|
||||
|
||||
export function resolvePlugin(pluginName: string, dirname: string): string|null {
|
||||
const possibleNames = [`babel-plugin-${pluginName}`, pluginName];
|
||||
const debug = buildDebug("babel:config:loading:files:plugins");
|
||||
|
||||
return resolveFromPossibleNames(possibleNames, dirname);
|
||||
const EXACT_RE = /^module:/;
|
||||
const BABEL_PLUGIN_PREFIX_RE = /^(?!@|module:|[^/\/]+[/\/]|babel-plugin-)/;
|
||||
const BABEL_PRESET_PREFIX_RE = /^(?!@|module:|[^/\/]+[/\/]|babel-preset-)/;
|
||||
const BABEL_PLUGIN_ORG_RE = /^(@babel[/\/])(?!plugin-|[^/\/]+[/\/])/;
|
||||
const BABEL_PRESET_ORG_RE = /^(@babel[/\/])(?!preset-|[^/\/]+[/\/])/;
|
||||
const OTHER_PLUGIN_ORG_RE = /^(@(?!babel[/\/])[^/\/]+[/\/])(?!babel-plugin-|[^/\/]+[/\/])/;
|
||||
const OTHER_PRESET_ORG_RE = /^(@(?!babel[/\/])[^/\/]+[/\/])(?!babel-preset-|[^/\/]+[/\/])/;
|
||||
|
||||
export function resolvePlugin(name: string, dirname: string): string | null {
|
||||
return resolveStandardizedName("plugin", name, dirname);
|
||||
}
|
||||
|
||||
export function resolvePreset(presetName: string, dirname: string): string|null {
|
||||
const possibleNames = [`babel-preset-${presetName}`, presetName];
|
||||
export function resolvePreset(name: string, dirname: string): string | null {
|
||||
return resolveStandardizedName("preset", name, dirname);
|
||||
}
|
||||
|
||||
// trying to resolve @organization shortcat
|
||||
// @foo/es2015 -> @foo/babel-preset-es2015
|
||||
const matches = presetName.match(/^(@[^/]+)\/(.+)$/);
|
||||
if (matches) {
|
||||
const [, orgName, presetPath] = matches;
|
||||
possibleNames.push(`${orgName}/babel-preset-${presetPath}`);
|
||||
export function loadPlugin(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
const filepath = resolvePlugin(name, dirname);
|
||||
if (!filepath) {
|
||||
throw new Error(`Plugin ${name} not found relative to ${dirname}`);
|
||||
}
|
||||
|
||||
return resolveFromPossibleNames(possibleNames, dirname);
|
||||
const value = requireModule("plugin", filepath);
|
||||
debug("Loaded plugin %o from %o.", name, dirname);
|
||||
|
||||
return { filepath, value };
|
||||
}
|
||||
|
||||
export function loadPlugin(name: string, dirname: string): { filepath: string, plugin: mixed } {
|
||||
const filepath = resolvePlugin(name, dirname);
|
||||
if (!filepath) throw new Error(`Plugin ${name} not found relative to ${dirname}`);
|
||||
|
||||
return {
|
||||
filepath,
|
||||
plugin: requireModule(filepath),
|
||||
};
|
||||
}
|
||||
|
||||
export function loadPreset(name: string, dirname: string): { filepath: string, preset: mixed } {
|
||||
export function loadPreset(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
const filepath = resolvePreset(name, dirname);
|
||||
if (!filepath) throw new Error(`Preset ${name} not found relative to ${dirname}`);
|
||||
if (!filepath) {
|
||||
throw new Error(`Preset ${name} not found relative to ${dirname}`);
|
||||
}
|
||||
|
||||
return {
|
||||
filepath,
|
||||
preset: requireModule(filepath),
|
||||
};
|
||||
const value = requireModule("preset", filepath);
|
||||
|
||||
debug("Loaded preset %o from %o.", name, dirname);
|
||||
|
||||
return { filepath, value };
|
||||
}
|
||||
|
||||
export function loadParser(name: string, dirname: string): { filepath: string, parser: Function } {
|
||||
const filepath = resolveQuiet(name, dirname);
|
||||
if (!filepath) throw new Error(`Parser ${name} not found relative to ${dirname}`);
|
||||
export function loadParser(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: Function } {
|
||||
const filepath = resolve.sync(name, { basedir: dirname });
|
||||
|
||||
const mod = requireModule(filepath);
|
||||
const mod = requireModule("parser", filepath);
|
||||
|
||||
if (!mod) {
|
||||
throw new Error(`Parser ${name} relative to ${dirname} does not export an object`);
|
||||
throw new Error(
|
||||
`Parser ${name} relative to ${dirname} does not export an object`,
|
||||
);
|
||||
}
|
||||
if (typeof mod.parse !== "function") {
|
||||
throw new Error(`Parser ${name} relative to ${dirname} does not export a .parse function`);
|
||||
throw new Error(
|
||||
`Parser ${name} relative to ${dirname} does not export a .parse function`,
|
||||
);
|
||||
}
|
||||
const value = mod.parse;
|
||||
|
||||
debug("Loaded parser %o from %o.", name, dirname);
|
||||
|
||||
return {
|
||||
filepath,
|
||||
parser: mod.parse,
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
export function loadGenerator(name: string, dirname: string): { filepath: string, generator: Function } {
|
||||
const filepath = resolveQuiet(name, dirname);
|
||||
if (!filepath) throw new Error(`Generator ${name} not found relative to ${dirname}`);
|
||||
export function loadGenerator(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: Function } {
|
||||
const filepath = resolve.sync(name, { basedir: dirname });
|
||||
|
||||
const mod = requireModule(filepath);
|
||||
const mod = requireModule("generator", filepath);
|
||||
|
||||
if (!mod) {
|
||||
throw new Error(`Generator ${name} relative to ${dirname} does not export an object`);
|
||||
throw new Error(
|
||||
`Generator ${name} relative to ${dirname} does not export an object`,
|
||||
);
|
||||
}
|
||||
if (typeof mod.print !== "function") {
|
||||
throw new Error(`Generator ${name} relative to ${dirname} does not export a .print function`);
|
||||
throw new Error(
|
||||
`Generator ${name} relative to ${dirname} does not export a .print function`,
|
||||
);
|
||||
}
|
||||
const value = mod.print;
|
||||
|
||||
debug("Loaded generator %o from %o.", name, dirname);
|
||||
|
||||
return {
|
||||
filepath,
|
||||
generator: mod.print,
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
function resolveQuiet(name: string, dirname: string): string|null {
|
||||
function standardizeName(type: "plugin" | "preset", name: string) {
|
||||
// Let absolute and relative paths through.
|
||||
if (path.isAbsolute(name)) return name;
|
||||
|
||||
const isPreset = type === "preset";
|
||||
|
||||
return (
|
||||
name
|
||||
// foo -> babel-preset-foo
|
||||
.replace(
|
||||
isPreset ? BABEL_PRESET_PREFIX_RE : BABEL_PLUGIN_PREFIX_RE,
|
||||
`babel-${type}-`,
|
||||
)
|
||||
// @babel/es2015 -> @babel/preset-es2015
|
||||
.replace(
|
||||
isPreset ? BABEL_PRESET_ORG_RE : BABEL_PLUGIN_ORG_RE,
|
||||
`$1${type}-`,
|
||||
)
|
||||
// @foo/mypreset -> @foo/babel-preset-mypreset
|
||||
.replace(
|
||||
isPreset ? OTHER_PRESET_ORG_RE : OTHER_PLUGIN_ORG_RE,
|
||||
`$1babel-${type}-`,
|
||||
)
|
||||
// module:mypreset -> mypreset
|
||||
.replace(EXACT_RE, "")
|
||||
);
|
||||
}
|
||||
|
||||
function resolveStandardizedName(
|
||||
type: "plugin" | "preset",
|
||||
name: string,
|
||||
dirname: string = process.cwd(),
|
||||
) {
|
||||
const standardizedName = standardizeName(type, name);
|
||||
|
||||
try {
|
||||
return resolve.sync(name, { basedir: dirname });
|
||||
return resolve.sync(standardizedName, { basedir: dirname });
|
||||
} catch (e) {
|
||||
// The 'resolve' module can currently throw ENOTDIR
|
||||
// https://github.com/substack/node-resolve/issues/121
|
||||
if (e.code !== "MODULE_NOT_FOUND" && e.code !== "ENOTDIR") throw e;
|
||||
if (e.code !== "MODULE_NOT_FOUND") throw e;
|
||||
|
||||
// Silently fail and move to the next item.
|
||||
if (standardizedName !== name) {
|
||||
let resolvedOriginal = false;
|
||||
try {
|
||||
resolve.sync(name, { basedir: dirname });
|
||||
resolvedOriginal = true;
|
||||
} catch (e2) {}
|
||||
|
||||
if (resolvedOriginal) {
|
||||
// eslint-disable-next-line max-len
|
||||
e.message += `\n- If you want to resolve "${name}", use "module:${name}"`;
|
||||
}
|
||||
}
|
||||
|
||||
let resolvedBabel = false;
|
||||
try {
|
||||
resolve.sync(standardizeName(type, "@babel/" + name), {
|
||||
basedir: dirname,
|
||||
});
|
||||
resolvedBabel = true;
|
||||
} catch (e2) {}
|
||||
|
||||
if (resolvedBabel) {
|
||||
// eslint-disable-next-line max-len
|
||||
e.message += `\n- Did you mean "@babel/${name}"?`;
|
||||
}
|
||||
|
||||
let resolvedOppositeType = false;
|
||||
const oppositeType = type === "preset" ? "plugin" : "preset";
|
||||
try {
|
||||
resolve.sync(standardizeName(oppositeType, name), { basedir: dirname });
|
||||
resolvedOppositeType = true;
|
||||
} catch (e2) {}
|
||||
|
||||
if (resolvedOppositeType) {
|
||||
// eslint-disable-next-line max-len
|
||||
e.message += `\n- Did you accidentally pass a ${type} as a ${oppositeType}?`;
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveFromPossibleNames(possibleNames: Array<string>, dirname: string): string|null {
|
||||
for (const name of possibleNames) {
|
||||
const result = resolveQuiet(name, dirname);
|
||||
if (result !== null) return result;
|
||||
const LOADING_MODULES = new Set();
|
||||
function requireModule(type: string, name: string): mixed {
|
||||
if (LOADING_MODULES.has(name)) {
|
||||
throw new Error(
|
||||
// eslint-disable-next-line max-len
|
||||
`Reentrant ${type} detected trying to load "${name}". This module is not ignored and is trying to load itself while compiling itself, leading to a dependency cycle. We recommend adding it to your "ignore" list in your babelrc, or to a .babelignore.`,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function requireModule(name: string): mixed {
|
||||
// $FlowIssue
|
||||
return require(name);
|
||||
try {
|
||||
LOADING_MODULES.add(name);
|
||||
// $FlowIssue
|
||||
return require(name);
|
||||
} finally {
|
||||
LOADING_MODULES.delete(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,34 +2,26 @@ import * as context from "../index";
|
||||
import Plugin from "./plugin";
|
||||
import * as messages from "babel-messages";
|
||||
import defaults from "lodash/defaults";
|
||||
import cloneDeepWith from "lodash/cloneDeepWith";
|
||||
import merge from "./helpers/merge";
|
||||
import merge from "lodash/merge";
|
||||
import removed from "./removed";
|
||||
import buildConfigChain from "./build-config-chain";
|
||||
import path from "path";
|
||||
import traverse from "babel-traverse";
|
||||
import clone from "lodash/clone";
|
||||
|
||||
import { loadPlugin, loadPreset, loadParser, loadGenerator } from "./loading/files";
|
||||
|
||||
type PluginObject = {
|
||||
pre?: Function;
|
||||
post?: Function;
|
||||
manipulateOptions?: Function;
|
||||
|
||||
visitor: ?{
|
||||
[key: string]: Function | {
|
||||
enter?: Function | Array<Function>;
|
||||
exit?: Function | Array<Function>;
|
||||
}
|
||||
};
|
||||
};
|
||||
import {
|
||||
loadPlugin,
|
||||
loadPreset,
|
||||
loadParser,
|
||||
loadGenerator,
|
||||
} from "./loading/files";
|
||||
|
||||
type MergeOptions = {
|
||||
type: "arguments"|"options"|"preset",
|
||||
options?: Object,
|
||||
extending?: Object,
|
||||
+type: "arguments" | "options" | "preset",
|
||||
options: {},
|
||||
alias: string,
|
||||
loc?: string,
|
||||
dirname?: string
|
||||
loc: string,
|
||||
dirname: string,
|
||||
};
|
||||
|
||||
const optionNames = new Set([
|
||||
@@ -74,292 +66,83 @@ const optionNames = new Set([
|
||||
"generatorOpts",
|
||||
]);
|
||||
|
||||
export default class OptionManager {
|
||||
const ALLOWED_PLUGIN_KEYS = new Set([
|
||||
"name",
|
||||
"manipulateOptions",
|
||||
"pre",
|
||||
"post",
|
||||
"visitor",
|
||||
"inherits",
|
||||
]);
|
||||
|
||||
export default function manageOptions(opts: {}): {
|
||||
options: Object,
|
||||
passes: Array<Array<[Plugin, ?{}]>>,
|
||||
} | null {
|
||||
return new OptionManager().init(opts);
|
||||
}
|
||||
|
||||
class OptionManager {
|
||||
constructor() {
|
||||
this.options = OptionManager.createBareOptions();
|
||||
this.options = createInitialOptions();
|
||||
this.passes = [[]];
|
||||
}
|
||||
|
||||
options: Object;
|
||||
|
||||
static memoisedPlugins: Array<{
|
||||
container: Function;
|
||||
plugin: Plugin;
|
||||
}>;
|
||||
|
||||
static memoisePluginContainer(fn, loc, i, alias) {
|
||||
for (const cache of (OptionManager.memoisedPlugins: Array<Object>)) {
|
||||
if (cache.container === fn) return cache.plugin;
|
||||
}
|
||||
|
||||
let obj: ?PluginObject;
|
||||
|
||||
if (typeof fn === "function") {
|
||||
obj = fn(context);
|
||||
} else {
|
||||
obj = fn;
|
||||
}
|
||||
|
||||
if (typeof obj === "object") {
|
||||
const plugin = new Plugin(obj, alias);
|
||||
OptionManager.memoisedPlugins.push({
|
||||
container: fn,
|
||||
plugin: plugin,
|
||||
});
|
||||
return plugin;
|
||||
} else {
|
||||
throw new TypeError(messages.get("pluginNotObject", loc, i, typeof obj) + loc + i);
|
||||
}
|
||||
}
|
||||
|
||||
static createBareOptions() {
|
||||
return {
|
||||
sourceType: "module",
|
||||
babelrc: true,
|
||||
filename: "unknown",
|
||||
code: true,
|
||||
metadata: true,
|
||||
ast: true,
|
||||
comments: true,
|
||||
compact: "auto",
|
||||
highlightCode: true,
|
||||
};
|
||||
}
|
||||
|
||||
static normalisePlugin(plugin, loc, i, alias) {
|
||||
plugin = plugin.__esModule ? plugin.default : plugin;
|
||||
|
||||
if (!(plugin instanceof Plugin)) {
|
||||
// allow plugin containers to be specified so they don't have to manually require
|
||||
if (typeof plugin === "function" || typeof plugin === "object") {
|
||||
plugin = OptionManager.memoisePluginContainer(plugin, loc, i, alias);
|
||||
} else {
|
||||
throw new TypeError(messages.get("pluginNotFunction", loc, i, typeof plugin));
|
||||
}
|
||||
}
|
||||
|
||||
plugin.init(loc, i);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
static normalisePlugins(loc, dirname, plugins) {
|
||||
return plugins.map(function (val, i) {
|
||||
let plugin, options;
|
||||
|
||||
if (!val) {
|
||||
throw new TypeError("Falsy value found in plugins");
|
||||
}
|
||||
|
||||
// destructure plugins
|
||||
if (Array.isArray(val)) {
|
||||
[plugin, options] = val;
|
||||
} else {
|
||||
plugin = val;
|
||||
}
|
||||
|
||||
const alias = typeof plugin === "string" ? plugin : `${loc}$${i}`;
|
||||
|
||||
// allow plugins to be specified as strings
|
||||
if (typeof plugin === "string") {
|
||||
plugin = loadPlugin(plugin, dirname).plugin;
|
||||
}
|
||||
|
||||
plugin = OptionManager.normalisePlugin(plugin, loc, i, alias);
|
||||
|
||||
return [plugin, options];
|
||||
});
|
||||
}
|
||||
passes: Array<Array<[Plugin, ?{}]>>;
|
||||
|
||||
/**
|
||||
* This is called when we want to merge the input `opts` into the
|
||||
* base options (passed as the `extendingOpts`: at top-level it's the
|
||||
* main options, at presets level it's presets options).
|
||||
* base options.
|
||||
*
|
||||
* - `alias` is used to output pretty traces back to the original source.
|
||||
* - `loc` is used to point to the original config.
|
||||
* - `dirname` is used to resolve plugins relative to it.
|
||||
*/
|
||||
|
||||
mergeOptions({
|
||||
type,
|
||||
options: rawOpts,
|
||||
extending: extendingOpts,
|
||||
alias,
|
||||
loc,
|
||||
dirname,
|
||||
}: MergeOptions) {
|
||||
alias = alias || "foreign";
|
||||
if (!rawOpts) return;
|
||||
mergeOptions(config: MergeOptions, pass?: Array<[Plugin, ?{}]>) {
|
||||
const result = loadConfig(config);
|
||||
|
||||
//
|
||||
if (typeof rawOpts !== "object" || Array.isArray(rawOpts)) {
|
||||
throw new TypeError(`Invalid options type for ${alias}`);
|
||||
const plugins = result.plugins.map(descriptor =>
|
||||
loadPluginDescriptor(descriptor),
|
||||
);
|
||||
const presets = result.presets.map(descriptor =>
|
||||
loadPresetDescriptor(descriptor),
|
||||
);
|
||||
|
||||
if (
|
||||
config.options.passPerPreset != null &&
|
||||
typeof config.options.passPerPreset !== "boolean"
|
||||
) {
|
||||
throw new Error(".passPerPreset must be a boolean or undefined");
|
||||
}
|
||||
const passPerPreset = config.options.passPerPreset;
|
||||
pass = pass || this.passes[0];
|
||||
|
||||
//
|
||||
const opts = cloneDeepWith(rawOpts, (val) => {
|
||||
if (val instanceof Plugin) {
|
||||
return val;
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
dirname = dirname || process.cwd();
|
||||
loc = loc || alias;
|
||||
|
||||
if (type !== "arguments") {
|
||||
if (opts.filename !== undefined) {
|
||||
throw new Error(`${alias}.filename is only allowed as a root argument`);
|
||||
// resolve presets
|
||||
if (presets.length > 0) {
|
||||
let presetPasses = null;
|
||||
if (passPerPreset) {
|
||||
presetPasses = presets.map(() => []);
|
||||
// The passes are created in the same order as the preset list, but are inserted before any
|
||||
// existing additional passes.
|
||||
this.passes.splice(1, 0, ...presetPasses);
|
||||
}
|
||||
|
||||
if (opts.babelrc !== undefined) {
|
||||
throw new Error(`${alias}.babelrc is only allowed as a root argument`);
|
||||
}
|
||||
}
|
||||
|
||||
if (type === "preset") {
|
||||
if (opts.only !== undefined) throw new Error(`${alias}.only is not supported in a preset`);
|
||||
if (opts.ignore !== undefined) throw new Error(`${alias}.ignore is not supported in a preset`);
|
||||
if (opts.extends !== undefined) throw new Error(`${alias}.extends is not supported in a preset`);
|
||||
if (opts.env !== undefined) throw new Error(`${alias}.env is not supported in a preset`);
|
||||
}
|
||||
|
||||
if (opts.sourceMap !== undefined) {
|
||||
if (opts.sourceMaps !== undefined) {
|
||||
throw new Error(`Both ${alias}.sourceMap and .sourceMaps have been set`);
|
||||
}
|
||||
|
||||
opts.sourceMaps = opts.sourceMap;
|
||||
delete opts.sourceMap;
|
||||
}
|
||||
|
||||
for (const key in opts) {
|
||||
// check for an unknown option
|
||||
if (!optionNames.has(key)) {
|
||||
if (removed[key]) {
|
||||
throw new ReferenceError(`Using removed Babel 5 option: ${alias}.${key} - ${removed[key].message}`);
|
||||
} else {
|
||||
// eslint-disable-next-line max-len
|
||||
const unknownOptErr = `Unknown option: ${alias}.${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`;
|
||||
|
||||
throw new ReferenceError(unknownOptErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.parserOpts && typeof opts.parserOpts.parser === "string") {
|
||||
opts.parserOpts.parser = loadParser(opts.parserOpts.parser, dirname).parser;
|
||||
}
|
||||
|
||||
if (opts.generatorOpts && typeof opts.generatorOpts.generator === "string") {
|
||||
opts.generatorOpts.generator = loadGenerator(opts.generatorOpts.generator, dirname).generator;
|
||||
presets.forEach((presetConfig, i) => {
|
||||
this.mergeOptions(presetConfig, presetPasses ? presetPasses[i] : pass);
|
||||
});
|
||||
}
|
||||
|
||||
// resolve plugins
|
||||
if (opts.plugins) {
|
||||
if (!Array.isArray(rawOpts.plugins)) throw new Error(`${alias}.plugins should be an array`);
|
||||
|
||||
opts.plugins = OptionManager.normalisePlugins(loc, dirname, opts.plugins);
|
||||
if (plugins.length > 0) {
|
||||
pass.unshift(...plugins);
|
||||
}
|
||||
|
||||
// resolve presets
|
||||
if (opts.presets) {
|
||||
if (!Array.isArray(rawOpts.presets)) throw new Error(`${alias}.presets should be an array`);
|
||||
|
||||
opts.presets = this.resolvePresets(opts.presets, dirname, (preset, presetLoc) => {
|
||||
this.mergeOptions({
|
||||
type: "preset",
|
||||
options: preset,
|
||||
|
||||
// For `passPerPreset` we merge child options back into the preset object instead of the root.
|
||||
extending: opts.passPerPreset ? preset : null,
|
||||
alias: presetLoc,
|
||||
loc: presetLoc,
|
||||
dirname: dirname,
|
||||
});
|
||||
});
|
||||
|
||||
// If not passPerPreset, the plugins have all been merged into the parent config so the presets
|
||||
// list is not needed.
|
||||
if (!opts.passPerPreset) delete opts.presets;
|
||||
}
|
||||
|
||||
// Merge them into current extending options in case of top-level
|
||||
// options. In case of presets, just re-assign options which are got
|
||||
// normalized during the `mergeOptions`.
|
||||
if (rawOpts === extendingOpts) {
|
||||
Object.assign(extendingOpts, opts);
|
||||
} else {
|
||||
merge(extendingOpts || this.options, opts);
|
||||
}
|
||||
merge(this.options, result.options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves presets options which can be either direct object data,
|
||||
* or a module name to require.
|
||||
*/
|
||||
resolvePresets(presets: Array<string | Object>, dirname: string, onResolve?) {
|
||||
return presets.map((preset) => {
|
||||
let options;
|
||||
if (Array.isArray(preset)) {
|
||||
if (preset.length > 2) {
|
||||
throw new Error(`Unexpected extra options ${JSON.stringify(preset.slice(2))} passed to preset.`);
|
||||
}
|
||||
|
||||
[preset, options] = preset;
|
||||
}
|
||||
|
||||
let presetLoc;
|
||||
try {
|
||||
if (typeof preset === "string") {
|
||||
({
|
||||
filepath: presetLoc,
|
||||
preset,
|
||||
} = loadPreset(preset, dirname));
|
||||
}
|
||||
const resolvedPreset = this.loadPreset(preset, options, { dirname });
|
||||
|
||||
if (onResolve) onResolve(resolvedPreset, presetLoc);
|
||||
|
||||
return resolvedPreset;
|
||||
} catch (e) {
|
||||
if (presetLoc) {
|
||||
e.message += ` (While processing preset: ${JSON.stringify(presetLoc)})`;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load one preset. The input is either the module name of the preset,
|
||||
* a function, or an object
|
||||
*/
|
||||
loadPreset(preset, options, meta) {
|
||||
let presetFactory = preset;
|
||||
|
||||
if (typeof presetFactory === "object" && presetFactory.__esModule) {
|
||||
if (presetFactory.default) {
|
||||
presetFactory = presetFactory.default;
|
||||
} else {
|
||||
throw new Error("Preset must export a default export when using ES6 modules.");
|
||||
}
|
||||
}
|
||||
|
||||
// Allow simple object exports
|
||||
if (typeof presetFactory === "object") {
|
||||
return presetFactory;
|
||||
}
|
||||
|
||||
if (typeof presetFactory !== "function") {
|
||||
// eslint-disable-next-line max-len
|
||||
throw new Error(`Unsupported preset format: ${typeof presetFactory}. Expected preset to return a function.`);
|
||||
}
|
||||
|
||||
return presetFactory(context, options, meta);
|
||||
}
|
||||
|
||||
init(opts: Object = {}): Object {
|
||||
init(opts: {}) {
|
||||
const configChain = buildConfigChain(opts);
|
||||
if (!configChain) return null;
|
||||
|
||||
@@ -371,7 +154,9 @@ export default class OptionManager {
|
||||
// There are a few case where thrown errors will try to annotate themselves multiple times, so
|
||||
// to keep things simple we just bail out if re-wrapping the message.
|
||||
if (!/^\[BABEL\]/.test(e.message)) {
|
||||
e.message = `[BABEL] ${opts.filename || "unknown"}: ${e.message}`;
|
||||
const filename =
|
||||
typeof opts.filename === "string" ? opts.filename : null;
|
||||
e.message = `[BABEL] ${filename || "unknown"}: ${e.message}`;
|
||||
}
|
||||
|
||||
throw e;
|
||||
@@ -379,6 +164,14 @@ export default class OptionManager {
|
||||
|
||||
opts = this.options;
|
||||
|
||||
// Tack the passes onto the object itself so that, if this object is passed back to Babel a second time,
|
||||
// it will be in the right structure to not change behavior.
|
||||
opts.plugins = this.passes[0];
|
||||
opts.presets = this.passes
|
||||
.slice(1)
|
||||
.filter(plugins => plugins.length > 0)
|
||||
.map(plugins => ({ plugins }));
|
||||
|
||||
if (opts.inputSourceMap) {
|
||||
opts.sourceMaps = true;
|
||||
}
|
||||
@@ -406,8 +199,366 @@ export default class OptionManager {
|
||||
sourceMapTarget: basenameRelative,
|
||||
});
|
||||
|
||||
return opts;
|
||||
return {
|
||||
options: opts,
|
||||
passes: this.passes,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
OptionManager.memoisedPlugins = [];
|
||||
type BasicDescriptor = {
|
||||
value: {} | Function,
|
||||
options: ?{},
|
||||
dirname: string,
|
||||
alias: string,
|
||||
loc: string,
|
||||
};
|
||||
|
||||
/**
|
||||
* Load and validate the given config into a set of options, plugins, and presets.
|
||||
*/
|
||||
function loadConfig(
|
||||
config,
|
||||
): {
|
||||
options: {},
|
||||
plugins: Array<BasicDescriptor>,
|
||||
presets: Array<BasicDescriptor>,
|
||||
} {
|
||||
const options = normalizeOptions(config);
|
||||
|
||||
if (
|
||||
config.options.plugins != null &&
|
||||
!Array.isArray(config.options.plugins)
|
||||
) {
|
||||
throw new Error(".plugins should be an array, null, or undefined");
|
||||
}
|
||||
|
||||
const plugins = (config.options.plugins || []).map((plugin, index) => {
|
||||
const { filepath, value, options } = normalizePair(
|
||||
plugin,
|
||||
loadPlugin,
|
||||
config.dirname,
|
||||
);
|
||||
|
||||
return {
|
||||
alias: filepath || `${config.loc}$${index}`,
|
||||
loc: filepath || config.loc,
|
||||
value,
|
||||
options,
|
||||
dirname: config.dirname,
|
||||
};
|
||||
});
|
||||
|
||||
if (
|
||||
config.options.presets != null &&
|
||||
!Array.isArray(config.options.presets)
|
||||
) {
|
||||
throw new Error(".presets should be an array, null, or undefined");
|
||||
}
|
||||
|
||||
const presets = (config.options.presets || []).map((preset, index) => {
|
||||
const { filepath, value, options } = normalizePair(
|
||||
preset,
|
||||
loadPreset,
|
||||
config.dirname,
|
||||
);
|
||||
|
||||
return {
|
||||
alias: filepath || `${config.loc}$${index}`,
|
||||
loc: filepath || config.loc,
|
||||
value,
|
||||
options,
|
||||
dirname: config.dirname,
|
||||
};
|
||||
});
|
||||
|
||||
return { options, plugins, presets };
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a generic plugin/preset from the given descriptor loaded from the config object.
|
||||
*/
|
||||
function loadDescriptor(descriptor, skipOptions) {
|
||||
if (typeof descriptor.value !== "function") {
|
||||
return { value: descriptor.value, descriptor };
|
||||
}
|
||||
|
||||
const { value, options } = descriptor;
|
||||
let item;
|
||||
try {
|
||||
if (skipOptions) {
|
||||
item = value(context);
|
||||
} else {
|
||||
item = value(context, options, { dirname: descriptor.dirname });
|
||||
}
|
||||
} catch (e) {
|
||||
if (descriptor.alias) {
|
||||
e.message += ` (While processing: ${JSON.stringify(descriptor.alias)})`;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (!item || typeof item !== "object") {
|
||||
throw new Error("Plugin/Preset did not return an object.");
|
||||
}
|
||||
|
||||
return { value: item, descriptor };
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a plugin for the given descriptor, returning the plugin/options pair.
|
||||
*/
|
||||
const PLUGIN_CACHE = new WeakMap();
|
||||
function loadPluginDescriptor(descriptor) {
|
||||
if (descriptor.value instanceof Plugin) {
|
||||
return [descriptor.value, descriptor.options];
|
||||
}
|
||||
|
||||
let result = PLUGIN_CACHE.get(descriptor.value);
|
||||
if (!result) {
|
||||
result = instantiatePlugin(
|
||||
loadDescriptor(descriptor, true /* skipOptions */),
|
||||
);
|
||||
PLUGIN_CACHE.set(descriptor.value, result);
|
||||
}
|
||||
|
||||
return [result, descriptor.options];
|
||||
}
|
||||
|
||||
function instantiatePlugin({ value: pluginObj, descriptor }) {
|
||||
Object.keys(pluginObj).forEach(key => {
|
||||
if (!ALLOWED_PLUGIN_KEYS.has(key)) {
|
||||
throw new Error(
|
||||
messages.get("pluginInvalidProperty", descriptor.alias, key),
|
||||
);
|
||||
}
|
||||
});
|
||||
if (
|
||||
pluginObj.visitor &&
|
||||
(pluginObj.visitor.enter || pluginObj.visitor.exit)
|
||||
) {
|
||||
throw new Error(
|
||||
"Plugins aren't allowed to specify catch-all enter/exit handlers. " +
|
||||
"Please target individual nodes.",
|
||||
);
|
||||
}
|
||||
|
||||
const plugin = Object.assign({}, pluginObj, {
|
||||
visitor: clone(pluginObj.visitor || {}),
|
||||
});
|
||||
|
||||
traverse.explode(plugin.visitor);
|
||||
|
||||
let inheritsDescriptor;
|
||||
let inherits;
|
||||
if (plugin.inherits) {
|
||||
inheritsDescriptor = {
|
||||
alias: `${descriptor.loc}$inherits`,
|
||||
loc: descriptor.loc,
|
||||
value: plugin.inherits,
|
||||
options: descriptor.options,
|
||||
dirname: descriptor.dirname,
|
||||
};
|
||||
|
||||
inherits = loadPluginDescriptor(inheritsDescriptor)[0];
|
||||
|
||||
plugin.pre = chain(inherits.pre, plugin.pre);
|
||||
plugin.post = chain(inherits.post, plugin.post);
|
||||
plugin.manipulateOptions = chain(
|
||||
inherits.manipulateOptions,
|
||||
plugin.manipulateOptions,
|
||||
);
|
||||
plugin.visitor = traverse.visitors.merge([
|
||||
inherits.visitor,
|
||||
plugin.visitor,
|
||||
]);
|
||||
}
|
||||
|
||||
return new Plugin(plugin, descriptor.alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a config object that will act as the root of a new nested config.
|
||||
*/
|
||||
function loadPresetDescriptor(descriptor): MergeOptions {
|
||||
return {
|
||||
type: "preset",
|
||||
options: loadDescriptor(descriptor).value,
|
||||
alias: descriptor.alias,
|
||||
loc: descriptor.loc,
|
||||
dirname: descriptor.dirname,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and return the options object for the config.
|
||||
*/
|
||||
function normalizeOptions(config) {
|
||||
const alias = config.alias || "foreign";
|
||||
const type = config.type;
|
||||
|
||||
//
|
||||
if (typeof config.options !== "object" || Array.isArray(config.options)) {
|
||||
throw new TypeError(`Invalid options type for ${alias}`);
|
||||
}
|
||||
|
||||
//
|
||||
const options = Object.assign({}, config.options);
|
||||
|
||||
if (type !== "arguments") {
|
||||
if (options.filename !== undefined) {
|
||||
throw new Error(`${alias}.filename is only allowed as a root argument`);
|
||||
}
|
||||
|
||||
if (options.babelrc !== undefined) {
|
||||
throw new Error(`${alias}.babelrc is only allowed as a root argument`);
|
||||
}
|
||||
}
|
||||
|
||||
if (type === "preset") {
|
||||
if (options.only !== undefined) {
|
||||
throw new Error(`${alias}.only is not supported in a preset`);
|
||||
}
|
||||
if (options.ignore !== undefined) {
|
||||
throw new Error(`${alias}.ignore is not supported in a preset`);
|
||||
}
|
||||
if (options.extends !== undefined) {
|
||||
throw new Error(`${alias}.extends is not supported in a preset`);
|
||||
}
|
||||
if (options.env !== undefined) {
|
||||
throw new Error(`${alias}.env is not supported in a preset`);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.sourceMap !== undefined) {
|
||||
if (options.sourceMaps !== undefined) {
|
||||
throw new Error(`Both ${alias}.sourceMap and .sourceMaps have been set`);
|
||||
}
|
||||
|
||||
options.sourceMaps = options.sourceMap;
|
||||
delete options.sourceMap;
|
||||
}
|
||||
|
||||
for (const key in options) {
|
||||
// check for an unknown option
|
||||
if (!optionNames.has(key)) {
|
||||
if (removed[key]) {
|
||||
throw new ReferenceError(
|
||||
`Using removed Babel 5 option: ${alias}.${key} - ${removed[key]
|
||||
.message}`,
|
||||
);
|
||||
} else {
|
||||
// eslint-disable-next-line max-len
|
||||
const unknownOptErr = `Unknown option: ${alias}.${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`;
|
||||
|
||||
throw new ReferenceError(unknownOptErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.parserOpts && typeof options.parserOpts.parser === "string") {
|
||||
options.parserOpts = Object.assign({}, options.parserOpts);
|
||||
options.parserOpts.parser = loadParser(
|
||||
options.parserOpts.parser,
|
||||
config.dirname,
|
||||
).value;
|
||||
}
|
||||
|
||||
if (
|
||||
options.generatorOpts &&
|
||||
typeof options.generatorOpts.generator === "string"
|
||||
) {
|
||||
options.generatorOpts = Object.assign({}, options.generatorOpts);
|
||||
options.generatorOpts.generator = loadGenerator(
|
||||
options.generatorOpts.generator,
|
||||
config.dirname,
|
||||
).value;
|
||||
}
|
||||
|
||||
delete options.passPerPreset;
|
||||
delete options.plugins;
|
||||
delete options.presets;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a plugin/preset item, resolve it into a standard format.
|
||||
*/
|
||||
function normalizePair(
|
||||
pair: mixed,
|
||||
resolver,
|
||||
dirname,
|
||||
): {
|
||||
filepath: string | null,
|
||||
value: {} | Function,
|
||||
options: ?{},
|
||||
} {
|
||||
let options;
|
||||
let value = pair;
|
||||
if (Array.isArray(pair)) {
|
||||
if (pair.length > 2) {
|
||||
throw new Error(
|
||||
`Unexpected extra options ${JSON.stringify(pair.slice(2))}.`,
|
||||
);
|
||||
}
|
||||
|
||||
[value, options] = pair;
|
||||
}
|
||||
|
||||
let filepath = null;
|
||||
if (typeof value === "string") {
|
||||
({ filepath, value } = resolver(value, dirname));
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
throw new Error(`Unexpected falsy value: ${String(value)}`);
|
||||
}
|
||||
|
||||
if (typeof value === "object" && value.__esModule) {
|
||||
if (value.default) {
|
||||
value = value.default;
|
||||
} else {
|
||||
throw new Error("Must export a default export when using ES6 modules.");
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value !== "object" && typeof value !== "function") {
|
||||
throw new Error(
|
||||
`Unsupported format: ${typeof value}. Expected an object or a function.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (options != null && typeof options !== "object") {
|
||||
throw new Error(
|
||||
"Plugin/Preset options must be an object, null, or undefined",
|
||||
);
|
||||
}
|
||||
|
||||
return { filepath, value, options };
|
||||
}
|
||||
|
||||
function chain(a, b) {
|
||||
const fns = [a, b].filter(Boolean);
|
||||
if (fns.length <= 1) return fns[0];
|
||||
|
||||
return function(...args) {
|
||||
for (const fn of fns) {
|
||||
fn.apply(this, args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createInitialOptions() {
|
||||
return {
|
||||
sourceType: "module",
|
||||
babelrc: true,
|
||||
filename: "unknown",
|
||||
code: true,
|
||||
metadata: true,
|
||||
ast: true,
|
||||
comments: true,
|
||||
compact: "auto",
|
||||
highlightCode: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,90 +1,39 @@
|
||||
import OptionManager from "./option-manager";
|
||||
import * as messages from "babel-messages";
|
||||
import traverse from "babel-traverse";
|
||||
import clone from "lodash/clone";
|
||||
|
||||
const GLOBAL_VISITOR_PROPS = ["enter", "exit"];
|
||||
// @flow
|
||||
|
||||
export default class Plugin {
|
||||
constructor(plugin: Object, key?: string) {
|
||||
this.initialized = false;
|
||||
this.raw = Object.assign({}, plugin);
|
||||
this.key = this.take("name") || key;
|
||||
constructor(plugin: {}, key?: string) {
|
||||
if (plugin.name != null && typeof plugin.name !== "string") {
|
||||
throw new Error("Plugin .name must be a string, null, or undefined");
|
||||
}
|
||||
if (
|
||||
plugin.manipulateOptions != null &&
|
||||
typeof plugin.manipulateOptions !== "function"
|
||||
) {
|
||||
throw new Error(
|
||||
"Plugin .manipulateOptions must be a function, null, or undefined",
|
||||
);
|
||||
}
|
||||
if (plugin.post != null && typeof plugin.post !== "function") {
|
||||
throw new Error("Plugin .post must be a function, null, or undefined");
|
||||
}
|
||||
if (plugin.pre != null && typeof plugin.pre !== "function") {
|
||||
throw new Error("Plugin .pre must be a function, null, or undefined");
|
||||
}
|
||||
if (plugin.visitor != null && typeof plugin.visitor !== "object") {
|
||||
throw new Error("Plugin .visitor must be an object, null, or undefined");
|
||||
}
|
||||
|
||||
this.manipulateOptions = this.take("manipulateOptions");
|
||||
this.post = this.take("post");
|
||||
this.pre = this.take("pre");
|
||||
this.visitor = this.normaliseVisitor(clone(this.take("visitor")) || {});
|
||||
this.key = plugin.name || key;
|
||||
|
||||
this.manipulateOptions = plugin.manipulateOptions;
|
||||
this.post = plugin.post;
|
||||
this.pre = plugin.pre;
|
||||
this.visitor = plugin.visitor;
|
||||
}
|
||||
|
||||
initialized: boolean;
|
||||
raw: Object;
|
||||
key: ?string;
|
||||
manipulateOptions: ?Function;
|
||||
post: ?Function;
|
||||
pre: ?Function;
|
||||
visitor: Object;
|
||||
|
||||
take(key) {
|
||||
const val = this.raw[key];
|
||||
delete this.raw[key];
|
||||
return val;
|
||||
}
|
||||
|
||||
chain(target, key) {
|
||||
if (!target[key]) return this[key];
|
||||
if (!this[key]) return target[key];
|
||||
|
||||
const fns: Array<?Function> = [target[key], this[key]];
|
||||
|
||||
return function (...args) {
|
||||
let val;
|
||||
for (const fn of fns) {
|
||||
if (fn) {
|
||||
const ret = fn.apply(this, args);
|
||||
if (ret != null) val = ret;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
};
|
||||
}
|
||||
|
||||
maybeInherit(loc: string) {
|
||||
let inherits = this.take("inherits");
|
||||
if (!inherits) return;
|
||||
|
||||
inherits = OptionManager.normalisePlugin(inherits, loc, "inherits");
|
||||
|
||||
this.manipulateOptions = this.chain(inherits, "manipulateOptions");
|
||||
this.post = this.chain(inherits, "post");
|
||||
this.pre = this.chain(inherits, "pre");
|
||||
this.visitor = traverse.visitors.merge([inherits.visitor, this.visitor]);
|
||||
}
|
||||
|
||||
/**
|
||||
* We lazy initialise parts of a plugin that rely on contextual information such as
|
||||
* position on disk and how it was specified.
|
||||
*/
|
||||
|
||||
init(loc: string, i: number) {
|
||||
if (this.initialized) return;
|
||||
this.initialized = true;
|
||||
|
||||
this.maybeInherit(loc);
|
||||
|
||||
for (const key in this.raw) {
|
||||
throw new Error(messages.get("pluginInvalidProperty", loc, i, key));
|
||||
}
|
||||
}
|
||||
|
||||
normaliseVisitor(visitor: Object): Object {
|
||||
for (const key of GLOBAL_VISITOR_PROPS) {
|
||||
if (visitor[key]) {
|
||||
throw new Error("Plugins aren't allowed to specify catch-all enter/exit handlers. " +
|
||||
"Please target individual nodes.");
|
||||
}
|
||||
}
|
||||
|
||||
traverse.explode(visitor);
|
||||
return visitor;
|
||||
}
|
||||
visitor: ?{};
|
||||
}
|
||||
|
||||
@@ -1,52 +1,59 @@
|
||||
// @flow
|
||||
/* eslint max-len: "off" */
|
||||
|
||||
export default {
|
||||
"auxiliaryComment": {
|
||||
"message": "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`",
|
||||
auxiliaryComment: {
|
||||
message: "Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`",
|
||||
},
|
||||
"blacklist": {
|
||||
"message": "Put the specific transforms you want in the `plugins` option",
|
||||
blacklist: {
|
||||
message: "Put the specific transforms you want in the `plugins` option",
|
||||
},
|
||||
"breakConfig": {
|
||||
"message": "This is not a necessary option in Babel 6",
|
||||
breakConfig: {
|
||||
message: "This is not a necessary option in Babel 6",
|
||||
},
|
||||
"experimental": {
|
||||
"message": "Put the specific transforms you want in the `plugins` option",
|
||||
experimental: {
|
||||
message: "Put the specific transforms you want in the `plugins` option",
|
||||
},
|
||||
"externalHelpers": {
|
||||
"message": "Use the `external-helpers` plugin instead. Check out http://babeljs.io/docs/plugins/external-helpers/",
|
||||
externalHelpers: {
|
||||
message:
|
||||
"Use the `external-helpers` plugin instead. Check out http://babeljs.io/docs/plugins/external-helpers/",
|
||||
},
|
||||
"extra": {
|
||||
"message": "",
|
||||
extra: {
|
||||
message: "",
|
||||
},
|
||||
"jsxPragma": {
|
||||
"message": "use the `pragma` option in the `react-jsx` plugin . Check out http://babeljs.io/docs/plugins/transform-react-jsx/",
|
||||
jsxPragma: {
|
||||
message:
|
||||
"use the `pragma` option in the `react-jsx` plugin . Check out http://babeljs.io/docs/plugins/transform-react-jsx/",
|
||||
},
|
||||
// "keepModuleIdExtensions": {
|
||||
// "message": ""
|
||||
// },
|
||||
"loose": {
|
||||
"message": "Specify the `loose` option for the relevant plugin you are using or use a preset that sets the option.",
|
||||
loose: {
|
||||
message:
|
||||
"Specify the `loose` option for the relevant plugin you are using or use a preset that sets the option.",
|
||||
},
|
||||
"metadataUsedHelpers": {
|
||||
"message": "Not required anymore as this is enabled by default",
|
||||
metadataUsedHelpers: {
|
||||
message: "Not required anymore as this is enabled by default",
|
||||
},
|
||||
"modules": {
|
||||
"message": "Use the corresponding module transform plugin in the `plugins` option. Check out http://babeljs.io/docs/plugins/#modules",
|
||||
modules: {
|
||||
message:
|
||||
"Use the corresponding module transform plugin in the `plugins` option. Check out http://babeljs.io/docs/plugins/#modules",
|
||||
},
|
||||
"nonStandard": {
|
||||
"message": "Use the `react-jsx` and `flow-strip-types` plugins to support JSX and Flow. Also check out the react preset http://babeljs.io/docs/plugins/preset-react/",
|
||||
nonStandard: {
|
||||
message:
|
||||
"Use the `react-jsx` and `flow-strip-types` plugins to support JSX and Flow. Also check out the react preset http://babeljs.io/docs/plugins/preset-react/",
|
||||
},
|
||||
"optional": {
|
||||
"message": "Put the specific transforms you want in the `plugins` option",
|
||||
optional: {
|
||||
message: "Put the specific transforms you want in the `plugins` option",
|
||||
},
|
||||
"sourceMapName": {
|
||||
"message": "Use the `sourceMapTarget` option",
|
||||
sourceMapName: {
|
||||
message: "Use the `sourceMapTarget` option",
|
||||
},
|
||||
"stage": {
|
||||
"message": "Check out the corresponding stage-x presets http://babeljs.io/docs/plugins/#presets",
|
||||
stage: {
|
||||
message:
|
||||
"Check out the corresponding stage-x presets http://babeljs.io/docs/plugins/#presets",
|
||||
},
|
||||
"whitelist": {
|
||||
"message": "Put the specific transforms you want in the `plugins` option",
|
||||
whitelist: {
|
||||
message: "Put the specific transforms you want in the `plugins` option",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ export template from "babel-template";
|
||||
|
||||
import loadConfig from "./config";
|
||||
|
||||
export function loadOptions(opts): Object|null {
|
||||
export function loadOptions(opts): Object | null {
|
||||
const config = loadConfig(opts);
|
||||
|
||||
return config ? config.options : null;
|
||||
@@ -41,4 +41,10 @@ export {
|
||||
* Recommended set of compilable extensions. Not used in babel-core directly, but meant as
|
||||
* as an easy source for tooling making use of babel-core.
|
||||
*/
|
||||
export const DEFAULT_EXTENSIONS = Object.freeze([".js", ".jsx", ".es6", ".es"]);
|
||||
export const DEFAULT_EXTENSIONS = Object.freeze([
|
||||
".js",
|
||||
".jsx",
|
||||
".es6",
|
||||
".es",
|
||||
".mjs",
|
||||
]);
|
||||
|
||||
@@ -20,17 +20,29 @@ const buildUmdWrapper = template(`
|
||||
|
||||
function buildGlobal(namespace, builder) {
|
||||
const body = [];
|
||||
const container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
|
||||
const container = t.functionExpression(
|
||||
null,
|
||||
[t.identifier("global")],
|
||||
t.blockStatement(body),
|
||||
);
|
||||
const tree = t.program([
|
||||
t.expressionStatement(t.callExpression(container, [helpers.get("selfGlobal")]))]);
|
||||
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
namespace,
|
||||
t.assignmentExpression("=", t.memberExpression(t.identifier("global"), namespace),
|
||||
t.objectExpression([]))
|
||||
t.expressionStatement(
|
||||
t.callExpression(container, [helpers.get("selfGlobal")]),
|
||||
),
|
||||
]));
|
||||
]);
|
||||
|
||||
body.push(
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
namespace,
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
t.memberExpression(t.identifier("global"), namespace),
|
||||
t.objectExpression([]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
builder(body);
|
||||
|
||||
@@ -39,9 +51,11 @@ function buildGlobal(namespace, builder) {
|
||||
|
||||
function buildUmd(namespace, builder) {
|
||||
const body = [];
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(namespace, t.identifier("global")),
|
||||
]));
|
||||
body.push(
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(namespace, t.identifier("global")),
|
||||
]),
|
||||
);
|
||||
|
||||
builder(body);
|
||||
|
||||
@@ -51,7 +65,7 @@ function buildUmd(namespace, builder) {
|
||||
BROWSER_ARGUMENTS: t.assignmentExpression(
|
||||
"=",
|
||||
t.memberExpression(t.identifier("root"), namespace),
|
||||
t.objectExpression([])
|
||||
t.objectExpression([]),
|
||||
),
|
||||
COMMON_ARGUMENTS: t.identifier("exports"),
|
||||
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
|
||||
@@ -63,31 +77,39 @@ function buildUmd(namespace, builder) {
|
||||
|
||||
function buildVar(namespace, builder) {
|
||||
const body = [];
|
||||
body.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(namespace, t.objectExpression([])),
|
||||
]));
|
||||
body.push(
|
||||
t.variableDeclaration("var", [
|
||||
t.variableDeclarator(namespace, t.objectExpression([])),
|
||||
]),
|
||||
);
|
||||
builder(body);
|
||||
body.push(t.expressionStatement(namespace));
|
||||
return t.program(body);
|
||||
}
|
||||
|
||||
function buildHelpers(body, namespace, whitelist) {
|
||||
helpers.list.forEach(function (name) {
|
||||
helpers.list.forEach(function(name) {
|
||||
if (whitelist && whitelist.indexOf(name) < 0) return;
|
||||
|
||||
const key = t.identifier(name);
|
||||
body.push(t.expressionStatement(
|
||||
t.assignmentExpression("=", t.memberExpression(namespace, key), helpers.get(name))
|
||||
));
|
||||
body.push(
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
"=",
|
||||
t.memberExpression(namespace, key),
|
||||
helpers.get(name),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
export default function (
|
||||
export default function(
|
||||
whitelist?: Array<string>,
|
||||
outputType: "global" | "umd" | "var" = "global",
|
||||
) {
|
||||
const namespace = t.identifier("babelHelpers");
|
||||
|
||||
const builder = function (body) {
|
||||
const builder = function(body) {
|
||||
return buildHelpers(body, namespace, whitelist);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import PluginPass from "../plugin-pass";
|
||||
import { NodePath, Hub, Scope } from "babel-traverse";
|
||||
import sourceMap from "source-map";
|
||||
import generate from "babel-generator";
|
||||
import codeFrame from "babel-code-frame";
|
||||
import { codeFrameColumns } from "babel-code-frame";
|
||||
import traverse from "babel-traverse";
|
||||
import Store from "../store";
|
||||
import { parse } from "babylon";
|
||||
@@ -17,7 +17,6 @@ import buildDebug from "debug";
|
||||
import loadConfig, { type ResolvedConfig } from "../../config";
|
||||
|
||||
import blockHoistPlugin from "../internal-plugins/block-hoist";
|
||||
import shadowFunctionsPlugin from "../internal-plugins/shadow-functions";
|
||||
|
||||
const babelDebug = buildDebug("babel:file");
|
||||
|
||||
@@ -42,11 +41,11 @@ const errorVisitor = {
|
||||
export default class File extends Store {
|
||||
constructor({ options, passes }: ResolvedConfig) {
|
||||
if (!INTERNAL_PLUGINS) {
|
||||
// Lazy-init the internal plugins to remove the init-time circular dependency between plugins being
|
||||
// Lazy-init the internal plugin to remove the init-time circular dependency between plugins being
|
||||
// passed babel-core's export object, which loads this file, and this 'loadConfig' loading plugins.
|
||||
INTERNAL_PLUGINS = loadConfig({
|
||||
babelrc: false,
|
||||
plugins: [ blockHoistPlugin, shadowFunctionsPlugin ],
|
||||
plugins: [blockHoistPlugin],
|
||||
}).passes[0];
|
||||
}
|
||||
|
||||
@@ -62,7 +61,7 @@ export default class File extends Store {
|
||||
};
|
||||
|
||||
for (const pluginPairs of passes) {
|
||||
for (const [ plugin ] of pluginPairs) {
|
||||
for (const [plugin] of pluginPairs) {
|
||||
if (plugin.manipulateOptions) {
|
||||
plugin.manipulateOptions(this.opts, this.parserOpts, this);
|
||||
}
|
||||
@@ -151,7 +150,7 @@ export default class File extends Store {
|
||||
|
||||
if (opts.sourceRoot != null) {
|
||||
// remove sourceRoot from filename
|
||||
const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
|
||||
const sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "/?");
|
||||
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
|
||||
}
|
||||
|
||||
@@ -173,17 +172,40 @@ export default class File extends Store {
|
||||
|
||||
resolveModuleSource(source: string): string {
|
||||
const resolveModuleSource = this.opts.resolveModuleSource;
|
||||
if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename);
|
||||
if (resolveModuleSource) {
|
||||
source = resolveModuleSource(source, this.opts.filename);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
addImport(source: string, imported: string, name?: string = imported): Object {
|
||||
addImport(
|
||||
source: string,
|
||||
imported?: string = "",
|
||||
name?: string = imported,
|
||||
): Object | null {
|
||||
const prependDeclaration = (
|
||||
specifiers: Array<BabelNodeImportSpecifier>,
|
||||
): void => {
|
||||
const declar = t.importDeclaration(specifiers, t.stringLiteral(source));
|
||||
declar._blockHoist = 3;
|
||||
|
||||
this.path.unshiftContainer("body", declar);
|
||||
};
|
||||
|
||||
// import "module-name";
|
||||
if (!imported) {
|
||||
prependDeclaration([]);
|
||||
return null;
|
||||
}
|
||||
|
||||
const alias = `${source}:${imported}`;
|
||||
let id = this.dynamicImportIds[alias];
|
||||
|
||||
if (!id) {
|
||||
source = this.resolveModuleSource(source);
|
||||
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(name);
|
||||
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(
|
||||
name,
|
||||
);
|
||||
|
||||
const specifiers = [];
|
||||
|
||||
@@ -195,10 +217,7 @@ export default class File extends Store {
|
||||
specifiers.push(t.importSpecifier(id, t.identifier(imported)));
|
||||
}
|
||||
|
||||
const declar = t.importDeclaration(specifiers, t.stringLiteral(source));
|
||||
declar._blockHoist = 3;
|
||||
|
||||
this.path.unshiftContainer("body", declar);
|
||||
prependDeclaration(specifiers);
|
||||
}
|
||||
|
||||
return id;
|
||||
@@ -223,11 +242,12 @@ export default class File extends Store {
|
||||
}
|
||||
|
||||
const ref = getHelper(name);
|
||||
const uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
|
||||
const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
|
||||
name,
|
||||
));
|
||||
|
||||
if (t.isFunctionExpression(ref) && !ref.id) {
|
||||
ref.body._compact = true;
|
||||
ref._generated = true;
|
||||
ref.id = uid;
|
||||
ref.type = "FunctionDeclaration";
|
||||
this.path.unshiftContainer("body", ref);
|
||||
@@ -258,7 +278,9 @@ export default class File extends Store {
|
||||
const declar = this.declarations[name];
|
||||
if (declar) return declar;
|
||||
|
||||
const uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject");
|
||||
const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
|
||||
"templateObject",
|
||||
));
|
||||
|
||||
const helperId = this.addHelper(helperName);
|
||||
const init = t.callExpression(helperId, [strings, raw]);
|
||||
@@ -271,7 +293,11 @@ export default class File extends Store {
|
||||
return uid;
|
||||
}
|
||||
|
||||
buildCodeFrameError(node: Object, msg: string, Error: typeof Error = SyntaxError): Error {
|
||||
buildCodeFrameError(
|
||||
node: Object,
|
||||
msg: string,
|
||||
Error: typeof Error = SyntaxError,
|
||||
): Error {
|
||||
const loc = node && (node.loc || node._loc);
|
||||
|
||||
const err = new Error(msg);
|
||||
@@ -281,7 +307,8 @@ export default class File extends Store {
|
||||
} else {
|
||||
traverse(node, errorVisitor, this.scope, err);
|
||||
|
||||
err.message += " (This is an error on an internal node. Probably an internal error";
|
||||
err.message +=
|
||||
" (This is an error on an internal node. Probably an internal error";
|
||||
|
||||
if (err.loc) {
|
||||
err.message += ". Location has been estimated.";
|
||||
@@ -309,7 +336,7 @@ export default class File extends Store {
|
||||
// single source file to a single output file.
|
||||
const source = outputMapConsumer.sources[0];
|
||||
|
||||
inputMapConsumer.eachMapping(function (mapping) {
|
||||
inputMapConsumer.eachMapping(function(mapping) {
|
||||
const generatedPosition = outputMapConsumer.generatedPositionFor({
|
||||
line: mapping.generatedLine,
|
||||
column: mapping.generatedColumn,
|
||||
@@ -319,10 +346,13 @@ export default class File extends Store {
|
||||
mergedGenerator.addMapping({
|
||||
source: mapping.source,
|
||||
|
||||
original: mapping.source == null ? null : {
|
||||
line: mapping.originalLine,
|
||||
column: mapping.originalColumn,
|
||||
},
|
||||
original:
|
||||
mapping.source == null
|
||||
? null
|
||||
: {
|
||||
line: mapping.originalLine,
|
||||
column: mapping.originalColumn,
|
||||
},
|
||||
|
||||
generated: generatedPosition,
|
||||
});
|
||||
@@ -386,15 +416,15 @@ export default class File extends Store {
|
||||
const passes = [];
|
||||
const visitors = [];
|
||||
|
||||
for (const [ plugin, pluginOpts ] of pluginPairs.concat(INTERNAL_PLUGINS)) {
|
||||
for (const [plugin, pluginOpts] of pluginPairs.concat(INTERNAL_PLUGINS)) {
|
||||
const pass = new PluginPass(this, plugin.key, pluginOpts);
|
||||
|
||||
passPairs.push([ plugin, pass ]);
|
||||
passPairs.push([plugin, pass]);
|
||||
passes.push(pass);
|
||||
visitors.push(plugin.visitor);
|
||||
}
|
||||
|
||||
for (const [ plugin, pass ] of passPairs) {
|
||||
for (const [plugin, pass] of passPairs) {
|
||||
const fn = plugin.pre;
|
||||
if (fn) fn.call(pass, this);
|
||||
}
|
||||
@@ -402,16 +432,19 @@ export default class File extends Store {
|
||||
debug(this.opts, "Start transform traverse");
|
||||
|
||||
// merge all plugin visitors into a single visitor
|
||||
const visitor = traverse.visitors.merge(visitors, passes, this.opts.wrapPluginVisitorMethod);
|
||||
const visitor = traverse.visitors.merge(
|
||||
visitors,
|
||||
passes,
|
||||
this.opts.wrapPluginVisitorMethod,
|
||||
);
|
||||
traverse(this.ast, visitor, this.scope);
|
||||
|
||||
debug(this.opts, "End transform traverse");
|
||||
|
||||
for (const [ plugin, pass ] of passPairs) {
|
||||
for (const [plugin, pass] of passPairs) {
|
||||
const fn = plugin.post;
|
||||
if (fn) fn.call(pass, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this.generate();
|
||||
@@ -429,11 +462,17 @@ export default class File extends Store {
|
||||
err._babel = true;
|
||||
}
|
||||
|
||||
let message = err.message = `${this.opts.filename}: ${err.message}`;
|
||||
let message = (err.message = `${this.opts.filename}: ${err.message}`);
|
||||
|
||||
const loc = err.loc;
|
||||
if (loc) {
|
||||
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, this.opts);
|
||||
const location = {
|
||||
start: {
|
||||
line: loc.line,
|
||||
column: loc.column + 1,
|
||||
},
|
||||
};
|
||||
err.codeFrame = codeFrameColumns(code, location, this.opts);
|
||||
message += "\n" + err.codeFrame;
|
||||
}
|
||||
|
||||
@@ -525,8 +564,11 @@ export default class File extends Store {
|
||||
|
||||
debug(this.opts, "Generation start");
|
||||
|
||||
const _result = gen(ast, opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
|
||||
this.code);
|
||||
const _result = gen(
|
||||
ast,
|
||||
opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
|
||||
this.code,
|
||||
);
|
||||
result.code = _result.code;
|
||||
result.map = _result.map;
|
||||
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
import * as t from "babel-types";
|
||||
|
||||
const SUPER_THIS_BOUND = Symbol("super this bound");
|
||||
|
||||
const superVisitor = {
|
||||
CallExpression(path) {
|
||||
if (!path.get("callee").isSuper()) return;
|
||||
|
||||
const { node } = path;
|
||||
if (node[SUPER_THIS_BOUND]) return;
|
||||
node[SUPER_THIS_BOUND] = true;
|
||||
|
||||
path.replaceWith(t.assignmentExpression("=", this.id, node));
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "internal.shadowFunctions",
|
||||
|
||||
visitor: {
|
||||
ThisExpression(path) {
|
||||
remap(path, "this");
|
||||
},
|
||||
|
||||
ReferencedIdentifier(path) {
|
||||
if (path.node.name === "arguments") {
|
||||
remap(path, "arguments");
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function shouldShadow(path, shadowPath) {
|
||||
if (path.is("_forceShadow")) {
|
||||
return true;
|
||||
} else {
|
||||
return shadowPath;
|
||||
}
|
||||
}
|
||||
|
||||
function remap(path, key) {
|
||||
// ensure that we're shadowed
|
||||
const shadowPath = path.inShadow(key);
|
||||
if (!shouldShadow(path, shadowPath)) return;
|
||||
|
||||
const shadowFunction = path.node._shadowedFunctionLiteral;
|
||||
|
||||
let currentFunction;
|
||||
let passedShadowFunction = false;
|
||||
|
||||
let fnPath = path.find(function (innerPath) {
|
||||
if (innerPath.parentPath && innerPath.parentPath.isClassProperty() && innerPath.key === "value") {
|
||||
return true;
|
||||
}
|
||||
if (path === innerPath) return false;
|
||||
if (innerPath.isProgram() || innerPath.isFunction()) {
|
||||
// catch current function in case this is the shadowed one and we can ignore it
|
||||
currentFunction = currentFunction || innerPath;
|
||||
}
|
||||
|
||||
if (innerPath.isProgram()) {
|
||||
passedShadowFunction = true;
|
||||
|
||||
return true;
|
||||
} else if (innerPath.isFunction() && !innerPath.isArrowFunctionExpression()) {
|
||||
if (shadowFunction) {
|
||||
if (innerPath === shadowFunction || innerPath.node === shadowFunction.node) return true;
|
||||
} else {
|
||||
if (!innerPath.is("shadow")) return true;
|
||||
}
|
||||
|
||||
passedShadowFunction = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (shadowFunction && fnPath.isProgram() && !shadowFunction.isProgram()) {
|
||||
// If the shadow wasn't found, take the closest function as a backup.
|
||||
// This is a bit of a hack, but it will allow the parameter transforms to work properly
|
||||
// without introducing yet another shadow-controlling flag.
|
||||
fnPath = path.findParent((p) => p.isProgram() || p.isFunction());
|
||||
}
|
||||
|
||||
// no point in realiasing if we're in this function
|
||||
if (fnPath === currentFunction) return;
|
||||
|
||||
// If the only functions that were encountered are arrow functions, skip remapping the
|
||||
// binding since arrow function syntax already does that.
|
||||
if (!passedShadowFunction) return;
|
||||
|
||||
const cached = fnPath.getData(key);
|
||||
if (cached) return path.replaceWith(cached);
|
||||
|
||||
const id = path.scope.generateUidIdentifier(key);
|
||||
|
||||
fnPath.setData(key, id);
|
||||
|
||||
const classPath = fnPath.findParent((p) => p.isClass());
|
||||
const hasSuperClass = !!(classPath && classPath.node && classPath.node.superClass);
|
||||
|
||||
if (key === "this" && fnPath.isMethod({ kind: "constructor" }) && hasSuperClass) {
|
||||
fnPath.scope.push({ id });
|
||||
|
||||
fnPath.traverse(superVisitor, { id });
|
||||
} else {
|
||||
const init = key === "this" ? t.thisExpression() : t.identifier(key);
|
||||
|
||||
// Forward the shadowed function, so that the identifiers do not get hoisted
|
||||
// up to the first non shadow function but rather up to the bound shadow function
|
||||
if (shadowFunction) init._shadowedFunctionLiteral = shadowFunction;
|
||||
|
||||
fnPath.scope.push({ id, init });
|
||||
}
|
||||
|
||||
return path.replaceWith(id);
|
||||
}
|
||||
@@ -5,7 +5,11 @@ import * as t from "babel-types";
|
||||
import File from "./file";
|
||||
import loadConfig from "../config";
|
||||
|
||||
export function analyse(code: string, opts: Object = {}, visitor?: Object): ?BabelFileMetadata {
|
||||
export function analyse(
|
||||
code: string,
|
||||
opts: Object = {},
|
||||
visitor?: Object,
|
||||
): ?BabelFileMetadata {
|
||||
opts.code = false;
|
||||
if (visitor) {
|
||||
opts.plugins = opts.plugins || [];
|
||||
@@ -19,14 +23,18 @@ export function transform(code: string, opts?: Object): BabelFileResult {
|
||||
if (config === null) return null;
|
||||
|
||||
const file = new File(config);
|
||||
return file.wrap(code, function () {
|
||||
return file.wrap(code, function() {
|
||||
file.addCode(code);
|
||||
file.parseCode(code);
|
||||
return file.transform();
|
||||
});
|
||||
}
|
||||
|
||||
export function transformFromAst(ast: Object, code: string, opts: Object): BabelFileResult {
|
||||
export function transformFromAst(
|
||||
ast: Object,
|
||||
code: string,
|
||||
opts: Object,
|
||||
): BabelFileResult {
|
||||
const config = loadConfig(opts);
|
||||
if (config === null) return null;
|
||||
|
||||
@@ -37,14 +45,18 @@ export function transformFromAst(ast: Object, code: string, opts: Object): Babel
|
||||
}
|
||||
|
||||
const file = new File(config);
|
||||
return file.wrap(code, function () {
|
||||
return file.wrap(code, function() {
|
||||
file.addCode(code);
|
||||
file.addAst(ast);
|
||||
return file.transform();
|
||||
});
|
||||
}
|
||||
|
||||
export function transformFile(filename: string, opts?: Object, callback: Function) {
|
||||
export function transformFile(
|
||||
filename: string,
|
||||
opts?: Object,
|
||||
callback: Function,
|
||||
) {
|
||||
if (typeof opts === "function") {
|
||||
callback = opts;
|
||||
opts = {};
|
||||
@@ -54,13 +66,13 @@ export function transformFile(filename: string, opts?: Object, callback: Functio
|
||||
const config = loadConfig(opts);
|
||||
if (config === null) return callback(null, null);
|
||||
|
||||
fs.readFile(filename, function (err, code) {
|
||||
fs.readFile(filename, function(err, code) {
|
||||
let result;
|
||||
|
||||
if (!err) {
|
||||
try {
|
||||
const file = new File(config);
|
||||
result = file.wrap(code, function () {
|
||||
result = file.wrap(code, function() {
|
||||
file.addCode(code);
|
||||
file.parseCode(code);
|
||||
return file.transform();
|
||||
@@ -78,7 +90,10 @@ export function transformFile(filename: string, opts?: Object, callback: Functio
|
||||
});
|
||||
}
|
||||
|
||||
export function transformFileSync(filename: string, opts?: Object = {}): string {
|
||||
export function transformFileSync(
|
||||
filename: string,
|
||||
opts?: Object = {},
|
||||
): string {
|
||||
opts.filename = filename;
|
||||
const config = loadConfig(opts);
|
||||
if (config === null) return null;
|
||||
@@ -86,7 +101,7 @@ export function transformFileSync(filename: string, opts?: Object = {}): string
|
||||
const code = fs.readFileSync(filename, "utf8");
|
||||
const file = new File(config);
|
||||
|
||||
return file.wrap(code, function () {
|
||||
return file.wrap(code, function() {
|
||||
file.addCode(code);
|
||||
file.parseCode(code);
|
||||
return file.transform();
|
||||
|
||||
@@ -17,7 +17,7 @@ function assertNotIgnored(result) {
|
||||
// shim
|
||||
function transformAsync(code, opts) {
|
||||
return {
|
||||
then: function (resolve) {
|
||||
then: function(resolve) {
|
||||
resolve(babel.transform(code, opts));
|
||||
},
|
||||
};
|
||||
@@ -55,11 +55,14 @@ describe("parser and generator options", function() {
|
||||
it("experimental syntax", function() {
|
||||
const experimental = "var a: number = 1;";
|
||||
|
||||
assert.deepEqual(newTransform(experimental).ast, babel.transform(experimental, {
|
||||
parserOpts: {
|
||||
plugins: ["flow"],
|
||||
},
|
||||
}).ast);
|
||||
assert.deepEqual(
|
||||
newTransform(experimental).ast,
|
||||
babel.transform(experimental, {
|
||||
parserOpts: {
|
||||
plugins: ["flow"],
|
||||
},
|
||||
}).ast,
|
||||
);
|
||||
assert.equal(newTransform(experimental).code, experimental);
|
||||
|
||||
function newTransformWithPlugins(string) {
|
||||
@@ -74,124 +77,158 @@ describe("parser and generator options", function() {
|
||||
});
|
||||
}
|
||||
|
||||
assert.deepEqual(newTransformWithPlugins(experimental).ast, babel.transform(experimental, {
|
||||
parserOpts: {
|
||||
plugins: ["flow"],
|
||||
},
|
||||
}).ast);
|
||||
assert.deepEqual(
|
||||
newTransformWithPlugins(experimental).ast,
|
||||
babel.transform(experimental, {
|
||||
parserOpts: {
|
||||
plugins: ["flow"],
|
||||
},
|
||||
}).ast,
|
||||
);
|
||||
assert.equal(newTransformWithPlugins(experimental).code, experimental);
|
||||
});
|
||||
|
||||
it("other options", function() {
|
||||
const experimental = "if (true) {\n import a from 'a';\n}";
|
||||
|
||||
assert.notEqual(newTransform(experimental).ast, babel.transform(experimental, {
|
||||
parserOpts: {
|
||||
allowImportExportEverywhere: true,
|
||||
},
|
||||
}).ast);
|
||||
assert.notEqual(
|
||||
newTransform(experimental).ast,
|
||||
babel.transform(experimental, {
|
||||
parserOpts: {
|
||||
allowImportExportEverywhere: true,
|
||||
},
|
||||
}).ast,
|
||||
);
|
||||
assert.equal(newTransform(experimental).code, experimental);
|
||||
});
|
||||
});
|
||||
|
||||
describe("api", function () {
|
||||
it("analyze", function () {
|
||||
describe("api", function() {
|
||||
it("analyze", function() {
|
||||
assert.equal(babel.analyse("foobar;").marked.length, 0);
|
||||
|
||||
assert.equal(babel.analyse("foobar;", {
|
||||
plugins: [new Plugin({
|
||||
visitor: {
|
||||
Program: function (path) {
|
||||
assert.equal(
|
||||
babel.analyse("foobar;", {
|
||||
plugins: [
|
||||
new Plugin({
|
||||
visitor: {
|
||||
Program: function(path) {
|
||||
path.mark("category", "foobar");
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
}).marked[0].message,
|
||||
"foobar",
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
babel.analyse(
|
||||
"foobar;",
|
||||
{},
|
||||
{
|
||||
Program: function(path) {
|
||||
path.mark("category", "foobar");
|
||||
},
|
||||
},
|
||||
})],
|
||||
}).marked[0].message, "foobar");
|
||||
|
||||
assert.equal(babel.analyse("foobar;", {}, {
|
||||
Program: function (path) {
|
||||
path.mark("category", "foobar");
|
||||
},
|
||||
}).marked[0].message, "foobar");
|
||||
});
|
||||
|
||||
it("exposes the resolvePlugin method", function() {
|
||||
assert.equal(babel.resolvePlugin("nonexistent-plugin"), null);
|
||||
});
|
||||
|
||||
it("exposes the resolvePreset method", function() {
|
||||
assert.equal(babel.resolvePreset("nonexistent-preset"), null);
|
||||
});
|
||||
|
||||
it("transformFile", function (done) {
|
||||
babel.transformFile(__dirname + "/fixtures/api/file.js", {
|
||||
babelrc: false,
|
||||
}, function (err, res) {
|
||||
if (err) return done(err);
|
||||
assert.equal(res.code, "foo();");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("transformFileSync", function () {
|
||||
assert.equal(babel.transformFileSync(__dirname + "/fixtures/api/file.js", {
|
||||
babelrc: false,
|
||||
}).code, "foo();");
|
||||
});
|
||||
|
||||
it("options throw on falsy true", function () {
|
||||
return assert.throws(
|
||||
function () {
|
||||
babel.transform("", {
|
||||
plugins: [__dirname + "/../../babel-plugin-syntax-jsx", false],
|
||||
});
|
||||
},
|
||||
/TypeError: \[BABEL\] unknown: Falsy value found in plugins/
|
||||
).marked[0].message,
|
||||
"foobar",
|
||||
);
|
||||
});
|
||||
|
||||
it("options merge backwards", function () {
|
||||
it("exposes the resolvePlugin method", function() {
|
||||
assert.throws(
|
||||
() => babel.resolvePlugin("nonexistent-plugin"),
|
||||
/Cannot find module 'babel-plugin-nonexistent-plugin'/,
|
||||
);
|
||||
});
|
||||
|
||||
it("exposes the resolvePreset method", function() {
|
||||
assert.throws(
|
||||
() => babel.resolvePreset("nonexistent-preset"),
|
||||
/Cannot find module 'babel-preset-nonexistent-preset'/,
|
||||
);
|
||||
});
|
||||
|
||||
it("transformFile", function(done) {
|
||||
babel.transformFile(
|
||||
__dirname + "/fixtures/api/file.js",
|
||||
{
|
||||
babelrc: false,
|
||||
},
|
||||
function(err, res) {
|
||||
if (err) return done(err);
|
||||
assert.equal(res.code, "foo();");
|
||||
done();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("transformFileSync", function() {
|
||||
assert.equal(
|
||||
babel.transformFileSync(__dirname + "/fixtures/api/file.js", {
|
||||
babelrc: false,
|
||||
}).code,
|
||||
"foo();",
|
||||
);
|
||||
});
|
||||
|
||||
it("options throw on falsy true", function() {
|
||||
return assert.throws(function() {
|
||||
babel.transform("", {
|
||||
plugins: [__dirname + "/../../babel-plugin-syntax-jsx", false],
|
||||
});
|
||||
}, /Error: \[BABEL\] unknown: Unexpected falsy value: false/);
|
||||
});
|
||||
|
||||
it("options merge backwards", function() {
|
||||
return transformAsync("", {
|
||||
presets: [__dirname + "/../../babel-preset-es2015"],
|
||||
plugins: [__dirname + "/../../babel-plugin-syntax-jsx"],
|
||||
}).then(function (result) {
|
||||
assert.ok(result.options.plugins[0][0].manipulateOptions.toString().indexOf("jsx") >= 0);
|
||||
}).then(function(result) {
|
||||
assert.ok(
|
||||
result.options.plugins[0][0].manipulateOptions
|
||||
.toString()
|
||||
.indexOf("jsx") >= 0,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("option wrapPluginVisitorMethod", function () {
|
||||
it("option wrapPluginVisitorMethod", function() {
|
||||
let calledRaw = 0;
|
||||
let calledIntercept = 0;
|
||||
|
||||
babel.transform("function foo() { bar(foobar); }", {
|
||||
wrapPluginVisitorMethod: function (pluginAlias, visitorType, callback) {
|
||||
wrapPluginVisitorMethod: function(pluginAlias, visitorType, callback) {
|
||||
if (pluginAlias !== "foobar") {
|
||||
return callback;
|
||||
}
|
||||
|
||||
assert.equal(visitorType, "enter");
|
||||
|
||||
return function () {
|
||||
return function() {
|
||||
calledIntercept++;
|
||||
return callback.apply(this, arguments);
|
||||
};
|
||||
},
|
||||
|
||||
plugins: [new Plugin({
|
||||
name: "foobar",
|
||||
visitor: {
|
||||
"Program|Identifier": function () {
|
||||
calledRaw++;
|
||||
plugins: [
|
||||
new Plugin({
|
||||
name: "foobar",
|
||||
visitor: {
|
||||
"Program|Identifier": function() {
|
||||
calledRaw++;
|
||||
},
|
||||
},
|
||||
},
|
||||
})],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
assert.equal(calledRaw, 4);
|
||||
assert.equal(calledIntercept, 4);
|
||||
});
|
||||
|
||||
it("pass per preset", function () {
|
||||
it("pass per preset", function() {
|
||||
let aliasBaseType = null;
|
||||
|
||||
function execTest(passPerPreset) {
|
||||
@@ -199,13 +236,15 @@ describe("api", function () {
|
||||
passPerPreset: passPerPreset,
|
||||
presets: [
|
||||
// First preset with our plugin, "before"
|
||||
function () {
|
||||
function() {
|
||||
return {
|
||||
plugins: [
|
||||
new Plugin({
|
||||
visitor: {
|
||||
Function: function (path) {
|
||||
const alias = path.scope.getProgramParent().path.get("body")[0].node;
|
||||
Function: function(path) {
|
||||
const alias = path.scope
|
||||
.getProgramParent()
|
||||
.path.get("body")[0].node;
|
||||
if (!babel.types.isTypeAlias(alias)) return;
|
||||
|
||||
// In case of `passPerPreset` being `false`, the
|
||||
@@ -228,11 +267,12 @@ describe("api", function () {
|
||||
require(__dirname + "/../../babel-preset-es2015"),
|
||||
|
||||
// Third preset for Flow.
|
||||
function () {
|
||||
function() {
|
||||
return {
|
||||
plugins: [
|
||||
require(__dirname + "/../../babel-plugin-syntax-flow"),
|
||||
require(__dirname + "/../../babel-plugin-transform-flow-strip-types"),
|
||||
require(__dirname +
|
||||
"/../../babel-plugin-transform-flow-strip-types"),
|
||||
],
|
||||
};
|
||||
},
|
||||
@@ -246,13 +286,16 @@ describe("api", function () {
|
||||
|
||||
assert.equal(aliasBaseType, "NumberTypeAnnotation");
|
||||
|
||||
assert.deepEqual([
|
||||
"\"use strict\";",
|
||||
"",
|
||||
"var x = function x(y) {",
|
||||
" return y;",
|
||||
"};",
|
||||
].join("\n"), result.code);
|
||||
assert.deepEqual(
|
||||
[
|
||||
'"use strict";',
|
||||
"",
|
||||
"var x = function x(y) {",
|
||||
" return y;",
|
||||
"};",
|
||||
].join("\n"),
|
||||
result.code,
|
||||
);
|
||||
|
||||
// 2. passPerPreset: false
|
||||
|
||||
@@ -262,14 +305,16 @@ describe("api", function () {
|
||||
|
||||
assert.equal(aliasBaseType, null);
|
||||
|
||||
assert.deepEqual([
|
||||
"\"use strict\";",
|
||||
"",
|
||||
"var x = function x(y) {",
|
||||
" return y;",
|
||||
"};",
|
||||
].join("\n"), result.code);
|
||||
|
||||
assert.deepEqual(
|
||||
[
|
||||
'"use strict";',
|
||||
"",
|
||||
"var x = function x(y) {",
|
||||
" return y;",
|
||||
"};",
|
||||
].join("\n"),
|
||||
result.code,
|
||||
);
|
||||
});
|
||||
|
||||
it("complex plugin and preset ordering", function() {
|
||||
@@ -277,7 +322,10 @@ describe("api", function () {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", babel.types.expressionStatement(babel.types.identifier(str)));
|
||||
path.pushContainer(
|
||||
"body",
|
||||
babel.types.expressionStatement(babel.types.identifier(str)),
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -288,288 +336,345 @@ describe("api", function () {
|
||||
}
|
||||
|
||||
const result = babel.transform("", {
|
||||
filename: path.join(__dirname, "fixtures", "config", "complex-plugin-config", "file.js"),
|
||||
presets: [
|
||||
pushPreset("argone"),
|
||||
pushPreset("argtwo"),
|
||||
],
|
||||
filename: path.join(
|
||||
__dirname,
|
||||
"fixtures",
|
||||
"config",
|
||||
"complex-plugin-config",
|
||||
"file.js",
|
||||
),
|
||||
presets: [pushPreset("argone"), pushPreset("argtwo")],
|
||||
env: {
|
||||
development: {
|
||||
passPerPreset: true,
|
||||
presets: [
|
||||
pushPreset("argthree"),
|
||||
pushPreset("argfour"),
|
||||
],
|
||||
presets: [pushPreset("argthree"), pushPreset("argfour")],
|
||||
env: {
|
||||
development: {
|
||||
passPerPreset: true,
|
||||
presets: [
|
||||
pushPreset("argfive"),
|
||||
pushPreset("argsix"),
|
||||
],
|
||||
presets: [pushPreset("argfive"), pushPreset("argsix")],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.code, [
|
||||
"argtwo;",
|
||||
"argone;",
|
||||
"eleven;",
|
||||
"twelve;",
|
||||
"one;",
|
||||
"two;",
|
||||
"five;",
|
||||
"six;",
|
||||
"three;",
|
||||
"four;",
|
||||
"seventeen;",
|
||||
"eighteen;",
|
||||
"nineteen;",
|
||||
"twenty;",
|
||||
"thirteen;",
|
||||
"fourteen;",
|
||||
"fifteen;",
|
||||
"sixteen;",
|
||||
"argfive;",
|
||||
"argsix;",
|
||||
"argthree;",
|
||||
"argfour;",
|
||||
"seven;",
|
||||
"eight;",
|
||||
"nine;",
|
||||
"ten;",
|
||||
].join("\n"));
|
||||
assert.equal(
|
||||
result.code,
|
||||
[
|
||||
"argtwo;",
|
||||
"argone;",
|
||||
"eleven;",
|
||||
"twelve;",
|
||||
"one;",
|
||||
"two;",
|
||||
"five;",
|
||||
"six;",
|
||||
"three;",
|
||||
"four;",
|
||||
"seventeen;",
|
||||
"eighteen;",
|
||||
"nineteen;",
|
||||
"twenty;",
|
||||
"thirteen;",
|
||||
"fourteen;",
|
||||
"fifteen;",
|
||||
"sixteen;",
|
||||
"argfive;",
|
||||
"argsix;",
|
||||
"argthree;",
|
||||
"argfour;",
|
||||
"seven;",
|
||||
"eight;",
|
||||
"nine;",
|
||||
"ten;",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
|
||||
it("source map merging", function () {
|
||||
const result = babel.transform([
|
||||
/* eslint-disable max-len */
|
||||
"function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }",
|
||||
"",
|
||||
"let Foo = function Foo() {",
|
||||
" _classCallCheck(this, Foo);",
|
||||
"};",
|
||||
"",
|
||||
"//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZG91dCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztJQUFNLEdBQUcsWUFBSCxHQUFHO3dCQUFILEdBQUciLCJmaWxlIjoidW5kZWZpbmVkIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgRm9vIHt9XG4iXX0=",
|
||||
/* eslint-enable max-len */
|
||||
].join("\n"), {
|
||||
sourceMap: true,
|
||||
});
|
||||
it("source map merging", function() {
|
||||
const result = babel.transform(
|
||||
[
|
||||
/* eslint-disable max-len */
|
||||
'function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }',
|
||||
"",
|
||||
"let Foo = function Foo() {",
|
||||
" _classCallCheck(this, Foo);",
|
||||
"};",
|
||||
"",
|
||||
"//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZG91dCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztJQUFNLEdBQUcsWUFBSCxHQUFHO3dCQUFILEdBQUciLCJmaWxlIjoidW5kZWZpbmVkIiwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgRm9vIHt9XG4iXX0=",
|
||||
/* eslint-enable max-len */
|
||||
].join("\n"),
|
||||
{
|
||||
sourceMap: true,
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual([
|
||||
"function _classCallCheck(instance, Constructor) {",
|
||||
" if (!(instance instanceof Constructor)) {",
|
||||
" throw new TypeError(\"Cannot call a class as a function\");",
|
||||
" }",
|
||||
"}",
|
||||
"",
|
||||
"let Foo = function Foo() {",
|
||||
" _classCallCheck(this, Foo);",
|
||||
"};",
|
||||
].join("\n"), result.code);
|
||||
assert.deepEqual(
|
||||
[
|
||||
"function _classCallCheck(instance, Constructor) {",
|
||||
" if (!(instance instanceof Constructor)) {",
|
||||
' throw new TypeError("Cannot call a class as a function");',
|
||||
" }",
|
||||
"}",
|
||||
"",
|
||||
"let Foo = function Foo() {",
|
||||
" _classCallCheck(this, Foo);",
|
||||
"};",
|
||||
].join("\n"),
|
||||
result.code,
|
||||
);
|
||||
|
||||
const consumer = new sourceMap.SourceMapConsumer(result.map);
|
||||
|
||||
assert.deepEqual(consumer.originalPositionFor({
|
||||
line: 7,
|
||||
column: 4,
|
||||
}), {
|
||||
name: null,
|
||||
source: "stdout",
|
||||
line: 1,
|
||||
column: 6,
|
||||
});
|
||||
assert.deepEqual(
|
||||
consumer.originalPositionFor({
|
||||
line: 7,
|
||||
column: 4,
|
||||
}),
|
||||
{
|
||||
name: null,
|
||||
source: "stdout",
|
||||
line: 1,
|
||||
column: 6,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("code option false", function () {
|
||||
return transformAsync("foo('bar');", { code: false }).then(function (result) {
|
||||
it("code option false", function() {
|
||||
return transformAsync("foo('bar');", { code: false }).then(function(
|
||||
result,
|
||||
) {
|
||||
assert.ok(!result.code);
|
||||
});
|
||||
});
|
||||
|
||||
it("ast option false", function () {
|
||||
return transformAsync("foo('bar');", { ast: false }).then(function (result) {
|
||||
it("ast option false", function() {
|
||||
return transformAsync("foo('bar');", { ast: false }).then(function(result) {
|
||||
assert.ok(!result.ast);
|
||||
});
|
||||
});
|
||||
|
||||
it("auxiliaryComment option", function () {
|
||||
it("auxiliaryComment option", function() {
|
||||
return transformAsync("class Foo {}", {
|
||||
auxiliaryCommentBefore: "before",
|
||||
auxiliaryCommentAfter: "after",
|
||||
plugins: [function (babel) {
|
||||
const t = babel.types;
|
||||
return {
|
||||
visitor: {
|
||||
Program: function (path) {
|
||||
path.unshiftContainer("body", t.expressionStatement(t.identifier("start")));
|
||||
path.pushContainer("body", t.expressionStatement(t.identifier("end")));
|
||||
plugins: [
|
||||
function(babel) {
|
||||
const t = babel.types;
|
||||
return {
|
||||
visitor: {
|
||||
Program: function(path) {
|
||||
path.unshiftContainer(
|
||||
"body",
|
||||
t.expressionStatement(t.identifier("start")),
|
||||
);
|
||||
path.pushContainer(
|
||||
"body",
|
||||
t.expressionStatement(t.identifier("end")),
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}],
|
||||
}).then(function (result) {
|
||||
assert.equal(result.code,
|
||||
"/*before*/start;\n/*after*/class Foo {}\n/*before*/end;\n/*after*/");
|
||||
};
|
||||
},
|
||||
],
|
||||
}).then(function(result) {
|
||||
assert.equal(
|
||||
result.code,
|
||||
"/*before*/\nstart;\n\n/*after*/\nclass Foo {}\n\n/*before*/\nend;\n\n/*after*/",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("modules metadata", function () {
|
||||
it("modules metadata", function() {
|
||||
return Promise.all([
|
||||
// eslint-disable-next-line max-len
|
||||
transformAsync("import { externalName as localName } from \"external\";").then(function (result) {
|
||||
transformAsync(
|
||||
'import { externalName as localName } from "external";',
|
||||
).then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.imports[0], {
|
||||
source: "external",
|
||||
imported: ["externalName"],
|
||||
specifiers: [{
|
||||
kind: "named",
|
||||
imported: "externalName",
|
||||
local: "localName",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "named",
|
||||
imported: "externalName",
|
||||
local: "localName",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("import * as localName2 from \"external\";").then(function (result) {
|
||||
transformAsync('import * as localName2 from "external";').then(function(
|
||||
result,
|
||||
) {
|
||||
assert.deepEqual(result.metadata.modules.imports[0], {
|
||||
source: "external",
|
||||
imported: ["*"],
|
||||
specifiers: [{
|
||||
kind: "namespace",
|
||||
local: "localName2",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "namespace",
|
||||
local: "localName2",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("import localName3 from \"external\";").then(function (result) {
|
||||
transformAsync('import localName3 from "external";').then(function(
|
||||
result,
|
||||
) {
|
||||
assert.deepEqual(result.metadata.modules.imports[0], {
|
||||
source: "external",
|
||||
imported: ["default"],
|
||||
specifiers: [{
|
||||
kind: "named",
|
||||
imported: "default",
|
||||
local: "localName3",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "named",
|
||||
imported: "default",
|
||||
local: "localName3",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("import localName from \"./array\";", {
|
||||
transformAsync('import localName from "./array";', {
|
||||
resolveModuleSource: function() {
|
||||
return "override-source";
|
||||
},
|
||||
}).then(function (result) {
|
||||
}).then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.imports, [
|
||||
{
|
||||
source: "override-source",
|
||||
imported: ["default"],
|
||||
specifiers: [
|
||||
{
|
||||
"kind": "named",
|
||||
"imported": "default",
|
||||
"local": "localName",
|
||||
kind: "named",
|
||||
imported: "default",
|
||||
local: "localName",
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
}),
|
||||
|
||||
transformAsync("export * as externalName1 from \"external\";", {
|
||||
transformAsync('export * as externalName1 from "external";', {
|
||||
plugins: [require("../../babel-plugin-syntax-export-extensions")],
|
||||
}).then(function (result) {
|
||||
}).then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: ["externalName1"],
|
||||
specifiers: [{
|
||||
kind: "external-namespace",
|
||||
exported: "externalName1",
|
||||
source: "external",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "external-namespace",
|
||||
exported: "externalName1",
|
||||
source: "external",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export externalName2 from \"external\";", {
|
||||
transformAsync('export externalName2 from "external";', {
|
||||
plugins: [require("../../babel-plugin-syntax-export-extensions")],
|
||||
}).then(function (result) {
|
||||
}).then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: ["externalName2"],
|
||||
specifiers: [{
|
||||
kind: "external",
|
||||
local: "externalName2",
|
||||
exported: "externalName2",
|
||||
source: "external",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "external",
|
||||
local: "externalName2",
|
||||
exported: "externalName2",
|
||||
source: "external",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export function namedFunction() {}").then(function (result) {
|
||||
transformAsync("export function namedFunction() {}").then(function(
|
||||
result,
|
||||
) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: ["namedFunction"],
|
||||
specifiers: [{
|
||||
kind: "local",
|
||||
local: "namedFunction",
|
||||
exported: "namedFunction",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "local",
|
||||
local: "namedFunction",
|
||||
exported: "namedFunction",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export var foo = \"bar\";").then(function (result) {
|
||||
transformAsync('export var foo = "bar";').then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
"exported": ["foo"],
|
||||
specifiers: [{
|
||||
kind: "local",
|
||||
local: "foo",
|
||||
exported: "foo",
|
||||
}],
|
||||
exported: ["foo"],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "local",
|
||||
local: "foo",
|
||||
exported: "foo",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export { localName as externalName3 };").then(function (result) {
|
||||
transformAsync("export { localName as externalName3 };").then(function(
|
||||
result,
|
||||
) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: ["externalName3"],
|
||||
specifiers: [{
|
||||
kind: "local",
|
||||
local: "localName",
|
||||
exported: "externalName3",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "local",
|
||||
local: "localName",
|
||||
exported: "externalName3",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export { externalName4 } from \"external\";").then(function (result) {
|
||||
transformAsync('export { externalName4 } from "external";').then(function(
|
||||
result,
|
||||
) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: ["externalName4"],
|
||||
specifiers: [{
|
||||
kind: "external",
|
||||
local: "externalName4",
|
||||
exported: "externalName4",
|
||||
source: "external",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "external",
|
||||
local: "externalName4",
|
||||
exported: "externalName4",
|
||||
source: "external",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export * from \"external\";").then(function (result) {
|
||||
transformAsync('export * from "external";').then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: [],
|
||||
specifiers: [{
|
||||
kind: "external-all",
|
||||
source: "external",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "external-all",
|
||||
source: "external",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
|
||||
transformAsync("export default function defaultFunction() {}").then(function (result) {
|
||||
transformAsync(
|
||||
"export default function defaultFunction() {}",
|
||||
).then(function(result) {
|
||||
assert.deepEqual(result.metadata.modules.exports, {
|
||||
exported: ["defaultFunction"],
|
||||
specifiers: [{
|
||||
kind: "local",
|
||||
local: "defaultFunction",
|
||||
exported: "default",
|
||||
}],
|
||||
specifiers: [
|
||||
{
|
||||
kind: "local",
|
||||
local: "defaultFunction",
|
||||
exported: "default",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("ignore option", function () {
|
||||
it("ignore option", function() {
|
||||
return Promise.all([
|
||||
transformAsync("", {
|
||||
ignore: ["/foo"],
|
||||
@@ -608,7 +713,7 @@ describe("api", function () {
|
||||
]);
|
||||
});
|
||||
|
||||
it("only option", function () {
|
||||
it("only option", function() {
|
||||
return Promise.all([
|
||||
transformAsync("", {
|
||||
only: ["/foo"],
|
||||
@@ -647,23 +752,23 @@ describe("api", function () {
|
||||
]);
|
||||
});
|
||||
|
||||
describe("env option", function () {
|
||||
describe("env option", function() {
|
||||
const oldBabelEnv = process.env.BABEL_ENV;
|
||||
const oldNodeEnv = process.env.NODE_ENV;
|
||||
|
||||
setup(function () {
|
||||
setup(function() {
|
||||
// Tests need to run with the default and specific values for these. They
|
||||
// need to be cleared for each test.
|
||||
delete process.env.BABEL_ENV;
|
||||
delete process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
suiteTeardown(function () {
|
||||
suiteTeardown(function() {
|
||||
process.env.BABEL_ENV = oldBabelEnv;
|
||||
process.env.NODE_ENV = oldNodeEnv;
|
||||
});
|
||||
|
||||
it("default", function () {
|
||||
it("default", function() {
|
||||
const result = babel.transform("foo;", {
|
||||
env: {
|
||||
development: { code: false },
|
||||
@@ -673,7 +778,7 @@ describe("api", function () {
|
||||
assert.equal(result.code, undefined);
|
||||
});
|
||||
|
||||
it("BABEL_ENV", function () {
|
||||
it("BABEL_ENV", function() {
|
||||
process.env.BABEL_ENV = "foo";
|
||||
const result = babel.transform("foo;", {
|
||||
env: {
|
||||
@@ -683,7 +788,7 @@ describe("api", function () {
|
||||
assert.equal(result.code, undefined);
|
||||
});
|
||||
|
||||
it("NODE_ENV", function () {
|
||||
it("NODE_ENV", function() {
|
||||
process.env.NODE_ENV = "foo";
|
||||
const result = babel.transform("foo;", {
|
||||
env: {
|
||||
@@ -694,41 +799,43 @@ describe("api", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("resolveModuleSource option", function () {
|
||||
it("resolveModuleSource option", function() {
|
||||
/* eslint-disable max-len */
|
||||
const actual = "import foo from \"foo-import-default\";\nimport \"foo-import-bare\";\nexport { foo } from \"foo-export-named\";";
|
||||
const expected = "import foo from \"resolved/foo-import-default\";\nimport \"resolved/foo-import-bare\";\nexport { foo } from \"resolved/foo-export-named\";";
|
||||
const actual =
|
||||
'import foo from "foo-import-default";\nimport "foo-import-bare";\nexport { foo } from "foo-export-named";';
|
||||
const expected =
|
||||
'import foo from "resolved/foo-import-default";\nimport "resolved/foo-import-bare";\nexport { foo } from "resolved/foo-export-named";';
|
||||
/* eslint-enable max-len */
|
||||
|
||||
return transformAsync(actual, {
|
||||
resolveModuleSource: function (originalSource) {
|
||||
resolveModuleSource: function(originalSource) {
|
||||
return "resolved/" + originalSource;
|
||||
},
|
||||
}).then(function (result) {
|
||||
}).then(function(result) {
|
||||
assert.equal(result.code.trim(), expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildExternalHelpers", function () {
|
||||
it("all", function () {
|
||||
describe("buildExternalHelpers", function() {
|
||||
it("all", function() {
|
||||
const script = buildExternalHelpers();
|
||||
assert.ok(script.indexOf("classCallCheck") >= -1);
|
||||
assert.ok(script.indexOf("inherits") >= 0);
|
||||
});
|
||||
|
||||
it("whitelist", function () {
|
||||
it("whitelist", function() {
|
||||
const script = buildExternalHelpers(["inherits"]);
|
||||
assert.ok(script.indexOf("classCallCheck") === -1);
|
||||
assert.ok(script.indexOf("inherits") >= 0);
|
||||
});
|
||||
|
||||
it("empty whitelist", function () {
|
||||
it("empty whitelist", function() {
|
||||
const script = buildExternalHelpers([]);
|
||||
assert.ok(script.indexOf("classCallCheck") === -1);
|
||||
assert.ok(script.indexOf("inherits") === -1);
|
||||
});
|
||||
|
||||
it("underscored", function () {
|
||||
it("underscored", function() {
|
||||
const script = buildExternalHelpers(["typeof"]);
|
||||
assert.ok(script.indexOf("typeof") >= 0);
|
||||
});
|
||||
|
||||
@@ -5,7 +5,9 @@ import vm from "vm";
|
||||
|
||||
describe("browserify", function() {
|
||||
it("babel/register may be used without breaking browserify", function(done) {
|
||||
const bundler = browserify(path.join(__dirname, "fixtures/browserify/register.js"));
|
||||
const bundler = browserify(
|
||||
path.join(__dirname, "fixtures/browserify/register.js"),
|
||||
);
|
||||
|
||||
bundler.bundle(function(err, bundle) {
|
||||
if (err) return done(err);
|
||||
|
||||
413
packages/babel-core/test/caching-api.js
Normal file
413
packages/babel-core/test/caching-api.js
Normal file
@@ -0,0 +1,413 @@
|
||||
import assert from "assert";
|
||||
import { makeStrongCache } from "../lib/config/caching";
|
||||
|
||||
describe("caching API", () => {
|
||||
it("should allow permacaching with .forever()", () => {
|
||||
let count = 0;
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.forever();
|
||||
return { arg, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
assert.notEqual(fn("one"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow permacaching with cache(true)", () => {
|
||||
let count = 0;
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache(true);
|
||||
return { arg, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
assert.notEqual(fn("one"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow disabling caching with .never()", () => {
|
||||
let count = 0;
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.never();
|
||||
return { arg, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 1 });
|
||||
assert.notEqual(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 4 });
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 5 });
|
||||
assert.notEqual(fn("two"), fn("two"));
|
||||
|
||||
assert.notEqual(fn("one"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow disabling caching with cache(false)", () => {
|
||||
let count = 0;
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache(false);
|
||||
return { arg, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 1 });
|
||||
assert.notEqual(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 4 });
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 5 });
|
||||
assert.notEqual(fn("two"), fn("two"));
|
||||
|
||||
assert.notEqual(fn("one"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow caching based on a value with .using(fn)", () => {
|
||||
let count = 0;
|
||||
let other = "default";
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
const val = cache.using(() => other);
|
||||
|
||||
return { arg, val, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "default";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow caching based on a value with cache(fn)", () => {
|
||||
let count = 0;
|
||||
let other = "default";
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
const val = cache(() => other);
|
||||
|
||||
return { arg, val, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "default";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow invalidation based on a value with .invalidate(fn)", () => {
|
||||
let count = 0;
|
||||
let other = "default";
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
const val = cache.invalidate(() => other);
|
||||
|
||||
return { arg, val, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 2 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 3 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "default";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "default", count: 4 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "default", count: 5 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", val: "new", count: 6 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", val: "new", count: 7 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
});
|
||||
|
||||
it("should allow invalidation with .using and .invalidate", () => {
|
||||
let count = 0;
|
||||
let other = "default";
|
||||
let another = "another";
|
||||
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
const val = cache.using(() => other);
|
||||
const val2 = cache.invalidate(() => another);
|
||||
|
||||
return { arg, val, val2, count: count++ };
|
||||
});
|
||||
|
||||
assert.deepEqual(fn("one"), {
|
||||
arg: "one",
|
||||
val: "default",
|
||||
val2: "another",
|
||||
count: 0,
|
||||
});
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), {
|
||||
arg: "two",
|
||||
val: "default",
|
||||
val2: "another",
|
||||
count: 1,
|
||||
});
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), {
|
||||
arg: "one",
|
||||
val: "new",
|
||||
val2: "another",
|
||||
count: 2,
|
||||
});
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), {
|
||||
arg: "two",
|
||||
val: "new",
|
||||
val2: "another",
|
||||
count: 3,
|
||||
});
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "default";
|
||||
|
||||
assert.deepEqual(fn("one"), {
|
||||
arg: "one",
|
||||
val: "default",
|
||||
val2: "another",
|
||||
count: 4,
|
||||
});
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), {
|
||||
arg: "two",
|
||||
val: "default",
|
||||
val2: "another",
|
||||
count: 5,
|
||||
});
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
other = "new";
|
||||
|
||||
assert.deepEqual(fn("one"), {
|
||||
arg: "one",
|
||||
val: "new",
|
||||
val2: "another",
|
||||
count: 6,
|
||||
});
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), {
|
||||
arg: "two",
|
||||
val: "new",
|
||||
val2: "another",
|
||||
count: 7,
|
||||
});
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
another = "second";
|
||||
|
||||
assert.deepEqual(fn("one"), {
|
||||
arg: "one",
|
||||
val: "new",
|
||||
val2: "second",
|
||||
count: 8,
|
||||
});
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), {
|
||||
arg: "two",
|
||||
val: "new",
|
||||
val2: "second",
|
||||
count: 9,
|
||||
});
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
});
|
||||
|
||||
it("should throw if caching is never configured and not defaulting", () => {
|
||||
const fn = makeStrongCache(() => {}, false /* autoPermacache */);
|
||||
|
||||
assert.throws(() => fn(), /Error: Caching was left unconfigured./);
|
||||
});
|
||||
|
||||
it("should auto-permacache by default", () => {
|
||||
let count = 0;
|
||||
|
||||
const fn = makeStrongCache(arg => ({ arg, count: count++ }));
|
||||
|
||||
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
|
||||
assert.equal(fn("one"), fn("one"));
|
||||
|
||||
assert.deepEqual(fn("two"), { arg: "two", count: 1 });
|
||||
assert.equal(fn("two"), fn("two"));
|
||||
|
||||
assert.notEqual(fn("one"), fn("two"));
|
||||
});
|
||||
|
||||
it("should throw if you set permacaching and use .using", () => {
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.forever();
|
||||
|
||||
cache.using(() => null);
|
||||
});
|
||||
|
||||
assert.throws(() => fn(), /Caching has already been configured/);
|
||||
});
|
||||
|
||||
it("should throw if you set permacaching and use .invalidate", () => {
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.forever();
|
||||
|
||||
cache.invalidate(() => null);
|
||||
});
|
||||
|
||||
assert.throws(() => fn(), /Caching has already been configured/);
|
||||
});
|
||||
|
||||
it("should throw if you set permacaching and use .never", () => {
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.forever();
|
||||
|
||||
cache.never();
|
||||
});
|
||||
|
||||
assert.throws(() => fn(), /Caching has already been configured/);
|
||||
});
|
||||
|
||||
it("should throw if you set no caching and use .using", () => {
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.never();
|
||||
|
||||
cache.using(() => null);
|
||||
});
|
||||
|
||||
assert.throws(() => fn(), /Caching has already been configured/);
|
||||
});
|
||||
|
||||
it("should throw if you set no caching and use .invalidate", () => {
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.never();
|
||||
|
||||
cache.invalidate(() => null);
|
||||
});
|
||||
|
||||
assert.throws(() => fn(), /Caching has already been configured/);
|
||||
});
|
||||
|
||||
it("should throw if you set no caching and use .never", () => {
|
||||
const fn = makeStrongCache((arg, cache) => {
|
||||
cache.never();
|
||||
|
||||
cache.using(() => null);
|
||||
});
|
||||
|
||||
assert.throws(() => fn(), /Caching has already been configured/);
|
||||
});
|
||||
|
||||
it("should throw if you configure .forever after exiting", () => {
|
||||
const fn = makeStrongCache((arg, cache) => cache);
|
||||
|
||||
assert.throws(
|
||||
() => fn().forever(),
|
||||
/Cannot change caching after evaluation/,
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw if you configure .never after exiting", () => {
|
||||
const fn = makeStrongCache((arg, cache) => cache);
|
||||
|
||||
assert.throws(() => fn().never(), /Cannot change caching after evaluation/);
|
||||
});
|
||||
|
||||
it("should throw if you configure .using after exiting", () => {
|
||||
const fn = makeStrongCache((arg, cache) => cache);
|
||||
|
||||
assert.throws(
|
||||
() => fn().using(() => null),
|
||||
/Cannot change caching after evaluation/,
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw if you configure .invalidate after exiting", () => {
|
||||
const fn = makeStrongCache((arg, cache) => cache);
|
||||
|
||||
assert.throws(
|
||||
() => fn().invalidate(() => null),
|
||||
/Cannot change caching after evaluation/,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@ import buildConfigChain from "../lib/config/build-config-chain";
|
||||
|
||||
function fixture() {
|
||||
const args = [__dirname, "fixtures", "config"];
|
||||
for (let i = 0; i < arguments.length; i ++) {
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
return path.join.apply(path, args);
|
||||
@@ -14,11 +14,11 @@ function base() {
|
||||
return process.cwd();
|
||||
}
|
||||
|
||||
describe("buildConfigChain", function () {
|
||||
describe("buildConfigChain", function() {
|
||||
let oldBabelEnv;
|
||||
let oldNodeEnv;
|
||||
|
||||
beforeEach(function () {
|
||||
beforeEach(function() {
|
||||
oldBabelEnv = process.env.BABEL_ENV;
|
||||
oldNodeEnv = process.env.NODE_ENV;
|
||||
|
||||
@@ -26,14 +26,33 @@ describe("buildConfigChain", function () {
|
||||
delete process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
afterEach(function() {
|
||||
process.env.BABEL_ENV = oldBabelEnv;
|
||||
process.env.NODE_ENV = oldNodeEnv;
|
||||
});
|
||||
|
||||
// TODO: Tests for ignore and only
|
||||
describe("ignore/only", () => {
|
||||
// TODO: More tests for ignore and only
|
||||
|
||||
it("dir1", function () {
|
||||
it("should ignore files that match", () => {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("nonexistant-fake", "src.js"),
|
||||
babelrc: false,
|
||||
ignore: [
|
||||
fixture("nonexistant-fake", "src.js"),
|
||||
|
||||
// We had a regression where multiple ignore patterns broke things, so
|
||||
// we keep some extra random items in here.
|
||||
fixture("nonexistant-fake", "other.js"),
|
||||
fixture("nonexistant-fake", "misc.js"),
|
||||
],
|
||||
});
|
||||
|
||||
assert.equal(chain, null);
|
||||
});
|
||||
});
|
||||
|
||||
it("dir1", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("dir1", "src.js"),
|
||||
});
|
||||
@@ -42,9 +61,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"extended",
|
||||
],
|
||||
plugins: ["extended"],
|
||||
},
|
||||
alias: fixture("extended.babelrc.json"),
|
||||
loc: fixture("extended.babelrc.json"),
|
||||
@@ -53,9 +70,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"root",
|
||||
],
|
||||
plugins: ["root"],
|
||||
},
|
||||
alias: fixture(".babelrc"),
|
||||
loc: fixture(".babelrc"),
|
||||
@@ -64,9 +79,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -86,7 +99,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("dir2", function () {
|
||||
it("dir2", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("dir2", "src.js"),
|
||||
});
|
||||
@@ -95,9 +108,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -106,9 +117,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"dir2",
|
||||
],
|
||||
plugins: ["dir2"],
|
||||
},
|
||||
alias: fixture("dir2", ".babelrc"),
|
||||
loc: fixture("dir2", ".babelrc"),
|
||||
@@ -128,7 +137,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("dir3", function () {
|
||||
it("dir3", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("dir3", "src.js"),
|
||||
});
|
||||
@@ -137,9 +146,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"extended",
|
||||
],
|
||||
plugins: ["extended"],
|
||||
},
|
||||
alias: fixture("extended.babelrc.json"),
|
||||
loc: fixture("extended.babelrc.json"),
|
||||
@@ -148,9 +155,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"root",
|
||||
],
|
||||
plugins: ["root"],
|
||||
},
|
||||
alias: fixture(".babelrc"),
|
||||
loc: fixture(".babelrc"),
|
||||
@@ -159,9 +164,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -181,7 +184,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("env - base", function () {
|
||||
it("env - base", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("env", "src.js"),
|
||||
});
|
||||
@@ -190,9 +193,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -201,9 +202,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"env-base",
|
||||
],
|
||||
plugins: ["env-base"],
|
||||
},
|
||||
alias: fixture("env", ".babelrc"),
|
||||
loc: fixture("env", ".babelrc"),
|
||||
@@ -223,7 +222,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("env - foo", function () {
|
||||
it("env - foo", function() {
|
||||
process.env.NODE_ENV = "foo";
|
||||
|
||||
const chain = buildConfigChain({
|
||||
@@ -234,9 +233,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -245,9 +242,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"env-base",
|
||||
],
|
||||
plugins: ["env-base"],
|
||||
},
|
||||
alias: fixture("env", ".babelrc"),
|
||||
loc: fixture("env", ".babelrc"),
|
||||
@@ -256,9 +251,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"env-foo",
|
||||
],
|
||||
plugins: ["env-foo"],
|
||||
},
|
||||
alias: fixture("env", ".babelrc.env.foo"),
|
||||
loc: fixture("env", ".babelrc.env.foo"),
|
||||
@@ -278,7 +271,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("env - bar", function () {
|
||||
it("env - bar", function() {
|
||||
process.env.NODE_ENV = "foo"; // overridden
|
||||
process.env.NODE_ENV = "bar";
|
||||
|
||||
@@ -290,9 +283,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -301,9 +292,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"env-base",
|
||||
],
|
||||
plugins: ["env-base"],
|
||||
},
|
||||
alias: fixture("env", ".babelrc"),
|
||||
loc: fixture("env", ".babelrc"),
|
||||
@@ -312,9 +301,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"env-bar",
|
||||
],
|
||||
plugins: ["env-bar"],
|
||||
},
|
||||
alias: fixture("env", ".babelrc.env.bar"),
|
||||
loc: fixture("env", ".babelrc.env.bar"),
|
||||
@@ -334,8 +321,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
|
||||
it("env - foo", function () {
|
||||
it("env - foo", function() {
|
||||
process.env.NODE_ENV = "foo";
|
||||
|
||||
const chain = buildConfigChain({
|
||||
@@ -375,7 +361,7 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("js-config", function () {
|
||||
it("js-config", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("js-config", "src.js"),
|
||||
});
|
||||
@@ -384,9 +370,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -395,10 +379,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"foo",
|
||||
"bar",
|
||||
],
|
||||
plugins: ["foo", "bar"],
|
||||
},
|
||||
alias: fixture("js-config", ".babelrc.js"),
|
||||
loc: fixture("js-config", ".babelrc.js"),
|
||||
@@ -418,18 +399,16 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("js-config-default - should read transpiled export default", function () {
|
||||
it("js-config-function", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("js-config-default", "src.js"),
|
||||
filename: fixture("js-config-function", "src.js"),
|
||||
});
|
||||
|
||||
const expected = [
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -438,10 +417,45 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"foo",
|
||||
"bar",
|
||||
],
|
||||
compact: true,
|
||||
},
|
||||
alias: fixture("js-config-function", ".babelrc.js"),
|
||||
loc: fixture("js-config-function", ".babelrc.js"),
|
||||
dirname: fixture("js-config-function"),
|
||||
},
|
||||
{
|
||||
type: "arguments",
|
||||
options: {
|
||||
filename: fixture("js-config-function", "src.js"),
|
||||
},
|
||||
alias: "base",
|
||||
loc: "base",
|
||||
dirname: base(),
|
||||
},
|
||||
];
|
||||
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("js-config-default - should read transpiled export default", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("js-config-default", "src.js"),
|
||||
});
|
||||
|
||||
const expected = [
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
dirname: fixture(),
|
||||
},
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: ["foo", "bar"],
|
||||
},
|
||||
alias: fixture("js-config-default", ".babelrc.js"),
|
||||
loc: fixture("js-config-default", ".babelrc.js"),
|
||||
@@ -460,7 +474,7 @@ describe("buildConfigChain", function () {
|
||||
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
it("js-config-extended", function () {
|
||||
it("js-config-extended", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("js-config-extended", "src.js"),
|
||||
});
|
||||
@@ -469,9 +483,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -480,9 +492,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"extended",
|
||||
],
|
||||
plugins: ["extended"],
|
||||
},
|
||||
alias: fixture("extended.babelrc.json"),
|
||||
loc: fixture("extended.babelrc.json"),
|
||||
@@ -491,10 +501,7 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"foo",
|
||||
"bar",
|
||||
],
|
||||
plugins: ["foo", "bar"],
|
||||
},
|
||||
alias: fixture("js-config-extended", ".babelrc.js"),
|
||||
loc: fixture("js-config-extended", ".babelrc.js"),
|
||||
@@ -514,19 +521,58 @@ describe("buildConfigChain", function () {
|
||||
assert.deepEqual(chain, expected);
|
||||
});
|
||||
|
||||
it("json-pkg-config-no-babel - should not throw if" +
|
||||
" package.json doesn't contain a `babel` field", function () {
|
||||
it(
|
||||
"json-pkg-config-no-babel - should not throw if" +
|
||||
" package.json doesn't contain a `babel` field",
|
||||
function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("json-pkg-config-no-babel", "src.js"),
|
||||
});
|
||||
|
||||
const expected = [
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
dirname: fixture(),
|
||||
},
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: ["json"],
|
||||
},
|
||||
alias: fixture("json-pkg-config-no-babel", ".babelrc"),
|
||||
loc: fixture("json-pkg-config-no-babel", ".babelrc"),
|
||||
dirname: fixture("json-pkg-config-no-babel"),
|
||||
},
|
||||
{
|
||||
type: "arguments",
|
||||
options: {
|
||||
filename: fixture("json-pkg-config-no-babel", "src.js"),
|
||||
},
|
||||
alias: "base",
|
||||
loc: "base",
|
||||
dirname: base(),
|
||||
},
|
||||
];
|
||||
|
||||
assert.deepEqual(chain, expected);
|
||||
},
|
||||
);
|
||||
|
||||
it("should not ignore file matching negated file pattern", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("json-pkg-config-no-babel", "src.js"),
|
||||
filename: fixture("ignore-negate", "src.js"),
|
||||
});
|
||||
|
||||
const expected = [
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: [
|
||||
"root-ignore",
|
||||
],
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
@@ -535,18 +581,16 @@ describe("buildConfigChain", function () {
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
plugins: [
|
||||
"json",
|
||||
],
|
||||
ignore: ["*", "!src.js"],
|
||||
},
|
||||
alias: fixture("json-pkg-config-no-babel", ".babelrc"),
|
||||
loc: fixture("json-pkg-config-no-babel", ".babelrc"),
|
||||
dirname: fixture("json-pkg-config-no-babel"),
|
||||
alias: fixture("ignore-negate", ".babelrc"),
|
||||
loc: fixture("ignore-negate", ".babelrc"),
|
||||
dirname: fixture("ignore-negate"),
|
||||
},
|
||||
{
|
||||
type: "arguments",
|
||||
options: {
|
||||
filename: fixture("json-pkg-config-no-babel", "src.js"),
|
||||
filename: fixture("ignore-negate", "src.js"),
|
||||
},
|
||||
alias: "base",
|
||||
loc: "base",
|
||||
@@ -555,85 +599,123 @@ describe("buildConfigChain", function () {
|
||||
];
|
||||
|
||||
assert.deepEqual(chain, expected);
|
||||
|
||||
const chain2 = buildConfigChain({
|
||||
filename: fixture("ignore-negate", "src2.js"),
|
||||
});
|
||||
|
||||
assert.equal(chain2, null);
|
||||
});
|
||||
|
||||
it("js-json-config - should throw an error if both a .babelrc" +
|
||||
" and a .babelrc.js are present", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
it("should not ignore file matching negated folder pattern", function() {
|
||||
const chain = buildConfigChain({
|
||||
filename: fixture("ignore-negate-folder", "folder", "src.js"),
|
||||
});
|
||||
|
||||
const expected = [
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: ["root-ignore"],
|
||||
},
|
||||
alias: fixture(".babelignore"),
|
||||
loc: fixture(".babelignore"),
|
||||
dirname: fixture(),
|
||||
},
|
||||
{
|
||||
type: "options",
|
||||
options: {
|
||||
ignore: ["*", "!folder"],
|
||||
},
|
||||
alias: fixture("ignore-negate-folder", ".babelrc"),
|
||||
loc: fixture("ignore-negate-folder", ".babelrc"),
|
||||
dirname: fixture("ignore-negate-folder"),
|
||||
},
|
||||
{
|
||||
type: "arguments",
|
||||
options: {
|
||||
filename: fixture("ignore-negate-folder", "folder", "src.js"),
|
||||
},
|
||||
alias: "base",
|
||||
loc: "base",
|
||||
dirname: base(),
|
||||
},
|
||||
];
|
||||
|
||||
assert.deepEqual(chain, expected);
|
||||
|
||||
const chain2 = buildConfigChain({
|
||||
filename: fixture("ignore-negate-folder", "src2.js"),
|
||||
});
|
||||
|
||||
assert.equal(chain2, null);
|
||||
});
|
||||
|
||||
it(
|
||||
"js-json-config - should throw an error if both a .babelrc" +
|
||||
" and a .babelrc.js are present",
|
||||
function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-json-config", "src.js"),
|
||||
});
|
||||
},
|
||||
/Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/
|
||||
);
|
||||
});
|
||||
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/);
|
||||
},
|
||||
);
|
||||
|
||||
it("js-pkg-config - should throw an error if both a .babelrc.js" +
|
||||
" and a package.json with a babel field are present", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
it(
|
||||
"js-pkg-config - should throw an error if both a .babelrc.js" +
|
||||
" and a package.json with a babel field are present",
|
||||
function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-pkg-config", "src.js"),
|
||||
});
|
||||
},
|
||||
/Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/
|
||||
);
|
||||
});
|
||||
}, /Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/);
|
||||
},
|
||||
);
|
||||
|
||||
it("json-pkg-config - should throw an error if both a .babelrc" +
|
||||
" and a package.json with a babel field are present", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
it(
|
||||
"json-pkg-config - should throw an error if both a .babelrc" +
|
||||
" and a package.json with a babel field are present",
|
||||
function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("json-pkg-config", "src.js"),
|
||||
});
|
||||
},
|
||||
/Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/
|
||||
);
|
||||
}, /Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/);
|
||||
},
|
||||
);
|
||||
|
||||
it("js-config-error", function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-config-error", "src.js"),
|
||||
});
|
||||
}, /Error while loading config/);
|
||||
});
|
||||
|
||||
it("js-config-error", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-config-error", "src.js"),
|
||||
});
|
||||
},
|
||||
/Error while loading config/
|
||||
);
|
||||
it("js-config-error2", function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-config-error2", "src.js"),
|
||||
});
|
||||
}, /Configuration should be an exported JavaScript object/);
|
||||
});
|
||||
|
||||
it("js-config-error2", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-config-error2", "src.js"),
|
||||
});
|
||||
},
|
||||
/Configuration should be an exported JavaScript object/
|
||||
);
|
||||
it("js-config-error3", function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-config-error3", "src.js"),
|
||||
});
|
||||
}, /Configuration should be an exported JavaScript object/);
|
||||
});
|
||||
|
||||
it("js-config-error3", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
buildConfigChain({
|
||||
filename: fixture("js-config-error3", "src.js"),
|
||||
});
|
||||
},
|
||||
/Configuration should be an exported JavaScript object/
|
||||
);
|
||||
});
|
||||
|
||||
it("json-config-error", function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
buildConfigChain({
|
||||
filename: fixture("json-config-error", "src.js"),
|
||||
});
|
||||
},
|
||||
/Error while parsing config/
|
||||
);
|
||||
it("json-config-error", function() {
|
||||
assert.throws(function() {
|
||||
buildConfigChain({
|
||||
filename: fixture("json-config-error", "src.js"),
|
||||
});
|
||||
}, /Error while parsing config/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,20 +2,23 @@ import traverse from "babel-traverse";
|
||||
import assert from "assert";
|
||||
import { parse } from "babylon";
|
||||
|
||||
describe("evaluation", function () {
|
||||
describe("evaluation", function() {
|
||||
function addTest(code, type, value, notConfident) {
|
||||
it(type + ": " + code, function () {
|
||||
it(type + ": " + code, function() {
|
||||
const visitor = {};
|
||||
|
||||
visitor[type] = function (path) {
|
||||
visitor[type] = function(path) {
|
||||
const evaluate = path.evaluate();
|
||||
assert.equal(evaluate.confident, !notConfident);
|
||||
assert.deepEqual(evaluate.value, value);
|
||||
};
|
||||
|
||||
traverse(parse(code, {
|
||||
plugins: ["*"],
|
||||
}), visitor);
|
||||
traverse(
|
||||
parse(code, {
|
||||
plugins: ["*"],
|
||||
}),
|
||||
visitor,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,14 +59,39 @@ describe("evaluation", function () {
|
||||
addTest("'abc' === 'xyz' || 1 === 1", "LogicalExpression", true);
|
||||
addTest("'abc' === 'xyz' || 1 === 10", "LogicalExpression", false);
|
||||
addTest("'abc' === 'abc' || config.flag === 1", "LogicalExpression", true);
|
||||
addTest("obj.a === 'abc' || config.flag === 1", "LogicalExpression", undefined, true);
|
||||
addTest(
|
||||
"obj.a === 'abc' || config.flag === 1",
|
||||
"LogicalExpression",
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
addTest("'abc' !== 'abc' && config.flag === 1", "LogicalExpression", false);
|
||||
addTest("obj.a === 'abc' && 1 === 1", "LogicalExpression", undefined, true);
|
||||
addTest("'abc' === 'abc' && (1 === 1 || config.flag)", "LogicalExpression", true);
|
||||
addTest("'abc' === 'xyz' || (1 === 1 && config.flag)", "LogicalExpression", undefined, true);
|
||||
addTest("'abc' === 'xyz' || (1 === 1 && 'four' === 'four')", "LogicalExpression", true);
|
||||
addTest("'abc' === 'abc' && (1 === 1 && 'four' === 'four')", "LogicalExpression", true);
|
||||
addTest(
|
||||
"'abc' === 'abc' && (1 === 1 || config.flag)",
|
||||
"LogicalExpression",
|
||||
true,
|
||||
);
|
||||
addTest(
|
||||
"'abc' === 'xyz' || (1 === 1 && config.flag)",
|
||||
"LogicalExpression",
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
addTest(
|
||||
"'abc' === 'xyz' || (1 === 1 && 'four' === 'four')",
|
||||
"LogicalExpression",
|
||||
true,
|
||||
);
|
||||
addTest(
|
||||
"'abc' === 'abc' && (1 === 1 && 'four' === 'four')",
|
||||
"LogicalExpression",
|
||||
true,
|
||||
);
|
||||
addTest("({})", "ObjectExpression", {});
|
||||
addTest("({a: '1'})", "ObjectExpression", { a: "1" });
|
||||
addTest("({['a' + 'b']: 10 * 20, 'z': [1, 2, 3]})", "ObjectExpression", { ab: 200, z: [1, 2, 3] });
|
||||
addTest("({['a' + 'b']: 10 * 20, 'z': [1, 2, 3]})", "ObjectExpression", {
|
||||
ab: 200,
|
||||
z: [1, 2, 3],
|
||||
});
|
||||
});
|
||||
|
||||
6
packages/babel-core/test/fixtures/config/ignore-negate-folder/.babelrc
vendored
Normal file
6
packages/babel-core/test/fixtures/config/ignore-negate-folder/.babelrc
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
ignore: [
|
||||
"*",
|
||||
"!folder",
|
||||
],
|
||||
}
|
||||
2
packages/babel-core/test/fixtures/config/ignore-negate-folder/folder/.gitignore
vendored
Normal file
2
packages/babel-core/test/fixtures/config/ignore-negate-folder/folder/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Blank .gitignore to ensure this directory exists.
|
||||
!.gitignore
|
||||
6
packages/babel-core/test/fixtures/config/ignore-negate/.babelrc
vendored
Normal file
6
packages/babel-core/test/fixtures/config/ignore-negate/.babelrc
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
ignore: [
|
||||
"*",
|
||||
"!src.js",
|
||||
],
|
||||
}
|
||||
7
packages/babel-core/test/fixtures/config/js-config-function/.babelrc.js
vendored
Normal file
7
packages/babel-core/test/fixtures/config/js-config-function/.babelrc.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function(api) {
|
||||
api.cache(true);
|
||||
|
||||
return {
|
||||
compact: true,
|
||||
};
|
||||
};
|
||||
30
packages/babel-core/test/fixtures/plugins/file-add-import/exec.js
vendored
Normal file
30
packages/babel-core/test/fixtures/plugins/file-add-import/exec.js
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
var res = transform("", {
|
||||
plugins: [
|
||||
function (b) {
|
||||
return {
|
||||
visitor: {
|
||||
Program: function(path, state) {
|
||||
var file = state.file;
|
||||
file.addImport("import-star", "*", "lib");
|
||||
file.addImport("import-default", "default", "foo");
|
||||
file.addImport("import-alias", "bar", "baz");
|
||||
file.addImport("import-default-alias", "quux");
|
||||
file.addImport("import-empty", "");
|
||||
file.addImport("import-none");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
var expected = multiline([
|
||||
'import "import-none";',
|
||||
'import "import-empty";',
|
||||
'import { quux as _quux } from "import-default-alias";',
|
||||
'import { bar as _baz } from "import-alias";',
|
||||
'import _foo from "import-default";',
|
||||
'import * as _lib from "import-star";',
|
||||
]);
|
||||
|
||||
assert.equal(res.code, expected);
|
||||
0
packages/babel-core/test/fixtures/resolution/babel-org-paths/node_modules/@babel/plugin-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-org-paths/node_modules/@babel/plugin-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-org-paths/node_modules/@babel/preset-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-org-paths/node_modules/@babel/preset-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-scoped-nested-module-paths/node_modules/@babel/mod/plugin.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-scoped-nested-module-paths/node_modules/@babel/mod/plugin.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-scoped-nested-module-paths/node_modules/@babel/mod/preset.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/babel-scoped-nested-module-paths/node_modules/@babel/mod/preset.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/foo-org-paths/node_modules/@foo/babel-plugin-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/foo-org-paths/node_modules/@foo/babel-plugin-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/foo-org-paths/node_modules/@foo/babel-preset-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/foo-org-paths/node_modules/@foo/babel-preset-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/module-paths/node_modules/plugin/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/module-paths/node_modules/plugin/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/module-paths/node_modules/preset/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/module-paths/node_modules/preset/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/nested-module-paths/node_modules/mod/plugin.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/nested-module-paths/node_modules/mod/plugin.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/nested-module-paths/node_modules/mod/preset.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/nested-module-paths/node_modules/mod/preset.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/relative-paths/dir/plugin.js
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/relative-paths/dir/plugin.js
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/relative-paths/dir/preset.js
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/relative-paths/dir/preset.js
vendored
Normal file
@@ -1 +0,0 @@
|
||||
!node_modules/
|
||||
@@ -1 +0,0 @@
|
||||
var x = "before";
|
||||
@@ -1 +0,0 @@
|
||||
var x = "AFTER";
|
||||
@@ -1,9 +0,0 @@
|
||||
module.exports = function () {
|
||||
return {
|
||||
visitor: {
|
||||
StringLiteral: function (path) {
|
||||
path.node.value = "after";
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
module.exports = function (context, options, fileContext) {
|
||||
if (/resolve-addons-relative-to-file$/.test(fileContext.dirname)) {
|
||||
return {
|
||||
plugins: [plugin],
|
||||
};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
function plugin () {
|
||||
return {
|
||||
visitor: {
|
||||
StringLiteral: function (path) {
|
||||
path.node.value =
|
||||
path.node.value.toUpperCase();
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
0
packages/babel-core/test/fixtures/resolution/scoped-nested-module-paths/node_modules/@foo/mod/plugin.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/scoped-nested-module-paths/node_modules/@foo/mod/plugin.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/scoped-nested-module-paths/node_modules/@foo/mod/preset.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/scoped-nested-module-paths/node_modules/@foo/mod/preset.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/standard-paths/node_modules/babel-plugin-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/standard-paths/node_modules/babel-plugin-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/standard-paths/node_modules/babel-preset-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/standard-paths/node_modules/babel-preset-mod/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-babel-paths/node_modules/@babel/plugin-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-babel-paths/node_modules/@babel/plugin-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-babel-paths/node_modules/@babel/preset-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-babel-paths/node_modules/@babel/preset-foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-missing-paths/.gitignore
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-missing-paths/.gitignore
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-module-paths/node_modules/foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-module-paths/node_modules/foo/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-opposite-paths/node_modules/babel-plugin-testplugin/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-opposite-paths/node_modules/babel-plugin-testplugin/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-opposite-paths/node_modules/babel-preset-testpreset/index.js
generated
vendored
Normal file
0
packages/babel-core/test/fixtures/resolution/throw-opposite-paths/node_modules/babel-preset-testpreset/index.js
generated
vendored
Normal file
@@ -1,3 +1,2 @@
|
||||
export function foo() {}
|
||||
|
||||
export function bar() {}
|
||||
|
||||
@@ -3,11 +3,12 @@ var Foo = function (_Bar) {
|
||||
|
||||
function Foo(options) {
|
||||
babelHelpers.classCallCheck(this, Foo);
|
||||
|
||||
var parentOptions = {};
|
||||
|
||||
parentOptions.init = function () {
|
||||
this;
|
||||
};
|
||||
|
||||
return babelHelpers.possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).call(this, parentOptions));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
function test() {
|
||||
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "hi";
|
||||
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user