Compare commits

..

105 Commits

Author SHA1 Message Date
Henry Zhu
a0f0411abf v7.0.0-alpha.15 2017-07-11 23:35:22 -04:00
Buu Nguyen
8decefe8bc Fix bug incorrect dereferencing rest argument (#5810)
* Fix bug incorrect dereferencing rest argument

* Fix pure path

* Minor refactor
2017-07-11 23:26:57 -04:00
Henry Zhu
650cd43096 move to src (#5942) 2017-07-11 23:23:15 -04:00
Henry Zhu
03f249430a v7.0.0-alpha.14 2017-07-11 22:53:09 -04:00
Henry Zhu
8460b4c62f v7.0.0-alpha.13 2017-07-11 22:27:56 -04:00
Brian Ng
4710b8a5ba Update babel-types docs [skip ci] (#5941) 2017-07-11 22:20:43 -04:00
Mauro Bringolf
465c087ac0 Removed update operators from number unary operators (#5940) 2017-07-11 19:08:50 -05:00
Brian Ng
bc123ad02a Change trailing comma option for polyfill scripts (#5939) 2017-07-11 18:13:26 -05:00
Justin Ridgewell
e170e6d760 Fix returning an object in a derived class constructor without super (#5885) 2017-07-11 17:43:19 -04:00
Ash
960e1708a1 babel-traverse: Mark appropriate template literals as pure (#5914)
* Identify pure template literals

* Mark template literals as pure where possible

* Changes based on code review

* nit
2017-07-11 17:42:34 -04:00
Daniel Tschinder
2ce5f166d7 Remove codecov node package and use bash uploader (#5937) 2017-07-11 13:37:54 -05:00
Sarup Banskota
a7a9e7ae17 Gitignore package-lock (#5918) 2017-07-10 13:44:27 -05:00
Justin Ridgewell
51ff4dd936 Fix async-to-generator ForAwait transform (#5932)
The old transform called an external `babel-traverse`, which doesn’t
does something funky.
2017-07-09 23:49:44 -05:00
Justin Ridgewell
628061c501 Add new.target transform (#5906)
* Add new.target transform

* Catch new.target under only an arrow function

* More unsupported reflect.construct cases

* Fix node 4 test

* Do not transform Methods

* More tests

* Properly setup function inheritance test

* Tests tests tests

* Fix ES6 class's new.target

* Remove expected output thats supposed to throw.
2017-07-07 14:28:19 -04:00
Sarup Banskota
003b8918c2 Fix typo in babel-types doc script + run it (#5855) 2017-07-06 16:19:51 -04:00
Brian Ng
58ec149c52 Fix some unneeded semis in test fixtures (#5892) 2017-06-27 22:15:10 -05:00
Daniel Tschinder
b3372a572d Remove whitespace generation (#5833)
* Remove whitespace generation and rely on default printing

Changes to printing:
* Add newline after last empty SwitchCase
* Add newlines around block comments if they are non-flow comments or contain newlines

* Fix a few more fixtures
2017-06-27 21:57:02 -05:00
Josh Johnston
bc29145465 Fix 5768 (to 7.0 branch) (#5891) 2017-06-27 20:04:23 -04:00
Henry Zhu
ed0de70656 Merge pull request #5889 from babel/update-babylon
Update babylon
2017-06-27 17:29:55 -04:00
Henry Zhu
9a75916012 remove unused dependencies 2017-06-27 17:18:13 -04:00
Henry Zhu
a4080dc095 update babylon 2017-06-27 17:17:41 -04:00
Henry Zhu
4e50b2d9d9 Merge pull request #5412 from babel/prettify
Use prettier
2017-06-27 17:12:14 -04:00
Brian Ng
e4b35f680d Run prettier 2017-06-27 12:15:00 -05:00
Brian Ng
93cc22dae1 Add prettier 2017-06-27 12:13:54 -05:00
Henry Zhu
89d8f70fcd Merge pull request #5813 from jridgewell/pr/5786
Optional Chaining Operator (Stage 1)
2017-06-27 11:10:47 -04:00
Justin Ridgewell
f363ec6b99 Add to stage-1 preset 2017-06-27 01:27:41 -04:00
Logan Smyth
b3183b1198 Force color output in test runs to ensure consistent behavior in Travis (Take 2) 2017-06-26 15:59:30 -07:00
Logan Smyth
892377ae57 Force color output in test runs to ensure consistent behavior in Travis. 2017-06-26 15:51:51 -07:00
Logan Smyth
95b3c8a16a Revert "TEMP: Another quick test"
This reverts commit 0005b9e4cf.
2017-06-26 15:49:56 -07:00
Logan Smyth
12e39116f0 Revert "TEMP: Debugging unexpected test failures."
This reverts commit 1fb3d5b0f6.
2017-06-26 15:49:54 -07:00
Logan Smyth
0005b9e4cf TEMP: Another quick test 2017-06-26 15:22:13 -07:00
Logan Smyth
1fb3d5b0f6 TEMP: Debugging unexpected test failures. 2017-06-26 14:59:39 -07:00
Henry Zhu
bd9e1860d0 for-of optimization on arrays/known functions that return arrays (#4747) 2017-06-26 16:47:39 -04:00
Sven SAULEAU
692e51609c Merge pull request #5886 from yavorsky/7-fix-commonjs-destructuring
7.0 port: Fix commonjs exports with destructuring.
2017-06-26 22:37:39 +02:00
Henry Zhu
bb5528b414 Merge pull request #4850 from babel/removeClassCallCheck-option
Remove ClassCallCheck, possibleConstructorReturn in loose mode
2017-06-26 15:24:11 -04:00
Buu Nguyen
033bad3098 Fix bug super ref check doesn’t honor spec evaluation order (#5801) 2017-06-26 15:16:47 -04:00
Artem Yavorsky
2cfd01aeb6 Add fixtures for exports with desctucturing. 2017-06-26 15:44:18 +03:00
Artem Yavorsky
ddba7ba89f Add destructuring case for modules-commonjs. 2017-06-26 14:33:58 +03:00
bill-improbableio
851d2cb6e0 Pass SIGINT signals to the spawned child process (#5861)
* Pass SIGINT signals down to the spawned child

* Kill process with correct signal

* Fix lint issues

* Fix exit for outer process
2017-06-24 19:04:53 -04:00
Joseph Frazier
a330cf2b09 Add support for evaluating String.raw expressions (#5681)
* Add support for evaluating `String.raw` expressions

* Dedupe evaluation code for template literal quasis

* Check scoping in `String.raw` evaluation
  This addresses https://github.com/babel/babel/pull/5681#discussion_r114203497

* Ensure that `tag` is a MemberExpression in `String.raw` evaluation
  This addresses https://github.com/babel/babel/pull/5681#discussion_r114203555

* babel-traverse: Move evaluateQuasis() outside _evaluate()
2017-06-24 16:00:42 -04:00
MarckK
b6b69c615a Fix type errors for destructuring assignments(#4227) (#5865) 2017-06-24 15:56:51 -04:00
Henry Zhu
4fdff567c6 remove superClass truthy check 2017-06-24 14:27:41 -04:00
David Colwell
622672d397 Remove Monorepo negative regarding npm results (#5884) [skip ci]
It's fixed as of:  https://github.com/npms-io/npms/issues/13
2017-06-22 23:01:13 -04:00
Justin Ridgewell
1ea3b0601c Merge pull request #5877 from mathiasbynens/update-unicode-property-regex
Move plugin-transform-unicode-property-regex to stage 3
2017-06-21 16:29:29 -04:00
Mathias Bynens
5492fe130a Move plugin-transform-unicode-property-regex to stage 3 2017-06-21 15:55:02 +02:00
Henry Zhu
8a4ab088e4 create and use a inheritsLoose helper 2017-06-19 11:58:49 -04:00
Henry Zhu
ba671d0a66 update babel-eslint, try out numeric separators (#5866)
* update babel-eslint, try out numeric separators

* update version
2017-06-17 23:31:47 -04:00
Henry Zhu
4595729cbb fix issue as a result of refactor (#5867) 2017-06-17 16:01:33 -04:00
Justin Ridgewell
5387d9f903 Merge pull request #5721 from Qantas94Heavy/rest-parameters-5656
Fix optimisation of shadowed rest parameters
2017-06-13 13:57:53 -04:00
Justin Ridgewell
05726a976e Merge pull request #5837 from jridgewell/hoist-closure-helpers
Hoist several closures
2017-06-12 02:23:45 -04:00
Ryan Gaus
070662e381 Add tests for babel-generator (#5845)
Added two tests for src/generators/flow.js that check if a value is of
type `empty` or `mixed`.
2017-06-10 09:28:37 -04:00
Henry Zhu
cdca54aed3 remove possibleConstructorReturn in loose mode as well 2017-06-09 18:42:52 -04:00
Henry Zhu
4081f3e23e removeClassCallCheck option 2017-06-09 16:50:17 -04:00
Brian Ng
cce83a0cea Fix parens issues with exponentiation in generator (#5830) 2017-06-09 11:10:16 -04:00
Sarup Banskota
f1303aa54c Misc updates to babel-core README (#5841) [skip ci]
* Minor grammar things
* Standardize fullstops on the options table
* Usage of `` where appropriate
2017-06-09 10:37:34 -04:00
Justin Ridgewell
ac33b1be27 Fix addCompletionRecords 2017-06-09 00:12:16 -04:00
Daniel Tschinder
36ab72f095 Support declare export statements (#5589)
* Add definition of declare export statements

* Add more codecoverage
2017-06-08 23:15:54 +02:00
Sarup Banskota
9b05b0df5c Include node 8.0 to travis config & update tests (#5807)
* Remove node 7 and introduce node 8 in travis config

Progress on #5804

* Run yarn install with node 8

Progress on #5804

* Remove expose_debug_as from tests; replace with expose_gc_as

Fixes #5804

* Remove dashed options since they aren't listed

* Revert "Remove dashed options since they aren't listed"

This reverts commit f826167e320ee85331e09ac63b5674401cac6236.
2017-06-08 18:50:42 +02:00
Justin Ridgewell
119d5c5871 Hoist several closures 2017-06-08 03:39:10 -04:00
Justin Ridgewell
0740e61131 Use strict 2017-06-08 00:47:19 -04:00
Justin Ridgewell
97d0ab78cb Update babylon 2017-06-07 03:52:42 -04:00
Justin Ridgewell
f537fc7da7 Add babel-generator tests 2017-06-07 03:22:52 -04:00
Justin Ridgewell
462825b15a Simplify transform
This also makes the output use less comparisons for `foo?.()?.bar`
cases. 😁
2017-06-07 03:22:52 -04:00
Justin Ridgewell
9e91ac54d3 Optional call expressions short circuit later member expressions 2017-06-07 03:22:52 -04:00
Justin Ridgewell
54d9732d0b Test Update and Unary expressions 2017-06-07 03:22:52 -04:00
Justin Ridgewell
d92309f0db PR comments 2017-06-07 03:22:52 -04:00
Justin Ridgewell
faa6c9f708 Use nil 2017-06-07 03:22:52 -04:00
Justin Ridgewell
6cc2f5dc78 Consider any unary expression 2017-06-07 03:22:52 -04:00
Justin Ridgewell
a62cb9281e Delete unnecessary check 2017-06-07 03:22:52 -04:00
Justin Ridgewell
ef87acc389 Test not-top-level optional chaining 2017-06-07 03:22:51 -04:00
Justin Ridgewell
1f22ac353a Lint 2017-06-07 03:22:51 -04:00
Justin Ridgewell
0e5f597ee6 Readme 2017-06-07 03:22:51 -04:00
Justin Ridgewell
899634d20b Add exec tests 2017-06-07 03:22:51 -04:00
Justin Ridgewell
b048bff77d Add optional to MemberExpression 2017-06-07 03:22:51 -04:00
Justin Ridgewell
9ce797dd34 Reduce context memoization when possible 2017-06-07 03:22:51 -04:00
Justin Ridgewell
acdd3637bc Refactor 2017-06-07 03:22:51 -04:00
Justin Ridgewell
85b6b4b1b2 Print optional chain operator 2017-06-07 03:22:51 -04:00
Justin Ridgewell
5fe4803562 Simplify NewExpression|CallExpression visitor 2017-06-07 03:22:51 -04:00
Justin Ridgewell
30ee87159d Split syntax and transform into two plugins 2017-06-07 03:22:51 -04:00
Justin Ridgewell
2a496890ff Use a better nested syntax
This way, it quickly returns from the conditions. The first nil will
now exit, instead of checking every nil.

This also allows conditionalChaining inside a container to still
operate the container.
2017-06-07 03:22:51 -04:00
Justin Ridgewell
3fae121460 Implement Null Propagation Operator 2017-06-07 03:22:51 -04:00
Sven SAULEAU
750b03a22f refactor: use WeakSet to keep track of transformed nodes 2017-06-07 03:22:51 -04:00
Sven SAULEAU
98487b5a15 fix: typo 2017-06-07 03:22:51 -04:00
Sven SAULEAU
a9d8040c0f refactor: change undefined to void 0 2017-06-07 03:22:51 -04:00
Sven SAULEAU
3faca62a77 wip 2017-06-07 03:22:51 -04:00
Sven SAULEAU
cc6959e1fa feat: WIP assignements 2017-06-07 03:22:51 -04:00
Sven SAULEAU
6bd3bf4d2f feat: optional chaining with function call 2017-06-07 03:22:51 -04:00
Sven SAULEAU
ed15443dba fix: use undefined instead of null 2017-06-07 03:22:51 -04:00
Sven SAULEAU
64ff5a080d refactor: improved transformation logic 2017-06-07 03:22:51 -04:00
Sven SAULEAU
72259ca5d3 feat: cleanup 2017-06-07 03:22:51 -04:00
Sven SAULEAU
00f58b9bfa feat: optional chaing 2017-06-07 03:22:51 -04:00
Justin Ridgewell
5cc1cbf3bc Matches pattern cleanup (#5826)
* Extract duplicated function into babel-types

Also reimplements in a sane way.

* Add tests

* cleanup
2017-06-06 11:20:05 -04:00
Justin Ridgewell
8df5514083 Fix numeric separator Number transform (#5825) 2017-06-06 08:14:30 -04:00
Henry Zhu
123dce5fcd Hardcode to double quotes, indent to 2 spaces (#5824) 2017-06-05 22:14:37 -05:00
Nicolò Ribaudo
b0524427c1 Wrap an arrow function in parentheses if it the test of a conditional expression (#5820)
* Wrap an arrow function in parentheses if it the test of a conditional expression

Fixes #5819

* Use ConditionalExpresion to check if () => {} should be wrapped

* Move `t.isTaggedTemplateExpression()` from ArrowFunctionExpression to
  ConditionalExpresion

* [test] `await (() => {})` needs the parentheses

* [test] (a ? b : c)`` needs the parentheses
2017-06-05 12:39:28 -04:00
Justin Ridgewell
53e3f0dbdc babel-types: avoid recreating validator closures (#5821) 2017-06-05 12:38:30 -04:00
Artem Yavorsky
c4fd05c0c2 Spec compatibility for template literals. (#5791)
* Spec compatibility for template literals.

* Update preset-es2015 `spec` expected case.

* Prevent array mutability by replacing `shift`.

* Fix condition for single item.

* Group concats to ensure toPrimitive sequence.

* Update function test case.

* Add semi for function test case.

* Simplify concat call expressions creating.

* Fix some cases with multiple idengifiers.

* Add test case with different literals.

* Add test case for `Symbol()` and toPrimitive order

* Add actual literal case.

* Add minNodeVersion to template literals order.

* Flip the logical expression.

* Update README for template literals spec option.

* docs [skip ci]
2017-06-05 08:53:10 -04:00
Simen Bekkhus
1e55653ac1 Don't call deprecated code frame export (#5815) 2017-06-02 08:49:26 -04:00
Henry Zhu
272209ace5 ⬆️ Alpha 12 (#5808)
* fix usage of codeframe
2017-06-01 15:13:17 -04:00
Sven SAULEAU
7e739f954d Merge pull request #5802 from babel/issue5371
Remove check for super calls in arrow function
2017-06-01 09:55:08 +02:00
Sven SAULEAU
bf9b434736 refactor: search parent instead of using state 2017-05-31 19:34:05 -05:00
Sven SAULEAU
819056e94a fix: remove check for super in arrow function 2017-05-31 19:33:57 -05:00
Henry Zhu
c5bad22767 v7.0.0-alpha.12 2017-05-31 17:11:39 -04:00
Henry Zhu
68ed633175 force-publish all packages [skip ci] 2017-05-31 17:09:11 -04:00
Karl Cheng
0667160b11 Fix optimisation of shadowed rest parameters
The arguments of a function would be unnecessarily copied if there was
a nested function that had a parameter with the same identifier as the
rest parameter for the outer function. This checks the scope of the
parameter is correct before deoptimising.

Fixes: https://github.com/babel/babel/issues/5656
Refs: https://github.com/babel/babel/issues/2091
2017-05-16 22:39:13 +10:00
968 changed files with 13849 additions and 7667 deletions

View File

@@ -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
.gitignore vendored
View File

@@ -10,6 +10,7 @@
/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

View File

@@ -7,7 +7,7 @@ cache:
directories:
- node_modules
node_js:
- '7'
- '8'
- '6'
- '4'

View File

@@ -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");
});
});

View File

@@ -2,6 +2,9 @@ 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
@@ -55,10 +58,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
@@ -67,7 +71,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:

View File

@@ -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!

View File

@@ -1,6 +1,6 @@
{
"lerna": "2.0.0-rc.4",
"version": "7.0.0-alpha.11",
"version": "7.0.0-alpha.15",
"changelog": {
"repo": "babel/babel",
"labels": {

View File

@@ -3,30 +3,31 @@
"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-cli": "7.0.0-alpha.9",
"babel-core": "7.0.0-alpha.9",
"babel-eslint": "^7.0.0",
"babel-cli": "7.0.0-alpha.12",
"babel-core": "7.0.0-alpha.12",
"babel-eslint": "8.0.0-alpha.12",
"babel-plugin-istanbul": "^2.0.1",
"babel-preset-env": "2.0.0-alpha.7",
"babel-preset-flow": "7.0.0-alpha.9",
"babel-preset-stage-0": "7.0.0-alpha.9",
"babel-register": "7.0.0-alpha.9",
"babel-preset-env": "2.0.0-alpha.12",
"babel-preset-flow": "7.0.0-alpha.12",
"babel-preset-stage-0": "7.0.0-alpha.12",
"babel-register": "7.0.0-alpha.12",
"browserify": "^13.1.1",
"bundle-collapser": "^1.2.1",
"chai": "^3.5.0",
"chalk": "1.1.1",
"codecov": "^1.0.1",
"chalk": "^1.1.1",
"derequire": "^2.0.2",
"eslint": "^3.9.0",
"eslint-config-babel": "^6.0.0",
"eslint": "^3.14.1",
"eslint-config-babel": "^7.0.1",
"eslint-plugin-flowtype": "^2.20.0",
"eslint-plugin-prettier": "^2.1.2",
"flow-bin": "^0.41.0",
"gulp": "^3.9.0",
"gulp-babel": "babel/gulp-babel#b7-alpha",
@@ -34,20 +35,23 @@
"gulp-plumber": "^1.0.1",
"gulp-util": "^3.0.7",
"gulp-watch": "^4.3.5",
"husky": "^0.13.2",
"lerna": "2.0.0-rc.4",
"lerna-changelog": "^0.2.0",
"lint-staged": "^3.6.1",
"lodash": "^4.2.0",
"mocha": "^3.0.0",
"nyc": "^10.0.0",
"output-file-sync": "^1.1.1",
"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"
},
"nyc": {
"all": true,
@@ -57,5 +61,11 @@
],
"sourceMap": false,
"instrument": false
},
"lint-staged": {
"*.js": [
"eslint --format=codeframe --fix",
"git add"
]
}
}

5
packages/.eslintrc Normal file
View File

@@ -0,0 +1,5 @@
{
"rules": {
"prettier/prettier": ["error", { "trailingComma": "all" }]
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "babel-cli",
"version": "7.0.0-alpha.11",
"version": "7.0.0-alpha.15",
"description": "Babel command line.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -16,9 +16,9 @@
"compiler"
],
"dependencies": {
"babel-core": "7.0.0-alpha.11",
"babel-polyfill": "7.0.0-alpha.9",
"babel-register": "7.0.0-alpha.11",
"babel-core": "7.0.0-alpha.15",
"babel-polyfill": "7.0.0-alpha.15",
"babel-register": "7.0.0-alpha.15",
"commander": "^2.8.1",
"convert-source-map": "^1.1.0",
"fs-readdir-recursive": "^1.0.0",
@@ -33,7 +33,7 @@
"chokidar": "^1.6.1"
},
"devDependencies": {
"babel-helper-fixtures": "7.0.0-alpha.10"
"babel-helper-fixtures": "7.0.0-alpha.15"
},
"bin": {
"babel-doctor": "./bin/babel-doctor.js",

View File

@@ -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,.mjs]", 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);

View File

@@ -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);

View File

@@ -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];
@@ -59,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);
@@ -80,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 {
@@ -90,5 +95,10 @@ getV8Flags(function (err, v8Flags) {
}
});
});
process.on("SIGINT", () => {
proc.kill("SIGINT");
process.exit(1);
});
}
});

View File

@@ -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);

View File

@@ -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);
}
}
});
}
};

View File

@@ -34,45 +34,117 @@ 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,
);
// 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,.mjs]", 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 +156,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 +164,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");
}

View File

@@ -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;
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -3,9 +3,6 @@
/*
Test comment
*/
arr.map(function (x) {
return x * MULTIPLIER;
});
// END OF FILE
}); // END OF FILE

View 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);

View File

@@ -1,6 +1,6 @@
{
"name": "babel-code-frame",
"version": "7.0.0-alpha.11",
"version": "7.0.0-alpha.15",
"description": "Generate errors that contain a code frame that point to source locations.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",

View File

@@ -90,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];
}
@@ -106,9 +106,15 @@ function highlight(defs: Object, text: string) {
*/
function getMarkerLines(
loc: NodeLocation, source: Array<string>, opts: Object
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 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;
@@ -165,12 +171,13 @@ function getMarkerLines(
return { start, end, markerLines };
}
export function codeFrameColumns (
export function codeFrameColumns(
rawLines: string,
loc: NodeLocation,
opts: Object = {},
): string {
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 });
@@ -186,34 +193,39 @@ export function codeFrameColumns (
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} | `;
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;
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),
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);
@@ -226,7 +238,7 @@ export function codeFrameColumns (
* Create a code frame, adding line numbers, code highlighting, and pointing to a given position.
*/
export default function (
export default function(
rawLines: string,
lineNumber: number,
colNumber: ?number,
@@ -236,7 +248,7 @@ export default function (
deprecationWarningShown = true;
const deprecationError = new Error(
"Passing lineNumber and colNumber is deprecated to babel-code-frame. Please use `codeFrameColumns`."
"Passing lineNumber and colNumber is deprecated to babel-code-frame. Please use `codeFrameColumns`.",
);
deprecationError.name = "DeprecationWarning";
@@ -249,7 +261,9 @@ export default function (
colNumber = Math.max(colNumber, 0);
const location: NodeLocation = { start: { column: colNumber, line: lineNumber } };
const location: NodeLocation = {
start: { column: colNumber, line: lineNumber },
};
return codeFrameColumns(rawLines, location, opts);
}

View File

@@ -2,35 +2,29 @@ import assert from "assert";
import chalk from "chalk";
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("maximum context lines and padding", function () {
it("maximum context lines and padding", function() {
const rawLines = [
"/**",
" * Sums two numbers.",
@@ -44,18 +38,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.",
@@ -69,43 +66,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);
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.",
@@ -119,17 +122,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.",
@@ -143,16 +149,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.",
@@ -166,78 +175,82 @@ 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"))
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("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");
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
assert.equal(
codeFrameColumns(rawLines, { start: { line: 2, column: 3 }, end: { line: 2, column: 16 } }), [
codeFrameColumns(rawLines, {
start: { line: 2, column: 3 },
end: { line: 2, column: 16 },
}),
[
" 1 | class Foo {",
"> 2 | constructor()",
" | ^^^^^^^^^^^^^",
" 3 | };",
].join("\n"));
].join("\n"),
);
});
it("mark multiple columns across lines", function() {
const rawLines = [
"class Foo {",
" constructor() {",
" }",
"};",
].join("\n");
const rawLines = ["class Foo {", " constructor() {", " }", "};"].join(
"\n",
);
assert.equal(
codeFrameColumns(rawLines, { start: { line: 2, column: 17 }, end: { line: 3, column: 3 } }), [
codeFrameColumns(rawLines, {
start: { line: 2, column: 17 },
end: { line: 3, column: 3 },
}),
[
" 1 | class Foo {",
"> 2 | constructor() {",
" | ^",
"> 3 | }",
" | ^^^",
" 4 | };",
].join("\n"));
].join("\n"),
);
});
it("mark multiple columns across multiple lines", function() {
@@ -249,7 +262,11 @@ describe("babel-code-frame", function () {
"};",
].join("\n");
assert.equal(
codeFrameColumns(rawLines, { start: { line: 2, column: 17 }, end: { line: 4, column: 3 } }), [
codeFrameColumns(rawLines, {
start: { line: 2, column: 17 },
end: { line: 4, column: 3 },
}),
[
" 1 | class Foo {",
"> 2 | constructor() {",
" | ^",
@@ -258,7 +275,8 @@ describe("babel-code-frame", function () {
"> 4 | }",
" | ^^^",
" 5 | };",
].join("\n"));
].join("\n"),
);
});
it("mark across multiple lines without columns", function() {
@@ -270,12 +288,14 @@ describe("babel-code-frame", function () {
"};",
].join("\n");
assert.equal(
codeFrameColumns(rawLines, { start: { line: 2 }, end: { line: 4 } }), [
codeFrameColumns(rawLines, { start: { line: 2 }, end: { line: 4 } }),
[
" 1 | class Foo {",
"> 2 | constructor() {",
"> 3 | console.log(arguments);",
"> 4 | }",
" 5 | };",
].join("\n"));
].join("\n"),
);
});
});

View File

@@ -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,7 +62,7 @@ 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 sourceCode = "if (true) return;";
@@ -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)`.

View File

@@ -1,6 +1,6 @@
{
"name": "babel-core",
"version": "7.0.0-alpha.11",
"version": "7.0.0-alpha.15",
"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.11",
"babel-generator": "7.0.0-alpha.11",
"babel-helpers": "7.0.0-alpha.11",
"babel-messages": "7.0.0-alpha.10",
"babel-template": "7.0.0-alpha.11",
"babel-traverse": "7.0.0-alpha.11",
"babel-types": "7.0.0-alpha.11",
"babylon": "7.0.0-beta.12",
"babel-code-frame": "7.0.0-alpha.15",
"babel-generator": "7.0.0-alpha.15",
"babel-helpers": "7.0.0-alpha.15",
"babel-messages": "7.0.0-alpha.15",
"babel-template": "7.0.0-alpha.15",
"babel-traverse": "7.0.0-alpha.15",
"babel-types": "7.0.0-alpha.15",
"babylon": "7.0.0-beta.15",
"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.10",
"babel-helper-transform-fixture-test-runner": "7.0.0-alpha.11",
"babel-polyfill": "7.0.0-alpha.9",
"babel-register": "7.0.0-alpha.11"
"babel-helper-transform-fixture-test-runner": "7.0.0-alpha.15",
"babel-register": "7.0.0-alpha.15"
}
}

View File

@@ -7,14 +7,14 @@ import micromatch from "micromatch";
import { findConfigs, loadConfig } from "./loading/files";
type ConfigItem = {
type: "options"|"arguments",
type: "options" | "arguments",
options: {},
dirname: string,
alias: string,
loc: string,
};
export default function buildConfigChain(opts: {}): Array<ConfigItem>|null {
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");
}
@@ -44,9 +44,9 @@ export default function buildConfigChain(opts: {}): Array<ConfigItem>|null {
}
class ConfigChainBuilder {
filename: string|null;
filename: string | null;
configs: Array<ConfigItem>;
possibleDirs: null|Array<string>;
possibleDirs: null | Array<string>;
constructor(filename) {
this.configs = [];
@@ -57,16 +57,14 @@ class ConfigChainBuilder {
/**
* Tests if a filename should be ignored based on "ignore" and "only" options.
*/
shouldIgnore(
ignore: mixed,
only: mixed,
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, ${JSON.stringify(ignore)} given`);
throw new Error(
`.ignore should be an array, ${JSON.stringify(ignore)} given`,
);
}
if (this.matchesPatterns(ignore, dirname)) return true;
@@ -74,7 +72,9 @@ class ConfigChainBuilder {
if (only) {
if (!Array.isArray(only)) {
throw new Error(`.only should be an array, ${JSON.stringify(only)} given`);
throw new Error(
`.only should be an array, ${JSON.stringify(only)} given`,
);
}
if (!this.matchesPatterns(only, dirname)) return true;
@@ -89,21 +89,27 @@ class ConfigChainBuilder {
*/
matchesPatterns(patterns: Array<mixed>, dirname: string) {
const filename = this.filename;
if (!filename) throw new Error("Assertion failure: .filename should always exist here");
if (!filename) {
throw new Error("Assertion failure: .filename should always exist here");
}
const res = [];
const strings = [];
const fns = [];
patterns.forEach((pattern) => {
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");
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 (res.some(re => re.test(filename))) return true;
if (fns.some(fn => fn(filename))) return true;
if (strings.length > 0) {
let possibleDirs = this.possibleDirs;
@@ -123,7 +129,7 @@ class ConfigChainBuilder {
}
}
const absolutePatterns = strings.map((pattern) => {
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);
@@ -131,7 +137,9 @@ class ConfigChainBuilder {
return (negate ? "!" : "") + path.resolve(dirname, pattern);
});
if (micromatch(possibleDirs, absolutePatterns, { nocase: true }).length > 0) {
if (
micromatch(possibleDirs, absolutePatterns, { nocase: true }).length > 0
) {
return true;
}
}
@@ -150,16 +158,16 @@ class ConfigChainBuilder {
});
}
mergeConfig({
type,
options: rawOpts,
alias,
dirname,
}) {
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(rawOpts.ignore || null, rawOpts.only || null, 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."): any), { code: "BABEL_IGNORED_FILE" });
throw Object.assign((new Error("This file has been ignored."): any), {
code: "BABEL_IGNORED_FILE",
});
}
const options = Object.assign({}, rawOpts);
@@ -168,13 +176,19 @@ class ConfigChainBuilder {
const envKey = getEnv();
if (rawOpts.env != null && (typeof rawOpts.env !== "object" || Array.isArray(rawOpts.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))) {
if (
envOpts != null &&
(typeof envOpts !== "object" || Array.isArray(envOpts))
) {
throw new Error(".env[...] block must be an object, null, or undefined");
}
@@ -196,11 +210,13 @@ class ConfigChainBuilder {
});
if (rawOpts.extends) {
if (typeof rawOpts.extends !== "string") throw new Error(".extends must be a string");
if (typeof rawOpts.extends !== "string") {
throw new Error(".extends must be a string");
}
const extendsConfig = loadConfig(rawOpts.extends, dirname);
const existingConfig = this.configs.some((config) => {
const existingConfig = this.configs.some(config => {
return config.alias === extendsConfig.filepath;
});
if (!existingConfig) {
@@ -214,4 +230,3 @@ class ConfigChainBuilder {
}
}
}

View File

@@ -13,7 +13,7 @@ type CacheConfiguratorObj = {
invalidate: <T>(handler: () => T) => T,
};
type CacheEntry<ResultT> = Array<[ ResultT, () => boolean ]>;
type CacheEntry<ResultT> = Array<[ResultT, () => boolean]>;
/**
* Given a function with a single argument, cache its results based on its argument and how it
@@ -22,7 +22,7 @@ type CacheEntry<ResultT> = Array<[ ResultT, () => boolean ]>;
export function makeStrongCache<ArgT, ResultT>(
handler: (ArgT, CacheConfigurator) => ResultT,
autoPermacache?: boolean,
): (ArgT) => ResultT {
): ArgT => ResultT {
return makeCachedFunction(new Map(), handler, autoPermacache);
}
@@ -34,22 +34,24 @@ export function makeStrongCache<ArgT, ResultT>(
export function makeWeakCache<ArgT: {}, ResultT>(
handler: (ArgT, CacheConfigurator) => ResultT,
autoPermacache?: boolean,
): (ArgT) => ResultT {
): ArgT => ResultT {
return makeCachedFunction(new WeakMap(), handler, autoPermacache);
}
type CacheMap<ArgT, ResultT> = Map<ArgT, CacheEntry<ResultT>>|WeakMap<ArgT, CacheEntry<ResultT>>;
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 {
): ArgT => ResultT {
return function cachedFunction(arg) {
let cachedValue: CacheEntry<ResultT>|void = callCache.get(arg);
let cachedValue: CacheEntry<ResultT> | void = callCache.get(arg);
if (cachedValue) {
for (const [ value, valid ] of cachedValue) {
for (const [value, valid] of cachedValue) {
if (valid()) return value;
}
}
@@ -64,55 +66,53 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
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"));
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],
];
cachedValue = [[value, () => true]];
} else if (result.invalidate) {
cachedValue = [
[value, result.valid],
];
cachedValue = [[value, result.valid]];
} else {
cachedValue = cachedValue || [];
cachedValue.push([ value, result.valid ]);
cachedValue.push([value, result.valid]);
}
callCache.set(arg, cachedValue);
}
@@ -121,7 +121,11 @@ function makeCachedFunction<ArgT, ResultT, Cache: CacheMap<ArgT, ResultT>>(
};
}
function makeCacheConfig(): { cache: CacheConfigurator, result: *, deactivate: () => void } {
function makeCacheConfig(): {
cache: CacheConfigurator,
result: *,
deactivate: () => void,
} {
const pairs = [];
const result = {
@@ -137,51 +141,80 @@ function makeCacheConfig(): { cache: CacheConfigurator, result: *, 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()");
const cache: CacheConfigurator = Object.assign(
(function cacheFn(val) {
if (typeof val === "boolean") {
if (val) cache.forever();
else cache.never();
return;
}
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;
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;
},
}: CacheConfiguratorObj));
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 };
}

View File

@@ -1,7 +1,5 @@
// @flow
export function getEnv(defaultValue: string = "development"): string {
return process.env.BABEL_ENV
|| process.env.NODE_ENV
|| defaultValue;
return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;
}

View File

@@ -5,13 +5,13 @@ 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: mixed): ResolvedConfig|null {
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");
}

View File

@@ -41,13 +41,16 @@ 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;
@@ -73,7 +76,9 @@ 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`);
}
return conf;
}
@@ -83,7 +88,9 @@ 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);
}
const readConfigJS = makeStrongCache((filepath, cache) => {
@@ -96,7 +103,10 @@ const readConfigJS = makeStrongCache((filepath, cache) => {
try {
// $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;
@@ -113,7 +123,9 @@ const readConfigJS = makeStrongCache((filepath, cache) => {
}
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 {
@@ -144,8 +156,12 @@ const readConfigFile = makeStaticFileCache((filepath, content) => {
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,
@@ -157,8 +173,8 @@ const readConfigFile = makeStaticFileCache((filepath, content) => {
const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
const ignore = content
.split("\n")
.map((line) => line.replace(/#(.*?)$/, "").trim())
.filter((line) => !!line);
.map(line => line.replace(/#(.*?)$/, "").trim())
.filter(line => !!line);
return {
filepath,
@@ -167,7 +183,7 @@ const readIgnoreConfig = makeStaticFileCache((filepath, content) => {
};
});
function makeStaticFileCache<T>(fn: (string, string) => T): (string) => T|null {
function makeStaticFileCache<T>(fn: (string, string) => T): string => T | null {
return makeStrongCache((filepath, cache) => {
if (cache.invalidate(() => fileMtime(filepath)) === null) {
cache.forever();
@@ -178,7 +194,7 @@ function makeStaticFileCache<T>(fn: (string, string) => T): (string) => T|null {
});
}
function fileMtime(filepath: string): number|null {
function fileMtime(filepath: string): number | null {
try {
return +fs.statSync(filepath).mtime;
} catch (e) {

View File

@@ -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, value: 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, value: 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, value: 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, value: 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`,
);
}

View File

@@ -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";

View File

@@ -15,17 +15,22 @@ 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 {
export function resolvePlugin(name: string, dirname: string): string | null {
return resolveStandardizedName("plugin", name, dirname);
}
export function resolvePreset(name: string, dirname: string): string|null {
export function resolvePreset(name: string, dirname: string): string | null {
return resolveStandardizedName("preset", name, dirname);
}
export function loadPlugin(name: string, dirname: string): { filepath: string, value: mixed } {
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}`);
if (!filepath) {
throw new Error(`Plugin ${name} not found relative to ${dirname}`);
}
return {
filepath,
@@ -33,9 +38,14 @@ export function loadPlugin(name: string, dirname: string): { filepath: string, v
};
}
export function loadPreset(name: string, dirname: string): { filepath: string, value: 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,
@@ -43,16 +53,23 @@ export function loadPreset(name: string, dirname: string): { filepath: string, v
};
}
export function loadParser(name: string, dirname: string): { filepath: string, value: Function } {
export function loadParser(
name: string,
dirname: string,
): { filepath: string, value: Function } {
const filepath = resolve.sync(name, { basedir: dirname });
const mod = requireModule(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`,
);
}
return {
@@ -61,16 +78,23 @@ export function loadParser(name: string, dirname: string): { filepath: string, v
};
}
export function loadGenerator(name: string, dirname: string): { filepath: string, value: Function } {
export function loadGenerator(
name: string,
dirname: string,
): { filepath: string, value: Function } {
const filepath = resolve.sync(name, { basedir: dirname });
const mod = requireModule(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`,
);
}
return {
@@ -79,24 +103,39 @@ export function loadGenerator(name: string, dirname: string): { filepath: string
};
}
function standardizeName(type: "plugin"|"preset", name: string) {
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, "");
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()) {
function resolveStandardizedName(
type: "plugin" | "preset",
name: string,
dirname: string = process.cwd(),
) {
const standardizedName = standardizeName(type, name);
try {
@@ -109,7 +148,7 @@ function resolveStandardizedName(type: "plugin"|"preset", name: string, dirname:
try {
resolve.sync(name, { basedir: dirname });
resolvedOriginal = true;
} catch (e2) { }
} catch (e2) {}
if (resolvedOriginal) {
// eslint-disable-next-line max-len
@@ -119,9 +158,11 @@ function resolveStandardizedName(type: "plugin"|"preset", name: string, dirname:
let resolvedBabel = false;
try {
resolve.sync(standardizeName(type, "@babel/" + name), { basedir: dirname });
resolve.sync(standardizeName(type, "@babel/" + name), {
basedir: dirname,
});
resolvedBabel = true;
} catch (e2) { }
} catch (e2) {}
if (resolvedBabel) {
// eslint-disable-next-line max-len
@@ -133,7 +174,7 @@ function resolveStandardizedName(type: "plugin"|"preset", name: string, dirname:
try {
resolve.sync(standardizeName(oppositeType, name), { basedir: dirname });
resolvedOppositeType = true;
} catch (e2) { }
} catch (e2) {}
if (resolvedOppositeType) {
// eslint-disable-next-line max-len

View File

@@ -11,14 +11,19 @@ import path from "path";
import traverse from "babel-traverse";
import clone from "lodash/clone";
import { loadPlugin, loadPreset, loadParser, loadGenerator } from "./loading/files";
import {
loadPlugin,
loadPreset,
loadParser,
loadGenerator,
} from "./loading/files";
type MergeOptions = {
+type: "arguments"|"options"|"preset",
+type: "arguments" | "options" | "preset",
options: {},
alias: string,
loc: string,
dirname: string
dirname: string,
};
const optionNames = new Set([
@@ -74,8 +79,8 @@ const ALLOWED_PLUGIN_KEYS = new Set([
export default function manageOptions(opts: {}): {
options: Object,
passes: Array<Array<[ Plugin, ?{} ]>>,
}|null {
passes: Array<Array<[Plugin, ?{}]>>,
} | null {
return new OptionManager().init(opts);
}
@@ -100,9 +105,12 @@ class OptionManager {
mergeOptions(config: MergeOptions, pass?: Array<[Plugin, ?{}]>) {
const result = loadConfig(config);
const plugins = result.plugins.map((descriptor) => loadPluginDescriptor(descriptor));
const presets = result.presets.map((descriptor) => loadPresetDescriptor(descriptor));
const plugins = result.plugins.map(descriptor =>
loadPluginDescriptor(descriptor),
);
const presets = result.presets.map(descriptor =>
loadPresetDescriptor(descriptor),
);
if (
config.options.passPerPreset != null &&
@@ -148,7 +156,8 @@ 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)) {
const filename = typeof opts.filename === "string" ? opts.filename : null;
const filename =
typeof opts.filename === "string" ? opts.filename : null;
e.message = `[BABEL] ${filename || "unknown"}: ${e.message}`;
}
@@ -160,9 +169,10 @@ class OptionManager {
// 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 }));
opts.presets = this.passes
.slice(1)
.filter(plugins => plugins.length > 0)
.map(plugins => ({ plugins }));
if (opts.inputSourceMap) {
opts.sourceMaps = true;
@@ -199,7 +209,7 @@ class OptionManager {
}
type BasicDescriptor = {
value: {}|Function,
value: {} | Function,
options: ?{},
dirname: string,
alias: string,
@@ -209,19 +219,28 @@ type BasicDescriptor = {
/**
* Load and validate the given config into a set of options, plugins, and presets.
*/
function loadConfig(config): {
function loadConfig(
config,
): {
options: {},
plugins: Array<BasicDescriptor>,
presets: Array<BasicDescriptor>,
} {
const options = normalizeOptions(config);
if (config.options.plugins != null && !Array.isArray(config.options.plugins)) {
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);
const { filepath, value, options } = normalizePair(
plugin,
loadPlugin,
config.dirname,
);
return {
alias: filepath || `${config.loc}$${index}`,
@@ -232,12 +251,19 @@ function loadConfig(config): {
};
});
if (config.options.presets != null && !Array.isArray(config.options.presets)) {
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);
const { filepath, value, options } = normalizePair(
preset,
loadPreset,
config.dirname,
);
return {
alias: filepath || `${config.loc}$${index}`,
@@ -255,7 +281,9 @@ function loadConfig(config): {
* 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 };
if (typeof descriptor.value !== "function") {
return { value: descriptor.value, descriptor };
}
const { value, options } = descriptor;
let item;
@@ -266,7 +294,9 @@ function loadDescriptor(descriptor, skipOptions) {
item = value(context, options, { dirname: descriptor.dirname });
}
} catch (e) {
if (descriptor.alias) e.message += ` (While processing: ${JSON.stringify(descriptor.alias)})`;
if (descriptor.alias) {
e.message += ` (While processing: ${JSON.stringify(descriptor.alias)})`;
}
throw e;
}
@@ -282,26 +312,37 @@ function loadDescriptor(descriptor, skipOptions) {
*/
const PLUGIN_CACHE = new WeakMap();
function loadPluginDescriptor(descriptor) {
if (descriptor.value instanceof Plugin) return [ descriptor.value, descriptor.options ];
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 */));
result = instantiatePlugin(
loadDescriptor(descriptor, true /* skipOptions */),
);
PLUGIN_CACHE.set(descriptor.value, result);
}
return [ result, descriptor.options];
return [result, descriptor.options];
}
function instantiatePlugin({ value: pluginObj, descriptor }) {
Object.keys(pluginObj).forEach((key) => {
Object.keys(pluginObj).forEach(key => {
if (!ALLOWED_PLUGIN_KEYS.has(key)) {
throw new Error(messages.get("pluginInvalidProperty", descriptor.alias, 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.");
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, {
@@ -325,8 +366,14 @@ function instantiatePlugin({ value: pluginObj, descriptor }) {
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]);
plugin.manipulateOptions = chain(
inherits.manipulateOptions,
plugin.manipulateOptions,
);
plugin.visitor = traverse.visitors.merge([
inherits.visitor,
plugin.visitor,
]);
}
return new Plugin(plugin, descriptor.alias);
@@ -371,10 +418,18 @@ function normalizeOptions(config) {
}
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.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) {
@@ -390,7 +445,10 @@ function normalizeOptions(config) {
// 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}`);
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.`;
@@ -402,12 +460,21 @@ function normalizeOptions(config) {
if (options.parserOpts && typeof options.parserOpts.parser === "string") {
options.parserOpts = Object.assign({}, options.parserOpts);
options.parserOpts.parser = loadParser(options.parserOpts.parser, config.dirname).value;
options.parserOpts.parser = loadParser(
options.parserOpts.parser,
config.dirname,
).value;
}
if (options.generatorOpts && typeof options.generatorOpts.generator === "string") {
if (
options.generatorOpts &&
typeof options.generatorOpts.generator === "string"
) {
options.generatorOpts = Object.assign({}, options.generatorOpts);
options.generatorOpts.generator = loadGenerator(options.generatorOpts.generator, config.dirname).value;
options.generatorOpts.generator = loadGenerator(
options.generatorOpts.generator,
config.dirname,
).value;
}
delete options.passPerPreset;
@@ -420,16 +487,22 @@ function normalizeOptions(config) {
/**
* Given a plugin/preset item, resolve it into a standard format.
*/
function normalizePair(pair: mixed, resolver, dirname): {
filepath: string|null,
value: {}|Function,
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))}.`);
throw new Error(
`Unexpected extra options ${JSON.stringify(pair.slice(2))}.`,
);
}
[value, options] = pair;
@@ -437,10 +510,7 @@ function normalizePair(pair: mixed, resolver, dirname): {
let filepath = null;
if (typeof value === "string") {
({
filepath,
value,
} = resolver(value, dirname));
({ filepath, value } = resolver(value, dirname));
}
if (!value) {
@@ -456,11 +526,15 @@ function normalizePair(pair: mixed, resolver, dirname): {
}
if (typeof value !== "object" && typeof value !== "function") {
throw new Error(`Unsupported format: ${typeof value}. Expected an object or a 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");
throw new Error(
"Plugin/Preset options must be an object, null, or undefined",
);
}
return { filepath, value, options };

View File

@@ -5,8 +5,13 @@ export default class Plugin {
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.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");

View File

@@ -2,52 +2,58 @@
/* 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",
},
};

View File

@@ -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", ".mjs"]);
export const DEFAULT_EXTENSIONS = Object.freeze([
".js",
".jsx",
".es6",
".es",
".mjs",
]);

View File

@@ -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);
};

View File

@@ -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";
@@ -45,7 +45,7 @@ export default class File extends Store {
// passed babel-core's export object, which loads this file, and this 'loadConfig' loading plugins.
INTERNAL_PLUGINS = loadConfig({
babelrc: false,
plugins: [ blockHoistPlugin ],
plugins: [blockHoistPlugin],
}).passes[0];
}
@@ -61,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);
}
@@ -150,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, "");
}
@@ -172,17 +172,25 @@ 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 {
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 = [];
@@ -222,7 +230,9 @@ 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;
@@ -257,7 +267,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]);
@@ -270,7 +282,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);
@@ -280,7 +296,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.";
@@ -308,7 +325,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,
@@ -318,10 +335,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,
});
@@ -385,15 +405,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);
}
@@ -401,16 +421,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();
@@ -428,11 +451,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;
}
@@ -524,8 +553,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;

View File

@@ -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();

View File

@@ -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,126 +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.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/
).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) {
@@ -201,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
@@ -230,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"),
],
};
},
@@ -248,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
@@ -264,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() {
@@ -279,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)),
);
},
},
};
@@ -290,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"],
@@ -610,7 +713,7 @@ describe("api", function () {
]);
});
it("only option", function () {
it("only option", function() {
return Promise.all([
transformAsync("", {
only: ["/foo"],
@@ -649,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 },
@@ -675,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: {
@@ -685,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: {
@@ -696,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);
});

View File

@@ -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);

View File

@@ -27,7 +27,6 @@ describe("caching API", () => {
return { arg, count: count++ };
});
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
assert.equal(fn("one"), fn("one"));
@@ -210,48 +209,97 @@ describe("caching API", () => {
return { arg, val, val2, count: count++ };
});
assert.deepEqual(fn("one"), { arg: "one", val: "default", val2: "another", count: 0 });
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.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.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.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.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.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.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.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.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.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 */);
const fn = makeStrongCache(() => {}, false /* autoPermacache */);
assert.throws(() => fn(), /Error: Caching was left unconfigured./);
});
@@ -259,7 +307,7 @@ describe("caching API", () => {
it("should auto-permacache by default", () => {
let count = 0;
const fn = makeStrongCache((arg) => ({ arg, count: count++ }));
const fn = makeStrongCache(arg => ({ arg, count: count++ }));
assert.deepEqual(fn("one"), { arg: "one", count: 0 });
assert.equal(fn("one"), fn("one"));
@@ -333,7 +381,10 @@ describe("caching API", () => {
it("should throw if you configure .forever after exiting", () => {
const fn = makeStrongCache((arg, cache) => cache);
assert.throws(() => fn().forever(), /Cannot change caching after evaluation/);
assert.throws(
() => fn().forever(),
/Cannot change caching after evaluation/,
);
});
it("should throw if you configure .never after exiting", () => {
@@ -345,12 +396,18 @@ describe("caching API", () => {
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/);
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/);
assert.throws(
() => fn().invalidate(() => null),
/Cannot change caching after evaluation/,
);
});
});

View File

@@ -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,7 +26,7 @@ describe("buildConfigChain", function () {
delete process.env.NODE_ENV;
});
afterEach(function () {
afterEach(function() {
process.env.BABEL_ENV = oldBabelEnv;
process.env.NODE_ENV = oldNodeEnv;
});
@@ -52,7 +52,7 @@ describe("buildConfigChain", function () {
});
});
it("dir1", function () {
it("dir1", function() {
const chain = buildConfigChain({
filename: fixture("dir1", "src.js"),
});
@@ -61,9 +61,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"extended",
],
plugins: ["extended"],
},
alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"),
@@ -72,9 +70,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"root",
],
plugins: ["root"],
},
alias: fixture(".babelrc"),
loc: fixture(".babelrc"),
@@ -83,9 +79,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -105,7 +99,7 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected);
});
it("dir2", function () {
it("dir2", function() {
const chain = buildConfigChain({
filename: fixture("dir2", "src.js"),
});
@@ -114,9 +108,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -125,9 +117,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"dir2",
],
plugins: ["dir2"],
},
alias: fixture("dir2", ".babelrc"),
loc: fixture("dir2", ".babelrc"),
@@ -147,7 +137,7 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected);
});
it("dir3", function () {
it("dir3", function() {
const chain = buildConfigChain({
filename: fixture("dir3", "src.js"),
});
@@ -156,9 +146,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"extended",
],
plugins: ["extended"],
},
alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"),
@@ -167,9 +155,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"root",
],
plugins: ["root"],
},
alias: fixture(".babelrc"),
loc: fixture(".babelrc"),
@@ -178,9 +164,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -200,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"),
});
@@ -209,9 +193,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -220,9 +202,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"env-base",
],
plugins: ["env-base"],
},
alias: fixture("env", ".babelrc"),
loc: fixture("env", ".babelrc"),
@@ -242,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({
@@ -253,9 +233,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -264,9 +242,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"env-base",
],
plugins: ["env-base"],
},
alias: fixture("env", ".babelrc"),
loc: fixture("env", ".babelrc"),
@@ -275,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"),
@@ -297,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";
@@ -309,9 +283,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -320,9 +292,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"env-base",
],
plugins: ["env-base"],
},
alias: fixture("env", ".babelrc"),
loc: fixture("env", ".babelrc"),
@@ -331,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"),
@@ -353,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({
@@ -394,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"),
});
@@ -403,9 +370,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -414,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"),
@@ -437,7 +399,7 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected);
});
it("js-config-function", function () {
it("js-config-function", function() {
const chain = buildConfigChain({
filename: fixture("js-config-function", "src.js"),
});
@@ -446,9 +408,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -477,7 +437,7 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected);
});
it("js-config-default - should read transpiled export default", function () {
it("js-config-default - should read transpiled export default", function() {
const chain = buildConfigChain({
filename: fixture("js-config-default", "src.js"),
});
@@ -486,9 +446,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -497,10 +455,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"foo",
"bar",
],
plugins: ["foo", "bar"],
},
alias: fixture("js-config-default", ".babelrc.js"),
loc: fixture("js-config-default", ".babelrc.js"),
@@ -519,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"),
});
@@ -528,9 +483,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -539,9 +492,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
plugins: [
"extended",
],
plugins: ["extended"],
},
alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"),
@@ -550,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"),
@@ -573,50 +521,49 @@ 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 () {
const chain = buildConfigChain({
filename: fixture("json-pkg-config-no-babel", "src.js"),
});
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",
],
const expected = [
{
type: "options",
options: {
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
dirname: fixture(),
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
dirname: fixture(),
},
{
type: "options",
options: {
plugins: [
"json",
],
{
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"),
},
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"),
{
type: "arguments",
options: {
filename: fixture("json-pkg-config-no-babel", "src.js"),
},
alias: "base",
loc: "base",
dirname: base(),
},
alias: "base",
loc: "base",
dirname: base(),
},
];
];
assert.deepEqual(chain, expected);
});
assert.deepEqual(chain, expected);
},
);
it("should not ignore file matching negated file pattern", function () {
it("should not ignore file matching negated file pattern", function() {
const chain = buildConfigChain({
filename: fixture("ignore-negate", "src.js"),
});
@@ -625,9 +572,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -636,10 +581,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"*",
"!src.js",
],
ignore: ["*", "!src.js"],
},
alias: fixture("ignore-negate", ".babelrc"),
loc: fixture("ignore-negate", ".babelrc"),
@@ -665,7 +607,7 @@ describe("buildConfigChain", function () {
assert.equal(chain2, null);
});
it("should not ignore file matching negated folder pattern", function () {
it("should not ignore file matching negated folder pattern", function() {
const chain = buildConfigChain({
filename: fixture("ignore-negate-folder", "folder", "src.js"),
});
@@ -674,9 +616,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"root-ignore",
],
ignore: ["root-ignore"],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
@@ -685,10 +625,7 @@ describe("buildConfigChain", function () {
{
type: "options",
options: {
ignore: [
"*",
"!folder",
],
ignore: ["*", "!folder"],
},
alias: fixture("ignore-negate-folder", ".babelrc"),
loc: fixture("ignore-negate-folder", ".babelrc"),
@@ -714,83 +651,71 @@ describe("buildConfigChain", function () {
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(
"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/);
});
});

View File

@@ -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],
});
});

View File

@@ -1,3 +1,2 @@
export function foo() {}
export function bar() {}
export function bar() {}

View File

@@ -3,13 +3,14 @@ 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));
}
return Foo;
}(Bar);
}(Bar);

View File

@@ -1,5 +1,4 @@
function test() {
var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "hi";
return x;
}

View File

@@ -2,30 +2,10 @@ function foo() {
var input = ['a', 'b', 'c'];
var output = {};
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = input[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var c = _step.value;
var name = c;
output[name] = name;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
for (var _i = 0; _i < input.length; _i++) {
var c = input[_i];
var name = c;
output[name] = name;
}
return output;

View File

@@ -2,7 +2,7 @@ function f() {
let g = async () => {
this;
};
};
}
class Class {
async m() {

View File

@@ -10,7 +10,7 @@ function f() {
return _ref.apply(this, arguments);
};
}();
};
}
class Class {
m() {
@@ -28,4 +28,5 @@ class Class {
}();
})();
}
}
}

View File

@@ -3,5 +3,4 @@
var _values = values;
value = _values[fieldName];
rest = babelHelpers.objectWithoutProperties(_values, [fieldName]);
var error = void 0;

View File

@@ -1,4 +1,2 @@
#!/usr/bin/env node
foobar();
foobar();

View File

@@ -6,55 +6,51 @@ describe("option-manager", () => {
it("throws for babel 5 plugin", () => {
return assert.throws(() => {
manageOptions({
plugins: [
({ Plugin }) => new Plugin("object-assign", {}),
],
plugins: [({ Plugin }) => new Plugin("object-assign", {})],
});
}, /Babel 5 plugin is being run with Babel 6/);
});
describe("mergeOptions", () => {
it("throws for removed babel 5 options", () => {
return assert.throws(
() => {
manageOptions({
"randomOption": true,
});
},
/Unknown option: base.randomOption/
);
return assert.throws(() => {
manageOptions({
randomOption: true,
});
}, /Unknown option: base.randomOption/);
});
it("throws for removed babel 5 options", () => {
return assert.throws(
() => {
manageOptions({
"auxiliaryComment": true,
"blacklist": true,
auxiliaryComment: true,
blacklist: true,
});
},
// eslint-disable-next-line max-len
/Using removed Babel 5 option: base.auxiliaryComment - Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`/
/Using removed Babel 5 option: base.auxiliaryComment - Use `auxiliaryCommentBefore` or `auxiliaryCommentAfter`/,
);
});
it("throws for resolved but erroring preset", () => {
return assert.throws(
() => {
manageOptions({
"presets": [path.join(__dirname, "fixtures/option-manager/not-a-preset")],
});
},
/While processing: .*option-manager(?:\/|\\\\)not-a-preset\.js/
);
return assert.throws(() => {
manageOptions({
presets: [
path.join(__dirname, "fixtures/option-manager/not-a-preset"),
],
});
}, /While processing: .*option-manager(?:\/|\\\\)not-a-preset\.js/);
});
});
describe("presets", function () {
describe("presets", function() {
function presetTest(name) {
it(name, function () {
it(name, function() {
const { options, passes } = manageOptions({
"presets": [path.join(__dirname, "fixtures/option-manager/presets", name)],
presets: [
path.join(__dirname, "fixtures/option-manager/presets", name),
],
});
assert.equal(true, Array.isArray(options.plugins));
@@ -65,10 +61,16 @@ describe("option-manager", () => {
}
function presetThrowsTest(name, msg) {
it(name, function () {
assert.throws(() => manageOptions({
"presets": [path.join(__dirname, "fixtures/option-manager/presets", name)],
}), msg);
it(name, function() {
assert.throws(
() =>
manageOptions({
presets: [
path.join(__dirname, "fixtures/option-manager/presets", name),
],
}),
msg,
);
});
}
@@ -77,7 +79,10 @@ describe("option-manager", () => {
presetTest("es2015_default_function");
presetTest("es2015_default_object");
presetThrowsTest("es2015_named", /Must export a default export when using ES6 modules/);
presetThrowsTest(
"es2015_named",
/Must export a default export when using ES6 modules/,
);
presetThrowsTest("es2015_invalid", /Unsupported format: string/);
presetThrowsTest("es5_invalid", /Unsupported format: string/);
});

View File

@@ -2,152 +2,172 @@ import { transform } from "../lib/index";
import Plugin from "../lib/config/plugin";
import chai from "chai";
describe("traversal path", function () {
it("replaceWithSourceString", function () {
describe("traversal path", function() {
it("replaceWithSourceString", function() {
const expectCode = "function foo() {}";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
FunctionDeclaration: function (path) {
path.replaceWithSourceString("console.whatever()");
plugins: [
new Plugin({
visitor: {
FunctionDeclaration: function(path) {
path.replaceWithSourceString("console.whatever()");
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("console.whatever();");
});
it("replaceWith (arrow expression body to block statement body)", function () {
it("replaceWith (arrow expression body to block statement body)", function() {
const expectCode = "var fn = () => true;";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
ArrowFunctionExpression: function (path) {
path.get("body").replaceWith({
type: "BlockStatement",
body: [{
type: "ReturnStatement",
argument: {
type: "BooleanLiteral",
value: true,
},
}],
});
plugins: [
new Plugin({
visitor: {
ArrowFunctionExpression: function(path) {
path.get("body").replaceWith({
type: "BlockStatement",
body: [
{
type: "ReturnStatement",
argument: {
type: "BooleanLiteral",
value: true,
},
},
],
});
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("var fn = () => {\n return true;\n};");
});
it("replaceWith (arrow block statement body to expression body)", function () {
it("replaceWith (arrow block statement body to expression body)", function() {
const expectCode = "var fn = () => { return true; }";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
ArrowFunctionExpression: function (path) {
path.get("body").replaceWith({
type: "BooleanLiteral",
value: true,
});
plugins: [
new Plugin({
visitor: {
ArrowFunctionExpression: function(path) {
path.get("body").replaceWith({
type: "BooleanLiteral",
value: true,
});
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("var fn = () => true;");
});
it("replaceWith (for-in left expression to variable declaration)", function () {
it("replaceWith (for-in left expression to variable declaration)", function() {
const expectCode = "for (KEY in right);";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
ForInStatement: function (path) {
path.get("left").replaceWith({
type: "VariableDeclaration",
kind: "var",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "KEY",
},
}],
});
plugins: [
new Plugin({
visitor: {
ForInStatement: function(path) {
path.get("left").replaceWith({
type: "VariableDeclaration",
kind: "var",
declarations: [
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "KEY",
},
},
],
});
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("for (var KEY in right);");
});
it("replaceWith (for-in left variable declaration to expression)", function () {
it("replaceWith (for-in left variable declaration to expression)", function() {
const expectCode = "for (var KEY in right);";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
ForInStatement: function (path) {
path.get("left").replaceWith({
type: "Identifier",
name: "KEY",
});
plugins: [
new Plugin({
visitor: {
ForInStatement: function(path) {
path.get("left").replaceWith({
type: "Identifier",
name: "KEY",
});
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("for (KEY in right);");
});
it("replaceWith (for-loop left expression to variable declaration)", function () {
it("replaceWith (for-loop left expression to variable declaration)", function() {
const expectCode = "for (KEY;;);";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
ForStatement: function (path) {
path.get("init").replaceWith({
type: "VariableDeclaration",
kind: "var",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "KEY",
},
}],
});
plugins: [
new Plugin({
visitor: {
ForStatement: function(path) {
path.get("init").replaceWith({
type: "VariableDeclaration",
kind: "var",
declarations: [
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "KEY",
},
},
],
});
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("for (var KEY;;);");
});
it("replaceWith (for-loop left variable declaration to expression)", function () {
it("replaceWith (for-loop left variable declaration to expression)", function() {
const expectCode = "for (var KEY;;);";
const actualCode = transform(expectCode, {
plugins: [new Plugin({
visitor: {
ForStatement: function (path) {
path.get("init").replaceWith({
type: "Identifier",
name: "KEY",
});
plugins: [
new Plugin({
visitor: {
ForStatement: function(path) {
path.get("init").replaceWith({
type: "Identifier",
name: "KEY",
});
},
},
},
})],
}),
],
}).code;
chai.expect(actualCode).to.be.equal("for (KEY;;);");

View File

@@ -2,7 +2,7 @@ import assert from "assert";
import * as babel from "../lib/index";
import path from "path";
describe("addon resolution", function () {
describe("addon resolution", function() {
const base = path.join(__dirname, "fixtures", "resolution");
beforeEach(function() {
@@ -20,9 +20,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"module:preset",
],
presets: ["module:preset"],
});
});
@@ -32,9 +30,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"module:plugin",
],
plugins: ["module:plugin"],
});
});
@@ -44,9 +40,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"mod",
],
presets: ["mod"],
});
});
@@ -56,9 +50,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"mod",
],
plugins: ["mod"],
});
});
@@ -68,9 +60,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"babel-preset-mod",
],
presets: ["babel-preset-mod"],
});
});
@@ -80,9 +70,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"babel-plugin-mod",
],
plugins: ["babel-plugin-mod"],
});
});
@@ -92,9 +80,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"@babel/foo",
],
presets: ["@babel/foo"],
});
});
@@ -104,9 +90,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"@babel/foo",
],
plugins: ["@babel/foo"],
});
});
@@ -116,9 +100,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"@babel/preset-foo",
],
presets: ["@babel/preset-foo"],
});
});
@@ -128,9 +110,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"@babel/plugin-foo",
],
plugins: ["@babel/plugin-foo"],
});
});
@@ -140,9 +120,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"@foo/mod",
],
presets: ["@foo/mod"],
});
});
@@ -152,9 +130,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"@foo/mod",
],
plugins: ["@foo/mod"],
});
});
@@ -164,9 +140,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"@foo/babel-preset-mod",
],
presets: ["@foo/babel-preset-mod"],
});
});
@@ -176,9 +150,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"@foo/babel-plugin-mod",
],
plugins: ["@foo/babel-plugin-mod"],
});
});
@@ -188,9 +160,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"./dir/preset.js",
],
presets: ["./dir/preset.js"],
});
});
@@ -200,9 +170,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"./dir/plugin.js",
],
plugins: ["./dir/plugin.js"],
});
});
@@ -212,9 +180,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"mod/preset",
],
presets: ["mod/preset"],
});
});
@@ -224,9 +190,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"mod/plugin",
],
plugins: ["mod/plugin"],
});
});
@@ -236,9 +200,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"@foo/mod/preset",
],
presets: ["@foo/mod/preset"],
});
});
@@ -248,9 +210,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"@foo/mod/plugin",
],
plugins: ["@foo/mod/plugin"],
});
});
@@ -260,9 +220,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"@babel/mod/preset",
],
presets: ["@babel/mod/preset"],
});
});
@@ -272,9 +230,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"@babel/mod/plugin",
],
plugins: ["@babel/mod/plugin"],
});
});
@@ -285,9 +241,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"foo",
],
presets: ["foo"],
});
// eslint-disable-next-line max-len
}, /Cannot find module 'babel-preset-foo'.*\n- If you want to resolve "foo", use "module:foo"/);
@@ -300,9 +254,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"foo",
],
plugins: ["foo"],
});
// eslint-disable-next-line max-len
}, /Cannot find module 'babel-plugin-foo'.*\n- If you want to resolve "foo", use "module:foo"/);
@@ -315,9 +267,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"foo",
],
presets: ["foo"],
});
// eslint-disable-next-line max-len
}, /Cannot find module 'babel-preset-foo'.*\n- Did you mean "@babel\/foo"\?/);
@@ -330,9 +280,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"foo",
],
plugins: ["foo"],
});
// eslint-disable-next-line max-len
}, /Cannot find module 'babel-plugin-foo'.*\n- Did you mean "@babel\/foo"\?/);
@@ -345,9 +293,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"testplugin",
],
presets: ["testplugin"],
});
// eslint-disable-next-line max-len
}, /Cannot find module 'babel-preset-testplugin'.*\n- Did you accidentally pass a preset as a plugin\?/);
@@ -360,9 +306,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"testpreset",
],
plugins: ["testpreset"],
});
// eslint-disable-next-line max-len
}, /Cannot find module 'babel-plugin-testpreset'.*\n- Did you accidentally pass a plugin as a preset\?/);
@@ -375,9 +319,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
presets: [
"foo",
],
presets: ["foo"],
});
}, /Cannot find module 'babel-preset-foo'/);
});
@@ -389,9 +331,7 @@ describe("addon resolution", function () {
babel.transform("", {
filename: "filename.js",
babelrc: false,
plugins: [
"foo",
],
plugins: ["foo"],
});
}, /Cannot find module 'babel-plugin-foo'/);
});

