Compare commits

...

108 Commits

Author SHA1 Message Date
Nicolò Ribaudo
f6ee26c3da v7.3.0 2019-01-21 22:22:39 +01:00
Tim McClure
e8de6fa5d4 Private Class Methods Stage 3: Private Accessors (#9101)
* Add accessor loose support

* Add private accessors spec support

* Fix private dupe name check

* Changes from code review

* Add duplicated names tests

* Add get/set-only tests

* Move accessors tests

* Split out updates tests

* Add helper change tests

* Update test output

* Update test options
2019-01-21 22:05:37 +01:00
Kagami Sascha Rosylight
3ae5e79ec8 Differentiate object spread and non-spread properties (#9341)
* add isSpread field

* use argument

* t.booleanLiteral

* fix typo

* push empty-argument object

* .object

* .value

* object field should be an expression

* lint

* update outputs

* isSpread for the second argument is redundant

* add test

* alternating spread
2019-01-21 22:04:47 +01:00
Thiago Arrais
e9331aa0c0 Transform for the smart pipeline operator proposal (#9179) 2019-01-21 22:04:14 +01:00
Henry Zhu
ba4141934f add v7 downloads [skip ci] (#9370) 2019-01-21 12:48:15 -05:00
Daniel Tschinder
96a7343142 Merge pull request #9348 from danez/perf
Parser Performance Collection
2019-01-21 02:27:42 -08:00
Armano
a2e6d8e968 Disallow usage of invalid keyword after export abstract statement in Typescript (#9336) 2019-01-19 15:48:05 -06:00
Nicolò Ribaudo
4ce37b7aca Update test262 sha (#9365) 2019-01-19 18:10:28 +01:00
Brian Ng
b92ad318f1 Add support for transform-named-capturing-groups-regex in preset-env (#9345) 2019-01-17 19:51:38 -06:00
Daniel Tschinder
2d6231fd3d Update flow whitelist 2019-01-17 16:16:32 -08:00
Daniel Tschinder
4e5e319d5b perf: remove double check for keywords in readWord
Instead of calling isKeyword we simple check directly if the keyword token is available
2019-01-17 16:16:31 -08:00
Daniel Tschinder
b66d921053 perf: Use === or Set.has instead of array.indexOf for keyword checks 2019-01-17 16:16:30 -08:00
Daniel Tschinder
f12905b531 perf: Use for loops while cloning classes 2019-01-17 16:16:29 -08:00
Daniel Tschinder
f216975378 perf: call isLineTerminator as last check 2019-01-17 16:16:28 -08:00
Daniel Tschinder
3a3d5cbe9c perf: Check for plugin only once before looping 2019-01-17 16:16:28 -08:00
Daniel Tschinder
10555c719e Build the parser also for node 6.9 and up 2019-01-17 16:16:27 -08:00
Daniel Tschinder
58768072ef perf: Ensure canInsertSemicolon is always called last
It does a lot of checks and a regex test
2019-01-17 16:16:26 -08:00
Daniel Tschinder
455e003567 perf: Optimize regex
This saves some steps, as the regex parser does not have to backtrack for character classes, but is has to for alternates
2019-01-17 16:15:07 -08:00
Daniel Tschinder
49f7bcf271 perf: Remove unnecessary check for flow plugin inside of flow plugin 2019-01-17 16:15:07 -08:00
Daniel Tschinder
c2e41588aa perf: run flow code in flow plugin 2019-01-17 16:15:05 -08:00
Daniel Tschinder
a1eac37bd2 Generate prettier comments 2019-01-17 16:15:04 -08:00
Daniel Tschinder
0370af58f1 perf: Use strict equals 2019-01-17 16:15:03 -08:00
Daniel Tschinder
8df0500f55 perf: Simplify reading of tokens.
This avoids checking isIdentifierStart for every single token
2019-01-17 16:15:01 -08:00
Daniel Tschinder
e4b8cfc768 perf: use Set instead of string indexOf 2019-01-17 16:15:00 -08:00
Daniel Tschinder
a7757ec4d0 perf: Use increment operator 2019-01-17 16:14:58 -08:00
Daniel Tschinder
25a8db2a29 perf: use normal equality check in stead of indexOf 2019-01-17 16:14:57 -08:00
Daniel Tschinder
48fd387779 perf: precalculate length 2019-01-17 16:14:56 -08:00
Daniel Tschinder
59c4bbb4ab perf: Make plugins a map instead of object
Fix plugin options
2019-01-17 16:14:55 -08:00
Daniel Tschinder
2dc1c91955 perf: Move input to state and precalculate length
This also fixes a bug with async functions
2019-01-17 16:14:54 -08:00
Daniel Tschinder
ae154c86ed perf: Minor optimizations 2019-01-17 16:14:53 -08:00
unconfident
e9588061d7 Copy "optional" property when cloning Identifier node (#9333)
Fixes #9331
2019-01-17 17:12:16 -05:00
Nicolò Ribaudo
0a88230ec4 Disallow async functions as loop bodies (#9314) 2019-01-17 17:07:48 -05:00
Nicolò Ribaudo
a27b9b4299 Add @babel/plugin-transform-named-capturing-groups-regex (#7105)
When the `runtime` flag is on (by default), this plugin adds a new helper which wraps the native `RegExp` class to provide groups support. People nees to use a polyfill (I implemented it in core-js) for browsers that don't support ES6 regexps.
2019-01-15 18:21:17 +01:00
Brian Ng
aaec2cd51d Fix handling newline with TypeScript declare and abstract classes (#9328) 2019-01-15 06:56:52 -06:00
Brian Ng
34c9890f41 Fix range on TypeScript index signature parameters (#9335) 2019-01-15 06:52:33 -06:00
Armano
e8038863c3 Fix range on TypeScript this type predicate (#9339) 2019-01-15 10:35:49 +01:00
Nicolò Ribaudo
694e3fd8cf Merge declaration and init of props in parser's state (#9312)
* Merge declaration and init of props in parser's state

* Move type def
2019-01-13 23:54:44 +01:00
Brian Ng
40ae6568a4 Add support for proposal-json-strings in preset-env (#9323) 2019-01-13 08:32:33 -06:00
Henry Zhu
4944e9e180 update sponsor link again [skip ci] 2019-01-13 08:00:46 -05:00
Nicolò Ribaudo
a24206eb96 Fix error for decorators not enabled (#9321)
* Fix error for decorators not enabled

* Update error message
2019-01-13 00:35:22 +01:00
Henry Zhu
d6b4ab75ee fix sponsor link [skip ci] 2019-01-12 10:41:49 -05:00
Nicolò Ribaudo
3e4b608a80 Parse class heritage as strict mode code (#9315) 2019-01-12 14:54:23 +01:00
Henry Zhu
28319eb07e add sponsor [skip ci] 2019-01-11 13:50:48 -05:00
Nicolò Ribaudo
5889620a6a Disallow new import(x) and import(x,) (#9313)
* Disallow "new import(...)"

* Disallow trailing comma inside dynamic import

* Rename test

* Update error message
2019-01-11 18:59:51 +01:00
Nicolò Ribaudo
9764718c32 Disallow trailing comma after rest (#9311)
* Add new tests

* Use state instead of param and disallow comma in [...a,]=[]

* Unify error messages

* Object destructuring

* Update whitelist
2019-01-11 13:08:38 +01:00
Nicolò Ribaudo
28b70e5910 Generate types for TSImportType 2019-01-11 11:46:15 +01:00
Henry Zhu
4c2f8d9337 @babel/generator: Add emit and builder for TSImportType (#9309) 2019-01-10 13:57:00 -05:00
Armano
2cc0376756 @babel/parser(ts): Add parsing of type import (#9302) 2019-01-10 11:14:48 -05:00
Nicolò Ribaudo
8e051cae46 [decorators] Set method names at compile time instead of at runtime (#9244) 2019-01-10 00:45:02 +01:00
Cameron Martin
778a61a3c2 [@babel/types] Moved generators related to babel-types into the babel-types package directory. (#9245) 2019-01-09 00:14:31 +01:00
Armano
46e3f6df1f @babel/parser: include leading character into range of generic ArrowFunctionExpression (#9295) 2019-01-08 07:19:55 -06:00
Brian Ng
03022d169e Throw error if TypeScript class has empty implements (#9292) 2019-01-07 15:27:27 -06:00
David Laban
9803253363 flow type update: babel-types.isType(?string, string): boolean (#9275) 2019-01-07 08:53:01 -06:00
Brian Ng
a55382e4ad Test262 update (#9288) 2019-01-07 08:52:36 -06:00
Sven Sauleau
b211b810d1 Use 2014-present in license (#9290) 2019-01-07 08:52:11 -06:00
James George
25e880d355 Add follow on twitter badge (#9264) [skip ci] 2019-01-07 09:49:20 -05:00
Daniel Tschinder
e43777bb5f Fix location for typescript type assertions in AST (#9284) 2019-01-06 16:39:14 -08:00
Nicolò Ribaudo
efc60a1703 Add test sources to prettierignore (#9287) [skip ci] 2019-01-06 20:59:02 +01:00
Daniel Tschinder
54f072991d Revert "Revert babel-helper-builder-react-jsx change from #4988" (#9119)
This reverts commit dbc07220ae.

# Conflicts:
#	packages/babel-helper-builder-react-jsx/src/index.js
2019-01-05 22:22:49 -08:00
Brian Ng
a58893d1e3 Ensure modifiers are included in TSParameterProperty ranges (#9276) 2019-01-04 10:02:09 -06:00
Nicolò Ribaudo
865eb93c2d [private methods] Define private methods before executing initializers (#9248) 2019-01-03 20:33:44 +01:00
Berlam Henderson
49f52bbcb3 Bump license years for 2019 (#9271) 2019-01-03 09:12:03 -06:00
Nicolò Ribaudo
9d1d0fe57a Add mixins support to the _decorate helper (#9166) 2018-12-29 22:54:30 +01:00
Brian Ng
ea1c436ea1 Fix handling scoped packages in preset-env include/exclude options (#9219) 2018-12-27 09:54:28 -06:00
David Laban
3f9a1c08cc Add tests for babel-types.isType (#9243) 2018-12-27 12:49:34 +01:00
J. S. Choi
c586d4e8ca parser, smart pipes: Add support for yield in pipeline bodies
Fixes #9178.
2018-12-23 17:09:18 +01:00
J. S. Choi
60ffe1d103 parser, smart pipes: Add test for async–await 2018-12-23 17:09:18 +01:00
Armano
b5177ce290 babel-parser: typescript: add missing bigint keyword (#9230) 2018-12-22 17:18:32 -06:00
Henry Zhu
d1aa665657 update sponsors [skip ci] 2018-12-21 21:39:06 -05:00
Nicolò Ribaudo
f130981546 v7.2.5 2018-12-21 23:32:48 +01:00
Nicolò Ribaudo
bc347bab7a Add @babel/helpers to devDependencies of runtime and runtime-corejs2 (#9222) 2018-12-21 10:08:47 +01:00
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
484 changed files with 11507 additions and 4495 deletions

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"
}
},
{
@@ -31,7 +31,7 @@
"files": ["packages/babel-plugin-*/src/index.js"],
"excludedFiles": ["packages/babel-plugin-transform-regenerator/**/*.js"],
"rules": {
"local-rules/plugin-name": "error"
"@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,2 +1,5 @@
package.json
packages/babel-preset-env/data
packages/*/test/fixtures/**/input.*
packages/*/test/fixtures/**/exec.*
packages/*/test/fixtures/**/output.*

View File

@@ -1,6 +1,5 @@
git:
depth: 5
sudo: false
language: node_js
cache:
yarn: true
@@ -20,17 +19,18 @@ before_install:
install:
# the `make test-ci` script runs this command already
- if [ "$JOB" != "test" ]; then yarn install; fi
- 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`).

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2014-2018 Sebastian McKenzie and other contributors
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,6 +1,6 @@
MAKEFLAGS = -j1
FLOW_COMMIT = e192e1a4793dd8e43415fbfe8046d832cb513c8b
TEST262_COMMIT = 238c88d4a084d9928372954e2fec54af2c951281
FLOW_COMMIT = 2ac56861e3ceff9ca406ae586fbafb3480c6c0b7
TEST262_COMMIT = 4f1155c566a222238fd86f179c6635ecb4c289bb
# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
export FORCE_COLOR = true
@@ -15,8 +15,8 @@ build: clean clean-lib
# call build again as the generated files might need to be compiled again.
./node_modules/.bin/gulp build
# generate flow and typescript typings
node scripts/generators/flow.js > ./packages/babel-types/lib/index.js.flow
node scripts/generators/typescript.js > ./packages/babel-types/lib/index.d.ts
node packages/babel-types/scripts/generators/flow.js > ./packages/babel-types/lib/index.js.flow
node packages/babel-types/scripts/generators/typescript.js > ./packages/babel-types/lib/index.d.ts
ifneq ("$(BABEL_COVERAGE)", "true")
make build-standalone
make build-preset-env-standalone
@@ -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
@@ -40,7 +46,8 @@ watch: clean clean-lib
# development too.
BABEL_ENV=development ./node_modules/.bin/gulp build-no-bundle
node ./packages/babel-types/scripts/generateTypeHelpers.js
node scripts/generators/flow.js > ./packages/babel-types/lib/index.js.flow
node packages/babel-types/scripts/generators/flow.js > ./packages/babel-types/lib/index.js.flow
node packages/babel-types/scripts/generators/typescript.js > ./packages/babel-types/lib/index.d.ts
BABEL_ENV=development ./node_modules/.bin/gulp watch
flow:
@@ -96,7 +103,7 @@ test-flow-update-whitelist:
bootstrap-test262:
rm -rf ./build/test262
mkdir -p ./build
git clone --branch=master --single-branch --shallow-since=2018-11-01 https://github.com/tc39/test262.git ./build/test262
git clone --branch=master --single-branch --shallow-since=2010-01-10 https://github.com/tc39/test262.git ./build/test262
cd build/test262 && git checkout $(TEST262_COMMIT)
test-test262:
@@ -115,7 +122,7 @@ prepublish-build:
rm -rf packages/babel-runtime/helpers
rm -rf packages/babel-runtime-corejs2/helpers
rm -rf packages/babel-runtime-corejs2/core-js
BABEL_ENV=production IS_PUBLISH=true make build-dist
BABEL_ENV=production make build-dist
make clone-license
prepublish:
@@ -124,8 +131,7 @@ prepublish:
make test
publish: prepublish
# --only-explicit-updates
./node_modules/.bin/lerna publish --force-publish="@babel/runtime,@babel/runtime-corejs2" --dangerously-only-publish-explicit-updates-this-is-a-custom-flag-for-babel-and-you-should-not-be-using-it-just-deal-with-more-packages-being-published-it-is-not-a-big-deal
./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

@@ -8,12 +8,16 @@
The compiler for writing next generation JavaScript.
</p>
<p align="center">
<a href="https://www.npmjs.com/package/@babel/core"><img alt="v7 npm Downloads" src="https://img.shields.io/npm/dm/@babel/core.svg?maxAge=43200&label=v7%20downloads"></a>
<a href="https://www.npmjs.com/package/babel-core"><img alt="v6 npm Downloads" src="https://img.shields.io/npm/dm/babel-core.svg?maxAge=43200&label=v6%20downloads"></a>
</p>
<p align="center">
<a href="https://travis-ci.org/babel/babel"><img alt="Travis Status" src="https://img.shields.io/travis/babel/babel/master.svg?label=travis&maxAge=43200"></a>
<a href="https://circleci.com/gh/babel/babel"><img alt="CircleCI Status" src="https://img.shields.io/circleci/project/github/babel/babel/master.svg?label=circle&maxAge=43200"></a>
<a href="https://codecov.io/github/babel/babel"><img alt="Coverage Status" src="https://img.shields.io/codecov/c/github/babel/babel/master.svg?maxAge=43200"></a>
<a href="https://slack.babeljs.io/"><img alt="Slack Status" src="https://slack.babeljs.io/badge.svg"></a>
<a href="https://www.npmjs.com/package/babel-core"><img alt="npm Downloads" src="https://img.shields.io/npm/dm/babel-core.svg?maxAge=43200"></a>
<a href="https://twitter.com/intent/follow?screen_name=babeljs"><img alt="Follow on Twitter" src="https://img.shields.io/twitter/follow/babeljs.svg?style=social&label=Follow"></a>
</p>
<h2 align="center">Supporting Babel</h2>
@@ -48,35 +52,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>
<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>
<a href="https://issuehunt.io" target="_blank"><img src="https://github.com/BoostIO/issuehunt-materials/blob/master/v1/issuehunt-logo-and-word-v1.png?raw=true" height="64"></a>
## Intro
@@ -103,7 +87,7 @@ Try it out at our [REPL](https://babeljs.io/repl/build/master#?code_lz=NoRgNATGD
### Who maintains Babel?
Mostly a handful of volunteers! Please check out our [team page](https://babeljs.io/team)!
Mostly a handful of volunteers, funded by you! Please check out our [team page](https://babeljs.io/team)!
### Looking for support?

View File

@@ -14,12 +14,16 @@ module.exports = function(api) {
let convertESM = true;
let ignoreLib = true;
let includeRuntime = false;
const nodeVersion = "6.9";
switch (env) {
// Configs used during bundling builds.
case "babel-parser":
convertESM = false;
ignoreLib = false;
envOpts.targets = {
node: nodeVersion,
};
break;
case "standalone":
convertESM = false;
@@ -29,7 +33,7 @@ module.exports = function(api) {
case "production":
// Config during builds before publish.
envOpts.targets = {
node: "6.9",
node: nodeVersion,
};
break;
case "development":

View File

@@ -1,6 +1,5 @@
{
"lerna": "2.11.0",
"version": "7.2.0",
"version": "7.3.0",
"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

@@ -9,34 +9,34 @@
"test": "make test"
},
"devDependencies": {
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
"@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.6",
"@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.5",
"@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.9.0",
"eslint-config-babel": "^8.0.2",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-local-rules": "0.1.0",
"eslint-plugin-prettier": "^3.0.0",
"flow-bin": "^0.82.0",
"flow-bin": "^0.87.0",
"graceful-fs": "^4.1.11",
"gulp": "^4.0.0",
"gulp-babel": "^8.0.0",
@@ -49,7 +49,7 @@
"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": "^8.1.0",
"lodash": "^4.17.10",
@@ -69,6 +69,9 @@
"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 < 12.0.0",
"npm": ">= 3.x <= 6.x",
@@ -124,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.2.0",
"version": "7.2.3",
"description": "Babel command line.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",

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. " +

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/core",
"version": "7.2.0",
"version": "7.2.2",
"description": "Babel compiler core.",
"main": "lib/index.js",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
@@ -34,12 +34,12 @@
},
"dependencies": {
"@babel/code-frame": "^7.0.0",
"@babel/generator": "^7.2.0",
"@babel/generator": "^7.2.2",
"@babel/helpers": "^7.2.0",
"@babel/parser": "^7.2.0",
"@babel/template": "^7.1.2",
"@babel/traverse": "^7.1.6",
"@babel/types": "^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": "^4.1.0",
"json5": "^2.1.0",

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

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

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

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

@@ -476,6 +476,21 @@ export function TSModuleBlock(node) {
this.tsPrintBraced(node.body, node);
}
export function TSImportType(node) {
const { argument, qualifier, typeParameters } = node;
this.word("import");
this.token("(");
this.print(argument, node);
this.token(")");
if (qualifier) {
this.token(".");
this.print(qualifier, node);
}
if (typeParameters) {
this.print(typeParameters, node);
}
}
export function TSImportEqualsDeclaration(node) {
const { isExport, id, moduleReference } = node;
if (isExport) {

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

@@ -0,0 +1,3 @@
let x: typeof import('./x');
let Y: import('./y').Y;
let z: import("/z").foo.bar<string>;

View File

@@ -0,0 +1,3 @@
let x: typeof import('./x');
let Y: import('./y').Y;
let z: import("/z").foo.bar<string>;

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/helper-builder-react-jsx",
"version": "7.0.0",
"version": "7.3.0",
"description": "Helper function to build react jsx",
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-builder-react-jsx",
"license": "MIT",
@@ -9,7 +9,7 @@
},
"main": "lib/index.js",
"dependencies": {
"@babel/types": "^7.0.0",
"@babel/types": "^7.3.0",
"esutils": "^2.0.0"
}
}

View File

@@ -19,6 +19,13 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
);
}
};
visitor.JSXSpreadChild = function(path) {
throw path.buildCodeFrameError(
"Spread children are not supported in React.",
);
};
visitor.JSXElement = {
exit(path, file) {
const callExpr = buildElementCall(path, file);

View File

@@ -1,10 +1,10 @@
{
"name": "@babel/helper-create-class-features-plugin",
"version": "7.2.0",
"version": "7.3.0",
"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-plugin-class-features",
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-create-class-features-plugin",
"main": "lib/index.js",
"publishConfig": {
"access": "public"
@@ -18,13 +18,13 @@
"@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.1.0"
"@babel/helper-replace-supers": "^7.2.3"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
},
"devDependencies": {
"@babel/core": "^7.2.0",
"@babel/core": "^7.2.2",
"@babel/helper-plugin-test-runner": "^7.0.0"
}
}

View File

@@ -1,3 +1,164 @@
export function hasDecorators(path) {
return !!(path.node.decorators && path.node.decorators.length);
import { types as t, template } from "@babel/core";
import ReplaceSupers from "@babel/helper-replace-supers";
import nameFunction from "@babel/helper-function-name";
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 method(key, body) {
return t.objectMethod(
"method",
t.identifier(key),
[],
t.blockStatement(body),
);
}
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)),
].filter(Boolean);
if (isMethod) {
const id = node.computed ? null : node.key;
t.toExpression(node);
properties.push(prop("value", nameFunction({ node, id, scope }) || node));
} else if (node.value) {
properties.push(
method("value", template.statements.ast`return ${node.value}`),
);
} else {
properties.push(prop("value", scope.buildUndefinedNode()));
}
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

@@ -1,4 +1,4 @@
import { hasDecorators } from "./decorators";
import { hasOwnDecorators } from "./decorators";
export const FEATURES = Object.freeze({
//classes: 1 << 0,
@@ -39,17 +39,30 @@ export function isLoose(file, feature) {
}
export function verifyUsedFeatures(path, file) {
if (hasDecorators(path) && !hasFeature(file, FEATURES.decorators)) {
throw path.buildCodeFrameError("Decorators are not enabled.");
if (hasOwnDecorators(path.node)) {
if (!hasFeature(file, FEATURES.decorators)) {
throw path.buildCodeFrameError(
"Decorators are not enabled." +
"\nIf you are using " +
'["@babel/plugin-proposal-decorators", { "legacy": true }], ' +
'make sure it comes *before* "@babel/plugin-proposal-class-properties" ' +
"and enable loose mode, like so:\n" +
'\t["@babel/plugin-proposal-decorators", { "legacy": true }]\n' +
'\t["@babel/plugin-proposal-class-properties", { "loose": true }]',
);
}
if (path.isPrivate()) {
throw path.buildCodeFrameError(
`Private ${
path.isClassMethod() ? "methods" : "fields"
} in decorated classes are not supported yet.`,
);
}
}
if (hasFeature(file, FEATURES.decorators)) {
throw new Error(
"@babel/plugin-class-features doesn't support decorators yet.",
);
}
if (path.isClassPrivateMethod()) {
// 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.");
}
@@ -59,12 +72,6 @@ export function verifyUsedFeatures(path, file) {
"@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 (

View File

@@ -6,16 +6,26 @@ 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 isPrivate = prop.isPrivate();
const isMethod = !prop.isProperty();
const isInstance = !prop.node.static;
if (isPrivate) {
const { name } = prop.node.key.id;
privateNamesMap.set(name, {
id: prop.scope.generateUidIdentifier(name),
static: !!prop.node.static,
method: prop.isClassPrivateMethod(),
methodId: prop.isClassPrivateMethod()
? prop.scope.generateUidIdentifier(name)
: undefined,
});
const update = privateNamesMap.has(name)
? privateNamesMap.get(name)
: {
id: prop.scope.generateUidIdentifier(name),
static: !isInstance,
method: isMethod,
};
if (prop.node.kind === "get") {
update.getId = prop.scope.generateUidIdentifier(`get_${name}`);
} else if (prop.node.kind === "set") {
update.setId = prop.scope.generateUidIdentifier(`set_${name}`);
} else if (prop.node.kind === "method" && isMethod && isInstance) {
update.methodId = prop.scope.generateUidIdentifier(name);
}
privateNamesMap.set(name, update);
}
}
return privateNamesMap;
@@ -31,7 +41,7 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
// 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;
const { id, static: isStatic, method: isMethod, getId, setId } = value;
if (loose) {
initNodes.push(
template.statement.ast`
@@ -39,7 +49,11 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
`,
);
} else if (isMethod && !isStatic) {
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
if (getId || setId) {
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
} else {
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
}
} else if (!isStatic) {
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
}
@@ -121,6 +135,8 @@ const privateNameHandlerSpec = {
static: isStatic,
method: isMethod,
methodId,
getId,
setId,
} = privateNamesMap.get(name);
if (isStatic && !isMethod) {
@@ -128,41 +144,57 @@ const privateNameHandlerSpec = {
file.addHelper("classStaticPrivateFieldSpecGet"),
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id)],
);
} else if (isMethod) {
}
if (isMethod) {
if (getId || setId) {
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
this.receiver(member),
t.cloneNode(id),
]);
}
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),
]);
}
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,
);
const {
id,
static: isStatic,
method: isMethod,
setId,
} = 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,
]);
}
if (isMethod) {
if (setId) {
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
this.receiver(member),
t.cloneNode(id),
value,
]);
}
return t.callExpression(file.addHelper("classPrivateMethodSet"), []);
}
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
this.receiver(member),
t.cloneNode(id),
value,
]);
},
call(member, args) {
@@ -255,21 +287,91 @@ function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
}
function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
const { methodId, id } = privateNamesMap.get(prop.node.key.id.name);
const privateName = privateNamesMap.get(prop.node.key.id.name);
const { methodId, id, getId, setId, initAdded } = privateName;
if (initAdded) return;
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}
if (methodId) {
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}
});
`;
}
if (getId || setId) {
privateNamesMap.set(prop.node.key.id.name, {
...privateName,
initAdded: true,
});
`;
if (getId && setId) {
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId.name},
set: ${setId.name}
});
`;
} else if (getId && !setId) {
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId.name}
});
`;
} else if (!getId && setId) {
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
set: ${setId.name}
});
`;
}
}
}
function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name);
const privateName = privateNamesMap.get(prop.node.key.id.name);
const { id, getId, setId, initAdded } = privateName;
if (initAdded) return;
if (getId || setId) {
privateNamesMap.set(prop.node.key.id.name, {
...privateName,
initAdded: true,
});
if (getId && setId) {
return template.statement.ast`
${id}.set(${ref}, {
get: ${getId.name},
set: ${setId.name}
});
`;
} else if (getId && !setId) {
return template.statement.ast`
${id}.set(${ref}, {
get: ${getId.name}
});
`;
} else if (!getId && setId) {
return template.statement.ast`
${id}.set(${ref}, {
set: ${setId.name}
});
`;
}
}
return template.statement.ast`${id}.add(${ref})`;
}
@@ -300,9 +402,37 @@ function buildPublicFieldInitSpec(ref, prop, state) {
}
function buildPrivateInstanceMethodDeclaration(prop, privateNamesMap) {
const { methodId } = privateNamesMap.get(prop.node.key.id.name);
const privateName = privateNamesMap.get(prop.node.key.id.name);
const {
methodId,
getId,
setId,
getterDeclared,
setterDeclared,
} = privateName;
const { params, body } = prop.node;
const methodValue = t.functionExpression(methodId, params, body);
const isGetter = getId && !getterDeclared && params.length === 0;
const isSetter = setId && !setterDeclared && params.length > 0;
if (isGetter) {
privateNamesMap.set(prop.node.key.id.name, {
...privateName,
getterDeclared: true,
});
return t.variableDeclaration("var", [
t.variableDeclarator(getId, methodValue),
]);
}
if (isSetter) {
privateNamesMap.set(prop.node.key.id.name, {
...privateName,
setterDeclared: true,
});
return t.variableDeclaration("var", [
t.variableDeclarator(setId, methodValue),
]);
}
return t.variableDeclaration("var", [
t.variableDeclarator(methodId, methodValue),
@@ -318,37 +448,45 @@ export function buildFieldsInitNodes(
) {
const staticNodes = [];
const instanceNodes = [];
let needsClassRef = false;
for (const prop of props) {
const isStatic = prop.node.static;
const isPrivateField = prop.isClassPrivateProperty();
const isPrivateMethod = prop.isClassPrivateMethod();
const isInstance = !isStatic;
const isPrivate = prop.isPrivate();
const isPublic = !isPrivate;
const isField = prop.isProperty();
const isMethod = !isField;
switch (true) {
case isStatic && isPrivateField && loose:
case isStatic && isPrivate && isField && loose:
needsClassRef = true;
staticNodes.push(
buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap),
);
break;
case isStatic && isPrivateField && !loose:
case isStatic && isPrivate && isField && !loose:
needsClassRef = true;
staticNodes.push(
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
);
break;
case isStatic && !isPrivateField && loose:
case isStatic && isPublic && isField && loose:
needsClassRef = true;
staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop));
break;
case isStatic && !isPrivateField && !loose:
case isStatic && isPublic && isField && !loose:
needsClassRef = true;
staticNodes.push(
buildPublicFieldInitSpec(t.cloneNode(ref), prop, state),
);
break;
case !isStatic && isPrivateField && loose:
case isInstance && isPrivate && isField && loose:
instanceNodes.push(
buildPrivateFieldInitLoose(t.thisExpression(), prop, privateNamesMap),
);
break;
case !isStatic && isPrivateField && !loose:
case isInstance && isPrivate && isField && !loose:
instanceNodes.push(
buildPrivateInstanceFieldInitSpec(
t.thisExpression(),
@@ -357,8 +495,8 @@ export function buildFieldsInitNodes(
),
);
break;
case !isStatic && isPrivateMethod && loose:
instanceNodes.push(
case isInstance && isPrivate && isMethod && loose:
instanceNodes.unshift(
buildPrivateMethodInitLoose(
t.thisExpression(),
prop,
@@ -369,8 +507,8 @@ export function buildFieldsInitNodes(
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
);
break;
case !isStatic && isPrivateMethod && !loose:
instanceNodes.push(
case isInstance && isPrivate && isMethod && !loose:
instanceNodes.unshift(
buildPrivateInstanceMethodInitSpec(
t.thisExpression(),
prop,
@@ -381,10 +519,10 @@ export function buildFieldsInitNodes(
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
);
break;
case !isStatic && !isPrivateField && loose:
case isInstance && isPublic && isField && loose:
instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop));
break;
case !isStatic && !isPrivateField && !loose:
case isInstance && isPublic && isField && !loose:
instanceNodes.push(
buildPublicFieldInitSpec(t.thisExpression(), prop, state),
);
@@ -394,5 +532,27 @@ export function buildFieldsInitNodes(
}
}
return { staticNodes, instanceNodes };
return {
staticNodes,
instanceNodes: instanceNodes.filter(Boolean),
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

@@ -1,11 +1,16 @@
import nameFunction from "@babel/helper-function-name";
import { types as t } from "@babel/core";
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,
@@ -54,7 +59,9 @@ export function createClassFeaturePlugin({
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");
@@ -68,21 +75,54 @@ export function createClassFeaturePlugin({
if (path.isPrivate()) {
const { name } = path.node.key.id;
const getName = `get ${name}`;
const setName = `set ${name}`;
if (privateNames.has(name)) {
throw path.buildCodeFrameError("Duplicate private field");
if (path.node.kind === "get") {
if (
privateNames.has(getName) ||
(privateNames.has(name) && !privateNames.has(setName))
) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(getName).add(name);
} else if (path.node.kind === "set") {
if (
privateNames.has(setName) ||
(privateNames.has(name) && !privateNames.has(getName))
) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(setName).add(name);
} else {
if (
(privateNames.has(name) &&
(!privateNames.has(getName) && !privateNames.has(setName))) ||
(privateNames.has(name) &&
(privateNames.has(getName) || privateNames.has(setName)))
) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(name);
}
privateNames.add(name);
}
if (path.isProperty() || path.isClassPrivateMethod()) {
props.push(path);
} else if (path.isClassMethod({ kind: "constructor" })) {
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) return;
if (!props.length && !isDecorated) return;
let ref;
@@ -93,13 +133,9 @@ export function createClassFeaturePlugin({
ref = path.node.id;
}
const keysNodes = extractComputedKeys(
ref,
path,
computedPaths,
this.file,
);
// 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,
@@ -109,19 +145,34 @@ export function createClassFeaturePlugin({
transformPrivateNamesUsage(ref, path, privateNamesMap, loose, state);
const { staticNodes, instanceNodes } = buildFieldsInitNodes(
ref,
props,
privateNamesMap,
state,
loose,
);
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);
@@ -130,28 +181,7 @@ export function createClassFeaturePlugin({
);
}
for (const prop of props) {
prop.remove();
}
if (
keysNodes.length === 0 &&
staticNodes.length === 0 &&
privateNamesNodes.length === 0
) {
return;
}
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;
}
path = wrapClass(path);
path.insertBefore(keysNodes);
path.insertAfter([...privateNamesNodes, ...staticNodes]);
},
@@ -161,6 +191,25 @@ export function createClassFeaturePlugin({
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,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

@@ -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/helpers",
"version": "7.2.0",
"version": "7.3.0",
"description": "Collection of helper functions used by Babel transforms.",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -13,7 +13,7 @@
"dependencies": {
"@babel/template": "^7.1.2",
"@babel/traverse": "^7.1.5",
"@babel/types": "^7.2.0"
"@babel/types": "^7.3.0"
},
"devDependencies": {
"@babel/helper-plugin-test-runner": "^7.0.0"

View File

@@ -389,16 +389,20 @@ helpers.objectSpread = helper("7.0.0-beta.0")`
export default function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = (arguments[i] != null) ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
if (i % 2) {
var source = (arguments[i] != null) ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === 'function') {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
defineProperty(target, key, source[key]);
});
} else {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(arguments[i]));
}
ownKeys.forEach(function(key) {
defineProperty(target, key, source[key]);
});
}
return target;
}
@@ -1048,7 +1052,11 @@ helpers.classPrivateFieldGet = helper("7.0.0-beta.0")`
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver).value;
var descriptor = privateMap.get(receiver);
if (descriptor.get) {
return descriptor.get.call(receiver);
}
return descriptor.value;
}
`;
@@ -1058,13 +1066,19 @@ helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
throw new TypeError("attempted to set private field on non-instance");
}
var descriptor = privateMap.get(receiver);
if (!descriptor.writable) {
// This should only throw in strict mode, but class bodies are
// always strict and private fields can only be used inside
// class bodies.
throw new TypeError("attempted to set read only private field");
if (descriptor.set) {
descriptor.set.call(receiver, value);
} else {
if (!descriptor.writable) {
// This should only throw in strict mode, but class bodies are
// always strict and private fields can only be used inside
// class bodies.
throw new TypeError("attempted to set read only private field");
}
descriptor.value = value;
}
descriptor.value = value;
return value;
}
`;
@@ -1213,23 +1227,430 @@ helpers.decorate = helper("7.1.5")`
*/
/*::
type Placements = {
static: Key[],
prototype: Key[],
own: Key[],
};
*/
// ClassDefinitionEvaluation (Steps 26-*)
export default function _decorate(
decorators /*: ClassDecorator[] */,
factory /*: ClassFactory */,
superClass /*: ?Class<*> */,
mixins /*: ?Array<Function> */,
) /*: Class<*> */ {
var api = _getDecoratorsApi();
if (mixins) {
for (var i = 0; i < mixins.length; i++) {
api = mixins[i](api);
}
}
var r = factory(function initialize(O) {
_initializeInstanceElements(O, decorated.elements);
api.initializeInstanceElements(O, decorated.elements);
}, superClass);
var decorated = _decorateClass(
var decorated = api.decorateClass(
_coalesceClassElements(r.d.map(_createElementDescriptor)),
decorators,
);
_initializeClassElements(r.F, decorated.elements);
api.initializeClassElements(r.F, decorated.elements);
return _runClassFinishers(r.F, decorated.finishers);
return api.runClassFinishers(r.F, decorated.finishers);
}
function _getDecoratorsApi() {
_getDecoratorsApi = function() {
return api;
};
var api = {
elementsDefinitionOrder: [["method"], ["field"]],
// InitializeInstanceElements
initializeInstanceElements: function(
/*::<C>*/ O /*: C */,
elements /*: ElementDescriptor[] */,
) {
["method", "field"].forEach(function(kind) {
elements.forEach(function(element /*: ElementDescriptor */) {
if (element.kind === kind && element.placement === "own") {
this.defineClassElement(O, element);
}
}, this);
}, this);
},
// InitializeClassElements
initializeClassElements: function(
/*::<C>*/ F /*: Class<C> */,
elements /*: ElementDescriptor[] */,
) {
var proto = F.prototype;
["method", "field"].forEach(function(kind) {
elements.forEach(function(element /*: ElementDescriptor */) {
var placement = element.placement;
if (
element.kind === kind &&
(placement === "static" || placement === "prototype")
) {
var receiver = placement === "static" ? F : proto;
this.defineClassElement(receiver, element);
}
}, this);
}, this);
},
// DefineClassElement
defineClassElement: function(
/*::<C>*/ receiver /*: C | Class<C> */,
element /*: ElementDescriptor */,
) {
var descriptor /*: PropertyDescriptor */ = element.descriptor;
if (element.kind === "field") {
var initializer = element.initializer;
descriptor = {
enumerable: descriptor.enumerable,
writable: descriptor.writable,
configurable: descriptor.configurable,
value: initializer === void 0 ? void 0 : initializer.call(receiver),
};
}
Object.defineProperty(receiver, element.key, descriptor);
},
// DecorateClass
decorateClass: function(
elements /*: ElementDescriptor[] */,
decorators /*: ClassDecorator[] */,
) /*: ElementsFinishers */ {
var newElements /*: ElementDescriptor[] */ = [];
var finishers /*: ClassFinisher[] */ = [];
var placements /*: Placements */ = {
static: [],
prototype: [],
own: [],
};
elements.forEach(function(element /*: ElementDescriptor */) {
this.addElementPlacement(element, placements);
}, this);
elements.forEach(function(element /*: ElementDescriptor */) {
if (!_hasDecorators(element)) return newElements.push(element);
var elementFinishersExtras /*: ElementFinishersExtras */ = this.decorateElement(
element,
placements,
);
newElements.push(elementFinishersExtras.element);
newElements.push.apply(newElements, elementFinishersExtras.extras);
finishers.push.apply(finishers, elementFinishersExtras.finishers);
}, this);
if (!decorators) {
return { elements: newElements, finishers: finishers };
}
var result /*: ElementsFinishers */ = this.decorateConstructor(
newElements,
decorators,
);
finishers.push.apply(finishers, result.finishers);
result.finishers = finishers;
return result;
},
// AddElementPlacement
addElementPlacement: function(
element /*: ElementDescriptor */,
placements /*: Placements */,
silent /*: boolean */,
) {
var keys = placements[element.placement];
if (!silent && keys.indexOf(element.key) !== -1) {
throw new TypeError("Duplicated element (" + element.key + ")");
}
keys.push(element.key);
},
// DecorateElement
decorateElement: function(
element /*: ElementDescriptor */,
placements /*: Placements */,
) /*: ElementFinishersExtras */ {
var extras /*: ElementDescriptor[] */ = [];
var finishers /*: ClassFinisher[] */ = [];
for (
var decorators = element.decorators, i = decorators.length - 1;
i >= 0;
i--
) {
// (inlined) RemoveElementPlacement
var keys = placements[element.placement];
keys.splice(keys.indexOf(element.key), 1);
var elementObject /*: ElementObjectInput */ = this.fromElementDescriptor(
element,
);
var elementFinisherExtras /*: ElementFinisherExtras */ = this.toElementFinisherExtras(
(0, decorators[i])(elementObject) /*: ElementObjectOutput */ ||
elementObject,
);
element = elementFinisherExtras.element;
this.addElementPlacement(element, placements);
if (elementFinisherExtras.finisher) {
finishers.push(elementFinisherExtras.finisher);
}
var newExtras /*: ElementDescriptor[] | void */ =
elementFinisherExtras.extras;
if (newExtras) {
for (var j = 0; j < newExtras.length; j++) {
this.addElementPlacement(newExtras[j], placements);
}
extras.push.apply(extras, newExtras);
}
}
return { element: element, finishers: finishers, extras: extras };
},
// DecorateConstructor
decorateConstructor: function(
elements /*: ElementDescriptor[] */,
decorators /*: ClassDecorator[] */,
) /*: ElementsFinishers */ {
var finishers /*: ClassFinisher[] */ = [];
for (var i = decorators.length - 1; i >= 0; i--) {
var obj /*: ClassObject */ = this.fromClassDescriptor(elements);
var elementsAndFinisher /*: ElementsFinisher */ = this.toClassDescriptor(
(0, decorators[i])(obj) /*: ClassObject */ || obj,
);
if (elementsAndFinisher.finisher !== undefined) {
finishers.push(elementsAndFinisher.finisher);
}
if (elementsAndFinisher.elements !== undefined) {
elements = elementsAndFinisher.elements;
for (var j = 0; j < elements.length - 1; j++) {
for (var k = j + 1; k < elements.length; k++) {
if (
elements[j].key === elements[k].key &&
elements[j].placement === elements[k].placement
) {
throw new TypeError(
"Duplicated element (" + elements[j].key + ")",
);
}
}
}
}
}
return { elements: elements, finishers: finishers };
},
// FromElementDescriptor
fromElementDescriptor: function(
element /*: ElementDescriptor */,
) /*: ElementObject */ {
var obj /*: ElementObject */ = {
kind: element.kind,
key: element.key,
placement: element.placement,
descriptor: element.descriptor,
};
var desc = {
value: "Descriptor",
configurable: true,
};
Object.defineProperty(obj, Symbol.toStringTag, desc);
if (element.kind === "field") obj.initializer = element.initializer;
return obj;
},
// ToElementDescriptors
toElementDescriptors: function(
elementObjects /*: ElementObject[] */,
) /*: ElementDescriptor[] */ {
if (elementObjects === undefined) return;
return toArray(elementObjects).map(function(elementObject) {
var element = this.toElementDescriptor(elementObject);
this.disallowProperty(elementObject, "finisher", "An element descriptor");
this.disallowProperty(elementObject, "extras", "An element descriptor");
return element;
}, this);
},
// ToElementDescriptor
toElementDescriptor: function(
elementObject /*: ElementObject */,
) /*: ElementDescriptor */ {
var kind = String(elementObject.kind);
if (kind !== "method" && kind !== "field") {
throw new TypeError(
'An element descriptor\\'s .kind property must be either "method" or' +
' "field", but a decorator created an element descriptor with' +
' .kind "' +
kind +
'"',
);
}
var key = toPropertyKey(elementObject.key);
var placement = String(elementObject.placement);
if (
placement !== "static" &&
placement !== "prototype" &&
placement !== "own"
) {
throw new TypeError(
'An element descriptor\\'s .placement property must be one of "static",' +
' "prototype" or "own", but a decorator created an element descriptor' +
' with .placement "' +
placement +
'"',
);
}
var descriptor /*: PropertyDescriptor */ = elementObject.descriptor;
this.disallowProperty(elementObject, "elements", "An element descriptor");
var element /*: ElementDescriptor */ = {
kind: kind,
key: key,
placement: placement,
descriptor: Object.assign({}, descriptor),
};
if (kind !== "field") {
this.disallowProperty(elementObject, "initializer", "A method descriptor");
} else {
this.disallowProperty(
descriptor,
"get",
"The property descriptor of a field descriptor",
);
this.disallowProperty(
descriptor,
"set",
"The property descriptor of a field descriptor",
);
this.disallowProperty(
descriptor,
"value",
"The property descriptor of a field descriptor",
);
element.initializer = elementObject.initializer;
}
return element;
},
toElementFinisherExtras: function(
elementObject /*: ElementObject */,
) /*: ElementFinisherExtras */ {
var element /*: ElementDescriptor */ = this.toElementDescriptor(
elementObject,
);
var finisher /*: ClassFinisher */ = _optionalCallableProperty(
elementObject,
"finisher",
);
var extras /*: ElementDescriptors[] */ = this.toElementDescriptors(
elementObject.extras,
);
return { element: element, finisher: finisher, extras: extras };
},
// FromClassDescriptor
fromClassDescriptor: function(
elements /*: ElementDescriptor[] */,
) /*: ClassObject */ {
var obj = {
kind: "class",
elements: elements.map(this.fromElementDescriptor, this),
};
var desc = { value: "Descriptor", configurable: true };
Object.defineProperty(obj, Symbol.toStringTag, desc);
return obj;
},
// ToClassDescriptor
toClassDescriptor: function(
obj /*: ClassObject */,
) /*: ElementsFinisher */ {
var kind = String(obj.kind);
if (kind !== "class") {
throw new TypeError(
'A class descriptor\\'s .kind property must be "class", but a decorator' +
' created a class descriptor with .kind "' +
kind +
'"',
);
}
this.disallowProperty(obj, "key", "A class descriptor");
this.disallowProperty(obj, "placement", "A class descriptor");
this.disallowProperty(obj, "descriptor", "A class descriptor");
this.disallowProperty(obj, "initializer", "A class descriptor");
this.disallowProperty(obj, "extras", "A class descriptor");
var finisher = _optionalCallableProperty(obj, "finisher");
var elements = this.toElementDescriptors(obj.elements);
return { elements: elements, finisher: finisher };
},
// RunClassFinishers
runClassFinishers: function(
constructor /*: Class<*> */,
finishers /*: ClassFinisher[] */,
) /*: Class<*> */ {
for (var i = 0; i < finishers.length; i++) {
var newConstructor /*: ?Class<*> */ = (0, finishers[i])(constructor);
if (newConstructor !== undefined) {
// NOTE: This should check if IsConstructor(newConstructor) is false.
if (typeof newConstructor !== "function") {
throw new TypeError("Finishers must return a constructor.");
}
constructor = newConstructor;
}
}
return constructor;
},
disallowProperty: function(obj, name, objectType) {
if (obj[name] !== undefined) {
throw new TypeError(objectType + " can't have a ." + name + " property.");
}
}
};
return api;
}
// ClassElementEvaluation
@@ -1246,10 +1667,6 @@ helpers.decorate = helper("7.1.5")`
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") {
@@ -1264,8 +1681,8 @@ helpers.decorate = helper("7.1.5")`
placement: def.static
? "static"
: def.kind === "field"
? "own"
: "prototype",
? "own"
: "prototype",
descriptor: descriptor,
};
if (def.decorators) element.decorators = def.decorators;
@@ -1292,7 +1709,9 @@ helpers.decorate = helper("7.1.5")`
) /*: ElementDescriptor[] */ {
var newElements /*: ElementDescriptor[] */ = [];
var isSameElement = function(other /*: ElementDescriptor */) /*: boolean */ {
var isSameElement = function(
other /*: ElementDescriptor */,
) /*: boolean */ {
return (
other.kind === "method" &&
other.key === element.key &&
@@ -1351,365 +1770,6 @@ helpers.decorate = helper("7.1.5")`
);
}
// InitializeClassElements
function _initializeClassElements /*::<C>*/(
F /*: Class<C> */,
elements /*: ElementDescriptor[] */,
) {
var proto = F.prototype;
["method", "field"].forEach(function(kind) {
elements.forEach(function(element /*: ElementDescriptor */) {
var placement = element.placement;
if (
element.kind === kind &&
(placement === "static" || placement === "prototype")
) {
var receiver = placement === "static" ? F : proto;
_defineClassElement(receiver, element);
}
});
});
}
// InitializeInstanceElements
function _initializeInstanceElements /*::<C>*/(
O /*: C */,
elements /*: ElementDescriptor[] */,
) {
["method", "field"].forEach(function(kind) {
elements.forEach(function(element /*: ElementDescriptor */) {
if (element.kind === kind && element.placement === "own") {
_defineClassElement(O, element);
}
});
});
}
// DefineClassElement
function _defineClassElement /*::<C>*/(
receiver /*: C | Class<C> */,
element /*: ElementDescriptor */,
) {
var descriptor /*: PropertyDescriptor */ = element.descriptor;
if (element.kind === "field") {
var initializer = element.initializer;
descriptor = {
enumerable: descriptor.enumerable,
writable: descriptor.writable,
configurable: descriptor.configurable,
value: initializer === void 0 ? void 0 : initializer.call(receiver),
};
}
Object.defineProperty(receiver, element.key, descriptor);
}
/*::
type Placements = {
static: Key[],
prototype: Key[],
own: Key[],
};
*/
// DecorateClass
function _decorateClass(
elements /*: ElementDescriptor[] */,
decorators /*: ClassDecorator[] */,
) /*: ElementsFinishers */ {
var newElements /*: ElementDescriptor[] */ = [];
var finishers /*: ClassFinisher[] */ = [];
var placements /*: Placements */ = { static: [], prototype: [], own: [] };
elements.forEach(function(element /*: ElementDescriptor */) {
_addElementPlacement(element, placements);
});
elements.forEach(function(element /*: ElementDescriptor */) {
if (!_hasDecorators(element)) return newElements.push(element);
var elementFinishersExtras /*: ElementFinishersExtras */ = _decorateElement(
element,
placements,
);
newElements.push(elementFinishersExtras.element);
newElements.push.apply(newElements, elementFinishersExtras.extras);
finishers.push.apply(finishers, elementFinishersExtras.finishers);
});
if (!decorators) {
return { elements: newElements, finishers: finishers };
}
var result /*: ElementsFinishers */ = _decorateConstructor(
newElements,
decorators,
);
finishers.push.apply(finishers, result.finishers);
result.finishers = finishers;
return result;
}
// AddElementPlacement
function _addElementPlacement(
element /*: ElementDescriptor */,
placements /*: Placements */,
silent /*: boolean */,
) {
var keys = placements[element.placement];
if (!silent && keys.indexOf(element.key) !== -1) {
throw new TypeError("Duplicated element (" + element.key + ")");
}
keys.push(element.key);
}
// DecorateElement
function _decorateElement(
element /*: ElementDescriptor */,
placements /*: Placements */,
) /*: ElementFinishersExtras */ {
var extras /*: ElementDescriptor[] */ = [];
var finishers /*: ClassFinisher[] */ = [];
for (
var decorators = element.decorators, i = decorators.length - 1;
i >= 0;
i--
) {
// (inlined) RemoveElementPlacement
var keys = placements[element.placement];
keys.splice(keys.indexOf(element.key), 1);
var elementObject /*: ElementObjectInput */ = _fromElementDescriptor(
element,
);
var elementFinisherExtras /*: ElementFinisherExtras */ = _toElementFinisherExtras(
(0, decorators[i])(elementObject) /*: ElementObjectOutput */ ||
elementObject,
);
element = elementFinisherExtras.element;
_addElementPlacement(element, placements);
if (elementFinisherExtras.finisher) {
finishers.push(elementFinisherExtras.finisher);
}
var newExtras /*: ElementDescriptor[] | void */ =
elementFinisherExtras.extras;
if (newExtras) {
for (var j = 0; j < newExtras.length; j++) {
_addElementPlacement(newExtras[j], placements);
}
extras.push.apply(extras, newExtras);
}
}
return { element: element, finishers: finishers, extras: extras };
}
// DecorateConstructor
function _decorateConstructor(
elements /*: ElementDescriptor[] */,
decorators /*: ClassDecorator[] */,
) /*: ElementsFinishers */ {
var finishers /*: ClassFinisher[] */ = [];
for (var i = decorators.length - 1; i >= 0; i--) {
var obj /*: ClassObject */ = _fromClassDescriptor(elements);
var elementsAndFinisher /*: ElementsFinisher */ = _toClassDescriptor(
(0, decorators[i])(obj) /*: ClassObject */ || obj,
);
if (elementsAndFinisher.finisher !== undefined) {
finishers.push(elementsAndFinisher.finisher);
}
if (elementsAndFinisher.elements !== undefined) {
elements = elementsAndFinisher.elements;
for (var j = 0; j < elements.length - 1; j++) {
for (var k = j + 1; k < elements.length; k++) {
if (
elements[j].key === elements[k].key &&
elements[j].placement === elements[k].placement
) {
throw new TypeError("Duplicated element (" + elements[j].key + ")");
}
}
}
}
}
return { elements: elements, finishers: finishers };
}
// FromElementDescriptor
function _fromElementDescriptor(
element /*: ElementDescriptor */,
) /*: ElementObject */ {
var obj /*: ElementObject */ = {
kind: element.kind,
key: element.key,
placement: element.placement,
descriptor: element.descriptor,
};
var desc = {
value: "Descriptor",
configurable: true,
};
Object.defineProperty(obj, Symbol.toStringTag, desc);
if (element.kind === "field") obj.initializer = element.initializer;
return obj;
}
// ToElementDescriptors
function _toElementDescriptors(
elementObjects /*: ElementObject[] */,
) /*: ElementDescriptor[] */ {
if (elementObjects === undefined) return;
return toArray(elementObjects).map(function(elementObject) {
var element = _toElementDescriptor(elementObject);
_disallowProperty(elementObject, "finisher", "An element descriptor");
_disallowProperty(elementObject, "extras", "An element descriptor");
return element;
});
}
// ToElementDescriptor
function _toElementDescriptor(
elementObject /*: ElementObject */,
) /*: ElementDescriptor */ {
var kind = String(elementObject.kind);
if (kind !== "method" && kind !== "field") {
throw new TypeError(
'An element descriptor\\'s .kind property must be either "method" or' +
' "field", but a decorator created an element descriptor with' +
' .kind "' +
kind +
'"',
);
}
var key = toPropertyKey(elementObject.key);
var placement = String(elementObject.placement);
if (
placement !== "static" &&
placement !== "prototype" &&
placement !== "own"
) {
throw new TypeError(
'An element descriptor\\'s .placement property must be one of "static",' +
' "prototype" or "own", but a decorator created an element descriptor' +
' with .placement "' +
placement +
'"',
);
}
var descriptor /*: PropertyDescriptor */ = elementObject.descriptor;
_disallowProperty(elementObject, "elements", "An element descriptor");
var element /*: ElementDescriptor */ = {
kind: kind,
key: key,
placement: placement,
descriptor: Object.assign({}, descriptor),
};
if (kind !== "field") {
_disallowProperty(elementObject, "initializer", "A method descriptor");
} else {
_disallowProperty(
descriptor,
"get",
"The property descriptor of a field descriptor",
);
_disallowProperty(
descriptor,
"set",
"The property descriptor of a field descriptor",
);
_disallowProperty(
descriptor,
"value",
"The property descriptor of a field descriptor",
);
element.initializer = elementObject.initializer;
}
return element;
}
function _toElementFinisherExtras(
elementObject /*: ElementObject */,
) /*: ElementFinisherExtras */ {
var element /*: ElementDescriptor */ = _toElementDescriptor(elementObject);
var finisher /*: ClassFinisher */ = _optionalCallableProperty(
elementObject,
"finisher",
);
var extras /*: ElementDescriptors[] */ = _toElementDescriptors(
elementObject.extras,
);
return { element: element, finisher: finisher, extras: extras };
}
// FromClassDescriptor
function _fromClassDescriptor(
elements /*: ElementDescriptor[] */,
) /*: ClassObject */ {
var obj = {
kind: "class",
elements: elements.map(_fromElementDescriptor),
};
var desc = { value: "Descriptor", configurable: true };
Object.defineProperty(obj, Symbol.toStringTag, desc);
return obj;
}
// ToClassDescriptor
function _toClassDescriptor(obj /*: ClassObject */) /*: ElementsFinisher */ {
var kind = String(obj.kind);
if (kind !== "class") {
throw new TypeError(
'A class descriptor\\'s .kind property must be "class", but a decorator' +
' created a class descriptor with .kind "' +
kind +
'"',
);
}
_disallowProperty(obj, "key", "A class descriptor");
_disallowProperty(obj, "placement", "A class descriptor");
_disallowProperty(obj, "descriptor", "A class descriptor");
_disallowProperty(obj, "initializer", "A class descriptor");
_disallowProperty(obj, "extras", "A class descriptor");
var finisher = _optionalCallableProperty(obj, "finisher");
var elements = _toElementDescriptors(obj.elements);
return { elements: elements, finisher: finisher };
}
function _disallowProperty(obj, name, objectType) {
if (obj[name] !== undefined) {
throw new TypeError(objectType + " can't have a ." + name + " property.");
}
}
function _optionalCallableProperty /*::<T>*/(
obj /*: T */,
name /*: $Keys<T> */,
@@ -1721,23 +1781,6 @@ helpers.decorate = helper("7.1.5")`
return value;
}
// RunClassFinishers
function _runClassFinishers(
constructor /*: Class<*> */,
finishers /*: ClassFinisher[] */,
) /*: Class<*> */ {
for (var i = 0; i < finishers.length; i++) {
var newConstructor /*: ?Class<*> */ = (0, finishers[i])(constructor);
if (newConstructor !== undefined) {
// NOTE: This should check if IsConstructor(newConstructor) is false.
if (typeof newConstructor !== "function") {
throw new TypeError("Finishers must return a constructor.");
}
constructor = newConstructor;
}
}
return constructor;
}
`;
helpers.classPrivateMethodGet = helper("7.1.6")`
@@ -1754,3 +1797,75 @@ helpers.classPrivateMethodSet = helper("7.1.6")`
throw new TypeError("attempted to reassign private method");
}
`;
helpers.wrapRegExp = helper("7.2.6")`
import wrapNativeSuper from "wrapNativeSuper";
import getPrototypeOf from "getPrototypeOf";
import possibleConstructorReturn from "possibleConstructorReturn";
import inherits from "inherits";
export default function _wrapRegExp(re, groups) {
_wrapRegExp = function(re, groups) {
return new BabelRegExp(re, groups);
};
var _RegExp = wrapNativeSuper(RegExp);
var _super = RegExp.prototype;
var _groups = new WeakMap();
function BabelRegExp(re, groups) {
var _this = _RegExp.call(this, re);
_groups.set(_this, groups);
return _this;
}
inherits(BabelRegExp, _RegExp);
BabelRegExp.prototype.exec = function(str) {
var result = _super.exec.call(this, str);
if (result) result.groups = buildGroups(result, this);
return result;
};
BabelRegExp.prototype[Symbol.replace] = function(str, substitution) {
if (typeof substitution === "string") {
var groups = _groups.get(this);
return _super[Symbol.replace].call(
this,
str,
substitution.replace(/\\$<([^>]+)>/g, function(_, name) {
return "$" + groups[name];
})
);
} else if (typeof substitution === "function") {
var _this = this;
return _super[Symbol.replace].call(
this,
str,
function() {
var args = [];
args.push.apply(args, arguments);
if (typeof args[args.length - 1] !== "object") {
// Modern engines already pass result.groups as the last arg.
args.push(buildGroups(args, _this));
}
return substitution.apply(this, args);
}
);
} else {
return _super[Symbol.replace].call(this, str, substitution);
}
}
function buildGroups(result, re) {
// NOTE: This function should return undefined if there are no groups,
// but in that case Babel doesn't add the wrapper anyway.
var g = _groups.get(re);
return Object.keys(groups).reduce(function(groups, name) {
groups[name] = result[g[name]];
return groups;
}, Object.create(null));
}
return _wrapRegExp.apply(this, arguments);
}
`;

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/node",
"version": "7.2.0",
"version": "7.2.2",
"description": "Babel command line",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -29,7 +29,7 @@
"@babel/core": "^7.0.0-0"
},
"devDependencies": {
"@babel/core": "^7.2.0",
"@babel/core": "^7.2.2",
"@babel/helper-fixtures": "^7.2.0",
"fs-readdir-recursive": "^1.0.0",
"output-file-sync": "^2.0.0"

View File

@@ -52,7 +52,7 @@ 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'.",
);
commander.option(
program.option(
"--root-mode [mode]",
"The project-root resolution mode. " +
"One of 'root' (the default), 'upward', or 'upward-optional'.",

View File

@@ -1,6 +1,6 @@
{
"name": "@babel/parser",
"version": "7.2.0",
"version": "7.3.0",
"description": "A JavaScript parser",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
@@ -30,7 +30,7 @@
"devDependencies": {
"@babel/helper-fixtures": "^7.2.0",
"charcodes": "0.1.0",
"unicode-11.0.0": "^0.7.7"
"unicode-11.0.0": "^0.7.8"
},
"bin": {
"parser": "./bin/babel-parser.js"

View File

@@ -60,11 +60,15 @@ function generate(chars) {
const startData = generate(start);
const contData = generate(cont);
console.log("/* prettier-ignore */");
console.log('let nonASCIIidentifierStartChars = "' + startData.nonASCII + '";');
console.log("/* prettier-ignore */");
console.log('let nonASCIIidentifierChars = "' + contData.nonASCII + '";');
console.log("/* prettier-ignore */");
console.log(
"const astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"
);
console.log("/* prettier-ignore */");
console.log(
"const astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"
);

View File

@@ -1,7 +1,7 @@
// @flow
import type { Options } from "../options";
import { reservedWords } from "../util/identifier";
import { isES2015ReservedWord } from "../util/identifier";
import type State from "../tokenizer/state";
import type { PluginsMap } from "./index";
@@ -16,21 +16,21 @@ export default class BaseParser {
// Initialized by Tokenizer
state: State;
input: string;
isReservedWord(word: string): boolean {
if (word === "await") {
return this.inModule;
} else {
return reservedWords[6](word);
return isES2015ReservedWord(word);
}
}
hasPlugin(name: string): boolean {
return Object.hasOwnProperty.call(this.plugins, name);
return this.plugins.has(name);
}
getPluginOption(plugin: string, name: string) {
if (this.hasPlugin(plugin)) return this.plugins[plugin][name];
// $FlowIssue
if (this.hasPlugin(plugin)) return this.plugins.get(plugin)[name];
}
}

View File

@@ -21,7 +21,11 @@
import { types as tt, type TokenType } from "../tokenizer/types";
import * as N from "../types";
import LValParser from "./lval";
import { reservedWords } from "../util/identifier";
import {
isStrictReservedWord,
isStrictBindReservedWord,
isKeyword,
} from "../util/identifier";
import type { Pos, Position } from "../util/location";
import * as charCodes from "charcodes";
@@ -130,6 +134,9 @@ export default class ExpressionParser extends LValParser {
return left;
}
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
this.state.commaAfterSpreadAt = -1;
let failOnShorthandAssign;
if (refShorthandDefaultPos) {
failOnShorthandAssign = false;
@@ -169,21 +176,26 @@ export default class ExpressionParser extends LValParser {
this.checkLVal(left, undefined, undefined, "assignment expression");
if (left.extra && left.extra.parenthesized) {
let errorMsg;
if (left.type === "ObjectPattern") {
errorMsg = "`({a}) = 0` use `({a} = 0)`";
} else if (left.type === "ArrayPattern") {
errorMsg = "`([a]) = 0` use `([a] = 0)`";
}
if (errorMsg) {
this.raise(
left.start,
`You're trying to assign to a parenthesized expression, eg. instead of ${errorMsg}`,
);
}
let patternErrorMsg;
let elementName;
if (left.type === "ObjectPattern") {
patternErrorMsg = "`({a}) = 0` use `({a} = 0)`";
elementName = "property";
} else if (left.type === "ArrayPattern") {
patternErrorMsg = "`([a]) = 0` use `([a] = 0)`";
elementName = "element";
}
if (patternErrorMsg && left.extra && left.extra.parenthesized) {
this.raise(
left.start,
`You're trying to assign to a parenthesized expression, eg. instead of ${patternErrorMsg}`,
);
}
if (elementName) this.checkCommaAfterRestFromSpread(elementName);
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
this.next();
node.right = this.parseMaybeAssign(noIn);
return this.finishNode(node, "AssignmentExpression");
@@ -191,6 +203,8 @@ export default class ExpressionParser extends LValParser {
this.unexpected(refShorthandDefaultPos.start);
}
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
return left;
}
@@ -515,7 +529,7 @@ export default class ExpressionParser extends LValParser {
} else if (this.match(tt.questionDot)) {
this.expectPlugin("optionalChaining");
state.optionalChainMember = true;
if (noCalls && this.lookahead().type == tt.parenL) {
if (noCalls && this.lookahead().type === tt.parenL) {
state.stop = true;
return base;
}
@@ -580,15 +594,13 @@ export default class ExpressionParser extends LValParser {
let node = this.startNodeAt(startPos, startLoc);
node.callee = base;
// TODO: Clean up/merge this into `this.state` or a class like acorn's
// `DestructuringErrors` alongside refShorthandDefaultPos and
// refNeedsArrowPos.
const refTrailingCommaPos: Pos = { start: -1 };
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
this.state.commaAfterSpreadAt = -1;
node.arguments = this.parseCallExpressionArguments(
tt.parenR,
possibleAsync,
refTrailingCommaPos,
base.type === "Import",
);
if (!state.optionalChainMember) {
this.finishCallExpression(node);
@@ -599,12 +611,7 @@ export default class ExpressionParser extends LValParser {
if (possibleAsync && this.shouldParseAsyncArrow()) {
state.stop = true;
if (refTrailingCommaPos.start > -1) {
this.raise(
refTrailingCommaPos.start,
"A trailing comma is not permitted after the rest element",
);
}
this.checkCommaAfterRestFromSpread("parameter");
node = this.parseAsyncArrowFromCallExpression(
this.startNodeAt(startPos, startLoc),
@@ -621,6 +628,7 @@ export default class ExpressionParser extends LValParser {
}
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
return node;
} else if (this.match(tt.backQuote)) {
@@ -700,7 +708,7 @@ export default class ExpressionParser extends LValParser {
parseCallExpressionArguments(
close: TokenType,
possibleAsyncArrow: boolean,
refTrailingCommaPos?: Pos,
dynamicImport?: boolean,
): $ReadOnlyArray<?N.Expression> {
const elts = [];
let innerParenStart;
@@ -711,7 +719,15 @@ export default class ExpressionParser extends LValParser {
first = false;
} else {
this.expect(tt.comma);
if (this.eat(close)) break;
if (this.eat(close)) {
if (dynamicImport) {
this.raise(
this.state.lastTokStart,
"Trailing comma is disallowed inside import(...) arguments",
);
}
break;
}
}
// we need to make sure that if this is an async arrow functions,
@@ -725,7 +741,6 @@ export default class ExpressionParser extends LValParser {
false,
possibleAsyncArrow ? { start: 0 } : undefined,
possibleAsyncArrow ? { start: 0 } : undefined,
possibleAsyncArrow ? refTrailingCommaPos : undefined,
),
);
}
@@ -858,9 +873,9 @@ export default class ExpressionParser extends LValParser {
return this.parseFunction(node, false, false, true);
} else if (
canBeArrow &&
!this.canInsertSemicolon() &&
id.name === "async" &&
this.match(tt.name)
this.match(tt.name) &&
!this.canInsertSemicolon()
) {
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
const oldInAsync = this.state.inAsync;
@@ -875,7 +890,8 @@ export default class ExpressionParser extends LValParser {
return node;
}
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
if (canBeArrow && this.match(tt.arrow) && !this.canInsertSemicolon()) {
this.next();
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
this.state.yieldOrAwaitInPossibleArrowParameters = null;
this.parseArrowExpression(node, [id]);
@@ -1135,7 +1151,11 @@ export default class ExpressionParser extends LValParser {
const node = this.startNodeAt(startPos, startLoc);
this.addExtra(node, "rawValue", value);
this.addExtra(node, "raw", this.input.slice(startPos, this.state.end));
this.addExtra(
node,
"raw",
this.state.input.slice(startPos, this.state.end),
);
node.value = value;
this.next();
return this.finishNode(node, type);
@@ -1192,14 +1212,7 @@ export default class ExpressionParser extends LValParser {
),
);
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);
}
this.checkCommaAfterRest(tt.parenR, "parameter");
break;
} else {
@@ -1312,7 +1325,10 @@ export default class ExpressionParser extends LValParser {
}
node.callee = this.parseNoCallExpr();
if (
if (node.callee.type === "Import") {
this.raise(node.callee.start, "Cannot use new with import(...)");
} else if (
node.callee.type === "OptionalMemberExpression" ||
node.callee.type === "OptionalCallExpression"
) {
@@ -1320,13 +1336,13 @@ export default class ExpressionParser extends LValParser {
this.state.lastTokEnd,
"constructors in/after an Optional Chain are not allowed",
);
}
if (this.eat(tt.questionDot)) {
} else if (this.eat(tt.questionDot)) {
this.raise(
this.state.start,
"constructors in/after an Optional Chain are not allowed",
);
}
this.parseNewArguments(node);
return this.finishNode(node, "NewExpression");
}
@@ -1358,7 +1374,7 @@ export default class ExpressionParser extends LValParser {
}
}
elem.value = {
raw: this.input
raw: this.state.input
.slice(this.state.start, this.state.end)
.replace(/\r\n?/g, "\n"),
cooked: this.state.value,
@@ -1398,8 +1414,6 @@ export default class ExpressionParser extends LValParser {
node.properties = [];
this.next();
let firstRestLocation = null;
while (!this.eat(tt.braceR)) {
if (first) {
first = false;
@@ -1435,34 +1449,14 @@ export default class ExpressionParser extends LValParser {
if (this.match(tt.ellipsis)) {
prop = this.parseSpread(isPattern ? { start: 0 } : undefined);
if (isPattern) {
this.toAssignable(prop, true, "object pattern");
}
node.properties.push(prop);
if (isPattern) {
const position = this.state.start;
if (firstRestLocation !== null) {
this.unexpected(
firstRestLocation,
"Cannot have multiple rest elements when destructuring",
);
} else if (this.eat(tt.braceR)) {
break;
} else if (
this.match(tt.comma) &&
this.lookahead().type === tt.braceR
) {
this.unexpected(
position,
"A trailing comma is not permitted after the rest element",
);
} else {
firstRestLocation = position;
continue;
}
} else {
continue;
this.toAssignable(prop, true, "object pattern");
this.checkCommaAfterRest(tt.braceR, "property");
this.expect(tt.braceR);
break;
}
continue;
}
prop.method = false;
@@ -1519,13 +1513,6 @@ export default class ExpressionParser extends LValParser {
node.properties.push(prop);
}
if (firstRestLocation !== null) {
this.unexpected(
firstRestLocation,
"The rest element has to be the last element when destructuring",
);
}
if (decorators.length) {
this.raise(
this.state.start,
@@ -1759,7 +1746,7 @@ 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"
@@ -1923,7 +1910,6 @@ export default class ExpressionParser extends LValParser {
allowEmpty: ?boolean,
refShorthandDefaultPos: ?Pos,
refNeedsArrowPos: ?Pos,
refTrailingCommaPos?: Pos,
): ?N.Expression {
let elt;
if (allowEmpty && this.match(tt.comma)) {
@@ -1936,10 +1922,6 @@ export default class ExpressionParser extends LValParser {
spreadNodeStartPos,
spreadNodeStartLoc,
);
if (refTrailingCommaPos && this.match(tt.comma)) {
refTrailingCommaPos.start = this.state.start;
}
} else {
elt = this.parseMaybeAssign(
false,
@@ -1994,7 +1976,8 @@ export default class ExpressionParser extends LValParser {
if (
(name === "class" || name === "function") &&
(this.state.lastTokEnd !== this.state.lastTokStart + 1 ||
this.input.charCodeAt(this.state.lastTokStart) !== charCodes.dot)
this.state.input.charCodeAt(this.state.lastTokStart) !==
charCodes.dot)
) {
this.state.context.pop();
}
@@ -2018,8 +2001,8 @@ export default class ExpressionParser extends LValParser {
): void {
if (
this.state.strict &&
(reservedWords.strict(word) ||
(isBinding && reservedWords.strictBind(word)))
(isStrictReservedWord(word) ||
(isBinding && isStrictBindReservedWord(word)))
) {
this.raise(startLoc, word + " is a reserved word in strict mode");
}
@@ -2038,7 +2021,7 @@ export default class ExpressionParser extends LValParser {
);
}
if (this.isReservedWord(word) || (checkKeywords && this.isKeyword(word))) {
if (this.isReservedWord(word) || (checkKeywords && isKeyword(word))) {
this.raise(startLoc, word + " is a reserved word");
}
}
@@ -2098,8 +2081,8 @@ export default class ExpressionParser extends LValParser {
this.next();
if (
this.match(tt.semi) ||
this.canInsertSemicolon() ||
(!this.match(tt.star) && !this.state.type.startsExpr)
(!this.match(tt.star) && !this.state.type.startsExpr) ||
this.canInsertSemicolon()
) {
node.delegate = false;
node.argument = null;

View File

@@ -6,9 +6,7 @@ import type { PluginList } from "../plugin-utils";
import { getOptions } from "../options";
import StatementParser from "./statement";
export type PluginsMap = {
[key: string]: { [option: string]: any },
};
export type PluginsMap = Map<string, { [string]: any }>;
export default class Parser extends StatementParser {
// Forward-declaration so typescript plugin can override jsx plugin
@@ -22,7 +20,6 @@ export default class Parser extends StatementParser {
this.options = options;
this.inModule = this.options.sourceType === "module";
this.input = input;
this.plugins = pluginsMap(this.options.plugins);
this.filename = options.sourceFilename;
}
@@ -36,10 +33,10 @@ export default class Parser extends StatementParser {
}
function pluginsMap(plugins: PluginList): PluginsMap {
const pluginMap: PluginsMap = (Object.create(null): Object);
const pluginMap: PluginsMap = new Map();
for (const plugin of plugins) {
const [name, options = {}] = Array.isArray(plugin) ? plugin : [plugin, {}];
if (!pluginMap[name]) pluginMap[name] = options || {};
const [name, options] = Array.isArray(plugin) ? plugin : [plugin, {}];
if (!pluginMap.has(name)) pluginMap.set(name, options || {});
}
return pluginMap;
}

View File

@@ -21,7 +21,7 @@ export default class LocationParser extends CommentsParser {
code?: string,
} = {},
): empty {
const loc = getLineInfo(this.input, pos);
const loc = getLineInfo(this.state.input, pos);
message += ` (${loc.line}:${loc.column})`;
// $FlowIgnore
const err: SyntaxError & { pos: number, loc: Position } = new SyntaxError(

View File

@@ -56,9 +56,13 @@ export default class LValParser extends NodeUtils {
case "ObjectExpression":
node.type = "ObjectPattern";
for (let index = 0; index < node.properties.length; index++) {
const prop = node.properties[index];
const isLast = index === node.properties.length - 1;
for (
let i = 0, length = node.properties.length, last = length - 1;
i < length;
i++
) {
const prop = node.properties[i];
const isLast = i === last;
this.toAssignableObjectExpressionProp(prop, isBinding, isLast);
}
break;
@@ -122,10 +126,7 @@ export default class LValParser extends NodeUtils {
this.raise(prop.key.start, error);
} else if (prop.type === "SpreadElement" && !isLast) {
this.raise(
prop.start,
"The rest element has to be the last element when destructuring",
);
this.raiseRestNotLast(prop.start, "property");
} else {
this.toAssignable(prop, isBinding, "object destructuring pattern");
}
@@ -148,12 +149,10 @@ export default class LValParser extends NodeUtils {
const arg = last.argument;
this.toAssignable(arg, isBinding, contextDescription);
if (
[
"Identifier",
"MemberExpression",
"ArrayPattern",
"ObjectPattern",
].indexOf(arg.type) === -1
arg.type !== "Identifier" &&
arg.type !== "MemberExpression" &&
arg.type !== "ArrayPattern" &&
arg.type !== "ObjectPattern"
) {
this.unexpected(arg.start);
}
@@ -162,13 +161,12 @@ export default class LValParser extends NodeUtils {
}
for (let i = 0; i < end; i++) {
const elt = exprList[i];
if (elt && elt.type === "SpreadElement") {
this.raise(
elt.start,
"The rest element has to be the last element when destructuring",
);
if (elt) {
this.toAssignable(elt, isBinding, contextDescription);
if (elt.type === "RestElement") {
this.raiseRestNotLast(elt.start, "element");
}
}
if (elt) this.toAssignable(elt, isBinding, contextDescription);
}
return exprList;
}
@@ -199,10 +197,10 @@ export default class LValParser extends NodeUtils {
// Parses spread element.
parseSpread<T: RestElement | SpreadElement>(
parseSpread(
refShorthandDefaultPos: ?Pos,
refNeedsArrowPos?: ?Pos,
): T {
): SpreadElement {
const node = this.startNode();
this.next();
node.argument = this.parseMaybeAssign(
@@ -211,6 +209,11 @@ export default class LValParser extends NodeUtils {
undefined,
refNeedsArrowPos,
);
if (this.state.commaAfterSpreadAt === -1 && this.match(tt.comma)) {
this.state.commaAfterSpreadAt = this.state.start;
}
return this.finishNode(node, "SpreadElement");
}
@@ -273,20 +276,13 @@ export default class LValParser extends NodeUtils {
break;
} else if (this.match(tt.ellipsis)) {
elts.push(this.parseAssignableListItemTypes(this.parseRest()));
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);
}
this.checkCommaAfterRest(
close,
this.state.inFunction && this.state.inParameters
? "parameter"
: "element",
);
this.expect(close);
break;
} else {
const decorators = [];
@@ -432,12 +428,35 @@ export default class LValParser extends NodeUtils {
}
checkToRestConversion(node: SpreadElement): void {
const validArgumentTypes = ["Identifier", "MemberExpression"];
if (validArgumentTypes.indexOf(node.argument.type) !== -1) {
return;
if (
node.argument.type !== "Identifier" &&
node.argument.type !== "MemberExpression"
) {
this.raise(node.argument.start, "Invalid rest operator's argument");
}
}
this.raise(node.argument.start, "Invalid rest operator's argument");
checkCommaAfterRest(close: TokenType, kind: string): void {
if (this.match(tt.comma)) {
if (this.lookahead().type === close) {
this.raiseCommaAfterRest(this.state.start, kind);
} else {
this.raiseRestNotLast(this.state.start, kind);
}
}
}
checkCommaAfterRestFromSpread(kind: string): void {
if (this.state.commaAfterSpreadAt > -1) {
this.raiseCommaAfterRest(this.state.commaAfterSpreadAt, kind);
}
}
raiseCommaAfterRest(pos: number, kind: string) {
this.raise(pos, `A trailing comma is not permitted after the rest ${kind}`);
}
raiseRestNotLast(pos: number, kind: string) {
this.raise(pos, `The rest ${kind} must be the last ${kind}`);
}
}

View File

@@ -7,8 +7,6 @@ import type { Comment, Node as NodeType, NodeBase } from "../types";
// Start an AST node, attaching a start offset.
const commentKeys = ["leadingComments", "trailingComments", "innerComments"];
class Node implements NodeBase {
constructor(parser: Parser, pos: number, loc: Position) {
this.type = "";
@@ -31,16 +29,22 @@ class Node implements NodeBase {
__clone(): this {
// $FlowIgnore
const node2: any = new Node();
Object.keys(this).forEach(key => {
const newNode: any = new Node();
const keys = Object.keys(this);
for (let i = 0, length = keys.length; i < length; i++) {
const key = keys[i];
// Do not clone comments that are already attached to the node
if (commentKeys.indexOf(key) < 0) {
if (
key !== "leadingComments" &&
key !== "trailingComments" &&
key !== "innerComments"
) {
// $FlowIgnore
node2[key] = this[key];
newNode[key] = this[key];
}
});
}
return node2;
return newNode;
}
}

View File

@@ -44,7 +44,7 @@ export default class StatementParser extends ExpressionParser {
const directiveLiteral = this.startNodeAt(expr.start, expr.loc.start);
const directive = this.startNodeAt(stmt.start, stmt.loc.start);
const raw = this.input.slice(expr.start, expr.end);
const raw = this.state.input.slice(expr.start, expr.end);
const val = (directiveLiteral.value = raw.slice(1, -1)); // remove quotes
this.addExtra(directiveLiteral, "raw", raw);
@@ -106,7 +106,12 @@ export default class StatementParser extends ExpressionParser {
return this.parseForStatement(node);
case tt._function:
if (this.lookahead().type === tt.dot) break;
if (!declaration) this.unexpected();
if (!declaration) {
this.raise(
this.state.start,
"Function declaration not allowed in this context",
);
}
return this.parseFunctionStatement(node);
case tt._class:
@@ -156,7 +161,7 @@ export default class StatementParser extends ExpressionParser {
this.next();
let result;
if (starttype == tt._import) {
if (starttype === tt._import) {
result = this.parseImport(node);
if (
@@ -189,7 +194,13 @@ export default class StatementParser extends ExpressionParser {
const state = this.state.clone();
this.next();
if (this.match(tt._function) && !this.canInsertSemicolon()) {
this.expect(tt._function);
if (!declaration) {
this.raise(
this.state.lastTokStart,
"Function declaration not allowed in this context",
);
}
this.next();
return this.parseFunction(node, true, false, true);
} else {
this.state = state;
@@ -210,7 +221,7 @@ export default class StatementParser extends ExpressionParser {
expr.type === "Identifier" &&
this.eat(tt.colon)
) {
return this.parseLabeledStatement(node, maybeName, expr);
return this.parseLabeledStatement(node, maybeName, expr, declaration);
} else {
return this.parseExpressionStatement(node, expr);
}
@@ -540,7 +551,9 @@ export default class StatementParser extends ExpressionParser {
parseThrowStatement(node: N.ThrowStatement): N.ThrowStatement {
this.next();
if (
lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start))
lineBreak.test(
this.state.input.slice(this.state.lastTokEnd, this.state.start),
)
) {
this.raise(this.state.lastTokEnd, "Illegal newline after throw");
}
@@ -649,6 +662,7 @@ export default class StatementParser extends ExpressionParser {
node: N.LabeledStatement,
maybeName: string,
expr: N.Identifier,
declaration: boolean,
): N.LabeledStatement {
for (const label of this.state.labels) {
if (label.name === maybeName) {
@@ -676,12 +690,12 @@ export default class StatementParser extends ExpressionParser {
kind: kind,
statementStart: this.state.start,
});
node.body = this.parseStatement(true);
node.body = this.parseStatement(declaration);
if (
node.body.type == "ClassDeclaration" ||
(node.body.type == "VariableDeclaration" && node.body.kind !== "var") ||
(node.body.type == "FunctionDeclaration" &&
node.body.type === "ClassDeclaration" ||
(node.body.type === "VariableDeclaration" && node.body.kind !== "var") ||
(node.body.type === "FunctionDeclaration" &&
(this.state.strict || node.body.generator || node.body.async))
) {
this.raise(node.body.start, "Invalid labeled declaration");
@@ -851,6 +865,7 @@ export default class StatementParser extends ExpressionParser {
kind: TokenType,
): N.VariableDeclaration {
const declarations = (node.declarations = []);
const isTypescript = this.hasPlugin("typescript");
// $FlowFixMe
node.kind = kind.keyword;
for (;;) {
@@ -865,7 +880,7 @@ export default class StatementParser extends ExpressionParser {
) {
// `const` with no initializer is allowed in TypeScript.
// It could be a declaration like `const x: number;`.
if (!this.hasPlugin("typescript")) {
if (!isTypescript) {
this.unexpected();
}
} else if (
@@ -896,9 +911,9 @@ 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;
@@ -994,8 +1009,16 @@ export default class StatementParser extends ExpressionParser {
this.next();
this.takeDecorators(node);
this.parseClassId(node, isStatement, optionalId);
// class bodies and heritages are implicitly strict
const oldStrict = this.state.strict;
this.state.strict = true;
this.parseClassSuper(node);
this.parseClassBody(node);
this.state.strict = oldStrict;
return this.finishNode(
node,
isStatement ? "ClassDeclaration" : "ClassExpression",
@@ -1020,9 +1043,6 @@ export default class StatementParser extends ExpressionParser {
}
parseClassBody(node: N.Class): void {
// class bodies are implicitly strict
const oldStrict = this.state.strict;
this.state.strict = true;
this.state.classLevel++;
const state = { hadConstructor: false };
@@ -1087,7 +1107,6 @@ export default class StatementParser extends ExpressionParser {
node.body = this.finishNode(classBody, "ClassBody");
this.state.classLevel--;
this.state.strict = oldStrict;
}
parseClassMember(
@@ -1262,7 +1281,7 @@ export default class StatementParser extends ExpressionParser {
} else if (
isSimple &&
(key.name === "get" || key.name === "set") &&
!(this.isLineTerminator() && this.match(tt.star))
!(this.match(tt.star) && this.isLineTerminator())
) {
// `get\n*` is an uninitialized property named 'get' followed by a generator.
// a getter or setter
@@ -1505,7 +1524,7 @@ export default class StatementParser extends ExpressionParser {
isAsyncFunction() {
if (!this.isContextual("async")) return false;
const { input, pos } = this.state;
const { input, pos, length } = this.state;
skipWhiteSpace.lastIndex = pos;
const skip = skipWhiteSpace.exec(input);
@@ -1517,7 +1536,7 @@ export default class StatementParser extends ExpressionParser {
return (
!lineBreak.test(input.slice(pos, next)) &&
input.slice(next, next + 8) === "function" &&
(next + 8 === input.length || !isIdentifierChar(input.charAt(next + 8)))
(next + 8 === length || !isIdentifierChar(input.charCodeAt(next + 8)))
);
}

View File

@@ -25,7 +25,7 @@ export default class UtilParser extends Tokenizer {
isLookaheadRelational(op: "<" | ">"): boolean {
const l = this.lookahead();
return l.type == tt.relational && l.value == op;
return l.type === tt.relational && l.value === op;
}
// TODO
@@ -87,7 +87,7 @@ export default class UtilParser extends Tokenizer {
hasPrecedingLineBreak(): boolean {
return lineBreak.test(
this.input.slice(this.state.lastTokEnd, this.state.start),
this.state.input.slice(this.state.lastTokEnd, this.state.start),
);
}

View File

@@ -300,7 +300,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (node) {
node.type = "Property";
if (node.kind === "method") node.kind = "init";
if (((node: any): N.ClassMethod).kind === "method") node.kind = "init";
node.shorthand = false;
}

View File

@@ -1124,7 +1124,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.types = [];
this.expect(tt.bracketL);
// We allow trailing commas
while (this.state.pos < this.input.length && !this.match(tt.bracketR)) {
while (this.state.pos < this.state.length && !this.match(tt.bracketR)) {
node.types.push(this.flowParseType());
if (this.match(tt.bracketR)) break;
this.expect(tt.comma);
@@ -1190,9 +1190,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
case "any":
return this.finishNode(node, "AnyTypeAnnotation");
case "void":
return this.finishNode(node, "VoidTypeAnnotation");
case "bool":
case "boolean":
return this.finishNode(node, "BooleanTypeAnnotation");
@@ -1369,6 +1366,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
"NumberLiteralTypeAnnotation",
);
case tt._void:
this.next();
return this.finishNode(node, "VoidTypeAnnotation");
case tt._null:
this.next();
return this.finishNode(node, "NullLiteralTypeAnnotation");
@@ -1384,6 +1385,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
default:
if (this.state.type.keyword === "typeof") {
return this.flowParseTypeofType();
} else if (this.state.type.keyword) {
const label = this.state.type.label;
this.next();
return super.createIdentifier(node, label);
}
}
@@ -1394,7 +1399,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const startPos = this.state.start,
startLoc = this.state.startLoc;
let type = this.flowParsePrimaryType();
while (!this.canInsertSemicolon() && this.match(tt.bracketL)) {
while (this.match(tt.bracketL) && !this.canInsertSemicolon()) {
const node = this.startNodeAt(startPos, startLoc);
node.elementType = type;
this.expect(tt.bracketL);
@@ -1626,7 +1631,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.match(tt.name) &&
(this.state.value === "type" ||
this.state.value === "interface" ||
this.state.value == "opaque")
this.state.value === "opaque")
) {
return false;
}
@@ -1842,7 +1847,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.assertModuleNodeAllowed(node);
}
parseExport(node: N.ExportNamedDeclaration): N.ExportNamedDeclaration {
parseExport(
node: N.ExportNamedDeclaration | N.ExportAllDeclaration,
): N.ExportNamedDeclaration | N.ExportAllDeclaration {
node = super.parseExport(node);
if (
node.type === "ExportNamedDeclaration" ||
@@ -1916,20 +1923,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
// don't consider `void` to be a keyword as then it'll use the void token type
// and set startExpr
isKeyword(name: string): boolean {
if (this.state.inType && name === "void") {
return false;
} else {
return super.isKeyword(name);
}
}
// ensure that inside flow types, we bypass the jsx parser plugin
readToken(code: number): void {
const next = this.input.charCodeAt(this.state.pos + 1);
if (
getTokenFromCode(code: number): void {
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (code === charCodes.leftCurlyBrace && next === charCodes.verticalBar) {
return this.finishOp(tt.braceBarL, 2);
} else if (
this.state.inType &&
(code === charCodes.greaterThan || code === charCodes.lessThan)
) {
@@ -1938,7 +1937,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.state.isIterator = true;
return super.readWord();
} else {
return super.readToken(code);
return super.getTokenFromCode(code);
}
}
@@ -2680,7 +2679,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
readToken_mult_modulo(code: number): void {
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (
code === charCodes.asterisk &&
next === charCodes.slash &&
@@ -2695,21 +2694,44 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.readToken_mult_modulo(code);
}
skipBlockComment(): void {
readToken_pipe_amp(code: number): void {
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (
this.hasPlugin("flow") &&
this.hasPlugin("flowComments") &&
this.skipFlowComment()
code === charCodes.verticalBar &&
next === charCodes.rightCurlyBrace
) {
// '|}'
this.finishOp(tt.braceBarR, 2);
return;
}
super.readToken_pipe_amp(code);
}
parseTopLevel(file: N.File, program: N.Program): N.File {
const fileNode = super.parseTopLevel(file, program);
if (this.state.hasFlowComment) {
this.unexpected(null, "Unterminated flow-comment");
}
return fileNode;
}
skipBlockComment(): void {
if (this.hasPlugin("flowComments") && this.skipFlowComment()) {
if (this.state.hasFlowComment) {
this.unexpected(
null,
"Cannot have a flow comment inside another flow comment",
);
}
this.hasFlowCommentCompletion();
this.state.pos += this.skipFlowComment();
this.state.hasFlowComment = true;
return;
}
let end;
if (this.hasPlugin("flow") && this.state.hasFlowComment) {
end = this.input.indexOf("*-/", (this.state.pos += 2));
if (this.state.hasFlowComment) {
const end = this.state.input.indexOf("*-/", (this.state.pos += 2));
if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment");
this.state.pos = end + 3;
return;
@@ -2719,23 +2741,40 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
skipFlowComment(): number | boolean {
const ch2 = this.input.charCodeAt(this.state.pos + 2);
const ch3 = this.input.charCodeAt(this.state.pos + 3);
const { pos } = this.state;
let shiftToFirstNonWhiteSpace = 2;
while (
[charCodes.space, charCodes.tab].includes(
this.state.input.charCodeAt(pos + shiftToFirstNonWhiteSpace),
)
) {
shiftToFirstNonWhiteSpace++;
}
const ch2 = this.state.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);
const ch3 = this.state.input.charCodeAt(
shiftToFirstNonWhiteSpace + pos + 1,
);
if (ch2 === charCodes.colon && ch3 === charCodes.colon) {
return 4; // check for /*::
return shiftToFirstNonWhiteSpace + 2; // check for /*::
}
if (this.input.slice(this.state.pos + 2, 14) === "flow-include") {
return 14; // check for /*flow-include
if (
this.state.input.slice(
shiftToFirstNonWhiteSpace + pos,
shiftToFirstNonWhiteSpace + pos + 12,
) === "flow-include"
) {
return shiftToFirstNonWhiteSpace + 12; // check for /*flow-include
}
if (ch2 === charCodes.colon && ch3 !== charCodes.colon) {
return 2; // check for /*:, advance only 2 steps
return shiftToFirstNonWhiteSpace; // check for /*:, advance up to :
}
return false;
}
hasFlowCommentCompletion(): void {
const end = this.input.indexOf("*/", this.state.pos);
const end = this.state.input.indexOf("*/", this.state.pos);
if (end === -1) {
this.raise(this.state.pos, "Unterminated comment");
}

View File

@@ -79,11 +79,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let out = "";
let chunkStart = this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(this.state.start, "Unterminated JSX contents");
}
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
switch (ch) {
case charCodes.lessThan:
@@ -93,20 +93,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
++this.state.pos;
return this.finishToken(tt.jsxTagStart);
}
return this.getTokenFromCode(ch);
return super.getTokenFromCode(ch);
}
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
return this.finishToken(tt.jsxText, out);
case charCodes.ampersand:
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadEntity();
chunkStart = this.state.pos;
break;
default:
if (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadNewLine(true);
chunkStart = this.state.pos;
} else {
@@ -117,12 +117,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
jsxReadNewLine(normalizeCRLF: boolean): string {
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
let out;
++this.state.pos;
if (
ch === charCodes.carriageReturn &&
this.input.charCodeAt(this.state.pos) === charCodes.lineFeed
this.state.input.charCodeAt(this.state.pos) === charCodes.lineFeed
) {
++this.state.pos;
out = normalizeCRLF ? "\n" : "\r\n";
@@ -139,25 +139,25 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let out = "";
let chunkStart = ++this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(this.state.start, "Unterminated string constant");
}
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
if (ch === quote) break;
if (ch === charCodes.ampersand) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadEntity();
chunkStart = this.state.pos;
} else if (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
out += this.jsxReadNewLine(false);
chunkStart = this.state.pos;
} else {
++this.state.pos;
}
}
out += this.input.slice(chunkStart, this.state.pos++);
out += this.state.input.slice(chunkStart, this.state.pos++);
return this.finishToken(tt.string, out);
}
@@ -165,11 +165,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let str = "";
let count = 0;
let entity;
let ch = this.input[this.state.pos];
let ch = this.state.input[this.state.pos];
const startPos = ++this.state.pos;
while (this.state.pos < this.input.length && count++ < 10) {
ch = this.input[this.state.pos++];
while (this.state.pos < this.state.length && count++ < 10) {
ch = this.state.input[this.state.pos++];
if (ch === ";") {
if (str[0] === "#") {
if (str[1] === "x") {
@@ -208,11 +208,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let ch;
const start = this.state.pos;
do {
ch = this.input.charCodeAt(++this.state.pos);
ch = this.state.input.charCodeAt(++this.state.pos);
} while (isIdentifierChar(ch) || ch === charCodes.dash);
return this.finishToken(
tt.jsxName,
this.input.slice(start, this.state.pos),
this.state.input.slice(start, this.state.pos),
);
}
@@ -520,8 +520,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
readToken(code: number): void {
if (this.state.inPropertyName) return super.readToken(code);
getTokenFromCode(code: number): void {
if (this.state.inPropertyName) return super.getTokenFromCode(code);
const context = this.curContext();
@@ -557,7 +557,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishToken(tt.jsxTagStart);
}
return super.readToken(code);
return super.getTokenFromCode(code);
}
updateContext(prevType: TokenType): void {

View File

@@ -45,6 +45,8 @@ function keywordTypeFromName(
return "TSAnyKeyword";
case "boolean":
return "TSBooleanKeyword";
case "bigint":
return "TSBigIntKeyword";
case "never":
return "TSNeverKeyword";
case "number":
@@ -218,6 +220,28 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return result;
}
tsParseImportType(): N.TsImportType {
const node: N.TsImportType = this.startNode();
this.expect(tt._import);
this.expect(tt.parenL);
if (!this.match(tt.string)) {
throw this.unexpected(
null,
"Argument in a type import must be a string literal",
);
}
node.argument = this.parseLiteral(this.state.value, "StringLiteral");
this.expect(tt.parenR);
if (this.eat(tt.dot)) {
node.qualifier = this.tsParseEntityName(/* allowReservedWords */ true);
}
if (this.isRelational("<")) {
node.typeParameters = this.tsParseTypeArguments();
}
return this.finishNode(node, "TSImportType");
}
tsParseEntityName(allowReservedWords: boolean): N.TsEntityName {
let entity: N.TsEntityName = this.parseIdentifier();
while (this.eat(tt.dot)) {
@@ -240,7 +264,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseThisTypePredicate(lhs: N.TsThisType): N.TsTypePredicate {
this.next();
const node: N.TsTypePredicate = this.startNode();
const node: N.TsTypePredicate = this.startNodeAtNode(lhs);
node.parameterName = lhs;
node.typeAnnotation = this.tsParseTypeAnnotation(/* eatColon */ false);
return this.finishNode(node, "TSTypePredicate");
@@ -255,7 +279,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseTypeQuery(): N.TsTypeQuery {
const node: N.TsTypeQuery = this.startNode();
this.expect(tt._typeof);
node.exprName = this.tsParseEntityName(/* allowReservedWords */ true);
if (this.match(tt._import)) {
node.exprName = this.tsParseImportType();
} else {
node.exprName = this.tsParseEntityName(/* allowReservedWords */ true);
}
return this.finishNode(node, "TSTypeQuery");
}
@@ -370,8 +398,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.expect(tt.bracketL);
const id = this.parseIdentifier();
this.expect(tt.colon);
id.typeAnnotation = this.tsParseTypeAnnotation(/* eatColon */ false);
id.typeAnnotation = this.tsParseTypeAnnotation();
this.finishNode(id, "Identifier"); // set end position to end of type
this.expect(tt.bracketR);
node.parameters = [id];
@@ -518,17 +547,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// No mandatory elements may follow optional elements
// If there's a rest element, it must be at the end of the tuple
let seenOptionalElement = false;
node.elementTypes.forEach((elementNode, i) => {
if (elementNode.type === "TSRestType") {
if (i !== node.elementTypes.length - 1) {
this.raise(
elementNode.start,
"A rest element must be last in a tuple type.",
);
}
} else if (elementNode.type === "TSOptionalType") {
node.elementTypes.forEach(elementNode => {
if (elementNode.type === "TSOptionalType") {
seenOptionalElement = true;
} else if (seenOptionalElement) {
} else if (seenOptionalElement && elementNode.type !== "TSRestType") {
this.raise(
elementNode.start,
"A required element cannot follow an optional element.",
@@ -545,6 +567,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const restNode: N.TsRestType = this.startNode();
this.next(); // skips ellipsis
restNode.typeAnnotation = this.tsParseType();
this.checkCommaAfterRest(tt.bracketR, "type");
return this.finishNode(restNode, "TSRestType");
}
@@ -643,6 +666,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
case tt._typeof:
return this.tsParseTypeQuery();
case tt._import:
return this.tsParseImportType();
case tt.braceL:
return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this))
? this.tsParseMappedType()
@@ -894,6 +919,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseTypeAssertion(): N.TsTypeAssertion {
const node: N.TsTypeAssertion = this.startNode();
this.next(); // <
// Not actually necessary to set state.inType because we never reach here if JSX plugin is enabled,
// but need `tsInType` to satisfy the assertion in `tsParseType`.
node.typeAnnotation = this.tsInType(() => this.tsParseType());
@@ -902,11 +928,21 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "TSTypeAssertion");
}
tsParseHeritageClause(): $ReadOnlyArray<N.TsExpressionWithTypeArguments> {
return this.tsParseDelimitedList(
tsParseHeritageClause(
descriptor: string,
): $ReadOnlyArray<N.TsExpressionWithTypeArguments> {
const originalStart = this.state.start;
const delimitedList = this.tsParseDelimitedList(
"HeritageClauseElement",
this.tsParseExpressionWithTypeArguments.bind(this),
);
if (!delimitedList.length) {
this.raise(originalStart, `'${descriptor}' list cannot be empty.`);
}
return delimitedList;
}
tsParseExpressionWithTypeArguments(): N.TsExpressionWithTypeArguments {
@@ -927,7 +963,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.id = this.parseIdentifier();
node.typeParameters = this.tsTryParseTypeParameters();
if (this.eat(tt._extends)) {
node.extends = this.tsParseHeritageClause();
node.extends = this.tsParseHeritageClause("extends");
}
const body: N.TSInterfaceBody = this.startNode();
body.body = this.tsInType(this.tsParseObjectTypeMembers.bind(this));
@@ -1151,6 +1187,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
tsTryParseDeclare(nany: any): ?N.Declaration {
if (this.isLineTerminator()) {
return;
}
switch (this.state.type) {
case tt._function:
this.next();
@@ -1227,10 +1267,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
): ?N.Declaration {
switch (value) {
case "abstract":
if (next || this.match(tt._class)) {
if (this.tsCheckLineTerminatorAndMatch(tt._class, next)) {
const cls: N.ClassDeclaration = node;
cls.abstract = true;
if (next) this.next();
if (next) {
this.next();
if (!this.match(tt._class)) {
this.unexpected(null, tt._class);
}
}
return this.parseClass(
cls,
/* isStatement */ true,
@@ -1247,7 +1292,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
break;
case "interface":
if (next || this.match(tt.name)) {
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
if (next) this.next();
return this.tsParseInterfaceDeclaration(node);
}
@@ -1257,20 +1302,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (next) this.next();
if (this.match(tt.string)) {
return this.tsParseAmbientExternalModuleDeclaration(node);
} else if (next || this.match(tt.name)) {
} else if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
return this.tsParseModuleOrNamespaceDeclaration(node);
}
break;
case "namespace":
if (next || this.match(tt.name)) {
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
if (next) this.next();
return this.tsParseModuleOrNamespaceDeclaration(node);
}
break;
case "type":
if (next || this.match(tt.name)) {
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
if (next) this.next();
return this.tsParseTypeAliasDeclaration(node);
}
@@ -1278,6 +1323,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
tsCheckLineTerminatorAndMatch(tokenType: TokenType, next: boolean) {
return (next || this.match(tokenType)) && !this.isLineTerminator();
}
tsTryParseGenericAsyncArrowFunction(
startPos: number,
startLoc: Position,
@@ -1362,6 +1411,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
allowModifiers: ?boolean,
decorators: N.Decorator[],
): N.Pattern | N.TSParameterProperty {
// Store original location/position to include modifiers in range
const startPos = this.state.start;
const startLoc = this.state.startLoc;
let accessibility: ?N.Accessibility;
let readonly = false;
if (allowModifiers) {
@@ -1373,7 +1426,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.parseAssignableListItemTypes(left);
const elt = this.parseMaybeDefault(left.start, left.loc.start, left);
if (accessibility || readonly) {
const pp: N.TSParameterProperty = this.startNodeAtNode(elt);
const pp: N.TSParameterProperty = this.startNodeAt(startPos, startLoc);
if (decorators.length) {
pp.decorators = decorators;
}
@@ -1387,12 +1440,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
pp.parameter = elt;
return this.finishNode(pp, "TSParameterProperty");
} else {
if (decorators.length) {
left.decorators = decorators;
}
return elt;
}
if (decorators.length) {
left.decorators = decorators;
}
return elt;
}
parseFunctionBodyAndFinish(
@@ -1871,7 +1925,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node.superTypeParameters = this.tsParseTypeArguments();
}
if (this.eatContextual("implements")) {
node.implements = this.tsParseHeritageClause();
node.implements = this.tsParseHeritageClause("implements");
}
}
@@ -1983,10 +2037,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// Correct TypeScript code should have at least 1 type parameter, but don't crash on bad code.
if (typeParameters && typeParameters.params.length !== 0) {
this.resetStartLocationFromNode(
arrowExpression,
typeParameters.params[0],
);
this.resetStartLocationFromNode(arrowExpression, typeParameters);
}
arrowExpression.typeParameters = typeParameters;
return arrowExpression;
@@ -1994,7 +2045,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// Handle type assertions
parseMaybeUnary(refShorthandDefaultPos?: ?Pos): N.Expression {
if (!this.hasPlugin("jsx") && this.eatRelational("<")) {
if (!this.hasPlugin("jsx") && this.isRelational("<")) {
return this.tsParseTypeAssertion();
} else {
return super.parseMaybeUnary(refShorthandDefaultPos);
@@ -2167,11 +2218,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
// ensure that inside types, we bypass the jsx parser plugin
readToken(code: number): void {
getTokenFromCode(code: number): void {
if (this.state.inType && (code === 62 || code === 60)) {
return this.finishOp(tt.relational, 1);
} else {
return super.readToken(code);
return super.getTokenFromCode(code);
}
}

View File

@@ -107,7 +107,9 @@ tt._function.updateContext = tt._class.updateContext = function(prevType) {
prevType !== tt._else &&
!(
prevType === tt._return &&
lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start))
lineBreak.test(
this.state.input.slice(this.state.lastTokEnd, this.state.start),
)
) &&
!(
(prevType === tt.colon || prevType === tt.braceL) &&

View File

@@ -3,11 +3,7 @@
import type { Options } from "../options";
import type { Position } from "../util/location";
import * as charCodes from "charcodes";
import {
isIdentifierStart,
isIdentifierChar,
isKeyword,
} from "../util/identifier";
import { isIdentifierStart, isIdentifierChar } from "../util/identifier";
import { types as tt, keywords as keywordTypes, type TokenType } from "./types";
import { type TokContext, types as ct } from "./context";
import LocationParser from "../parser/location";
@@ -20,7 +16,7 @@ import {
} from "../util/whitespace";
import State from "./state";
const VALID_REGEX_FLAGS = "gmsiyu";
const VALID_REGEX_FLAGS = new Set(["g", "m", "s", "i", "y", "u"]);
// The following character codes are forbidden from being
// an immediate sibling of NumericLiteralSeparator _
@@ -157,12 +153,6 @@ export default class Tokenizer extends LocationParser {
// TODO
isKeyword(word: string): boolean {
return isKeyword(word);
}
// TODO
lookahead(): State {
const old = this.state;
this.state = old.clone(true);
@@ -185,7 +175,7 @@ export default class Tokenizer extends LocationParser {
this.state.pos = this.state.start;
while (this.state.pos < this.state.lineStart) {
this.state.lineStart =
this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1;
this.state.input.lastIndexOf("\n", this.state.lineStart - 2) + 1;
--this.state.curLine;
}
this.nextToken();
@@ -206,7 +196,7 @@ export default class Tokenizer extends LocationParser {
this.state.octalPosition = null;
this.state.start = this.state.pos;
this.state.startLoc = this.state.curPosition();
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.finishToken(tt.eof);
return;
}
@@ -214,17 +204,7 @@ export default class Tokenizer extends LocationParser {
if (curContext.override) {
curContext.override(this);
} else {
this.readToken(this.input.codePointAt(this.state.pos));
}
}
readToken(code: number): void {
// Identifier or keyword. '\uXXXX' sequences are allowed in
// identifiers, so '\' also dispatches to that.
if (isIdentifierStart(code) || code === charCodes.backslash) {
this.readWord();
} else {
this.getTokenFromCode(code);
this.getTokenFromCode(this.state.input.codePointAt(this.state.pos));
}
}
@@ -254,14 +234,14 @@ export default class Tokenizer extends LocationParser {
skipBlockComment(): void {
const startLoc = this.state.curPosition();
const start = this.state.pos;
const end = this.input.indexOf("*/", (this.state.pos += 2));
const end = this.state.input.indexOf("*/", (this.state.pos += 2));
if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment");
this.state.pos = end + 2;
lineBreakG.lastIndex = start;
let match;
while (
(match = lineBreakG.exec(this.input)) &&
(match = lineBreakG.exec(this.state.input)) &&
match.index < this.state.pos
) {
++this.state.curLine;
@@ -270,7 +250,7 @@ export default class Tokenizer extends LocationParser {
this.pushComment(
true,
this.input.slice(start + 2, end),
this.state.input.slice(start + 2, end),
start,
this.state.pos,
startLoc,
@@ -281,22 +261,22 @@ export default class Tokenizer extends LocationParser {
skipLineComment(startSkip: number): void {
const start = this.state.pos;
const startLoc = this.state.curPosition();
let ch = this.input.charCodeAt((this.state.pos += startSkip));
if (this.state.pos < this.input.length) {
let ch = this.state.input.charCodeAt((this.state.pos += startSkip));
if (this.state.pos < this.state.length) {
while (
ch !== charCodes.lineFeed &&
ch !== charCodes.carriageReturn &&
ch !== charCodes.lineSeparator &&
ch !== charCodes.paragraphSeparator &&
++this.state.pos < this.input.length
++this.state.pos < this.state.length
) {
ch = this.input.charCodeAt(this.state.pos);
ch = this.state.input.charCodeAt(this.state.pos);
}
}
this.pushComment(
false,
this.input.slice(start + startSkip, this.state.pos),
this.state.input.slice(start + startSkip, this.state.pos),
start,
this.state.pos,
startLoc,
@@ -308,12 +288,18 @@ export default class Tokenizer extends LocationParser {
// whitespace and comments, and.
skipSpace(): void {
loop: while (this.state.pos < this.input.length) {
const ch = this.input.charCodeAt(this.state.pos);
loop: while (this.state.pos < this.state.length) {
const ch = this.state.input.charCodeAt(this.state.pos);
switch (ch) {
case charCodes.space:
case charCodes.nonBreakingSpace:
case charCodes.tab:
++this.state.pos;
break;
case charCodes.carriageReturn:
if (
this.input.charCodeAt(this.state.pos + 1) === charCodes.lineFeed
this.state.input.charCodeAt(this.state.pos + 1) ===
charCodes.lineFeed
) {
++this.state.pos;
}
@@ -327,7 +313,7 @@ export default class Tokenizer extends LocationParser {
break;
case charCodes.slash:
switch (this.input.charCodeAt(this.state.pos + 1)) {
switch (this.state.input.charCodeAt(this.state.pos + 1)) {
case charCodes.asterisk:
this.skipBlockComment();
break;
@@ -382,7 +368,7 @@ export default class Tokenizer extends LocationParser {
}
const nextPos = this.state.pos + 1;
const next = this.input.charCodeAt(nextPos);
const next = this.state.input.charCodeAt(nextPos);
if (next >= charCodes.digit0 && next <= charCodes.digit9) {
this.raise(this.state.pos, "Unexpected digit after hash token");
}
@@ -405,13 +391,13 @@ export default class Tokenizer extends LocationParser {
}
readToken_dot(): void {
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (next >= charCodes.digit0 && next <= charCodes.digit9) {
this.readNumber(true);
return;
}
const next2 = this.input.charCodeAt(this.state.pos + 2);
const next2 = this.state.input.charCodeAt(this.state.pos + 2);
if (next === charCodes.dot && next2 === charCodes.dot) {
this.state.pos += 3;
this.finishToken(tt.ellipsis);
@@ -429,7 +415,7 @@ export default class Tokenizer extends LocationParser {
return;
}
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (next === charCodes.equalsTo) {
this.finishOp(tt.assign, 2);
} else {
@@ -438,12 +424,12 @@ export default class Tokenizer extends LocationParser {
}
readToken_interpreter(): boolean {
if (this.state.pos !== 0 || this.state.input.length < 2) return false;
if (this.state.pos !== 0 || this.state.length < 2) return false;
const start = this.state.pos;
this.state.pos += 1;
let ch = this.input.charCodeAt(this.state.pos);
let ch = this.state.input.charCodeAt(this.state.pos);
if (ch !== charCodes.exclamationMark) return false;
while (
@@ -451,12 +437,12 @@ export default class Tokenizer extends LocationParser {
ch !== charCodes.carriageReturn &&
ch !== charCodes.lineSeparator &&
ch !== charCodes.paragraphSeparator &&
++this.state.pos < this.input.length
++this.state.pos < this.state.length
) {
ch = this.input.charCodeAt(this.state.pos);
ch = this.state.input.charCodeAt(this.state.pos);
}
const value = this.input.slice(start + 2, this.state.pos);
const value = this.state.input.slice(start + 2, this.state.pos);
this.finishToken(tt.interpreterDirective, value);
@@ -467,13 +453,13 @@ export default class Tokenizer extends LocationParser {
// '%*'
let type = code === charCodes.asterisk ? tt.star : tt.modulo;
let width = 1;
let next = this.input.charCodeAt(this.state.pos + 1);
let next = this.state.input.charCodeAt(this.state.pos + 1);
const exprAllowed = this.state.exprAllowed;
// Exponentiation operator **
if (code === charCodes.asterisk && next === charCodes.asterisk) {
width++;
next = this.input.charCodeAt(this.state.pos + 2);
next = this.state.input.charCodeAt(this.state.pos + 2);
type = tt.exponent;
}
@@ -486,11 +472,13 @@ export default class Tokenizer extends LocationParser {
}
readToken_pipe_amp(code: number): void {
// '|&'
const next = this.input.charCodeAt(this.state.pos + 1);
// '||' '&&' '||=' '&&='
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (next === code) {
if (this.input.charCodeAt(this.state.pos + 2) === charCodes.equalsTo) {
if (
this.state.input.charCodeAt(this.state.pos + 2) === charCodes.equalsTo
) {
this.finishOp(tt.assign, 3);
} else {
this.finishOp(
@@ -506,10 +494,6 @@ export default class Tokenizer extends LocationParser {
if (next === charCodes.greaterThan) {
this.finishOp(tt.pipeline, 2);
return;
} else if (next === charCodes.rightCurlyBrace && this.hasPlugin("flow")) {
// '|}'
this.finishOp(tt.braceBarR, 2);
return;
}
}
@@ -526,7 +510,7 @@ export default class Tokenizer extends LocationParser {
readToken_caret(): void {
// '^'
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (next === charCodes.equalsTo) {
this.finishOp(tt.assign, 2);
} else {
@@ -536,14 +520,17 @@ export default class Tokenizer extends LocationParser {
readToken_plus_min(code: number): void {
// '+-'
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (next === code) {
if (
next === charCodes.dash &&
!this.inModule &&
this.input.charCodeAt(this.state.pos + 2) === charCodes.greaterThan &&
lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))
this.state.input.charCodeAt(this.state.pos + 2) ===
charCodes.greaterThan &&
lineBreak.test(
this.state.input.slice(this.state.lastTokEnd, this.state.pos),
)
) {
// A `-->` line comment
this.skipLineComment(3);
@@ -564,16 +551,20 @@ export default class Tokenizer extends LocationParser {
readToken_lt_gt(code: number): void {
// '<>'
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
let size = 1;
if (next === code) {
size =
code === charCodes.greaterThan &&
this.input.charCodeAt(this.state.pos + 2) === charCodes.greaterThan
this.state.input.charCodeAt(this.state.pos + 2) ===
charCodes.greaterThan
? 3
: 2;
if (this.input.charCodeAt(this.state.pos + size) === charCodes.equalsTo) {
if (
this.state.input.charCodeAt(this.state.pos + size) ===
charCodes.equalsTo
) {
this.finishOp(tt.assign, size + 1);
return;
}
@@ -585,8 +576,8 @@ export default class Tokenizer extends LocationParser {
next === charCodes.exclamationMark &&
code === charCodes.lessThan &&
!this.inModule &&
this.input.charCodeAt(this.state.pos + 2) === charCodes.dash &&
this.input.charCodeAt(this.state.pos + 3) === charCodes.dash
this.state.input.charCodeAt(this.state.pos + 2) === charCodes.dash &&
this.state.input.charCodeAt(this.state.pos + 3) === charCodes.dash
) {
// `<!--`, an XML-style comment that should be interpreted as a line comment
this.skipLineComment(4);
@@ -605,11 +596,11 @@ export default class Tokenizer extends LocationParser {
readToken_eq_excl(code: number): void {
// '=!'
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (next === charCodes.equalsTo) {
this.finishOp(
tt.equality,
this.input.charCodeAt(this.state.pos + 2) === charCodes.equalsTo
this.state.input.charCodeAt(this.state.pos + 2) === charCodes.equalsTo
? 3
: 2,
);
@@ -626,8 +617,8 @@ export default class Tokenizer extends LocationParser {
readToken_question(): void {
// '?'
const next = this.input.charCodeAt(this.state.pos + 1);
const next2 = this.input.charCodeAt(this.state.pos + 2);
const next = this.state.input.charCodeAt(this.state.pos + 1);
const next2 = this.state.input.charCodeAt(this.state.pos + 2);
if (next === charCodes.questionMark && !this.state.inType) {
if (next2 === charCodes.equalsTo) {
// '??='
@@ -651,10 +642,6 @@ export default class Tokenizer extends LocationParser {
getTokenFromCode(code: number): void {
switch (code) {
case charCodes.numberSign:
this.readToken_numberSign();
return;
// The interpretation of a dot depends on whether it is followed
// by a digit or another two dots.
@@ -687,19 +674,10 @@ export default class Tokenizer extends LocationParser {
++this.state.pos;
this.finishToken(tt.bracketR);
return;
case charCodes.leftCurlyBrace:
if (
this.hasPlugin("flow") &&
this.input.charCodeAt(this.state.pos + 1) === charCodes.verticalBar
) {
this.finishOp(tt.braceBarL, 2);
} else {
++this.state.pos;
this.finishToken(tt.braceL);
}
++this.state.pos;
this.finishToken(tt.braceL);
return;
case charCodes.rightCurlyBrace:
++this.state.pos;
this.finishToken(tt.braceR);
@@ -708,7 +686,7 @@ export default class Tokenizer extends LocationParser {
case charCodes.colon:
if (
this.hasPlugin("functionBind") &&
this.input.charCodeAt(this.state.pos + 1) === charCodes.colon
this.state.input.charCodeAt(this.state.pos + 1) === charCodes.colon
) {
this.finishOp(tt.doubleColon, 2);
} else {
@@ -720,10 +698,6 @@ export default class Tokenizer extends LocationParser {
case charCodes.questionMark:
this.readToken_question();
return;
case charCodes.atSign:
++this.state.pos;
this.finishToken(tt.at);
return;
case charCodes.graveAccent:
++this.state.pos;
@@ -731,7 +705,7 @@ export default class Tokenizer extends LocationParser {
return;
case charCodes.digit0: {
const next = this.input.charCodeAt(this.state.pos + 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
// '0x', '0X' - hex number
if (next === charCodes.lowercaseX || next === charCodes.uppercaseX) {
this.readRadixNumber(16);
@@ -809,6 +783,25 @@ export default class Tokenizer extends LocationParser {
case charCodes.tilde:
this.finishOp(tt.tilde, 1);
return;
case charCodes.atSign:
++this.state.pos;
this.finishToken(tt.at);
return;
case charCodes.numberSign:
this.readToken_numberSign();
return;
case charCodes.backslash:
this.readWord();
return;
default:
if (isIdentifierStart(code)) {
this.readWord();
return;
}
}
this.raise(
@@ -818,7 +811,7 @@ export default class Tokenizer extends LocationParser {
}
finishOp(type: TokenType, size: number): void {
const str = this.input.slice(this.state.pos, this.state.pos + size);
const str = this.state.input.slice(this.state.pos, this.state.pos + size);
this.state.pos += size;
this.finishToken(type, str);
}
@@ -827,10 +820,10 @@ export default class Tokenizer extends LocationParser {
const start = this.state.pos;
let escaped, inClass;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(start, "Unterminated regular expression");
}
const ch = this.input.charAt(this.state.pos);
const ch = this.state.input.charAt(this.state.pos);
if (lineBreak.test(ch)) {
this.raise(start, "Unterminated regular expression");
}
@@ -848,16 +841,16 @@ export default class Tokenizer extends LocationParser {
}
++this.state.pos;
}
const content = this.input.slice(start, this.state.pos);
const content = this.state.input.slice(start, this.state.pos);
++this.state.pos;
let mods = "";
while (this.state.pos < this.input.length) {
const char = this.input[this.state.pos];
const charCode = this.input.codePointAt(this.state.pos);
while (this.state.pos < this.state.length) {
const char = this.state.input[this.state.pos];
const charCode = this.state.input.codePointAt(this.state.pos);
if (VALID_REGEX_FLAGS.indexOf(char) > -1) {
if (VALID_REGEX_FLAGS.has(char)) {
if (mods.indexOf(char) > -1) {
this.raise(this.state.pos + 1, "Duplicate regular expression flag");
}
@@ -902,12 +895,12 @@ export default class Tokenizer extends LocationParser {
let total = 0;
for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {
const code = this.input.charCodeAt(this.state.pos);
const code = this.state.input.charCodeAt(this.state.pos);
let val;
if (this.hasPlugin("numericSeparator")) {
const prev = this.input.charCodeAt(this.state.pos - 1);
const next = this.input.charCodeAt(this.state.pos + 1);
const prev = this.state.input.charCodeAt(this.state.pos - 1);
const next = this.state.input.charCodeAt(this.state.pos + 1);
if (code === charCodes.underscore) {
if (allowedSiblings.indexOf(next) === -1) {
this.raise(this.state.pos, "Invalid or unexpected token");
@@ -961,18 +954,22 @@ export default class Tokenizer extends LocationParser {
}
if (this.hasPlugin("bigInt")) {
if (this.input.charCodeAt(this.state.pos) === charCodes.lowercaseN) {
if (
this.state.input.charCodeAt(this.state.pos) === charCodes.lowercaseN
) {
++this.state.pos;
isBigInt = true;
}
}
if (isIdentifierStart(this.input.codePointAt(this.state.pos))) {
if (isIdentifierStart(this.state.input.codePointAt(this.state.pos))) {
this.raise(this.state.pos, "Identifier directly after number");
}
if (isBigInt) {
const str = this.input.slice(start, this.state.pos).replace(/[_n]/g, "");
const str = this.state.input
.slice(start, this.state.pos)
.replace(/[_n]/g, "");
this.finishToken(tt.bigint, str);
return;
}
@@ -992,7 +989,7 @@ export default class Tokenizer extends LocationParser {
}
let octal =
this.state.pos - start >= 2 &&
this.input.charCodeAt(start) === charCodes.digit0;
this.state.input.charCodeAt(start) === charCodes.digit0;
if (octal) {
if (this.state.strict) {
this.raise(
@@ -1000,30 +997,30 @@ export default class Tokenizer extends LocationParser {
"Legacy octal literals are not allowed in strict mode",
);
}
if (/[89]/.test(this.input.slice(start, this.state.pos))) {
if (/[89]/.test(this.state.input.slice(start, this.state.pos))) {
octal = false;
}
}
let next = this.input.charCodeAt(this.state.pos);
let next = this.state.input.charCodeAt(this.state.pos);
if (next === charCodes.dot && !octal) {
++this.state.pos;
this.readInt(10);
isFloat = true;
next = this.input.charCodeAt(this.state.pos);
next = this.state.input.charCodeAt(this.state.pos);
}
if (
(next === charCodes.uppercaseE || next === charCodes.lowercaseE) &&
!octal
) {
next = this.input.charCodeAt(++this.state.pos);
next = this.state.input.charCodeAt(++this.state.pos);
if (next === charCodes.plusSign || next === charCodes.dash) {
++this.state.pos;
}
if (this.readInt(10) === null) this.raise(start, "Invalid number");
isFloat = true;
next = this.input.charCodeAt(this.state.pos);
next = this.state.input.charCodeAt(this.state.pos);
}
if (this.hasPlugin("bigInt")) {
@@ -1035,12 +1032,14 @@ export default class Tokenizer extends LocationParser {
}
}
if (isIdentifierStart(this.input.codePointAt(this.state.pos))) {
if (isIdentifierStart(this.state.input.codePointAt(this.state.pos))) {
this.raise(this.state.pos, "Identifier directly after number");
}
// remove "_" for numeric literal separator, and "n" for BigInts
const str = this.input.slice(start, this.state.pos).replace(/[_n]/g, "");
const str = this.state.input
.slice(start, this.state.pos)
.replace(/[_n]/g, "");
if (isBigInt) {
this.finishToken(tt.bigint, str);
@@ -1054,13 +1053,13 @@ export default class Tokenizer extends LocationParser {
// Read a string value, interpreting backslash-escapes.
readCodePoint(throwOnInvalid: boolean): number | null {
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
let code;
if (ch === charCodes.leftCurlyBrace) {
const codePos = ++this.state.pos;
code = this.readHexChar(
this.input.indexOf("}", this.state.pos) - this.state.pos,
this.state.input.indexOf("}", this.state.pos) - this.state.pos,
throwOnInvalid,
);
++this.state.pos;
@@ -1085,13 +1084,13 @@ export default class Tokenizer extends LocationParser {
let out = "",
chunkStart = ++this.state.pos;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(this.state.start, "Unterminated string constant");
}
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
if (ch === quote) break;
if (ch === charCodes.backslash) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
// $FlowFixMe
out += this.readEscapedChar(false);
chunkStart = this.state.pos;
@@ -1107,7 +1106,7 @@ export default class Tokenizer extends LocationParser {
++this.state.pos;
}
}
out += this.input.slice(chunkStart, this.state.pos++);
out += this.state.input.slice(chunkStart, this.state.pos++);
this.finishToken(tt.string, out);
}
@@ -1118,14 +1117,14 @@ export default class Tokenizer extends LocationParser {
chunkStart = this.state.pos,
containsInvalid = false;
for (;;) {
if (this.state.pos >= this.input.length) {
if (this.state.pos >= this.state.length) {
this.raise(this.state.start, "Unterminated template");
}
const ch = this.input.charCodeAt(this.state.pos);
const ch = this.state.input.charCodeAt(this.state.pos);
if (
ch === charCodes.graveAccent ||
(ch === charCodes.dollarSign &&
this.input.charCodeAt(this.state.pos + 1) ===
this.state.input.charCodeAt(this.state.pos + 1) ===
charCodes.leftCurlyBrace)
) {
if (this.state.pos === this.state.start && this.match(tt.template)) {
@@ -1139,12 +1138,12 @@ export default class Tokenizer extends LocationParser {
return;
}
}
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
this.finishToken(tt.template, containsInvalid ? null : out);
return;
}
if (ch === charCodes.backslash) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
const escaped = this.readEscapedChar(true);
if (escaped === null) {
containsInvalid = true;
@@ -1153,11 +1152,13 @@ export default class Tokenizer extends LocationParser {
}
chunkStart = this.state.pos;
} else if (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.state.pos);
out += this.state.input.slice(chunkStart, this.state.pos);
++this.state.pos;
switch (ch) {
case charCodes.carriageReturn:
if (this.input.charCodeAt(this.state.pos) === charCodes.lineFeed) {
if (
this.state.input.charCodeAt(this.state.pos) === charCodes.lineFeed
) {
++this.state.pos;
}
case charCodes.lineFeed:
@@ -1180,7 +1181,7 @@ export default class Tokenizer extends LocationParser {
readEscapedChar(inTemplate: boolean): string | null {
const throwOnInvalid = !inTemplate;
const ch = this.input.charCodeAt(++this.state.pos);
const ch = this.state.input.charCodeAt(++this.state.pos);
++this.state.pos;
switch (ch) {
case charCodes.lowercaseN:
@@ -1204,7 +1205,9 @@ export default class Tokenizer extends LocationParser {
case charCodes.lowercaseF:
return "\f";
case charCodes.carriageReturn:
if (this.input.charCodeAt(this.state.pos) === charCodes.lineFeed) {
if (
this.state.input.charCodeAt(this.state.pos) === charCodes.lineFeed
) {
++this.state.pos;
}
case charCodes.lineFeed:
@@ -1215,7 +1218,7 @@ export default class Tokenizer extends LocationParser {
if (ch >= charCodes.digit0 && ch <= charCodes.digit7) {
const codePos = this.state.pos - 1;
// $FlowFixMe
let octalStr = this.input
let octalStr = this.state.input
.substr(this.state.pos - 1, 3)
.match(/^[0-7]+/)[0];
let octal = parseInt(octalStr, 8);
@@ -1266,23 +1269,28 @@ export default class Tokenizer extends LocationParser {
// as a micro-optimization.
readWord1(): string {
let word = "";
this.state.containsEsc = false;
let word = "",
first = true,
chunkStart = this.state.pos;
while (this.state.pos < this.input.length) {
const ch = this.input.codePointAt(this.state.pos);
const start = this.state.pos;
let chunkStart = this.state.pos;
while (this.state.pos < this.state.length) {
const ch = this.state.input.codePointAt(this.state.pos);
if (isIdentifierChar(ch)) {
this.state.pos += ch <= 0xffff ? 1 : 2;
} else if (this.state.isIterator && ch === charCodes.atSign) {
this.state.pos += 1;
++this.state.pos;
} else if (ch === charCodes.backslash) {
this.state.containsEsc = true;
word += this.input.slice(chunkStart, this.state.pos);
word += this.state.input.slice(chunkStart, this.state.pos);
const escStart = this.state.pos;
const identifierCheck =
this.state.pos === start ? isIdentifierStart : isIdentifierChar;
if (this.input.charCodeAt(++this.state.pos) !== charCodes.lowercaseU) {
if (
this.state.input.charCodeAt(++this.state.pos) !== charCodes.lowercaseU
) {
this.raise(
this.state.pos,
"Expecting Unicode escape sequence \\uXXXX",
@@ -1291,8 +1299,11 @@ export default class Tokenizer extends LocationParser {
++this.state.pos;
const esc = this.readCodePoint(true);
// $FlowFixMe (thinks esc may be null, but throwOnInvalid is true)
if (!(first ? isIdentifierStart : isIdentifierChar)(esc, true)) {
if (
// $FlowFixMe (thinks esc may be null, but throwOnInvalid is true)
!identifierCheck(esc, true)
) {
this.raise(escStart, "Invalid Unicode escape");
}
@@ -1302,9 +1313,8 @@ export default class Tokenizer extends LocationParser {
} else {
break;
}
first = false;
}
return word + this.input.slice(chunkStart, this.state.pos);
return word + this.state.input.slice(chunkStart, this.state.pos);
}
isIterator(word: string): boolean {
@@ -1316,14 +1326,10 @@ export default class Tokenizer extends LocationParser {
readWord(): void {
const word = this.readWord1();
let type = tt.name;
const type = keywordTypes[word] || tt.name;
if (this.isKeyword(word)) {
if (this.state.containsEsc) {
this.raise(this.state.pos, `Escape sequence in keyword ${word}`);
}
type = keywordTypes[word];
if (type.keyword && this.state.containsEsc) {
this.raise(this.state.pos, `Escape sequence in keyword ${word}`);
}
// Allow @@iterator and @@asyncIterator as a identifier only inside type
@@ -1358,7 +1364,7 @@ export default class Tokenizer extends LocationParser {
(prevType === tt.name && this.state.exprAllowed)
) {
return lineBreak.test(
this.input.slice(this.state.lastTokEnd, this.state.start),
this.state.input.slice(this.state.lastTokEnd, this.state.start),
);
}

View File

@@ -6,95 +6,52 @@ import { Position } from "../util/location";
import { types as ct, type TokContext } from "./context";
import type { Token } from "./index";
import { types as tt, type TokenType, type TopicContextState } from "./types";
import { types as tt, type TokenType } from "./types";
type TopicContextState = {
// When a topic binding has been currently established,
// then this is 1. Otherwise, it is 0. This is forwards compatible
// with a future plugin for multiple lexical topics.
maxNumOfResolvableTopics: number,
// When a topic binding has been currently established, and if that binding
// has been used as a topic reference `#`, then this is 0. Otherwise, it is
// `null`. This is forwards compatible with a future plugin for multiple
// lexical topics.
maxTopicIndex: null | 0,
};
export default class State {
strict: boolean;
input: string;
length: number;
curLine: number;
// And, if locations are used, the {line, column} object
// corresponding to those offsets
startLoc: Position;
endLoc: Position;
init(options: Options, input: string): void {
this.strict =
options.strictMode === false ? false : options.sourceType === "module";
this.input = input;
this.length = input.length;
this.potentialArrowAt = -1;
this.noArrowAt = [];
this.noArrowParamsConversionAt = [];
this.inMethod = false;
this.inFunction = false;
this.inParameters = false;
this.maybeInArrowParameters = false;
this.inGenerator = false;
this.inAsync = false;
this.inPipeline = false;
this.inPropertyName = false;
this.inType = false;
this.inClassProperty = false;
this.noAnonFunctionType = false;
this.hasFlowComment = false;
this.isIterator = false;
// Used by smartPipelines.
this.topicContext = {
maxNumOfResolvableTopics: 0,
maxTopicIndex: null,
};
this.classLevel = 0;
this.labels = [];
this.decoratorStack = [[]];
this.yieldOrAwaitInPossibleArrowParameters = null;
this.tokens = [];
this.comments = [];
this.trailingComments = [];
this.leadingComments = [];
this.commentStack = [];
// $FlowIgnore
this.commentPreviousNode = null;
this.pos = this.lineStart = 0;
this.curLine = options.startLine;
this.type = tt.eof;
this.value = null;
this.start = this.end = this.pos;
this.startLoc = this.endLoc = this.curPosition();
// $FlowIgnore
this.lastTokEndLoc = this.lastTokStartLoc = null;
this.lastTokStart = this.lastTokEnd = this.pos;
this.context = [ct.braceStatement];
this.exprAllowed = true;
this.containsEsc = this.containsOctal = false;
this.octalPosition = null;
this.invalidTemplateEscapePosition = null;
this.exportedIdentifiers = [];
}
// TODO
strict: boolean;
// TODO
input: string;
// Used to signify the start of a potential arrow function
potentialArrowAt: number;
potentialArrowAt: number = -1;
// Used to signify the start of an expression which looks like a
// typed arrow function, but it isn't
// e.g. a ? (b) : c => d
// ^
noArrowAt: number[];
noArrowAt: number[] = [];
// Used to signify the start of an expression whose params, if it looks like
// an arrow function, shouldn't be converted to assignable nodes.
@@ -102,110 +59,118 @@ export default class State {
// conditional expressions.
// e.g. a ? (b) : c => d
// ^
noArrowParamsConversionAt: number[];
noArrowParamsConversionAt: number[] = [];
// A comma after "...a" is only allowed in spread, but not in rest.
// Since we parse destructuring patterns as array/object literals
// and then convert them, we need to track it.
commaAfterSpreadAt: number = -1;
// Flags to track whether we are in a function, a generator.
inFunction: boolean;
inParameters: boolean;
maybeInArrowParameters: boolean;
inGenerator: boolean;
inMethod: boolean | N.MethodKind;
inAsync: boolean;
inPipeline: boolean;
inType: boolean;
noAnonFunctionType: boolean;
inPropertyName: boolean;
inClassProperty: boolean;
hasFlowComment: boolean;
isIterator: boolean;
inFunction: boolean = false;
inParameters: boolean = false;
maybeInArrowParameters: boolean = false;
inGenerator: boolean = false;
inMethod: boolean | N.MethodKind = false;
inAsync: boolean = false;
inPipeline: boolean = false;
inType: boolean = false;
noAnonFunctionType: boolean = false;
inPropertyName: boolean = false;
inClassProperty: boolean = false;
hasFlowComment: boolean = false;
isIterator: boolean = false;
// For the smartPipelines plugin:
topicContext: TopicContextState;
topicContext: TopicContextState = {
maxNumOfResolvableTopics: 0,
maxTopicIndex: null,
};
// Check whether we are in a (nested) class or not.
classLevel: number;
classLevel: number = 0;
// Labels in scope.
labels: Array<{
kind: ?("loop" | "switch"),
name?: ?string,
statementStart?: number,
}>;
}> = [];
// Leading decorators. Last element of the stack represents the decorators in current context.
// Supports nesting of decorators, e.g. @foo(@bar class inner {}) class outer {}
// where @foo belongs to the outer class and @bar to the inner
decoratorStack: Array<Array<N.Decorator>>;
decoratorStack: Array<Array<N.Decorator>> = [[]];
// The first yield or await expression inside parenthesized expressions
// and arrow function parameters. It is used to disallow yield and await in
// arrow function parameters.
yieldOrAwaitInPossibleArrowParameters: ?N.YieldExpression;
yieldOrAwaitInPossibleArrowParameters:
| N.YieldExpression
| N.AwaitExpression
| null = null;
// Token store.
tokens: Array<Token | N.Comment>;
tokens: Array<Token | N.Comment> = [];
// Comment store.
comments: Array<N.Comment>;
comments: Array<N.Comment> = [];
// Comment attachment store
trailingComments: Array<N.Comment>;
leadingComments: Array<N.Comment>;
trailingComments: Array<N.Comment> = [];
leadingComments: Array<N.Comment> = [];
commentStack: Array<{
start: number,
leadingComments: ?Array<N.Comment>,
trailingComments: ?Array<N.Comment>,
type: string,
}>;
commentPreviousNode: N.Node;
}> = [];
// $FlowIgnore this is initialized when the parser starts.
commentPreviousNode: N.Node = null;
// The current position of the tokenizer in the input.
pos: number;
lineStart: number;
curLine: number;
pos: number = 0;
lineStart: number = 0;
// Properties of the current token:
// Its type
type: TokenType;
type: TokenType = tt.eof;
// For tokens that include more information than their type, the value
value: any;
value: any = null;
// Its start and end offset
start: number;
end: number;
// And, if locations are used, the {line, column} object
// corresponding to those offsets
startLoc: Position;
endLoc: Position;
start: number = 0;
end: number = 0;
// Position information for the previous token
lastTokEndLoc: Position;
lastTokStartLoc: Position;
lastTokStart: number;
lastTokEnd: number;
// $FlowIgnore this is initialized when generating the second token.
lastTokEndLoc: Position = null;
// $FlowIgnore this is initialized when generating the second token.
lastTokStartLoc: Position = null;
lastTokStart: number = 0;
lastTokEnd: number = 0;
// The context stack is used to superficially track syntactic
// context to predict whether a regular expression is allowed in a
// given position.
context: Array<TokContext>;
exprAllowed: boolean;
context: Array<TokContext> = [ct.braceStatement];
exprAllowed: boolean = true;
// Used to signal to callers of `readWord1` whether the word
// contained any escape sequences. This is needed because words with
// escape sequences must not be interpreted as keywords.
containsEsc: boolean;
containsEsc: boolean = false;
// TODO
containsOctal: boolean;
octalPosition: ?number;
containsOctal: boolean = false;
octalPosition: ?number = null;
// Names of exports store. `default` is stored as a name for both
// `export default foo;` and `export { foo as default };`.
exportedIdentifiers: Array<string>;
exportedIdentifiers: Array<string> = [];
invalidTemplateEscapePosition: ?number;
invalidTemplateEscapePosition: ?number = null;
curPosition(): Position {
return new Position(this.curLine, this.pos - this.lineStart);
@@ -213,7 +178,9 @@ export default class State {
clone(skipArrays?: boolean): State {
const state = new State();
Object.keys(this).forEach(key => {
const keys = Object.keys(this);
for (let i = 0, length = keys.length; i < length; i++) {
const key = keys[i];
// $FlowIgnore
let val = this[key];
@@ -223,7 +190,8 @@ export default class State {
// $FlowIgnore
state[key] = val;
});
}
return state;
}
}

View File

@@ -13,7 +13,12 @@
// expressions and divisions. It is set on all token types that can
// be followed by an expression (thus, a slash after them would be a
// regular expression).
//
// The `startsExpr` property is used to determine whether an expression
// may be the “argument” subexpression of a `yield` expression or
// `yield` statement. It is set on all token types that may be at the
// start of a subexpression.
// `isLoop` marks a keyword as starting a loop, which is important
// to know when parsing a label, in order to allow or disallow
// continue jumps to that label.
@@ -104,7 +109,7 @@ export const types: { [name: string]: TokenType } = {
backQuote: new TokenType("`", { startsExpr }),
dollarBraceL: new TokenType("${", { beforeExpr, startsExpr }),
at: new TokenType("@"),
hash: new TokenType("#"),
hash: new TokenType("#", { startsExpr }),
// Special hashbang token.
interpreterDirective: new TokenType("#!..."),
@@ -128,20 +133,20 @@ export const types: { [name: string]: TokenType } = {
incDec: new TokenType("++/--", { prefix, postfix, startsExpr }),
bang: new TokenType("!", { beforeExpr, prefix, startsExpr }),
tilde: new TokenType("~", { beforeExpr, prefix, startsExpr }),
pipeline: new BinopTokenType("|>", 0),
nullishCoalescing: new BinopTokenType("??", 1),
logicalOR: new BinopTokenType("||", 1),
logicalAND: new BinopTokenType("&&", 2),
bitwiseOR: new BinopTokenType("|", 3),
bitwiseXOR: new BinopTokenType("^", 4),
bitwiseAND: new BinopTokenType("&", 5),
equality: new BinopTokenType("==/!=", 6),
relational: new BinopTokenType("</>", 7),
bitShift: new BinopTokenType("<</>>", 8),
pipeline: BinopTokenType("|>", 0),
nullishCoalescing: BinopTokenType("??", 1),
logicalOR: BinopTokenType("||", 1),
logicalAND: BinopTokenType("&&", 2),
bitwiseOR: BinopTokenType("|", 3),
bitwiseXOR: BinopTokenType("^", 4),
bitwiseAND: BinopTokenType("&", 5),
equality: BinopTokenType("==/!=", 6),
relational: BinopTokenType("</>", 7),
bitShift: BinopTokenType("<</>>", 8),
plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }),
modulo: new BinopTokenType("%", 10),
star: new BinopTokenType("*", 10),
slash: new BinopTokenType("/", 10),
modulo: BinopTokenType("%", 10),
star: BinopTokenType("*", 10),
slash: BinopTokenType("/", 10),
exponent: new TokenType("**", {
beforeExpr,
binop: 11,
@@ -149,61 +154,55 @@ export const types: { [name: string]: TokenType } = {
}),
};
export const keywords = {
break: new KeywordTokenType("break"),
case: new KeywordTokenType("case", { beforeExpr }),
catch: new KeywordTokenType("catch"),
continue: new KeywordTokenType("continue"),
debugger: new KeywordTokenType("debugger"),
default: new KeywordTokenType("default", { beforeExpr }),
do: new KeywordTokenType("do", { isLoop, beforeExpr }),
else: new KeywordTokenType("else", { beforeExpr }),
finally: new KeywordTokenType("finally"),
for: new KeywordTokenType("for", { isLoop }),
function: new KeywordTokenType("function", { startsExpr }),
if: new KeywordTokenType("if"),
return: new KeywordTokenType("return", { beforeExpr }),
switch: new KeywordTokenType("switch"),
throw: new KeywordTokenType("throw", { beforeExpr, prefix, startsExpr }),
try: new KeywordTokenType("try"),
var: new KeywordTokenType("var"),
let: new KeywordTokenType("let"),
const: new KeywordTokenType("const"),
while: new KeywordTokenType("while", { isLoop }),
with: new KeywordTokenType("with"),
new: new KeywordTokenType("new", { beforeExpr, startsExpr }),
this: new KeywordTokenType("this", { startsExpr }),
super: new KeywordTokenType("super", { startsExpr }),
class: new KeywordTokenType("class", { startsExpr }),
extends: new KeywordTokenType("extends", { beforeExpr }),
export: new KeywordTokenType("export"),
import: new KeywordTokenType("import", { startsExpr }),
yield: new KeywordTokenType("yield", { beforeExpr, startsExpr }),
null: new KeywordTokenType("null", { startsExpr }),
true: new KeywordTokenType("true", { startsExpr }),
false: new KeywordTokenType("false", { startsExpr }),
in: new KeywordTokenType("in", { beforeExpr, binop: 7 }),
instanceof: new KeywordTokenType("instanceof", { beforeExpr, binop: 7 }),
typeof: new KeywordTokenType("typeof", { beforeExpr, prefix, startsExpr }),
void: new KeywordTokenType("void", { beforeExpr, prefix, startsExpr }),
delete: new KeywordTokenType("delete", { beforeExpr, prefix, startsExpr }),
};
function makeKeywordProps(
name: string,
conf: any,
): PropertyDescriptor<TokenType> {
return { value: KeywordTokenType(name, conf), enumerable: true };
}
// $FlowIssue
export const keywords = Object.create(null, {
break: makeKeywordProps("break"),
case: makeKeywordProps("case", { beforeExpr }),
catch: makeKeywordProps("catch"),
continue: makeKeywordProps("continue"),
debugger: makeKeywordProps("debugger"),
default: makeKeywordProps("default", { beforeExpr }),
do: makeKeywordProps("do", { isLoop, beforeExpr }),
else: makeKeywordProps("else", { beforeExpr }),
finally: makeKeywordProps("finally"),
for: makeKeywordProps("for", { isLoop }),
function: makeKeywordProps("function", { startsExpr }),
if: makeKeywordProps("if"),
return: makeKeywordProps("return", { beforeExpr }),
switch: makeKeywordProps("switch"),
throw: makeKeywordProps("throw", { beforeExpr, prefix, startsExpr }),
try: makeKeywordProps("try"),
var: makeKeywordProps("var"),
let: makeKeywordProps("let"),
const: makeKeywordProps("const"),
while: makeKeywordProps("while", { isLoop }),
with: makeKeywordProps("with"),
new: makeKeywordProps("new"),
this: makeKeywordProps("this", { startsExpr }),
super: makeKeywordProps("super", { startsExpr }),
class: makeKeywordProps("class", { startsExpr }),
extends: makeKeywordProps("extends", { beforeExpr }),
export: makeKeywordProps("export"),
import: makeKeywordProps("import", { startsExpr }),
yield: makeKeywordProps("yield", { beforeExpr, startsExpr }),
null: makeKeywordProps("null", { startsExpr }),
true: makeKeywordProps("true", { startsExpr }),
false: makeKeywordProps("false", { startsExpr }),
in: makeKeywordProps("in", { beforeExpr, binop: 7 }),
instanceof: makeKeywordProps("instanceof", { beforeExpr, binop: 7 }),
typeof: makeKeywordProps("typeof", { beforeExpr, prefix, startsExpr }),
void: makeKeywordProps("void", { beforeExpr, prefix, startsExpr }),
delete: makeKeywordProps("delete", { beforeExpr, prefix, startsExpr }),
});
// Map keyword names to token types.
Object.keys(keywords).forEach(name => {
types["_" + name] = keywords[name];
});
// A type for the smartPipelines plugin.
export type TopicContextState = {
// When a topic binding has been currently established,
// then this is 1. Otherwise, it is 0. This is forwards compatible
// with a future plugin for multiple lexical topics.
maxNumOfResolvableTopics: number,
// When a topic binding has been currently established, and if that binding
// has been used as a topic reference `#`, then this is 0. Otherwise, it is
// `null`. This is forwards compatible with a future plugin for multiple
// lexical topics.
maxTopicIndex: null | 0,
};

View File

@@ -1146,6 +1146,7 @@ export type TsType =
| TsIndexedAccessType
| TsMappedType
| TsLiteralType
| TsImportType
// TODO: This probably shouldn't be included here.
| TsTypePredicate;
@@ -1157,6 +1158,7 @@ export type TsKeywordTypeType =
| "TSNumberKeyword"
| "TSObjectKeyword"
| "TSBooleanKeyword"
| "TSBigIntKeyword"
| "TSStringKeyword"
| "TSSymbolKeyword"
| "TSVoidKeyword"
@@ -1200,7 +1202,7 @@ export type TsTypePredicate = TsTypeBase & {
// `typeof` operator
export type TsTypeQuery = TsTypeBase & {
type: "TSTypeQuery",
exprName: TsEntityName,
exprName: TsEntityName | TsImportType,
};
export type TsTypeLiteral = TsTypeBase & {
@@ -1285,6 +1287,13 @@ export type TsLiteralType = TsTypeBase & {
literal: NumericLiteral | StringLiteral | BooleanLiteral,
};
export type TsImportType = TsTypeBase & {
type: "TsImportType",
argument: StringLiteral,
qualifier?: TsEntityName,
typeParameters?: TsTypeParameterInstantiation,
};
// ================
// TypeScript declarations
// ================

View File

@@ -4,28 +4,72 @@
import * as charCodes from "charcodes";
function makePredicate(words: string): (str: string) => boolean {
const wordsArr = words.split(" ");
return function(str) {
return wordsArr.indexOf(str) >= 0;
};
}
// Reserved word lists for various dialects of the language
export const reservedWords = {
"6": makePredicate("enum await"),
strict: makePredicate(
"implements interface let package private protected public static yield",
),
strictBind: makePredicate("eval arguments"),
export const isES2015ReservedWord = (word: string): boolean => {
return word === "enum" || word === "await";
};
// And the keywords
const reservedWordsStrict = new Set([
"implements",
"interface",
"let",
"package",
"private",
"protected",
"public",
"static",
"yield",
]);
export function isStrictReservedWord(word: string): boolean {
return reservedWordsStrict.has(word);
}
export const isKeyword = makePredicate(
"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this let const class extends export import yield super",
);
export function isStrictBindReservedWord(word: string): boolean {
return word === "eval" || word === "arguments";
}
const keywords = new Set([
"break",
"case",
"catch",
"continue",
"debugger",
"default",
"do",
"else",
"finally",
"for",
"function",
"if",
"return",
"switch",
"throw",
"try",
"var",
"while",
"with",
"null",
"true",
"false",
"instanceof",
"typeof",
"void",
"delete",
"new",
"in",
"this",
"let",
"const",
"class",
"extends",
"export",
"import",
"yield",
"super",
]);
export function isKeyword(word: string): boolean {
return keywords.has(word);
}
// ## Character categories
@@ -64,7 +108,7 @@ const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,1
// rare.
function isInAstralSet(code: number, set: $ReadOnlyArray<number>): boolean {
let pos = 0x10000;
for (let i = 0; i < set.length; i += 2) {
for (let i = 0, length = set.length; i < length; i += 2) {
pos += set[i];
if (pos > code) return false;

View File

@@ -4,7 +4,7 @@ import * as charCodes from "charcodes";
// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.
export const lineBreak = /\r\n?|\n|\u2028|\u2029/;
export const lineBreak = /\r\n?|[\n\u2028\u2029]/;
export const lineBreakG = new RegExp(lineBreak.source, "g");
// https://tc39.github.io/ecma262/#sec-line-terminators

View File

@@ -0,0 +1,3 @@
{
"throws": "Function declaration not allowed in this context (1:10)"
}

View File

@@ -0,0 +1 @@
while (1) foo: bar: function foo(){}

View File

@@ -0,0 +1,3 @@
{
"throws": "Function declaration not allowed in this context (1:20)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Rest parameter must be last formal parameter (1:18)"
"throws": "The rest parameter must be the last parameter (1:18)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Rest parameter must be last formal parameter (3:13)"
"throws": "The rest parameter must be the last parameter (3:13)"
}

View File

@@ -0,0 +1 @@
[...a,] = [];

View File

@@ -0,0 +1 @@
[...a,];

View File

@@ -0,0 +1,99 @@
{
"type": "File",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"program": {
"type": "Program",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"expression": {
"type": "ArrayExpression",
"start": 0,
"end": 7,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 7
}
},
"elements": [
{
"type": "SpreadElement",
"start": 1,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 5
}
},
"argument": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "a"
},
"name": "a"
}
}
]
}
}
],
"directives": []
}
}

View File

@@ -1,3 +1,3 @@
{
"throws": "The rest element has to be the last element when destructuring (1:1)"
"throws": "The rest element must be the last element (1:1)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "A trailing comma is not permitted after the rest element (1:8)"
"throws": "A trailing comma is not permitted after the rest parameter (1:8)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Rest parameter must be last formal parameter (3:13)"
"throws": "The rest parameter must be the last parameter (3:13)"
}

View File

@@ -0,0 +1,4 @@
class C extends (function B() {
with ({});
return B;
}()) {}

View File

@@ -0,0 +1,3 @@
{
"throws": "'with' in strict mode (2:2)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Rest parameter must be last formal parameter (1:18)"
"throws": "The rest parameter must be the last parameter (1:18)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Rest parameter must be last formal parameter (1:5)"
"throws": "The rest parameter must be the last parameter (1:5)"
}

View File

@@ -1 +0,0 @@
[...a, ] = b

View File

@@ -1,132 +0,0 @@
{
"type": "File",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"program": {
"type": "Program",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"expression": {
"type": "AssignmentExpression",
"start": 0,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 12
}
},
"operator": "=",
"left": {
"type": "ArrayPattern",
"start": 0,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 8
}
},
"elements": [
{
"type": "RestElement",
"start": 1,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 5
}
},
"argument": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "a"
},
"name": "a"
}
}
]
},
"right": {
"type": "Identifier",
"start": 11,
"end": 12,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 12
},
"identifierName": "b"
},
"name": "b"
}
}
}
],
"directives": []
}
}

View File

@@ -1,3 +0,0 @@
{
"throws": "Unexpected token (1:10)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \"{\" (1:22)"
"throws": "yield is a reserved word in strict mode (1:16)"
}

View File

@@ -1,4 +1,4 @@
{
"sourceType": "module",
"throws": "Unexpected token, expected \"function\" (1:21)"
"throws": "Unexpected token, expected \"=>\" (1:31)"
}

View File

@@ -0,0 +1 @@
while (1) async function foo(){}

View File

@@ -0,0 +1,3 @@
{
"throws": "Function declaration not allowed in this context (1:10)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "A trailing comma is not permitted after the rest element (1:11)"
"throws": "A trailing comma is not permitted after the rest parameter (1:11)"
}

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