Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1fe2d05f4 | ||
|
|
b9a3806f9e | ||
|
|
b25fea49fe | ||
|
|
83cbc11d46 | ||
|
|
0f685d9b42 | ||
|
|
d86b831364 | ||
|
|
0050266a50 | ||
|
|
b6300a0869 | ||
|
|
4ba998c5db | ||
|
|
2fb1f9aed3 | ||
|
|
85ea5b0b50 | ||
|
|
d349b74a4f | ||
|
|
3a9743fce4 | ||
|
|
2817844e89 | ||
|
|
7943a48cc3 | ||
|
|
953182d44a | ||
|
|
045d019149 | ||
|
|
d1514f57bd | ||
|
|
fdb65ab8b1 | ||
|
|
81123fb972 | ||
|
|
738060ebfa | ||
|
|
07b0f22a3f | ||
|
|
e03e5ba01d | ||
|
|
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 | ||
|
|
8b132c0889 | ||
|
|
b927fb2a7e |
@@ -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: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
16
.github/actions/filter-commit-message/Dockerfile
vendored
Normal file
16
.github/actions/filter-commit-message/Dockerfile
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM debian:stable-slim
|
||||
|
||||
LABEL "name"="filter"
|
||||
LABEL "version"="1.1.0"
|
||||
|
||||
LABEL "com.github.actions.name"="Filter commit message"
|
||||
LABEL "com.github.actions.description"="Stop a workflow if the message of the current commit doesn't match the pattern"
|
||||
LABEL "com.github.actions.icon"="filter"
|
||||
LABEL "com.github.actions.color"="gray-dark"
|
||||
|
||||
ADD entrypoint.sh /action/entrypoint.sh
|
||||
|
||||
RUN chmod +x /action/entrypoint.sh
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends git
|
||||
|
||||
ENTRYPOINT ["/action/entrypoint.sh"]
|
||||
15
.github/actions/filter-commit-message/entrypoint.sh
vendored
Normal file
15
.github/actions/filter-commit-message/entrypoint.sh
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
pattern=$1
|
||||
message=$(git log --oneline --format=%B -1 $GITHUB_SHA)
|
||||
|
||||
if echo "$message" | grep -Pq "$pattern"; then
|
||||
echo "INFO: $message matches $pattern"
|
||||
exit 0
|
||||
else
|
||||
echo "INFO: $message does not match $pattern"
|
||||
# 78 is the "neutral" exit status
|
||||
exit 78
|
||||
fi
|
||||
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"]
|
||||
38
.github/actions/trigger-github-release/entrypoint.sh
vendored
Executable file
38
.github/actions/trigger-github-release/entrypoint.sh
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "INFO: Installing action dependencies..."
|
||||
(cd /action; npm ci)
|
||||
|
||||
echo "INFO: Checking out current commit..."
|
||||
git -c advice.detachedHead=false checkout $GITHUB_SHA
|
||||
|
||||
# GitHub doesn't support running actions on new tags yet: we need to run it on the commit.
|
||||
# For this reason, we can't be sure that the tag already exists. We can use the commit
|
||||
# message to create the tag. If the tag already exists locally, they won't conflict because
|
||||
# they have the same name and are on the same commit.
|
||||
echo "INFO: Getting release version..."
|
||||
# current_tag=$(git describe --abbrev=0 --tags HEAD)
|
||||
current_tag=$(git log --oneline --format=%B -1 HEAD)
|
||||
|
||||
echo "INFO: Creating new tag..."
|
||||
(git tag $current_tag $GITHUB_SHA) || echo "INFO: Tag already exists"
|
||||
|
||||
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);
|
||||
});
|
||||
28
.github/main.workflow
vendored
Normal file
28
.github/main.workflow
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
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 commit",
|
||||
"On master branch",
|
||||
]
|
||||
}
|
||||
|
||||
action "Is version commit" {
|
||||
uses = "./.github/actions/filter-commit-message"
|
||||
# This regex is run using "grep -P".
|
||||
# The (-\\S+) part is for 7.0.0-beta.1 releases.
|
||||
args = "^v(\\d+\\.){2}\\d+(-\\S+)?$"
|
||||
}
|
||||
|
||||
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`).
|
||||
|
||||
13
Gulpfile.js
13
Gulpfile.js
@@ -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");
|
||||
@@ -17,8 +17,7 @@ const source = require("vinyl-source-stream");
|
||||
const buffer = require("vinyl-buffer");
|
||||
const rollupBabel = require("rollup-plugin-babel");
|
||||
const rollupNodeResolve = require("rollup-plugin-node-resolve");
|
||||
const registerStandalonePackageTask = require("./scripts/gulp-tasks")
|
||||
.registerStandalonePackageTask;
|
||||
const { registerStandalonePackageTask } = require("./scripts/gulp-tasks");
|
||||
|
||||
const sources = ["codemods", "packages"];
|
||||
|
||||
@@ -38,7 +37,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 +49,7 @@ function compilationLogger(rollup) {
|
||||
function errorsLogger() {
|
||||
return plumber({
|
||||
errorHandler(err) {
|
||||
gutil.log(err.stack);
|
||||
fancyLog(err.stack);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -138,7 +137,7 @@ registerStandalonePackageTask(
|
||||
"babel",
|
||||
"Babel",
|
||||
path.join(__dirname, "packages"),
|
||||
require("./packages/babel-core/package.json").version
|
||||
require("./packages/babel-standalone/package.json").version
|
||||
);
|
||||
|
||||
const presetEnvWebpackPlugins = [
|
||||
@@ -167,6 +166,6 @@ registerStandalonePackageTask(
|
||||
"babel-preset-env",
|
||||
"babelPresetEnv",
|
||||
path.join(__dirname, "packages"),
|
||||
require("./packages/babel-preset-env/package.json").version,
|
||||
require("./packages/babel-preset-env-standalone/package.json").version,
|
||||
presetEnvWebpackPlugins
|
||||
);
|
||||
|
||||
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
|
||||
|
||||
28
Makefile
28
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:
|
||||
@@ -123,9 +130,12 @@ prepublish:
|
||||
make prepublish-build
|
||||
make test
|
||||
|
||||
new-version:
|
||||
./node_modules/.bin/lerna version --force-publish="@babel/runtime,@babel/runtime-corejs2,@babel/standalone,@babel/preset-env-standalone"
|
||||
|
||||
# NOTE: Run make new-version first
|
||||
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 from-git --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":
|
||||
|
||||
@@ -8,3 +8,5 @@ coverage:
|
||||
target: "80%"
|
||||
patch:
|
||||
enabled: false
|
||||
ignore:
|
||||
- packages/babel-types/src/*/generated/index.js
|
||||
|
||||
15
lerna.json
15
lerna.json
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"lerna": "2.11.0",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.3",
|
||||
"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": [
|
||||
|
||||
75
package.json
75
package.json
@@ -9,55 +9,55 @@
|
||||
"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",
|
||||
"duplicate-package-checker-webpack-plugin": "^2.1.0",
|
||||
"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.92.1",
|
||||
"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 +69,9 @@
|
||||
"webpack-dependency-suite": "^2.4.4",
|
||||
"webpack-stream": "^4.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@lerna/**/@lerna/collect-updates": "https://github.com/nicolo-ribaudo/lerna.git#babel-collect-updates"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.9.0 < 12.0.0",
|
||||
"npm": ">= 3.x <= 6.x",
|
||||
@@ -105,7 +108,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 +129,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.3.3",
|
||||
"description": "Babel compiler core.",
|
||||
"main": "lib/index.js",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
@@ -34,16 +34,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/generator": "^7.2.0",
|
||||
"@babel/generator": "^7.3.3",
|
||||
"@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.3.3",
|
||||
"@babel/template": "^7.2.2",
|
||||
"@babel/traverse": "^7.2.2",
|
||||
"@babel/types": "^7.3.3",
|
||||
"convert-source-map": "^1.1.0",
|
||||
"debug": "^4.1.0",
|
||||
"json5": "^2.1.0",
|
||||
"lodash": "^4.17.10",
|
||||
"lodash": "^4.17.11",
|
||||
"resolve": "^1.3.2",
|
||||
"semver": "^5.4.1",
|
||||
"source-map": "^0.5.0"
|
||||
|
||||
@@ -54,6 +54,7 @@ function makeCachedFunction<
|
||||
ArgT,
|
||||
ResultT,
|
||||
SideChannel,
|
||||
// $FlowIssue https://github.com/facebook/flow/issues/4528
|
||||
Cache: CacheMap<ArgT, ResultT, SideChannel>,
|
||||
>(
|
||||
callCache: Cache,
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
makeWeakCache,
|
||||
type CacheConfigurator,
|
||||
} from "../caching";
|
||||
import makeAPI from "../helpers/config-api";
|
||||
import makeAPI, { type PluginAPI } from "../helpers/config-api";
|
||||
import { makeStaticFileCache } from "./utils";
|
||||
import pathPatternToRegex from "../pattern-to-regex";
|
||||
import type { FilePackageData, RelativeConfig, ConfigFile } from "./types";
|
||||
@@ -150,7 +150,7 @@ const LOADING_CONFIGS = new Set();
|
||||
|
||||
const readConfigJS = makeStrongCache(
|
||||
(
|
||||
filepath,
|
||||
filepath: string,
|
||||
cache: CacheConfigurator<{
|
||||
envName: string,
|
||||
caller: CallerMetadata | void,
|
||||
@@ -193,7 +193,7 @@ const readConfigJS = makeStrongCache(
|
||||
}
|
||||
|
||||
if (typeof options === "function") {
|
||||
options = options(makeAPI(cache));
|
||||
options = ((options: any): (api: PluginAPI) => {})(makeAPI(cache));
|
||||
|
||||
if (!cache.configured()) throwConfigError();
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
});
|
||||
|
||||
@@ -131,6 +131,7 @@ function isThenable(val: mixed): boolean {
|
||||
return (
|
||||
!!val &&
|
||||
(typeof val === "object" || typeof val === "function") &&
|
||||
!!val.then &&
|
||||
typeof val.then === "function"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/generator",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.3",
|
||||
"description": "Turns an AST into code.",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -14,14 +14,14 @@
|
||||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.2.0",
|
||||
"@babel/types": "^7.3.3",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.10",
|
||||
"lodash": "^4.17.11",
|
||||
"source-map": "^0.5.0",
|
||||
"trim-right": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/helper-fixtures": "^7.2.0",
|
||||
"@babel/parser": "^7.2.0"
|
||||
"@babel/parser": "^7.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,35 @@ export function Directive(node: Object) {
|
||||
this.semicolon();
|
||||
}
|
||||
|
||||
// These regexes match an even number of \ followed by a quote
|
||||
const unescapedSingleQuoteRE = /(?:^|[^\\])(?:\\\\)*'/;
|
||||
const unescapedDoubleQuoteRE = /(?:^|[^\\])(?:\\\\)*"/;
|
||||
|
||||
export function DirectiveLiteral(node: Object) {
|
||||
const raw = this.getPossibleRaw(node);
|
||||
if (raw != null) {
|
||||
this.token(raw);
|
||||
return;
|
||||
}
|
||||
|
||||
const { value } = node;
|
||||
|
||||
// NOTE: In directives we can't change escapings,
|
||||
// because they change the behavior.
|
||||
// e.g. "us\x65 string" (\x65 is e) is not a "use strict" directive.
|
||||
|
||||
if (!unescapedDoubleQuoteRE.test(value)) {
|
||||
this.token(`"${value}"`);
|
||||
} else if (!unescapedSingleQuoteRE.test(value)) {
|
||||
this.token(`'${value}'`);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Malformed AST: it is not possible to print a directive containing" +
|
||||
" both unescaped single and double quotes.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function InterpreterDirective(node: Object) {
|
||||
this.token(`#!${node.value}\n`);
|
||||
}
|
||||
|
||||
export { StringLiteral as DirectiveLiteral } from "./types";
|
||||
|
||||
@@ -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 +1,2 @@
|
||||
0; // Not a directive
|
||||
"©";
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
0;// Not a directive
|
||||
"\u00A9";
|
||||
@@ -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>;
|
||||
@@ -384,6 +384,48 @@ describe("programmatic generation", function() {
|
||||
[key: any]: number
|
||||
}`);
|
||||
});
|
||||
|
||||
describe("directives", function() {
|
||||
it("preserves escapes", function() {
|
||||
const directive = t.directive(
|
||||
t.directiveLiteral(String.raw`us\x65 strict`),
|
||||
);
|
||||
const output = generate(directive).code;
|
||||
|
||||
expect(output).toBe(String.raw`"us\x65 strict";`);
|
||||
});
|
||||
|
||||
it("preserves escapes in minified output", function() {
|
||||
// https://github.com/babel/babel/issues/4767
|
||||
|
||||
const directive = t.directive(t.directiveLiteral(String.raw`foo\n\t\r`));
|
||||
const output = generate(directive, { minified: true }).code;
|
||||
|
||||
expect(output).toBe(String.raw`"foo\n\t\r";`);
|
||||
});
|
||||
|
||||
it("unescaped single quote", function() {
|
||||
const directive = t.directive(t.directiveLiteral(String.raw`'\'\"`));
|
||||
const output = generate(directive).code;
|
||||
|
||||
expect(output).toBe(String.raw`"'\'\"";`);
|
||||
});
|
||||
|
||||
it("unescaped double quote", function() {
|
||||
const directive = t.directive(t.directiveLiteral(String.raw`"\'\"`));
|
||||
const output = generate(directive).code;
|
||||
|
||||
expect(output).toBe(String.raw`'"\'\"';`);
|
||||
});
|
||||
|
||||
it("unescaped single and double quotes together throw", function() {
|
||||
const directive = t.directive(t.directiveLiteral(String.raw`'"`));
|
||||
|
||||
expect(() => {
|
||||
generate(directive);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("CodeGenerator", function() {
|
||||
|
||||
@@ -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.0",
|
||||
"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,14 @@
|
||||
"@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",
|
||||
"@babel/helper-split-export-declaration": "^7.0.0"
|
||||
},
|
||||
"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,17 +39,30 @@ export function isLoose(file, feature) {
|
||||
}
|
||||
|
||||
export function verifyUsedFeatures(path, file) {
|
||||
if (hasDecorators(path) && !hasFeature(file, FEATURES.decorators)) {
|
||||
throw path.buildCodeFrameError("Decorators are not enabled.");
|
||||
if (hasOwnDecorators(path.node)) {
|
||||
if (!hasFeature(file, FEATURES.decorators)) {
|
||||
throw path.buildCodeFrameError(
|
||||
"Decorators are not enabled." +
|
||||
"\nIf you are using " +
|
||||
'["@babel/plugin-proposal-decorators", { "legacy": true }], ' +
|
||||
'make sure it comes *before* "@babel/plugin-proposal-class-properties" ' +
|
||||
"and enable loose mode, like so:\n" +
|
||||
'\t["@babel/plugin-proposal-decorators", { "legacy": true }]\n' +
|
||||
'\t["@babel/plugin-proposal-class-properties", { "loose": true }]',
|
||||
);
|
||||
}
|
||||
|
||||
if (path.isPrivate()) {
|
||||
throw path.buildCodeFrameError(
|
||||
`Private ${
|
||||
path.isClassMethod() ? "methods" : "fields"
|
||||
} in decorated classes are not supported yet.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFeature(file, FEATURES.decorators)) {
|
||||
throw new Error(
|
||||
"@babel/plugin-class-features doesn't support decorators yet.",
|
||||
);
|
||||
}
|
||||
|
||||
if (path.isClassPrivateMethod()) {
|
||||
// NOTE: We can't use path.isPrivateMethod() because it isn't supported in <7.2.0
|
||||
if (path.isPrivate() && path.isMethod()) {
|
||||
if (!hasFeature(file, FEATURES.privateMethods)) {
|
||||
throw path.buildCodeFrameError("Class private methods are not enabled.");
|
||||
}
|
||||
@@ -59,12 +72,6 @@ export function verifyUsedFeatures(path, file) {
|
||||
"@babel/plugin-class-features doesn't support class static private methods yet.",
|
||||
);
|
||||
}
|
||||
|
||||
if (path.node.kind !== "method") {
|
||||
throw path.buildCodeFrameError(
|
||||
"@babel/plugin-class-features doesn't support class private accessors yet.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
@@ -6,16 +6,26 @@ import optimiseCall from "@babel/helper-optimise-call-expression";
|
||||
export function buildPrivateNamesMap(props) {
|
||||
const privateNamesMap = new Map();
|
||||
for (const prop of props) {
|
||||
if (prop.isPrivate()) {
|
||||
const isPrivate = prop.isPrivate();
|
||||
const isMethod = !prop.isProperty();
|
||||
const isInstance = !prop.node.static;
|
||||
if (isPrivate) {
|
||||
const { name } = prop.node.key.id;
|
||||
privateNamesMap.set(name, {
|
||||
id: prop.scope.generateUidIdentifier(name),
|
||||
static: !!prop.node.static,
|
||||
method: prop.isClassPrivateMethod(),
|
||||
methodId: prop.isClassPrivateMethod()
|
||||
? prop.scope.generateUidIdentifier(name)
|
||||
: undefined,
|
||||
});
|
||||
const update = privateNamesMap.has(name)
|
||||
? privateNamesMap.get(name)
|
||||
: {
|
||||
id: prop.scope.generateUidIdentifier(name),
|
||||
static: !isInstance,
|
||||
method: isMethod,
|
||||
};
|
||||
if (prop.node.kind === "get") {
|
||||
update.getId = prop.scope.generateUidIdentifier(`get_${name}`);
|
||||
} else if (prop.node.kind === "set") {
|
||||
update.setId = prop.scope.generateUidIdentifier(`set_${name}`);
|
||||
} else if (prop.node.kind === "method" && isMethod && isInstance) {
|
||||
update.methodId = prop.scope.generateUidIdentifier(name);
|
||||
}
|
||||
privateNamesMap.set(name, update);
|
||||
}
|
||||
}
|
||||
return privateNamesMap;
|
||||
@@ -31,7 +41,7 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
|
||||
// In spec mode, only instance fields need a "private name" initializer
|
||||
// because static fields are directly assigned to a variable in the
|
||||
// buildPrivateStaticFieldInitSpec function.
|
||||
const { id, static: isStatic, method: isMethod } = value;
|
||||
const { id, static: isStatic, method: isMethod, getId, setId } = value;
|
||||
if (loose) {
|
||||
initNodes.push(
|
||||
template.statement.ast`
|
||||
@@ -39,7 +49,11 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
|
||||
`,
|
||||
);
|
||||
} else if (isMethod && !isStatic) {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
|
||||
if (getId || setId) {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
|
||||
} else {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
|
||||
}
|
||||
} else if (!isStatic) {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
|
||||
}
|
||||
@@ -121,6 +135,8 @@ const privateNameHandlerSpec = {
|
||||
static: isStatic,
|
||||
method: isMethod,
|
||||
methodId,
|
||||
getId,
|
||||
setId,
|
||||
} = privateNamesMap.get(name);
|
||||
|
||||
if (isStatic && !isMethod) {
|
||||
@@ -128,41 +144,57 @@ const privateNameHandlerSpec = {
|
||||
file.addHelper("classStaticPrivateFieldSpecGet"),
|
||||
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id)],
|
||||
);
|
||||
} else if (isMethod) {
|
||||
}
|
||||
if (isMethod) {
|
||||
if (getId || setId) {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
]);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateMethodGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
t.cloneNode(methodId),
|
||||
]);
|
||||
} else {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
]);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
]);
|
||||
},
|
||||
|
||||
set(member, value) {
|
||||
const { classRef, privateNamesMap, file } = this;
|
||||
const { name } = member.node.property.id;
|
||||
const { id, static: isStatic, method: isMethod } = privateNamesMap.get(
|
||||
name,
|
||||
);
|
||||
const {
|
||||
id,
|
||||
static: isStatic,
|
||||
method: isMethod,
|
||||
setId,
|
||||
} = privateNamesMap.get(name);
|
||||
|
||||
if (isStatic && !isMethod) {
|
||||
return t.callExpression(
|
||||
file.addHelper("classStaticPrivateFieldSpecSet"),
|
||||
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id), value],
|
||||
);
|
||||
} else if (isMethod) {
|
||||
return t.callExpression(file.addHelper("classPrivateMethodSet"), []);
|
||||
} else {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
value,
|
||||
]);
|
||||
}
|
||||
if (isMethod) {
|
||||
if (setId) {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
value,
|
||||
]);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateMethodSet"), []);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
value,
|
||||
]);
|
||||
},
|
||||
|
||||
call(member, args) {
|
||||
@@ -255,21 +287,91 @@ function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
|
||||
}
|
||||
|
||||
function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
|
||||
const { methodId, id } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||
const { methodId, id, getId, setId, initAdded } = privateName;
|
||||
if (initAdded) return;
|
||||
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
value: ${methodId.name}
|
||||
if (methodId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
value: ${methodId.name}
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
if (getId || setId) {
|
||||
privateNamesMap.set(prop.node.key.id.name, {
|
||||
...privateName,
|
||||
initAdded: true,
|
||||
});
|
||||
`;
|
||||
|
||||
if (getId && setId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
get: ${getId.name},
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
} else if (getId && !setId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
get: ${getId.name}
|
||||
});
|
||||
`;
|
||||
} else if (!getId && setId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
|
||||
const { id } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||
const { id, getId, setId, initAdded } = privateName;
|
||||
if (initAdded) return;
|
||||
|
||||
if (getId || setId) {
|
||||
privateNamesMap.set(prop.node.key.id.name, {
|
||||
...privateName,
|
||||
initAdded: true,
|
||||
});
|
||||
|
||||
if (getId && setId) {
|
||||
return template.statement.ast`
|
||||
${id}.set(${ref}, {
|
||||
get: ${getId.name},
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
} else if (getId && !setId) {
|
||||
return template.statement.ast`
|
||||
${id}.set(${ref}, {
|
||||
get: ${getId.name}
|
||||
});
|
||||
`;
|
||||
} else if (!getId && setId) {
|
||||
return template.statement.ast`
|
||||
${id}.set(${ref}, {
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
}
|
||||
}
|
||||
return template.statement.ast`${id}.add(${ref})`;
|
||||
}
|
||||
|
||||
@@ -300,9 +402,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,37 +454,45 @@ export function buildFieldsInitNodes(
|
||||
) {
|
||||
const staticNodes = [];
|
||||
const instanceNodes = [];
|
||||
let needsClassRef = false;
|
||||
|
||||
for (const prop of props) {
|
||||
const isStatic = prop.node.static;
|
||||
const isPrivateField = prop.isClassPrivateProperty();
|
||||
const isPrivateMethod = prop.isClassPrivateMethod();
|
||||
const isInstance = !isStatic;
|
||||
const isPrivate = prop.isPrivate();
|
||||
const isPublic = !isPrivate;
|
||||
const isField = prop.isProperty();
|
||||
const isMethod = !isField;
|
||||
|
||||
switch (true) {
|
||||
case isStatic && isPrivateField && loose:
|
||||
case isStatic && isPrivate && isField && loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(
|
||||
buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case isStatic && isPrivateField && !loose:
|
||||
case isStatic && isPrivate && isField && !loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(
|
||||
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case isStatic && !isPrivateField && loose:
|
||||
case isStatic && isPublic && isField && loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop));
|
||||
break;
|
||||
case isStatic && !isPrivateField && !loose:
|
||||
case isStatic && isPublic && isField && !loose:
|
||||
needsClassRef = true;
|
||||
staticNodes.push(
|
||||
buildPublicFieldInitSpec(t.cloneNode(ref), prop, state),
|
||||
);
|
||||
break;
|
||||
case !isStatic && isPrivateField && loose:
|
||||
case isInstance && isPrivate && isField && loose:
|
||||
instanceNodes.push(
|
||||
buildPrivateFieldInitLoose(t.thisExpression(), prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case !isStatic && isPrivateField && !loose:
|
||||
case isInstance && isPrivate && isField && !loose:
|
||||
instanceNodes.push(
|
||||
buildPrivateInstanceFieldInitSpec(
|
||||
t.thisExpression(),
|
||||
@@ -357,8 +501,8 @@ export function buildFieldsInitNodes(
|
||||
),
|
||||
);
|
||||
break;
|
||||
case !isStatic && isPrivateMethod && loose:
|
||||
instanceNodes.push(
|
||||
case isInstance && isPrivate && isMethod && loose:
|
||||
instanceNodes.unshift(
|
||||
buildPrivateMethodInitLoose(
|
||||
t.thisExpression(),
|
||||
prop,
|
||||
@@ -369,8 +513,8 @@ export function buildFieldsInitNodes(
|
||||
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case !isStatic && isPrivateMethod && !loose:
|
||||
instanceNodes.push(
|
||||
case isInstance && isPrivate && isMethod && !loose:
|
||||
instanceNodes.unshift(
|
||||
buildPrivateInstanceMethodInitSpec(
|
||||
t.thisExpression(),
|
||||
prop,
|
||||
@@ -381,10 +525,10 @@ export function buildFieldsInitNodes(
|
||||
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
|
||||
);
|
||||
break;
|
||||
case !isStatic && !isPrivateField && loose:
|
||||
case isInstance && isPublic && isField && loose:
|
||||
instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop));
|
||||
break;
|
||||
case !isStatic && !isPrivateField && !loose:
|
||||
case isInstance && isPublic && isField && !loose:
|
||||
instanceNodes.push(
|
||||
buildPublicFieldInitSpec(t.thisExpression(), prop, state),
|
||||
);
|
||||
@@ -394,5 +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.isClassPrivateMethod()) {
|
||||
props.push(path);
|
||||
} else if (path.isClassMethod({ kind: "constructor" })) {
|
||||
if (path.isClassMethod({ kind: "constructor" })) {
|
||||
constructor = path;
|
||||
} else {
|
||||
elements.push(path);
|
||||
if (path.isProperty() || path.isPrivate()) {
|
||||
props.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDecorated) isDecorated = hasOwnDecorators(path.node);
|
||||
}
|
||||
|
||||
if (!props.length) return;
|
||||
if (!props.length && !isDecorated) return;
|
||||
|
||||
let ref;
|
||||
|
||||
@@ -93,13 +133,9 @@ export function createClassFeaturePlugin({
|
||||
ref = path.node.id;
|
||||
}
|
||||
|
||||
const keysNodes = extractComputedKeys(
|
||||
ref,
|
||||
path,
|
||||
computedPaths,
|
||||
this.file,
|
||||
);
|
||||
|
||||
// NODE: These three functions don't support decorators yet,
|
||||
// but verifyUsedFeatures throws if there are both
|
||||
// decorators and private fields.
|
||||
const privateNamesMap = buildPrivateNamesMap(props);
|
||||
const privateNamesNodes = buildPrivateNamesNodes(
|
||||
privateNamesMap,
|
||||
@@ -109,19 +145,34 @@ export function createClassFeaturePlugin({
|
||||
|
||||
transformPrivateNamesUsage(ref, path, privateNamesMap, loose, state);
|
||||
|
||||
const { staticNodes, instanceNodes } = buildFieldsInitNodes(
|
||||
ref,
|
||||
props,
|
||||
privateNamesMap,
|
||||
state,
|
||||
loose,
|
||||
);
|
||||
let keysNodes, staticNodes, instanceNodes, wrapClass;
|
||||
|
||||
if (isDecorated) {
|
||||
staticNodes = keysNodes = [];
|
||||
({ instanceNodes, wrapClass } = buildDecoratedClass(
|
||||
ref,
|
||||
path,
|
||||
elements,
|
||||
this.file,
|
||||
));
|
||||
} else {
|
||||
keysNodes = extractComputedKeys(ref, path, computedPaths, this.file);
|
||||
({ staticNodes, instanceNodes, wrapClass } = buildFieldsInitNodes(
|
||||
ref,
|
||||
props,
|
||||
privateNamesMap,
|
||||
state,
|
||||
loose,
|
||||
));
|
||||
}
|
||||
|
||||
if (instanceNodes.length > 0) {
|
||||
injectInitialization(
|
||||
path,
|
||||
constructor,
|
||||
instanceNodes,
|
||||
(referenceVisitor, state) => {
|
||||
if (isDecorated) return;
|
||||
for (const prop of props) {
|
||||
if (prop.node.static) continue;
|
||||
prop.traverse(referenceVisitor, state);
|
||||
@@ -130,28 +181,7 @@ export function createClassFeaturePlugin({
|
||||
);
|
||||
}
|
||||
|
||||
for (const prop of props) {
|
||||
prop.remove();
|
||||
}
|
||||
|
||||
if (
|
||||
keysNodes.length === 0 &&
|
||||
staticNodes.length === 0 &&
|
||||
privateNamesNodes.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.isClassExpression()) {
|
||||
path.scope.push({ id: ref });
|
||||
path.replaceWith(
|
||||
t.assignmentExpression("=", t.cloneNode(ref), path.node),
|
||||
);
|
||||
} else if (!path.node.id) {
|
||||
// Anonymous class declaration
|
||||
path.node.id = ref;
|
||||
}
|
||||
|
||||
path = wrapClass(path);
|
||||
path.insertBefore(keysNodes);
|
||||
path.insertAfter([...privateNamesNodes, ...staticNodes]);
|
||||
},
|
||||
@@ -161,6 +191,25 @@ export function createClassFeaturePlugin({
|
||||
|
||||
throw path.buildCodeFrameError(`Unknown PrivateName "${path}"`);
|
||||
},
|
||||
|
||||
ExportDefaultDeclaration(path) {
|
||||
if (this.file.get(versionKey) !== version) return;
|
||||
|
||||
const decl = path.get("declaration");
|
||||
|
||||
if (decl.isClassDeclaration() && hasDecorators(decl.node)) {
|
||||
if (decl.node.id) {
|
||||
// export default class Foo {}
|
||||
// -->
|
||||
// class Foo {} export { Foo as default }
|
||||
splitExportDeclaration(path);
|
||||
} else {
|
||||
// Annyms class declarations can be
|
||||
// transformed as if they were expressions
|
||||
decl.node.type = "ClassExpression";
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,6 @@
|
||||
"dependencies": {
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"lodash": "^4.17.10"
|
||||
"lodash": "^4.17.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-fixtures",
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.10",
|
||||
"lodash": "^4.17.11",
|
||||
"semver": "^5.3.0",
|
||||
"try-resolve": "^1.0.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",
|
||||
"lodash": "^4.17.10"
|
||||
"@babel/template": "^7.2.2",
|
||||
"@babel/types": "^7.2.2",
|
||||
"lodash": "^4.17.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.10"
|
||||
"lodash": "^4.17.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"babel-check-duplicated-nodes": "^1.0.0",
|
||||
"jest": "^22.4.2",
|
||||
"jest-diff": "^22.4.0",
|
||||
"lodash": "^4.17.10",
|
||||
"lodash": "^4.17.11",
|
||||
"resolve": "^1.3.2",
|
||||
"source-map": "^0.5.0"
|
||||
}
|
||||
|
||||
@@ -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/",
|
||||
@@ -22,14 +22,14 @@
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"commander": "^2.8.1",
|
||||
"lodash": "^4.17.10",
|
||||
"lodash": "^4.17.11",
|
||||
"v8flags": "^3.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@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'.",
|
||||
|
||||
6
packages/babel-node/test/fixtures/babel-node/node_--inspect/options.json
vendored
Normal file
6
packages/babel-node/test/fixtures/babel-node/node_--inspect/options.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"args": ["--inspect", "--eval", "console.log('foo');"],
|
||||
"stderr": "Debugger listening on",
|
||||
"stderrContains": true,
|
||||
"stdout": "foo"
|
||||
}
|
||||
4
packages/babel-node/test/fixtures/babel-node/node_--no-lazy/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/node_--no-lazy/options.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["--nolazy", "--eval", "console.log('foo')"],
|
||||
"stdout": "foo"
|
||||
}
|
||||
4
packages/babel-node/test/fixtures/babel-node/node_-gc_alias_--expose-gc/options.json
vendored
Normal file
4
packages/babel-node/test/fixtures/babel-node/node_-gc_alias_--expose-gc/options.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"args": ["-gc", "--eval", "console.log(typeof global.gc)"],
|
||||
"stdout": "function"
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1149,6 +1149,7 @@ A specifier in an import or export declaration.
|
||||
```js
|
||||
interface ImportDeclaration <: ModuleDeclaration {
|
||||
type: "ImportDeclaration";
|
||||
importKind: null | "type" | "typeof" | "value";
|
||||
specifiers: [ ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier ];
|
||||
source: Literal;
|
||||
}
|
||||
@@ -1156,6 +1157,8 @@ interface ImportDeclaration <: ModuleDeclaration {
|
||||
|
||||
An import declaration, e.g., `import foo from "mod";`.
|
||||
|
||||
> importKind is only set when `flow` plugin enabled in babel-parser
|
||||
|
||||
### ImportSpecifier
|
||||
|
||||
```js
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/parser",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.3",
|
||||
"description": "A JavaScript parser",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -28,9 +28,10 @@
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@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,35 @@ export default class StatementParser extends ExpressionParser {
|
||||
return this.finishNode(node, "InterpreterDirective");
|
||||
}
|
||||
|
||||
isLet(context: ?string): 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);
|
||||
// For ambiguous cases, determine if a LexicalDeclaration (or only a
|
||||
// Statement) is allowed here. If context is not empty then only a Statement
|
||||
// is allowed. However, `let [` is an explicit negative lookahead for
|
||||
// ExpressionStatement, so special-case it first.
|
||||
if (nextCh === charCodes.leftSquareBracket) return true;
|
||||
if (context) return false;
|
||||
|
||||
if (nextCh === charCodes.leftCurlyBrace) return true;
|
||||
|
||||
if (isIdentifierStart(nextCh)) {
|
||||
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
|
||||
@@ -78,16 +112,22 @@ export default class StatementParser extends ExpressionParser {
|
||||
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
|
||||
// does not help.
|
||||
|
||||
parseStatement(declaration: boolean, topLevel?: boolean): N.Statement {
|
||||
parseStatement(context: ?string, topLevel?: boolean): N.Statement {
|
||||
if (this.match(tt.at)) {
|
||||
this.parseDecorators(true);
|
||||
}
|
||||
return this.parseStatementContent(declaration, topLevel);
|
||||
return this.parseStatementContent(context, topLevel);
|
||||
}
|
||||
|
||||
parseStatementContent(declaration: boolean, topLevel: ?boolean): N.Statement {
|
||||
const starttype = this.state.type;
|
||||
parseStatementContent(context: ?string, topLevel: ?boolean): N.Statement {
|
||||
let starttype = this.state.type;
|
||||
const node = this.startNode();
|
||||
let kind;
|
||||
|
||||
if (this.isLet(context)) {
|
||||
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
|
||||
@@ -104,13 +144,28 @@ export default class StatementParser extends ExpressionParser {
|
||||
return this.parseDoStatement(node);
|
||||
case tt._for:
|
||||
return this.parseForStatement(node);
|
||||
case tt._function:
|
||||
case tt._function: {
|
||||
if (this.lookahead().type === tt.dot) break;
|
||||
if (!declaration) this.unexpected();
|
||||
return this.parseFunctionStatement(node);
|
||||
if (
|
||||
context &&
|
||||
(this.state.strict || (context !== "if" && context !== "label"))
|
||||
) {
|
||||
this.raise(
|
||||
this.state.start,
|
||||
"Function declaration not allowed in this context",
|
||||
);
|
||||
}
|
||||
const result = this.parseFunctionStatement(node);
|
||||
|
||||
// TODO: Remove this once we have proper scope tracking in place.
|
||||
if (context && result.generator) {
|
||||
this.unexpected(node.start);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
case tt._class:
|
||||
if (!declaration) this.unexpected();
|
||||
if (context) this.unexpected();
|
||||
return this.parseClass(node, true);
|
||||
|
||||
case tt._if:
|
||||
@@ -124,12 +179,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 (context && kind !== "var") this.unexpected();
|
||||
return this.parseVarStatement(node, kind);
|
||||
|
||||
case tt._while:
|
||||
return this.parseWhileStatement(node);
|
||||
@@ -156,7 +210,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 +243,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 (context) {
|
||||
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 +270,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, context);
|
||||
} else {
|
||||
return this.parseExpressionStatement(node, expr);
|
||||
}
|
||||
@@ -376,7 +436,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
// outside of the loop body.
|
||||
this.withTopicForbiddingContext(() =>
|
||||
// Parse the loop body's body.
|
||||
this.parseStatement(false),
|
||||
this.parseStatement("do"),
|
||||
);
|
||||
|
||||
this.state.labels.pop();
|
||||
@@ -399,32 +459,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 +496,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 +514,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);
|
||||
}
|
||||
@@ -468,8 +532,8 @@ export default class StatementParser extends ExpressionParser {
|
||||
parseIfStatement(node: N.IfStatement): N.IfStatement {
|
||||
this.next();
|
||||
node.test = this.parseParenExpression();
|
||||
node.consequent = this.parseStatement(false);
|
||||
node.alternate = this.eat(tt._else) ? this.parseStatement(false) : null;
|
||||
node.consequent = this.parseStatement("if");
|
||||
node.alternate = this.eat(tt._else) ? this.parseStatement("if") : null;
|
||||
return this.finishNode(node, "IfStatement");
|
||||
}
|
||||
|
||||
@@ -525,7 +589,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.expect(tt.colon);
|
||||
} else {
|
||||
if (cur) {
|
||||
cur.consequent.push(this.parseStatement(true));
|
||||
cur.consequent.push(this.parseStatement(null));
|
||||
} else {
|
||||
this.unexpected();
|
||||
}
|
||||
@@ -540,7 +604,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 +659,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);
|
||||
@@ -612,7 +678,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
// They are permitted in test expressions, outside of the loop body.
|
||||
this.withTopicForbiddingContext(() =>
|
||||
// Parse loop body.
|
||||
this.parseStatement(false),
|
||||
this.parseStatement("while"),
|
||||
);
|
||||
|
||||
this.state.labels.pop();
|
||||
@@ -634,7 +700,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
// part of the outer context, outside of the function body.
|
||||
this.withTopicForbiddingContext(() =>
|
||||
// Parse the statement body.
|
||||
this.parseStatement(false),
|
||||
this.parseStatement("with"),
|
||||
);
|
||||
|
||||
return this.finishNode(node, "WithStatement");
|
||||
@@ -649,6 +715,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
node: N.LabeledStatement,
|
||||
maybeName: string,
|
||||
expr: N.Identifier,
|
||||
context: ?string,
|
||||
): N.LabeledStatement {
|
||||
for (const label of this.state.labels) {
|
||||
if (label.name === maybeName) {
|
||||
@@ -676,16 +743,13 @@ export default class StatementParser extends ExpressionParser {
|
||||
kind: kind,
|
||||
statementStart: this.state.start,
|
||||
});
|
||||
node.body = this.parseStatement(true);
|
||||
|
||||
if (
|
||||
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");
|
||||
}
|
||||
node.body = this.parseStatement(
|
||||
context
|
||||
? context.indexOf("label") === -1
|
||||
? context + "label"
|
||||
: context
|
||||
: "label",
|
||||
);
|
||||
|
||||
this.state.labels.pop();
|
||||
node.label = expr;
|
||||
@@ -752,7 +816,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
octalPosition = this.state.octalPosition;
|
||||
}
|
||||
|
||||
const stmt = this.parseStatement(true, topLevel);
|
||||
const stmt = this.parseStatement(null, topLevel);
|
||||
|
||||
if (directives && !parsedNonDirective && this.isValidDirective(stmt)) {
|
||||
const directive = this.stmtToDirective(stmt);
|
||||
@@ -800,7 +864,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
// outside of the loop body.
|
||||
this.withTopicForbiddingContext(() =>
|
||||
// Parse the loop body.
|
||||
this.parseStatement(false),
|
||||
this.parseStatement("for"),
|
||||
);
|
||||
|
||||
this.state.labels.pop();
|
||||
@@ -814,16 +878,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();
|
||||
@@ -835,7 +899,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
// They are permitted in test expressions, outside of the loop body.
|
||||
this.withTopicForbiddingContext(() =>
|
||||
// Parse loop body.
|
||||
this.parseStatement(false),
|
||||
this.parseStatement("for"),
|
||||
);
|
||||
|
||||
this.state.labels.pop();
|
||||
@@ -848,24 +912,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 +949,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 +963,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 +1001,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 +1028,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 +1046,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
);
|
||||
|
||||
this.state.inParameters = oldInParameters;
|
||||
this.checkYieldAwaitInDefaultParams();
|
||||
}
|
||||
|
||||
// Parse a class declaration or literal (depending on the
|
||||
@@ -993,9 +1059,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 +1094,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 +1158,6 @@ export default class StatementParser extends ExpressionParser {
|
||||
node.body = this.finishNode(classBody, "ClassBody");
|
||||
|
||||
this.state.classLevel--;
|
||||
this.state.strict = oldStrict;
|
||||
}
|
||||
|
||||
parseClassMember(
|
||||
@@ -1262,7 +1332,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 +1521,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 +1636,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 +1657,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 +1689,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.",
|
||||
@@ -1567,12 +1703,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
parseExportDeclaration(node: N.ExportNamedDeclaration): ?N.Declaration {
|
||||
return this.parseStatement(true);
|
||||
return this.parseStatement(null);
|
||||
}
|
||||
|
||||
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 +1722,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 +1737,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 +1757,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 +1836,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 +1893,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 +1929,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 +1938,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 +1955,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);
|
||||
@@ -1561,7 +1566,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
// interfaces
|
||||
parseStatement(declaration: boolean, topLevel?: boolean): N.Statement {
|
||||
parseStatement(context: ?string, topLevel?: boolean): N.Statement {
|
||||
// strict mode handling of `interface` since it's a reserved word
|
||||
if (
|
||||
this.state.strict &&
|
||||
@@ -1572,7 +1577,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.next();
|
||||
return this.flowParseInterface(node);
|
||||
} else {
|
||||
const stmt = super.parseStatement(declaration, topLevel);
|
||||
const stmt = super.parseStatement(context, topLevel);
|
||||
// We will parse a flow pragma in any comment before the first statement.
|
||||
if (this.flowPragma === undefined && !this.isValidDirective(stmt)) {
|
||||
this.flowPragma = null;
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -314,17 +342,18 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
tsParseBindingListForSignature(): $ReadOnlyArray<
|
||||
N.Identifier | N.RestElement | N.ObjectPattern,
|
||||
N.Identifier | N.RestElement | N.ObjectPattern | N.ArrayPattern,
|
||||
> {
|
||||
return this.parseBindingList(tt.parenR).map(pattern => {
|
||||
if (
|
||||
pattern.type !== "Identifier" &&
|
||||
pattern.type !== "RestElement" &&
|
||||
pattern.type !== "ObjectPattern"
|
||||
pattern.type !== "ObjectPattern" &&
|
||||
pattern.type !== "ArrayPattern"
|
||||
) {
|
||||
throw this.unexpected(
|
||||
pattern.start,
|
||||
`Name in a signature must be an Identifier or ObjectPattern, instead got ${
|
||||
`Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got ${
|
||||
pattern.type
|
||||
}`,
|
||||
);
|
||||
@@ -370,8 +399,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 +548,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 +568,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 +667,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()
|
||||
@@ -769,6 +795,21 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.match(tt.bracketL)) {
|
||||
let braceStackCounter = 1;
|
||||
this.next();
|
||||
|
||||
while (braceStackCounter > 0) {
|
||||
if (this.match(tt.bracketL)) {
|
||||
++braceStackCounter;
|
||||
} else if (this.match(tt.bracketR)) {
|
||||
--braceStackCounter;
|
||||
}
|
||||
this.next();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -894,6 +935,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 +944,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 +979,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 +1203,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 +1233,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 +1290,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 +1315,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 +1325,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 +1346,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 +1434,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 +1449,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 +1463,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 +1638,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);
|
||||
@@ -1624,10 +1699,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return super.parseExportDefaultExpression();
|
||||
}
|
||||
|
||||
parseStatementContent(
|
||||
declaration: boolean,
|
||||
topLevel: ?boolean,
|
||||
): N.Statement {
|
||||
parseStatementContent(context: ?string, topLevel: ?boolean): N.Statement {
|
||||
if (this.state.type === tt._const) {
|
||||
const ahead = this.lookahead();
|
||||
if (ahead.type === tt.name && ahead.value === "enum") {
|
||||
@@ -1637,7 +1709,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.tsParseEnumDeclaration(node, /* isConst */ true);
|
||||
}
|
||||
}
|
||||
return super.parseStatementContent(declaration, topLevel);
|
||||
return super.parseStatementContent(context, topLevel);
|
||||
}
|
||||
|
||||
parseAccessModifier(): ?N.Accessibility {
|
||||
@@ -1790,14 +1862,19 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.finishNode(typeCastNode, "TSTypeCastExpression");
|
||||
}
|
||||
|
||||
return node;
|
||||
return this.finishNode(node, node.type);
|
||||
}
|
||||
|
||||
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 +1883,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 +1951,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 +1969,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 +2066,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 +2074,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 +2247,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;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user