Compare commits

...

190 Commits

Author SHA1 Message Date
Henry Zhu
79f4956948 v7.0.0-alpha.19 2017-08-07 18:21:08 -04:00
Henry Zhu
7f92e1d9dd Update gulp, fix build (#6061)
* gulp-babel 7.0
2017-08-07 17:09:22 -04:00
Andy
e37a5eb5eb Add babel-plugin-syntax-typescript, babel-plugin-transform-typescript, and babel-preset-typescript (#5899)
* Add babel-plugin-syntax-typescript and babel-plugin-transform-typescript

* Add babel-preset-typescript

* Remove unnecessary handler for JSXOpeningElement

* Use `t.isFoo(node)` instead of `node.type === "Foo"`

* Clean up parameter property assignment generation

* Don't use function for `isSuperCall`

* slice -> shift

* Calculate sourceFileHasJsx only if necessary

* Remove `export =` support

* remove some syntax readme newlines [skip ci]
2017-08-07 11:45:52 -04:00
Henry Zhu
66ec5263a4 Use Yarn Workspaces (#6056)
* update lerna and lerna-changelog

* Lerna: enable yarn, yarn workspaces [skip ci]

* use older version of Babel since it matches on semver (cannot be the same version)

* install yarn version

* revert node engine change

* update flow

* circle ci on 8

* update lock
2017-08-05 14:48:15 -04:00
Teddy Katz
13d931c417 Don't insert the same node into the AST multiple times (fixes babel/babili#556) (#6054) 2017-08-04 19:00:29 -04:00
Henry Zhu
47a9ba3440 Merge pull request #6051 from babel/5709-2
Rewrite parameter transform and drop _blockHoist reliance
2017-08-04 18:55:23 -04:00
Henry Zhu
a1debae8f0 babylon beta.19 (#6053) 2017-08-04 14:46:12 -04:00
Henry Zhu
30c4d6b456 Merge pull request #6052 from babel/array-destructuring-hole
Array destructuring hole
2017-08-04 12:20:50 -04:00
Henry Zhu
0e58007264 add test for spread with hole 2017-08-04 12:06:26 -04:00
Henry Zhu
577173cc02 fix export when array destructuring exported value with hole 2017-08-04 11:53:49 -04:00
Henry Zhu
8c457e9283 Merge pull request #5468 from babel/react-preset
Add requireDirective to strip-flow-types for use in React preset
2017-08-04 11:31:12 -04:00
Brian Ng
2a83867436 Fixes from review 2017-08-04 10:16:45 -05:00
Brian Ng
9dd65c809f fixes 2017-08-03 22:27:30 -05:00
Brian Ng
af5f34ace5 Throw if annotation found without directive 2017-08-03 21:54:36 -05:00
Brian Ng
57da9bdbed Add requireDirective to strip-flow-types for use in React preset 2017-08-03 21:13:45 -05:00
Logan Smyth
d86ae2fb84 Remove _blockHoist usage from param processing. 2017-08-03 20:56:50 -05:00
Logan Smyth
18084db7cf Fix an ordering bug in object-rest-spread. 2017-08-03 20:56:24 -05:00
Logan Smyth
8e19a5b057 Update param scope values when expanding parameters. 2017-08-03 20:56:24 -05:00
Logan Smyth
95882d4e5a Rewrite param processing to be more clearly defined. 2017-08-03 20:56:08 -05:00
Henry Zhu
99ab2b206c update to alpha.18 (#6050) 2017-08-03 20:40:53 -04:00
Henry Zhu
77cfa94682 yarn: fix ci? 2017-08-03 20:02:31 -04:00
Henry Zhu
79c6814d65 v7.0.0-alpha.18 2017-08-03 18:20:36 -04:00
Henry Zhu
d479673074 prepublish [skip ci] 2017-08-03 18:18:36 -04:00
Henry Zhu
6630ae9794 Merge pull request #6046 from jridgewell/pr/6038
Fix invalid block-scoped loop
2017-08-03 08:51:25 -04:00
Justin Ridgewell
6bb1486405 Fix 2017-08-02 19:47:14 -04:00
Sarup Banskota
75808a2d14 Prevent getFunctionParent from returning Program (#5923) 2017-08-02 16:30:33 -05:00
jbrown215
4e9a25e34a Flow opaque type aliases (#5990) 2017-08-02 16:30:19 -05:00
Henry Zhu
0f823beeb1 Newlines in fixtures (#6044)
* write newlines for fixtures

* rerun fixtures
2017-08-02 15:35:29 -04:00
Sergey Rubanov
829c75a866 Development Only: drop Node 4-5 and npm 2 (#6037) [skip ci]
Node versions 4 and 5 are obsolete. Version of npm bundled in Node 6 is 3 so npm 2 could be dropped as well.
2017-08-02 14:30:13 -04:00
Henry Zhu
9d7c82d869 Adding failing test for 6025 2017-08-01 16:16:47 -04:00
Brian Ng
21eeed8a8c Fix generate interfaces script (#6031)
* Fix typo in TSPropertySignature type definition

* Sort fields in generate-interfaces script
2017-08-01 14:38:46 -04:00
Brian Ng
889f4e7791 Fix refs in transform-optional-chaining docs [skip ci] (#6035) 2017-08-01 14:30:16 -04:00
Brian Ng
c5e81516dd Add optional catch binding to stage 3 preset (#6032) 2017-07-31 16:00:43 -04:00
Brian Ng
6d965c0926 Make babel-node a standalone package (#6023)
* Make babel-node a standalone package

* New package `babel-node` previously `babel-cli/bin/babel-node`

* updates
2017-07-29 22:26:28 -04:00
Andy
e32042f353 babel-generator: Comment TypeScript-specific code (#6026) 2017-07-28 18:03:38 -04:00
Andy
c1d07fd6db babel-generator: Add TypeScript support (#5896)
* babel-generator: Add TypeScript support

* Remove type declarations; not published from babylon

* Remove TODOs

* Consistently use `this.word` for tokens that are words
2017-07-28 16:07:05 -04:00
Henry Zhu
f83c83d49c add proposals repo [skip ci] (#6024) 2017-07-28 15:31:47 -04:00
chocolateboy
605adc922d allow PluginPass.file.addImport to create empty import statements (#6022)
* allow PluginPass.file.addImport to create empty import statements; fixes #6021

omitting addImport's second argument creates an import statement with an
empty `specifiers` array i.e. an empty import statement:

plugin:

    Program (path, { file }) {
        file.addImport('foo-bar/register')
    }

output:

    import "foo-bar/register";
2017-07-28 12:37:00 -04:00
Henry Zhu
593cbc1d53 Function sent (#6020)
* change back to function-sent

* update stage 2
2017-07-26 18:01:40 -04:00
Noah Lemen
5c45753cd6 add TEST_GREP example clarification [skip ci] (#6013) 2017-07-26 17:53:46 -04:00
Andy
1563221171 babel-types: Have NewExpression inherit from CallExpression (#6019) 2017-07-26 17:53:23 -04:00
Andy
b242e0d946 babel-generator: Make plugins list explicit for test cases (#6018) 2017-07-26 15:46:47 -04:00
Henry Zhu
9322fd0458 v7.0.0-alpha.17 2017-07-26 08:38:44 -04:00
Henry Zhu
f01438e9b1 update devdeps to latest, update babylon (#6012)
* temporary flow strip measure
2017-07-26 07:57:49 -04:00
Henry Zhu
ce5d1d0f59 why 2017-07-25 17:47:59 -04:00
Henry Zhu
7f1cd44d60 v7.0.0-alpha.16 2017-07-25 17:35:35 -04:00
Henry Zhu
2841945095 temporarily rename function-sent pkg to 2 (#6011) [skip ci]
* update readme [skip ci]

* rename to sent2 until we get the package [skip ci]
2017-07-25 17:30:31 -04:00
Henry Zhu
76060bb2c7 commit yarn.lock 2017-07-25 17:10:10 -04:00
Henry Zhu
84dfa659e7 update to alpha.15 (#6009) 2017-07-25 17:08:15 -04:00
Samuel Reed
e0b4543601 feature: Support whitelisting mutable props for react-constant-elements (#5307) 2017-07-25 13:34:21 -05:00
Andy
248743e6c5 babel-types: Add TypeScript definitions (#5856)
* babel-types: Add TypeScript definitions

* Add missing builders

* Allow arrow function to have "generator"

* Replace link to resolved issue with comment

* Re-add 'generator' to functionCommon
2017-07-25 11:42:25 -04:00
Brian Ng
9a1b8ea443 Add support for flow predicates in babel-generator (#5984) 2017-07-25 11:38:17 -04:00
Brian Ng
55aea26f13 Add support for export type star in babel-generator (#5985)
* Add support for export type star in babel-generator

* Bump babylon
2017-07-25 11:37:27 -04:00
Nicolò Ribaudo
fb9a752262 Function sent (#5920)
* Create "babel-helper-wrap-function"

It contains the logic to wrap a function inside a call expression.
It was part of the "babel-helper-remap-async-to-generator" package, but
it is needed to transpile "function.sent"

* Create "babel-transform-function-sent"

It transforms the "function.sent" meta property by replacing it with
"yield" and making the generator ignore the first ".next()" call.

* "function.sent" is the last value passed to .next(), not the first one

* Disable exec tests on old node

* Fix flow error

* Add "transform-function-sent" to "stage-2" preset

* Do every trasformation in one traversal

* Test for "yield function.sent"

* [skip ci]

* Fix some typos [skip ci]
2017-07-25 11:07:01 -04:00
Peeyush Kushwaha
4a35243118 Non string computed keys in object-rest-spread (#5757) 2017-07-25 09:46:52 -05:00
MarckK
9fc910d8c0 Add optionality to catch bindings (#5956) 2017-07-25 09:38:48 -05:00
Noah Lemen
51a293601b add JSXAttribute visitor function, wraps JSXElement attributes in a JSXExpressionContainer; also adds test fixtures (#6006) 2017-07-25 09:30:32 -04:00
Daniel Tschinder
19c4dd2d8c Update chai to 4.x (#6002) 2017-07-24 15:19:32 -04:00
Peeyush Kushwaha
2225892348 Use first binding for multiple var declarations (#5745)
* Use first binding for multiple var declarations
Since var declarations after initial binding have no effect, use the
first declaration. Fixes #2378

* Include hoisted function bindings

* Missing newline in expected.js

* Simplify constantViolations in new Binding on existing

* clarify comment language
2017-07-24 14:43:17 -04:00
Daniel Tschinder
677160385c Update chalk to 2.x (#6003) 2017-07-24 11:06:57 -04:00
Daniel Tschinder
9b04cbbc4f Update find-cache-dir to 1.0 (#5999) 2017-07-23 20:23:55 -04:00
Daniel Tschinder
4aca487b6d Update default-require-extensions to 2.0 (#6000) 2017-07-23 20:23:29 -04:00
Daniel Tschinder
5afe40b095 Update to-fast-properties to 2.0 (#5997) 2017-07-23 09:22:05 -04:00
Daniel Tschinder
b081f68e87 Update output-file-sync to 2.0 (#5996)
* Update output-file-sync to 2.0

* Ignore test tmp directory
2017-07-23 09:21:51 -04:00
Daniel Tschinder
c9ed159a18 Update jsesc to the latest version (#5995) 2017-07-23 09:21:22 -04:00
Daniel Tschinder
b9ed9919c1 Update globals to v10 (#5993) 2017-07-23 09:21:08 -04:00
Daniel Tschinder
04b4e414ad Fix clean to remove package-lock files (#5991)
Otherweise the same versions get installed over an over again in
dev environments
2017-07-23 09:20:36 -04:00
Ryan Gaus
0b890ced19 Code generator tests (#5847) 2017-07-20 18:22:18 -04:00
Justin Ridgewell
c60bf9a897 Fixup builder-binary-assignment-operator-visitor (#5969)
Using a `SequenceExpression` instead, we avoid awkward
`AssignmentExpression`s as direct children of `BlockStatement`s.
2017-07-20 11:47:47 -04:00
Naveen jain
245c78dcdc Added test cases for babel-generator (#5934)
* edited .gitignore to ignore all package-lock.json files
2017-07-20 11:39:26 -04:00
Justin Ridgewell
8a98141b60 Fix a few type inferences (#5835) 2017-07-20 11:38:12 -04:00
Justin Ridgewell
78544417fc Remove noop (#5970)
It’s ugly, but it gets the job done. And it unblocks my babel-type
changes.
2017-07-20 11:36:13 -04:00
Justin Ridgewell
c6edce115c Fix numeric-separator transform (#5968) 2017-07-20 11:35:53 -04:00
Selwyn
579499c66d Update v8flags to version 3.0.0 (#5975) 2017-07-19 14:31:23 -04:00
Justin Ridgewell
827c70e015 Support exporting deep destructuring (#5953) 2017-07-18 14:07:09 -05:00
Justin Ridgewell
8a5488e59f Fix for-of loose optimization (#5964)
VariableDeclarators can’t have a MemberExpression id.
2017-07-18 15:01:36 -04:00
Justin Ridgewell
63204ae51e Remove maybePopFromStatements (#5945)
It prevented you from pushing into the `params` of a function.

```js
fnpath.pushContainer("params", t.identifier("memo"))
```
2017-07-18 14:55:33 -04:00
Justin Ridgewell
28ae47a174 Stop mutating nodes (#5963)
* Stop mutating nodes

* Update tests

* linting
2017-07-18 13:24:07 -04:00
Mauro Bringolf
aa684d1b0c Spec compliancy of check-es2015-constants plugin (#5930)
* Figuring out where to place throw statement

* Restored path argument destructuring

* New approach using comma expressions for assignments

* Moved throwNode into body of forXstatements

* Refactored with helper function and ensureBlock, additional tests for update exprs

* Added exec tests for all violations

* Hoisted helper function for comma expression outside of visitor
2017-07-17 20:01:01 -04:00
Brian Ng
1fdec955f8 Bump istanbul and nyc (#5959) 2017-07-17 15:58:49 -04:00
Sarup Banskota
213ad1ed7a [generator] remove parens from break & continue (#5950)
* Remove parens around break and continue

Fixes #5742

* Fix space in doc comment

* Add some tests

* Remove newlines within CommentBlock

* Prevent newline before/after label

* Remove reference to node

* Check for label within startTerminatorless

* Print block instead of single line comment

* Clean up
2017-07-17 09:30:28 -07:00
Justin Ridgewell
797fb3c2e4 Optimize and remove state from typeof-symbol transform (#5955)
Also fixes a bug with returning a Symbol from a Class constructor
(because the transform wasn’t run on helpers before).
2017-07-17 10:51:36 -04:00
Justin Ridgewell
9d612e717e Fix react-inline-elements bug (#5958) 2017-07-17 10:46:13 -04:00
Justin Ridgewell
e919c6e6eb Add several test cases for systemjs exports (#5954) 2017-07-17 08:51:37 -05:00
Sven SAULEAU
d82afb407e Merge pull request #5949 from babel/unused-eslint-rule
remove unused ESLint rule
2017-07-14 11:51:36 +02:00
Sven SAULEAU
b858d7ce5e chore: remove unused ESLint rule 2017-07-14 11:25:09 +02:00
Mauro Bringolf
b83e0ec7b0 2nd try: Add loose option for es2015-parameters transformation (#5943)
* Import changes to parameters package from previous branch

* Refactor plugin option access via state
2017-07-12 17:36:44 -04:00
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
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
1819 changed files with 22855 additions and 9270 deletions

View File

@@ -6,12 +6,28 @@ let envOpts = {
module.exports = {
comments: false,
plugins: [
// temp until next release
function() {
return {
visitor: {
"Function": function(path) {
const node = path.node;
for (let i = 0; i < node.params.length; i++) {
const param = node.params[i];
if (param.type === "AssignmentPattern") {
param.left.optional = false;
}
}
}
}
};
}
],
presets: [
[
"env", envOpts
],
["env", envOpts],
"stage-0",
"flow",
"flow"
],
env: {
cov: {
@@ -21,9 +37,9 @@ module.exports = {
}
};
if (process.env.BABEL_ENV === 'development') {
if (process.env.BABEL_ENV === "development") {
envOpts.targets = {
node: "current"
};
envOpts.debug = true;
};
}

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,

View File

@@ -13,6 +13,5 @@ lib/types.js
lib/third-party-libs.js.flow
[options]
strip_root=true
suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe
suppress_comment= \\(.\\|\n\\)*\\$FlowIssue

3
.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
@@ -21,6 +22,8 @@ dist
/packages/babel-runtime/helpers/es6/*.js
!/packages/babel-runtime/helpers/es6/toArray.js
/packages/babel-register/test/.babel
/packages/babel-cli/test/tmp
/packages/babel-node/test/tmp
/packages/*/lib
.nyc_output
/babel.sublime-workspace

View File

@@ -7,12 +7,17 @@ cache:
directories:
- node_modules
node_js:
- '7'
- '8'
- '6'
- '4'
env:
- JOB=test
global:
- PATH=$HOME/.yarn/bin:$PATH
- JOB=test
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.28.1
script:
- 'if [ "$JOB" = "test" ]; then make test-ci; fi'

1
.yarnrc Normal file
View File

@@ -0,0 +1 @@
workspaces-experimental true

View File

@@ -40,7 +40,7 @@ Feel free to check out the `#discussion`/`#development` channels on our [Slack](
**Note:** Versions `< 5.1.10` can't be built.
Babel is built for Node.js 4 and up but we develop using Node.js 6. Make sure you are on npm 3.
Babel is built for Node.js 4 and up but we develop using Node.js 6/8 and yarn.
You can check this with `node -v` and `npm -v`.
@@ -120,6 +120,12 @@ Use the `TEST_GREP` variable to run a subset of tests by name:
$ TEST_GREP=transformation make test
```
Substitute spaces for hyphens and forward slashes when targeting specific test names:
```sh
$ TEST_GREP="arrow functions destructuring parameters" make test
```
To enable the Node.js debugger added in v6.3.0, set the `TEST_DEBUG` environment variable:
```sh

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,9 +2,13 @@ MAKEFLAGS = -j1
export NODE_ENV = test
# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
export FORCE_COLOR = true
.PHONY: build build-dist watch lint fix clean test-clean test-only test test-ci publish bootstrap
build: clean
rm -rf packages/*/lib
./node_modules/.bin/gulp build
build-dist: build
@@ -22,7 +26,7 @@ lint:
./node_modules/.bin/eslint scripts packages *.js --format=codeframe
flow:
./node_modules/.bin/flow check
./node_modules/.bin/flow check --strip-root
fix:
./node_modules/.bin/eslint scripts packages *.js --format=codeframe --fix
@@ -43,6 +47,8 @@ clean-all:
rm -rf packages/*/lib
rm -rf node_modules
rm -rf packages/*/node_modules
rm -rf package-lock.json
rm -rf packages/*/package-lock.json
make clean
test-only:
@@ -55,10 +61,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

View File

@@ -86,6 +86,7 @@ Check out our [CONTRIBUTING.md](https://github.com/babel/babel/blob/master/CONTR
You can also start by checking out the issues with the [help-wanted](https://github.com/babel/babel/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label.
Our discussions/notes/roadmap: [babel/notes](https://github.com/babel/notes)
Our progress on TC39 proposals: [babel/proposals](https://github.com/babel/proposals)
## Packages

View File

@@ -1,7 +1,7 @@
machine:
node:
version:
6
8
dependencies:
pre:

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,8 +1,7 @@
{
"lerna": "2.0.0-rc.4",
"version": "7.0.0-alpha.12",
"version": "7.0.0-alpha.19",
"changelog": {
"repo": "babel/babel",
"labels": {
"tag: spec compliancy": ":eyeglasses: Spec Compliancy",
"tag: breaking change": ":boom: Breaking Change",
@@ -21,5 +20,10 @@
"test/**"
]
}
}
},
"packages": [
"packages/*"
],
"npmClient": "yarn",
"useWorkspaces": true
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,51 +3,55 @@
"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-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-cli": "7.0.0-alpha.15",
"babel-core": "7.0.0-alpha.15",
"babel-eslint": "8.0.0-alpha.15",
"babel-plugin-istanbul": "^4.1.4",
"babel-preset-env": "2.0.0-alpha.15",
"babel-preset-flow": "7.0.0-alpha.15",
"babel-preset-stage-0": "7.0.0-alpha.15",
"babel-register": "7.0.0-alpha.15",
"browserify": "^13.1.1",
"bundle-collapser": "^1.2.1",
"chai": "^3.5.0",
"chalk": "1.1.1",
"codecov": "^1.0.1",
"chai": "^4.1.0",
"chalk": "^2.0.0",
"derequire": "^2.0.2",
"eslint": "^3.9.0",
"eslint-config-babel": "^6.0.0",
"eslint": "^3.14.1",
"eslint-config-babel": "^7.0.1",
"eslint-plugin-flowtype": "^2.20.0",
"flow-bin": "^0.41.0",
"eslint-plugin-prettier": "^2.1.2",
"flow-bin": "^0.52.0",
"gulp": "^3.9.0",
"gulp-babel": "babel/gulp-babel#b7-alpha",
"gulp-babel": "^7.0.0",
"gulp-newer": "^1.0.0",
"gulp-plumber": "^1.0.1",
"gulp-util": "^3.0.7",
"gulp-watch": "^4.3.5",
"lerna": "2.0.0-rc.4",
"lerna-changelog": "^0.2.0",
"husky": "^0.13.2",
"lerna": "2.0.0",
"lerna-changelog": "^0.6.0",
"lint-staged": "^3.6.1",
"lodash": "^4.2.0",
"mocha": "^3.0.0",
"nyc": "^10.0.0",
"output-file-sync": "^1.1.1",
"nyc": "^11.0.3",
"output-file-sync": "^2.0.0",
"prettier": "^1.5.0",
"rimraf": "^2.4.3",
"semver": "^5.0.0",
"through2": "^2.0.0",
"uglify-js": "^2.4.16"
},
"devEngines": {
"node": ">= 4.x <= 7.x",
"npm": "2.x || 3.x || 4.x"
"engines": {
"node": ">= 4.x <= 8.x",
"npm": ">= 2.x <= 5.x"
},
"nyc": {
"all": true,
@@ -57,5 +61,14 @@
],
"sourceMap": false,
"instrument": false
}
},
"lint-staged": {
"*.js": [
"eslint --format=codeframe --fix",
"git add"
]
},
"workspaces": [
"packages/*"
]
}

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.12",
"version": "7.0.0-alpha.19",
"description": "Babel command line.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -16,24 +16,24 @@
"compiler"
],
"dependencies": {
"babel-core": "7.0.0-alpha.12",
"babel-polyfill": "7.0.0-alpha.12",
"babel-register": "7.0.0-alpha.12",
"babel-core": "7.0.0-alpha.19",
"babel-polyfill": "7.0.0-alpha.19",
"babel-register": "7.0.0-alpha.19",
"commander": "^2.8.1",
"convert-source-map": "^1.1.0",
"fs-readdir-recursive": "^1.0.0",
"glob": "^7.0.0",
"lodash": "^4.2.0",
"output-file-sync": "^1.1.0",
"output-file-sync": "^2.0.0",
"slash": "^1.0.0",
"source-map": "^0.5.0",
"v8flags": "^2.0.10"
"v8flags": "^3.0.0"
},
"optionalDependencies": {
"chokidar": "^1.6.1"
},
"devDependencies": {
"babel-helper-fixtures": "7.0.0-alpha.12"
"babel-helper-fixtures": "7.0.0-alpha.19"
},
"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.12",
"version": "7.0.0-alpha.19",
"description": "Generate errors that contain a code frame that point to source locations.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -8,8 +8,11 @@
"repository": "https://github.com/babel/babel/tree/master/packages/babel-code-frame",
"main": "lib/index.js",
"dependencies": {
"chalk": "^1.1.0",
"chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^3.0.0"
},
"devDependencies": {
"strip-ansi": "^4.0.0"
}
}

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

@@ -1,36 +1,31 @@
import assert from "assert";
import chalk from "chalk";
import stripAnsi from "strip-ansi";
import codeFrame, { codeFrameColumns } from "..";
describe("babel-code-frame", function () {
it("basic usage", function () {
const rawLines = [
"class Foo {",
" constructor()",
"};",
].join("\n");
assert.equal(codeFrame(rawLines, 2, 16), [
" 1 | class Foo {",
"> 2 | constructor()",
" | ^",
" 3 | };",
].join("\n"));
describe("babel-code-frame", function() {
it("basic usage", function() {
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
assert.equal(
codeFrame(rawLines, 2, 16),
[
" 1 | class Foo {",
"> 2 | constructor()",
" | ^",
" 3 | };",
].join("\n"),
);
});
it("optional column number", function () {
const rawLines = [
"class Foo {",
" constructor()",
"};",
].join("\n");
assert.equal(codeFrame(rawLines, 2, null), [
" 1 | class Foo {",
"> 2 | constructor()",
" 3 | };",
].join("\n"));
it("optional column number", function() {
const rawLines = ["class Foo {", " constructor()", "};"].join("\n");
assert.equal(
codeFrame(rawLines, 2, null),
[" 1 | class Foo {", "> 2 | constructor()", " 3 | };"].join("\n"),
);
});
it("maximum context lines and padding", function () {
it("maximum context lines and padding", function() {
const rawLines = [
"/**",
" * Sums two numbers.",
@@ -44,18 +39,21 @@ describe("babel-code-frame", function () {
" return a + b",
"}",
].join("\n");
assert.equal(codeFrame(rawLines, 7, 2), [
" 5 | * @param b Number",
" 6 | * @returns Number",
"> 7 | */",
" | ^",
" 8 | ",
" 9 | function sum(a, b) {",
" 10 | return a + b",
].join("\n"));
assert.equal(
codeFrame(rawLines, 7, 2),
[
" 5 | * @param b Number",
" 6 | * @returns Number",
"> 7 | */",
" | ^",
" 8 | ",
" 9 | function sum(a, b) {",
" 10 | return a + b",
].join("\n"),
);
});
it("no unnecessary padding due to one-off errors", function () {
it("no unnecessary padding due to one-off errors", function() {
const rawLines = [
"/**",
" * Sums two numbers.",
@@ -69,43 +67,49 @@ describe("babel-code-frame", function () {
" return a + b",
"}",
].join("\n");
assert.equal(codeFrame(rawLines, 6, 2), [
" 4 | * @param a Number",
" 5 | * @param b Number",
"> 6 | * @returns Number",
" | ^",
" 7 | */",
" 8 | ",
" 9 | function sum(a, b) {",
].join("\n"));
assert.equal(
codeFrame(rawLines, 6, 2),
[
" 4 | * @param a Number",
" 5 | * @param b Number",
"> 6 | * @returns Number",
" | ^",
" 7 | */",
" 8 | ",
" 9 | function sum(a, b) {",
].join("\n"),
);
});
it("tabs", function () {
it("tabs", function() {
const rawLines = [
"\tclass Foo {",
"\t \t\t constructor\t(\t)",
"\t};",
].join("\n");
assert.equal(codeFrame(rawLines, 2, 25), [
" 1 | \tclass Foo {",
"> 2 | \t \t\t constructor\t(\t)",
" | \t \t\t \t \t ^",
" 3 | \t};",
].join("\n"));
assert.equal(
codeFrame(rawLines, 2, 25),
[
" 1 | \tclass Foo {",
"> 2 | \t \t\t constructor\t(\t)",
" | \t \t\t \t \t ^",
" 3 | \t};",
].join("\n"),
);
});
it("opts.highlightCode", function () {
it("opts.highlightCode", function() {
const rawLines = "console.log('babel')";
const result = codeFrame(rawLines, 1, 9, { highlightCode: true });
const stripped = chalk.stripColor(result);
const stripped = stripAnsi(result);
assert.ok(result.length > stripped.length);
assert.equal(stripped, [
"> 1 | console.log('babel')",
" | ^",
].join("\n"));
assert.equal(
stripped,
["> 1 | console.log('babel')", " | ^"].join("\n"),
);
});
it("opts.linesAbove", function () {
it("opts.linesAbove", function() {
const rawLines = [
"/**",
" * Sums two numbers.",
@@ -119,17 +123,20 @@ describe("babel-code-frame", function () {
" return a + b",
"}",
].join("\n");
assert.equal(codeFrame(rawLines, 7, 2, { linesAbove: 1 }), [
" 6 | * @returns Number",
"> 7 | */",
" | ^",
" 8 | ",
" 9 | function sum(a, b) {",
" 10 | return a + b",
].join("\n"));
assert.equal(
codeFrame(rawLines, 7, 2, { linesAbove: 1 }),
[
" 6 | * @returns Number",
"> 7 | */",
" | ^",
" 8 | ",
" 9 | function sum(a, b) {",
" 10 | return a + b",
].join("\n"),
);
});
it("opts.linesBelow", function () {
it("opts.linesBelow", function() {
const rawLines = [
"/**",
" * Sums two numbers.",
@@ -143,16 +150,19 @@ describe("babel-code-frame", function () {
" return a + b",
"}",
].join("\n");
assert.equal(codeFrame(rawLines, 7, 2, { linesBelow: 1 }), [
" 5 | * @param b Number",
" 6 | * @returns Number",
"> 7 | */",
" | ^",
" 8 | ",
].join("\n"));
assert.equal(
codeFrame(rawLines, 7, 2, { linesBelow: 1 }),
[
" 5 | * @param b Number",
" 6 | * @returns Number",
"> 7 | */",
" | ^",
" 8 | ",
].join("\n"),
);
});
it("opts.linesAbove and opts.linesBelow", function () {
it("opts.linesAbove and opts.linesBelow", function() {
const rawLines = [
"/**",
" * Sums two numbers.",
@@ -166,78 +176,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 +263,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 +276,8 @@ describe("babel-code-frame", function () {
"> 4 | }",
" | ^^^",
" 5 | };",
].join("\n"));
].join("\n"),
);
});
it("mark across multiple lines without columns", function() {
@@ -270,12 +289,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.12",
"version": "7.0.0-alpha.19",
"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.12",
"babel-generator": "7.0.0-alpha.12",
"babel-helpers": "7.0.0-alpha.12",
"babel-messages": "7.0.0-alpha.12",
"babel-template": "7.0.0-alpha.12",
"babel-traverse": "7.0.0-alpha.12",
"babel-types": "7.0.0-alpha.12",
"babylon": "7.0.0-beta.12",
"babel-code-frame": "7.0.0-alpha.19",
"babel-generator": "7.0.0-alpha.19",
"babel-helpers": "7.0.0-alpha.19",
"babel-messages": "7.0.0-alpha.19",
"babel-template": "7.0.0-alpha.19",
"babel-traverse": "7.0.0-alpha.19",
"babel-types": "7.0.0-alpha.19",
"babylon": "7.0.0-beta.19",
"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.12",
"babel-helper-transform-fixture-test-runner": "7.0.0-alpha.12",
"babel-polyfill": "7.0.0-alpha.12",
"babel-register": "7.0.0-alpha.12"
"babel-helper-transform-fixture-test-runner": "7.0.0-alpha.19",
"babel-register": "7.0.0-alpha.19"
}
}

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

@@ -1,5 +1,3 @@
// @flow
import * as context from "../index";
import Plugin from "./plugin";
import * as messages from "babel-messages";
@@ -11,14 +9,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 +77,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 +103,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 +154,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 +167,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 +207,7 @@ class OptionManager {
}
type BasicDescriptor = {
value: {}|Function,
value: {} | Function,
options: ?{},
dirname: string,
alias: string,
@@ -209,19 +217,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 +249,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 +279,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 +292,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 +310,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 +364,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 +416,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 +443,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 +458,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 +485,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 +508,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 +524,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,40 @@ export default class File extends Store {
resolveModuleSource(source: string): string {
const resolveModuleSource = this.opts.resolveModuleSource;
if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename);
if (resolveModuleSource) {
source = resolveModuleSource(source, this.opts.filename);
}
return source;
}
addImport(source: string, imported: string, name?: string = imported): Object {
addImport(
source: string,
imported?: string = "",
name?: string = imported,
): Object | null {
const prependDeclaration = (
specifiers: Array<BabelNodeImportSpecifier>,
): void => {
const declar = t.importDeclaration(specifiers, t.stringLiteral(source));
declar._blockHoist = 3;
this.path.unshiftContainer("body", declar);
};
// import "module-name";
if (!imported) {
prependDeclaration([]);
return null;
}
const alias = `${source}:${imported}`;
let id = this.dynamicImportIds[alias];
if (!id) {
source = this.resolveModuleSource(source);
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(name);
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(
name,
);
const specifiers = [];
@@ -194,10 +217,7 @@ export default class File extends Store {
specifiers.push(t.importSpecifier(id, t.identifier(imported)));
}
const declar = t.importDeclaration(specifiers, t.stringLiteral(source));
declar._blockHoist = 3;
this.path.unshiftContainer("body", declar);
prependDeclaration(specifiers);
}
return id;
@@ -222,11 +242,12 @@ export default class File extends Store {
}
const ref = getHelper(name);
const uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
name,
));
if (t.isFunctionExpression(ref) && !ref.id) {
ref.body._compact = true;
ref._generated = true;
ref.id = uid;
ref.type = "FunctionDeclaration";
this.path.unshiftContainer("body", ref);
@@ -257,7 +278,9 @@ export default class File extends Store {
const declar = this.declarations[name];
if (declar) return declar;
const uid = this.declarations[name] = this.scope.generateUidIdentifier("templateObject");
const uid = (this.declarations[name] = this.scope.generateUidIdentifier(
"templateObject",
));
const helperId = this.addHelper(helperName);
const init = t.callExpression(helperId, [strings, raw]);
@@ -270,7 +293,11 @@ export default class File extends Store {
return uid;
}
buildCodeFrameError(node: Object, msg: string, Error: typeof Error = SyntaxError): Error {
buildCodeFrameError(
node: Object,
msg: string,
Error: typeof Error = SyntaxError,
): Error {
const loc = node && (node.loc || node._loc);
const err = new Error(msg);
@@ -280,7 +307,8 @@ export default class File extends Store {
} else {
traverse(node, errorVisitor, this.scope, err);
err.message += " (This is an error on an internal node. Probably an internal error";
err.message +=
" (This is an error on an internal node. Probably an internal error";
if (err.loc) {
err.message += ". Location has been estimated.";
@@ -308,7 +336,7 @@ export default class File extends Store {
// single source file to a single output file.
const source = outputMapConsumer.sources[0];
inputMapConsumer.eachMapping(function (mapping) {
inputMapConsumer.eachMapping(function(mapping) {
const generatedPosition = outputMapConsumer.generatedPositionFor({
line: mapping.generatedLine,
column: mapping.generatedColumn,
@@ -318,10 +346,13 @@ export default class File extends Store {
mergedGenerator.addMapping({
source: mapping.source,
original: mapping.source == null ? null : {
line: mapping.originalLine,
column: mapping.originalColumn,
},
original:
mapping.source == null
? null
: {
line: mapping.originalLine,
column: mapping.originalColumn,
},
generated: generatedPosition,
});
@@ -385,15 +416,15 @@ export default class File extends Store {
const passes = [];
const visitors = [];
for (const [ plugin, pluginOpts ] of pluginPairs.concat(INTERNAL_PLUGINS)) {
for (const [plugin, pluginOpts] of pluginPairs.concat(INTERNAL_PLUGINS)) {
const pass = new PluginPass(this, plugin.key, pluginOpts);
passPairs.push([ plugin, pass ]);
passPairs.push([plugin, pass]);
passes.push(pass);
visitors.push(plugin.visitor);
}
for (const [ plugin, pass ] of passPairs) {
for (const [plugin, pass] of passPairs) {
const fn = plugin.pre;
if (fn) fn.call(pass, this);
}
@@ -401,16 +432,19 @@ export default class File extends Store {
debug(this.opts, "Start transform traverse");
// merge all plugin visitors into a single visitor
const visitor = traverse.visitors.merge(visitors, passes, this.opts.wrapPluginVisitorMethod);
const visitor = traverse.visitors.merge(
visitors,
passes,
this.opts.wrapPluginVisitorMethod,
);
traverse(this.ast, visitor, this.scope);
debug(this.opts, "End transform traverse");
for (const [ plugin, pass ] of passPairs) {
for (const [plugin, pass] of passPairs) {
const fn = plugin.post;
if (fn) fn.call(pass, this);
}
}
return this.generate();
@@ -428,11 +462,17 @@ export default class File extends Store {
err._babel = true;
}
let message = err.message = `${this.opts.filename}: ${err.message}`;
let message = (err.message = `${this.opts.filename}: ${err.message}`);
const loc = err.loc;
if (loc) {
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, this.opts);
const location = {
start: {
line: loc.line,
column: loc.column + 1,
},
};
err.codeFrame = codeFrameColumns(code, location, this.opts);
message += "\n" + err.codeFrame;
}
@@ -524,8 +564,11 @@ export default class File extends Store {
debug(this.opts, "Generation start");
const _result = gen(ast, opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
this.code);
const _result = gen(
ast,
opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts,
this.code,
);
result.code = _result.code;
result.map = _result.map;

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

@@ -0,0 +1,30 @@
var res = transform("", {
plugins: [
function (b) {
return {
visitor: {
Program: function(path, state) {
var file = state.file;
file.addImport("import-star", "*", "lib");
file.addImport("import-default", "default", "foo");
file.addImport("import-alias", "bar", "baz");
file.addImport("import-default-alias", "quux");
file.addImport("import-empty", "");
file.addImport("import-none");
}
}
};
}
]
});
var expected = multiline([
'import "import-none";',
'import "import-empty";',
'import { quux as _quux } from "import-default-alias";',
'import { bar as _baz } from "import-alias";',
'import _foo from "import-default";',
'import * as _lib from "import-star";',
]);
assert.equal(res.code, expected);

View File

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

View File

@@ -3,11 +3,12 @@ var Foo = function (_Bar) {
function Foo(options) {
babelHelpers.classCallCheck(this, Foo);
var parentOptions = {};
parentOptions.init = function () {
this;
};
return babelHelpers.possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).call(this, parentOptions));
}

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

@@ -1,7 +1,8 @@
"use strict";
var _values = values;
value = _values[fieldName];
rest = babelHelpers.objectWithoutProperties(_values, [fieldName]);
var error = void 0;
var _fieldName = fieldName;
value = _values[_fieldName];
rest = babelHelpers.objectWithoutProperties(_values, [_fieldName].map(babelHelpers.toPropertyKey));
_values;
var error = void 0;

View File

@@ -1,4 +1,2 @@
#!/usr/bin/env node
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.12",
"version": "7.0.0-alpha.19",
"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.12",
"babel-types": "7.0.0-alpha.12",
"detect-indent": "^4.0.0",
"jsesc": "^1.3.0",
"babel-messages": "7.0.0-alpha.19",
"babel-types": "7.0.0-alpha.19",
"jsesc": "^2.5.1",
"lodash": "^4.2.0",
"source-map": "^0.5.0",
"trim-right": "^1.0.1"
},
"devDependencies": {
"babel-helper-fixtures": "7.0.0-alpha.12",
"babylon": "^7.0.0-beta.12"
"babel-helper-fixtures": "7.0.0-alpha.19",
"babylon": "^7.0.0-beta.19"
}
}

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

@@ -8,6 +8,18 @@ export function ClassDeclaration(node: Object, parent: Object) {
this.printJoin(node.decorators, node);
}
if (node.declare) {
// TS
this.word("declare");
this.space();
}
if (node.abstract) {
// TS
this.word("abstract");
this.space();
}
this.word("class");
if (node.id) {
@@ -59,10 +71,25 @@ export function ClassBody(node: Object) {
export function ClassProperty(node: Object) {
this.printJoin(node.decorators, node);
if (node.accessibility) {
// TS
this.word(node.accessibility);
this.space();
}
if (node.static) {
this.word("static");
this.space();
}
if (node.abstract) {
// TS
this.word("abstract");
this.space();
}
if (node.readonly) {
// TS
this.word("readonly");
this.space();
}
if (node.computed) {
this.token("[");
this.print(node.key, node);
@@ -71,6 +98,12 @@ export function ClassProperty(node: Object) {
this._variance(node);
this.print(node.key, node);
}
if (node.optional) {
// TS
this.token("?");
}
this.print(node.typeAnnotation, node);
if (node.value) {
this.space();
@@ -82,12 +115,30 @@ export function ClassProperty(node: Object) {
}
export function ClassMethod(node: Object) {
this._classMethodHead(node);
this.space();
this.print(node.body, node);
}
export function _classMethodHead(node) {
this.printJoin(node.decorators, node);
if (node.accessibility) {
// TS
this.word(node.accessibility);
this.space();
}
if (node.abstract) {
// TS
this.word("abstract");
this.space();
}
if (node.static) {
this.word("static");
this.space();
}
this._method(node);
this._methodHead(node);
}

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,22 @@ 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;
}
this.print(node.typeParameters, node); // TS
if (node.optional) {
this.token("?.");
}
this.token("(");
this.printList(node.arguments, node);
this.token(")");
@@ -79,34 +93,16 @@ export function Decorator(node: Object) {
this.newline();
}
function commaSeparatorNewline() {
this.token(",");
this.newline();
if (!this.endsWith("\n")) this.space();
}
export function CallExpression(node: Object) {
this.print(node.callee, node);
this.print(node.typeParameters, node); // TS
if (node.optional) {
this.token("?.");
}
this.token("(");
const isPrettyCall = node._prettyCall;
let separator;
if (isPrettyCall) {
separator = commaSeparatorNewline;
this.newline();
this.indent();
}
this.printList(node.arguments, node, { separator });
if (isPrettyCall) {
this.newline();
this.dedent();
}
this.printList(node.arguments, node);
this.token(")");
}
@@ -115,7 +111,7 @@ export function Import() {
}
function buildYieldAwait(keyword: string) {
return function (node: Object) {
return function(node: Object) {
this.word(keyword);
if (node.delegate) {
@@ -156,8 +152,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 +201,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,6 @@
import * as t from "babel-types";
import { ExportAllDeclaration } from "./modules";
export function AnyTypeAnnotation() {
this.word("any");
}
@@ -20,24 +23,47 @@ 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);
this.print(node.id.typeAnnotation.typeAnnotation, node);
if (node.predicate) {
this.space();
this.print(node.predicate, node);
}
this.semicolon();
}
export function InferredPredicate(/*node: Object*/) {
this.token("%");
this.word("checks");
}
export function DeclaredPredicate(node: Object) {
this.token("%");
this.word("checks");
this.token("(");
this.print(node.value, node);
this.token(")");
}
export function DeclareInterface(node: Object) {
this.word("declare");
this.space();
@@ -69,9 +95,19 @@ export function DeclareTypeAlias(node: Object) {
this.TypeAlias(node);
}
export function DeclareVariable(node: Object) {
this.word("declare");
this.space();
export function DeclareOpaqueType(node: Object, parent: Object) {
if (!t.isDeclareExportDeclaration(parent)) {
this.word("declare");
this.space();
}
this.OpaqueType(node);
}
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 +115,50 @@ 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();
ExportAllDeclaration.apply(this, arguments);
}
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 +180,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 +207,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);
@@ -225,38 +311,27 @@ export function TypeAlias(node: Object) {
this.semicolon();
}
export function TypeAnnotation(node: Object) {
this.token(":");
export function OpaqueType(node: Object) {
this.word("opaque");
this.space();
if (node.optional) this.token("?");
this.print(node.typeAnnotation, node);
}
export function TypeParameter(node: Object) {
this._variance(node);
this.word(node.name);
if (node.bound) {
this.print(node.bound, node);
this.word("type");
this.space();
this.print(node.id, node);
this.print(node.typeParameters, node);
if (node.supertype) {
this.token(":");
this.space();
this.print(node.supertype, node);
}
if (node.default) {
if (node.impltype) {
this.space();
this.token("=");
this.space();
this.print(node.default, node);
this.print(node.impltype, node);
}
this.semicolon();
}
export function TypeParameterInstantiation(node: Object) {
this.token("<");
this.printList(node.params, node, {});
this.token(">");
}
export { TypeParameterInstantiation as TypeParameterDeclaration };
export function ObjectTypeAnnotation(node: Object) {
if (node.exact) {
this.token("{|");
@@ -264,7 +339,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

@@ -8,3 +8,5 @@ export * from "./types";
export * from "./flow";
export * from "./base";
export * from "./jsx";
export * from "./tsFlowCommon";
export * from "./typescript";

View File

@@ -3,20 +3,31 @@ import * as t from "babel-types";
export function _params(node: Object) {
this.print(node.typeParameters, node);
this.token("(");
this.printList(node.params, node, {
iterator: (node) => {
if (node.optional) this.token("?");
this.print(node.typeAnnotation, node);
},
});
this._parameters(node.params, node);
this.token(")");
if (node.returnType) {
this.print(node.returnType, node);
this.print(node.returnType, node);
}
export function _parameters(parameters, parent) {
for (let i = 0; i < parameters.length; i++) {
this._param(parameters[i], parent);
if (i < parameters.length - 1) {
this.token(",");
this.space();
}
}
}
export function _method(node: Object) {
export function _param(parameter, parent) {
this.printJoin(parameter.decorators, parameter);
this.print(parameter, parent);
if (parameter.optional) this.token("?"); // TS / flow
this.print(parameter.typeAnnotation, parameter); // TS / flow
}
export function _methodHead(node: Object) {
const kind = node.kind;
const key = node.key;
@@ -44,12 +55,25 @@ export function _method(node: Object) {
this.print(key, node);
}
if (node.optional) {
// TS
this.token("?");
}
this._params(node);
this.space();
this.print(node.body, node);
}
export function FunctionExpression(node: Object) {
export function _predicate(node: Object) {
if (node.predicate) {
if (!node.returnType) {
this.token(":");
}
this.space();
this.print(node.predicate, node);
}
}
export function _functionHead(node: Object) {
if (node.async) {
this.word("async");
this.space();
@@ -57,14 +81,17 @@ export function FunctionExpression(node: Object) {
this.word("function");
if (node.generator) this.token("*");
this.space();
if (node.id) {
this.space();
this.print(node.id, node);
} else {
this.space();
}
this._params(node);
this._predicate(node);
}
export function FunctionExpression(node: Object) {
this._functionHead(node);
this.space();
this.print(node.body, node);
}
@@ -79,12 +106,18 @@ 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);
}
this._predicate(node);
this.space();
this.token("=>");
this.space();
@@ -93,6 +126,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

@@ -44,6 +44,10 @@ export function ExportNamespaceSpecifier(node: Object) {
export function ExportAllDeclaration(node: Object) {
this.word("export");
this.space();
if (node.exportKind === "type") {
this.word("type");
this.space();
}
this.token("*");
this.space();
this.word("from");
@@ -91,7 +95,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 +145,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,14 +117,14 @@ 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];
if (label) {
this.space();
const terminatorState = this.startTerminatorless();
const isLabel = key == "label";
const terminatorState = this.startTerminatorless(isLabel);
this.print(label, node);
this.endTerminatorless(terminatorState);
}
@@ -170,10 +171,12 @@ export function TryStatement(node: Object) {
export function CatchClause(node: Object) {
this.word("catch");
this.space();
this.token("(");
this.print(node.param, node);
this.token(")");
this.space();
if (node.param) {
this.token("(");
this.print(node.param, node);
this.token(")");
this.space();
}
this.print(node.body, node);
}
@@ -233,6 +236,12 @@ function constDeclarationIndent() {
}
export function VariableDeclaration(node: Object, parent: Object) {
if (node.declare) {
// TS
this.word("declare");
this.space();
}
this.word(node.kind);
this.space();
@@ -261,7 +270,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

@@ -0,0 +1,38 @@
export function TypeAnnotation(node) {
this.token(":");
this.space();
if (node.optional) this.token("?");
this.print(node.typeAnnotation, node);
}
export function TypeParameterInstantiation(node): void {
this.token("<");
this.printList(node.params, node, {});
this.token(">");
}
export { TypeParameterInstantiation as TypeParameterDeclaration };
export function TypeParameter(node) {
this._variance(node);
this.word(node.name);
if (node.bound) {
this.print(node.bound, node);
}
if (node.constraint) {
this.space();
this.word("extends");
this.space();
this.print(node.constraint, node);
}
if (node.default) {
this.space();
this.token("=");
this.space();
this.print(node.default, node);
}
}

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;
@@ -33,7 +31,9 @@ export { ObjectExpression as ObjectPattern };
export function ObjectMethod(node: Object) {
this.printJoin(node.decorators, node);
this._method(node);
this._methodHead(node);
this.space();
this.print(node.body, node);
}
export function ObjectProperty(node: Object) {
@@ -45,8 +45,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 +57,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 +116,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

@@ -0,0 +1,456 @@
export function TSParameterProperty(node) {
if (node.accessibility) {
this.word(node.accessibility);
this.space();
}
if (node.readonly) {
this.word("readonly");
this.space();
}
this._param(node.parameter);
}
export function TSDeclareFunction(node) {
if (node.declare) {
this.word("declare");
this.space();
}
this._functionHead(node);
this.token(";");
}
export function TSDeclareMethod(node) {
this._classMethodHead(node);
this.token(";");
}
export function TSQualifiedName(node) {
this.print(node.left, node);
this.token(".");
this.print(node.right, node);
}
export function TSCallSignatureDeclaration(node) {
this.tsPrintSignatureDeclarationBase(node);
}
export function TSConstructSignatureDeclaration(node) {
this.word("new");
this.space();
this.tsPrintSignatureDeclarationBase(node);
}
export function TSPropertySignature(node) {
const { readonly, initializer } = node;
if (readonly) {
this.word("readonly");
this.space();
}
this.tsPrintPropertyOrMethodName(node);
this.print(node.typeAnnotation, node);
if (initializer) {
this.space();
this.token("=");
this.space();
this.print(initializer, node);
}
this.token(";");
}
export function tsPrintPropertyOrMethodName(node) {
if (node.computed) {
this.token("[");
}
this.print(node.key, node);
if (node.computed) {
this.token("]");
}
if (node.optional) {
this.token("?");
}
}
export function TSMethodSignature(node) {
this.tsPrintPropertyOrMethodName(node);
this.tsPrintSignatureDeclarationBase(node);
this.token(";");
}
export function TSIndexSignature(node) {
const { readonly } = node;
if (readonly) {
this.word("readonly");
this.space();
}
this.token("[");
this._parameters(node.parameters, node);
this.token("]");
this.print(node.typeAnnotation, node);
this.token(";");
}
export function TSAnyKeyword() {
this.word("any");
}
export function TSNumberKeyword() {
this.word("number");
}
export function TSObjectKeyword() {
this.word("object");
}
export function TSBooleanKeyword() {
this.word("boolean");
}
export function TSStringKeyword() {
this.word("string");
}
export function TSSymbolKeyword() {
this.word("symbol");
}
export function TSVoidKeyword() {
this.word("void");
}
export function TSUndefinedKeyword() {
this.word("undefined");
}
export function TSNullKeyword() {
this.word("null");
}
export function TSNeverKeyword() {
this.word("never");
}
export function TSThisType() {
this.word("this");
}
export function TSFunctionType(node) {
this.tsPrintFunctionOrConstructorType(node);
}
export function TSConstructorType(node) {
this.word("new");
this.space();
this.tsPrintFunctionOrConstructorType(node);
}
export function tsPrintFunctionOrConstructorType(
node: FunctionOrConstructorType,
) {
const { typeParameters, parameters } = node;
this.print(typeParameters, node);
this.token("(");
this._parameters(parameters, node);
this.token(")");
this.space();
this.token("=>");
this.space();
this.print(node.typeAnnotation.typeAnnotation, node);
}
export function TSTypeReference(node) {
this.print(node.typeName, node);
this.print(node.typeParameters, node);
}
export function TSTypePredicate(node) {
this.print(node.parameterName);
this.space();
this.word("is");
this.space();
this.print(node.typeAnnotation.typeAnnotation);
}
export function TSTypeQuery(node) {
this.word("typeof");
this.space();
this.print(node.exprName);
}
export function TSTypeLiteral(node) {
this.tsPrintTypeLiteralOrInterfaceBody(node.members, node);
}
export function tsPrintTypeLiteralOrInterfaceBody(members, node) {
this.tsPrintBraced(members, node);
}
export function tsPrintBraced(members, node) {
this.token("{");
if (members.length) {
this.indent();
this.newline();
for (const member of members) {
this.print(member, node);
//this.token(sep);
this.newline();
}
this.dedent();
this.rightBrace();
} else {
this.token("}");
}
}
export function TSArrayType(node) {
this.print(node.elementType);
this.token("[]");
}
export function TSTupleType(node) {
this.token("[");
this.printList(node.elementTypes, node);
this.token("]");
}
export function TSUnionType(node) {
this.tsPrintUnionOrIntersectionType(node, "|");
}
export function TSIntersectionType(node) {
this.tsPrintUnionOrIntersectionType(node, "&");
}
export function tsPrintUnionOrIntersectionType(node, sep) {
this.printJoin(node.types, node, {
separator() {
this.space();
this.token(sep);
this.space();
},
});
}
export function TSParenthesizedType(node) {
this.token("(");
this.print(node.typeAnnotation, node);
this.token(")");
}
export function TSTypeOperator(node) {
this.token(node.operator);
this.space();
this.print(node.typeAnnotation, node);
}
export function TSIndexedAccessType(node) {
this.print(node.objectType, node);
this.token("[");
this.print(node.indexType, node);
this.token("]");
}
export function TSMappedType(node) {
const { readonly, typeParameter, optional } = node;
this.token("{");
this.space();
if (readonly) {
this.word("readonly");
this.space();
}
this.token("[");
this.word(typeParameter.name);
this.space();
this.word("in");
this.space();
this.print(typeParameter.constraint, typeParameter);
this.token("]");
if (optional) {
this.token("?");
}
this.token(":");
this.space();
this.print(node.typeAnnotation, node);
this.space();
this.token("}");
}
export function TSLiteralType(node) {
this.print(node.literal, node);
}
export function TSExpressionWithTypeArguments(node) {
this.print(node.expression, node);
this.print(node.typeParameters, node);
}
export function TSInterfaceDeclaration(node) {
const { declare, id, typeParameters, extends: extendz, body } = node;
if (declare) {
this.word("declare");
this.space();
}
this.word("interface");
this.space();
this.print(id, node);
this.print(typeParameters, node);
if (extendz) {
this.space();
this.word("extends");
this.space();
this.printList(extendz, node);
}
this.space();
this.print(body, node);
}
export function TSInterfaceBody(node) {
this.tsPrintTypeLiteralOrInterfaceBody(node.body, node);
}
export function TSTypeAliasDeclaration(node) {
const { declare, id, typeParameters, typeAnnotation } = node;
if (declare) {
this.word("declare");
this.space();
}
this.word("type");
this.space();
this.print(id, node);
this.print(typeParameters, node);
this.space();
this.token("=");
this.space();
this.print(typeAnnotation, node);
this.token(";");
}
export function TSAsExpression(node) {
const { expression, typeAnnotation } = node;
this.print(expression, node);
this.space();
this.word("as");
this.space();
this.print(typeAnnotation, node);
}
export function TSTypeAssertion(node) {
const { typeAnnotation, expression } = node;
this.token("<");
this.print(typeAnnotation, node);
this.token(">");
this.space();
this.print(expression, node);
}
export function TSEnumDeclaration(node) {
const { declare, const: isConst, id, members } = node;
if (declare) {
this.word("declare");
this.space();
}
if (isConst) {
this.word("const");
this.space();
}
this.word("enum");
this.space();
this.print(id, node);
this.space();
this.tsPrintBraced(members, node);
}
export function TSEnumMember(node) {
const { id, initializer } = node;
this.print(id, node);
if (initializer) {
this.space();
this.token("=");
this.space();
this.print(initializer, node);
}
this.token(",");
}
export function TSModuleDeclaration(node) {
const { declare, id } = node;
if (declare) {
this.word("declare");
this.space();
}
if (!node.global) {
this.word(id.type === "Identifier" ? "namespace" : "module");
this.space();
}
this.print(id, node);
if (!node.body) {
this.token(";");
return;
}
let body = node.body;
while (body.type === "TSModuleDeclaration") {
this.token(".");
this.print(body.id, body);
body = body.body;
}
this.space();
this.print(body, node);
}
export function TSModuleBlock(node) {
this.tsPrintBraced(node.body, node);
}
export function TSImportEqualsDeclaration(node) {
const { isExport, id, moduleReference } = node;
if (isExport) {
this.word("export");
this.space();
}
this.word("import");
this.space();
this.print(id, node);
this.space();
this.token("=");
this.space();
this.print(moduleReference, node);
this.token(";");
}
export function TSExternalModuleReference(node) {
this.token("require(");
this.print(node.expression, node);
this.token(")");
}
export function TSNonNullExpression(node) {
this.print(node.expression, node);
this.token("!");
}
export function TSExportAssignment(node) {
this.word("export");
this.space();
this.token("=");
this.space();
this.print(node.expression, node);
this.token(";");
}
export function TSNamespaceExportDeclaration(node) {
this.word("export");
this.space();
this.word("as");
this.space();
this.word("namespace");
this.space();
this.print(node.id, node);
}
export function tsPrintSignatureDeclarationBase(node) {
const { typeParameters, parameters } = node;
this.print(typeParameters, node);
this.token("(");
this._parameters(parameters, node);
this.token(")");
this.print(node.typeAnnotation, node);
}

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;
@@ -75,14 +93,24 @@ export function Binary(node: Object, parent: Object): boolean {
return false;
}
export function TSAsExpression() {
return true;
}
export function TSTypeAssertion() {
return true;
}
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 +134,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 +180,10 @@ 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) ||
t.isTSTypeAssertion(parent) ||
t.isTSAsExpression(parent)
) {
return true;
}
@@ -169,10 +201,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 +213,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,40 +11,39 @@ 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;
_printedCommentStarts: Object = {};
_parenPushNewlineState: ?Object = null;
_noLineTerminator: boolean = false;
_printAuxAfterOnNextUserNode: boolean = false;
_printedComments: WeakSet = new WeakSet();
_endsWithInteger = false;
@@ -107,7 +103,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 +148,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();
}
@@ -283,7 +282,7 @@ export default class Printer {
*
* This is to prevent breaking semantics for terminatorless separator nodes. eg:
*
* return foo;
* return foo;
*
* returns `foo`. But if we do:
*
@@ -293,10 +292,15 @@ export default class Printer {
* `undefined` will be returned and not `foo` due to the terminator.
*/
startTerminatorless(): Object {
return this._parenPushNewlineState = {
printed: false,
};
startTerminatorless(isLabel: boolean = false): Object {
if (isLabel) {
this._noLineTerminator = true;
return null;
} else {
return (this._parenPushNewlineState = {
printed: false,
});
}
}
/**
@@ -304,7 +308,8 @@ export default class Printer {
*/
endTerminatorless(state: Object) {
if (state.printed) {
this._noLineTerminator = false;
if (state && state.printed) {
this.dedent();
this.newline();
this.token(")");
@@ -321,8 +326,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 +343,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 +352,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 +401,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 +499,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 +514,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 +534,33 @@ 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() && !this._noLineTerminator && isBlockComment
? 1
: 0,
);
if (!this.endsWith("[") && !this.endsWith("{")) this.space();
let val = comment.type === "CommentLine" ? `//${comment.value}\n` : `/*${comment.value}*/`;
let val =
!isBlockComment && !this._noLineTerminator
? `//${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 +571,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 && !this._noLineTerminator ? 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

@@ -2,4 +2,4 @@ foo("foo");
foo("foo\nlol");
foo("foo\n\"lol");
foo("foo\n\"'lol");
foo("😂");
foo("😂");

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

@@ -0,0 +1 @@
{ "plugins": ["jsx"] }

View File

@@ -2,4 +2,4 @@ foo('foo');
foo('foo\nlol');
foo('foo\n"lol');
foo('foo\n"\'lol');
foo('😂');
foo('😂');

View File

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

View File

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

View File

@@ -1,2 +1,2 @@
{ print("hello"); // comment
}
}

View File

@@ -1,4 +1,4 @@
{
print("hello");
// comment
}
}

View File

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

View File

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

View File

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

View File

@@ -2,4 +2,4 @@
print("hello");
// comment2
print("hello2");
print("hello2");

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;

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