Compare commits
138 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d896ce2b53 | ||
|
|
44d8a59361 | ||
|
|
344d35bbe9 | ||
|
|
fe71154626 | ||
|
|
65cbbc1ef8 | ||
|
|
d37c958637 | ||
|
|
9eb010da50 | ||
|
|
7e9029e337 | ||
|
|
00c3e3c8e0 | ||
|
|
7192546eb8 | ||
|
|
4c4c22a316 | ||
|
|
56044c7851 | ||
|
|
828169e611 | ||
|
|
1452e977a0 | ||
|
|
ede69eef7f | ||
|
|
03230eaa9c | ||
|
|
7dc157f9be | ||
|
|
854313a759 | ||
|
|
46ba5940c2 | ||
|
|
42c5d3fc4b | ||
|
|
d4e045ac24 | ||
|
|
8bc9f9a05f | ||
|
|
93e1b5e612 | ||
|
|
4f69699b71 | ||
|
|
f4f5ca2aaa | ||
|
|
8071dca9ad | ||
|
|
178f2d7949 | ||
|
|
65febdd13a | ||
|
|
f77c450cda | ||
|
|
f2af6c1170 | ||
|
|
43b83f8ed7 | ||
|
|
af88e63dff | ||
|
|
f6ee26c3da | ||
|
|
e8de6fa5d4 | ||
|
|
3ae5e79ec8 | ||
|
|
e9331aa0c0 | ||
|
|
ba4141934f | ||
|
|
96a7343142 | ||
|
|
a2e6d8e968 | ||
|
|
4ce37b7aca | ||
|
|
b92ad318f1 | ||
|
|
2d6231fd3d | ||
|
|
4e5e319d5b | ||
|
|
b66d921053 | ||
|
|
f12905b531 | ||
|
|
f216975378 | ||
|
|
3a3d5cbe9c | ||
|
|
10555c719e | ||
|
|
58768072ef | ||
|
|
455e003567 | ||
|
|
49f7bcf271 | ||
|
|
c2e41588aa | ||
|
|
a1eac37bd2 | ||
|
|
0370af58f1 | ||
|
|
8df0500f55 | ||
|
|
e4b8cfc768 | ||
|
|
a7757ec4d0 | ||
|
|
25a8db2a29 | ||
|
|
48fd387779 | ||
|
|
59c4bbb4ab | ||
|
|
2dc1c91955 | ||
|
|
ae154c86ed | ||
|
|
e9588061d7 | ||
|
|
0a88230ec4 | ||
|
|
a27b9b4299 | ||
|
|
aaec2cd51d | ||
|
|
34c9890f41 | ||
|
|
e8038863c3 | ||
|
|
694e3fd8cf | ||
|
|
40ae6568a4 | ||
|
|
4944e9e180 | ||
|
|
a24206eb96 | ||
|
|
d6b4ab75ee | ||
|
|
3e4b608a80 | ||
|
|
28319eb07e | ||
|
|
5889620a6a | ||
|
|
9764718c32 | ||
|
|
28b70e5910 | ||
|
|
4c2f8d9337 | ||
|
|
2cc0376756 | ||
|
|
8e051cae46 | ||
|
|
778a61a3c2 | ||
|
|
46e3f6df1f | ||
|
|
03022d169e | ||
|
|
9803253363 | ||
|
|
a55382e4ad | ||
|
|
b211b810d1 | ||
|
|
25e880d355 | ||
|
|
e43777bb5f | ||
|
|
efc60a1703 | ||
|
|
54f072991d | ||
|
|
a58893d1e3 | ||
|
|
865eb93c2d | ||
|
|
49f52bbcb3 | ||
|
|
9d1d0fe57a | ||
|
|
ea1c436ea1 | ||
|
|
3f9a1c08cc | ||
|
|
c586d4e8ca | ||
|
|
60ffe1d103 | ||
|
|
b5177ce290 | ||
|
|
d1aa665657 | ||
|
|
f130981546 | ||
|
|
bc347bab7a | ||
|
|
21228abfde | ||
|
|
e417437355 | ||
|
|
0bb720401b | ||
|
|
d35f2ad92b | ||
|
|
57759cb1a1 | ||
|
|
9e95da4eaa | ||
|
|
911c2d0bf4 | ||
|
|
116ca22def | ||
|
|
52fb884550 | ||
|
|
5cb38995c0 | ||
|
|
3c8e15dbc1 | ||
|
|
c1499b13ac | ||
|
|
7bcd62cfee | ||
|
|
47da5cf75a | ||
|
|
72471aff63 | ||
|
|
b9340bc597 | ||
|
|
731182eee4 | ||
|
|
f4eec5ca79 | ||
|
|
b60adce4cb | ||
|
|
66c4bc8f64 | ||
|
|
d2dc28ed2b | ||
|
|
0514a9f903 | ||
|
|
d1d3c823cc | ||
|
|
9b005dedfd | ||
|
|
4fdb71151f | ||
|
|
f611bb016b | ||
|
|
4dff205dc1 | ||
|
|
72fd2d192c | ||
|
|
35815832b5 | ||
|
|
9c45b8faf7 | ||
|
|
ca2918ab13 | ||
|
|
d915f31bcb | ||
|
|
4ca35ef8b9 | ||
|
|
4b73818c87 | ||
|
|
d305419da6 |
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
13
.flowconfig
13
.flowconfig
@@ -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
|
||||
|
||||
9
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
9
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -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**
|
||||
|
||||
7
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
7
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@@ -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: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/Regression-v7.md
vendored
10
.github/ISSUE_TEMPLATE/Regression-v7.md
vendored
@@ -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**
|
||||
|
||||
7
.github/ISSUE_TEMPLATE/Support_question.md
vendored
7
.github/ISSUE_TEMPLATE/Support_question.md
vendored
@@ -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: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/Support_us.md
vendored
8
.github/ISSUE_TEMPLATE/Support_us.md
vendored
@@ -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: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
18
.github/actions/trigger-github-release/Dockerfile
vendored
Normal file
18
.github/actions/trigger-github-release/Dockerfile
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM node:10
|
||||
|
||||
LABEL "name" = "trigger-github-release"
|
||||
LABEL "version" = "0.0.1"
|
||||
|
||||
LABEL "com.github.actions.name" = "Trigger GitHub release"
|
||||
LABEL "com.github.actions.description" = "Trigger a new GitHub release and generate the changelog using lerna-changelog."
|
||||
LABEL "com.github.actions.icon" = "tag"
|
||||
LABEL "com.github.actions.color" = "yellow"
|
||||
|
||||
ADD entrypoint.sh /action/entrypoint.sh
|
||||
ADD package.json /action/package.json
|
||||
ADD package-lock.json /action/package-lock.json
|
||||
ADD release.js /action/release.js
|
||||
|
||||
RUN chmod +x /action/entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/action/entrypoint.sh"]
|
||||
29
.github/actions/trigger-github-release/entrypoint.sh
vendored
Executable file
29
.github/actions/trigger-github-release/entrypoint.sh
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "INFO: Installing action dependencies..."
|
||||
(cd /action; npm ci)
|
||||
|
||||
echo "INFO: Checking out current tag..."
|
||||
git -c advice.detachedHead=false checkout $GITHUB_REF
|
||||
|
||||
echo "INFO: Getting tag info..."
|
||||
current_tag=$(git describe --abbrev=0 --tags)
|
||||
last_tag=$(git describe --abbrev=0 --tags HEAD^)
|
||||
echo "INFO: New version is $current_tag; last version is $last_tag."
|
||||
|
||||
echo "INFO: Generating the changelog..."
|
||||
|
||||
# lerna-changelog expects the token to be provided as GITHUB_AUTH,
|
||||
# but GitHub actions don't allow to predefine custom env vars prefixed with
|
||||
# GITHUB_. We need to define it here.
|
||||
changelog=$(
|
||||
GITHUB_AUTH="$GITHUB_TOKEN" \
|
||||
node /action/node_modules/.bin/lerna-changelog --tag-from $last_tag --tag-to $current_tag
|
||||
)
|
||||
|
||||
echo "INFO: Publishing the new GitHub release..."
|
||||
echo "$changelog" | node /action/release $current_tag
|
||||
|
||||
echo "INFO: Done! Don't forget to thank new contributors :)"
|
||||
1415
.github/actions/trigger-github-release/package-lock.json
generated
vendored
Normal file
1415
.github/actions/trigger-github-release/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
.github/actions/trigger-github-release/package.json
vendored
Normal file
12
.github/actions/trigger-github-release/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@internal/trigger-github-release",
|
||||
"version": "0.0.1",
|
||||
"author": "Nicolò Ribaudo <nicolo.ribaudo@gmail.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/rest": "^16.3.0",
|
||||
"get-stdin": "^6.0.0",
|
||||
"lerna-changelog": "^0.8.2"
|
||||
}
|
||||
}
|
||||
25
.github/actions/trigger-github-release/release.js
vendored
Normal file
25
.github/actions/trigger-github-release/release.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
|
||||
const [ /* node */, /* file */, tag ] = process.argv;
|
||||
|
||||
const getStdin = require("get-stdin");
|
||||
const octokit = require("@octokit/rest")();
|
||||
|
||||
octokit.authenticate({
|
||||
type: "token",
|
||||
token: process.env.GITHUB_TOKEN
|
||||
});
|
||||
|
||||
const [ repoOwner, repoName ] = process.env.GITHUB_REPOSITORY.split("/");
|
||||
|
||||
getStdin()
|
||||
.then(changelog => octokit.repos.createRelease({
|
||||
owner: repoOwner,
|
||||
repo: repoName,
|
||||
tag_name: tag,
|
||||
body: changelog,
|
||||
}))
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
26
.github/main.workflow
vendored
Normal file
26
.github/main.workflow
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
workflow "Release" {
|
||||
on = "push"
|
||||
resolves = ["Trigger GitHub release"]
|
||||
}
|
||||
|
||||
action "Trigger GitHub release" {
|
||||
uses = "./.github/actions/trigger-github-release/"
|
||||
secrets = ["GITHUB_TOKEN"]
|
||||
|
||||
# When GitHub Actions will support the "release" event for public
|
||||
# repositories, we won't need these checks anymore.
|
||||
needs = [
|
||||
"Is version tag",
|
||||
"On master branch",
|
||||
]
|
||||
}
|
||||
|
||||
action "Is version tag" {
|
||||
uses = "actions/bin/filter@master"
|
||||
args = "tag v*"
|
||||
}
|
||||
|
||||
action "On master branch" {
|
||||
uses = "actions/bin/filter@master"
|
||||
args = "branch master"
|
||||
}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.DS_Store
|
||||
/node_modules
|
||||
/.github/actions/*/node_modules
|
||||
/packages/*/node_modules
|
||||
/packages/*/LICENSE
|
||||
!/packages/babel-parser/LICENSE
|
||||
@@ -15,6 +16,7 @@ coverage
|
||||
dist
|
||||
/.package.json
|
||||
package-lock.json
|
||||
!/.github/actions/*/package-lock.json
|
||||
|
||||
/packages/babel-runtime/helpers/*.js
|
||||
!/packages/babel-runtime/helpers/toArray.js
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
package.json
|
||||
packages/babel-preset-env/data
|
||||
packages/*/test/fixtures/**/input.*
|
||||
packages/*/test/fixtures/**/exec.*
|
||||
packages/*/test/fixtures/**/output.*
|
||||
|
||||
16
.travis.yml
16
.travis.yml
@@ -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
|
||||
|
||||
158
CHANGELOG.md
158
CHANGELOG.md
@@ -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`).
|
||||
|
||||
@@ -6,7 +6,7 @@ const chalk = require("chalk");
|
||||
const newer = require("gulp-newer");
|
||||
const babel = require("gulp-babel");
|
||||
const gulpWatch = require("gulp-watch");
|
||||
const gutil = require("gulp-util");
|
||||
const fancyLog = require("fancy-log");
|
||||
const filter = require("gulp-filter");
|
||||
const gulp = require("gulp");
|
||||
const path = require("path");
|
||||
@@ -38,7 +38,7 @@ function getIndexFromPackage(name) {
|
||||
|
||||
function compilationLogger(rollup) {
|
||||
return through.obj(function(file, enc, callback) {
|
||||
gutil.log(
|
||||
fancyLog(
|
||||
`Compiling '${chalk.cyan(file.relative)}'${
|
||||
rollup ? " with rollup " : ""
|
||||
}...`
|
||||
@@ -50,7 +50,7 @@ function compilationLogger(rollup) {
|
||||
function errorsLogger() {
|
||||
return plumber({
|
||||
errorHandler(err) {
|
||||
gutil.log(err.stack);
|
||||
fancyLog(err.stack);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -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
|
||||
|
||||
24
Makefile
24
Makefile
@@ -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
|
||||
|
||||
32
README.md
32
README.md
@@ -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?
|
||||
|
||||
|
||||
@@ -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":
|
||||
|
||||
15
lerna.json
15
lerna.json
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"lerna": "2.11.0",
|
||||
"version": "7.2.1",
|
||||
"version": "7.3.2",
|
||||
"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": [
|
||||
|
||||
74
package.json
74
package.json
@@ -9,55 +9,54 @@
|
||||
"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.3",
|
||||
"@babel/core": "^7.2.2",
|
||||
"@babel/eslint-plugin-development": "^1.0.1",
|
||||
"@babel/plugin-proposal-class-properties": "^7.3.0",
|
||||
"@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.3.1",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"@babel/runtime": "^7.1.5",
|
||||
"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",
|
||||
"browserify": "^16.2.2",
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"babel-eslint": "^11.0.0-beta.0",
|
||||
"babel-jest": "^24.0.0",
|
||||
"babel-loader": "^8.0.5",
|
||||
"babel-plugin-transform-charcodes": "^0.2.0",
|
||||
"browserify": "^16.2.3",
|
||||
"bundle-collapser": "^1.2.1",
|
||||
"chalk": "^2.3.2",
|
||||
"charcodes": "^0.1.0",
|
||||
"charcodes": "^0.2.0",
|
||||
"derequire": "^2.0.2",
|
||||
"enhanced-resolve": "^3.0.0",
|
||||
"eslint": "^5.9.0",
|
||||
"eslint": "^5.12.1",
|
||||
"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",
|
||||
"graceful-fs": "^4.1.11",
|
||||
"eslint-plugin-flowtype": "^3.2.1",
|
||||
"eslint-plugin-prettier": "^3.0.1",
|
||||
"fancy-log": "^1.3.3",
|
||||
"flow-bin": "^0.87.0",
|
||||
"graceful-fs": "^4.1.15",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-babel": "^8.0.0",
|
||||
"gulp-filter": "^5.1.0",
|
||||
"gulp-newer": "^1.0.0",
|
||||
"gulp-plumber": "^1.2.0",
|
||||
"gulp-plumber": "^1.2.1",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-uglify": "^3.0.1",
|
||||
"gulp-util": "^3.0.7",
|
||||
"gulp-watch": "^5.0.1",
|
||||
"husky": "^1.2.0",
|
||||
"jest": "^23.6.0",
|
||||
"lerna": "^2.11.0",
|
||||
"husky": "^1.3.1",
|
||||
"jest": "^24.0.0",
|
||||
"lerna": "^3.6.0",
|
||||
"lerna-changelog": "^0.5.0",
|
||||
"lint-staged": "^8.1.0",
|
||||
"lodash": "^4.17.10",
|
||||
"lodash": "^4.17.11",
|
||||
"merge-stream": "^1.0.1",
|
||||
"output-file-sync": "^2.0.0",
|
||||
"prettier": "^1.15.2",
|
||||
"prettier": "^1.16.1",
|
||||
"pump": "^3.0.0",
|
||||
"rimraf": "^2.4.3",
|
||||
"rimraf": "^2.6.3",
|
||||
"rollup-plugin-babel": "^4.0.0-beta.0",
|
||||
"rollup-plugin-node-resolve": "^3.0.2",
|
||||
"rollup-stream": "^1.24.1",
|
||||
@@ -69,6 +68,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",
|
||||
@@ -105,7 +107,9 @@
|
||||
"_browser\\.js"
|
||||
],
|
||||
"testEnvironment": "node",
|
||||
"setupTestFrameworkScriptFile": "<rootDir>/test/testSetupFile.js",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/test/testSetupFile.js"
|
||||
],
|
||||
"transformIgnorePatterns": [
|
||||
"/node_modules/",
|
||||
"<rootDir>/packages/babel-standalone/babel(\\.min)?\\.js",
|
||||
@@ -124,6 +128,10 @@
|
||||
"/test/tmp/",
|
||||
"/test/__data__/",
|
||||
"<rootDir>/build/"
|
||||
]
|
||||
}
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^@babel/([a-zA-Z0-9_-]+)$": "<rootDir>/packages/babel-$1/"
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
@@ -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/",
|
||||
|
||||
@@ -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. " +
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/generator",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.2",
|
||||
"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.2",
|
||||
"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.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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("#");
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
type A = interface { p: string };
|
||||
type B = interface extends X { p: string };
|
||||
type C = interface extends X, Y { p: string };
|
||||
type D = interface extends X.Y<Z> { p: string };
|
||||
|
||||
@@ -6,4 +6,7 @@ type B = interface extends X {
|
||||
};
|
||||
type C = interface extends X, Y {
|
||||
p: string
|
||||
};
|
||||
};
|
||||
type D = interface extends X.Y<Z> {
|
||||
p: string
|
||||
};
|
||||
|
||||
@@ -14,3 +14,5 @@ type overloads =
|
||||
;
|
||||
|
||||
type func = string => string;
|
||||
|
||||
type D = X.Y<Z>;
|
||||
|
||||
@@ -9,3 +9,4 @@ type union = {
|
||||
};
|
||||
type overloads = (x: string) => number & (x: number) => string;
|
||||
type func = (string) => string;
|
||||
type D = X.Y<Z>;
|
||||
|
||||
1
packages/babel-generator/test/fixtures/types/PipelineBareFunction/input.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/types/PipelineBareFunction/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
let result = "hello" |> doubleSay |> text.capitalize |> a.b.exclaim;
|
||||
3
packages/babel-generator/test/fixtures/types/PipelineBareFunction/options.json
vendored
Normal file
3
packages/babel-generator/test/fixtures/types/PipelineBareFunction/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["pipelineOperator", { "proposal": "smart" }], "doExpressions"]
|
||||
}
|
||||
1
packages/babel-generator/test/fixtures/types/PipelineBareFunction/output.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/types/PipelineBareFunction/output.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
let result = "hello" |> doubleSay |> text.capitalize |> a.b.exclaim;
|
||||
8
packages/babel-generator/test/fixtures/types/PipelineTopicExpression/input.js
vendored
Normal file
8
packages/babel-generator/test/fixtures/types/PipelineTopicExpression/input.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
value |> # + 1;
|
||||
value |> 1 + #;
|
||||
value |> do {
|
||||
#;
|
||||
};
|
||||
value |> do {
|
||||
if (yes) #;
|
||||
};
|
||||
3
packages/babel-generator/test/fixtures/types/PipelineTopicExpression/options.json
vendored
Normal file
3
packages/babel-generator/test/fixtures/types/PipelineTopicExpression/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["pipelineOperator", { "proposal": "smart" }], "doExpressions"]
|
||||
}
|
||||
8
packages/babel-generator/test/fixtures/types/PipelineTopicExpression/output.js
vendored
Normal file
8
packages/babel-generator/test/fixtures/types/PipelineTopicExpression/output.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
value |> # + 1;
|
||||
value |> 1 + #;
|
||||
value |> do {
|
||||
#;
|
||||
};
|
||||
value |> do {
|
||||
if (yes) #;
|
||||
};
|
||||
3
packages/babel-generator/test/fixtures/typescript/types-import-type/input.js
vendored
Normal file
3
packages/babel-generator/test/fixtures/typescript/types-import-type/input.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
let x: typeof import('./x');
|
||||
let Y: import('./y').Y;
|
||||
let z: import("/z").foo.bar<string>;
|
||||
3
packages/babel-generator/test/fixtures/typescript/types-import-type/output.js
vendored
Normal file
3
packages/babel-generator/test/fixtures/typescript/types-import-type/output.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
let x: typeof import('./x');
|
||||
let Y: import('./y').Y;
|
||||
let z: import("/z").foo.bar<string>;
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
# @babel/plugin-class-features
|
||||
# @babel/helper-create-class-features-plugin
|
||||
|
||||
> Compile class public and private fields, private methods and decorators to ES6
|
||||
|
||||
See our website [@babel/plugin-class-features](https://babeljs.io/docs/en/next/babel-plugin-class-features.html) for more information.
|
||||
See our website [@babel/helper-create-class-features-plugin](https://babeljs.io/docs/en/next/babel-helper-create-class-features-plugin.html) for more information.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/plugin-class-features
|
||||
npm install --save-dev @babel/helper-create-class-features-plugin
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/plugin-class-features --dev
|
||||
yarn add @babel/helper-create-class-features-plugin --dev
|
||||
```
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "@babel/helper-create-class-features-plugin",
|
||||
"version": "7.2.1",
|
||||
"version": "7.3.2",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { hasDecorators } from "./decorators";
|
||||
import { hasOwnDecorators } from "./decorators";
|
||||
|
||||
export const FEATURES = Object.freeze({
|
||||
//classes: 1 << 0,
|
||||
@@ -39,14 +39,26 @@ 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 (hasFeature(file, FEATURES.decorators)) {
|
||||
throw new Error(
|
||||
"@babel/plugin-class-features doesn't support decorators yet.",
|
||||
);
|
||||
if (path.isPrivate()) {
|
||||
throw path.buildCodeFrameError(
|
||||
`Private ${
|
||||
path.isClassMethod() ? "methods" : "fields"
|
||||
} in decorated classes are not supported yet.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: We can't use path.isPrivateMethod() because it isn't supported in <7.2.0
|
||||
@@ -60,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 (
|
||||
|
||||
@@ -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.isMethod(),
|
||||
methodId: prop.isMethod()
|
||||
? 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,43 @@ function buildPublicFieldInitSpec(ref, prop, state) {
|
||||
}
|
||||
|
||||
function buildPrivateInstanceMethodDeclaration(prop, privateNamesMap) {
|
||||
const { methodId } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const { params, body } = prop.node;
|
||||
const methodValue = t.functionExpression(methodId, params, body);
|
||||
const privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||
const {
|
||||
methodId,
|
||||
getId,
|
||||
setId,
|
||||
getterDeclared,
|
||||
setterDeclared,
|
||||
} = privateName;
|
||||
const { params, body, generator, async } = prop.node;
|
||||
const methodValue = t.functionExpression(
|
||||
methodId,
|
||||
params,
|
||||
body,
|
||||
generator,
|
||||
async,
|
||||
);
|
||||
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,6 +454,7 @@ export function buildFieldsInitNodes(
|
||||
) {
|
||||
const staticNodes = [];
|
||||
const instanceNodes = [];
|
||||
let needsClassRef = false;
|
||||
|
||||
for (const prop of props) {
|
||||
const isStatic = prop.node.static;
|
||||
@@ -329,19 +466,23 @@ export function buildFieldsInitNodes(
|
||||
|
||||
switch (true) {
|
||||
case isStatic && isPrivate && isField && loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(
|
||||
buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case isStatic && isPrivate && isField && !loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(
|
||||
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case isStatic && isPublic && isField && loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop));
|
||||
break;
|
||||
case isStatic && isPublic && isField && !loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(
|
||||
buildPublicFieldInitSpec(t.cloneNode(ref), prop, state),
|
||||
);
|
||||
@@ -361,7 +502,7 @@ export function buildFieldsInitNodes(
|
||||
);
|
||||
break;
|
||||
case isInstance && isPrivate && isMethod && loose:
|
||||
instanceNodes.push(
|
||||
instanceNodes.unshift(
|
||||
buildPrivateMethodInitLoose(
|
||||
t.thisExpression(),
|
||||
prop,
|
||||
@@ -373,7 +514,7 @@ export function buildFieldsInitNodes(
|
||||
);
|
||||
break;
|
||||
case isInstance && isPrivate && isMethod && !loose:
|
||||
instanceNodes.push(
|
||||
instanceNodes.unshift(
|
||||
buildPrivateInstanceMethodInitSpec(
|
||||
t.thisExpression(),
|
||||
prop,
|
||||
@@ -397,5 +538,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;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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.isPrivate()) {
|
||||
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";
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
const sym = Symbol();
|
||||
const sym1 = Symbol();
|
||||
|
||||
class A {
|
||||
[sym]: A.B;
|
||||
[sym1]: Array<A>;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["flow"],
|
||||
"plugins": ["proposal-class-properties"]
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
const sym = Symbol();
|
||||
|
||||
class A {
|
||||
[sym]: A;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["flow"],
|
||||
"plugins": ["proposal-class-properties"]
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/helpers",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.1",
|
||||
"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"
|
||||
|
||||
@@ -1048,7 +1048,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 +1062,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 +1223,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 +1663,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 +1677,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 +1705,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 +1766,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 +1777,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 +1793,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);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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'.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> A JavaScript parser
|
||||
|
||||
See our website [@babel/parser](https://babeljs.io/docs/en/next/babel-parser.html) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20babylon%22+is%3Aopen) associated with this package.
|
||||
See our website [@babel/parser](https://babeljs.io/docs/en/next/babel-parser.html) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A+parser+%28babylon%29%22+is%3Aopen) associated with this package.
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/parser",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.2",
|
||||
"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"
|
||||
|
||||
@@ -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) + ";"
|
||||
);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import type { Options } from "../options";
|
||||
import { reservedWords } from "../util/identifier";
|
||||
|
||||
import type State from "../tokenizer/state";
|
||||
import type { PluginsMap } from "./index";
|
||||
|
||||
@@ -16,21 +14,13 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
import { types as tt, type TokenType } from "../tokenizer/types";
|
||||
import * as N from "../types";
|
||||
import LValParser from "./lval";
|
||||
import { reservedWords } from "../util/identifier";
|
||||
import {
|
||||
isKeyword,
|
||||
isReservedWord,
|
||||
isStrictReservedWord,
|
||||
isStrictBindReservedWord,
|
||||
} from "../util/identifier";
|
||||
import type { Pos, Position } from "../util/location";
|
||||
import * as charCodes from "charcodes";
|
||||
|
||||
@@ -122,14 +127,23 @@ export default class ExpressionParser extends LValParser {
|
||||
): N.Expression {
|
||||
const startPos = this.state.start;
|
||||
const startLoc = this.state.startLoc;
|
||||
if (this.match(tt._yield) && this.state.inGenerator) {
|
||||
let left = this.parseYield();
|
||||
if (afterLeftParse) {
|
||||
left = afterLeftParse.call(this, left, startPos, startLoc);
|
||||
if (this.isContextual("yield")) {
|
||||
if (this.state.inGenerator) {
|
||||
let left = this.parseYield(noIn);
|
||||
if (afterLeftParse) {
|
||||
left = afterLeftParse.call(this, left, startPos, startLoc);
|
||||
}
|
||||
return left;
|
||||
} else {
|
||||
// The tokenizer will assume an expression is allowed after
|
||||
// `yield`, but this isn't that kind of yield
|
||||
this.state.exprAllowed = false;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
|
||||
this.state.commaAfterSpreadAt = -1;
|
||||
|
||||
let failOnShorthandAssign;
|
||||
if (refShorthandDefaultPos) {
|
||||
failOnShorthandAssign = false;
|
||||
@@ -138,7 +152,7 @@ export default class ExpressionParser extends LValParser {
|
||||
failOnShorthandAssign = true;
|
||||
}
|
||||
|
||||
if (this.match(tt.parenL) || this.match(tt.name) || this.match(tt._yield)) {
|
||||
if (this.match(tt.parenL) || this.match(tt.name)) {
|
||||
this.state.potentialArrowAt = this.state.start;
|
||||
}
|
||||
|
||||
@@ -169,21 +183,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 +210,8 @@ export default class ExpressionParser extends LValParser {
|
||||
this.unexpected(refShorthandDefaultPos.start);
|
||||
}
|
||||
|
||||
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
@@ -398,7 +419,13 @@ export default class ExpressionParser extends LValParser {
|
||||
// Parse unary operators, both prefix and postfix.
|
||||
|
||||
parseMaybeUnary(refShorthandDefaultPos: ?Pos): N.Expression {
|
||||
if (this.state.type.prefix) {
|
||||
if (
|
||||
this.isContextual("await") &&
|
||||
(this.state.inAsync ||
|
||||
(!this.state.inFunction && this.options.allowAwaitOutsideFunction))
|
||||
) {
|
||||
return this.parseAwait();
|
||||
} else if (this.state.type.prefix) {
|
||||
const node = this.startNode();
|
||||
const update = this.match(tt.incDec);
|
||||
node.operator = this.state.value;
|
||||
@@ -515,7 +542,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;
|
||||
}
|
||||
@@ -570,9 +597,11 @@ export default class ExpressionParser extends LValParser {
|
||||
return this.finishNode(node, "MemberExpression");
|
||||
} else if (!noCalls && this.match(tt.parenL)) {
|
||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
const oldYieldPos = this.state.yieldPos;
|
||||
const oldAwaitPos = this.state.awaitPos;
|
||||
this.state.maybeInArrowParameters = true;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.state.yieldPos = 0;
|
||||
this.state.awaitPos = 0;
|
||||
|
||||
const possibleAsync = this.atPossibleAsync(base);
|
||||
this.next();
|
||||
@@ -580,15 +609,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,28 +626,26 @@ 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),
|
||||
node,
|
||||
);
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
this.checkYieldAwaitInDefaultParams();
|
||||
this.state.yieldPos = oldYieldPos;
|
||||
this.state.awaitPos = oldAwaitPos;
|
||||
} else {
|
||||
this.toReferencedListDeep(node.arguments);
|
||||
|
||||
// We keep the old value if it isn't null, for cases like
|
||||
// (x = async(yield)) => {}
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters =
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP;
|
||||
this.state.yieldPos = oldYieldPos || this.state.yieldPos;
|
||||
this.state.awaitPos = oldAwaitPos || this.state.awaitPos;
|
||||
}
|
||||
|
||||
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
||||
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
|
||||
|
||||
return node;
|
||||
} else if (this.match(tt.backQuote)) {
|
||||
@@ -700,7 +725,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 +736,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 +758,6 @@ export default class ExpressionParser extends LValParser {
|
||||
false,
|
||||
possibleAsyncArrow ? { start: 0 } : undefined,
|
||||
possibleAsyncArrow ? { start: 0 } : undefined,
|
||||
possibleAsyncArrow ? refTrailingCommaPos : undefined,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -826,29 +858,12 @@ export default class ExpressionParser extends LValParser {
|
||||
this.next();
|
||||
return this.finishNode(node, "ThisExpression");
|
||||
|
||||
case tt._yield:
|
||||
if (this.state.inGenerator) this.unexpected();
|
||||
|
||||
case tt.name: {
|
||||
node = this.startNode();
|
||||
const allowAwait =
|
||||
this.state.value === "await" &&
|
||||
(this.state.inAsync ||
|
||||
(!this.state.inFunction && this.options.allowAwaitOutsideFunction));
|
||||
|
||||
const containsEsc = this.state.containsEsc;
|
||||
const allowYield = this.shouldAllowYieldIdentifier();
|
||||
const id = this.parseIdentifier(allowAwait || allowYield);
|
||||
const id = this.parseIdentifier();
|
||||
|
||||
if (id.name === "await") {
|
||||
if (
|
||||
this.state.inAsync ||
|
||||
this.inModule ||
|
||||
(!this.state.inFunction && this.options.allowAwaitOutsideFunction)
|
||||
) {
|
||||
return this.parseAwait(node);
|
||||
}
|
||||
} else if (
|
||||
if (
|
||||
!containsEsc &&
|
||||
id.name === "async" &&
|
||||
this.match(tt._function) &&
|
||||
@@ -858,28 +873,23 @@ 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;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.state.inAsync = true;
|
||||
const params = [this.parseIdentifier()];
|
||||
this.expect(tt.arrow);
|
||||
// let foo = async bar => {};
|
||||
this.parseArrowExpression(node, params, true);
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
this.state.inAsync = oldInAsync;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.parseArrowExpression(node, [id]);
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
if (canBeArrow && this.match(tt.arrow) && !this.canInsertSemicolon()) {
|
||||
this.next();
|
||||
this.parseArrowExpression(node, [id], false);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1135,7 +1145,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);
|
||||
@@ -1156,9 +1170,11 @@ export default class ExpressionParser extends LValParser {
|
||||
this.expect(tt.parenL);
|
||||
|
||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
const oldYieldPos = this.state.yieldPos;
|
||||
const oldAwaitPos = this.state.awaitPos;
|
||||
this.state.maybeInArrowParameters = true;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.state.yieldPos = 0;
|
||||
this.state.awaitPos = 0;
|
||||
|
||||
const innerStartPos = this.state.start;
|
||||
const innerStartLoc = this.state.startLoc;
|
||||
@@ -1192,14 +1208,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 {
|
||||
@@ -1226,21 +1235,23 @@ export default class ExpressionParser extends LValParser {
|
||||
this.shouldParseArrow() &&
|
||||
(arrowNode = this.parseArrow(arrowNode))
|
||||
) {
|
||||
this.checkYieldAwaitInDefaultParams();
|
||||
this.state.yieldPos = oldYieldPos;
|
||||
this.state.awaitPos = oldAwaitPos;
|
||||
for (const param of exprList) {
|
||||
if (param.extra && param.extra.parenthesized) {
|
||||
this.unexpected(param.extra.parenStart);
|
||||
}
|
||||
}
|
||||
|
||||
this.parseArrowExpression(arrowNode, exprList);
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = oldYOAIPAP;
|
||||
this.parseArrowExpression(arrowNode, exprList, false);
|
||||
return arrowNode;
|
||||
}
|
||||
|
||||
// We keep the old value if it isn't null, for cases like
|
||||
// (x = (yield)) => {}
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters =
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters || oldYOAIPAP;
|
||||
this.state.yieldPos = oldYieldPos || this.state.yieldPos;
|
||||
this.state.awaitPos = oldAwaitPos || this.state.awaitPos;
|
||||
|
||||
if (!exprList.length) {
|
||||
this.unexpected(this.state.lastTokStart);
|
||||
@@ -1312,7 +1323,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 +1334,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 +1372,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 +1412,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 +1447,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 +1511,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,
|
||||
@@ -1734,21 +1719,28 @@ export default class ExpressionParser extends LValParser {
|
||||
const oldInMethod = this.state.inMethod;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
const oldInGenerator = this.state.inGenerator;
|
||||
const oldYieldPos = this.state.yieldPos;
|
||||
const oldAwaitPos = this.state.awaitPos;
|
||||
this.state.inFunction = true;
|
||||
this.state.inMethod = node.kind || true;
|
||||
this.state.inAsync = isAsync;
|
||||
this.state.inGenerator = isGenerator;
|
||||
this.state.yieldPos = 0;
|
||||
this.state.awaitPos = 0;
|
||||
|
||||
this.initFunction(node, isAsync);
|
||||
node.generator = !!isGenerator;
|
||||
const allowModifiers = isConstructor; // For TypeScript parameter properties
|
||||
this.parseFunctionParams((node: any), allowModifiers);
|
||||
this.checkYieldAwaitInDefaultParams();
|
||||
this.parseFunctionBodyAndFinish(node, type);
|
||||
|
||||
this.state.inFunction = oldInFunc;
|
||||
this.state.inMethod = oldInMethod;
|
||||
this.state.inAsync = oldInAsync;
|
||||
this.state.inGenerator = oldInGenerator;
|
||||
this.state.yieldPos = oldYieldPos;
|
||||
this.state.awaitPos = oldAwaitPos;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -1758,44 +1750,33 @@ export default class ExpressionParser extends LValParser {
|
||||
// assignable list.
|
||||
parseArrowExpression(
|
||||
node: N.ArrowFunctionExpression,
|
||||
params?: ?(N.Expression[]),
|
||||
isAsync?: boolean,
|
||||
params: ?(N.Expression[]),
|
||||
isAsync: boolean,
|
||||
): N.ArrowFunctionExpression {
|
||||
// if we got there, it's no more "yield in possible arrow parameters";
|
||||
// it's just "yield in arrow parameters"
|
||||
const yOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
if (yOAIPAP) {
|
||||
if (yOAIPAP.type === "YieldExpression") {
|
||||
this.raise(
|
||||
yOAIPAP.start,
|
||||
"yield is not allowed in the parameters of an arrow function" +
|
||||
" inside a generator",
|
||||
);
|
||||
} else {
|
||||
this.raise(
|
||||
yOAIPAP.start,
|
||||
"await is not allowed in the parameters of an arrow function" +
|
||||
" inside an async function",
|
||||
);
|
||||
}
|
||||
}
|
||||
this.initFunction(node, isAsync);
|
||||
|
||||
const oldInFunc = this.state.inFunction;
|
||||
this.state.inFunction = true;
|
||||
this.initFunction(node, isAsync);
|
||||
if (params) this.setArrowFunctionParameters(node, params);
|
||||
|
||||
const oldInAsync = this.state.inAsync;
|
||||
const oldInGenerator = this.state.inGenerator;
|
||||
const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;
|
||||
const oldYieldPos = this.state.yieldPos;
|
||||
const oldAwaitPos = this.state.awaitPos;
|
||||
this.state.inFunction = true;
|
||||
this.state.inAsync = isAsync;
|
||||
this.state.inGenerator = false;
|
||||
this.state.maybeInArrowParameters = false;
|
||||
this.state.yieldPos = 0;
|
||||
this.state.awaitPos = 0;
|
||||
|
||||
if (params) this.setArrowFunctionParameters(node, params);
|
||||
this.parseFunctionBody(node, true);
|
||||
|
||||
this.state.inAsync = oldInAsync;
|
||||
this.state.inGenerator = oldInGenerator;
|
||||
this.state.inFunction = oldInFunc;
|
||||
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
||||
this.state.yieldPos = oldYieldPos;
|
||||
this.state.awaitPos = oldAwaitPos;
|
||||
|
||||
return this.finishNode(node, "ArrowFunctionExpression");
|
||||
}
|
||||
@@ -1845,17 +1826,14 @@ export default class ExpressionParser extends LValParser {
|
||||
if (isExpression) {
|
||||
node.body = this.parseMaybeAssign();
|
||||
} else {
|
||||
// Start a new scope with regard to labels and the `inGenerator`
|
||||
// Start a new scope with regard to labels
|
||||
// flag (restore them to their old value afterwards).
|
||||
const oldInGen = this.state.inGenerator;
|
||||
const oldInFunc = this.state.inFunction;
|
||||
const oldLabels = this.state.labels;
|
||||
this.state.inGenerator = node.generator;
|
||||
this.state.inFunction = true;
|
||||
this.state.labels = [];
|
||||
node.body = this.parseBlock(true);
|
||||
this.state.inFunction = oldInFunc;
|
||||
this.state.inGenerator = oldInGen;
|
||||
this.state.labels = oldLabels;
|
||||
}
|
||||
|
||||
@@ -1923,7 +1901,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 +1913,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,
|
||||
@@ -1970,15 +1943,6 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
|
||||
parseIdentifierName(pos: number, liberal?: boolean): string {
|
||||
if (!liberal) {
|
||||
this.checkReservedWord(
|
||||
this.state.value,
|
||||
this.state.start,
|
||||
!!this.state.type.keyword,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
let name: string;
|
||||
|
||||
if (this.match(tt.name)) {
|
||||
@@ -1994,7 +1958,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();
|
||||
}
|
||||
@@ -2002,11 +1967,17 @@ export default class ExpressionParser extends LValParser {
|
||||
throw this.unexpected();
|
||||
}
|
||||
|
||||
if (!liberal && name === "await" && this.state.inAsync) {
|
||||
this.raise(pos, "invalid use of await inside of an async function");
|
||||
if (!liberal) {
|
||||
this.checkReservedWord(
|
||||
name,
|
||||
this.state.start,
|
||||
!!this.state.type.keyword,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
this.next();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -2016,43 +1987,58 @@ export default class ExpressionParser extends LValParser {
|
||||
checkKeywords: boolean,
|
||||
isBinding: boolean,
|
||||
): void {
|
||||
if (
|
||||
this.state.strict &&
|
||||
(reservedWords.strict(word) ||
|
||||
(isBinding && reservedWords.strictBind(word)))
|
||||
) {
|
||||
this.raise(startLoc, word + " is a reserved word in strict mode");
|
||||
}
|
||||
|
||||
if (this.state.inGenerator && word === "yield") {
|
||||
const state = this.state;
|
||||
if (state.inGenerator && word === "yield") {
|
||||
this.raise(
|
||||
startLoc,
|
||||
"yield is a reserved word inside generator functions",
|
||||
"Can not use 'yield' as identifier inside a generator",
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.inClassProperty && word === "arguments") {
|
||||
if (state.inAsync && word === "await") {
|
||||
this.raise(
|
||||
startLoc,
|
||||
"Can not use 'await' as identifier inside an async function",
|
||||
);
|
||||
}
|
||||
|
||||
if (state.inClassProperty && word === "arguments") {
|
||||
this.raise(
|
||||
startLoc,
|
||||
"'arguments' is not allowed in class field initializer",
|
||||
);
|
||||
}
|
||||
if (checkKeywords && isKeyword(word)) {
|
||||
this.raise(startLoc, `Unexpected keyword '${word}'`);
|
||||
}
|
||||
|
||||
if (this.isReservedWord(word) || (checkKeywords && this.isKeyword(word))) {
|
||||
this.raise(startLoc, word + " is a reserved word");
|
||||
const reservedTest = !state.strict
|
||||
? isReservedWord
|
||||
: isBinding
|
||||
? isStrictBindReservedWord
|
||||
: isStrictReservedWord;
|
||||
|
||||
if (reservedTest(word, this.inModule)) {
|
||||
if (!state.inAsync && word === "await") {
|
||||
this.raise(
|
||||
startLoc,
|
||||
"Can not use keyword 'await' outside an async function",
|
||||
);
|
||||
}
|
||||
this.raise(startLoc, `Unexpected reserved word '${word}'`);
|
||||
}
|
||||
}
|
||||
|
||||
// Parses await expression inside async function.
|
||||
|
||||
parseAwait(node: N.AwaitExpression): N.AwaitExpression {
|
||||
// istanbul ignore next: this condition is checked at the call site so won't be hit here
|
||||
if (
|
||||
!this.state.inAsync &&
|
||||
(this.state.inFunction || !this.options.allowAwaitOutsideFunction)
|
||||
) {
|
||||
this.unexpected();
|
||||
parseAwait(): N.AwaitExpression {
|
||||
if (!this.state.awaitPos) {
|
||||
this.state.awaitPos = this.state.start;
|
||||
}
|
||||
const node = this.startNode();
|
||||
|
||||
this.next();
|
||||
|
||||
if (this.state.inParameters) {
|
||||
this.raise(
|
||||
node.start,
|
||||
@@ -2065,14 +2051,6 @@ export default class ExpressionParser extends LValParser {
|
||||
"await* has been removed from the async functions proposal. Use Promise.all() instead.",
|
||||
);
|
||||
}
|
||||
if (
|
||||
this.state.maybeInArrowParameters &&
|
||||
// We only set yieldOrAwaitInPossibleArrowParameters if we haven't already
|
||||
// found a possible invalid AwaitExpression.
|
||||
!this.state.yieldOrAwaitInPossibleArrowParameters
|
||||
) {
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = node;
|
||||
}
|
||||
|
||||
node.argument = this.parseMaybeUnary();
|
||||
return this.finishNode(node, "AwaitExpression");
|
||||
@@ -2080,32 +2058,27 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
// Parses yield expression inside generator.
|
||||
|
||||
parseYield(): N.YieldExpression {
|
||||
parseYield(noIn?: ?boolean): N.YieldExpression {
|
||||
if (!this.state.yieldPos) {
|
||||
this.state.yieldPos = this.state.start;
|
||||
}
|
||||
const node = this.startNode();
|
||||
|
||||
if (this.state.inParameters) {
|
||||
this.raise(node.start, "yield is not allowed in generator parameters");
|
||||
}
|
||||
if (
|
||||
this.state.maybeInArrowParameters &&
|
||||
// We only set yieldOrAwaitInPossibleArrowParameters if we haven't already
|
||||
// found a possible invalid YieldExpression.
|
||||
!this.state.yieldOrAwaitInPossibleArrowParameters
|
||||
) {
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = node;
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
node.delegate = this.eat(tt.star);
|
||||
node.argument = this.parseMaybeAssign();
|
||||
node.argument = this.parseMaybeAssign(noIn);
|
||||
}
|
||||
return this.finishNode(node, "YieldExpression");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -14,16 +14,11 @@ import type {
|
||||
SpreadElement,
|
||||
} from "../types";
|
||||
import type { Pos, Position } from "../util/location";
|
||||
import { isStrictBindReservedWord } from "../util/identifier";
|
||||
import { NodeUtils } from "./node";
|
||||
|
||||
export default class LValParser extends NodeUtils {
|
||||
// Forward-declaration: defined in expression.js
|
||||
+checkReservedWord: (
|
||||
word: string,
|
||||
startLoc: number,
|
||||
checkKeywords: boolean,
|
||||
isBinding: boolean,
|
||||
) => void;
|
||||
+parseIdentifier: (liberal?: boolean) => Identifier;
|
||||
+parseMaybeAssign: (
|
||||
noIn?: ?boolean,
|
||||
@@ -56,9 +51,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 +121,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 +144,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 +156,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 +192,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 +204,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");
|
||||
}
|
||||
|
||||
@@ -221,22 +219,11 @@ export default class LValParser extends NodeUtils {
|
||||
return this.finishNode(node, "RestElement");
|
||||
}
|
||||
|
||||
shouldAllowYieldIdentifier(): boolean {
|
||||
return (
|
||||
this.match(tt._yield) && !this.state.strict && !this.state.inGenerator
|
||||
);
|
||||
}
|
||||
|
||||
parseBindingIdentifier(): Identifier {
|
||||
return this.parseIdentifier(this.shouldAllowYieldIdentifier());
|
||||
}
|
||||
|
||||
// Parses lvalue (assignable) atom.
|
||||
parseBindingAtom(): Pattern {
|
||||
switch (this.state.type) {
|
||||
case tt._yield:
|
||||
case tt.name:
|
||||
return this.parseBindingIdentifier();
|
||||
return this.parseIdentifier();
|
||||
|
||||
case tt.bracketL: {
|
||||
const node = this.startNode();
|
||||
@@ -273,20 +260,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 = [];
|
||||
@@ -351,7 +331,17 @@ export default class LValParser extends NodeUtils {
|
||||
): void {
|
||||
switch (expr.type) {
|
||||
case "Identifier":
|
||||
this.checkReservedWord(expr.name, expr.start, false, true);
|
||||
if (
|
||||
this.state.strict &&
|
||||
isStrictBindReservedWord(expr.name, this.inModule)
|
||||
) {
|
||||
this.raise(
|
||||
expr.start,
|
||||
`${isBinding ? "Binding" : "Assigning to"} '${
|
||||
expr.name
|
||||
}' in strict mode`,
|
||||
);
|
||||
}
|
||||
|
||||
if (checkClashes) {
|
||||
// we need to prefix this with an underscore for the cases where we have a key of
|
||||
@@ -432,12 +422,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}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,12 +91,16 @@ export class NodeUtils extends UtilParser {
|
||||
return node;
|
||||
}
|
||||
|
||||
resetStartLocation(node: NodeBase, start: number, startLoc: Position): void {
|
||||
node.start = start;
|
||||
node.loc.start = startLoc;
|
||||
if (this.options.ranges) node.range[0] = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the start location of node to the start location of locationNode
|
||||
*/
|
||||
resetStartLocationFromNode(node: NodeBase, locationNode: NodeBase): void {
|
||||
node.start = locationNode.start;
|
||||
node.loc.start = locationNode.loc.start;
|
||||
if (this.options.ranges) node.range[0] = locationNode.range[0];
|
||||
this.resetStartLocation(node, locationNode.start, locationNode.loc.start);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
import * as N from "../types";
|
||||
import { types as tt, type TokenType } from "../tokenizer/types";
|
||||
import ExpressionParser from "./expression";
|
||||
import { isIdentifierChar } from "../util/identifier";
|
||||
import {
|
||||
isIdentifierChar,
|
||||
isIdentifierStart,
|
||||
keywordRelationalOperator,
|
||||
} from "../util/identifier";
|
||||
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
|
||||
import * as charCodes from "charcodes";
|
||||
|
||||
// Reused empty array added for node fields that are always empty.
|
||||
|
||||
@@ -44,7 +49,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);
|
||||
@@ -71,6 +76,39 @@ export default class StatementParser extends ExpressionParser {
|
||||
return this.finishNode(node, "InterpreterDirective");
|
||||
}
|
||||
|
||||
isLet(declaration?: boolean): boolean {
|
||||
if (!this.isContextual("let")) {
|
||||
return false;
|
||||
}
|
||||
skipWhiteSpace.lastIndex = this.state.pos;
|
||||
const skip = skipWhiteSpace.exec(this.state.input);
|
||||
// $FlowIgnore
|
||||
const next = this.state.pos + skip[0].length;
|
||||
const nextCh = this.state.input.charCodeAt(next);
|
||||
if (
|
||||
(nextCh === charCodes.leftCurlyBrace &&
|
||||
!lineBreak.test(this.state.input.slice(this.state.end, next))) ||
|
||||
nextCh === charCodes.leftSquareBracket
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (isIdentifierStart(nextCh)) {
|
||||
if (
|
||||
!declaration &&
|
||||
lineBreak.test(this.state.input.slice(this.state.end, next))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
let pos = next + 1;
|
||||
while (isIdentifierChar(this.state.input.charCodeAt(pos))) {
|
||||
++pos;
|
||||
}
|
||||
const ident = this.state.input.slice(next, pos);
|
||||
if (!keywordRelationalOperator.test(ident)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse a single statement.
|
||||
//
|
||||
// If expecting a statement and finding a slash operator, parse a
|
||||
@@ -86,8 +124,14 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
parseStatementContent(declaration: boolean, topLevel: ?boolean): N.Statement {
|
||||
const starttype = this.state.type;
|
||||
let starttype = this.state.type;
|
||||
const node = this.startNode();
|
||||
let kind;
|
||||
|
||||
if (this.isLet(declaration)) {
|
||||
starttype = tt._var;
|
||||
kind = "let";
|
||||
}
|
||||
|
||||
// Most types of statements are recognized by the keyword they
|
||||
// start with. Many are trivial to parse, some require a bit of
|
||||
@@ -106,7 +150,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:
|
||||
@@ -124,12 +173,11 @@ export default class StatementParser extends ExpressionParser {
|
||||
case tt._try:
|
||||
return this.parseTryStatement(node);
|
||||
|
||||
case tt._let:
|
||||
case tt._const:
|
||||
if (!declaration) this.unexpected(); // NOTE: falls through to _var
|
||||
|
||||
case tt._var:
|
||||
return this.parseVarStatement(node, starttype);
|
||||
kind = kind || this.state.value;
|
||||
if (!declaration && kind !== "var") this.unexpected();
|
||||
return this.parseVarStatement(node, kind);
|
||||
|
||||
case tt._while:
|
||||
return this.parseWhileStatement(node);
|
||||
@@ -156,7 +204,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 +237,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 +264,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);
|
||||
}
|
||||
@@ -399,32 +453,36 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.next();
|
||||
this.state.labels.push(loopLabel);
|
||||
|
||||
let forAwait = false;
|
||||
if (this.state.inAsync && this.isContextual("await")) {
|
||||
forAwait = true;
|
||||
this.next();
|
||||
let awaitAt = -1;
|
||||
if (
|
||||
(this.state.inAsync ||
|
||||
(!this.state.inFunction && this.options.allowAwaitOutsideFunction)) &&
|
||||
this.eatContextual("await")
|
||||
) {
|
||||
awaitAt = this.state.lastTokStart;
|
||||
}
|
||||
this.expect(tt.parenL);
|
||||
|
||||
if (this.match(tt.semi)) {
|
||||
if (forAwait) {
|
||||
this.unexpected();
|
||||
if (awaitAt > -1) {
|
||||
this.unexpected(awaitAt);
|
||||
}
|
||||
return this.parseFor(node, null);
|
||||
}
|
||||
|
||||
if (this.match(tt._var) || this.match(tt._let) || this.match(tt._const)) {
|
||||
const isLet = this.isLet();
|
||||
if (this.match(tt._var) || this.match(tt._const) || isLet) {
|
||||
const init = this.startNode();
|
||||
const varKind = this.state.type;
|
||||
const kind = isLet ? "let" : this.state.value;
|
||||
this.next();
|
||||
this.parseVar(init, true, varKind);
|
||||
this.parseVar(init, true, kind);
|
||||
this.finishNode(init, "VariableDeclaration");
|
||||
|
||||
if (this.match(tt._in) || this.isContextual("of")) {
|
||||
if (init.declarations.length === 1) {
|
||||
const declaration = init.declarations[0];
|
||||
const isForInInitializer =
|
||||
varKind === tt._var &&
|
||||
kind === "var" &&
|
||||
declaration.init &&
|
||||
declaration.id.type != "ObjectPattern" &&
|
||||
declaration.id.type != "ArrayPattern" &&
|
||||
@@ -432,12 +490,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
if (this.state.strict && isForInInitializer) {
|
||||
this.raise(this.state.start, "for-in initializer in strict mode");
|
||||
} else if (isForInInitializer || !declaration.init) {
|
||||
return this.parseForIn(node, init, forAwait);
|
||||
return this.parseForIn(node, init, awaitAt);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forAwait) {
|
||||
this.unexpected();
|
||||
if (awaitAt > -1) {
|
||||
this.unexpected(awaitAt);
|
||||
}
|
||||
return this.parseFor(node, init);
|
||||
}
|
||||
@@ -450,12 +508,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
: "for-in statement";
|
||||
this.toAssignable(init, undefined, description);
|
||||
this.checkLVal(init, undefined, undefined, description);
|
||||
return this.parseForIn(node, init, forAwait);
|
||||
return this.parseForIn(node, init, awaitAt);
|
||||
} else if (refShorthandDefaultPos.start) {
|
||||
this.unexpected(refShorthandDefaultPos.start);
|
||||
}
|
||||
if (forAwait) {
|
||||
this.unexpected();
|
||||
if (awaitAt > -1) {
|
||||
this.unexpected(awaitAt);
|
||||
}
|
||||
return this.parseFor(node, init);
|
||||
}
|
||||
@@ -540,7 +598,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");
|
||||
}
|
||||
@@ -593,7 +653,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
parseVarStatement(
|
||||
node: N.VariableDeclaration,
|
||||
kind: TokenType,
|
||||
kind: "var" | "let" | "const",
|
||||
): N.VariableDeclaration {
|
||||
this.next();
|
||||
this.parseVar(node, false, kind);
|
||||
@@ -649,6 +709,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 +737,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");
|
||||
@@ -814,16 +875,16 @@ export default class StatementParser extends ExpressionParser {
|
||||
parseForIn(
|
||||
node: N.ForInOf,
|
||||
init: N.VariableDeclaration,
|
||||
forAwait: boolean,
|
||||
awaitAt: number,
|
||||
): N.ForInOf {
|
||||
const type = this.match(tt._in) ? "ForInStatement" : "ForOfStatement";
|
||||
if (forAwait) {
|
||||
if (awaitAt > -1) {
|
||||
this.eatContextual("of");
|
||||
} else {
|
||||
this.next();
|
||||
}
|
||||
if (type === "ForOfStatement") {
|
||||
node.await = !!forAwait;
|
||||
node.await = awaitAt > -1;
|
||||
}
|
||||
node.left = init;
|
||||
node.right = this.parseExpression();
|
||||
@@ -848,24 +909,24 @@ export default class StatementParser extends ExpressionParser {
|
||||
parseVar(
|
||||
node: N.VariableDeclaration,
|
||||
isFor: boolean,
|
||||
kind: TokenType,
|
||||
kind: "var" | "let" | "const",
|
||||
): N.VariableDeclaration {
|
||||
const declarations = (node.declarations = []);
|
||||
// $FlowFixMe
|
||||
node.kind = kind.keyword;
|
||||
const isTypescript = this.hasPlugin("typescript");
|
||||
node.kind = kind;
|
||||
for (;;) {
|
||||
const decl = this.startNode();
|
||||
this.parseVarHead(decl);
|
||||
this.parseVarId(decl, kind);
|
||||
if (this.eat(tt.eq)) {
|
||||
decl.init = this.parseMaybeAssign(isFor);
|
||||
} else {
|
||||
if (
|
||||
kind === tt._const &&
|
||||
kind === "const" &&
|
||||
!(this.match(tt._in) || this.isContextual("of"))
|
||||
) {
|
||||
// `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 (
|
||||
@@ -885,7 +946,10 @@ export default class StatementParser extends ExpressionParser {
|
||||
return node;
|
||||
}
|
||||
|
||||
parseVarHead(decl: N.VariableDeclarator): void {
|
||||
parseVarId(decl: N.VariableDeclarator, kind: "var" | "let" | "const"): void {
|
||||
if ((kind === "const" || kind === "let") && this.isContextual("let")) {
|
||||
this.unexpected(null, "let is disallowed as a lexically bound name");
|
||||
}
|
||||
decl.id = this.parseBindingAtom();
|
||||
this.checkLVal(decl.id, true, undefined, "variable declaration");
|
||||
}
|
||||
@@ -896,32 +960,28 @@ export default class StatementParser extends ExpressionParser {
|
||||
parseFunction<T: N.NormalFunction>(
|
||||
node: T,
|
||||
isStatement: boolean,
|
||||
allowExpressionBody?: boolean,
|
||||
isAsync?: boolean,
|
||||
optionalId?: boolean,
|
||||
allowExpressionBody?: boolean = false,
|
||||
isAsync?: boolean = false,
|
||||
optionalId?: boolean = false,
|
||||
): T {
|
||||
const oldInFunc = this.state.inFunction;
|
||||
const oldInMethod = this.state.inMethod;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
const oldInGenerator = this.state.inGenerator;
|
||||
const oldInClassProperty = this.state.inClassProperty;
|
||||
const oldYieldPos = this.state.yieldPos;
|
||||
const oldAwaitPos = this.state.awaitPos;
|
||||
this.state.inFunction = true;
|
||||
this.state.inMethod = false;
|
||||
this.state.inClassProperty = false;
|
||||
this.state.yieldPos = 0;
|
||||
this.state.awaitPos = 0;
|
||||
|
||||
this.initFunction(node, isAsync);
|
||||
|
||||
if (this.match(tt.star)) {
|
||||
node.generator = true;
|
||||
this.next();
|
||||
}
|
||||
node.generator = this.eat(tt.star);
|
||||
|
||||
if (
|
||||
isStatement &&
|
||||
!optionalId &&
|
||||
!this.match(tt.name) &&
|
||||
!this.match(tt._yield)
|
||||
) {
|
||||
if (isStatement && !optionalId && !this.match(tt.name)) {
|
||||
this.unexpected();
|
||||
}
|
||||
|
||||
@@ -938,8 +998,8 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.state.inAsync = isAsync;
|
||||
this.state.inGenerator = node.generator;
|
||||
}
|
||||
if (this.match(tt.name) || this.match(tt._yield)) {
|
||||
node.id = this.parseBindingIdentifier();
|
||||
if (this.match(tt.name)) {
|
||||
node.id = this.parseIdentifier();
|
||||
}
|
||||
if (isStatement) {
|
||||
this.state.inAsync = isAsync;
|
||||
@@ -965,6 +1025,8 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.state.inAsync = oldInAsync;
|
||||
this.state.inGenerator = oldInGenerator;
|
||||
this.state.inClassProperty = oldInClassProperty;
|
||||
this.state.yieldPos = oldYieldPos;
|
||||
this.state.awaitPos = oldAwaitPos;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -981,6 +1043,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
);
|
||||
|
||||
this.state.inParameters = oldInParameters;
|
||||
this.checkYieldAwaitInDefaultParams();
|
||||
}
|
||||
|
||||
// Parse a class declaration or literal (depending on the
|
||||
@@ -993,9 +1056,17 @@ export default class StatementParser extends ExpressionParser {
|
||||
): T {
|
||||
this.next();
|
||||
this.takeDecorators(node);
|
||||
|
||||
// A class definition is always strict mode code.
|
||||
const oldStrict = this.state.strict;
|
||||
this.state.strict = true;
|
||||
|
||||
this.parseClassId(node, isStatement, optionalId);
|
||||
this.parseClassSuper(node);
|
||||
this.parseClassBody(node);
|
||||
|
||||
this.state.strict = oldStrict;
|
||||
|
||||
return this.finishNode(
|
||||
node,
|
||||
isStatement ? "ClassDeclaration" : "ClassExpression",
|
||||
@@ -1020,9 +1091,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 +1155,6 @@ export default class StatementParser extends ExpressionParser {
|
||||
node.body = this.finishNode(classBody, "ClassBody");
|
||||
|
||||
this.state.classLevel--;
|
||||
this.state.strict = oldStrict;
|
||||
}
|
||||
|
||||
parseClassMember(
|
||||
@@ -1262,7 +1329,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
|
||||
@@ -1451,35 +1518,109 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
// Parses module export declaration.
|
||||
|
||||
// TODO: better type. Node is an N.AnyExport.
|
||||
parseExport(node: N.Node): N.Node {
|
||||
// export * from '...'
|
||||
if (this.shouldParseExportStar()) {
|
||||
this.parseExportStar(node);
|
||||
if (node.type === "ExportAllDeclaration") return node;
|
||||
} else if (this.isExportDefaultSpecifier()) {
|
||||
this.expectPlugin("exportDefaultFrom");
|
||||
const specifier = this.startNode();
|
||||
specifier.exported = this.parseIdentifier(true);
|
||||
const specifiers = [this.finishNode(specifier, "ExportDefaultSpecifier")];
|
||||
node.specifiers = specifiers;
|
||||
if (this.match(tt.comma) && this.lookahead().type === tt.star) {
|
||||
this.expect(tt.comma);
|
||||
const specifier = this.startNode();
|
||||
this.expect(tt.star);
|
||||
this.expectContextual("as");
|
||||
specifier.exported = this.parseIdentifier();
|
||||
specifiers.push(this.finishNode(specifier, "ExportNamespaceSpecifier"));
|
||||
} else {
|
||||
this.parseExportSpecifiersMaybe(node);
|
||||
}
|
||||
parseExport(node: N.Node): N.AnyExport {
|
||||
const hasDefault = this.maybeParseExportDefaultSpecifier(node);
|
||||
const parseAfterDefault = !hasDefault || this.eat(tt.comma);
|
||||
const hasStar = parseAfterDefault && this.eatExportStar(node);
|
||||
const hasNamespace =
|
||||
hasStar && this.maybeParseExportNamespaceSpecifier(node);
|
||||
const parseAfterNamespace =
|
||||
parseAfterDefault && (!hasNamespace || this.eat(tt.comma));
|
||||
const isFromRequired = hasDefault || hasStar;
|
||||
|
||||
if (hasStar && !hasNamespace) {
|
||||
if (hasDefault) this.unexpected();
|
||||
this.parseExportFrom(node, true);
|
||||
} else if (this.eat(tt._default)) {
|
||||
|
||||
return this.finishNode(node, "ExportAllDeclaration");
|
||||
}
|
||||
|
||||
const hasSpecifiers = this.maybeParseExportNamedSpecifiers(node);
|
||||
|
||||
if (
|
||||
(hasDefault && parseAfterDefault && !hasStar && !hasSpecifiers) ||
|
||||
(hasNamespace && parseAfterNamespace && !hasSpecifiers)
|
||||
) {
|
||||
throw this.unexpected(null, tt.braceL);
|
||||
}
|
||||
|
||||
let hasDeclaration;
|
||||
if (isFromRequired || hasSpecifiers) {
|
||||
hasDeclaration = false;
|
||||
this.parseExportFrom(node, isFromRequired);
|
||||
} else {
|
||||
hasDeclaration = this.maybeParseExportDeclaration(node);
|
||||
}
|
||||
|
||||
if (isFromRequired || hasSpecifiers || hasDeclaration) {
|
||||
this.checkExport(node, true);
|
||||
return this.finishNode(node, "ExportNamedDeclaration");
|
||||
}
|
||||
|
||||
if (this.eat(tt._default)) {
|
||||
// export default ...
|
||||
node.declaration = this.parseExportDefaultExpression();
|
||||
this.checkExport(node, true, true);
|
||||
|
||||
return this.finishNode(node, "ExportDefaultDeclaration");
|
||||
} else if (this.shouldParseExportDeclaration()) {
|
||||
}
|
||||
|
||||
throw this.unexpected(null, tt.braceL);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
eatExportStar(node: N.Node): boolean {
|
||||
return this.eat(tt.star);
|
||||
}
|
||||
|
||||
maybeParseExportDefaultSpecifier(node: N.Node): boolean {
|
||||
if (this.isExportDefaultSpecifier()) {
|
||||
// export defaultObj ...
|
||||
this.expectPlugin("exportDefaultFrom");
|
||||
const specifier = this.startNode();
|
||||
specifier.exported = this.parseIdentifier(true);
|
||||
node.specifiers = [this.finishNode(specifier, "ExportDefaultSpecifier")];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
maybeParseExportNamespaceSpecifier(node: N.Node): boolean {
|
||||
if (this.isContextual("as")) {
|
||||
if (!node.specifiers) node.specifiers = [];
|
||||
this.expectPlugin("exportNamespaceFrom");
|
||||
|
||||
const specifier = this.startNodeAt(
|
||||
this.state.lastTokStart,
|
||||
this.state.lastTokStartLoc,
|
||||
);
|
||||
|
||||
this.next();
|
||||
|
||||
specifier.exported = this.parseIdentifier(true);
|
||||
node.specifiers.push(
|
||||
this.finishNode(specifier, "ExportNamespaceSpecifier"),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
maybeParseExportNamedSpecifiers(node: N.Node): boolean {
|
||||
if (this.match(tt.braceL)) {
|
||||
if (!node.specifiers) node.specifiers = [];
|
||||
node.specifiers.push(...this.parseExportSpecifiers());
|
||||
|
||||
node.source = null;
|
||||
node.declaration = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
maybeParseExportDeclaration(node: N.Node): boolean {
|
||||
if (this.shouldParseExportDeclaration()) {
|
||||
if (this.isContextual("async")) {
|
||||
const next = this.lookahead();
|
||||
|
||||
@@ -1492,20 +1633,16 @@ export default class StatementParser extends ExpressionParser {
|
||||
node.specifiers = [];
|
||||
node.source = null;
|
||||
node.declaration = this.parseExportDeclaration(node);
|
||||
} else {
|
||||
// export { x, y as z } [from '...']
|
||||
node.declaration = null;
|
||||
node.specifiers = this.parseExportSpecifiers();
|
||||
this.parseExportFrom(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
this.checkExport(node, true);
|
||||
return this.finishNode(node, "ExportNamedDeclaration");
|
||||
return false;
|
||||
}
|
||||
|
||||
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 +1654,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)))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1549,11 +1686,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
this.parseDecorators(false);
|
||||
return this.parseClass(expr, true, true);
|
||||
} else if (
|
||||
this.match(tt._let) ||
|
||||
this.match(tt._const) ||
|
||||
this.match(tt._var)
|
||||
) {
|
||||
} else if (this.match(tt._const) || this.match(tt._var) || this.isLet()) {
|
||||
return this.raise(
|
||||
this.state.start,
|
||||
"Only expressions, functions or classes are allowed as the `default` export.",
|
||||
@@ -1572,7 +1705,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
isExportDefaultSpecifier(): boolean {
|
||||
if (this.match(tt.name)) {
|
||||
return this.state.value !== "async";
|
||||
return this.state.value !== "async" && this.state.value !== "let";
|
||||
}
|
||||
|
||||
if (!this.match(tt._default)) {
|
||||
@@ -1586,17 +1719,9 @@ export default class StatementParser extends ExpressionParser {
|
||||
);
|
||||
}
|
||||
|
||||
parseExportSpecifiersMaybe(node: N.ExportNamedDeclaration): void {
|
||||
if (this.eat(tt.comma)) {
|
||||
node.specifiers = node.specifiers.concat(this.parseExportSpecifiers());
|
||||
}
|
||||
}
|
||||
|
||||
parseExportFrom(node: N.ExportNamedDeclaration, expect?: boolean): void {
|
||||
if (this.eatContextual("from")) {
|
||||
node.source = this.match(tt.string)
|
||||
? this.parseExprAtom()
|
||||
: this.unexpected();
|
||||
node.source = this.parseImportSource();
|
||||
this.checkExport(node);
|
||||
} else {
|
||||
if (expect) {
|
||||
@@ -1609,39 +1734,6 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
shouldParseExportStar(): boolean {
|
||||
return this.match(tt.star);
|
||||
}
|
||||
|
||||
parseExportStar(node: N.ExportNamedDeclaration): void {
|
||||
this.expect(tt.star);
|
||||
|
||||
if (this.isContextual("as")) {
|
||||
this.parseExportNamespace(node);
|
||||
} else {
|
||||
this.parseExportFrom(node, true);
|
||||
this.finishNode(node, "ExportAllDeclaration");
|
||||
}
|
||||
}
|
||||
|
||||
parseExportNamespace(node: N.ExportNamedDeclaration): void {
|
||||
this.expectPlugin("exportNamespaceFrom");
|
||||
|
||||
const specifier = this.startNodeAt(
|
||||
this.state.lastTokStart,
|
||||
this.state.lastTokStartLoc,
|
||||
);
|
||||
|
||||
this.next();
|
||||
|
||||
specifier.exported = this.parseIdentifier(true);
|
||||
|
||||
node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")];
|
||||
|
||||
this.parseExportSpecifiersMaybe(node);
|
||||
this.parseExportFrom(node, true);
|
||||
}
|
||||
|
||||
shouldParseExportDeclaration(): boolean {
|
||||
if (this.match(tt.at)) {
|
||||
this.expectOnePlugin(["decorators", "decorators-legacy"]);
|
||||
@@ -1662,9 +1754,9 @@ export default class StatementParser extends ExpressionParser {
|
||||
return (
|
||||
this.state.type.keyword === "var" ||
|
||||
this.state.type.keyword === "const" ||
|
||||
this.state.type.keyword === "let" ||
|
||||
this.state.type.keyword === "function" ||
|
||||
this.state.type.keyword === "class" ||
|
||||
this.isLet() ||
|
||||
this.isAsyncFunction()
|
||||
);
|
||||
}
|
||||
@@ -1741,27 +1833,24 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
checkDuplicateExports(
|
||||
node: N.Identifier | N.ExportNamedDeclaration | N.ExportSpecifier,
|
||||
node:
|
||||
| N.Identifier
|
||||
| N.ExportNamedDeclaration
|
||||
| N.ExportSpecifier
|
||||
| N.ExportDefaultSpecifier,
|
||||
name: string,
|
||||
): void {
|
||||
if (this.state.exportedIdentifiers.indexOf(name) > -1) {
|
||||
this.raiseDuplicateExportError(node, name);
|
||||
throw this.raise(
|
||||
node.start,
|
||||
name === "default"
|
||||
? "Only one default export allowed per module."
|
||||
: `\`${name}\` has already been exported. Exported identifiers must be unique.`,
|
||||
);
|
||||
}
|
||||
this.state.exportedIdentifiers.push(name);
|
||||
}
|
||||
|
||||
raiseDuplicateExportError(
|
||||
node: N.Identifier | N.ExportNamedDeclaration | N.ExportSpecifier,
|
||||
name: string,
|
||||
): empty {
|
||||
throw this.raise(
|
||||
node.start,
|
||||
name === "default"
|
||||
? "Only one default export allowed per module."
|
||||
: `\`${name}\` has already been exported. Exported identifiers must be unique.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Parses a comma-separated list of module exports.
|
||||
|
||||
parseExportSpecifiers(): Array<N.ExportSpecifier> {
|
||||
@@ -1801,23 +1890,26 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
// Parses import declaration.
|
||||
|
||||
parseImport(node: N.Node): N.ImportDeclaration | N.TsImportEqualsDeclaration {
|
||||
parseImport(node: N.Node): N.AnyImport {
|
||||
// import '...'
|
||||
if (this.match(tt.string)) {
|
||||
node.specifiers = [];
|
||||
node.source = this.parseExprAtom();
|
||||
} else {
|
||||
node.specifiers = [];
|
||||
this.parseImportSpecifiers(node);
|
||||
node.specifiers = [];
|
||||
if (!this.match(tt.string)) {
|
||||
const hasDefault = this.maybeParseDefaultImportSpecifier(node);
|
||||
const parseNext = !hasDefault || this.eat(tt.comma);
|
||||
const hasStar = parseNext && this.maybeParseStarImportSpecifier(node);
|
||||
if (parseNext && !hasStar) this.parseNamedImportSpecifiers(node);
|
||||
this.expectContextual("from");
|
||||
node.source = this.match(tt.string)
|
||||
? this.parseExprAtom()
|
||||
: this.unexpected();
|
||||
}
|
||||
node.source = this.parseImportSource();
|
||||
this.semicolon();
|
||||
return this.finishNode(node, "ImportDeclaration");
|
||||
}
|
||||
|
||||
parseImportSource(): N.StringLiteral {
|
||||
if (!this.match(tt.string)) this.unexpected();
|
||||
return this.parseExprAtom();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
shouldParseDefaultImport(node: N.ImportDeclaration): boolean {
|
||||
return this.match(tt.name);
|
||||
@@ -1834,9 +1926,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
node.specifiers.push(this.finishNode(specifier, type));
|
||||
}
|
||||
|
||||
// Parses a comma-separated list of module imports.
|
||||
parseImportSpecifiers(node: N.ImportDeclaration): void {
|
||||
let first = true;
|
||||
maybeParseDefaultImportSpecifier(node: N.ImportDeclaration): boolean {
|
||||
if (this.shouldParseDefaultImport(node)) {
|
||||
// import defaultObj, { x, y as z } from '...'
|
||||
this.parseImportSpecifierLocal(
|
||||
@@ -1845,10 +1935,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
"ImportDefaultSpecifier",
|
||||
"default import specifier",
|
||||
);
|
||||
|
||||
if (!this.eat(tt.comma)) return;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
maybeParseStarImportSpecifier(node: N.ImportDeclaration): boolean {
|
||||
if (this.match(tt.star)) {
|
||||
const specifier = this.startNode();
|
||||
this.next();
|
||||
@@ -1860,10 +1952,13 @@ export default class StatementParser extends ExpressionParser {
|
||||
"ImportNamespaceSpecifier",
|
||||
"import namespace specifier",
|
||||
);
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
parseNamedImportSpecifiers(node: N.ImportDeclaration) {
|
||||
let first = true;
|
||||
this.expect(tt.braceL);
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (first) {
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,4 +147,22 @@ export default class UtilParser extends Tokenizer {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
checkYieldAwaitInDefaultParams() {
|
||||
if (
|
||||
this.state.yieldPos &&
|
||||
(!this.state.awaitPos || this.state.yieldPos < this.state.awaitPos)
|
||||
) {
|
||||
this.raise(
|
||||
this.state.yieldPos,
|
||||
"Yield cannot be used as name inside a generator function",
|
||||
);
|
||||
}
|
||||
if (this.state.awaitPos) {
|
||||
this.raise(
|
||||
this.state.awaitPos,
|
||||
"Await cannot be used as name inside an async function",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -344,7 +344,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
} else {
|
||||
if (
|
||||
this.match(tt._const) ||
|
||||
this.match(tt._let) ||
|
||||
this.isLet() ||
|
||||
((this.isContextual("type") || this.isContextual("interface")) &&
|
||||
!insideModule)
|
||||
) {
|
||||
@@ -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,15 +1847,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
super.assertModuleNodeAllowed(node);
|
||||
}
|
||||
|
||||
parseExport(node: N.ExportNamedDeclaration): N.ExportNamedDeclaration {
|
||||
node = super.parseExport(node);
|
||||
parseExport(node: N.Node): N.AnyExport {
|
||||
const decl = super.parseExport(node);
|
||||
if (
|
||||
node.type === "ExportNamedDeclaration" ||
|
||||
node.type === "ExportAllDeclaration"
|
||||
decl.type === "ExportNamedDeclaration" ||
|
||||
decl.type === "ExportAllDeclaration"
|
||||
) {
|
||||
node.exportKind = node.exportKind || "value";
|
||||
decl.exportKind = decl.exportKind || "value";
|
||||
}
|
||||
return node;
|
||||
return decl;
|
||||
}
|
||||
|
||||
parseExportDeclaration(node: N.ExportNamedDeclaration): ?N.Declaration {
|
||||
@@ -1886,27 +1891,26 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
shouldParseExportStar(): boolean {
|
||||
return (
|
||||
super.shouldParseExportStar() ||
|
||||
(this.isContextual("type") && this.lookahead().type === tt.star)
|
||||
);
|
||||
}
|
||||
eatExportStar(node: N.Node): boolean {
|
||||
if (super.eatExportStar(...arguments)) return true;
|
||||
|
||||
parseExportStar(node: N.ExportNamedDeclaration): void {
|
||||
if (this.eatContextual("type")) {
|
||||
if (this.isContextual("type") && this.lookahead().type === tt.star) {
|
||||
node.exportKind = "type";
|
||||
this.next();
|
||||
this.next();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.parseExportStar(node);
|
||||
return false;
|
||||
}
|
||||
|
||||
parseExportNamespace(node: N.ExportNamedDeclaration) {
|
||||
if (node.exportKind === "type") {
|
||||
this.unexpected();
|
||||
maybeParseExportNamespaceSpecifier(node: N.Node): boolean {
|
||||
const pos = this.state.start;
|
||||
const hasNamespace = super.maybeParseExportNamespaceSpecifier(node);
|
||||
if (hasNamespace && node.exportKind === "type") {
|
||||
this.unexpected(pos);
|
||||
}
|
||||
|
||||
return super.parseExportNamespace(node);
|
||||
return hasNamespace;
|
||||
}
|
||||
|
||||
parseClassId(node: N.Class, isStatement: boolean, optionalId: ?boolean) {
|
||||
@@ -1916,20 +1920,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 +1934,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.state.isIterator = true;
|
||||
return super.readWord();
|
||||
} else {
|
||||
return super.readToken(code);
|
||||
return super.getTokenFromCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2226,7 +2222,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
// parse typeof and type imports
|
||||
parseImportSpecifiers(node: N.ImportDeclaration): void {
|
||||
maybeParseDefaultImportSpecifier(node: N.ImportDeclaration): boolean {
|
||||
node.importKind = "value";
|
||||
|
||||
let kind = null;
|
||||
@@ -2253,7 +2249,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
super.parseImportSpecifiers(node);
|
||||
return super.maybeParseDefaultImportSpecifier(node);
|
||||
}
|
||||
|
||||
// parse import-type/typeof shorthand
|
||||
@@ -2348,8 +2344,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
// parse flow type annotations on variable declarator heads - let foo: string = bar
|
||||
parseVarHead(decl: N.VariableDeclarator): void {
|
||||
super.parseVarHead(decl);
|
||||
parseVarId(
|
||||
decl: N.VariableDeclarator,
|
||||
kind: "var" | "let" | "const",
|
||||
): void {
|
||||
super.parseVarId(decl, kind);
|
||||
if (this.match(tt.colon)) {
|
||||
decl.id.typeAnnotation = this.flowParseTypeAnnotation();
|
||||
this.finishNode(decl.id, decl.id.type);
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,7 +1187,18 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
tsTryParseDeclare(nany: any): ?N.Declaration {
|
||||
switch (this.state.type) {
|
||||
if (this.isLineTerminator()) {
|
||||
return;
|
||||
}
|
||||
let starttype = this.state.type;
|
||||
let kind;
|
||||
|
||||
if (this.isContextual("let")) {
|
||||
starttype = tt._var;
|
||||
kind = "let";
|
||||
}
|
||||
|
||||
switch (starttype) {
|
||||
case tt._function:
|
||||
this.next();
|
||||
return this.parseFunction(nany, /* isStatement */ true);
|
||||
@@ -1170,8 +1217,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
// falls through
|
||||
case tt._var:
|
||||
case tt._let:
|
||||
return this.parseVarStatement(nany, this.state.type);
|
||||
kind = kind || this.state.value;
|
||||
return this.parseVarStatement(nany, kind);
|
||||
case tt.name: {
|
||||
const value = this.state.value;
|
||||
if (value === "global") {
|
||||
@@ -1227,10 +1274,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 +1299,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 +1309,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 +1330,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 +1418,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 +1433,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 +1447,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(
|
||||
@@ -1561,16 +1622,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
*/
|
||||
checkDuplicateExports() {}
|
||||
|
||||
parseImport(
|
||||
node: N.Node,
|
||||
): N.ImportDeclaration | N.TsImportEqualsDeclaration {
|
||||
parseImport(node: N.Node): N.AnyImport {
|
||||
if (this.match(tt.name) && this.lookahead().type === tt.eq) {
|
||||
return this.tsParseImportEqualsDeclaration(node);
|
||||
}
|
||||
return super.parseImport(node);
|
||||
}
|
||||
|
||||
parseExport(node: N.Node): N.Node {
|
||||
parseExport(node: N.Node): N.AnyExport {
|
||||
if (this.match(tt._import)) {
|
||||
// `export import A = B;`
|
||||
this.expect(tt._import);
|
||||
@@ -1794,10 +1853,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
parseExportDeclaration(node: N.ExportNamedDeclaration): ?N.Declaration {
|
||||
// Store original location/position
|
||||
const startPos = this.state.start;
|
||||
const startLoc = this.state.startLoc;
|
||||
|
||||
// "export declare" is equivalent to just "export".
|
||||
const isDeclare = this.eatContextual("declare");
|
||||
|
||||
let declaration: ?N.Declaration;
|
||||
|
||||
if (this.match(tt.name)) {
|
||||
declaration = this.tsTryParseExportDeclaration();
|
||||
}
|
||||
@@ -1806,6 +1870,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
if (declaration && isDeclare) {
|
||||
// Reset location to include `declare` in range
|
||||
this.resetStartLocation(declaration, startPos, startLoc);
|
||||
|
||||
declaration.declare = true;
|
||||
}
|
||||
|
||||
@@ -1871,7 +1938,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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1889,8 +1956,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
// `let x: number;`
|
||||
parseVarHead(decl: N.VariableDeclarator): void {
|
||||
super.parseVarHead(decl);
|
||||
parseVarId(
|
||||
decl: N.VariableDeclarator,
|
||||
kind: "var" | "let" | "const",
|
||||
): void {
|
||||
super.parseVarId(decl, kind);
|
||||
if (decl.id.type === "Identifier" && this.eat(tt.bang)) {
|
||||
decl.definite = true;
|
||||
}
|
||||
@@ -1983,10 +2053,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 +2061,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 +2234,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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,18 +1205,22 @@ 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:
|
||||
this.state.lineStart = this.state.pos;
|
||||
++this.state.curLine;
|
||||
case charCodes.lineSeparator:
|
||||
case charCodes.paragraphSeparator:
|
||||
return "";
|
||||
default:
|
||||
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);
|
||||
@@ -1239,6 +1244,7 @@ export default class Tokenizer extends LocationParser {
|
||||
this.state.pos += octalStr.length - 1;
|
||||
return String.fromCharCode(octal);
|
||||
}
|
||||
|
||||
return String.fromCharCode(ch);
|
||||
}
|
||||
}
|
||||
@@ -1266,23 +1272,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 +1302,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 +1316,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 +1329,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
|
||||
@@ -1354,11 +1363,10 @@ export default class Tokenizer extends LocationParser {
|
||||
// `tt.name`.
|
||||
if (
|
||||
prevType === tt._return ||
|
||||
prevType === tt._yield ||
|
||||
(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),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1378,8 +1386,8 @@ export default class Tokenizer extends LocationParser {
|
||||
|
||||
if (
|
||||
prevType === tt._var ||
|
||||
prevType === tt._let ||
|
||||
prevType === tt._const
|
||||
prevType === tt._const ||
|
||||
prevType === tt.name
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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,114 @@ 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;
|
||||
// Positions to delayed-check that yield/await does not exist in default parameters.
|
||||
yieldPos: number = 0;
|
||||
awaitPos: number = 0;
|
||||
|
||||
// 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 +174,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 +186,8 @@ export default class State {
|
||||
|
||||
// $FlowIgnore
|
||||
state[key] = val;
|
||||
});
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,53 @@ 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"),
|
||||
const: makeKeywordProps("const"),
|
||||
while: makeKeywordProps("while", { isLoop }),
|
||||
with: makeKeywordProps("with"),
|
||||
new: makeKeywordProps("new", { beforeExpr, startsExpr }),
|
||||
this: makeKeywordProps("this", { startsExpr }),
|
||||
super: makeKeywordProps("super", { startsExpr }),
|
||||
class: makeKeywordProps("class", { startsExpr }),
|
||||
extends: makeKeywordProps("extends", { beforeExpr }),
|
||||
export: makeKeywordProps("export"),
|
||||
import: makeKeywordProps("import", { 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,
|
||||
};
|
||||
|
||||
@@ -783,7 +783,9 @@ export type AnyExport =
|
||||
| ExportNamedDeclaration
|
||||
| ExportDefaultDeclaration
|
||||
| ExportAllDeclaration
|
||||
| TsExportAssignment;
|
||||
| TsExportAssignment
|
||||
| TsImportEqualsDeclaration
|
||||
| TsNamespaceExportDeclaration;
|
||||
|
||||
export type ModuleSpecifier = NodeBase & {
|
||||
local: Identifier,
|
||||
@@ -820,7 +822,7 @@ export type ImportNamespaceSpecifier = ModuleSpecifier & {
|
||||
export type ExportNamedDeclaration = NodeBase & {
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: ?Declaration,
|
||||
specifiers: $ReadOnlyArray<ExportSpecifier>,
|
||||
specifiers: $ReadOnlyArray<ExportSpecifier | ExportDefaultSpecifier>,
|
||||
source: ?Literal,
|
||||
|
||||
exportKind?: "type" | "value", // TODO: Not in spec
|
||||
@@ -831,6 +833,11 @@ export type ExportSpecifier = NodeBase & {
|
||||
exported: Identifier,
|
||||
};
|
||||
|
||||
export type ExportDefaultSpecifier = NodeBase & {
|
||||
type: "ExportDefaultSpecifier",
|
||||
exported: Identifier,
|
||||
};
|
||||
|
||||
export type ExportDefaultDeclaration = NodeBase & {
|
||||
type: "ExportDefaultDeclaration",
|
||||
declaration:
|
||||
@@ -1146,6 +1153,7 @@ export type TsType =
|
||||
| TsIndexedAccessType
|
||||
| TsMappedType
|
||||
| TsLiteralType
|
||||
| TsImportType
|
||||
// TODO: This probably shouldn't be included here.
|
||||
| TsTypePredicate;
|
||||
|
||||
@@ -1157,6 +1165,7 @@ export type TsKeywordTypeType =
|
||||
| "TSNumberKeyword"
|
||||
| "TSObjectKeyword"
|
||||
| "TSBooleanKeyword"
|
||||
| "TSBigIntKeyword"
|
||||
| "TSStringKeyword"
|
||||
| "TSSymbolKeyword"
|
||||
| "TSVoidKeyword"
|
||||
@@ -1200,7 +1209,7 @@ export type TsTypePredicate = TsTypeBase & {
|
||||
// `typeof` operator
|
||||
export type TsTypeQuery = TsTypeBase & {
|
||||
type: "TSTypeQuery",
|
||||
exprName: TsEntityName,
|
||||
exprName: TsEntityName | TsImportType,
|
||||
};
|
||||
|
||||
export type TsTypeLiteral = TsTypeBase & {
|
||||
@@ -1285,6 +1294,13 @@ export type TsLiteralType = TsTypeBase & {
|
||||
literal: NumericLiteral | StringLiteral | BooleanLiteral,
|
||||
};
|
||||
|
||||
export type TsImportType = TsTypeBase & {
|
||||
type: "TsImportType",
|
||||
argument: StringLiteral,
|
||||
qualifier?: TsEntityName,
|
||||
typeParameters?: TsTypeParameterInstantiation,
|
||||
};
|
||||
|
||||
// ================
|
||||
// TypeScript declarations
|
||||
// ================
|
||||
|
||||
@@ -4,29 +4,98 @@
|
||||
|
||||
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"),
|
||||
const reservedWords = {
|
||||
strict: [
|
||||
"implements",
|
||||
"interface",
|
||||
"let",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"static",
|
||||
"yield",
|
||||
],
|
||||
strictBind: ["eval", "arguments"],
|
||||
};
|
||||
|
||||
// And the keywords
|
||||
|
||||
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",
|
||||
const reservedWordsStrictSet = new Set(reservedWords.strict);
|
||||
const reservedWordsStrictBindSet = new Set(
|
||||
reservedWords.strict.concat(reservedWords.strictBind),
|
||||
);
|
||||
|
||||
/**
|
||||
* Checks if word is a reserved word in non-strict mode
|
||||
*/
|
||||
export const isReservedWord = (word: string, inModule: boolean): boolean => {
|
||||
return (inModule && word === "await") || word === "enum";
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if word is a reserved word in non-binding strict mode
|
||||
*
|
||||
* Includes non-strict reserved words
|
||||
*/
|
||||
export function isStrictReservedWord(word: string, inModule: boolean): boolean {
|
||||
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if word is a reserved word in binding strict mode
|
||||
*
|
||||
* Includes non-strict reserved words and non-binding strict reserved words
|
||||
*/
|
||||
export function isStrictBindReservedWord(
|
||||
word: string,
|
||||
inModule: boolean,
|
||||
): boolean {
|
||||
return isReservedWord(word, inModule) || reservedWordsStrictBindSet.has(word);
|
||||
}
|
||||
|
||||
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",
|
||||
"const",
|
||||
"class",
|
||||
"extends",
|
||||
"export",
|
||||
"import",
|
||||
"super",
|
||||
]);
|
||||
|
||||
export function isKeyword(word: string): boolean {
|
||||
return keywords.has(word);
|
||||
}
|
||||
|
||||
export const keywordRelationalOperator = /^in(stanceof)?$/;
|
||||
|
||||
// ## Character categories
|
||||
|
||||
// Big ugly regular expressions that matches characters in the
|
||||
@@ -64,7 +133,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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"strictMode": true,
|
||||
"throws": "public is a reserved word in strict mode (2:0)"
|
||||
"throws": "Unexpected reserved word 'public' (2:0)"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Function declaration not allowed in this context (1:10)"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
while (1) foo: bar: function foo(){}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Function declaration not allowed in this context (1:20)"
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-false/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-false/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
for await (const i of imports) {}
|
||||
3
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-false/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-false/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \"(\" (1:4)"
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-true/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-true/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
for await (const i of imports) {}
|
||||
3
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-true/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-true/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"allowAwaitOutsideFunction": true
|
||||
}
|
||||
136
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-true/output.json
vendored
Normal file
136
packages/babel-parser/test/fixtures/core/opts/allowAwaitOutsideFunction-true/output.json
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 33,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 33
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 33,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 33
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ForOfStatement",
|
||||
"start": 0,
|
||||
"end": 33,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 33
|
||||
}
|
||||
},
|
||||
"await": true,
|
||||
"left": {
|
||||
"type": "VariableDeclaration",
|
||||
"start": 11,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 11
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"start": 17,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 17,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 18
|
||||
},
|
||||
"identifierName": "i"
|
||||
},
|
||||
"name": "i"
|
||||
},
|
||||
"init": null
|
||||
}
|
||||
],
|
||||
"kind": "const"
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"start": 22,
|
||||
"end": 29,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 22
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 29
|
||||
},
|
||||
"identifierName": "imports"
|
||||
},
|
||||
"name": "imports"
|
||||
},
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"start": 31,
|
||||
"end": 33,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 31
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 33
|
||||
}
|
||||
},
|
||||
"body": [],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
3
packages/babel-parser/test/fixtures/core/regression/9374/input.js
vendored
Normal file
3
packages/babel-parser/test/fixtures/core/regression/9374/input.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
function* test() {
|
||||
yield new Foo();
|
||||
}
|
||||
152
packages/babel-parser/test/fixtures/core/regression/9374/output.json
vendored
Normal file
152
packages/babel-parser/test/fixtures/core/regression/9374/output.json
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 39,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 39,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"start": 0,
|
||||
"end": 39,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 10,
|
||||
"end": 14,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 14
|
||||
},
|
||||
"identifierName": "test"
|
||||
},
|
||||
"name": "test"
|
||||
},
|
||||
"generator": true,
|
||||
"async": false,
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"start": 17,
|
||||
"end": 39,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"start": 21,
|
||||
"end": 37,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "YieldExpression",
|
||||
"start": 21,
|
||||
"end": 36,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"delegate": false,
|
||||
"argument": {
|
||||
"type": "NewExpression",
|
||||
"start": 27,
|
||||
"end": 36,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 17
|
||||
}
|
||||
},
|
||||
"callee": {
|
||||
"type": "Identifier",
|
||||
"start": 31,
|
||||
"end": 34,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 12
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"identifierName": "Foo"
|
||||
},
|
||||
"name": "Foo"
|
||||
},
|
||||
"arguments": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user