Compare commits

...

142 Commits

Author SHA1 Message Date
Nicolò Ribaudo
21228abfde v7.2.4 2018-12-20 13:08:41 +01:00
Nicolò Ribaudo
e417437355 Minify standalone 2018-12-20 12:50:41 +01:00
Nicolò Ribaudo
0bb720401b v7.2.3 2018-12-20 12:18:31 +01:00
Nicolò Ribaudo
d35f2ad92b Update lerna to v3.6.0
Use forked @lerna/collect-updates to prevent publishing of dependents:
this is the same as Lerna 2's --dangerously-only-publish-explicit-etc option.
2018-12-20 11:46:56 +01:00
Nicolò Ribaudo
57759cb1a1 [lerna] Don't ignore .json data files in preset-env (#9200) 2018-12-20 11:43:40 +01:00
Cameron Martin
9e95da4eaa Added type-level mapping between aliases and nodes that have that alias. (#9110) 2018-12-19 10:57:27 +01:00
Nicolò Ribaudo
911c2d0bf4 Use @babel/eslint-plugin-developement (#9206) 2018-12-18 22:59:43 +01:00
cphamlet
116ca22def Minor typo for -f flag in cli (#9201) 2018-12-17 19:29:23 -08:00
Tan Li Hau
52fb884550 Strips flow directive fully (#9197) 2018-12-17 09:27:56 +01:00
Daniel Tschinder
5cb38995c0 Allow keywords to be used in type annotations (#9184) 2018-12-15 12:51:24 -08:00
Andy Edwards
3c8e15dbc1 don't throw classNameTDZError if referenced identifier is within a TypeAnnotation (#9190)
fix #9189

Obviously this code is intended to throw an error if someone tries to reference a class before it's defined, like:
```js
class Foo {
  someField = Foo;
}
```
But there's no problem with referencing the class in a type annotation before it's defined, and this is often necessary for tree structures:
```js
class Foo {
  [someSymbol]: Foo;
}
```
2018-12-15 15:16:43 +01:00
Nicolò Ribaudo
c1499b13ac v7.2.2 2018-12-15 10:59:56 +01:00
Nicolò Ribaudo
7bcd62cfee Build standalone on prepublish 2018-12-15 10:52:23 +01:00
Daniel Tschinder
47da5cf75a Correctly transform spreads to use proper concat method (#9108)
* Correctly transform spreads to use proper concat method

* Add tests to ensure array spread clones elements
2018-12-13 23:24:43 -08:00
Vikram Rangaraj
72471aff63 Handle flow comments with leading spaces (#9168)
* check for spaces and tabs before a flow comment

* fix issue with using string index and shift interchangably

* update tests

* Use update charcodes version

* Disallow flow-comments in flow-comments and check for unterminated comments
2018-12-13 22:10:01 -08:00
Patrick Eriksson
b9340bc597 Fix package.json repository URLs (#9176) 2018-12-13 21:15:40 +01:00
Thiago Arrais
731182eee4 Types for pipeline operator (smart proposal) (#9122) 2018-12-13 06:58:58 +01:00
Daniel Tschinder
f4eec5ca79 Add new flag that indicates if a module has exports (#9171) 2018-12-12 21:24:44 -08:00
Nicolò Ribaudo
b60adce4cb Update CHANGELOG.md 2018-12-12 23:56:33 +01:00
Henry Zhu
66c4bc8f64 update list of sponsors [skip ci] 2018-12-12 16:07:49 -05:00
Daniel Tschinder
d2dc28ed2b add triage label to new issues [skip ci] (#9158) 2018-12-12 10:23:54 -08:00
Brian Ng
0514a9f903 Update v7 regression issue template link (#9157) 2018-12-10 12:00:52 -06:00
Nicolò Ribaudo
d1d3c823cc Move decorators transform to @babel/helper-create-class-features-plugin (#9059)
* Move decorators to @babel/plugin-class-features

* Minor refactoring

* Use the new helper package
2018-12-09 12:30:25 +01:00
Nicolò Ribaudo
9b005dedfd Fix --root-mode option in babel-node (#9148) 2018-12-07 22:47:56 +01:00
Rubén Norte
4fdb71151f Inherit properties in function from method in loose mode (#9135) 2018-12-07 15:57:48 +01:00
Brian Ng
f611bb016b Bump Babel deps (#9145) 2018-12-07 08:55:06 -06:00
Kagami Sascha Rosylight
4dff205dc1 Disable parameter-destructuring in Edge 18 (#9140) 2018-12-07 08:14:08 -06:00
Kagami Sascha Rosylight
72fd2d192c Add missing colon to issue template (#9143) 2018-12-07 13:32:36 +01:00
Daniel Tschinder
35815832b5 Move to travis vm based builds (#9133) 2018-12-05 15:02:37 -08:00
Daniel Tschinder
9c45b8faf7 Ensure we always use local versions of babel dependencies in tests (#9132) 2018-12-05 14:14:16 -08:00
Daniel Tschinder
ca2918ab13 Test local version of babel/types 2018-12-05 13:34:36 -08:00
Daniel Tschinder
d915f31bcb Add tests for createTypeAnnotationBasedOnTypeof 2018-12-05 13:24:55 -08:00
Daniel Tschinder
4ca35ef8b9 Fix running flow on travis and update flow (#9128)
* Fix running flow on travis and update flow

- ensure bootstrap is run before running flow as we need some generated files for correctly doing typechecks
- ensure that we only ignore the build directory inside the babel folder as currently we ignore everything because travis checks out into ‘/home/travis/build/’

* Fix all flow errors
2018-12-05 12:30:30 -08:00
Henry Zhu
4b73818c87 Update issue templates [skip ci] (#9131) 2018-12-05 13:58:53 -05:00
Joel Denning
d305419da6 Not depending on return value of super(). Fixes #9020. (#9060)
* Not depending on return value of super(). Fixes #9020.

* Feedback from nicolo-ribaudo

* Feedback -- fixing bad call to replaceWithMultiple
2018-12-04 21:50:17 +01:00
Nicolò Ribaudo
8b132c0889 v7.2.1 2018-12-04 16:21:47 +01:00
Nicolò Ribaudo
b927fb2a7e Don't use isClassPrivateMethod because is isn't supported in <7.2.0 (#9121) 2018-12-04 08:35:10 +01:00
Nicolò Ribaudo
282129ea66 v7.2.0 2018-12-03 20:00:35 +01:00
Nicolò Ribaudo
fc5d49b6f6 Add access:public to @babel/helper-create-class-features-plugin 2018-12-03 20:00:24 +01:00
Nicolò Ribaudo
6c2771c116 Add @babel/plugin-proposal-private-methods to @babel/standalone (#9115) 2018-12-03 19:40:00 +01:00
Sven Sauleau
fdc869ce16 Merge pull request #8289 from valtech-nyc/implement-smart-pipeline-in-parser
Implement Smart Pipeline proposal in @babel/parser
2018-12-03 19:28:45 +01:00
Daniel Tschinder
fa9df678ac Move tests from babylon to babel-parser and enable one test that works now 2018-12-03 00:46:54 -08:00
Daniel Tschinder
3932830535 Parse non-octals with leading zeros in non strict mode correctly (#9114)
* Parse non-octals with leading zeros in non strict mode correctly

* Better error message
2018-12-03 00:04:37 -08:00
Daniel Tschinder
07eaa3c63f Ignore empty fixture directories and fix fixtures in the parser (#9113)
* Ignore fixture directories that do not contain input or exec

* Fix parser test fixtures structures for some imported esprima tests.

* Warn on test folders that are not empty and do not contain testfiles
2018-12-02 22:55:06 -08:00
Daniel Tschinder
3530d11418 Update find-cache-dir (#9111)
Dropped support for node <6
2018-12-02 12:12:19 -08:00
Kai Cataldo
806e133473 Export @babel/parser#tokTypes in @babel/core (#8986)
* Export @babel/parser in @babel/core

* Expose tokTypes instead of parser
2018-11-30 18:41:58 -08:00
Veaceslav Cotruta
2bf8dde782 Propagates the extensions overrides provided by CLI during files walk (#8668)
* Propagates the extensions overrides provided by CLI during files walk

* Adds tests for issue #7620, PR #8668
2018-11-29 18:57:27 -08:00
Nicolò Ribaudo
4e28459a2f Make @babel/plugin-class-features a normal helper package (#9083)
* Make @babel/plugin-class-features a normal helper package

This effectively disallows using it directly.

* Rename helper

* Style

* Don't add prefix to plugin name

* Move private methods plugin
2018-11-29 16:42:45 +01:00
wtgtybhertgeghgtwtg
c4d6f6dcce Pass rootMode from @babel/node. (#9078)
* Pass `root-mode` from `@babel/node`.

* Filter `babelOptions`.
2018-11-28 21:29:38 -08:00
Tim McClure
0859535b62 Private class methods stage 3 (#8654)
* Add private method syntax support

* Add private method spec support

* Add private method loose support

* Throw error if static private method is used

* Add more isStatic & isMethod checks

* Remove `writable:false` from private method inits

`writable` is false by default.

* Add private method func obj equality check

* Throw if private accessor is used

* Add check for fields === private method loose mode

* Throw buildCodeFrameErrors instead of Errors

* Move obj destructuring inside for loop

* Remove "computed" from ClassPrivateMethod type def
2018-11-28 16:20:09 -08:00
Daniel Tschinder
6e39b58f8a Add node 11 to CI and remove node 9 (#9096) 2018-11-28 12:36:58 -08:00
Daniel Tschinder
559d649994 Skip minifying standalone (#9094)
Also remove unused dependency on uglify js. gulp-uglify uses its own version.
2018-11-28 12:36:24 -08:00
Brian Ng
3fda01b185 Update mapping for regex unicode plugin in preset-env (#9091) 2018-11-27 22:09:15 -06:00
Daniel Tschinder
4f2eacf615 chore: Fix warning when using prettier in code generators (#9093)
Also add more output to the generation
2018-11-27 19:34:11 -08:00
Gcaufy
0047ae84b3 Remove unused variable (#9089)
When I was reading the code, I see `parent` is not used in `_getComments` function.
so it make me confused why we delivery the `parent` in those functions.

If I'm wrong, please correct me.
2018-11-27 14:03:39 -08:00
Paul Happ
2bb24f996f Fix yield expression transform (#9076) 2018-11-27 09:45:06 -06:00
Nicolò Ribaudo
61f2aed5b0 Disallow await inside arrow functions (#9074)
* Disallow await inside arrow functions

* Update test262 whitelist
2018-11-26 12:43:04 +01:00
Ruben Verborgh
9308c870f5 Fix destructuring assignment in arrow functions. (#8916)
Fixes 8912.
2018-11-25 19:29:58 +01:00
wtgtybhertgeghgtwtg
1b8d664bbe Move fs-readdir-recursive and output-file-sync to devDependencies (#9079)
For `@babel/node`.
2018-11-25 18:04:03 +01:00
Justin Ridgewell
844dd33f3d Microbouji patch/8136 (#9073)
* Fix optional chaining bug regarding spread in function calls

* Revamp optional-chain to be top down

Instead of going both upwards and downwards from the first real optional expression, we can just start from the top down.

* Add more tests
2018-11-24 09:32:24 -05:00
Nicolò Ribaudo
856edbf95f [flow] Allow type casts in array patterns inside arrow parameters (#9069) 2018-11-24 12:23:49 +01:00
mAAdhaTTah
100b38784d Replace else with fall through 2018-11-21 21:07:03 -05:00
mAAdhaTTah
4cbd22a15f Hardcode "#" in error message
It's not going to be anything else...
2018-11-21 21:05:51 -05:00
Daniel Tschinder
d2971a1959 Fix compatibility between typescript and jsx plugins in interface declarations (#9058) 2018-11-21 15:58:50 -08:00
Brian Ng
4f16a12c03 Fix bug with parsing TS generic async arrow function (#9055) 2018-11-21 15:34:09 -06:00
Brian Ng
e7f0c065cf Bump some deps (#9056) 2018-11-21 15:21:36 -06:00
mAAdhaTTah
70318c9413 s/may/should 2018-11-21 16:02:34 -05:00
mAAdhaTTah
6e84352b51 PrimaryTopicReference -> PipelinePrimaryTopicReference 2018-11-21 15:54:56 -05:00
mAAdhaTTah
0eb9b2463d Move plugin check to pipeline op appearance
No need to recheck it throughout then.
2018-11-21 15:54:26 -05:00
Grigory Moroz
445b14148e Better error for disallowed trailing commas/parameters after rest elements (#9046)
* handle disordered rest parameter in function expressions

* remove spaces [lint]

* polish function parameters validation

* add test with arrow function and comma after rest parameter [babel-parser]
2018-11-21 07:49:36 +01:00
Brian Ng
61c1c77a28 Update mappings for node 10 in preset-env (#9048) 2018-11-20 15:29:45 -06:00
Nicolò Ribaudo
5979b0669b Merge class features plugins
* Create @babel/plugin-class-features

* Move class properties transformation logic to enanced-classes (#8130)
2018-11-20 21:14:35 +01:00
Daniel Tschinder
a2afb974be Fix parsing typescript function types with destructuring (#9035)
* Fix parsing typescript function types with destructuring

* Use integer instead of actual stack
2018-11-19 13:55:58 -08:00
Nicolò Ribaudo
c11cdcb6d8 Fix recursive async function expressions (#9039)
* Fix recursive async function expressions

* Update fixtures
2018-11-19 17:19:54 +01:00
Nicolò Ribaudo
8c7d4b55c9 Add plugins name (#8769)
* Add plugins name

* Add missing names found by the plugin

* Add eslint plugin
2018-11-18 23:02:58 +01:00
Sergey Rubanov
88696601e1 Add Node 11 support (#9037) 2018-11-18 08:17:06 -07:00
Logan Smyth
20a9d71016 Normalize presets before merging config with others. (#9034) 2018-11-16 21:23:23 -08:00
Daniel Tschinder
1af57e6f71 Fix test262 tests again! 2018-11-14 23:29:17 -08:00
Nicolò Ribaudo
4e1d6e7ff4 v7.1.6 2018-11-13 22:10:06 +01:00
Henry Zhu
efb71ea12b fix publish command [skip ci] (#8982) 2018-11-13 11:47:05 -08:00
Logan Smyth
cbbb3c7962 Ensure that the arrow nodes have a location before using them. (#9003) 2018-11-12 17:10:49 -08:00
Greg Bergé
4fcee1751a Fix cloneNode with typeAnnotation. (#8997)
Fixes #8996
2018-11-12 17:10:09 -08:00
Tien Pham
efa571a42c Update CHANGELOG.md (#9014) 2018-11-11 23:33:56 +01:00
Alican Çubukçuoğlu
bf8c4785f2 Fix "TypeError: comments is not iterable" (#8701) 2018-11-09 13:58:28 -08:00
Brian Ng
4f206b2416 prettier@1.15.1 (#9001) 2018-11-09 15:25:13 -06:00
Daniel Tschinder
504b331da4 Fix browser files to have the same API as the nodejs ones (#9004) 2018-11-09 13:11:46 -08:00
Daniel Tschinder
74f969b603 Update debug dependency (#8989) 2018-11-09 16:27:41 +01:00
Remi Liu
4dfd801887 [Types] fix generated TS/Flow comment types (#9007) 2018-11-09 09:03:53 -06:00
Daniel Tschinder
62233ed7c9 Update json5 to latest version (#8990) 2018-11-08 17:29:13 -08:00
ylemkimon
7b54ab620b preset-env: fix opera from esmodules target and Browserslist not used (#8555) 2018-11-08 10:29:49 -06:00
Daniel Tschinder
343f776ca5 Rename primitive types to reserved types (#8984) 2018-11-07 16:50:36 -06:00
Daniel Tschinder
756ded4d64 Remove definition of micromatch which was removed. (#8988) 2018-11-07 16:49:27 -06:00
Nicolò Ribaudo
b706e34fc8 [decorators] Correctly insert _initialize(this) after super(). (#8970)
* [decorators] Correctly insert `_initialize(this)` after `super()`.

This commit fixes to problem:
1) After `super();` statements, `_initialize(this)` was inserted without
   a trailing semicolon.
2) `(0, super())` causes an infinite recursion.

* Fix tests

* Add test
2018-11-06 21:58:09 -08:00
Daniel Tschinder
5d5cd8612f Fix several edge cases with context expression state (#8972)
* Fix several edge cases with context expression state

* Fix review comments

* Remove unused field
2018-11-06 19:37:24 -08:00
Henry Zhu
afe67a7035 v7.1.5 2018-11-06 17:21:22 -05:00
Nicolò Ribaudo
2fa1984635 Fix await in function name and parameters (#7727)
* Disallow await in function parameters

* Fix await as function name

* Update test whitelists
2018-11-06 08:30:06 +01:00
Retsam
2194842d11 Typescript: Validate tuple type element positions (#8828)
* feat: validate the positions of rest elements and optional elements in tuple types

Adds a validation step to the parser which raises syntax errors if a rest param is not at the end of a tuple, or if a mandatory param follows an optional parameter

* Fix spread after optional case; add test case
2018-11-05 23:19:34 -08:00
Daniel Tschinder
e3b2c1afff fix: Do not allow TypeCastExpressions w/o parens (#8956) 2018-11-05 15:34:24 -08:00
James Garbutt
b95cbc4a8e output aliased types in typescript declarations (#8629) 2018-11-05 23:58:57 +01:00
Nicolò Ribaudo
24c4901ff5 Remove Babylon plugins for features already merged to the ECMAScript spec (#8448)
These are now enabled by default:
- objectRestSpread (2018)
- asyncGenerators (2018)
- optionalCatchBInding (2019)
- jsonStrings (2019)

TODO (after this commit):
- [ ] Deprecate the `@babel/plugin-syntax-*` packages.
- [ ] Deprecate the `@babel/plugin-proposal-*` packages.
- [ ] Create the `@babel/plugin-transform-*` packages.
2018-11-05 23:48:06 +01:00
Daniel Tschinder
c125b1dd74 Update test262 commit, as old commit broke for some reason 2018-11-05 10:53:34 -08:00
Jordan Brown
f216a7b06f [flow] Add support for parsing _ as implicit instantiation in call/new (#8883)
* [flow] Add support for parsing  as implicit instantiation in call/new

* Update flow tests and fix underscore being a reserved type

* Rebase onto flow-test

* Fix flow commit hash
2018-11-05 10:45:40 -08:00
Logan Smyth
c6d2f45cab Resolve babel.config.js 'babelrcRoots' values relative to the config file. (#8910) 2018-11-05 08:51:27 -08:00
Daniel Tschinder
1d4d760ffc Update test262 to latest commit and enable mapping for features
Also added an automated check for new features which are not mapped or ignored
2018-11-04 18:49:53 +01:00
mAAdhaTTah
a0e94ec24d Move PipelineStyle to types.js file 2018-11-03 14:03:17 -04:00
mAAdhaTTah
b593af17a9 Replace codePointToString with ES6 method 2018-11-03 14:00:42 -04:00
mAAdhaTTah
4521204ea0 Merge branch 'master' into implement-smart-pipeline-in-parser
* master: (222 commits)
  Set correct methods name
  Use toPropertyKey in the "decorate" helper
  Allow function types in type params within arrow return types (#8954)
  Fix message when plugin of a wrong type is passed (#8950)
  rename colliding let bindings with for loop init (#8937)
  edge incomplete support for arrow destructuring (babel #8349) (#8926)
  fix single-arg async arrows when retainLines=true (#8868)
  [flow] Explicit inexact objects with `...` (#8884)
  Update preset-env data (#8898)
  Treat break inside block inside loop (#8914)
  fixed "source map" formatting in comment (#8878) [skip ci]
  fix typo in contributing guidelines (#8901) [skip ci]
  fix: Expression x === 'y' && '' should not evaluate to undefined. (#8880)
  fixed an extra word
  Fixes #8865 (#8866)
  v7.1.4
  v7.1.3
  Bump Babel deps (#8770)
  flow-bin@0.82.0 (#8832)
  Insertafter jsx fix (#8833)
  ...

# Conflicts:
#	packages/babel-parser/src/tokenizer/index.js
#	packages/babel-parser/test/fixtures/experimental/class-private-properties/failure-numeric-literal/options.json
#	packages/babel-parser/test/fixtures/experimental/pipeline-operator/invalid-proposal/options.json
2018-11-03 14:00:12 -04:00
Nicolò Ribaudo
d35563ee1a Set correct methods name 2018-11-02 13:59:57 +01:00
Nicolò Ribaudo
38397ce11f Use toPropertyKey in the "decorate" helper
This commit also makes the "toPropertyKey" helper call @@toPrimitive
when needed.
2018-11-02 13:59:57 +01:00
Daniel Tschinder
cd81b079ee Allow function types in type params within arrow return types (#8954) 2018-11-01 09:10:46 -05:00
everdimension
e85faec47d Fix message when plugin of a wrong type is passed (#8950) 2018-10-31 14:34:26 -05:00
Byron Luk
0d9e77f559 rename colliding let bindings with for loop init (#8937)
* rename colliding let bindings with for loop init

* added complex test case to check if loop init collisions were handled correctly

* updated test files
2018-10-31 20:28:36 +01:00
Ben Mosher
c82750a48a edge incomplete support for arrow destructuring (babel #8349) (#8926) 2018-10-31 10:15:27 -05:00
Ryan Marsh
de80aefece fix single-arg async arrows when retainLines=true (#8868) 2018-10-30 06:49:11 +01:00
Jordan Brown
e4929e11f6 [flow] Explicit inexact objects with ... (#8884) 2018-10-29 15:09:17 -05:00
Brian Ng
d942d47e10 Update preset-env data (#8898) 2018-10-25 09:48:41 -05:00
Thiago Arrais
84e7884d9c Treat break inside block inside loop (#8914) 2018-10-25 09:46:36 -05:00
0xflotus
9d0dcedb2b fixed "source map" formatting in comment (#8878) [skip ci] 2018-10-20 00:51:46 +02:00
Byron Luk
b576bf4b41 fix typo in contributing guidelines (#8901) [skip ci] 2018-10-19 08:49:33 +02:00
Cyp
e541d6031a fix: Expression x === 'y' && '' should not evaluate to undefined. (#8880)
Fixes https://github.com/babel/minify/issues/908.
2018-10-16 21:25:49 +02:00
Sven Sauleau
5fa3628506 Merge pull request #8873 from vvyomjjain/patch-1
fixed an extra word
2018-10-14 18:53:17 +02:00
Vyom Jain
f71e4660d4 fixed an extra word
"visit join" doesn't sound right. Either there is a word missing or the word 'visit' may be removed.
2018-10-14 22:14:02 +05:30
Byron Luk
929567523c Fixes #8865 (#8866) 2018-10-12 09:28:15 -05:00
James DiGioia
122906d525 Verify if MemberExpression is computed
If a property access is computed, e.g. a[b], then it's in topic style. Currently,
this isn't accounted for. Test & change ensures this doesn't parse.
2018-08-10 08:06:38 -04:00
James DiGioia
25d01460fd Fix error message for #4 case
This impact private fields as well as smart pipeline, providing a clearer
error message for both.
2018-08-10 07:52:55 -04:00
James DiGioia
ba5642d4ee Add test for computer properties
This seems to parse fine. Should it?
2018-08-09 22:08:39 -04:00
James DiGioia
15e6d844ae Remove additional parser logic
These are parsable only in follow-on proposals, not in the base proposal,
so we'll introduce that in a separate PR.
2018-08-09 22:08:23 -04:00
James DiGioia
d1cae2dec2 Remove unneeded comment
This is no longer true, now that we return `tt.hash`.
2018-08-09 21:10:43 -04:00
James DiGioia
11aee13ff2 Swap Yoda condition 2018-08-09 21:04:47 -04:00
James DiGioia
39e7ee6e65 Switch Pipeline types to extend NodeBase
This doesn't work because the `type` values are not compatible.
2018-07-22 18:55:12 -04:00
James DiGioia
094ef31c01 Wrap callback in try/finally
This ensures we clean up always if the callback throws.
2018-07-22 18:52:07 -04:00
James DiGioia
afd0638b74 Reuse hash token instead of new primaryTopicToken
Set whether we're in a pipeline in order to determine how to parse the
hash. The error message changes as a result, since the `hash` never
enters the block.
2018-07-22 18:46:31 -04:00
James DiGioia
6e41edb90f Fix TopicContextState type in Flow 2018-07-22 17:58:51 -04:00
James DiGioia
7931f4c241 Rename topicContextState -> .topicContext 2018-07-12 23:11:55 -04:00
James DiGioia
b847d40842 Inline readTopicContextState method 2018-07-12 23:10:07 -04:00
James DiGioia
e91a02cc49 Reuse declared type in function return value 2018-07-12 23:08:11 -04:00
James DiGioia
cc526940ee Quote proposals in error message 2018-07-12 23:07:09 -04:00
James DiGioia
7188820151 Delete commented code 2018-07-12 22:55:01 -04:00
James DiGioia
00845709ce Add comment for number sign 2018-07-12 22:48:53 -04:00
James DiGioia
b50fdc191e Inline function checkSmartPipelineHeadEarlyErrors
It's only used once.
2018-07-12 22:47:45 -04:00
James DiGioia
ef0f723fc5 Reverse yoda conditions
If "smart" proposal is, we'll no longer say.
2018-07-12 22:46:34 -04:00
J. S. Choi
fbf62b4830 Implement Smart Pipeline proposal in @babel/parser 2018-07-09 22:44:27 -04:00
1315 changed files with 42023 additions and 4932 deletions

View File

@@ -34,7 +34,7 @@ jobs:
build:
working_directory: ~/babel
docker:
- image: circleci/node:10
- image: circleci/node:11
steps:
- checkout
- restore-cache: *restore-yarn-cache

View File

@@ -1,7 +1,7 @@
{
"root": true,
"extends": "babel",
"plugins": ["local-rules", "prettier"],
"plugins": ["prettier", "@babel/development"],
"rules": {
"prettier/prettier": "error"
},
@@ -12,8 +12,8 @@
{
"files": ["packages/*/src/**/*.js", "codemods/*/src/**/*.js"],
"rules": {
"local-rules/no-undefined-identifier": "error",
"local-rules/no-deprecated-clone": "error"
"@babel/development/no-undefined-identifier": "error",
"@babel/development/no-deprecated-clone": "error"
}
},
{
@@ -26,6 +26,13 @@
"env": {
"jest": true
}
},
{
"files": ["packages/babel-plugin-*/src/index.js"],
"excludedFiles": ["packages/babel-plugin-transform-regenerator/**/*.js"],
"rules": {
"@babel/development/plugin-name": "error"
}
}
]
}

View File

@@ -1,11 +1,10 @@
[ignore]
.*/build/.*
.*/packages/.*/lib
.*/packages/.*/test
.*/codemods/.*/lib
.*/codemods/.*/test
.*/node_modules/conventional-changelog-core/
.*/node_modules/module-deps/
<PROJECT_ROOT>/build/.*
<PROJECT_ROOT>/packages/.*/lib
<PROJECT_ROOT>/packages/.*/test
<PROJECT_ROOT>/codemods/.*/lib
<PROJECT_ROOT>/codemods/.*/test
<PROJECT_ROOT>/node_modules/module-deps/
[include]
packages/*/src

View File

@@ -1,6 +1,9 @@
---
name: 🐛 Bug Report
about: If something isn't working as expected 🤔.
name: "\U0001F41B Bug Report"
about: "If something isn't working as expected \U0001F914."
title: ''
labels: 'i: bug, i: needs triage'
assignees: ''
---
@@ -31,7 +34,7 @@ A clear and concise description of what you expected to happen (or code).
- Babel version(s): [e.g. v6.0.0, v7.0.0-beta.34]
- Node/npm version: [e.g. Node 8/npm 5]
- OS: [e.g. OSX 10.13.4, Windows 10]
- Monorepo [e.g. yes/no/Lerna]
- Monorepo: [e.g. yes/no/Lerna]
- How you are using Babel: [e.g. `cli`, `register`, `loader`]
**Possible Solution**

View File

@@ -1,6 +1,9 @@
---
name: 🚀 Feature Request
about: I have a suggestion (and may want to implement it 🙂)!
name: "\U0001F680 Feature Request"
about: "I have a suggestion (and may want to implement it \U0001F642)!"
title: ''
labels: 'i: enhancement, i: needs triage'
assignees: ''
---

View File

@@ -1,12 +1,16 @@
---
name: 💥 v7 Regression
about: Report an unexpected behavior in v7 from v6 (Check the upgrade guide first ✌️)
name: "\U0001F4A5 v7 Regression"
about: Report an unexpected behavior in v7 from v6 (Check the upgrade guide first
✌️)
title: ''
labels: 'i: bug, 7.x: regression, i: needs triage'
assignees: ''
---
# v7 Regression
> First check out: https://new.babeljs.io/docs/en/next/v7-migration.html
> First check out: https://babeljs.io/docs/en/v7-migration
> Also a partial upgrade tool: https://github.com/babel/babel-upgrade
**Potential Commit/PR that introduced the regression**

View File

@@ -1,6 +1,9 @@
---
name: 🤗 Support Question
about: If you have a question 💬, please check out our Slack or StackOverflow!
name: "\U0001F917 Support Question"
about: "If you have a question \U0001F4AC, please check out our Slack or StackOverflow!"
title: ''
labels: 'i: question, i: needs triage'
assignees: ''
---

View File

@@ -1,6 +1,10 @@
---
name: 🤝 Support us on Babel
about: If you would like to support our efforts in maintaining this community-driven project 🙌!
name: "\U0001F91D Support us on Babel"
about: "If you would like to support our efforts in maintaining this community-driven
project \U0001F64C!"
title: ''
labels: ''
assignees: ''
---

View File

@@ -1,14 +1,11 @@
git:
depth: 10
sudo: false
depth: 5
language: node_js
cache:
yarn: true
directories:
- node_modules
node_js:
# We test the latest version on circleci
- '9'
- '10'
- '8'
- '6'
@@ -20,17 +17,20 @@ env:
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash
install: yarn --ignore-engines
install:
# the `make test-ci` script runs this command already
- if [ "$JOB" != "test" ] && [ "$JOB" != "lint" ]; then yarn install; fi
- if [ "$JOB" = "lint" ]; then make bootstrap; fi
before_script:
- 'if [ "$JOB" = "babel-parser-flow-tests" ]; then make bootstrap-flow; fi'
- 'if [ "$JOB" = "babel-parser-test262-tests" ]; then make bootstrap-test262; fi'
- if [ "$JOB" = "babel-parser-flow-tests" ]; then make bootstrap-flow; fi
- if [ "$JOB" = "babel-parser-test262-tests" ]; then make bootstrap-test262; fi
script:
- 'if [ "$JOB" = "test" ]; then make test-ci; fi'
- 'if [ "$JOB" = "lint" ]; then make lint && make flow; fi'
- 'if [ "$JOB" = "babel-parser-flow-tests" ]; then make test-flow-ci; fi'
- 'if [ "$JOB" = "babel-parser-test262-tests" ]; then make test-test262-ci; fi'
- if [ "$JOB" = "test" ]; then make test-ci; fi
- if [ "$JOB" = "lint" ]; then make lint && make flow; fi
- if [ "$JOB" = "babel-parser-flow-tests" ]; then make test-flow-ci; fi
- if [ "$JOB" = "babel-parser-test262-tests" ]; then make test-test262-ci; fi
matrix:
fast_finish: true

View File

@@ -15,6 +15,164 @@ See [CHANGELOG - v4](/.github/CHANGELOG-v4.md), [CHANGELOG - v5](/.github/CHANGE
See [CHANGELOG - 6to5](/.github/CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
See [Babylon's CHANGELOG](packages/babylon/CHANGELOG.md) for the Babylon pre-7.0.0-beta.29 version changelog.
## v7.2.1 (2018-12-04)
This release fixes a regression introduced in v7.2.0 (https://github.com/babel/babel/issues/9120)
#### :bug: Bug Fix
* `babel-helper-create-class-features-plugin`
* [#9121](https://github.com/babel/babel/pull/9121) Don't use isClassPrivateMethod because it isn't supported in <7.2.0. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
## v7.2.0 (2018-12-03)
You can read more about this release at https://babeljs.io/blog/2018/12/03/7.2.0.
#### :rocket: New Feature
* `babel-parser`
* [#8289](https://github.com/babel/babel/pull/8289) Implement Smart Pipeline proposal in @babel/parser. ([@mAAdhaTTah](https://github.com/mAAdhaTTah))
* `babel-core`
* [#8986](https://github.com/babel/babel/pull/8986) Export @babel/parser#tokTypes in @babel/core. ([@kaicataldo](https://github.com/kaicataldo))
* `babel-node`
* [#9078](https://github.com/babel/babel/pull/9078) Pass `rootMode` from `@babel/node`.. ([@wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg))
* `babel-generator`, `babel-helpers`, `babel-plugin-class-features`, `babel-plugin-proposal-private-methods`, `babel-plugin-syntax-class-properties`, `babel-types`
* [#8654](https://github.com/babel/babel/pull/8654) Private class methods stage 3. ([@tim-mc](https://github.com/tim-mc))
* `babel-preset-env`
* [#9048](https://github.com/babel/babel/pull/9048) Update mappings for node 10 in preset-env. ([@existentialism](https://github.com/existentialism))
#### :bug: Bug Fix
* `babel-parser`
* [#9114](https://github.com/babel/babel/pull/9114) Parse non-octals with leading zeros in non strict mode correctly. ([@danez](https://github.com/danez))
* [#9074](https://github.com/babel/babel/pull/9074) Disallow await inside arrow functions. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* [#9069](https://github.com/babel/babel/pull/9069) [flow] Allow type casts in array patterns inside arrow parameters. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* [#9058](https://github.com/babel/babel/pull/9058) Fix compatibility between typescript and jsx plugins in interface declarations. ([@danez](https://github.com/danez))
* [#9055](https://github.com/babel/babel/pull/9055) Fix bug with parsing TS generic async arrow function. ([@existentialism](https://github.com/existentialism))
* [#9035](https://github.com/babel/babel/pull/9035) Fix parsing typescript function types with destructuring. ([@danez](https://github.com/danez))
* `babel-helper-fixtures`, `babel-parser`
* [#9113](https://github.com/babel/babel/pull/9113) Ignore empty fixture directories and fix fixtures in the parser. ([@danez](https://github.com/danez))
* `babel-preset-env`
* [#9091](https://github.com/babel/babel/pull/9091) Update mapping for regex unicode plugin in preset-env. ([@existentialism](https://github.com/existentialism))
* `babel-plugin-transform-destructuring`
* [#8916](https://github.com/babel/babel/pull/8916) Fix destructuring assignment in arrow functions without block. ([@RubenVerborgh](https://github.com/RubenVerborgh))
* `babel-plugin-proposal-optional-chaining`
* [#9073](https://github.com/babel/babel/pull/9073) Microbouji patch/8136. ([@jridgewell](https://github.com/jridgewell))
* `babel-core`, `babel-helper-wrap-function`, `babel-plugin-proposal-async-generator-functions`, `babel-plugin-proposal-function-sent`, `babel-plugin-transform-async-to-generator`, `babel-plugin-transform-classes`
* [#9039](https://github.com/babel/babel/pull/9039) Fix recursive async function expressions. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* `babel-core`
* [#9034](https://github.com/babel/babel/pull/9034) Normalize presets before merging config with others.. ([@loganfsmyth](https://github.com/loganfsmyth))
#### :nail_care: Polish
* `babel-generator`
* [#9089](https://github.com/babel/babel/pull/9089) Remove unused variable. ([@Gcaufy](https://github.com/Gcaufy))
* `babel-node`
* [#9079](https://github.com/babel/babel/pull/9079) Move `fs-readdir-recursive` and `output-file-sync` to `devDependencies` for `@babel/node`.. ([@wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg))
* `babel-parser`
* [#9046](https://github.com/babel/babel/pull/9046) a better error message for disallowed trailing commas/additional parameters after rest elements in function params. ([@morozRed](https://github.com/morozRed))
* `babel-*`
* [#8769](https://github.com/babel/babel/pull/8769) Add plugins name. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
#### :house: Internal
* `babel-helper-create-class-features-plugin`, `babel-plugin-proposal-class-properties`, `babel-plugin-proposal-private-methods`
* [#9083](https://github.com/babel/babel/pull/9083) Make @babel/plugin-class-features a normal helper package. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* Other
* [#9096](https://github.com/babel/babel/pull/9096) Add node 11 to CI and remove node 9. ([@danez](https://github.com/danez))
* [#9094](https://github.com/babel/babel/pull/9094) Skip minifying standalone in non-publish runs. ([@danez](https://github.com/danez))
* `babel-types`
* [#9093](https://github.com/babel/babel/pull/9093) Fix warning when using prettier in code generators. ([@danez](https://github.com/danez))
* `babel-generator`
* [#9089](https://github.com/babel/babel/pull/9089) Remove unused variable. ([@Gcaufy](https://github.com/Gcaufy))
## v7.1.6 (2018-11-13)
#### :bug: Bug Fix
* `babel-generator`
* [#9003](https://github.com/babel/babel/pull/9003) Fix retainLines regression for arrow functions. ([@loganfsmyth](https://github.com/loganfsmyth))
* `babel-types`
* [#8997](https://github.com/babel/babel/pull/8997) Fix cloneNode with typeAnnotation.. ([@neoziro](https://github.com/neoziro))
* `babel-plugin-transform-flow-strip-types`, `babel-plugin-transform-react-jsx`
* [#8701](https://github.com/babel/babel/pull/8701) Fix "TypeError: comments is not iterable". ([@AlicanC](https://github.com/AlicanC))
* `babel-core`
* [#9004](https://github.com/babel/babel/pull/9004) Fix browser files to have the same API as the nodejs ones. ([@danez](https://github.com/danez))
* Other
* [#9007](https://github.com/babel/babel/pull/9007) [Types] fix generated TS/Flow comment types. ([@ljqx](https://github.com/ljqx))
* `babel-preset-env`
* [#8555](https://github.com/babel/babel/pull/8555) preset-env: fix `opera` from `esmodules` target and Browserslist not used. ([@ylemkimon](https://github.com/ylemkimon))
* `babel-plugin-proposal-decorators`, `babel-traverse`
* [#8970](https://github.com/babel/babel/pull/8970) [decorators] Correctly insert `_initialize(this)` after `super()`.. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* `babel-parser`
* [#8972](https://github.com/babel/babel/pull/8972) Fix several edge cases with context expression state. ([@danez](https://github.com/danez))
#### :nail_care: Polish
* `babel-parser`
* [#8984](https://github.com/babel/babel/pull/8984) Rename primitive types to reserved types. ([@danez](https://github.com/danez))
#### :house: Internal
* [#8982](https://github.com/babel/babel/pull/8982) fix publish command [skip ci]. ([@hzoo](https://github.com/hzoo))
* [#8988](https://github.com/babel/babel/pull/8988) Remove definition of micromatch which was removed.. ([@danez](https://github.com/danez))
## v7.1.5 (2018-11-06)
#### :eyeglasses: Spec Compliancy
* `babel-parser`, `babylon`
* [#7727](https://github.com/babel/babel/pull/7727) Fix await in function name and parameters. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
#### :rocket: New Feature
* `babel-parser`
* [#8828](https://github.com/babel/babel/pull/8828) Typescript: Validate tuple type element positions. ([@Retsam](https://github.com/Retsam))
* [#8883](https://github.com/babel/babel/pull/8883) [flow] Add support for parsing `_` as implicit instantiation in call/new. ([@jbrown215](https://github.com/jbrown215))
* `babel-core`, `babel-generator`, `babel-parser`, `babel-plugin-syntax-typescript`, `babel-traverse`
* [#8448](https://github.com/babel/babel/pull/8448) Remove Babylon plugins for features already merged to the ECMAScript spec. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* `babel-parser`, `babel-types`
* [#8884](https://github.com/babel/babel/pull/8884) [flow] Explicit inexact objects with `...`. ([@jbrown215](https://github.com/jbrown215))
* `babel-preset-env`
* [#8898](https://github.com/babel/babel/pull/8898) Update preset-env data. ([@existentialism](https://github.com/existentialism))
#### :bug: Bug Fix
* `babel-parser`
* [#8956](https://github.com/babel/babel/pull/8956) Do not allow TypeCastExpressions w/o parens . ([@danez](https://github.com/danez))
* [#8954](https://github.com/babel/babel/pull/8954) Allow function types in type params within arrow return types. ([@danez](https://github.com/danez))
* [#8866](https://github.com/babel/babel/pull/8866) Closes [#8865](https://github.com/babel/babel/issues/8865). ([@byronluk](https://github.com/byronluk))
* `babel-core`
* [#8910](https://github.com/babel/babel/pull/8910) Resolve babel.config.js 'babelrcRoots' values relative to the config file.. ([@loganfsmyth](https://github.com/loganfsmyth))
* [#8950](https://github.com/babel/babel/pull/8950) Fix message when plugin of a wrong type is passed. ([@everdimension](https://github.com/everdimension))
* `babel-plugin-transform-block-scoping`
* [#8937](https://github.com/babel/babel/pull/8937) rename colliding let bindings with for loop init. ([@byronluk](https://github.com/byronluk))
* [#8914](https://github.com/babel/babel/pull/8914) Treat break inside block inside loop. ([@thiagoarrais](https://github.com/thiagoarrais))
* `babel-preset-env`
* [#8926](https://github.com/babel/babel/pull/8926) preset-env: Edge support for arrow param destructuring. ([@benmosher](https://github.com/benmosher))
* `babel-generator`
* [#8868](https://github.com/babel/babel/pull/8868) fix single-arg async arrows when retainLines=true. ([@ryanwmarsh](https://github.com/ryanwmarsh))
* `babel-traverse`
* [#8880](https://github.com/babel/babel/pull/8880) fix: Expression x === 'y' && '' should not evaluate to undefined.. ([@Cyp](https://github.com/Cyp))
#### :nail_care: Polish
* [#8873](https://github.com/babel/babel/pull/8873) fixed an extra word. ([@vvyomjjain](https://github.com/vvyomjjain))
## v7.1.4 (2018-10-11)
Just re-published `@babel/traverse` without `**` so that it works in Node 6.
## v7.1.3 (2018-10-11)
#### :bug: Bug Fix
* `babel-generator`, `babel-parser`, `babel-plugin-transform-typescript`, `babel-types`
* [#8720](https://github.com/babel/babel/pull/8720) Typescript - Tuple elements can be optional. ([@Retsam](https://github.com/Retsam))
* `babel-traverse`
* [#8833](https://github.com/babel/babel/pull/8833) Insertafter jsx fix. ([@kevintab95](https://github.com/kevintab95))
* `babel-parser`
* [#8830](https://github.com/babel/babel/pull/8830) Correct handling of newline after async with paren-less arrow func. ([@Retsam](https://github.com/Retsam))
* [#8756](https://github.com/babel/babel/pull/8756) class private methods and properties: should not allow spaces between # and identifier. ([@macabeus](https://github.com/macabeus))
* [#8804](https://github.com/babel/babel/pull/8804) Fix parsing of slash after class expression. ([@existentialism](https://github.com/existentialism))
* [#8767](https://github.com/babel/babel/pull/8767) [decorators] [typescript] Parse type parameters. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo))
* [#8792](https://github.com/babel/babel/pull/8792) Fix perf issue in typescript parser plugin. ([@matthewrobertson](https://github.com/matthewrobertson))
* `babel-generator`, `babel-parser`, `babel-plugin-transform-typescript`, `babel-types`
* [#8805](https://github.com/babel/babel/pull/8805) Typescript - Tuples can include rest elements. ([@Retsam](https://github.com/Retsam))
* `babel-types`
* [#8791](https://github.com/babel/babel/pull/8791) types: allow jsxEmptyExpression inside jsxExpressionContainer. ([@tvooo](https://github.com/tvooo))
* `babel-plugin-transform-modules-systemjs`
* [#8820](https://github.com/babel/babel/pull/8820) System module format - fixes function hoisting failure case. ([@guybedford](https://github.com/guybedford))
* `babel-plugin-transform-destructuring`
* [#8793](https://github.com/babel/babel/pull/8793) Ensure destructuring's computed key handling matches object-rest-spread. ([@existentialism](https://github.com/existentialism))
## 7.1.2 (2018-09-28)
Same as v7.1.1, except compiled against Node 6 instead of Node 8 by accident (e.g had `async functions`).
@@ -2542,7 +2700,7 @@ Also started Babel to compile itself with Babel 7! (We'll be working on making i
#### :nail_care: Polish
* `babel-register`
* [#5411](https://github.com/babel/babel/pull/5411) Seperate version env cache files. ([@pwmckenna](https://github.com/pwmckenna))
* [#5411](https://github.com/babel/babel/pull/5411) Separate version env cache files. ([@pwmckenna](https://github.com/pwmckenna))
#### :memo: Documentation
* `babel-plugin-transform-runtime`

View File

@@ -310,7 +310,7 @@ Note that the code shown in Chrome DevTools is compiled code and therefore diffe
- Create a new issue that describes the proposal (ex: [#538](https://github.com/babel/babylon/issues/538)). Include any relevant information like proposal repo/author, examples, parsing approaches, meeting notes, presentation slides, and more.
- The pull request should include:
- [ ] An update to the [plugins](https://github.com/babel/babel/tree/master/packages/babel-parser#plugins) part of the readme. Add a new entry to that list for the new plugin flag (and link to the proposal)
- [ ] If any new nodes or modifications need to be added to the AST, update [ast/spec.md](https://github.com/babel/babel/bloc/master/packages/babel-parser/ast/spec.md)
- [ ] If any new nodes or modifications need to be added to the AST, update [ast/spec.md](https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md)
- [ ] Make sure you use the `this.hasPlugin("plugin-name-here")` check in the babel parser so that your new plugin code only runs when that flag is turned on (not default behavior)
- [ ] Add failing/passing tests according to spec behavior
- Start working about the Babel transform itself!

View File

@@ -1,6 +1,6 @@
MAKEFLAGS = -j1
FLOW_COMMIT = bea8b83f50f597454941d2a7ecef6e93a881e576
TEST262_COMMIT = 06c2f019019cf7850923de4d56828e6dfd9212b8
FLOW_COMMIT = e192e1a4793dd8e43415fbfe8046d832cb513c8b
TEST262_COMMIT = 238c88d4a084d9928372954e2fec54af2c951281
# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
export FORCE_COLOR = true
@@ -28,6 +28,12 @@ build-standalone:
build-preset-env-standalone:
./node_modules/.bin/gulp build-babel-preset-env-standalone
prepublish-build-standalone:
BABEL_ENV=production IS_PUBLISH=true ./node_modules/.bin/gulp build-babel-standalone
prepublish-build-preset-env-standalone:
BABEL_ENV=production IS_PUBLISH=true ./node_modules/.bin/gulp build-babel-preset-env-standalone
build-dist: build
cd packages/babel-polyfill; \
scripts/build-dist.sh
@@ -82,7 +88,7 @@ test-ci-coverage:
bootstrap-flow:
rm -rf ./build/flow
mkdir -p ./build
git clone --branch=master --single-branch --shallow-since=2017-01-01 https://github.com/facebook/flow.git ./build/flow
git clone --branch=master --single-branch --shallow-since=2018-11-01 https://github.com/facebook/flow.git ./build/flow
cd build/flow && git checkout $(FLOW_COMMIT)
test-flow:
@@ -96,7 +102,7 @@ test-flow-update-whitelist:
bootstrap-test262:
rm -rf ./build/test262
mkdir -p ./build
git clone --branch=master --single-branch --shallow-since=2017-01-01 https://github.com/tc39/test262.git ./build/test262
git clone --branch=master --single-branch --shallow-since=2018-11-01 https://github.com/tc39/test262.git ./build/test262
cd build/test262 && git checkout $(TEST262_COMMIT)
test-test262:
@@ -124,8 +130,7 @@ prepublish:
make test
publish: prepublish
# --only-explicit-updates
./node_modules/.bin/lerna publish
./node_modules/.bin/lerna publish --force-publish="@babel/runtime,@babel/runtime-corejs2,@babel/standalone,@babel/preset-env-standalone" --require-scripts
make clean
bootstrap: clean-all

View File

@@ -48,35 +48,15 @@ Become a sponsor and get your logo on our README on Github with a link to your s
<a href="https://opencollective.com/babel/sponsor/12/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/13/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/14/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/15/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/16/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/17/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/18/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/19/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/20/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/21/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/22/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/23/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/24/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/25/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/26/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/27/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/28/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/babel/sponsor/29/website" target="_blank"><img src="https://opencollective.com/babel/sponsor/29/avatar.svg"></a>
## Patreon Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://www.patreon.com/henryzhu)]
## Silver
<a href="https://issue.sh/?utm_medium=github&utm_campaign=babel" target="_blank"><img src="https://user-images.githubusercontent.com/5557143/43912065-c8cdff78-9c33-11e8-829a-0b4166ccc215.png"></a>
## Bronze
<a href="http://teamextension.io/" target="_blank"><img src="https://teamextension.io/dist/img/logo/te-logo-compact.png" height="64"></a>
<a href="https://webflow.com/" target="_blank"><img src="https://opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2F4a5024b0-8cf2-11e7-b1a2-b30b1de1463c.png&height=64"></a>
<p><a href="https://twitter.com/mikesherov">Mike Sherov</a></p>
## Intro
@@ -107,7 +87,7 @@ Mostly a handful of volunteers! Please check out our [team page](https://babeljs
### Looking for support?
For questions and support please visit join our [Slack Community](https://slack.babeljs.io/) (you can sign-up [here](https://slack.babeljs.io/) for an invite), ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/babeljs), or ping us on [Twitter](https://twitter.com/babeljs).
For questions and support please join our [Slack Community](https://slack.babeljs.io/) (you can sign-up [here](https://slack.babeljs.io/) for an invite), ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/babeljs), or ping us on [Twitter](https://twitter.com/babeljs).
### Is there a Babel song?

View File

@@ -2,8 +2,10 @@
const noDeprecatedClone = require("./scripts/eslint_rules/no-deprecated-clone");
const noUndefinedIdentifier = require("./scripts/eslint_rules/no-undefined-identifier");
const pluginName = require("./scripts/eslint_rules/plugin-name");
module.exports = {
"no-deprecated-clone": noDeprecatedClone,
"no-undefined-identifier": noUndefinedIdentifier,
"plugin-name": pluginName,
};

View File

@@ -1,6 +1,5 @@
{
"lerna": "2.11.0",
"version": "7.1.4",
"version": "7.2.4",
"changelog": {
"repo": "babel/babel",
"cacheDir": ".changelog",
@@ -14,21 +13,21 @@
"PR: Internal :house:": ":house: Internal"
}
},
"commands": {
"command": {
"publish": {
"ignore": [
"ignoreChanges": [
"*.md",
"*.json",
"*.txt",
"test/**",
"codemods/**",
"package.json"
"# We ignore every JSON file, except for built-in-modules, built-ins and plugins defined in babel-preset-env/data.",
"@(!(built-in-modules|built-ins|plugins)).json"
]
}
},
"packages": [
"packages/*",
"codemods/*"
"codemods/*",
"packages/*"
],
"npmClient": "yarn",
"npmClientArgs": [

View File

@@ -2,12 +2,6 @@
* Basic declarations for the npm modules we use.
*/
declare module "micromatch" {
declare module.exports: {
(Array<string>, Array<string>, ?{ nocase: boolean }): Array<string>,
};
}
declare module "resolve" {
declare export default {
sync: (string, {| basedir: string |}) => string;

View File

@@ -9,69 +9,71 @@
"test": "make test"
},
"devDependencies": {
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-export-namespace-from": "^7.0.0",
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
"@babel/plugin-transform-modules-commonjs": "^7.1.0",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.0",
"@babel/cli": "^7.2.0",
"@babel/core": "^7.2.0",
"@babel/eslint-plugin-development": "^1.0.1",
"@babel/plugin-proposal-class-properties": "^7.2.1",
"@babel/plugin-proposal-export-namespace-from": "^7.2.0",
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.2.0",
"@babel/preset-env": "^7.2.0",
"@babel/preset-flow": "^7.0.0",
"@babel/register": "^7.0.0",
"@babel/runtime": "^7.1.2",
"@babel/runtime": "^7.2.0",
"babel-core": "^7.0.0-0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.4",
"babel-plugin-transform-charcodes": "^0.1.0",
"babel-plugin-transform-charcodes": "^0.1.1",
"browserify": "^16.2.2",
"bundle-collapser": "^1.2.1",
"chalk": "^2.3.2",
"charcodes": "^0.1.0",
"charcodes": "^0.1.1",
"derequire": "^2.0.2",
"enhanced-resolve": "^3.0.0",
"eslint": "^5.6.0",
"eslint-config-babel": "^8.0.1",
"eslint-plugin-flowtype": "^2.50.1",
"eslint-plugin-local-rules": "0.1.0",
"eslint-plugin-prettier": "^2.6.2",
"flow-bin": "^0.82.0",
"eslint": "^5.9.0",
"eslint-config-babel": "^8.0.2",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-prettier": "^3.0.0",
"flow-bin": "^0.87.0",
"graceful-fs": "^4.1.11",
"gulp": "^4.0.0",
"gulp-babel": "^8.0.0-beta.2",
"gulp-babel": "^8.0.0",
"gulp-filter": "^5.1.0",
"gulp-newer": "^1.0.0",
"gulp-plumber": "^1.0.1",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^3.0.0",
"gulp-plumber": "^1.2.0",
"gulp-rename": "^1.4.0",
"gulp-uglify": "^3.0.1",
"gulp-util": "^3.0.7",
"gulp-watch": "^5.0.0",
"husky": "^1.0.0-rc.15",
"gulp-watch": "^5.0.1",
"husky": "^1.2.0",
"jest": "^23.6.0",
"lerna": "^2.11.0",
"lerna": "^3.6.0",
"lerna-changelog": "^0.5.0",
"lint-staged": "^7.3.0",
"lint-staged": "^8.1.0",
"lodash": "^4.17.10",
"merge-stream": "^1.0.1",
"output-file-sync": "^2.0.0",
"prettier": "^1.14.3",
"pump": "^1.0.2",
"prettier": "^1.15.2",
"pump": "^3.0.0",
"rimraf": "^2.4.3",
"rollup-plugin-babel": "^4.0.0-beta.0",
"rollup-plugin-node-resolve": "^3.0.2",
"rollup-stream": "^1.24.1",
"test262-stream": "^1.2.0",
"through2": "^2.0.0",
"uglify-js": "^2.4.16",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0",
"webpack": "^3.4.1",
"webpack-dependency-suite": "^2.4.4",
"webpack-stream": "^4.0.0"
},
"resolutions": {
"@lerna/**/@lerna/collect-updates": "https://github.com/nicolo-ribaudo/lerna.git#babel-collect-updates"
},
"engines": {
"node": ">= 6.9.0 <= 11.0.0-0",
"node": ">= 6.9.0 < 12.0.0",
"npm": ">= 3.x <= 6.x",
"yarn": ">=0.27.5 || >=1.0.0-20170811"
},
@@ -125,6 +127,9 @@
"/test/tmp/",
"/test/__data__/",
"<rootDir>/build/"
]
],
"moduleNameMapper": {
"^@babel/([a-zA-Z0-9_-]+)$": "<rootDir>/packages/babel-$1/"
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/cli",
"version": "7.1.2",
"version": "7.2.3",
"description": "Babel command line.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -36,8 +36,8 @@
"@babel/core": "^7.0.0-0"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/helper-fixtures": "^7.0.0"
"@babel/core": "^7.2.0",
"@babel/helper-fixtures": "^7.2.0"
},
"bin": {
"babel": "./bin/babel.js",

View File

@@ -137,7 +137,11 @@ export default async function({ cliOptions, babelOptions }) {
const dirname = filename;
util
.readdirForCompilable(filename, cliOptions.includeDotfiles)
.readdirForCompilable(
filename,
cliOptions.includeDotfiles,
cliOptions.extensions,
)
.forEach(function(filename) {
_filenames.push(path.join(dirname, filename));
});

View File

@@ -22,7 +22,7 @@ commander.option(
"comma-separated list of plugin names",
collect,
);
commander.option("--config-file [path]", "Path a to .babelrc file to use");
commander.option("--config-file [path]", "Path to a .babelrc file to use");
commander.option(
"--env-name [name]",
"The name of the 'env' to use when loading configs and plugins. " +
@@ -81,7 +81,7 @@ commander.option(
"print a comment after any injected non-user code",
);
// General soucemap formatting.
// General source map formatting.
commander.option("-s, --source-maps [true|false|inline|both]", "", booleanify);
commander.option(
"--source-map-target [string]",

View File

@@ -29,8 +29,11 @@ export function readdir(
export function readdirForCompilable(
dirname: string,
includeDotfiles: boolean,
altExts?: Array<string>,
) {
return readdir(dirname, includeDotfiles, isCompilableExtension);
return readdir(dirname, includeDotfiles, function(filename) {
return isCompilableExtension(filename, altExts);
});
}
/**

View File

@@ -0,0 +1 @@
(() => 42)

View File

@@ -0,0 +1 @@
arr.map(x => x * MULTIPLIER);

View File

@@ -0,0 +1,3 @@
{
"args": ["src", "--out-file", "test.js", "--extensions", ".es"]
}

View File

@@ -0,0 +1,10 @@
"use strict";
(function () {
return 42;
});
"use strict";
arr.map(function (x) {
return x * MULTIPLIER;
});

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/core",
"version": "7.1.2",
"version": "7.2.2",
"description": "Babel compiler core.",
"main": "lib/index.js",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
@@ -34,15 +34,15 @@
},
"dependencies": {
"@babel/code-frame": "^7.0.0",
"@babel/generator": "^7.1.2",
"@babel/helpers": "^7.1.2",
"@babel/parser": "^7.1.2",
"@babel/template": "^7.1.2",
"@babel/traverse": "^7.1.0",
"@babel/types": "^7.1.2",
"@babel/generator": "^7.2.2",
"@babel/helpers": "^7.2.0",
"@babel/parser": "^7.2.2",
"@babel/template": "^7.2.2",
"@babel/traverse": "^7.2.2",
"@babel/types": "^7.2.2",
"convert-source-map": "^1.1.0",
"debug": "^3.1.0",
"json5": "^0.5.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
"lodash": "^4.17.10",
"resolve": "^1.3.2",
"semver": "^5.4.1",

View File

@@ -43,6 +43,7 @@ export function makeWeakCache<
>(
handler: (ArgT, CacheConfigurator<SideChannel>) => ResultT,
): (ArgT, SideChannel) => ResultT {
// $FlowIssue https://github.com/facebook/flow/issues/4528
return makeCachedFunction(new WeakMap(), handler);
}
@@ -54,6 +55,7 @@ function makeCachedFunction<
ArgT,
ResultT,
SideChannel,
// $FlowIssue https://github.com/facebook/flow/issues/4528
Cache: CacheMap<ArgT, ResultT, SideChannel>,
>(
callCache: Cache,

View File

@@ -67,7 +67,7 @@ export function buildPresetChain(
return {
plugins: dedupDescriptors(chain.plugins),
presets: dedupDescriptors(chain.presets),
options: chain.options,
options: chain.options.map(o => normalizeOptions(o)),
};
}
@@ -155,6 +155,7 @@ export function buildRootChain(
}
let { babelrc, babelrcRoots } = opts;
let babelrcRootsDirectory = context.cwd;
const configFileChain = emptyChain();
if (configFile) {
@@ -168,6 +169,7 @@ export function buildRootChain(
babelrc = validatedFile.options.babelrc;
}
if (babelrcRoots === undefined) {
babelrcRootsDirectory = validatedFile.dirname;
babelrcRoots = validatedFile.options.babelrcRoots;
}
@@ -185,7 +187,7 @@ export function buildRootChain(
if (
(babelrc === true || babelrc === undefined) &&
pkgData &&
babelrcLoadEnabled(context, pkgData, babelrcRoots)
babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory)
) {
({ ignore: ignoreFile, config: babelrcFile } = findRelativeConfig(
pkgData,
@@ -229,6 +231,7 @@ function babelrcLoadEnabled(
context: ConfigContext,
pkgData: FilePackageData,
babelrcRoots: BabelrcSearch | void,
babelrcRootsDirectory: string,
): boolean {
if (typeof babelrcRoots === "boolean") return babelrcRoots;
@@ -243,7 +246,9 @@ function babelrcLoadEnabled(
let babelrcPatterns = babelrcRoots;
if (!Array.isArray(babelrcPatterns)) babelrcPatterns = [babelrcPatterns];
babelrcPatterns = babelrcPatterns.map(pat => {
return typeof pat === "string" ? path.resolve(context.cwd, pat) : pat;
return typeof pat === "string"
? path.resolve(babelrcRootsDirectory, pat)
: pat;
});
// Fast path to avoid having to match patterns if the babelrc is just
@@ -253,10 +258,12 @@ function babelrcLoadEnabled(
}
return babelrcPatterns.some(pat => {
if (typeof pat === "string") pat = pathPatternToRegex(pat, context.cwd);
if (typeof pat === "string") {
pat = pathPatternToRegex(pat, babelrcRootsDirectory);
}
return pkgData.directories.some(directory => {
return matchPattern(pat, context.cwd, directory, context);
return matchPattern(pat, babelrcRootsDirectory, directory, context);
});
});
}

View File

@@ -132,7 +132,7 @@ function resolveStandardizedName(
} catch (e2) {}
if (resolvedOppositeType) {
e.message += `\n- Did you accidentally pass a ${type} as a ${oppositeType}?`;
e.message += `\n- Did you accidentally pass a ${oppositeType} as a ${type}?`;
}
throw e;

View File

@@ -55,6 +55,7 @@ export default function makeAPI(
async: () => false,
caller,
assertVersion,
tokTypes: undefined,
};
}

View File

@@ -350,7 +350,7 @@ function validateNested(loc: NestingPath, opts: {}) {
NONPRESET_VALIDATORS[key] ||
BABELRC_VALIDATORS[key] ||
ROOT_VALIDATORS[key] ||
throwUnknownError;
(throwUnknownError: Validator<void>);
validator(optLoc, opts[key]);
});

View File

@@ -10,6 +10,8 @@ export { version } from "../package.json";
export { getEnv } from "./config/helpers/environment";
export * as types from "@babel/types";
export { tokTypes } from "@babel/parser";
export { default as traverse } from "@babel/traverse";
export { default as template } from "@babel/template";

View File

@@ -1,14 +1,29 @@
// @flow
import type { FileResult } from "./transformation";
export default function transformFile(
filename: string,
opts?: Object = {},
callback: (?Error, FileResult | null) => void,
// duplicated from transform-file so we do not have to import anything here
type TransformFile = {
(filename: string, callback: Function): void,
(filename: string, opts: ?Object, callback: Function): void,
};
export const transformFile: TransformFile = (function transformFile(
filename,
opts,
callback,
) {
if (typeof opts === "function") {
callback = opts;
}
callback(new Error("Transforming files is not supported in browsers"), null);
}: Function);
export function transformFileSync() {
throw new Error("Transforming files is not supported in browsers");
}
export function transformFileAsync() {
return Promise.reject(
new Error("Transforming files is not supported in browsers"),
);
}

View File

@@ -1,5 +0,0 @@
// @flow
export default function transformFileSync() {
throw new Error("Transforming files is not supported in browsers");
}

View File

@@ -9,6 +9,14 @@ import {
type FileResultCallback,
} from "./transformation";
import typeof * as transformFileBrowserType from "./transform-file-browser";
import typeof * as transformFileType from "./transform-file";
// Kind of gross, but essentially asserting that the exports of this module are the same as the
// exports of transform-file-browser, since this file may be replaced at bundle time with
// transform-file-browser.
((({}: any): $Exact<transformFileBrowserType>): $Exact<transformFileType>);
type TransformFile = {
(filename: string, callback: FileResultCallback): void,
(filename: string, opts: ?InputOptions, callback: FileResultCallback): void,

View File

@@ -1,16 +1,6 @@
// @flow
const pluginNameMap = {
asyncGenerators: {
syntax: {
name: "@babel/plugin-syntax-async-generators",
url: "https://git.io/vb4SY",
},
transform: {
name: "@babel/plugin-proposal-async-generator-functions",
url: "https://git.io/vb4yp",
},
},
classProperties: {
syntax: {
name: "@babel/plugin-syntax-class-properties",
@@ -143,26 +133,6 @@ const pluginNameMap = {
url: "https://git.io/vb4yS",
},
},
objectRestSpread: {
syntax: {
name: "@babel/plugin-syntax-object-rest-spread",
url: "https://git.io/vb4y5",
},
transform: {
name: "@babel/plugin-proposal-object-rest-spread",
url: "https://git.io/vb4Ss",
},
},
optionalCatchBinding: {
syntax: {
name: "@babel/plugin-syntax-optional-catch-binding",
url: "https://git.io/vb4Sn",
},
transform: {
name: "@babel/plugin-proposal-optional-catch-binding",
url: "https://git.io/vb4SI",
},
},
optionalChaining: {
syntax: {
name: "@babel/plugin-syntax-optional-chaining",
@@ -203,6 +173,41 @@ const pluginNameMap = {
url: "https://git.io/vb4Sm",
},
},
// TODO: This plugins are now supported by default by @babel/parser: they can
// be removed from this list. Although removing them isn't a breaking change,
// it's better to keep a nice error message for users using older versions of
// the parser. They can be removed in Babel 8.
asyncGenerators: {
syntax: {
name: "@babel/plugin-syntax-async-generators",
url: "https://git.io/vb4SY",
},
transform: {
name: "@babel/plugin-proposal-async-generator-functions",
url: "https://git.io/vb4yp",
},
},
objectRestSpread: {
syntax: {
name: "@babel/plugin-syntax-object-rest-spread",
url: "https://git.io/vb4y5",
},
transform: {
name: "@babel/plugin-proposal-object-rest-spread",
url: "https://git.io/vb4Ss",
},
},
optionalCatchBinding: {
syntax: {
name: "@babel/plugin-syntax-optional-catch-binding",
url: "https://git.io/vb4Sn",
},
transform: {
name: "@babel/plugin-proposal-optional-catch-binding",
url: "https://git.io/vb4SI",
},
},
};
const getNameURLCombination = ({ name, url }) => `${name} (${url})`;

View File

@@ -154,6 +154,14 @@ describe("api", function() {
);
});
it("exposes types", function() {
expect(babel.types).toBeDefined();
});
it("exposes the parser's token types", function() {
expect(babel.tokTypes).toBeDefined();
});
it("transformFile", function(done) {
const options = {
babelrc: false,
@@ -769,10 +777,10 @@ describe("api", function() {
options,
function(err) {
expect(err.message).toMatch(
"Support for the experimental syntax 'asyncGenerators' isn't currently enabled (1:15):",
"Support for the experimental syntax 'logicalAssignment' isn't currently enabled (1:3):",
);
expect(err.message).toMatch(
"Add @babel/plugin-proposal-async-generator-functions (https://git.io/vb4yp) to the " +
"Add @babel/plugin-proposal-logical-assignment-operators (https://git.io/vAlRe) to the " +
"'plugins' section of your Babel config to enable transformation.",
);
done();

View File

@@ -1,4 +1 @@
async function* agf() {
await 1;
yield 2;
}
a ||= 2;

View File

@@ -43,9 +43,11 @@ function () {
}, _callee, this);
}));
return function bar() {
function bar() {
return _bar.apply(this, arguments);
};
}
return bar;
}()
}]);

View File

@@ -1,5 +1,8 @@
{
"compact": false,
"presets": ["env"],
"plugins": ["external-helpers", "proposal-object-rest-spread"]
"plugins": [
["external-helpers", { "helperVersion": "7.1.5" }],
"proposal-object-rest-spread"
]
}

View File

@@ -400,7 +400,7 @@ describe("addon resolution", function() {
presets: ["testplugin"],
});
}).toThrow(
/Cannot find module 'babel-preset-testplugin'.*\n- Did you accidentally pass a preset as a plugin\?/,
/Cannot find module 'babel-preset-testplugin'.*\n- Did you accidentally pass a plugin as a preset\?/,
);
});
@@ -414,7 +414,7 @@ describe("addon resolution", function() {
plugins: ["testpreset"],
});
}).toThrow(
/Cannot find module 'babel-plugin-testpreset'.*\n- Did you accidentally pass a plugin as a preset\?/,
/Cannot find module 'babel-plugin-testpreset'.*\n- Did you accidentally pass a preset as a plugin\?/,
);
});

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/generator",
"version": "7.1.3",
"version": "7.2.2",
"description": "Turns an AST into code.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -14,14 +14,14 @@
"lib"
],
"dependencies": {
"@babel/types": "^7.1.3",
"@babel/types": "^7.2.2",
"jsesc": "^2.5.1",
"lodash": "^4.17.10",
"source-map": "^0.5.0",
"trim-right": "^1.0.1"
},
"devDependencies": {
"@babel/helper-fixtures": "^7.0.0",
"@babel/parser": "^7.0.0"
"@babel/helper-fixtures": "^7.2.0",
"@babel/parser": "^7.2.2"
}
}

View File

@@ -140,6 +140,12 @@ export function ClassMethod(node: Object) {
this.print(node.body, node);
}
export function ClassPrivateMethod(node: Object) {
this._classMethodHead(node);
this.space();
this.print(node.body, node);
}
export function _classMethodHead(node) {
this.printJoin(node.decorators, node);

View File

@@ -111,7 +111,25 @@ export function ArrowFunctionExpression(node: Object) {
t.isIdentifier(firstParam) &&
!hasTypes(node, firstParam)
) {
this.print(firstParam, node);
if (
this.format.retainLines &&
node.loc &&
node.body.loc &&
node.loc.start.line < node.body.loc.start.line
) {
this.token("(");
if (firstParam.loc && firstParam.loc.start.line > node.loc.start.line) {
this.indent();
this.print(firstParam, node);
this.dedent();
this._catchUp("start", node.body.loc);
} else {
this.print(firstParam, node);
}
this.token(")");
} else {
this.print(firstParam, node);
}
} else {
this._params(node);
}

View File

@@ -151,3 +151,15 @@ export function BigIntLiteral(node: Object) {
}
this.token(node.value);
}
export function PipelineTopicExpression(node: Object) {
this.print(node.expression, node);
}
export function PipelineBareFunction(node: Object) {
this.print(node.callee, node);
}
export function PipelinePrimaryTopicReference() {
this.token("#");
}

View File

@@ -166,6 +166,7 @@ export function YieldExpression(node: Object, parent: Object): boolean {
t.isCallExpression(parent) ||
t.isMemberExpression(parent) ||
t.isNewExpression(parent) ||
(t.isAwaitExpression(parent) && t.isYieldExpression(node)) ||
(t.isConditionalExpression(parent) && node === parent.test) ||
isClassExtendsClause(node, parent)
);

View File

@@ -363,14 +363,14 @@ export default class Printer {
}
if (needsParens) this.token("(");
this._printLeadingComments(node, parent);
this._printLeadingComments(node);
const loc = t.isProgram(node) || t.isFile(node) ? null : node.loc;
this.withSource("start", loc, () => {
this[node.type](node, parent);
});
this._printTrailingComments(node, parent);
this._printTrailingComments(node);
if (needsParens) this.token(")");
@@ -472,12 +472,12 @@ export default class Printer {
this.print(node, parent);
}
_printTrailingComments(node, parent) {
this._printComments(this._getComments(false, node, parent));
_printTrailingComments(node) {
this._printComments(this._getComments(false, node));
}
_printLeadingComments(node, parent) {
this._printComments(this._getComments(true, node, parent));
_printLeadingComments(node) {
this._printComments(this._getComments(true, node));
}
printInnerComments(node, indent = true) {

View File

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

View File

@@ -1 +1 @@
{ "plugins": ["asyncGenerators", "classProperties"] }
{ "plugins": ["classProperties"] }

View File

@@ -0,0 +1,11 @@
var fn = async (
arg
) => {}
async (x)
=> {}
async x => {}
async (x
) => {};

View File

@@ -0,0 +1,3 @@
{
"retainLines": true
}

View File

@@ -0,0 +1,11 @@
var fn = async (
arg
) => {};
async (x) =>
{};
async x => {};
async (x) =>
{};

View File

@@ -10,3 +10,7 @@ function* asdf() {
function* a(b) {
(yield xhr({ url: "views/test.html" })).data;
}
(async function* () {
await (yield 1);
});

View File

@@ -11,4 +11,8 @@ function* a(b) {
(yield xhr({
url: "views/test.html"
})).data;
}
}
(async function* () {
await (yield 1);
});

View File

@@ -5,6 +5,15 @@ class Foo {
get foo() {}
set foo(bar) {}
async #foo() {}
#foo() {}
get #foo() {}
set #foo(bar) {}
* #foo() {}
async * #foo() {}
get #bar() {}
set #baz(taz) {}
static async foo() {}
static foo() {}
static ["foo"]() {}
@@ -52,4 +61,4 @@ class Foo {
get
static
() {}
}
}

View File

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

View File

@@ -9,6 +9,22 @@ class Foo {
set foo(bar) {}
async #foo() {}
#foo() {}
get #foo() {}
set #foo(bar) {}
*#foo() {}
async *#foo() {}
get #bar() {}
set #baz(taz) {}
static async foo() {}
static foo() {}

View File

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

View File

@@ -0,0 +1 @@
let result = "hello" |> doubleSay |> text.capitalize |> a.b.exclaim;

View File

@@ -0,0 +1,3 @@
{
"plugins": [["pipelineOperator", { "proposal": "smart" }], "doExpressions"]
}

View File

@@ -0,0 +1 @@
let result = "hello" |> doubleSay |> text.capitalize |> a.b.exclaim;

View File

@@ -0,0 +1,8 @@
value |> # + 1;
value |> 1 + #;
value |> do {
#;
};
value |> do {
if (yes) #;
};

View File

@@ -0,0 +1,3 @@
{
"plugins": [["pipelineOperator", { "proposal": "smart" }], "doExpressions"]
}

View File

@@ -0,0 +1,8 @@
value |> # + 1;
value |> 1 + #;
value |> do {
#;
};
value |> do {
if (yes) #;
};

View File

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

View File

@@ -0,0 +1,3 @@
src
test
*.log

View File

@@ -0,0 +1,19 @@
# @babel/plugin-class-features
> Compile class public and private fields, private methods and decorators to ES6
See our website [@babel/plugin-class-features](https://babeljs.io/docs/en/next/babel-plugin-class-features.html) for more information.
## Install
Using npm:
```sh
npm install --save-dev @babel/plugin-class-features
```
or using yarn:
```sh
yarn add @babel/plugin-class-features --dev
```

View File

@@ -0,0 +1,30 @@
{
"name": "@babel/helper-create-class-features-plugin",
"version": "7.2.3",
"author": "The Babel Team (https://babeljs.io/team)",
"license": "MIT",
"description": "Compile class public and private fields, private methods and decorators to ES6",
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-create-class-features-plugin",
"main": "lib/index.js",
"publishConfig": {
"access": "public"
},
"keywords": [
"babel",
"babel-plugin"
],
"dependencies": {
"@babel/helper-function-name": "^7.1.0",
"@babel/helper-member-expression-to-functions": "^7.0.0",
"@babel/helper-optimise-call-expression": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/helper-replace-supers": "^7.2.3"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/helper-plugin-test-runner": "^7.0.0"
}
}

View File

@@ -0,0 +1,154 @@
import { types as t, template } from "@babel/core";
import ReplaceSupers from "@babel/helper-replace-supers";
export function hasOwnDecorators(node) {
return !!(node.decorators && node.decorators.length);
}
export function hasDecorators(node) {
return hasOwnDecorators(node) || node.body.body.some(hasOwnDecorators);
}
function prop(key, value) {
if (!value) return null;
return t.objectProperty(t.identifier(key), value);
}
function value(body, params = [], async, generator) {
const method = t.objectMethod("method", t.identifier("value"), params, body);
method.async = !!async;
method.generator = !!generator;
return method;
}
function takeDecorators(node) {
let result;
if (node.decorators && node.decorators.length > 0) {
result = t.arrayExpression(
node.decorators.map(decorator => decorator.expression),
);
}
node.decorators = undefined;
return result;
}
function getKey(node) {
if (node.computed) {
return node.key;
} else if (t.isIdentifier(node.key)) {
return t.stringLiteral(node.key.name);
} else {
return t.stringLiteral(String(node.key.value));
}
}
// NOTE: This function can be easily bound as .bind(file, classRef, superRef)
// to make it easier to use it in a loop.
function extractElementDescriptor(/* this: File, */ classRef, superRef, path) {
const { node, scope } = path;
const isMethod = path.isClassMethod();
if (path.isPrivate()) {
throw path.buildCodeFrameError(
`Private ${
isMethod ? "methods" : "fields"
} in decorated classes are not supported yet.`,
);
}
new ReplaceSupers(
{
methodPath: path,
methodNode: node,
objectRef: classRef,
isStatic: node.static,
superRef,
scope,
file: this,
},
true,
).replace();
const properties = [
prop("kind", t.stringLiteral(isMethod ? node.kind : "field")),
prop("decorators", takeDecorators(node)),
prop("static", node.static && t.booleanLiteral(true)),
prop("key", getKey(node)),
isMethod
? value(node.body, node.params, node.async, node.generator)
: node.value
? value(template.ast`{ return ${node.value} }`)
: prop("value", scope.buildUndefinedNode()),
].filter(Boolean);
path.remove();
return t.objectExpression(properties);
}
function addDecorateHelper(file) {
try {
return file.addHelper("decorate");
} catch (err) {
if (err.code === "BABEL_HELPER_UNKNOWN") {
err.message +=
"\n '@babel/plugin-transform-decorators' in non-legacy mode" +
" requires '@babel/core' version ^7.0.2 and you appear to be using" +
" an older version.";
}
throw err;
}
}
export function buildDecoratedClass(ref, path, elements, file) {
const { node, scope } = path;
const initializeId = scope.generateUidIdentifier("initialize");
const isDeclaration = node.id && path.isDeclaration();
const isStrict = path.isInStrictMode();
const { superClass } = node;
node.type = "ClassDeclaration";
if (!node.id) node.id = t.cloneNode(ref);
let superId;
if (superClass) {
superId = scope.generateUidIdentifierBasedOnNode(node.superClass, "super");
node.superClass = superId;
}
const classDecorators = takeDecorators(node);
const definitions = t.arrayExpression(
elements.map(extractElementDescriptor.bind(file, node.id, superId)),
);
let replacement = template.expression.ast`
${addDecorateHelper(file)}(
${classDecorators || t.nullLiteral()},
function (${initializeId}, ${superClass ? superId : null}) {
${node}
return { F: ${t.cloneNode(node.id)}, d: ${definitions} };
},
${superClass}
)
`;
let classPathDesc = "arguments.1.body.body.0";
if (!isStrict) {
replacement.arguments[1].body.directives.push(
t.directive(t.directiveLiteral("use strict")),
);
}
if (isDeclaration) {
replacement = template.ast`let ${ref} = ${replacement}`;
classPathDesc = "declarations.0.init." + classPathDesc;
}
return {
instanceNodes: [template.statement.ast`${initializeId}(this)`],
wrapClass(path) {
path.replaceWith(replacement);
return path.get(classPathDesc);
},
};
}

View File

@@ -0,0 +1,91 @@
import { hasOwnDecorators } from "./decorators";
export const FEATURES = Object.freeze({
//classes: 1 << 0,
fields: 1 << 1,
privateMethods: 1 << 2,
decorators: 1 << 3,
});
// We can't use a symbol because this needs to always be the same, even if
// this package isn't deduped by npm. e.g.
// - node_modules/
// - @babel/plugin-class-features
// - @babel/plugin-proposal-decorators
// - node_modules
// - @babel-plugin-class-features
const featuresKey = "@babel/plugin-class-features/featuresKey";
const looseKey = "@babel/plugin-class-features/looseKey";
export function enableFeature(file, feature, loose) {
// We can't blindly enable the feature because, if it was already set,
// "loose" can't be changed, so that
// @babel/plugin-class-properties { loose: true }
// @babel/plugin-class-properties { loose: false }
// is transformed in loose mode.
// We only enabled the feature if it was previously disabled.
if (!hasFeature(file, feature)) {
file.set(featuresKey, file.get(featuresKey) | feature);
if (loose) file.set(looseKey, file.get(looseKey) | feature);
}
}
function hasFeature(file, feature) {
return !!(file.get(featuresKey) & feature);
}
export function isLoose(file, feature) {
return !!(file.get(looseKey) & feature);
}
export function verifyUsedFeatures(path, file) {
if (hasOwnDecorators(path)) {
if (!hasFeature(file, FEATURES.decorators)) {
throw path.buildCodeFrameError("Decorators are not enabled.");
}
if (path.isPrivate()) {
throw path.buildCodeFrameError(
`Private ${
path.isClassMethod() ? "methods" : "fields"
} in decorated classes are not supported yet.`,
);
}
}
// NOTE: We can't use path.isPrivateMethod() because it isn't supported in <7.2.0
if (path.isPrivate() && path.isMethod()) {
if (!hasFeature(file, FEATURES.privateMethods)) {
throw path.buildCodeFrameError("Class private methods are not enabled.");
}
if (path.node.static) {
throw path.buildCodeFrameError(
"@babel/plugin-class-features doesn't support class static private methods yet.",
);
}
if (path.node.kind !== "method") {
throw path.buildCodeFrameError(
"@babel/plugin-class-features doesn't support class private accessors yet.",
);
}
}
if (
hasFeature(file, FEATURES.privateMethods) &&
hasFeature(file, FEATURES.fields) &&
isLoose(file, FEATURES.privateMethods) !== isLoose(file, FEATURES.fields)
) {
throw path.buildCodeFrameError(
"'loose' mode configuration must be the same for both @babel/plugin-proposal-class-properties " +
"and @babel/plugin-proposal-private-methods",
);
}
if (path.isProperty()) {
if (!hasFeature(file, FEATURES.fields)) {
throw path.buildCodeFrameError("Class fields are not enabled.");
}
}
}

View File

@@ -0,0 +1,428 @@
import { template, traverse, types as t } from "@babel/core";
import { environmentVisitor } from "@babel/helper-replace-supers";
import memberExpressionToFunctions from "@babel/helper-member-expression-to-functions";
import optimiseCall from "@babel/helper-optimise-call-expression";
export function buildPrivateNamesMap(props) {
const privateNamesMap = new Map();
for (const prop of props) {
if (prop.isPrivate()) {
const { name } = prop.node.key.id;
privateNamesMap.set(name, {
id: prop.scope.generateUidIdentifier(name),
static: !!prop.node.static,
method: prop.isMethod(),
methodId: prop.isMethod()
? prop.scope.generateUidIdentifier(name)
: undefined,
});
}
}
return privateNamesMap;
}
export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
const initNodes = [];
for (const [name, value] of privateNamesMap) {
// In loose mode, both static and instance fields are transpiled using a
// secret non-enumerable property. Hence, we also need to generate that
// key (using the classPrivateFieldLooseKey helper).
// In spec mode, only instance fields need a "private name" initializer
// because static fields are directly assigned to a variable in the
// buildPrivateStaticFieldInitSpec function.
const { id, static: isStatic, method: isMethod } = value;
if (loose) {
initNodes.push(
template.statement.ast`
var ${id} = ${state.addHelper("classPrivateFieldLooseKey")}("${name}")
`,
);
} else if (isMethod && !isStatic) {
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
} else if (!isStatic) {
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
}
}
return initNodes;
}
// Traverses the class scope, handling private name references. If an inner
// class redeclares the same private name, it will hand off traversal to the
// restricted visitor (which doesn't traverse the inner class's inner scope).
const privateNameVisitor = {
PrivateName(path) {
const { privateNamesMap } = this;
const { node, parentPath } = path;
if (!parentPath.isMemberExpression({ property: node })) return;
if (!privateNamesMap.has(node.id.name)) return;
this.handle(parentPath);
},
Class(path) {
const { privateNamesMap } = this;
const body = path.get("body.body");
for (const prop of body) {
if (!prop.isPrivate()) {
continue;
}
if (!privateNamesMap.has(prop.node.key.id.name)) continue;
// This class redeclares the private name.
// So, we can only evaluate the things in the outer scope.
path.traverse(privateNameInnerVisitor, this);
path.skip();
break;
}
},
};
// Traverses the outer portion of a class, without touching the class's inner
// scope, for private names.
const privateNameInnerVisitor = traverse.visitors.merge([
{
PrivateName: privateNameVisitor.PrivateName,
},
environmentVisitor,
]);
const privateNameHandlerSpec = {
memoise(member, count) {
const { scope } = member;
const { object } = member.node;
const memo = scope.maybeGenerateMemoised(object);
if (!memo) {
return;
}
this.memoiser.set(object, memo, count);
},
receiver(member) {
const { object } = member.node;
if (this.memoiser.has(object)) {
return t.cloneNode(this.memoiser.get(object));
}
return t.cloneNode(object);
},
get(member) {
const { classRef, privateNamesMap, file } = this;
const { name } = member.node.property.id;
const {
id,
static: isStatic,
method: isMethod,
methodId,
} = privateNamesMap.get(name);
if (isStatic && !isMethod) {
return t.callExpression(
file.addHelper("classStaticPrivateFieldSpecGet"),
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id)],
);
} else if (isMethod) {
return t.callExpression(file.addHelper("classPrivateMethodGet"), [
this.receiver(member),
t.cloneNode(id),
t.cloneNode(methodId),
]);
} else {
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
this.receiver(member),
t.cloneNode(id),
]);
}
},
set(member, value) {
const { classRef, privateNamesMap, file } = this;
const { name } = member.node.property.id;
const { id, static: isStatic, method: isMethod } = privateNamesMap.get(
name,
);
if (isStatic && !isMethod) {
return t.callExpression(
file.addHelper("classStaticPrivateFieldSpecSet"),
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id), value],
);
} else if (isMethod) {
return t.callExpression(file.addHelper("classPrivateMethodSet"), []);
} else {
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
this.receiver(member),
t.cloneNode(id),
value,
]);
}
},
call(member, args) {
// The first access (the get) should do the memo assignment.
this.memoise(member, 1);
return optimiseCall(this.get(member), this.receiver(member), args);
},
};
const privateNameHandlerLoose = {
handle(member) {
const { privateNamesMap, file } = this;
const { object } = member.node;
const { name } = member.node.property.id;
member.replaceWith(
template.expression`BASE(REF, PROP)[PROP]`({
BASE: file.addHelper("classPrivateFieldLooseBase"),
REF: object,
PROP: privateNamesMap.get(name).id,
}),
);
},
};
export function transformPrivateNamesUsage(
ref,
path,
privateNamesMap,
loose,
state,
) {
const body = path.get("body");
if (loose) {
body.traverse(privateNameVisitor, {
privateNamesMap,
file: state,
...privateNameHandlerLoose,
});
} else {
memberExpressionToFunctions(body, privateNameVisitor, {
privateNamesMap,
classRef: ref,
file: state,
...privateNameHandlerSpec,
});
}
}
function buildPrivateFieldInitLoose(ref, prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode();
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
writable: true,
value: ${value}
});
`;
}
function buildPrivateInstanceFieldInitSpec(ref, prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode();
return template.statement.ast`${id}.set(${ref}, {
// configurable is always false for private elements
// enumerable is always false for private elements
writable: true,
value: ${value},
})`;
}
function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode();
return template.statement.ast`
var ${id} = {
// configurable is false by default
// enumerable is false by default
writable: true,
value: ${value}
};
`;
}
function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
const { methodId, id } = privateNamesMap.get(prop.node.key.id.name);
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
value: ${methodId.name}
});
`;
}
function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name);
return template.statement.ast`${id}.add(${ref})`;
}
function buildPublicFieldInitLoose(ref, prop) {
const { key, computed } = prop.node;
const value = prop.node.value || prop.scope.buildUndefinedNode();
return t.expressionStatement(
t.assignmentExpression(
"=",
t.memberExpression(ref, key, computed || t.isLiteral(key)),
value,
),
);
}
function buildPublicFieldInitSpec(ref, prop, state) {
const { key, computed } = prop.node;
const value = prop.node.value || prop.scope.buildUndefinedNode();
return t.expressionStatement(
t.callExpression(state.addHelper("defineProperty"), [
ref,
computed || t.isLiteral(key) ? key : t.stringLiteral(key.name),
value,
]),
);
}
function buildPrivateInstanceMethodDeclaration(prop, privateNamesMap) {
const { methodId } = privateNamesMap.get(prop.node.key.id.name);
const { params, body } = prop.node;
const methodValue = t.functionExpression(methodId, params, body);
return t.variableDeclaration("var", [
t.variableDeclarator(methodId, methodValue),
]);
}
export function buildFieldsInitNodes(
ref,
props,
privateNamesMap,
state,
loose,
) {
const staticNodes = [];
const instanceNodes = [];
let needsClassRef = false;
for (const prop of props) {
const isStatic = prop.node.static;
const isInstance = !isStatic;
const isPrivate = prop.isPrivate();
const isPublic = !isPrivate;
const isField = prop.isProperty();
const isMethod = !isField;
switch (true) {
case isStatic && isPrivate && isField && loose:
needsClassRef = true;
staticNodes.push(
buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap),
);
break;
case isStatic && isPrivate && isField && !loose:
needsClassRef = true;
staticNodes.push(
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
);
break;
case isStatic && isPublic && isField && loose:
needsClassRef = true;
staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop));
break;
case isStatic && isPublic && isField && !loose:
needsClassRef = true;
staticNodes.push(
buildPublicFieldInitSpec(t.cloneNode(ref), prop, state),
);
break;
case isInstance && isPrivate && isField && loose:
instanceNodes.push(
buildPrivateFieldInitLoose(t.thisExpression(), prop, privateNamesMap),
);
break;
case isInstance && isPrivate && isField && !loose:
instanceNodes.push(
buildPrivateInstanceFieldInitSpec(
t.thisExpression(),
prop,
privateNamesMap,
),
);
break;
case isInstance && isPrivate && isMethod && loose:
instanceNodes.push(
buildPrivateMethodInitLoose(
t.thisExpression(),
prop,
privateNamesMap,
),
);
staticNodes.push(
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
);
break;
case isInstance && isPrivate && isMethod && !loose:
instanceNodes.push(
buildPrivateInstanceMethodInitSpec(
t.thisExpression(),
prop,
privateNamesMap,
),
);
staticNodes.push(
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
);
break;
case isInstance && isPublic && isField && loose:
instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop));
break;
case isInstance && isPublic && isField && !loose:
instanceNodes.push(
buildPublicFieldInitSpec(t.thisExpression(), prop, state),
);
break;
default:
throw new Error("Unreachable.");
}
}
return {
staticNodes,
instanceNodes,
wrapClass(path) {
for (const prop of props) {
prop.remove();
}
if (!needsClassRef) return path;
if (path.isClassExpression()) {
path.scope.push({ id: ref });
path.replaceWith(
t.assignmentExpression("=", t.cloneNode(ref), path.node),
);
} else if (!path.node.id) {
// Anonymous class declaration
path.node.id = ref;
}
return path;
},
};
}

View File

@@ -0,0 +1,187 @@
import nameFunction from "@babel/helper-function-name";
import splitExportDeclaration from "@babel/helper-split-export-declaration";
import {
buildPrivateNamesNodes,
buildPrivateNamesMap,
transformPrivateNamesUsage,
buildFieldsInitNodes,
} from "./fields";
import {
hasOwnDecorators,
buildDecoratedClass,
hasDecorators,
} from "./decorators";
import { injectInitialization, extractComputedKeys } from "./misc";
import {
enableFeature,
verifyUsedFeatures,
FEATURES,
isLoose,
} from "./features";
import pkg from "../package.json";
export { FEATURES };
// Note: Versions are represented as an integer. e.g. 7.1.5 is represented
// as 70000100005. This method is easier than using a semver-parsing
// package, but it breaks if we relese x.y.z where x, y or z are
// greater than 99_999.
const version = pkg.version.split(".").reduce((v, x) => v * 1e5 + +x, 0);
const versionKey = "@babel/plugin-class-features/version";
export function createClassFeaturePlugin({
name,
feature,
loose,
manipulateOptions,
}) {
return {
name,
manipulateOptions,
pre() {
enableFeature(this.file, feature, loose);
if (!this.file.get(versionKey) || this.file.get(versionKey) < version) {
this.file.set(versionKey, version);
}
},
visitor: {
Class(path, state) {
if (this.file.get(versionKey) !== version) return;
verifyUsedFeatures(path, this.file);
// Only fields are currently supported, this needs to be moved somewhere
// else when other features are added.
const loose = isLoose(this.file, FEATURES.fields);
let constructor;
let isDecorated = hasOwnDecorators(path.node);
const props = [];
const elements = [];
const computedPaths = [];
const privateNames = new Set();
const body = path.get("body");
for (const path of body.get("body")) {
verifyUsedFeatures(path, this.file);
if (path.node.computed) {
computedPaths.push(path);
}
if (path.isPrivate()) {
const { name } = path.node.key.id;
if (privateNames.has(name)) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(name);
}
if (path.isClassMethod({ kind: "constructor" })) {
constructor = path;
} else {
elements.push(path);
if (path.isProperty() || path.isPrivate()) {
props.push(path);
}
}
if (!isDecorated) isDecorated = hasOwnDecorators(path.node);
}
if (!props.length && !isDecorated) return;
let ref;
if (path.isClassExpression() || !path.node.id) {
nameFunction(path);
ref = path.scope.generateUidIdentifier("class");
} else {
ref = path.node.id;
}
// NODE: These three functions don't support decorators yet,
// but verifyUsedFeatures throws if there are both
// decorators and private fields.
const privateNamesMap = buildPrivateNamesMap(props);
const privateNamesNodes = buildPrivateNamesNodes(
privateNamesMap,
loose,
state,
);
transformPrivateNamesUsage(ref, path, privateNamesMap, loose, state);
let keysNodes, staticNodes, instanceNodes, wrapClass;
if (isDecorated) {
staticNodes = keysNodes = [];
({ instanceNodes, wrapClass } = buildDecoratedClass(
ref,
path,
elements,
this.file,
));
} else {
keysNodes = extractComputedKeys(ref, path, computedPaths, this.file);
({ staticNodes, instanceNodes, wrapClass } = buildFieldsInitNodes(
ref,
props,
privateNamesMap,
state,
loose,
));
}
if (instanceNodes.length > 0) {
injectInitialization(
path,
constructor,
instanceNodes,
(referenceVisitor, state) => {
if (isDecorated) return;
for (const prop of props) {
if (prop.node.static) continue;
prop.traverse(referenceVisitor, state);
}
},
);
}
path = wrapClass(path);
path.insertBefore(keysNodes);
path.insertAfter([...privateNamesNodes, ...staticNodes]);
},
PrivateName(path) {
if (this.file.get(versionKey) !== version) return;
throw path.buildCodeFrameError(`Unknown PrivateName "${path}"`);
},
ExportDefaultDeclaration(path) {
if (this.file.get(versionKey) !== version) return;
const decl = path.get("declaration");
if (decl.isClassDeclaration() && hasDecorators(decl.node)) {
if (decl.node.id) {
// export default class Foo {}
// -->
// class Foo {} export { Foo as default }
splitExportDeclaration(path);
} else {
// Annyms class declarations can be
// transformed as if they were expressions
decl.node.type = "ClassExpression";
}
}
},
},
};
}

View File

@@ -0,0 +1,111 @@
import { template, traverse, types as t } from "@babel/core";
import { environmentVisitor } from "@babel/helper-replace-supers";
const findBareSupers = traverse.visitors.merge([
{
Super(path) {
const { node, parentPath } = path;
if (parentPath.isCallExpression({ callee: node })) {
this.push(parentPath);
}
},
},
environmentVisitor,
]);
const referenceVisitor = {
"TSTypeAnnotation|TypeAnnotation"(path) {
path.skip();
},
ReferencedIdentifier(path) {
if (this.scope.hasOwnBinding(path.node.name)) {
this.scope.rename(path.node.name);
path.skip();
}
},
};
const classFieldDefinitionEvaluationTDZVisitor = traverse.visitors.merge([
{
ReferencedIdentifier(path) {
if (
this.classBinding &&
this.classBinding === path.scope.getBinding(path.node.name)
) {
const classNameTDZError = this.file.addHelper("classNameTDZError");
const throwNode = t.callExpression(classNameTDZError, [
t.stringLiteral(path.node.name),
]);
path.replaceWith(t.sequenceExpression([throwNode, path.node]));
path.skip();
}
},
},
environmentVisitor,
]);
export function injectInitialization(path, constructor, nodes, renamer) {
if (!nodes.length) return;
const isDerived = !!path.node.superClass;
if (!constructor) {
const newConstructor = t.classMethod(
"constructor",
t.identifier("constructor"),
[],
t.blockStatement([]),
);
if (isDerived) {
newConstructor.params = [t.restElement(t.identifier("args"))];
newConstructor.body.body.push(template.statement.ast`super(...args)`);
}
[constructor] = path.get("body").unshiftContainer("body", newConstructor);
}
if (renamer) {
renamer(referenceVisitor, { scope: constructor.scope });
}
if (isDerived) {
const bareSupers = [];
constructor.traverse(findBareSupers, bareSupers);
for (const bareSuper of bareSupers) {
bareSuper.insertAfter(nodes);
}
} else {
constructor.get("body").unshiftContainer("body", nodes);
}
}
export function extractComputedKeys(ref, path, computedPaths, file) {
const declarations = [];
for (const computedPath of computedPaths) {
computedPath.traverse(classFieldDefinitionEvaluationTDZVisitor, {
classBinding: path.node.id && path.scope.getBinding(path.node.id.name),
file,
});
const computedNode = computedPath.node;
// Make sure computed property names are only evaluated once (upon class definition)
// and in the right order in combination with static properties
if (!computedPath.get("key").isConstantExpression()) {
const ident = path.scope.generateUidIdentifierBasedOnNode(
computedNode.key,
);
declarations.push(
t.variableDeclaration("var", [
t.variableDeclarator(ident, computedNode.key),
]),
);
computedNode.key = t.cloneNode(ident);
}
}
return declarations;
}

View File

@@ -0,0 +1,6 @@
{
"plugins": [
["proposal-class-properties", { "loose": true }, "name 1"],
["proposal-class-properties", { "loose": false }, "name 2"]
]
}

View File

@@ -0,0 +1,6 @@
class A {
constructor() {
this.foo = void 0;
}
}

View File

@@ -0,0 +1,7 @@
const sym = Symbol();
const sym1 = Symbol();
class A {
[sym]: A.B;
[sym1]: Array<A>;
}

View File

@@ -0,0 +1,8 @@
{
"presets": [
"flow"
],
"plugins": [
"proposal-class-properties"
]
}

View File

@@ -0,0 +1,13 @@
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const sym = Symbol();
const sym1 = Symbol();
class A {
constructor() {
_defineProperty(this, sym, void 0);
_defineProperty(this, sym1, void 0);
}
}

View File

@@ -0,0 +1,5 @@
const sym = Symbol();
class A {
[sym]: A;
}

View File

@@ -0,0 +1,8 @@
{
"presets": [
"flow"
],
"plugins": [
"proposal-class-properties"
]
}

View File

@@ -0,0 +1,10 @@
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const sym = Symbol();
class A {
constructor() {
_defineProperty(this, sym, void 0);
}
}

View File

@@ -0,0 +1,3 @@
import runner from "@babel/helper-plugin-test-runner";
runner(__dirname);

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/helper-fixtures",
"version": "7.0.0",
"version": "7.2.0",
"description": "Helper function to support fixtures",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"license": "MIT",

View File

@@ -70,7 +70,7 @@ function findFile(filepath: string, allowJSON: boolean) {
throw new Error(`Found conflicting file matches: ${matches.join(", ")}`);
}
return matches[0] || filepath + ".js";
return matches[0];
}
export default function get(entryLoc): Array<Suite> {
@@ -101,10 +101,26 @@ export default function get(entryLoc): Array<Suite> {
}
function push(taskName, taskDir) {
const actualLoc = findFile(taskDir + "/input");
const expectLoc = findFile(taskDir + "/output", true /* allowJSON */);
const taskDirStats = fs.statSync(taskDir);
let actualLoc = findFile(taskDir + "/input");
let execLoc = findFile(taskDir + "/exec");
// If neither input nor exec is present it is not a real testcase
if (taskDirStats.isDirectory() && !actualLoc && !execLoc) {
if (fs.readdirSync(taskDir).length > 0) {
console.warn(`Skipped test folder with invalid layout: ${taskDir}`);
}
return;
} else if (!actualLoc) {
actualLoc = taskDir + "/input.js";
} else if (!execLoc) {
execLoc = taskDir + "/exec.js";
}
const expectLoc =
findFile(taskDir + "/output", true /* allowJSON */) ||
taskDir + "/output.js";
const actualLocAlias =
suiteName + "/" + taskName + "/" + path.basename(actualLoc);
const expectLocAlias =
@@ -112,7 +128,7 @@ export default function get(entryLoc): Array<Suite> {
let execLocAlias =
suiteName + "/" + taskName + "/" + path.basename(actualLoc);
if (fs.statSync(taskDir).isFile()) {
if (taskDirStats.isFile()) {
const ext = path.extname(taskDir);
if (EXTENSIONS.indexOf(ext) === -1) return;

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/helper-module-transforms",
"version": "7.1.0",
"version": "7.2.2",
"description": "Babel helper functions for implementing ES6 module transformations",
"author": "Logan Smyth <loganfsmyth@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -14,8 +14,8 @@
"@babel/helper-module-imports": "^7.0.0",
"@babel/helper-simple-access": "^7.1.0",
"@babel/helper-split-export-declaration": "^7.0.0",
"@babel/template": "^7.1.0",
"@babel/types": "^7.0.0",
"@babel/template": "^7.2.2",
"@babel/types": "^7.2.2",
"lodash": "^4.17.10"
}
}

View File

@@ -8,6 +8,8 @@ export type ModuleMetadata = {
// The name of the variable that will reference an object containing export names.
exportNameListName: null | string,
hasExports: boolean,
// Lookup from local binding to export information.
local: Map<string, LocalExportMetadata>,
@@ -52,18 +54,7 @@ export type LocalExportMetadata = {
* Check if the module has any exports that need handling.
*/
export function hasExports(metadata: ModuleMetadata) {
const { local, source } = metadata;
return (
local.size > 0 ||
Array.from(source).some(([, meta]) => {
return (
meta.reexports.size > 0 ||
meta.reexportNamespace.size > 0 ||
!!meta.reexportAll
);
})
);
return metadata.hasExports;
}
/**
@@ -99,7 +90,10 @@ export default function normalizeModuleAndLoadMetadata(
nameAnonymousExports(programPath);
const { local, source } = getModuleMetadata(programPath, { loose, lazy });
const { local, source, hasExports } = getModuleMetadata(programPath, {
loose,
lazy,
});
removeModuleDeclarations(programPath);
@@ -127,6 +121,7 @@ export default function normalizeModuleAndLoadMetadata(
return {
exportName,
exportNameListName: null,
hasExports,
local,
source,
};
@@ -171,6 +166,7 @@ function getModuleMetadata(
}
return data;
};
let hasExports = false;
programPath.get("body").forEach(child => {
if (child.isImportDeclaration()) {
const data = getData(child.node.source);
@@ -219,6 +215,7 @@ function getModuleMetadata(
}
});
} else if (child.isExportAllDeclaration()) {
hasExports = true;
const data = getData(child.node.source);
if (!data.loc) data.loc = child.node.loc;
@@ -226,6 +223,7 @@ function getModuleMetadata(
loc: child.node.loc,
};
} else if (child.isExportNamedDeclaration() && child.node.source) {
hasExports = true;
const data = getData(child.node.source);
if (!data.loc) data.loc = child.node.loc;
@@ -242,6 +240,11 @@ function getModuleMetadata(
throw exportName.buildCodeFrameError('Illegal export "__esModule".');
}
});
} else if (
child.isExportNamedDeclaration() ||
child.isExportDefaultDeclaration()
) {
hasExports = true;
}
});
@@ -295,6 +298,7 @@ function getModuleMetadata(
}
return {
hasExports,
local: localData,
source: sourceData,
};

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/helper-replace-supers",
"version": "7.1.0",
"version": "7.2.3",
"description": "Helper function to replace supers",
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-replace-supers",
"license": "MIT",
@@ -11,7 +11,7 @@
"dependencies": {
"@babel/helper-member-expression-to-functions": "^7.0.0",
"@babel/helper-optimise-call-expression": "^7.0.0",
"@babel/traverse": "^7.1.0",
"@babel/traverse": "^7.2.3",
"@babel/types": "^7.0.0"
}
}

View File

@@ -40,6 +40,9 @@ function skipAllButComputedKey(path) {
}
export const environmentVisitor = {
TypeAnnotation(path) {
path.skip();
},
Function(path) {
// Methods will be handled by the Method visit
if (path.isMethod()) return;

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/helper-wrap-function",
"version": "7.1.0",
"version": "7.2.0",
"description": "Helper to wrap functions inside a function call.",
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-wrap-function",
"license": "MIT",
@@ -12,6 +12,6 @@
"@babel/helper-function-name": "^7.1.0",
"@babel/template": "^7.1.0",
"@babel/traverse": "^7.1.0",
"@babel/types": "^7.0.0"
"@babel/types": "^7.2.0"
}
}

View File

@@ -3,7 +3,7 @@ import nameFunction from "@babel/helper-function-name";
import template from "@babel/template";
import * as t from "@babel/types";
const buildExpressionWrapper = template.expression(`
const buildAnonymousExpressionWrapper = template.expression(`
(function () {
var REF = FUNCTION;
return function NAME(PARAMS) {
@@ -12,6 +12,16 @@ const buildExpressionWrapper = template.expression(`
})()
`);
const buildNamedExpressionWrapper = template.expression(`
(function () {
var REF = FUNCTION;
function NAME(PARAMS) {
return REF.apply(this, arguments);
}
return NAME;
})()
`);
const buildDeclarationWrapper = template(`
function NAME(PARAMS) { return REF.apply(this, arguments); }
function REF() {
@@ -53,7 +63,9 @@ function plainFunction(path: NodePath, callId: Object) {
const functionId = node.id;
const wrapper = isDeclaration
? buildDeclarationWrapper
: buildExpressionWrapper;
: functionId
? buildNamedExpressionWrapper
: buildAnonymousExpressionWrapper;
if (path.isArrowFunctionExpression()) {
path.arrowFunctionToExpression();

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/helpers",
"version": "7.1.2",
"version": "7.2.0",
"description": "Collection of helper functions used by Babel transforms.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -12,8 +12,8 @@
"main": "lib/index.js",
"dependencies": {
"@babel/template": "^7.1.2",
"@babel/traverse": "^7.1.0",
"@babel/types": "^7.1.2"
"@babel/traverse": "^7.1.5",
"@babel/types": "^7.2.0"
},
"devDependencies": {
"@babel/helper-plugin-test-runner": "^7.0.0"

View File

@@ -935,13 +935,28 @@ helpers.skipFirstGeneratorNext = helper("7.0.0-beta.0")`
}
`;
helpers.toPropertyKey = helper("7.0.0-beta.0")`
export default function _toPropertyKey(key) {
if (typeof key === "symbol") {
return key;
} else {
return String(key);
helpers.toPrimitive = helper("7.1.5")`
export default function _toPrimitive(
input,
hint /*: "default" | "string" | "number" | void */
) {
if (typeof input !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
`;
helpers.toPropertyKey = helper("7.1.5")`
import toPrimitive from "toPrimitive";
export default function _toPropertyKey(arg) {
var key = toPrimitive(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
`;
@@ -1077,10 +1092,12 @@ helpers.classStaticPrivateFieldSpecSet = helper("7.0.2")`
descriptor.value = value;
return value;
}
`;
helpers.decorate = helper("7.0.2")`
helpers.decorate = helper("7.1.5")`
import toArray from "toArray";
import toPropertyKey from "toPropertyKey";
// These comments are stripped by @babel/template
/*::
@@ -1219,6 +1236,8 @@ helpers.decorate = helper("7.0.2")`
function _createElementDescriptor(
def /*: ElementDefinition */,
) /*: ElementDescriptor */ {
var key = toPropertyKey(def.key);
var descriptor /*: PropertyDescriptor */;
if (def.kind === "method") {
descriptor = {
@@ -1227,6 +1246,10 @@ helpers.decorate = helper("7.0.2")`
configurable: true,
enumerable: false,
};
Object.defineProperty(def.value, "name", {
value: typeof key === "symbol" ? "" : key,
configurable: true,
});
} else if (def.kind === "get") {
descriptor = { get: def.value, configurable: true, enumerable: false };
} else if (def.kind === "set") {
@@ -1237,7 +1260,7 @@ helpers.decorate = helper("7.0.2")`
var element /*: ElementDescriptor */ = {
kind: def.kind === "field" ? "field" : "method",
key: def.key,
key: key,
placement: def.static
? "static"
: def.kind === "field"
@@ -1574,8 +1597,7 @@ helpers.decorate = helper("7.0.2")`
);
}
var key = elementObject.key;
if (typeof key !== "string" && typeof key !== "symbol") key = String(key);
var key = toPropertyKey(elementObject.key);
var placement = String(elementObject.placement);
if (
@@ -1716,4 +1738,19 @@ helpers.decorate = helper("7.0.2")`
}
return constructor;
}
`;
`;
helpers.classPrivateMethodGet = helper("7.1.6")`
export default function _classPrivateMethodGet(receiver, privateSet, fn) {
if (!privateSet.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return fn;
}
`;
helpers.classPrivateMethodSet = helper("7.1.6")`
export default function _classPrivateMethodSet() {
throw new TypeError("attempted to reassign private method");
}
`;

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/node",
"version": "7.0.0",
"version": "7.2.2",
"description": "Babel command line",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -22,17 +22,17 @@
"@babel/polyfill": "^7.0.0",
"@babel/register": "^7.0.0",
"commander": "^2.8.1",
"fs-readdir-recursive": "^1.0.0",
"lodash": "^4.17.10",
"output-file-sync": "^2.0.0",
"v8flags": "^3.1.1"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/helper-fixtures": "^7.0.0"
"@babel/core": "^7.2.2",
"@babel/helper-fixtures": "^7.2.0",
"fs-readdir-recursive": "^1.0.0",
"output-file-sync": "^2.0.0"
},
"bin": {
"babel-node": "./bin/babel-node.js"

View File

@@ -52,6 +52,11 @@ program.option(
"The name of the 'env' to use when loading configs and plugins. " +
"Defaults to the value of BABEL_ENV, or else NODE_ENV, or else 'development'.",
);
program.option(
"--root-mode [mode]",
"The project-root resolution mode. " +
"One of 'root' (the default), 'upward', or 'upward-optional'.",
);
program.option("-w, --plugins [string]", "", collect);
program.option("-b, --presets [string]", "", collect);
@@ -59,7 +64,7 @@ program.version(pkg.version);
program.usage("[options] [ -e script | script.js ] [arguments]");
program.parse(process.argv);
register({
const babelOptions = {
caller: {
name: "@babel/node",
},
@@ -70,12 +75,21 @@ register({
presets: program.presets,
configFile: program.configFile,
envName: program.envName,
rootMode: program.rootMode,
// Commander will default the "--no-" arguments to true, but we want to
// leave them undefined so that @babel/core can handle the
// default-assignment logic on its own.
babelrc: program.babelrc === true ? undefined : program.babelrc,
});
};
for (const key of Object.keys(babelOptions)) {
if (babelOptions[key] === undefined) {
delete babelOptions[key];
}
}
register(babelOptions);
const replPlugin = ({ types: t }) => ({
visitor: {

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/parser",
"version": "7.1.3",
"version": "7.2.3",
"description": "A JavaScript parser",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -28,7 +28,7 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@babel/helper-fixtures": "^7.0.0",
"@babel/helper-fixtures": "^7.2.0",
"charcodes": "0.1.0",
"unicode-11.0.0": "^0.7.7"
},

View File

@@ -23,6 +23,7 @@ import * as N from "../types";
import LValParser from "./lval";
import { reservedWords } from "../util/identifier";
import type { Pos, Position } from "../util/location";
import * as charCodes from "charcodes";
export default class ExpressionParser extends LValParser {
// Forward-declaration: defined in statement.js
@@ -296,18 +297,21 @@ export default class ExpressionParser extends LValParser {
}
const op = this.state.type;
if (op === tt.nullishCoalescing) {
this.expectPlugin("nullishCoalescingOperator");
} else if (op === tt.pipeline) {
if (op === tt.pipeline) {
this.expectPlugin("pipelineOperator");
this.state.inPipeline = true;
this.checkPipelineAtInfixOperator(left, leftStartPos);
} else if (op === tt.nullishCoalescing) {
this.expectPlugin("nullishCoalescingOperator");
}
this.next();
const startPos = this.state.start;
const startLoc = this.state.startLoc;
if (op === tt.pipeline) {
if (
op === tt.pipeline &&
this.getPluginOption("pipelineOperator", "proposal") === "minimal"
) {
if (
this.match(tt.name) &&
this.state.value === "await" &&
@@ -320,22 +324,17 @@ export default class ExpressionParser extends LValParser {
}
}
node.right = this.parseExprOp(
this.parseMaybeUnary(),
startPos,
startLoc,
op.rightAssociative ? prec - 1 : prec,
noIn,
);
node.right = this.parseExprOpRightExpr(op, prec, noIn);
this.finishNode(
node,
op === tt.logicalOR ||
op === tt.logicalAND ||
op === tt.nullishCoalescing
op === tt.logicalAND ||
op === tt.nullishCoalescing
? "LogicalExpression"
: "BinaryExpression",
);
return this.parseExprOp(
node,
leftStartPos,
@@ -348,6 +347,54 @@ export default class ExpressionParser extends LValParser {
return left;
}
// Helper function for `parseExprOp`. Parse the right-hand side of binary-
// operator expressions, then apply any operator-specific functions.
parseExprOpRightExpr(
op: TokenType,
prec: number,
noIn: ?boolean,
): N.Expression {
switch (op) {
case tt.pipeline:
if (this.getPluginOption("pipelineOperator", "proposal") === "smart") {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
return this.withTopicPermittingContext(() => {
return this.parseSmartPipelineBody(
this.parseExprOpBaseRightExpr(op, prec, noIn),
startPos,
startLoc,
);
});
}
// falls through
default:
return this.parseExprOpBaseRightExpr(op, prec, noIn);
}
}
// Helper function for `parseExprOpRightExpr`. Parse the right-hand side of
// binary-operator expressions without applying any operator-specific functions.
parseExprOpBaseRightExpr(
op: TokenType,
prec: number,
noIn: ?boolean,
): N.Expression {
const startPos = this.state.start;
const startLoc = this.state.startLoc;
return this.parseExprOp(
this.parseMaybeUnary(),
startPos,
startLoc,
op.rightAssociative ? prec - 1 : prec,
noIn,
);
}
// Parse unary operators, both prefix and postfix.
parseMaybeUnary(refShorthandDefaultPos: ?Pos): N.Expression {
@@ -522,10 +569,15 @@ export default class ExpressionParser extends LValParser {
}
return this.finishNode(node, "MemberExpression");
} else if (!noCalls && this.match(tt.parenL)) {
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
this.state.maybeInArrowParameters = true;
this.state.yieldOrAwaitInPossibleArrowParameters = null;
const possibleAsync = this.atPossibleAsync(base);
this.next();
const node = this.startNodeAt(startPos, startLoc);
let node = this.startNodeAt(startPos, startLoc);
node.callee = base;
// TODO: Clean up/merge this into `this.state` or a class like acorn's
@@ -554,13 +606,22 @@ export default class ExpressionParser extends LValParser {
);
}
return this.parseAsyncArrowFromCallExpression(
node = this.parseAsyncArrowFromCallExpression(
this.startNodeAt(startPos, startLoc),
node,
);
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
} else {
this.toReferencedList(node.arguments);
this.toReferencedListDeep(node.arguments);
// We keep the old value if it isn't null, for cases like
// (x = async(yield)) => {}
this.state.yieldOrAwaitInPossibleArrowParameters =
this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP;
}
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
return node;
} else if (this.match(tt.backQuote)) {
return this.parseTaggedTemplateExpression(
@@ -685,11 +746,8 @@ export default class ExpressionParser extends LValParser {
node: N.ArrowFunctionExpression,
call: N.CallExpression,
): N.ArrowFunctionExpression {
const oldYield = this.state.yieldInPossibleArrowParameters;
this.state.yieldInPossibleArrowParameters = null;
this.expect(tt.arrow);
this.parseArrowExpression(node, call.arguments, true);
this.state.yieldInPossibleArrowParameters = oldYield;
return node;
}
@@ -707,6 +765,10 @@ export default class ExpressionParser extends LValParser {
// or `{}`.
parseExprAtom(refShorthandDefaultPos?: ?Pos): N.Expression {
// If a division operator appears in an expression position, the
// tokenizer got confused, and we force it to read a regexp instead.
if (this.state.type === tt.slash) this.readRegexp();
const canBeArrow = this.state.potentialArrowAt === this.state.start;
let node;
@@ -800,21 +862,24 @@ export default class ExpressionParser extends LValParser {
id.name === "async" &&
this.match(tt.name)
) {
const oldYield = this.state.yieldInPossibleArrowParameters;
this.state.yieldInPossibleArrowParameters = null;
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
const oldInAsync = this.state.inAsync;
this.state.yieldOrAwaitInPossibleArrowParameters = null;
this.state.inAsync = true;
const params = [this.parseIdentifier()];
this.expect(tt.arrow);
// let foo = bar => {};
// let foo = async bar => {};
this.parseArrowExpression(node, params, true);
this.state.yieldInPossibleArrowParameters = oldYield;
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
this.state.inAsync = oldInAsync;
return node;
}
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
const oldYield = this.state.yieldInPossibleArrowParameters;
this.state.yieldInPossibleArrowParameters = null;
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
this.state.yieldOrAwaitInPossibleArrowParameters = null;
this.parseArrowExpression(node, [id]);
this.state.yieldInPossibleArrowParameters = oldYield;
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
return node;
}
@@ -872,7 +937,14 @@ export default class ExpressionParser extends LValParser {
true,
refShorthandDefaultPos,
);
this.toReferencedList(node.elements);
if (!this.state.maybeInArrowParameters) {
// This could be an array pattern:
// ([a: string, b: string]) => {}
// In this case, we don't have to call toReferencedList. We will
// call it, if needed, when we are sure that it is a parenthesized
// expression by calling toReferencedListDeep.
this.toReferencedList(node.elements);
}
return this.finishNode(node, "ArrayExpression");
case tt.braceL:
@@ -910,6 +982,32 @@ export default class ExpressionParser extends LValParser {
}
}
case tt.hash: {
if (this.state.inPipeline) {
node = this.startNode();
if (
this.getPluginOption("pipelineOperator", "proposal") !== "smart"
) {
this.raise(
node.start,
"Primary Topic Reference found but pipelineOperator not passed 'smart' for 'proposal' option.",
);
}
this.next();
if (this.primaryTopicReferenceIsAllowedInCurrentTopicContext()) {
this.registerTopicReference();
return this.finishNode(node, "PipelinePrimaryTopicReference");
} else {
throw this.raise(
node.start,
`Topic reference was used in a lexical context without topic binding`,
);
}
}
}
default:
throw this.unexpected();
}
@@ -950,7 +1048,16 @@ export default class ExpressionParser extends LValParser {
parseFunctionExpression(): N.FunctionExpression | N.MetaProperty {
const node = this.startNode();
const meta = this.parseIdentifier(true);
// We do not do parseIdentifier here because when parseFunctionExpression
// is called we already know that the current token is a "name" with the value "function"
// This will improve perf a tiny little bit as we do not do validation but more importantly
// here is that parseIdentifier will remove an item from the expression stack
// if "function" or "class" is parsed as identifier (in objects e.g.), which should not happen here.
let meta = this.startNode();
this.next();
meta = this.createIdentifier(meta, "function");
if (this.state.inGenerator && this.eat(tt.dot)) {
return this.parseMetaProperty(node, meta, "sent");
}
@@ -1049,9 +1156,9 @@ export default class ExpressionParser extends LValParser {
this.expect(tt.parenL);
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
const oldYield = this.state.yieldInPossibleArrowParameters;
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
this.state.maybeInArrowParameters = true;
this.state.yieldInPossibleArrowParameters = null;
this.state.yieldOrAwaitInPossibleArrowParameters = null;
const innerStartPos = this.state.start;
const innerStartLoc = this.state.startLoc;
@@ -1085,11 +1192,13 @@ export default class ExpressionParser extends LValParser {
),
);
if (this.match(tt.comma) && this.lookahead().type === tt.parenR) {
this.raise(
this.state.start,
"A trailing comma is not permitted after the rest element",
);
if (this.match(tt.comma)) {
const nextTokenType = this.lookahead().type;
const errorMessage =
nextTokenType === tt.parenR
? "A trailing comma is not permitted after the rest element"
: "Rest parameter must be last formal parameter";
this.raise(this.state.start, errorMessage);
}
break;
@@ -1124,11 +1233,14 @@ export default class ExpressionParser extends LValParser {
}
this.parseArrowExpression(arrowNode, exprList);
this.state.yieldInPossibleArrowParameters = oldYield;
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
return arrowNode;
}
this.state.yieldInPossibleArrowParameters = oldYield;
// We keep the old value if it isn't null, for cases like
// (x = (yield)) => {}
this.state.yieldOrAwaitInPossibleArrowParameters =
this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP;
if (!exprList.length) {
this.unexpected(this.state.lastTokStart);
@@ -1140,10 +1252,10 @@ export default class ExpressionParser extends LValParser {
}
if (refNeedsArrowPos.start) this.unexpected(refNeedsArrowPos.start);
this.toReferencedListDeep(exprList, /* isParenthesizedExpr */ true);
if (exprList.length > 1) {
val = this.startNodeAt(innerStartPos, innerStartLoc);
val.expressions = exprList;
this.toReferencedList(val.expressions);
this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
} else {
val = exprList[0];
@@ -1322,7 +1434,6 @@ export default class ExpressionParser extends LValParser {
}
if (this.match(tt.ellipsis)) {
this.expectPlugin("objectRestSpread");
prop = this.parseSpread(isPattern ? { start: 0 } : undefined);
if (isPattern) {
this.toAssignable(prop, true, "object pattern");
@@ -1382,11 +1493,7 @@ export default class ExpressionParser extends LValParser {
prop.computed = false;
} else {
isAsync = true;
if (this.match(tt.star)) {
this.expectPlugin("asyncGenerators");
this.next();
isGenerator = true;
}
isGenerator = this.eat(tt.star);
this.parsePropertyName(prop);
}
} else {
@@ -1625,9 +1732,11 @@ export default class ExpressionParser extends LValParser {
): T {
const oldInFunc = this.state.inFunction;
const oldInMethod = this.state.inMethod;
const oldInAsync = this.state.inAsync;
const oldInGenerator = this.state.inGenerator;
this.state.inFunction = true;
this.state.inMethod = node.kind || true;
this.state.inAsync = isAsync;
this.state.inGenerator = isGenerator;
this.initFunction(node, isAsync);
@@ -1638,6 +1747,7 @@ export default class ExpressionParser extends LValParser {
this.state.inFunction = oldInFunc;
this.state.inMethod = oldInMethod;
this.state.inAsync = oldInAsync;
this.state.inGenerator = oldInGenerator;
return node;
@@ -1649,16 +1759,25 @@ export default class ExpressionParser extends LValParser {
parseArrowExpression(
node: N.ArrowFunctionExpression,
params?: ?(N.Expression[]),
isAsync?: boolean,
isAsync?: boolean = false,
): N.ArrowFunctionExpression {
// if we got there, it's no more "yield in possible arrow parameters";
// it's just "yield in arrow parameters"
if (this.state.yieldInPossibleArrowParameters) {
this.raise(
this.state.yieldInPossibleArrowParameters.start,
"yield is not allowed in the parameters of an arrow function" +
" inside a generator",
);
const yOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
if (yOAIPAP) {
if (yOAIPAP.type === "YieldExpression") {
this.raise(
yOAIPAP.start,
"yield is not allowed in the parameters of an arrow function" +
" inside a generator",
);
} else {
this.raise(
yOAIPAP.start,
"await is not allowed in the parameters of an arrow function" +
" inside an async function",
);
}
}
const oldInFunc = this.state.inFunction;
@@ -1666,11 +1785,14 @@ export default class ExpressionParser extends LValParser {
this.initFunction(node, isAsync);
if (params) this.setArrowFunctionParameters(node, params);
const oldInAsync = this.state.inAsync;
const oldInGenerator = this.state.inGenerator;
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
this.state.inAsync = isAsync;
this.state.inGenerator = false;
this.state.maybeInArrowParameters = false;
this.parseFunctionBody(node, true);
this.state.inAsync = oldInAsync;
this.state.inGenerator = oldInGenerator;
this.state.inFunction = oldInFunc;
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
@@ -1718,9 +1840,7 @@ export default class ExpressionParser extends LValParser {
const isExpression = allowExpression && !this.match(tt.braceL);
const oldInParameters = this.state.inParameters;
const oldInAsync = this.state.inAsync;
this.state.inParameters = false;
this.state.inAsync = node.async;
if (isExpression) {
node.body = this.parseMaybeAssign();
@@ -1738,7 +1858,6 @@ export default class ExpressionParser extends LValParser {
this.state.inGenerator = oldInGen;
this.state.labels = oldLabels;
}
this.state.inAsync = oldInAsync;
this.checkFunctionNameAndParams(node, allowExpression);
this.state.inParameters = oldInParameters;
@@ -1839,8 +1958,14 @@ export default class ExpressionParser extends LValParser {
parseIdentifier(liberal?: boolean): N.Identifier {
const node = this.startNode();
const name = this.parseIdentifierName(node.start, liberal);
return this.createIdentifier(node, name);
}
createIdentifier(node: N.Identifier, name: string): N.Identifier {
node.name = name;
node.loc.identifierName = name;
return this.finishNode(node, "Identifier");
}
@@ -1860,6 +1985,19 @@ export default class ExpressionParser extends LValParser {
name = this.state.value;
} else if (this.state.type.keyword) {
name = this.state.type.keyword;
// `class` and `function` keywords push new context into this.context.
// But there is no chance to pop the context if the keyword is consumed
// as an identifier such as a property name.
// If the previous token is a dot, this does not apply because the
// context-managing code already ignored the keyword
if (
(name === "class" || name === "function") &&
(this.state.lastTokEnd !== this.state.lastTokStart + 1 ||
this.input.charCodeAt(this.state.lastTokStart) !== charCodes.dot)
) {
this.state.context.pop();
}
} else {
throw this.unexpected();
}
@@ -1915,12 +2053,27 @@ export default class ExpressionParser extends LValParser {
) {
this.unexpected();
}
if (this.state.inParameters) {
this.raise(
node.start,
"await is not allowed in async function parameters",
);
}
if (this.match(tt.star)) {
this.raise(
node.start,
"await* has been removed from the async functions proposal. Use Promise.all() instead.",
);
}
if (
this.state.maybeInArrowParameters &&
// We only set yieldOrAwaitInPossibleArrowParameters if we haven't already
// found a possible invalid AwaitExpression.
!this.state.yieldOrAwaitInPossibleArrowParameters
) {
this.state.yieldOrAwaitInPossibleArrowParameters = node;
}
node.argument = this.parseMaybeUnary();
return this.finishNode(node, "AwaitExpression");
}
@@ -1935,11 +2088,11 @@ export default class ExpressionParser extends LValParser {
}
if (
this.state.maybeInArrowParameters &&
// We only set yieldInPossibleArrowParameters if we haven't already
// We only set yieldOrAwaitInPossibleArrowParameters if we haven't already
// found a possible invalid YieldExpression.
!this.state.yieldInPossibleArrowParameters
!this.state.yieldOrAwaitInPossibleArrowParameters
) {
this.state.yieldInPossibleArrowParameters = node;
this.state.yieldOrAwaitInPossibleArrowParameters = node;
}
this.next();
@@ -1956,4 +2109,180 @@ export default class ExpressionParser extends LValParser {
}
return this.finishNode(node, "YieldExpression");
}
// Validates a pipeline (for any of the pipeline Babylon plugins) at the point
// of the infix operator `|>`.
checkPipelineAtInfixOperator(left: N.Expression, leftStartPos: number) {
if (this.getPluginOption("pipelineOperator", "proposal") === "smart") {
if (left.type === "SequenceExpression") {
// Ensure that the pipeline head is not a comma-delimited
// sequence expression.
throw this.raise(
leftStartPos,
`Pipeline head should not be a comma-separated sequence expression`,
);
}
}
}
parseSmartPipelineBody(
childExpression: N.Expression,
startPos: number,
startLoc: Position,
): N.PipelineBody {
const pipelineStyle = this.checkSmartPipelineBodyStyle(childExpression);
this.checkSmartPipelineBodyEarlyErrors(
childExpression,
pipelineStyle,
startPos,
);
return this.parseSmartPipelineBodyInStyle(
childExpression,
pipelineStyle,
startPos,
startLoc,
);
}
checkSmartPipelineBodyEarlyErrors(
childExpression: N.Expression,
pipelineStyle: N.PipelineStyle,
startPos: number,
): void {
if (this.match(tt.arrow)) {
// If the following token is invalidly `=>`, then throw a human-friendly error
// instead of something like 'Unexpected token, expected ";"'.
throw this.raise(
this.state.start,
`Unexpected arrow "=>" after pipeline body; arrow function in pipeline body must be parenthesized`,
);
} else if (
pipelineStyle === "PipelineTopicExpression" &&
childExpression.type === "SequenceExpression"
) {
throw this.raise(
startPos,
`Pipeline body may not be a comma-separated sequence expression`,
);
}
}
parseSmartPipelineBodyInStyle(
childExpression: N.Expression,
pipelineStyle: N.PipelineStyle,
startPos: number,
startLoc: Position,
): N.PipelineBody {
const bodyNode = this.startNodeAt(startPos, startLoc);
switch (pipelineStyle) {
case "PipelineBareFunction":
bodyNode.callee = childExpression;
break;
case "PipelineBareConstructor":
bodyNode.callee = childExpression.callee;
break;
case "PipelineBareAwaitedFunction":
bodyNode.callee = childExpression.argument;
break;
case "PipelineTopicExpression":
if (!this.topicReferenceWasUsedInCurrentTopicContext()) {
throw this.raise(
startPos,
`Pipeline is in topic style but does not use topic reference`,
);
}
bodyNode.expression = childExpression;
break;
default:
throw this.raise(startPos, `Unknown pipeline style ${pipelineStyle}`);
}
return this.finishNode(bodyNode, pipelineStyle);
}
checkSmartPipelineBodyStyle(expression: N.Expression): N.PipelineStyle {
switch (expression.type) {
default:
return this.isSimpleReference(expression)
? "PipelineBareFunction"
: "PipelineTopicExpression";
}
}
isSimpleReference(expression: N.Expression): boolean {
switch (expression.type) {
case "MemberExpression":
return (
!expression.computed && this.isSimpleReference(expression.object)
);
case "Identifier":
return true;
default:
return false;
}
}
// Enable topic references from outer contexts within smart pipeline bodies.
// The function modifies the parser's topic-context state to enable or disable
// the use of topic references with the smartPipelines plugin. They then run a
// callback, then they reset the parser to the old topic-context state that it
// had before the function was called.
withTopicPermittingContext<T>(callback: () => T): T {
const outerContextTopicState = this.state.topicContext;
this.state.topicContext = {
// Enable the use of the primary topic reference.
maxNumOfResolvableTopics: 1,
// Hide the use of any topic references from outer contexts.
maxTopicIndex: null,
};
try {
return callback();
} finally {
this.state.topicContext = outerContextTopicState;
}
}
// Disable topic references from outer contexts within syntax constructs
// such as the bodies of iteration statements.
// The function modifies the parser's topic-context state to enable or disable
// the use of topic references with the smartPipelines plugin. They then run a
// callback, then they reset the parser to the old topic-context state that it
// had before the function was called.
withTopicForbiddingContext<T>(callback: () => T): T {
const outerContextTopicState = this.state.topicContext;
this.state.topicContext = {
// Disable the use of the primary topic reference.
maxNumOfResolvableTopics: 0,
// Hide the use of any topic references from outer contexts.
maxTopicIndex: null,
};
try {
return callback();
} finally {
this.state.topicContext = outerContextTopicState;
}
}
// Register the use of a primary topic reference (`#`) within the current
// topic context.
registerTopicReference(): void {
this.state.topicContext.maxTopicIndex = 0;
}
primaryTopicReferenceIsAllowedInCurrentTopicContext(): boolean {
return this.state.topicContext.maxNumOfResolvableTopics >= 1;
}
topicReferenceWasUsedInCurrentTopicContext(): boolean {
return (
this.state.topicContext.maxTopicIndex != null &&
this.state.topicContext.maxTopicIndex >= 0
);
}
}

View File

@@ -177,10 +177,26 @@ export default class LValParser extends NodeUtils {
toReferencedList(
exprList: $ReadOnlyArray<?Expression>,
isParenthesizedExpr?: boolean, // eslint-disable-line no-unused-vars
): $ReadOnlyArray<?Expression> {
return exprList;
}
toReferencedListDeep(
exprList: $ReadOnlyArray<?Expression>,
isParenthesizedExpr?: boolean,
): $ReadOnlyArray<?Expression> {
this.toReferencedList(exprList, isParenthesizedExpr);
for (const expr of exprList) {
if (expr && expr.type === "ArrayExpression") {
this.toReferencedListDeep(expr.elements);
}
}
return exprList;
}
// Parses spread element.
parseSpread<T: RestElement | SpreadElement>(
@@ -257,7 +273,20 @@ export default class LValParser extends NodeUtils {
break;
} else if (this.match(tt.ellipsis)) {
elts.push(this.parseAssignableListItemTypes(this.parseRest()));
this.expect(close);
if (
this.state.inFunction &&
this.state.inParameters &&
this.match(tt.comma)
) {
const nextTokenType = this.lookahead().type;
const errorMessage =
nextTokenType === tt.parenR
? "A trailing comma is not permitted after the rest element"
: "Rest parameter must be last formal parameter";
this.raise(this.state.start, errorMessage);
} else {
this.expect(close);
}
break;
} else {
const decorators = [];

View File

@@ -369,8 +369,18 @@ export default class StatementParser extends ExpressionParser {
parseDoStatement(node: N.DoWhileStatement): N.DoWhileStatement {
this.next();
this.state.labels.push(loopLabel);
node.body = this.parseStatement(false);
node.body =
// For the smartPipelines plugin: Disable topic references from outer
// contexts within the loop body. They are permitted in test expressions,
// outside of the loop body.
this.withTopicForbiddingContext(() =>
// Parse the loop body's body.
this.parseStatement(false),
);
this.state.labels.pop();
this.expect(tt._while);
node.test = this.parseParenExpression();
this.eat(tt.semi);
@@ -391,7 +401,6 @@ export default class StatementParser extends ExpressionParser {
let forAwait = false;
if (this.state.inAsync && this.isContextual("await")) {
this.expectPlugin("asyncGenerators");
forAwait = true;
this.next();
}
@@ -556,10 +565,19 @@ export default class StatementParser extends ExpressionParser {
this.checkLVal(clause.param, true, clashes, "catch clause");
this.expect(tt.parenR);
} else {
this.expectPlugin("optionalCatchBinding");
clause.param = null;
}
clause.body = this.parseBlock();
clause.body =
// For the smartPipelines plugin: Disable topic references from outer
// contexts within the function body. They are permitted in function
// default-parameter expressions, which are part of the outer context,
// outside of the function body.
this.withTopicForbiddingContext(() =>
// Parse the catch clause's body.
this.parseBlock(false),
);
node.handler = this.finishNode(clause, "CatchClause");
}
@@ -587,8 +605,18 @@ export default class StatementParser extends ExpressionParser {
this.next();
node.test = this.parseParenExpression();
this.state.labels.push(loopLabel);
node.body = this.parseStatement(false);
node.body =
// For the smartPipelines plugin:
// Disable topic references from outer contexts within the loop body.
// They are permitted in test expressions, outside of the loop body.
this.withTopicForbiddingContext(() =>
// Parse loop body.
this.parseStatement(false),
);
this.state.labels.pop();
return this.finishNode(node, "WhileStatement");
}
@@ -598,7 +626,17 @@ export default class StatementParser extends ExpressionParser {
}
this.next();
node.object = this.parseParenExpression();
node.body = this.parseStatement(false);
node.body =
// For the smartPipelines plugin:
// Disable topic references from outer contexts within the function body.
// They are permitted in function default-parameter expressions, which are
// part of the outer context, outside of the function body.
this.withTopicForbiddingContext(() =>
// Parse the statement body.
this.parseStatement(false),
);
return this.finishNode(node, "WithStatement");
}
@@ -621,8 +659,8 @@ export default class StatementParser extends ExpressionParser {
const kind = this.state.type.isLoop
? "loop"
: this.match(tt._switch)
? "switch"
: null;
? "switch"
: null;
for (let i = this.state.labels.length - 1; i >= 0; i--) {
const label = this.state.labels[i];
if (label.statementStart === node.start) {
@@ -755,8 +793,18 @@ export default class StatementParser extends ExpressionParser {
this.expect(tt.semi);
node.update = this.match(tt.parenR) ? null : this.parseExpression();
this.expect(tt.parenR);
node.body = this.parseStatement(false);
node.body =
// For the smartPipelines plugin: Disable topic references from outer
// contexts within the loop body. They are permitted in test expressions,
// outside of the loop body.
this.withTopicForbiddingContext(() =>
// Parse the loop body.
this.parseStatement(false),
);
this.state.labels.pop();
return this.finishNode(node, "ForStatement");
}
@@ -780,8 +828,18 @@ export default class StatementParser extends ExpressionParser {
node.left = init;
node.right = this.parseExpression();
this.expect(tt.parenR);
node.body = this.parseStatement(false);
node.body =
// For the smartPipelines plugin:
// Disable topic references from outer contexts within the loop body.
// They are permitted in test expressions, outside of the loop body.
this.withTopicForbiddingContext(() =>
// Parse loop body.
this.parseStatement(false),
);
this.state.labels.pop();
return this.finishNode(node, type);
}
@@ -838,12 +896,13 @@ export default class StatementParser extends ExpressionParser {
parseFunction<T: N.NormalFunction>(
node: T,
isStatement: boolean,
allowExpressionBody?: boolean,
isAsync?: boolean,
optionalId?: boolean,
allowExpressionBody?: boolean = false,
isAsync?: boolean = false,
optionalId?: boolean = false,
): T {
const oldInFunc = this.state.inFunction;
const oldInMethod = this.state.inMethod;
const oldInAsync = this.state.inAsync;
const oldInGenerator = this.state.inGenerator;
const oldInClassProperty = this.state.inClassProperty;
this.state.inFunction = true;
@@ -853,9 +912,6 @@ export default class StatementParser extends ExpressionParser {
this.initFunction(node, isAsync);
if (this.match(tt.star)) {
if (node.async) {
this.expectPlugin("asyncGenerators");
}
node.generator = true;
this.next();
}
@@ -877,21 +933,36 @@ export default class StatementParser extends ExpressionParser {
// valid because yield is parsed as if it was outside the generator.
// Therefore, this.state.inGenerator is set before or after parsing the
// function id according to the "isStatement" parameter.
if (!isStatement) this.state.inGenerator = node.generator;
// The same applies to await & async functions.
if (!isStatement) {
this.state.inAsync = isAsync;
this.state.inGenerator = node.generator;
}
if (this.match(tt.name) || this.match(tt._yield)) {
node.id = this.parseBindingIdentifier();
}
if (isStatement) this.state.inGenerator = node.generator;
if (isStatement) {
this.state.inAsync = isAsync;
this.state.inGenerator = node.generator;
}
this.parseFunctionParams(node);
this.parseFunctionBodyAndFinish(
node,
isStatement ? "FunctionDeclaration" : "FunctionExpression",
allowExpressionBody,
);
// For the smartPipelines plugin: Disable topic references from outer
// contexts within the function body. They are permitted in test
// expressions, outside of the function body.
this.withTopicForbiddingContext(() => {
// Parse the function body.
this.parseFunctionBodyAndFinish(
node,
isStatement ? "FunctionDeclaration" : "FunctionExpression",
allowExpressionBody,
);
});
this.state.inFunction = oldInFunc;
this.state.inMethod = oldInMethod;
this.state.inAsync = oldInAsync;
this.state.inGenerator = oldInGenerator;
this.state.inClassProperty = oldInClassProperty;
@@ -962,44 +1033,49 @@ export default class StatementParser extends ExpressionParser {
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
if (this.eat(tt.semi)) {
if (decorators.length > 0) {
// For the smartPipelines plugin: Disable topic references from outer
// contexts within the class body. They are permitted in test expressions,
// outside of the class body.
this.withTopicForbiddingContext(() => {
while (!this.eat(tt.braceR)) {
if (this.eat(tt.semi)) {
if (decorators.length > 0) {
this.raise(
this.state.lastTokEnd,
"Decorators must not be followed by a semicolon",
);
}
continue;
}
if (this.match(tt.at)) {
decorators.push(this.parseDecorator());
continue;
}
const member = this.startNode();
// steal the decorators if there are any
if (decorators.length) {
member.decorators = decorators;
this.resetStartLocationFromNode(member, decorators[0]);
decorators = [];
}
this.parseClassMember(classBody, member, state);
if (
member.kind === "constructor" &&
member.decorators &&
member.decorators.length > 0
) {
this.raise(
this.state.lastTokEnd,
"Decorators must not be followed by a semicolon",
member.start,
"Decorators can't be used with a constructor. Did you mean '@dec class { ... }'?",
);
}
continue;
}
if (this.match(tt.at)) {
decorators.push(this.parseDecorator());
continue;
}
const member = this.startNode();
// steal the decorators if there are any
if (decorators.length) {
member.decorators = decorators;
this.resetStartLocationFromNode(member, decorators[0]);
decorators = [];
}
this.parseClassMember(classBody, member, state);
if (
member.kind === "constructor" &&
member.decorators &&
member.decorators.length > 0
) {
this.raise(
member.start,
"Decorators can't be used with a constructor. Did you mean '@dec class { ... }'?",
);
}
}
});
if (decorators.length) {
this.raise(
@@ -1153,11 +1229,7 @@ export default class StatementParser extends ExpressionParser {
}
} else if (isSimple && key.name === "async" && !this.isLineTerminator()) {
// an async method
const isGenerator = this.match(tt.star);
if (isGenerator) {
this.expectPlugin("asyncGenerators");
this.next();
}
const isGenerator = this.eat(tt.star);
method.kind = "method";
// The so-called parsed name would have been "async": get the real name.

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