View File

@@ -1,6 +1,6 @@
{
"name": "babel-generator",
"version": "7.0.0-alpha.11",
"version": "7.0.0-alpha.15",
"description": "Turns an AST into code.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -11,16 +11,15 @@
"lib"
],
"dependencies": {
"babel-messages": "7.0.0-alpha.10",
"babel-types": "7.0.0-alpha.11",
"detect-indent": "^4.0.0",
"babel-messages": "7.0.0-alpha.15",
"babel-types": "7.0.0-alpha.15",
"jsesc": "^1.3.0",
"lodash": "^4.2.0",
"source-map": "^0.5.0",
"trim-right": "^1.0.1"
},
"devDependencies": {
"babel-helper-fixtures": "7.0.0-alpha.10",
"babylon": "^7.0.0-beta.12"
"babel-helper-fixtures": "7.0.0-alpha.15",
"babylon": "^7.0.0-beta.15"
}
}

View File

@@ -54,7 +54,7 @@ export default class Buffer {
configurable: true,
enumerable: true,
get() {
return this.map = map.get();
return (this.map = map.get());
},
set(value) {
Object.defineProperty(this, "map", { value, writable: true });
@@ -81,7 +81,11 @@ export default class Buffer {
queue(str: string): void {
// Drop trailing spaces when a newline is inserted.
if (str === "\n") while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) this._queue.shift();
if (str === "\n") {
while (this._queue.length > 0 && SPACES_RE.test(this._queue[0][0])) {
this._queue.shift();
}
}
const { line, column, filename, identifierName } = this._sourcePosition;
this._queue.unshift([str, line, column, identifierName, filename]);
@@ -89,13 +93,26 @@ export default class Buffer {
_flush(): void {
let item;
while (item = this._queue.pop()) this._append(...item);
while ((item = this._queue.pop())) this._append(...item);
}
_append(str: string, line: number, column: number, identifierName: ?string, filename: ?string): void {
_append(
str: string,
line: number,
column: number,
identifierName: ?string,
filename: ?string,
): void {
// If there the line is ending, adding a new mapping marker is redundant
if (this._map && str[0] !== "\n") {
this._map.mark(this._position.line, this._position.column, line, column, identifierName, filename);
this._map.mark(
this._position.line,
this._position.column,
line,
column,
identifierName,
filename,
);
}
this._buf.push(str);
@@ -112,11 +129,15 @@ export default class Buffer {
}
removeTrailingNewline(): void {
if (this._queue.length > 0 && this._queue[0][0] === "\n") this._queue.shift();
if (this._queue.length > 0 && this._queue[0][0] === "\n") {
this._queue.shift();
}
}
removeLastSemicolon(): void {
if (this._queue.length > 0 && this._queue[0][0] === ";") this._queue.shift();
if (this._queue.length > 0 && this._queue[0][0] === ";") {
this._queue.shift();
}
}
endsWith(suffix: string): boolean {
@@ -133,7 +154,8 @@ export default class Buffer {
return last === suffix;
}
const end = this._last + this._queue.reduce((acc, item) => item[0] + acc, "");
const end =
this._last + this._queue.reduce((acc, item) => item[0] + acc, "");
if (suffix.length <= end.length) {
return end.slice(-suffix.length) === suffix;
}
@@ -157,10 +179,10 @@ export default class Buffer {
const pos = loc ? loc[prop] : null;
this._sourcePosition.identifierName = loc && loc.identifierName || null;
this._sourcePosition.identifierName = (loc && loc.identifierName) || null;
this._sourcePosition.line = pos ? pos.line : null;
this._sourcePosition.column = pos ? pos.column : null;
this._sourcePosition.filename = loc && loc.filename || null;
this._sourcePosition.filename = (loc && loc.filename) || null;
}
/**
@@ -190,7 +212,9 @@ export default class Buffer {
const extra = this._queue.reduce((acc, item) => item[0] + acc, "");
const lastIndex = extra.lastIndexOf("\n");
return lastIndex === -1 ? this._position.column + extra.length : (extra.length - 1 - lastIndex);
return lastIndex === -1
? this._position.column + extra.length
: extra.length - 1 - lastIndex;
}
getCurrentLine(): number {

View File

@@ -1,9 +1,12 @@
import * as t from "babel-types";
import * as n from "../node";
export function UnaryExpression(node: Object) {
if (node.operator === "void" || node.operator === "delete" || node.operator === "typeof") {
if (
node.operator === "void" ||
node.operator === "delete" ||
node.operator === "typeof"
) {
this.word(node.operator);
this.space();
} else {
@@ -51,11 +54,20 @@ export function NewExpression(node: Object, parent: Object) {
this.word("new");
this.space();
this.print(node.callee, node);
if (node.arguments.length === 0 && this.format.minified &&
!t.isCallExpression(parent, { callee: node }) &&
!t.isMemberExpression(parent) &&
!t.isNewExpression(parent)) return;
if (
this.format.minified &&
node.arguments.length === 0 &&
!node.optional &&
!t.isCallExpression(parent, { callee: node }) &&
!t.isMemberExpression(parent) &&
!t.isNewExpression(parent)
) {
return;
}
if (node.optional) {
this.token("?.");
}
this.token("(");
this.printList(node.arguments, node);
this.token(")");
@@ -89,6 +101,9 @@ function commaSeparatorNewline() {
export function CallExpression(node: Object) {
this.print(node.callee, node);
if (node.optional) {
this.token("?.");
}
this.token("(");
const isPrettyCall = node._prettyCall;
@@ -115,7 +130,7 @@ export function Import() {
}
function buildYieldAwait(keyword: string) {
return function (node: Object) {
return function(node: Object) {
this.word(keyword);
if (node.delegate) {
@@ -156,8 +171,10 @@ export function AssignmentPattern(node: Object) {
export function AssignmentExpression(node: Object, parent: Object) {
// Somewhere inside a for statement `init` node but doesn't usually
// needs a paren except for `in` expressions: `for (a in b ? a : b;;)`
const parens = this.inForStatementInitCounter && node.operator === "in" &&
!n.needsParens(node, parent);
const parens =
this.inForStatementInitCounter &&
node.operator === "in" &&
!n.needsParens(node, parent);
if (parens) {
this.token("(");
@@ -203,12 +220,17 @@ export function MemberExpression(node: Object) {
computed = true;
}
if (node.optional) {
this.token("?.");
}
if (computed) {
this.token("[");
this.print(node.property, node);
this.token("]");
} else {
this.token(".");
if (!node.optional) {
this.token(".");
}
this.print(node.property, node);
}
}

View File

@@ -1,3 +1,5 @@
import * as t from "babel-types";
export function AnyTypeAnnotation() {
this.word("any");
}
@@ -20,17 +22,21 @@ export function NullLiteralTypeAnnotation() {
this.word("null");
}
export function DeclareClass(node: Object) {
this.word("declare");
this.space();
export function DeclareClass(node: Object, parent: Object) {
if (!t.isDeclareExportDeclaration(parent)) {
this.word("declare");
this.space();
}
this.word("class");
this.space();
this._interfaceish(node);
}
export function DeclareFunction(node: Object) {
this.word("declare");
this.space();
export function DeclareFunction(node: Object, parent: Object) {
if (!t.isDeclareExportDeclaration(parent)) {
this.word("declare");
this.space();
}
this.word("function");
this.space();
this.print(node.id, node);
@@ -69,9 +75,11 @@ export function DeclareTypeAlias(node: Object) {
this.TypeAlias(node);
}
export function DeclareVariable(node: Object) {
this.word("declare");
this.space();
export function DeclareVariable(node: Object, parent: Object) {
if (!t.isDeclareExportDeclaration(parent)) {
this.word("declare");
this.space();
}
this.word("var");
this.space();
this.print(node.id, node);
@@ -79,6 +87,57 @@ export function DeclareVariable(node: Object) {
this.semicolon();
}
export function DeclareExportDeclaration(node: Object) {
this.word("declare");
this.space();
this.word("export");
this.space();
if (node.default) {
this.word("default");
this.space();
}
FlowExportDeclaration.apply(this, arguments);
}
export function DeclareExportAllDeclaration(node: Object) {
this.word("declare");
this.space();
this.word("export");
this.space();
this.token("*");
this.space();
this.word("from");
this.space();
this.print(node.source, node);
this.semicolon();
}
function FlowExportDeclaration(node: Object) {
if (node.declaration) {
const declar = node.declaration;
this.print(declar, node);
if (!t.isStatement(declar)) this.semicolon();
} else {
this.token("{");
if (node.specifiers.length) {
this.space();
this.printList(node.specifiers, node);
this.space();
}
this.token("}");
if (node.source) {
this.space();
this.word("from");
this.space();
this.print(node.source, node);
}
this.semicolon();
}
}
export function ExistsTypeAnnotation() {
this.token("*");
}
@@ -100,7 +159,10 @@ export function FunctionTypeAnnotation(node: Object, parent: Object) {
this.token(")");
// this node type is overloaded, not sure why but it makes it EXTREMELY annoying
if (parent.type === "ObjectTypeCallProperty" || parent.type === "DeclareFunction") {
if (
parent.type === "ObjectTypeCallProperty" ||
parent.type === "DeclareFunction"
) {
this.token(":");
} else {
this.space();
@@ -124,7 +186,10 @@ export function InterfaceExtends(node: Object) {
this.print(node.typeParameters, node);
}
export { InterfaceExtends as ClassImplements, InterfaceExtends as GenericTypeAnnotation };
export {
InterfaceExtends as ClassImplements,
InterfaceExtends as GenericTypeAnnotation,
};
export function _interfaceish(node: Object) {
this.print(node.id, node);
@@ -264,7 +329,11 @@ export function ObjectTypeAnnotation(node: Object) {
this.token("{");
}
const props = node.properties.concat(node.callProperties, node.indexers);
// TODO: remove the array fallbacks and instead enforce the types to require an array
const props = node.properties.concat(
node.callProperties || [],
node.indexers || [],
);
if (props.length) {
this.space();

View File

@@ -4,7 +4,7 @@ export function _params(node: Object) {
this.print(node.typeParameters, node);
this.token("(");
this.printList(node.params, node, {
iterator: (node) => {
iterator: node => {
if (node.optional) this.token("?");
this.print(node.typeAnnotation, node);
},
@@ -79,7 +79,11 @@ export function ArrowFunctionExpression(node: Object) {
const firstParam = node.params[0];
if (node.params.length === 1 && t.isIdentifier(firstParam) && !hasTypes(node, firstParam)) {
if (
node.params.length === 1 &&
t.isIdentifier(firstParam) &&
!hasTypes(node, firstParam)
) {
this.print(firstParam, node);
} else {
this._params(node);
@@ -93,6 +97,11 @@ export function ArrowFunctionExpression(node: Object) {
}
function hasTypes(node, param) {
return node.typeParameters || node.returnType || param.typeAnnotation || param.optional ||
param.trailingComments;
return (
node.typeParameters ||
node.returnType ||
param.typeAnnotation ||
param.optional ||
param.trailingComments
);
}

View File

@@ -91,7 +91,10 @@ function ExportDeclaration(node: Object) {
let hasSpecial = false;
while (true) {
const first = specifiers[0];
if (t.isExportDefaultSpecifier(first) || t.isExportNamespaceSpecifier(first)) {
if (
t.isExportDefaultSpecifier(first) ||
t.isExportNamespaceSpecifier(first)
) {
hasSpecial = true;
this.print(specifiers.shift(), node);
if (specifiers.length) {
@@ -138,7 +141,10 @@ export function ImportDeclaration(node: Object) {
// print "special" specifiers first
while (true) {
const first = specifiers[0];
if (t.isImportDefaultSpecifier(first) || t.isImportNamespaceSpecifier(first)) {
if (
t.isImportDefaultSpecifier(first) ||
t.isImportNamespaceSpecifier(first)
) {
this.print(specifiers.shift(), node);
if (specifiers.length) {
this.token(",");

View File

@@ -17,7 +17,8 @@ export function IfStatement(node: Object) {
this.token(")");
this.space();
const needsBlock = node.alternate && t.isIfStatement(getLastStatement(node.consequent));
const needsBlock =
node.alternate && t.isIfStatement(getLastStatement(node.consequent));
if (needsBlock) {
this.token("{");
this.newline();
@@ -80,8 +81,8 @@ export function WhileStatement(node: Object) {
this.printBlock(node);
}
const buildForXStatement = function (op) {
return function (node: Object) {
const buildForXStatement = function(op) {
return function(node: Object) {
this.word("for");
this.space();
if (op === "of" && node.await) {
@@ -116,7 +117,7 @@ export function DoWhileStatement(node: Object) {
}
function buildLabelStatement(prefix, key = "label") {
return function (node: Object) {
return function(node: Object) {
this.word(prefix);
const label = node[key];
@@ -261,7 +262,10 @@ export function VariableDeclaration(node: Object, parent: Object) {
let separator;
if (hasInits) {
separator = node.kind === "const" ? constDeclarationIndent : variableDeclarationIndent;
separator =
node.kind === "const"
? constDeclarationIndent
: variableDeclarationIndent;
}
//

View File

@@ -10,9 +10,7 @@ export function RestElement(node: Object) {
this.print(node.argument, node);
}
export {
RestElement as SpreadElement,
};
export { RestElement as SpreadElement };
export function ObjectExpression(node: Object) {
const props = node.properties;
@@ -45,8 +43,11 @@ export function ObjectProperty(node: Object) {
this.token("]");
} else {
// print `({ foo: foo = 5 } = {})` as `({ foo = 5 } = {});`
if (t.isAssignmentPattern(node.value) && t.isIdentifier(node.key) &&
node.key.name === node.value.left.name) {
if (
t.isAssignmentPattern(node.value) &&
t.isIdentifier(node.key) &&
node.key.name === node.value.left.name
) {
this.print(node.value, node);
return;
}
@@ -54,10 +55,12 @@ export function ObjectProperty(node: Object) {
this.print(node.key, node);
// shorthand!
if (node.shorthand &&
if (
node.shorthand &&
(t.isIdentifier(node.key) &&
t.isIdentifier(node.value) &&
node.key.name === node.value.name)) {
t.isIdentifier(node.value) &&
node.key.name === node.value.name)
) {
return;
}
}
@@ -111,7 +114,7 @@ export function NumericLiteral(node: Object) {
const raw = this.getPossibleRaw(node);
const value = node.value + "";
if (raw == null) {
this.number(value); // normalize
this.number(value); // normalize
} else if (this.format.minified) {
this.number(raw.length < value.length ? raw : value);
} else {

View File

@@ -1,8 +1,6 @@
import detectIndent from "detect-indent";
import SourceMap from "./source-map";
import * as messages from "babel-messages";
import Printer from "./printer";
import type { Format } from "./printer";
import Printer, { type Format } from "./printer";
/**
* Babel's code generator, turns an ast into code, maintaining sourcemaps,
@@ -11,10 +9,9 @@ import type { Format } from "./printer";
class Generator extends Printer {
constructor(ast, opts = {}, code) {
const tokens = ast.tokens || [];
const format = normalizeOptions(code, opts, tokens);
const format = normalizeOptions(code, opts);
const map = opts.sourceMaps ? new SourceMap(opts, code) : null;
super(format, map, tokens);
super(format, map);
this.ast = ast;
}
@@ -39,13 +36,7 @@ class Generator extends Printer {
* - If `opts.compact = "auto"` and the code is over 500KB, `compact` will be set to `true`.
*/
function normalizeOptions(code, opts, tokens): Format {
let style = " ";
if (code && typeof code === "string") {
const indent = detectIndent(code).indent;
if (indent && indent !== " ") style = indent;
}
function normalizeOptions(code, opts): Format {
const format = {
auxiliaryCommentBefore: opts.auxiliaryCommentBefore,
auxiliaryCommentAfter: opts.auxiliaryCommentAfter,
@@ -56,11 +47,11 @@ function normalizeOptions(code, opts, tokens): Format {
compact: opts.compact,
minified: opts.minified,
concise: opts.concise,
quotes: findCommonStringDelimiter(code, tokens),
quotes: "double",
jsonCompatibleStrings: opts.jsonCompatibleStrings,
indent: {
adjustMultilineComment: true,
style: style,
style: " ",
base: 0,
},
};
@@ -68,17 +59,23 @@ function normalizeOptions(code, opts, tokens): Format {
if (format.minified) {
format.compact = true;
format.shouldPrintComment = format.shouldPrintComment || (() => format.comments);
format.shouldPrintComment =
format.shouldPrintComment || (() => format.comments);
} else {
format.shouldPrintComment = format.shouldPrintComment || ((value) => format.comments ||
(value.indexOf("@license") >= 0 || value.indexOf("@preserve") >= 0));
format.shouldPrintComment =
format.shouldPrintComment ||
(value =>
format.comments ||
(value.indexOf("@license") >= 0 || value.indexOf("@preserve") >= 0));
}
if (format.compact === "auto") {
format.compact = code.length > 500000; // 500KB
format.compact = code.length > 500_000; // 500KB
if (format.compact) {
console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "500KB"));
console.error(
"[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "500KB"),
);
}
}
@@ -89,43 +86,6 @@ function normalizeOptions(code, opts, tokens): Format {
return format;
}
/**
* Determine if input code uses more single or double quotes.
*/
function findCommonStringDelimiter(code, tokens) {
const DEFAULT_STRING_DELIMITER = "double";
if (!code) {
return DEFAULT_STRING_DELIMITER;
}
const occurences = {
single: 0,
double: 0,
};
let checked = 0;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (token.type.label !== "string") continue;
const raw = code.slice(token.start, token.end);
if (raw[0] === "'") {
occurences.single++;
} else {
occurences.double++;
}
checked++;
if (checked >= 3) break;
}
if (occurences.single > occurences.double) {
return "single";
} else {
return "double";
}
}
/**
* We originally exported the Generator class above, but to make it extra clear that it is a private API,
* we have moved that to an internal class instance and simplified the interface to the two public methods
@@ -141,7 +101,7 @@ export class CodeGenerator {
}
}
export default function (ast: Object, opts: Object, code: string): Object {
export default function(ast: Object, opts: Object, code: string): Object {
const gen = new Generator(ast, opts, code);
return gen.generate();
}

View File

@@ -7,15 +7,16 @@ function expandAliases(obj) {
function add(type, func) {
const fn = newObj[type];
newObj[type] = fn ? function(node, parent, stack) {
const result = fn(node, parent, stack);
newObj[type] = fn
? function(node, parent, stack) {
const result = fn(node, parent, stack);
return result == null ? func(node, parent, stack) : result;
} : func;
return result == null ? func(node, parent, stack) : result;
}
: func;
}
for (const type of Object.keys(obj)) {
const aliases = t.FLIPPED_ALIAS_KEYS[type];
if (aliases) {
for (const alias of aliases) {
@@ -46,8 +47,10 @@ function isOrHasCallExpression(node) {
}
if (t.isMemberExpression(node)) {
return isOrHasCallExpression(node.object) ||
(!node.computed && isOrHasCallExpression(node.property));
return (
isOrHasCallExpression(node.object) ||
(!node.computed && isOrHasCallExpression(node.property))
);
} else {
return false;
}

View File

@@ -38,17 +38,33 @@ export function UpdateExpression(node: Object, parent: Object): boolean {
return t.isMemberExpression(parent) && parent.object === node;
}
export function ObjectExpression(node: Object, parent: Object, printStack: Array<Object>): boolean {
export function ObjectExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack, { considerArrow: true });
}
export function DoExpression(node: Object, parent: Object, printStack: Array<Object>): boolean {
export function DoExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack);
}
export function Binary(node: Object, parent: Object): boolean {
if (
((t.isCallExpression(parent) || t.isNewExpression(parent)) && parent.callee === node) ||
node.operator === "**" &&
t.isBinaryExpression(parent, { operator: "**" })
) {
return parent.left === node;
}
if (
((t.isCallExpression(parent) || t.isNewExpression(parent)) &&
parent.callee === node) ||
t.isUnaryLike(parent) ||
(t.isMemberExpression(parent) && parent.object === node) ||
t.isAwaitExpression(parent)
@@ -65,7 +81,9 @@ export function Binary(node: Object, parent: Object): boolean {
if (
// Logical expressions with the same precedence don't need parens.
(parentPos === nodePos && parent.right === node && !t.isLogicalExpression(parent)) ||
(parentPos === nodePos &&
parent.right === node &&
!t.isLogicalExpression(parent)) ||
parentPos > nodePos
) {
return true;
@@ -78,11 +96,13 @@ export function Binary(node: Object, parent: Object): boolean {
export function BinaryExpression(node: Object, parent: Object): boolean {
// let i = (1 in []);
// for ((1 in []);;);
return node.operator === "in" && (t.isVariableDeclarator(parent) || t.isFor(parent));
return (
node.operator === "in" &&
(t.isVariableDeclarator(parent) || t.isFor(parent))
);
}
export function SequenceExpression(node: Object, parent: Object): boolean {
if (
// Although parentheses wouldn"t hurt around sequence
// expressions in the head of for loops, traditional style
@@ -106,44 +126,45 @@ export function SequenceExpression(node: Object, parent: Object): boolean {
}
export function YieldExpression(node: Object, parent: Object): boolean {
return t.isBinary(parent) ||
t.isUnaryLike(parent) ||
t.isCallExpression(parent) ||
t.isMemberExpression(parent) ||
t.isNewExpression(parent) ||
(t.isConditionalExpression(parent) && node === parent.test);
return (
t.isBinary(parent) ||
t.isUnaryLike(parent) ||
t.isCallExpression(parent) ||
t.isMemberExpression(parent) ||
t.isNewExpression(parent) ||
(t.isConditionalExpression(parent) && node === parent.test)
);
}
export { YieldExpression as AwaitExpression };
export function ClassExpression(node: Object, parent: Object, printStack: Array<Object>): boolean {
export function ClassExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack, { considerDefaultExports: true });
}
export function UnaryLike(node: Object, parent: Object): boolean {
return t.isMemberExpression(parent, { object: node }) ||
t.isCallExpression(parent, { callee: node }) ||
t.isNewExpression(parent, { callee: node });
return (
t.isMemberExpression(parent, { object: node }) ||
t.isCallExpression(parent, { callee: node }) ||
t.isNewExpression(parent, { callee: node }) ||
t.isBinaryExpression(parent, { operator: "**", left: node })
);
}
export function FunctionExpression(node: Object, parent: Object, printStack: Array<Object>): boolean {
export function FunctionExpression(
node: Object,
parent: Object,
printStack: Array<Object>,
): boolean {
return isFirstInStatement(printStack, { considerDefaultExports: true });
}
export function ArrowFunctionExpression(node: Object, parent: Object): boolean {
if (
// export default (function () {});
t.isExportDeclaration(parent) ||
t.isBinaryExpression(parent) ||
t.isLogicalExpression(parent) ||
t.isUnaryExpression(parent) ||
t.isTaggedTemplateExpression(parent)
) {
return true;
}
return UnaryLike(node, parent);
return t.isExportDeclaration(parent) || ConditionalExpression(node, parent);
}
export function ConditionalExpression(node: Object, parent: Object): boolean {
@@ -151,7 +172,8 @@ export function ConditionalExpression(node: Object, parent: Object): boolean {
t.isUnaryLike(parent) ||
t.isBinary(parent) ||
t.isConditionalExpression(parent, { test: node }) ||
t.isAwaitExpression(parent)
t.isAwaitExpression(parent) ||
t.isTaggedTemplateExpression(parent)
) {
return true;
}
@@ -169,10 +191,10 @@ export function AssignmentExpression(node: Object): boolean {
// Walk up the print stack to deterimine if our node can come first
// in statement.
function isFirstInStatement(printStack: Array<Object>, {
considerArrow = false,
considerDefaultExports = false,
} = {}): boolean {
function isFirstInStatement(
printStack: Array<Object>,
{ considerArrow = false, considerDefaultExports = false } = {},
): boolean {
let i = printStack.length - 1;
let node = printStack[i];
i--;
@@ -181,8 +203,9 @@ function isFirstInStatement(printStack: Array<Object>, {
if (
t.isExpressionStatement(parent, { expression: node }) ||
t.isTaggedTemplateExpression(parent) ||
considerDefaultExports && t.isExportDefaultDeclaration(parent, { declaration: node }) ||
considerArrow && t.isArrowFunctionExpression(parent, { body: node })
(considerDefaultExports &&
t.isExportDefaultDeclaration(parent, { declaration: node })) ||
(considerArrow && t.isArrowFunctionExpression(parent, { body: node }))
) {
return true;
}

View File

@@ -3,7 +3,7 @@ import * as t from "babel-types";
type WhitespaceObject = {
before?: boolean,
after?: boolean
after?: boolean,
};
/**
@@ -45,15 +45,22 @@ function isHelper(node) {
} else if (t.isCallExpression(node)) {
return isHelper(node.callee);
} else if (t.isBinary(node) || t.isAssignmentExpression(node)) {
return (t.isIdentifier(node.left) && isHelper(node.left)) || isHelper(node.right);
return (
(t.isIdentifier(node.left) && isHelper(node.left)) || isHelper(node.right)
);
} else {
return false;
}
}
function isType(node) {
return t.isLiteral(node) || t.isObjectExpression(node) || t.isArrayExpression(node) ||
t.isIdentifier(node) || t.isMemberExpression(node);
return (
t.isLiteral(node) ||
t.isObjectExpression(node) ||
t.isArrayExpression(node) ||
t.isIdentifier(node) ||
t.isMemberExpression(node)
);
}
/**
@@ -61,7 +68,6 @@ function isType(node) {
*/
export const nodes = {
/**
* Test if AssignmentExpression needs whitespace.
*/
@@ -80,9 +86,12 @@ export const nodes = {
* Test if SwitchCase needs whitespace.
*/
SwitchCase(node: Object, parent: Object): ?WhitespaceObject {
SwitchCase(node: Object, parent: Object): WhitespaceObject {
return {
before: node.consequent.length || parent.cases[0] === node,
after:
!node.consequent.length &&
parent.cases[parent.cases.length - 1] === node,
};
},
@@ -164,9 +173,10 @@ export const nodes = {
* Test if Property needs whitespace.
*/
nodes.ObjectProperty =
nodes.ObjectTypeProperty =
nodes.ObjectMethod = function (node: Object, parent): ?WhitespaceObject {
nodes.ObjectProperty = nodes.ObjectTypeProperty = nodes.ObjectMethod = function(
node: Object,
parent,
): ?WhitespaceObject {
if (parent.properties[0] === node) {
return {
before: true,
@@ -174,12 +184,37 @@ nodes.ObjectMethod = function (node: Object, parent): ?WhitespaceObject {
}
};
nodes.ObjectTypeCallProperty = function(
node: Object,
parent,
): ?WhitespaceObject {
if (
parent.callProperties[0] === node &&
(!parent.properties || !parent.properties.length)
) {
return {
before: true,
};
}
};
nodes.ObjectTypeIndexer = function(node: Object, parent): ?WhitespaceObject {
if (
parent.indexers[0] === node &&
(!parent.properties || !parent.properties.length) &&
(!parent.callProperties || !parent.callProperties.length)
) {
return {
before: true,
};
}
};
/**
* Returns lists from node types that need whitespace.
*/
export const list = {
/**
* Return VariableDeclaration declarations init properties.
*/
@@ -216,12 +251,12 @@ export const list = {
["LabeledStatement", true],
["SwitchStatement", true],
["TryStatement", true],
].forEach(function ([type, amounts]) {
].forEach(function([type, amounts]) {
if (typeof amounts === "boolean") {
amounts = { after: amounts, before: amounts };
}
[type].concat(t.FLIPPED_ALIAS_KEYS[type] || []).forEach(function (type) {
nodes[type] = function () {
[type].concat(t.FLIPPED_ALIAS_KEYS[type] || []).forEach(function(type) {
nodes[type] = function() {
return amounts;
};
});

View File

@@ -1,10 +1,7 @@
import find from "lodash/find";
import findLast from "lodash/findLast";
import isInteger from "lodash/isInteger";
import repeat from "lodash/repeat";
import Buffer from "./buffer";
import * as n from "./node";
import Whitespace from "./whitespace";
import * as t from "babel-types";
import * as generatorFunctions from "./generators";
@@ -14,35 +11,33 @@ const ZERO_DECIMAL_INTEGER = /\.0+$/;
const NON_DECIMAL_LITERAL = /^0[box]/;
export type Format = {
shouldPrintComment: (comment: string) => boolean;
retainLines: boolean;
retainFunctionParens: boolean;
comments: boolean;
auxiliaryCommentBefore: string;
auxiliaryCommentAfter: string;
compact: boolean | "auto";
minified: boolean;
quotes: "single" | "double";
concise: boolean;
shouldPrintComment: (comment: string) => boolean,
retainLines: boolean,
retainFunctionParens: boolean,
comments: boolean,
auxiliaryCommentBefore: string,
auxiliaryCommentAfter: string,
compact: boolean | "auto",
minified: boolean,
quotes: "single" | "double",
concise: boolean,
indent: {
adjustMultilineComment: boolean;
style: string;
base: number;
}
adjustMultilineComment: boolean,
style: string,
base: number,
},
};
export default class Printer {
constructor(format, map, tokens) {
constructor(format, map) {
this.format = format || {};
this._buf = new Buffer(map);
this._whitespace = tokens.length > 0 ? new Whitespace(tokens) : null;
}
format: Format;
inForStatementInitCounter: number = 0;
_buf: Buffer;
_whitespace: Whitespace;
_printStack: Array<Node> = [];
_indent: number = 0;
_insideAux: boolean = false;
@@ -107,7 +102,10 @@ export default class Printer {
space(force: boolean = false): void {
if (this.format.compact) return;
if ((this._buf.hasContent() && !this.endsWith(" ") && !this.endsWith("\n")) || force) {
if (
(this._buf.hasContent() && !this.endsWith(" ") && !this.endsWith("\n")) ||
force
) {
this._space();
}
}
@@ -149,14 +147,14 @@ export default class Printer {
token(str: string): void {
// space is mandatory to avoid outputting <!--
// http://javascript.spec.whatwg.org/#comment-syntax
if ((str === "--" && this.endsWith("!")) ||
if (
(str === "--" && this.endsWith("!")) ||
// Need spaces for operators of the same kind to avoid: `a+++b`
(str[0] === "+" && this.endsWith("+")) ||
(str[0] === "-" && this.endsWith("-")) ||
// Needs spaces to avoid changing '34' to '34.', which would still be a valid number.
(str[0] === "." && this._endsWithInteger)) {
(str[0] === "." && this._endsWithInteger)
) {
this._space();
}
@@ -294,9 +292,9 @@ export default class Printer {
*/
startTerminatorless(): Object {
return this._parenPushNewlineState = {
return (this._parenPushNewlineState = {
printed: false,
};
});
}
/**
@@ -322,7 +320,11 @@ export default class Printer {
const printMethod = this[node.type];
if (!printMethod) {
// eslint-disable-next-line max-len
throw new ReferenceError(`unknown node of type ${JSON.stringify(node.type)} with constructor ${JSON.stringify(node && node.constructor.name)}`);
throw new ReferenceError(
`unknown node of type ${JSON.stringify(
node.type,
)} with constructor ${JSON.stringify(node && node.constructor.name)}`,
);
}
this._printStack.push(node);
@@ -335,7 +337,8 @@ export default class Printer {
if (
this.format.retainFunctionParens &&
node.type === "FunctionExpression" &&
node.extra && node.extra.parenthesized
node.extra &&
node.extra.parenthesized
) {
needsParens = true;
}
@@ -343,7 +346,7 @@ export default class Printer {
this._printLeadingComments(node, parent);
const loc = (t.isProgram(node) || t.isFile(node)) ? null : node.loc;
const loc = t.isProgram(node) || t.isFile(node) ? null : node.loc;
this.withSource("start", loc, () => {
this[node.type](node, parent);
});
@@ -392,7 +395,12 @@ export default class Printer {
getPossibleRaw(node) {
const extra = node.extra;
if (extra && extra.raw != null && extra.rawValue != null && node.value === extra.rawValue) {
if (
extra &&
extra.raw != null &&
extra.rawValue != null &&
node.value === extra.rawValue
) {
return extra.raw;
}
}
@@ -485,33 +493,13 @@ export default class Printer {
}
let lines = 0;
if (node.start != null && !node._ignoreUserWhitespace && this._whitespace) {
// user node
if (leading) {
const comments = node.leadingComments;
const comment = comments && find(comments, (comment) =>
!!comment.loc && this.format.shouldPrintComment(comment.value));
lines = this._whitespace.getNewlinesBefore(comment || node);
} else {
const comments = node.trailingComments;
const comment = comments && findLast(comments, (comment) =>
!!comment.loc && this.format.shouldPrintComment(comment.value));
lines = this._whitespace.getNewlinesAfter(comment || node);
}
} else {
// generated node
// don't add newlines at the beginning of the file
if (this._buf.hasContent()) {
if (!leading) lines++; // always include at least a single line after
if (opts.addNewlines) lines += opts.addNewlines(leading, node) || 0;
let needs = n.needsWhitespaceAfter;
if (leading) needs = n.needsWhitespaceBefore;
const needs = leading ? n.needsWhitespaceBefore : n.needsWhitespaceAfter;
if (needs(node, parent)) lines++;
// generated nodes can't add starting file whitespace
if (!this._buf.hasContent()) lines = 0;
}
this.newline(lines);
@@ -520,7 +508,9 @@ export default class Printer {
_getComments(leading, node) {
// Note, we use a boolean flag here instead of passing in the attribute name as it is faster
// because this is called extremely frequently.
return (node && (leading ? node.leadingComments : node.trailingComments)) || [];
return (
(node && (leading ? node.leadingComments : node.trailingComments)) || []
);
}
_printComment(comment) {
@@ -538,22 +528,27 @@ export default class Printer {
this._printedCommentStarts[comment.start] = true;
}
// whitespace before
this.newline(this._whitespace ? this._whitespace.getNewlinesBefore(comment) : 0);
const isBlockComment = comment.type === "CommentBlock";
// Always add a newline before a block comment
this.newline(this._buf.hasContent() && isBlockComment ? 1 : 0);
if (!this.endsWith("[") && !this.endsWith("{")) this.space();
let val = comment.type === "CommentLine" ? `//${comment.value}\n` : `/*${comment.value}*/`;
let val = !isBlockComment ? `//${comment.value}\n` : `/*${comment.value}*/`;
//
if (comment.type === "CommentBlock" && this.format.indent.adjustMultilineComment) {
if (isBlockComment && this.format.indent.adjustMultilineComment) {
const offset = comment.loc && comment.loc.start.column;
if (offset) {
const newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n");
}
const indentSize = Math.max(this._getIndent().length, this._buf.getCurrentColumn());
const indentSize = Math.max(
this._getIndent().length,
this._buf.getCurrentColumn(),
);
val = val.replace(/\n(?!$)/g, `\n${repeat(" ", indentSize)}`);
}
@@ -564,10 +559,8 @@ export default class Printer {
this._append(val);
});
// whitespace after
this.newline((this._whitespace ? this._whitespace.getNewlinesAfter(comment) : 0) +
// Subtract one to account for the line force-added above.
(comment.type === "CommentLine" ? -1 : 0));
// Always add a newline after a block comment
this.newline(isBlockComment ? 1 : 0);
}
_printComments(comments?: Array<Object>) {

View File

@@ -18,16 +18,16 @@ export default class SourceMap {
get() {
if (!this._cachedMap) {
const map = this._cachedMap = new sourceMap.SourceMapGenerator({
const map = (this._cachedMap = new sourceMap.SourceMapGenerator({
file: this._opts.sourceMapTarget,
sourceRoot: this._opts.sourceRoot,
});
}));
const code = this._code;
if (typeof code === "string") {
map.setSourceContent(this._opts.sourceFileName, code);
} else if (typeof code === "object") {
Object.keys(code).forEach((sourceFileName) => {
Object.keys(code).forEach(sourceFileName => {
map.setSourceContent(sourceFileName, code[sourceFileName]);
});
}
@@ -60,8 +60,11 @@ export default class SourceMap {
// If this mapping points to the same source location as the last one, we can ignore it since
// the previous one covers it.
if (this._lastGenLine === generatedLine && this._lastSourceLine === line &&
this._lastSourceColumn === column) {
if (
this._lastGenLine === generatedLine &&
this._lastSourceLine === line &&
this._lastSourceColumn === column
) {
return;
}
@@ -80,10 +83,13 @@ export default class SourceMap {
column: generatedColumn,
},
source: line == null ? undefined : filename || this._opts.sourceFileName,
original: line == null ? undefined : {
line: line,
column: column,
},
original:
line == null
? undefined
: {
line: line,
column: column,
},
});
}
}

View File

@@ -1,92 +0,0 @@
/**
* Get whitespace around tokens.
*/
export default class Whitespace {
constructor(tokens) {
this.tokens = tokens;
this.used = {};
}
/**
* Count all the newlines before a node.
*/
getNewlinesBefore(node) {
let startToken;
let endToken;
const tokens = this.tokens;
let index = this._findToken((token) => token.start - node.start, 0, tokens.length);
if (index >= 0) {
while (index && node.start === tokens[index - 1].start) --index;
startToken = tokens[index - 1];
endToken = tokens[index];
}
return this._getNewlinesBetween(startToken, endToken);
}
/**
* Count all the newlines after a node.
*/
getNewlinesAfter(node) {
let startToken;
let endToken;
const tokens = this.tokens;
let index = this._findToken((token) => token.end - node.end, 0, tokens.length);
if (index >= 0) {
while (index && node.end === tokens[index - 1].end) --index;
startToken = tokens[index];
endToken = tokens[index + 1];
if (endToken.type.label === ",") endToken = tokens[index + 2];
}
if (endToken && endToken.type.label === "eof") {
return 1;
} else {
return this._getNewlinesBetween(startToken, endToken);
}
}
/**
* Count all the newlines between two tokens.
*/
_getNewlinesBetween(startToken, endToken) {
if (!endToken || !endToken.loc) return 0;
const start = startToken ? startToken.loc.end.line : 1;
const end = endToken.loc.start.line;
let lines = 0;
for (let line = start; line < end; line++) {
if (typeof this.used[line] === "undefined") {
this.used[line] = true;
lines++;
}
}
return lines;
}
/**
* Find a token between start and end.
*/
_findToken(test: Function, start: number, end: number): number {
if (start >= end) return -1;
const middle = (start + end) >>> 1;
const match: number = test(this.tokens[middle]);
if (match < 0) {
return this._findToken(test, middle + 1, end);
} else if (match > 0) {
return this._findToken(test, start, middle);
} else if (match === 0) {
return middle;
}
return -1;
}
}

View File

@@ -1,6 +1,7 @@
function foo() {
bar();
if (foo) {
bar();
}
}
bar();
if (foo) {
bar();
}
}

View File

@@ -1,6 +1,7 @@
function foo() {
bar();
if (foo) {
bar();
}
}
}

View File

@@ -1,6 +1,7 @@
function foo() {
bar();
if (foo) {
bar();
if (foo) {
bar();
}
}
}
}

View File

@@ -1,9 +1,9 @@
var single = 'quotes';
var outnumber = 'double';
var moreSingleQuotesThanDouble = '!';
React.createClass({
render() {
return <View multiple="attributes" attribute="If parent is JSX keep double quote" />;
}
});
});

View File

@@ -1,8 +1,6 @@
function test() {
/*
* this is comment
*/
var i = 20;
}
}

View File

@@ -1,7 +1,6 @@
// from #23
/**/
/*
*/
*/

View File

@@ -1,4 +1,6 @@
// from #23
/**/
/*
*/
*/

View File

@@ -3,9 +3,10 @@ var test = {
* Before bracket init
*/
["a"]: "1",
[/*
* Inside bracket init
*/
[
/*
* Inside bracket init
*/
"b"]: "2"
},
ok = 42;
ok = 42;

View File

@@ -3,25 +3,20 @@ var test = {
* Before bracket init
*/
["a"]: "1",
[/*
* Inside bracket init
*/
[
/*
* Inside bracket init
*/
"b"]: "2",
["c"
/*
* After bracket key
*/]: "3",
*/
]: "3",
// Before bracket, line comment
["d"]: "4",
[
// Inside bracket, line comment
[// Inside bracket, line comment
"e"]: "5",
["f"
// After bracket, line comment
["f" // After bracket, line comment
]: "6"
};
};

View File

@@ -1,6 +1,11 @@
!function () {} //
, 42;
!{ get 42() {} //
, foo: 42 };
!{
get 42() {} //
,
foo: 42
};
(function () {} //
);
);

View File

@@ -1,5 +1,4 @@
if (cond)
// Leading to if-block
if (cond) // Leading to if-block
{
print("hello");
} // Trailing to if-block
} // Trailing to if-block

View File

@@ -1,3 +1,2 @@
if (cond)
// Leading to EmptyStatement
; // Trailing to EmptyStatement
if (cond) // Leading to EmptyStatement
; // Trailing to EmptyStatement

View File

@@ -2,6 +2,6 @@ function test() {
// Leading if statement
if (cond) {
print("hello");
}
// Trailing if-block statement
}
} // Trailing if-block statement
}

View File

@@ -3,10 +3,11 @@ var test = {
* Test 2
*/
a: "1",
/*
* Test 1
*/
b: "2",
// Test 3
c: "3"
};
};

View File

@@ -19,11 +19,7 @@
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function test() {}
// Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
function test() {} // Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
@@ -43,4 +39,4 @@ function test() {}
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -21,9 +21,7 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
function test() {}
/*
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
@@ -46,4 +44,4 @@ function test() {}
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
*/

View File

@@ -1,3 +1,2 @@
// Leading
var i = 20;
// Trailing
var i = 20; // Trailing

View File

@@ -8,7 +8,6 @@ function test() {
* Leading comment 2
*
*/
var i = 20;
/*
* Trailing comment
@@ -19,4 +18,4 @@ function test() {
* Trailing comment 2
*
*/
}
}

View File

@@ -1,10 +1,8 @@
function test() {
var
// Leading to VariableDeclarator
var // Leading to VariableDeclarator
// Leading to VariableDeclarator
i = 20,
// Leading to VariableDeclarator
// Leading to VariableDeclarator
// Leading to VariableDeclarator
j = 20;
}
}

View File

@@ -1,18 +1,20 @@
{
var t = 20; /*
* This is trailing comment
*/
var t = 20;
/*
* This is trailing comment
*/
}
{
var tt = 20; /*
* This is trailing comment
*/
var tt = 20;
/*
* This is trailing comment
*/
}
{
{
var t = 20; /*
* This is trailing comment
*/
var t = 20;
/*
* This is trailing comment
*/
}
}
}

View File

@@ -5,8 +5,13 @@
//for (var i = 10 + (10 in []) in []);
//for (var i = 10 + 10 in [] in []);
for (var i = (1 in []);;);
for ((1 in []);;);
for (1 * (1 in []);;);
for (1 * (1 + 1 in []);;);
for (1 * (1 + 1 in []);;);
for (1 * (1 + (1 in []));;);
for (1 * (1 + (1 in []));;);

View File

@@ -1,4 +1,5 @@
for ((a in b) ? a : b; i;);
for (function () {
for (;;);
} && (a in b);;);
} && (a in b);;);

View File

@@ -1,7 +1,13 @@
const bar1 = (x: number): string => {};
const bar2 = (x?) => {};
const bar3 = (x?: string) => {};
const bar4 = x => {};
const bar5 = (x): string => {};
const bar6 = (x: number) => {};
const bar7 = <T>(x) => {};
const bar7 = <T>(x) => {};

View File

@@ -2,4 +2,4 @@ var a: { (): number };
var a: { (): number; };
var a: { (): number; y: string; (x: string): string };
var a: { <T>(x: T): number; };
interface A { (): number; };
interface A { (): number; }

View File

@@ -1,5 +1,17 @@
var a: { (): number };
var a: { (): number };
var a: { y: string, (): number, (x: string): string, };
var a: { <T>(x: T): number };
interface A { (): number };
var a: {
(): number
};
var a: {
(): number
};
var a: {
y: string,
(): number,
(x: string): string,
};
var a: {
<T>(x: T): number
};
interface A {
(): number
}

View File

@@ -0,0 +1,24 @@
declare export var foo
declare export var foo;
declare export function foo(): void
declare export function foo(): void;
declare export function foo<T>(): void;
declare export function foo(x: number, y: string): void;
declare export class A {}
declare export class A<T> extends B<T> { x: number }
declare export class A { static foo(): number; static x : string }
declare export class A { static [ indexer: number]: string }
declare export class A { static () : number }
declare export class A mixins B<T>, C {}
declare export default class A {}
declare export default function foo(): void;
declare export default string
declare export * from 'asd';
declare export { a, b };
declare export {};
declare export { c, d } from 'bar';
declare module B {
declare export type B = {};
declare export interface Moon {}
}

View File

@@ -0,0 +1,32 @@
declare export var foo;
declare export var foo;
declare export function foo(): void;
declare export function foo(): void;
declare export function foo<T>(): void;
declare export function foo(x: number, y: string): void;
declare export class A {}
declare export class A<T> extends B<T> {
x: number
}
declare export class A {
static foo: () => number,
static x: string,
}
declare export class A {
static [indexer: number]: string
}
declare export class A {
static (): number
}
declare export class A mixins B<T>, C {}
declare export default class A {}
declare export default function foo(): void;
declare export default string;
declare export * from 'asd';
declare export { a, b };
declare export {};
declare export { c, d } from 'bar';
declare module B {
declare export type B = {};
declare export interface Moon {}
}

View File

@@ -7,8 +7,12 @@ declare module A {
declare function foo(): number;
}
declare module A {
declare class B { foo: () => number }
declare class B {
foo: () => number
}
}
declare module A {
declare module.exports: { foo: () => number }
}
declare module.exports: {
foo: () => number
}
}

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