Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -1,2 +1,5 @@
|
||||
package.json
|
||||
packages/babel-preset-env/data
|
||||
packages/*/test/fixtures/**/input.*
|
||||
packages/*/test/fixtures/**/exec.*
|
||||
packages/*/test/fixtures/**/output.*
|
||||
|
||||
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
|
||||
|
||||
15
Makefile
15
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
|
||||
@@ -46,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:
|
||||
@@ -102,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:
|
||||
@@ -130,7 +131,7 @@ prepublish:
|
||||
make test
|
||||
|
||||
publish: prepublish
|
||||
./node_modules/.bin/lerna publish --force-publish="@babel/runtime,@babel/runtime-corejs2,@babel/standalone,@babel/preset-env-standalone"
|
||||
./node_modules/.bin/lerna publish --force-publish="@babel/runtime,@babel/runtime-corejs2,@babel/standalone,@babel/preset-env-standalone" --require-scripts
|
||||
make clean
|
||||
|
||||
bootstrap: clean-all
|
||||
|
||||
12
README.md
12
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>
|
||||
@@ -55,8 +59,8 @@ Become a sponsor and get your logo on our README on Github with a link to your s
|
||||
|
||||
## 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>
|
||||
<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
|
||||
|
||||
@@ -83,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":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "7.2.3",
|
||||
"version": "7.3.0",
|
||||
"changelog": {
|
||||
"repo": "babel/babel",
|
||||
"cacheDir": ".changelog",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/generator",
|
||||
"version": "7.2.2",
|
||||
"version": "7.3.0",
|
||||
"description": "Turns an AST into code.",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -14,7 +14,7 @@
|
||||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.2.2",
|
||||
"@babel/types": "^7.3.0",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.10",
|
||||
"source-map": "^0.5.0",
|
||||
@@ -22,6 +22,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/helper-fixtures": "^7.2.0",
|
||||
"@babel/parser": "^7.2.2"
|
||||
"@babel/parser": "^7.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
3
packages/babel-generator/test/fixtures/typescript/types-import-type/input.js
vendored
Normal file
3
packages/babel-generator/test/fixtures/typescript/types-import-type/input.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
let x: typeof import('./x');
|
||||
let Y: import('./y').Y;
|
||||
let z: import("/z").foo.bar<string>;
|
||||
3
packages/babel-generator/test/fixtures/typescript/types-import-type/output.js
vendored
Normal file
3
packages/babel-generator/test/fixtures/typescript/types-import-type/output.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
let x: typeof import('./x');
|
||||
let Y: import('./y').Y;
|
||||
let z: import("/z").foo.bar<string>;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/helper-builder-react-jsx",
|
||||
"version": "7.0.0",
|
||||
"version": "7.3.0",
|
||||
"description": "Helper function to build react jsx",
|
||||
"repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-builder-react-jsx",
|
||||
"license": "MIT",
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.0.0",
|
||||
"@babel/types": "^7.3.0",
|
||||
"esutils": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,13 @@ You can turn on the 'throwIfNamespace' flag to bypass this warning.`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
visitor.JSXSpreadChild = function(path) {
|
||||
throw path.buildCodeFrameError(
|
||||
"Spread children are not supported in React.",
|
||||
);
|
||||
};
|
||||
|
||||
visitor.JSXElement = {
|
||||
exit(path, file) {
|
||||
const callExpr = buildElementCall(path, file);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/helper-create-class-features-plugin",
|
||||
"version": "7.2.3",
|
||||
"version": "7.3.0",
|
||||
"author": "The Babel Team (https://babeljs.io/team)",
|
||||
"license": "MIT",
|
||||
"description": "Compile class public and private fields, private methods and decorators to ES6",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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);
|
||||
@@ -14,11 +15,13 @@ function prop(key, value) {
|
||||
return t.objectProperty(t.identifier(key), value);
|
||||
}
|
||||
|
||||
function value(body, params = [], async, generator) {
|
||||
const method = t.objectMethod("method", t.identifier("value"), params, body);
|
||||
method.async = !!async;
|
||||
method.generator = !!generator;
|
||||
return method;
|
||||
function method(key, body) {
|
||||
return t.objectMethod(
|
||||
"method",
|
||||
t.identifier(key),
|
||||
[],
|
||||
t.blockStatement(body),
|
||||
);
|
||||
}
|
||||
|
||||
function takeDecorators(node) {
|
||||
@@ -74,13 +77,20 @@ function extractElementDescriptor(/* this: File, */ classRef, superRef, path) {
|
||||
prop("decorators", takeDecorators(node)),
|
||||
prop("static", node.static && t.booleanLiteral(true)),
|
||||
prop("key", getKey(node)),
|
||||
isMethod
|
||||
? value(node.body, node.params, node.async, node.generator)
|
||||
: node.value
|
||||
? value(template.ast`{ return ${node.value} }`)
|
||||
: prop("value", scope.buildUndefinedNode()),
|
||||
].filter(Boolean);
|
||||
|
||||
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);
|
||||
|
||||
@@ -39,9 +39,17 @@ export function isLoose(file, feature) {
|
||||
}
|
||||
|
||||
export function verifyUsedFeatures(path, file) {
|
||||
if (hasOwnDecorators(path)) {
|
||||
if (hasOwnDecorators(path.node)) {
|
||||
if (!hasFeature(file, FEATURES.decorators)) {
|
||||
throw path.buildCodeFrameError("Decorators are not enabled.");
|
||||
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()) {
|
||||
@@ -64,12 +72,6 @@ export function verifyUsedFeatures(path, file) {
|
||||
"@babel/plugin-class-features doesn't support class static private methods yet.",
|
||||
);
|
||||
}
|
||||
|
||||
if (path.node.kind !== "method") {
|
||||
throw path.buildCodeFrameError(
|
||||
"@babel/plugin-class-features doesn't support class private accessors yet.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
@@ -6,16 +6,26 @@ import optimiseCall from "@babel/helper-optimise-call-expression";
|
||||
export function buildPrivateNamesMap(props) {
|
||||
const privateNamesMap = new Map();
|
||||
for (const prop of props) {
|
||||
if (prop.isPrivate()) {
|
||||
const isPrivate = prop.isPrivate();
|
||||
const isMethod = !prop.isProperty();
|
||||
const isInstance = !prop.node.static;
|
||||
if (isPrivate) {
|
||||
const { name } = prop.node.key.id;
|
||||
privateNamesMap.set(name, {
|
||||
id: prop.scope.generateUidIdentifier(name),
|
||||
static: !!prop.node.static,
|
||||
method: prop.isMethod(),
|
||||
methodId: prop.isMethod()
|
||||
? prop.scope.generateUidIdentifier(name)
|
||||
: undefined,
|
||||
});
|
||||
const update = privateNamesMap.has(name)
|
||||
? privateNamesMap.get(name)
|
||||
: {
|
||||
id: prop.scope.generateUidIdentifier(name),
|
||||
static: !isInstance,
|
||||
method: isMethod,
|
||||
};
|
||||
if (prop.node.kind === "get") {
|
||||
update.getId = prop.scope.generateUidIdentifier(`get_${name}`);
|
||||
} else if (prop.node.kind === "set") {
|
||||
update.setId = prop.scope.generateUidIdentifier(`set_${name}`);
|
||||
} else if (prop.node.kind === "method" && isMethod && isInstance) {
|
||||
update.methodId = prop.scope.generateUidIdentifier(name);
|
||||
}
|
||||
privateNamesMap.set(name, update);
|
||||
}
|
||||
}
|
||||
return privateNamesMap;
|
||||
@@ -31,7 +41,7 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
|
||||
// In spec mode, only instance fields need a "private name" initializer
|
||||
// because static fields are directly assigned to a variable in the
|
||||
// buildPrivateStaticFieldInitSpec function.
|
||||
const { id, static: isStatic, method: isMethod } = value;
|
||||
const { id, static: isStatic, method: isMethod, getId, setId } = value;
|
||||
if (loose) {
|
||||
initNodes.push(
|
||||
template.statement.ast`
|
||||
@@ -39,7 +49,11 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
|
||||
`,
|
||||
);
|
||||
} else if (isMethod && !isStatic) {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
|
||||
if (getId || setId) {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
|
||||
} else {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
|
||||
}
|
||||
} else if (!isStatic) {
|
||||
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
|
||||
}
|
||||
@@ -121,6 +135,8 @@ const privateNameHandlerSpec = {
|
||||
static: isStatic,
|
||||
method: isMethod,
|
||||
methodId,
|
||||
getId,
|
||||
setId,
|
||||
} = privateNamesMap.get(name);
|
||||
|
||||
if (isStatic && !isMethod) {
|
||||
@@ -128,41 +144,57 @@ const privateNameHandlerSpec = {
|
||||
file.addHelper("classStaticPrivateFieldSpecGet"),
|
||||
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id)],
|
||||
);
|
||||
} else if (isMethod) {
|
||||
}
|
||||
if (isMethod) {
|
||||
if (getId || setId) {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
]);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateMethodGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
t.cloneNode(methodId),
|
||||
]);
|
||||
} else {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
]);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateFieldGet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
]);
|
||||
},
|
||||
|
||||
set(member, value) {
|
||||
const { classRef, privateNamesMap, file } = this;
|
||||
const { name } = member.node.property.id;
|
||||
const { id, static: isStatic, method: isMethod } = privateNamesMap.get(
|
||||
name,
|
||||
);
|
||||
const {
|
||||
id,
|
||||
static: isStatic,
|
||||
method: isMethod,
|
||||
setId,
|
||||
} = privateNamesMap.get(name);
|
||||
|
||||
if (isStatic && !isMethod) {
|
||||
return t.callExpression(
|
||||
file.addHelper("classStaticPrivateFieldSpecSet"),
|
||||
[this.receiver(member), t.cloneNode(classRef), t.cloneNode(id), value],
|
||||
);
|
||||
} else if (isMethod) {
|
||||
return t.callExpression(file.addHelper("classPrivateMethodSet"), []);
|
||||
} else {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
value,
|
||||
]);
|
||||
}
|
||||
if (isMethod) {
|
||||
if (setId) {
|
||||
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
value,
|
||||
]);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateMethodSet"), []);
|
||||
}
|
||||
return t.callExpression(file.addHelper("classPrivateFieldSet"), [
|
||||
this.receiver(member),
|
||||
t.cloneNode(id),
|
||||
value,
|
||||
]);
|
||||
},
|
||||
|
||||
call(member, args) {
|
||||
@@ -255,21 +287,91 @@ function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
|
||||
}
|
||||
|
||||
function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
|
||||
const { methodId, id } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||
const { methodId, id, getId, setId, initAdded } = privateName;
|
||||
if (initAdded) return;
|
||||
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
value: ${methodId.name}
|
||||
if (methodId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
value: ${methodId.name}
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
if (getId || setId) {
|
||||
privateNamesMap.set(prop.node.key.id.name, {
|
||||
...privateName,
|
||||
initAdded: true,
|
||||
});
|
||||
`;
|
||||
|
||||
if (getId && setId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
get: ${getId.name},
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
} else if (getId && !setId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
get: ${getId.name}
|
||||
});
|
||||
`;
|
||||
} else if (!getId && setId) {
|
||||
return template.statement.ast`
|
||||
Object.defineProperty(${ref}, ${id}, {
|
||||
// configurable is false by default
|
||||
// enumerable is false by default
|
||||
// writable is false by default
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
|
||||
const { id } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||
const { id, getId, setId, initAdded } = privateName;
|
||||
if (initAdded) return;
|
||||
|
||||
if (getId || setId) {
|
||||
privateNamesMap.set(prop.node.key.id.name, {
|
||||
...privateName,
|
||||
initAdded: true,
|
||||
});
|
||||
|
||||
if (getId && setId) {
|
||||
return template.statement.ast`
|
||||
${id}.set(${ref}, {
|
||||
get: ${getId.name},
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
} else if (getId && !setId) {
|
||||
return template.statement.ast`
|
||||
${id}.set(${ref}, {
|
||||
get: ${getId.name}
|
||||
});
|
||||
`;
|
||||
} else if (!getId && setId) {
|
||||
return template.statement.ast`
|
||||
${id}.set(${ref}, {
|
||||
set: ${setId.name}
|
||||
});
|
||||
`;
|
||||
}
|
||||
}
|
||||
return template.statement.ast`${id}.add(${ref})`;
|
||||
}
|
||||
|
||||
@@ -300,9 +402,37 @@ function buildPublicFieldInitSpec(ref, prop, state) {
|
||||
}
|
||||
|
||||
function buildPrivateInstanceMethodDeclaration(prop, privateNamesMap) {
|
||||
const { methodId } = privateNamesMap.get(prop.node.key.id.name);
|
||||
const privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||
const {
|
||||
methodId,
|
||||
getId,
|
||||
setId,
|
||||
getterDeclared,
|
||||
setterDeclared,
|
||||
} = privateName;
|
||||
const { params, body } = prop.node;
|
||||
const methodValue = t.functionExpression(methodId, params, body);
|
||||
const isGetter = getId && !getterDeclared && params.length === 0;
|
||||
const isSetter = setId && !setterDeclared && params.length > 0;
|
||||
|
||||
if (isGetter) {
|
||||
privateNamesMap.set(prop.node.key.id.name, {
|
||||
...privateName,
|
||||
getterDeclared: true,
|
||||
});
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(getId, methodValue),
|
||||
]);
|
||||
}
|
||||
if (isSetter) {
|
||||
privateNamesMap.set(prop.node.key.id.name, {
|
||||
...privateName,
|
||||
setterDeclared: true,
|
||||
});
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(setId, methodValue),
|
||||
]);
|
||||
}
|
||||
|
||||
return t.variableDeclaration("var", [
|
||||
t.variableDeclarator(methodId, methodValue),
|
||||
@@ -366,7 +496,7 @@ export function buildFieldsInitNodes(
|
||||
);
|
||||
break;
|
||||
case isInstance && isPrivate && isMethod && loose:
|
||||
instanceNodes.push(
|
||||
instanceNodes.unshift(
|
||||
buildPrivateMethodInitLoose(
|
||||
t.thisExpression(),
|
||||
prop,
|
||||
@@ -378,7 +508,7 @@ export function buildFieldsInitNodes(
|
||||
);
|
||||
break;
|
||||
case isInstance && isPrivate && isMethod && !loose:
|
||||
instanceNodes.push(
|
||||
instanceNodes.unshift(
|
||||
buildPrivateInstanceMethodInitSpec(
|
||||
t.thisExpression(),
|
||||
prop,
|
||||
@@ -404,7 +534,7 @@ export function buildFieldsInitNodes(
|
||||
|
||||
return {
|
||||
staticNodes,
|
||||
instanceNodes,
|
||||
instanceNodes: instanceNodes.filter(Boolean),
|
||||
wrapClass(path) {
|
||||
for (const prop of props) {
|
||||
prop.remove();
|
||||
|
||||
@@ -75,11 +75,39 @@ 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.isClassMethod({ kind: "constructor" })) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/helpers",
|
||||
"version": "7.2.0",
|
||||
"version": "7.3.0",
|
||||
"description": "Collection of helper functions used by Babel transforms.",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.1.2",
|
||||
"@babel/traverse": "^7.1.5",
|
||||
"@babel/types": "^7.2.0"
|
||||
"@babel/types": "^7.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/helper-plugin-test-runner": "^7.0.0"
|
||||
|
||||
@@ -389,16 +389,20 @@ helpers.objectSpread = helper("7.0.0-beta.0")`
|
||||
|
||||
export default function _objectSpread(target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = (arguments[i] != null) ? arguments[i] : {};
|
||||
var ownKeys = Object.keys(source);
|
||||
if (typeof Object.getOwnPropertySymbols === 'function') {
|
||||
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
||||
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
||||
}));
|
||||
if (i % 2) {
|
||||
var source = (arguments[i] != null) ? arguments[i] : {};
|
||||
var ownKeys = Object.keys(source);
|
||||
if (typeof Object.getOwnPropertySymbols === 'function') {
|
||||
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
||||
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
||||
}));
|
||||
}
|
||||
ownKeys.forEach(function(key) {
|
||||
defineProperty(target, key, source[key]);
|
||||
});
|
||||
} else {
|
||||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(arguments[i]));
|
||||
}
|
||||
ownKeys.forEach(function(key) {
|
||||
defineProperty(target, key, source[key]);
|
||||
});
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -1048,7 +1052,11 @@ helpers.classPrivateFieldGet = helper("7.0.0-beta.0")`
|
||||
if (!privateMap.has(receiver)) {
|
||||
throw new TypeError("attempted to get private field on non-instance");
|
||||
}
|
||||
return privateMap.get(receiver).value;
|
||||
var descriptor = privateMap.get(receiver);
|
||||
if (descriptor.get) {
|
||||
return descriptor.get.call(receiver);
|
||||
}
|
||||
return descriptor.value;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1058,13 +1066,19 @@ helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
|
||||
throw new TypeError("attempted to set private field on non-instance");
|
||||
}
|
||||
var descriptor = privateMap.get(receiver);
|
||||
if (!descriptor.writable) {
|
||||
// This should only throw in strict mode, but class bodies are
|
||||
// always strict and private fields can only be used inside
|
||||
// class bodies.
|
||||
throw new TypeError("attempted to set read only private field");
|
||||
if (descriptor.set) {
|
||||
descriptor.set.call(receiver, value);
|
||||
} else {
|
||||
if (!descriptor.writable) {
|
||||
// This should only throw in strict mode, but class bodies are
|
||||
// always strict and private fields can only be used inside
|
||||
// class bodies.
|
||||
throw new TypeError("attempted to set read only private field");
|
||||
}
|
||||
|
||||
descriptor.value = value;
|
||||
}
|
||||
descriptor.value = value;
|
||||
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
@@ -1213,23 +1227,430 @@ helpers.decorate = helper("7.1.5")`
|
||||
|
||||
*/
|
||||
|
||||
/*::
|
||||
|
||||
type Placements = {
|
||||
static: Key[],
|
||||
prototype: Key[],
|
||||
own: Key[],
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
// ClassDefinitionEvaluation (Steps 26-*)
|
||||
export default function _decorate(
|
||||
decorators /*: ClassDecorator[] */,
|
||||
factory /*: ClassFactory */,
|
||||
superClass /*: ?Class<*> */,
|
||||
mixins /*: ?Array<Function> */,
|
||||
) /*: Class<*> */ {
|
||||
var api = _getDecoratorsApi();
|
||||
if (mixins) {
|
||||
for (var i = 0; i < mixins.length; i++) {
|
||||
api = mixins[i](api);
|
||||
}
|
||||
}
|
||||
|
||||
var r = factory(function initialize(O) {
|
||||
_initializeInstanceElements(O, decorated.elements);
|
||||
api.initializeInstanceElements(O, decorated.elements);
|
||||
}, superClass);
|
||||
var decorated = _decorateClass(
|
||||
var decorated = api.decorateClass(
|
||||
_coalesceClassElements(r.d.map(_createElementDescriptor)),
|
||||
decorators,
|
||||
);
|
||||
|
||||
_initializeClassElements(r.F, decorated.elements);
|
||||
api.initializeClassElements(r.F, decorated.elements);
|
||||
|
||||
return _runClassFinishers(r.F, decorated.finishers);
|
||||
return api.runClassFinishers(r.F, decorated.finishers);
|
||||
}
|
||||
|
||||
function _getDecoratorsApi() {
|
||||
_getDecoratorsApi = function() {
|
||||
return api;
|
||||
};
|
||||
|
||||
var api = {
|
||||
elementsDefinitionOrder: [["method"], ["field"]],
|
||||
|
||||
// InitializeInstanceElements
|
||||
initializeInstanceElements: function(
|
||||
/*::<C>*/ O /*: C */,
|
||||
elements /*: ElementDescriptor[] */,
|
||||
) {
|
||||
["method", "field"].forEach(function(kind) {
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
if (element.kind === kind && element.placement === "own") {
|
||||
this.defineClassElement(O, element);
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
// InitializeClassElements
|
||||
initializeClassElements: function(
|
||||
/*::<C>*/ F /*: Class<C> */,
|
||||
elements /*: ElementDescriptor[] */,
|
||||
) {
|
||||
var proto = F.prototype;
|
||||
|
||||
["method", "field"].forEach(function(kind) {
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
var placement = element.placement;
|
||||
if (
|
||||
element.kind === kind &&
|
||||
(placement === "static" || placement === "prototype")
|
||||
) {
|
||||
var receiver = placement === "static" ? F : proto;
|
||||
this.defineClassElement(receiver, element);
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
},
|
||||
|
||||
// DefineClassElement
|
||||
defineClassElement: function(
|
||||
/*::<C>*/ receiver /*: C | Class<C> */,
|
||||
element /*: ElementDescriptor */,
|
||||
) {
|
||||
var descriptor /*: PropertyDescriptor */ = element.descriptor;
|
||||
if (element.kind === "field") {
|
||||
var initializer = element.initializer;
|
||||
descriptor = {
|
||||
enumerable: descriptor.enumerable,
|
||||
writable: descriptor.writable,
|
||||
configurable: descriptor.configurable,
|
||||
value: initializer === void 0 ? void 0 : initializer.call(receiver),
|
||||
};
|
||||
}
|
||||
Object.defineProperty(receiver, element.key, descriptor);
|
||||
},
|
||||
|
||||
// DecorateClass
|
||||
decorateClass: function(
|
||||
elements /*: ElementDescriptor[] */,
|
||||
decorators /*: ClassDecorator[] */,
|
||||
) /*: ElementsFinishers */ {
|
||||
var newElements /*: ElementDescriptor[] */ = [];
|
||||
var finishers /*: ClassFinisher[] */ = [];
|
||||
var placements /*: Placements */ = {
|
||||
static: [],
|
||||
prototype: [],
|
||||
own: [],
|
||||
};
|
||||
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
this.addElementPlacement(element, placements);
|
||||
}, this);
|
||||
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
if (!_hasDecorators(element)) return newElements.push(element);
|
||||
|
||||
var elementFinishersExtras /*: ElementFinishersExtras */ = this.decorateElement(
|
||||
element,
|
||||
placements,
|
||||
);
|
||||
newElements.push(elementFinishersExtras.element);
|
||||
newElements.push.apply(newElements, elementFinishersExtras.extras);
|
||||
finishers.push.apply(finishers, elementFinishersExtras.finishers);
|
||||
}, this);
|
||||
|
||||
if (!decorators) {
|
||||
return { elements: newElements, finishers: finishers };
|
||||
}
|
||||
|
||||
var result /*: ElementsFinishers */ = this.decorateConstructor(
|
||||
newElements,
|
||||
decorators,
|
||||
);
|
||||
finishers.push.apply(finishers, result.finishers);
|
||||
result.finishers = finishers;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
// AddElementPlacement
|
||||
addElementPlacement: function(
|
||||
element /*: ElementDescriptor */,
|
||||
placements /*: Placements */,
|
||||
silent /*: boolean */,
|
||||
) {
|
||||
var keys = placements[element.placement];
|
||||
if (!silent && keys.indexOf(element.key) !== -1) {
|
||||
throw new TypeError("Duplicated element (" + element.key + ")");
|
||||
}
|
||||
keys.push(element.key);
|
||||
},
|
||||
|
||||
// DecorateElement
|
||||
decorateElement: function(
|
||||
element /*: ElementDescriptor */,
|
||||
placements /*: Placements */,
|
||||
) /*: ElementFinishersExtras */ {
|
||||
var extras /*: ElementDescriptor[] */ = [];
|
||||
var finishers /*: ClassFinisher[] */ = [];
|
||||
|
||||
for (
|
||||
var decorators = element.decorators, i = decorators.length - 1;
|
||||
i >= 0;
|
||||
i--
|
||||
) {
|
||||
// (inlined) RemoveElementPlacement
|
||||
var keys = placements[element.placement];
|
||||
keys.splice(keys.indexOf(element.key), 1);
|
||||
|
||||
var elementObject /*: ElementObjectInput */ = this.fromElementDescriptor(
|
||||
element,
|
||||
);
|
||||
var elementFinisherExtras /*: ElementFinisherExtras */ = this.toElementFinisherExtras(
|
||||
(0, decorators[i])(elementObject) /*: ElementObjectOutput */ ||
|
||||
elementObject,
|
||||
);
|
||||
|
||||
element = elementFinisherExtras.element;
|
||||
this.addElementPlacement(element, placements);
|
||||
|
||||
if (elementFinisherExtras.finisher) {
|
||||
finishers.push(elementFinisherExtras.finisher);
|
||||
}
|
||||
|
||||
var newExtras /*: ElementDescriptor[] | void */ =
|
||||
elementFinisherExtras.extras;
|
||||
if (newExtras) {
|
||||
for (var j = 0; j < newExtras.length; j++) {
|
||||
this.addElementPlacement(newExtras[j], placements);
|
||||
}
|
||||
extras.push.apply(extras, newExtras);
|
||||
}
|
||||
}
|
||||
|
||||
return { element: element, finishers: finishers, extras: extras };
|
||||
},
|
||||
|
||||
// DecorateConstructor
|
||||
decorateConstructor: function(
|
||||
elements /*: ElementDescriptor[] */,
|
||||
decorators /*: ClassDecorator[] */,
|
||||
) /*: ElementsFinishers */ {
|
||||
var finishers /*: ClassFinisher[] */ = [];
|
||||
|
||||
for (var i = decorators.length - 1; i >= 0; i--) {
|
||||
var obj /*: ClassObject */ = this.fromClassDescriptor(elements);
|
||||
var elementsAndFinisher /*: ElementsFinisher */ = this.toClassDescriptor(
|
||||
(0, decorators[i])(obj) /*: ClassObject */ || obj,
|
||||
);
|
||||
|
||||
if (elementsAndFinisher.finisher !== undefined) {
|
||||
finishers.push(elementsAndFinisher.finisher);
|
||||
}
|
||||
|
||||
if (elementsAndFinisher.elements !== undefined) {
|
||||
elements = elementsAndFinisher.elements;
|
||||
|
||||
for (var j = 0; j < elements.length - 1; j++) {
|
||||
for (var k = j + 1; k < elements.length; k++) {
|
||||
if (
|
||||
elements[j].key === elements[k].key &&
|
||||
elements[j].placement === elements[k].placement
|
||||
) {
|
||||
throw new TypeError(
|
||||
"Duplicated element (" + elements[j].key + ")",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { elements: elements, finishers: finishers };
|
||||
},
|
||||
|
||||
// FromElementDescriptor
|
||||
fromElementDescriptor: function(
|
||||
element /*: ElementDescriptor */,
|
||||
) /*: ElementObject */ {
|
||||
var obj /*: ElementObject */ = {
|
||||
kind: element.kind,
|
||||
key: element.key,
|
||||
placement: element.placement,
|
||||
descriptor: element.descriptor,
|
||||
};
|
||||
|
||||
var desc = {
|
||||
value: "Descriptor",
|
||||
configurable: true,
|
||||
};
|
||||
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
||||
|
||||
if (element.kind === "field") obj.initializer = element.initializer;
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
// ToElementDescriptors
|
||||
toElementDescriptors: function(
|
||||
elementObjects /*: ElementObject[] */,
|
||||
) /*: ElementDescriptor[] */ {
|
||||
if (elementObjects === undefined) return;
|
||||
return toArray(elementObjects).map(function(elementObject) {
|
||||
var element = this.toElementDescriptor(elementObject);
|
||||
this.disallowProperty(elementObject, "finisher", "An element descriptor");
|
||||
this.disallowProperty(elementObject, "extras", "An element descriptor");
|
||||
return element;
|
||||
}, this);
|
||||
},
|
||||
|
||||
// ToElementDescriptor
|
||||
toElementDescriptor: function(
|
||||
elementObject /*: ElementObject */,
|
||||
) /*: ElementDescriptor */ {
|
||||
var kind = String(elementObject.kind);
|
||||
if (kind !== "method" && kind !== "field") {
|
||||
throw new TypeError(
|
||||
'An element descriptor\\'s .kind property must be either "method" or' +
|
||||
' "field", but a decorator created an element descriptor with' +
|
||||
' .kind "' +
|
||||
kind +
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
var key = toPropertyKey(elementObject.key);
|
||||
|
||||
var placement = String(elementObject.placement);
|
||||
if (
|
||||
placement !== "static" &&
|
||||
placement !== "prototype" &&
|
||||
placement !== "own"
|
||||
) {
|
||||
throw new TypeError(
|
||||
'An element descriptor\\'s .placement property must be one of "static",' +
|
||||
' "prototype" or "own", but a decorator created an element descriptor' +
|
||||
' with .placement "' +
|
||||
placement +
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
var descriptor /*: PropertyDescriptor */ = elementObject.descriptor;
|
||||
|
||||
this.disallowProperty(elementObject, "elements", "An element descriptor");
|
||||
|
||||
var element /*: ElementDescriptor */ = {
|
||||
kind: kind,
|
||||
key: key,
|
||||
placement: placement,
|
||||
descriptor: Object.assign({}, descriptor),
|
||||
};
|
||||
|
||||
if (kind !== "field") {
|
||||
this.disallowProperty(elementObject, "initializer", "A method descriptor");
|
||||
} else {
|
||||
this.disallowProperty(
|
||||
descriptor,
|
||||
"get",
|
||||
"The property descriptor of a field descriptor",
|
||||
);
|
||||
this.disallowProperty(
|
||||
descriptor,
|
||||
"set",
|
||||
"The property descriptor of a field descriptor",
|
||||
);
|
||||
this.disallowProperty(
|
||||
descriptor,
|
||||
"value",
|
||||
"The property descriptor of a field descriptor",
|
||||
);
|
||||
|
||||
element.initializer = elementObject.initializer;
|
||||
}
|
||||
|
||||
return element;
|
||||
},
|
||||
|
||||
toElementFinisherExtras: function(
|
||||
elementObject /*: ElementObject */,
|
||||
) /*: ElementFinisherExtras */ {
|
||||
var element /*: ElementDescriptor */ = this.toElementDescriptor(
|
||||
elementObject,
|
||||
);
|
||||
var finisher /*: ClassFinisher */ = _optionalCallableProperty(
|
||||
elementObject,
|
||||
"finisher",
|
||||
);
|
||||
var extras /*: ElementDescriptors[] */ = this.toElementDescriptors(
|
||||
elementObject.extras,
|
||||
);
|
||||
|
||||
return { element: element, finisher: finisher, extras: extras };
|
||||
},
|
||||
|
||||
// FromClassDescriptor
|
||||
fromClassDescriptor: function(
|
||||
elements /*: ElementDescriptor[] */,
|
||||
) /*: ClassObject */ {
|
||||
var obj = {
|
||||
kind: "class",
|
||||
elements: elements.map(this.fromElementDescriptor, this),
|
||||
};
|
||||
|
||||
var desc = { value: "Descriptor", configurable: true };
|
||||
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
// ToClassDescriptor
|
||||
toClassDescriptor: function(
|
||||
obj /*: ClassObject */,
|
||||
) /*: ElementsFinisher */ {
|
||||
var kind = String(obj.kind);
|
||||
if (kind !== "class") {
|
||||
throw new TypeError(
|
||||
'A class descriptor\\'s .kind property must be "class", but a decorator' +
|
||||
' created a class descriptor with .kind "' +
|
||||
kind +
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
this.disallowProperty(obj, "key", "A class descriptor");
|
||||
this.disallowProperty(obj, "placement", "A class descriptor");
|
||||
this.disallowProperty(obj, "descriptor", "A class descriptor");
|
||||
this.disallowProperty(obj, "initializer", "A class descriptor");
|
||||
this.disallowProperty(obj, "extras", "A class descriptor");
|
||||
|
||||
var finisher = _optionalCallableProperty(obj, "finisher");
|
||||
var elements = this.toElementDescriptors(obj.elements);
|
||||
|
||||
return { elements: elements, finisher: finisher };
|
||||
},
|
||||
|
||||
// RunClassFinishers
|
||||
runClassFinishers: function(
|
||||
constructor /*: Class<*> */,
|
||||
finishers /*: ClassFinisher[] */,
|
||||
) /*: Class<*> */ {
|
||||
for (var i = 0; i < finishers.length; i++) {
|
||||
var newConstructor /*: ?Class<*> */ = (0, finishers[i])(constructor);
|
||||
if (newConstructor !== undefined) {
|
||||
// NOTE: This should check if IsConstructor(newConstructor) is false.
|
||||
if (typeof newConstructor !== "function") {
|
||||
throw new TypeError("Finishers must return a constructor.");
|
||||
}
|
||||
constructor = newConstructor;
|
||||
}
|
||||
}
|
||||
return constructor;
|
||||
},
|
||||
|
||||
disallowProperty: function(obj, name, objectType) {
|
||||
if (obj[name] !== undefined) {
|
||||
throw new TypeError(objectType + " can't have a ." + name + " property.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
// ClassElementEvaluation
|
||||
@@ -1246,10 +1667,6 @@ helpers.decorate = helper("7.1.5")`
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
};
|
||||
Object.defineProperty(def.value, "name", {
|
||||
value: typeof key === "symbol" ? "" : key,
|
||||
configurable: true,
|
||||
});
|
||||
} else if (def.kind === "get") {
|
||||
descriptor = { get: def.value, configurable: true, enumerable: false };
|
||||
} else if (def.kind === "set") {
|
||||
@@ -1264,8 +1681,8 @@ helpers.decorate = helper("7.1.5")`
|
||||
placement: def.static
|
||||
? "static"
|
||||
: def.kind === "field"
|
||||
? "own"
|
||||
: "prototype",
|
||||
? "own"
|
||||
: "prototype",
|
||||
descriptor: descriptor,
|
||||
};
|
||||
if (def.decorators) element.decorators = def.decorators;
|
||||
@@ -1292,7 +1709,9 @@ helpers.decorate = helper("7.1.5")`
|
||||
) /*: ElementDescriptor[] */ {
|
||||
var newElements /*: ElementDescriptor[] */ = [];
|
||||
|
||||
var isSameElement = function(other /*: ElementDescriptor */) /*: boolean */ {
|
||||
var isSameElement = function(
|
||||
other /*: ElementDescriptor */,
|
||||
) /*: boolean */ {
|
||||
return (
|
||||
other.kind === "method" &&
|
||||
other.key === element.key &&
|
||||
@@ -1351,365 +1770,6 @@ helpers.decorate = helper("7.1.5")`
|
||||
);
|
||||
}
|
||||
|
||||
// InitializeClassElements
|
||||
function _initializeClassElements /*::<C>*/(
|
||||
F /*: Class<C> */,
|
||||
elements /*: ElementDescriptor[] */,
|
||||
) {
|
||||
var proto = F.prototype;
|
||||
|
||||
["method", "field"].forEach(function(kind) {
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
var placement = element.placement;
|
||||
if (
|
||||
element.kind === kind &&
|
||||
(placement === "static" || placement === "prototype")
|
||||
) {
|
||||
var receiver = placement === "static" ? F : proto;
|
||||
_defineClassElement(receiver, element);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// InitializeInstanceElements
|
||||
function _initializeInstanceElements /*::<C>*/(
|
||||
O /*: C */,
|
||||
elements /*: ElementDescriptor[] */,
|
||||
) {
|
||||
["method", "field"].forEach(function(kind) {
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
if (element.kind === kind && element.placement === "own") {
|
||||
_defineClassElement(O, element);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// DefineClassElement
|
||||
function _defineClassElement /*::<C>*/(
|
||||
receiver /*: C | Class<C> */,
|
||||
element /*: ElementDescriptor */,
|
||||
) {
|
||||
var descriptor /*: PropertyDescriptor */ = element.descriptor;
|
||||
if (element.kind === "field") {
|
||||
var initializer = element.initializer;
|
||||
descriptor = {
|
||||
enumerable: descriptor.enumerable,
|
||||
writable: descriptor.writable,
|
||||
configurable: descriptor.configurable,
|
||||
value: initializer === void 0 ? void 0 : initializer.call(receiver),
|
||||
};
|
||||
}
|
||||
Object.defineProperty(receiver, element.key, descriptor);
|
||||
}
|
||||
|
||||
/*::
|
||||
|
||||
type Placements = {
|
||||
static: Key[],
|
||||
prototype: Key[],
|
||||
own: Key[],
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
// DecorateClass
|
||||
function _decorateClass(
|
||||
elements /*: ElementDescriptor[] */,
|
||||
decorators /*: ClassDecorator[] */,
|
||||
) /*: ElementsFinishers */ {
|
||||
var newElements /*: ElementDescriptor[] */ = [];
|
||||
var finishers /*: ClassFinisher[] */ = [];
|
||||
var placements /*: Placements */ = { static: [], prototype: [], own: [] };
|
||||
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
_addElementPlacement(element, placements);
|
||||
});
|
||||
|
||||
elements.forEach(function(element /*: ElementDescriptor */) {
|
||||
if (!_hasDecorators(element)) return newElements.push(element);
|
||||
|
||||
var elementFinishersExtras /*: ElementFinishersExtras */ = _decorateElement(
|
||||
element,
|
||||
placements,
|
||||
);
|
||||
newElements.push(elementFinishersExtras.element);
|
||||
newElements.push.apply(newElements, elementFinishersExtras.extras);
|
||||
finishers.push.apply(finishers, elementFinishersExtras.finishers);
|
||||
});
|
||||
|
||||
if (!decorators) {
|
||||
return { elements: newElements, finishers: finishers };
|
||||
}
|
||||
|
||||
var result /*: ElementsFinishers */ = _decorateConstructor(
|
||||
newElements,
|
||||
decorators,
|
||||
);
|
||||
finishers.push.apply(finishers, result.finishers);
|
||||
result.finishers = finishers;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// AddElementPlacement
|
||||
function _addElementPlacement(
|
||||
element /*: ElementDescriptor */,
|
||||
placements /*: Placements */,
|
||||
silent /*: boolean */,
|
||||
) {
|
||||
var keys = placements[element.placement];
|
||||
if (!silent && keys.indexOf(element.key) !== -1) {
|
||||
throw new TypeError("Duplicated element (" + element.key + ")");
|
||||
}
|
||||
keys.push(element.key);
|
||||
}
|
||||
|
||||
// DecorateElement
|
||||
function _decorateElement(
|
||||
element /*: ElementDescriptor */,
|
||||
placements /*: Placements */,
|
||||
) /*: ElementFinishersExtras */ {
|
||||
var extras /*: ElementDescriptor[] */ = [];
|
||||
var finishers /*: ClassFinisher[] */ = [];
|
||||
|
||||
for (
|
||||
var decorators = element.decorators, i = decorators.length - 1;
|
||||
i >= 0;
|
||||
i--
|
||||
) {
|
||||
// (inlined) RemoveElementPlacement
|
||||
var keys = placements[element.placement];
|
||||
keys.splice(keys.indexOf(element.key), 1);
|
||||
|
||||
var elementObject /*: ElementObjectInput */ = _fromElementDescriptor(
|
||||
element,
|
||||
);
|
||||
var elementFinisherExtras /*: ElementFinisherExtras */ = _toElementFinisherExtras(
|
||||
(0, decorators[i])(elementObject) /*: ElementObjectOutput */ ||
|
||||
elementObject,
|
||||
);
|
||||
|
||||
element = elementFinisherExtras.element;
|
||||
_addElementPlacement(element, placements);
|
||||
|
||||
if (elementFinisherExtras.finisher) {
|
||||
finishers.push(elementFinisherExtras.finisher);
|
||||
}
|
||||
|
||||
var newExtras /*: ElementDescriptor[] | void */ =
|
||||
elementFinisherExtras.extras;
|
||||
if (newExtras) {
|
||||
for (var j = 0; j < newExtras.length; j++) {
|
||||
_addElementPlacement(newExtras[j], placements);
|
||||
}
|
||||
extras.push.apply(extras, newExtras);
|
||||
}
|
||||
}
|
||||
|
||||
return { element: element, finishers: finishers, extras: extras };
|
||||
}
|
||||
|
||||
// DecorateConstructor
|
||||
function _decorateConstructor(
|
||||
elements /*: ElementDescriptor[] */,
|
||||
decorators /*: ClassDecorator[] */,
|
||||
) /*: ElementsFinishers */ {
|
||||
var finishers /*: ClassFinisher[] */ = [];
|
||||
|
||||
for (var i = decorators.length - 1; i >= 0; i--) {
|
||||
var obj /*: ClassObject */ = _fromClassDescriptor(elements);
|
||||
var elementsAndFinisher /*: ElementsFinisher */ = _toClassDescriptor(
|
||||
(0, decorators[i])(obj) /*: ClassObject */ || obj,
|
||||
);
|
||||
|
||||
if (elementsAndFinisher.finisher !== undefined) {
|
||||
finishers.push(elementsAndFinisher.finisher);
|
||||
}
|
||||
|
||||
if (elementsAndFinisher.elements !== undefined) {
|
||||
elements = elementsAndFinisher.elements;
|
||||
|
||||
for (var j = 0; j < elements.length - 1; j++) {
|
||||
for (var k = j + 1; k < elements.length; k++) {
|
||||
if (
|
||||
elements[j].key === elements[k].key &&
|
||||
elements[j].placement === elements[k].placement
|
||||
) {
|
||||
throw new TypeError("Duplicated element (" + elements[j].key + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { elements: elements, finishers: finishers };
|
||||
}
|
||||
|
||||
// FromElementDescriptor
|
||||
function _fromElementDescriptor(
|
||||
element /*: ElementDescriptor */,
|
||||
) /*: ElementObject */ {
|
||||
var obj /*: ElementObject */ = {
|
||||
kind: element.kind,
|
||||
key: element.key,
|
||||
placement: element.placement,
|
||||
descriptor: element.descriptor,
|
||||
};
|
||||
|
||||
var desc = {
|
||||
value: "Descriptor",
|
||||
configurable: true,
|
||||
};
|
||||
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
||||
|
||||
if (element.kind === "field") obj.initializer = element.initializer;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// ToElementDescriptors
|
||||
function _toElementDescriptors(
|
||||
elementObjects /*: ElementObject[] */,
|
||||
) /*: ElementDescriptor[] */ {
|
||||
if (elementObjects === undefined) return;
|
||||
return toArray(elementObjects).map(function(elementObject) {
|
||||
var element = _toElementDescriptor(elementObject);
|
||||
_disallowProperty(elementObject, "finisher", "An element descriptor");
|
||||
_disallowProperty(elementObject, "extras", "An element descriptor");
|
||||
return element;
|
||||
});
|
||||
}
|
||||
|
||||
// ToElementDescriptor
|
||||
function _toElementDescriptor(
|
||||
elementObject /*: ElementObject */,
|
||||
) /*: ElementDescriptor */ {
|
||||
var kind = String(elementObject.kind);
|
||||
if (kind !== "method" && kind !== "field") {
|
||||
throw new TypeError(
|
||||
'An element descriptor\\'s .kind property must be either "method" or' +
|
||||
' "field", but a decorator created an element descriptor with' +
|
||||
' .kind "' +
|
||||
kind +
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
var key = toPropertyKey(elementObject.key);
|
||||
|
||||
var placement = String(elementObject.placement);
|
||||
if (
|
||||
placement !== "static" &&
|
||||
placement !== "prototype" &&
|
||||
placement !== "own"
|
||||
) {
|
||||
throw new TypeError(
|
||||
'An element descriptor\\'s .placement property must be one of "static",' +
|
||||
' "prototype" or "own", but a decorator created an element descriptor' +
|
||||
' with .placement "' +
|
||||
placement +
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
var descriptor /*: PropertyDescriptor */ = elementObject.descriptor;
|
||||
|
||||
_disallowProperty(elementObject, "elements", "An element descriptor");
|
||||
|
||||
var element /*: ElementDescriptor */ = {
|
||||
kind: kind,
|
||||
key: key,
|
||||
placement: placement,
|
||||
descriptor: Object.assign({}, descriptor),
|
||||
};
|
||||
|
||||
if (kind !== "field") {
|
||||
_disallowProperty(elementObject, "initializer", "A method descriptor");
|
||||
} else {
|
||||
_disallowProperty(
|
||||
descriptor,
|
||||
"get",
|
||||
"The property descriptor of a field descriptor",
|
||||
);
|
||||
_disallowProperty(
|
||||
descriptor,
|
||||
"set",
|
||||
"The property descriptor of a field descriptor",
|
||||
);
|
||||
_disallowProperty(
|
||||
descriptor,
|
||||
"value",
|
||||
"The property descriptor of a field descriptor",
|
||||
);
|
||||
|
||||
element.initializer = elementObject.initializer;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function _toElementFinisherExtras(
|
||||
elementObject /*: ElementObject */,
|
||||
) /*: ElementFinisherExtras */ {
|
||||
var element /*: ElementDescriptor */ = _toElementDescriptor(elementObject);
|
||||
var finisher /*: ClassFinisher */ = _optionalCallableProperty(
|
||||
elementObject,
|
||||
"finisher",
|
||||
);
|
||||
var extras /*: ElementDescriptors[] */ = _toElementDescriptors(
|
||||
elementObject.extras,
|
||||
);
|
||||
|
||||
return { element: element, finisher: finisher, extras: extras };
|
||||
}
|
||||
|
||||
// FromClassDescriptor
|
||||
function _fromClassDescriptor(
|
||||
elements /*: ElementDescriptor[] */,
|
||||
) /*: ClassObject */ {
|
||||
var obj = {
|
||||
kind: "class",
|
||||
elements: elements.map(_fromElementDescriptor),
|
||||
};
|
||||
|
||||
var desc = { value: "Descriptor", configurable: true };
|
||||
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// ToClassDescriptor
|
||||
function _toClassDescriptor(obj /*: ClassObject */) /*: ElementsFinisher */ {
|
||||
var kind = String(obj.kind);
|
||||
if (kind !== "class") {
|
||||
throw new TypeError(
|
||||
'A class descriptor\\'s .kind property must be "class", but a decorator' +
|
||||
' created a class descriptor with .kind "' +
|
||||
kind +
|
||||
'"',
|
||||
);
|
||||
}
|
||||
|
||||
_disallowProperty(obj, "key", "A class descriptor");
|
||||
_disallowProperty(obj, "placement", "A class descriptor");
|
||||
_disallowProperty(obj, "descriptor", "A class descriptor");
|
||||
_disallowProperty(obj, "initializer", "A class descriptor");
|
||||
_disallowProperty(obj, "extras", "A class descriptor");
|
||||
|
||||
var finisher = _optionalCallableProperty(obj, "finisher");
|
||||
var elements = _toElementDescriptors(obj.elements);
|
||||
|
||||
return { elements: elements, finisher: finisher };
|
||||
}
|
||||
|
||||
function _disallowProperty(obj, name, objectType) {
|
||||
if (obj[name] !== undefined) {
|
||||
throw new TypeError(objectType + " can't have a ." + name + " property.");
|
||||
}
|
||||
}
|
||||
|
||||
function _optionalCallableProperty /*::<T>*/(
|
||||
obj /*: T */,
|
||||
name /*: $Keys<T> */,
|
||||
@@ -1721,23 +1781,6 @@ helpers.decorate = helper("7.1.5")`
|
||||
return value;
|
||||
}
|
||||
|
||||
// RunClassFinishers
|
||||
function _runClassFinishers(
|
||||
constructor /*: Class<*> */,
|
||||
finishers /*: ClassFinisher[] */,
|
||||
) /*: Class<*> */ {
|
||||
for (var i = 0; i < finishers.length; i++) {
|
||||
var newConstructor /*: ?Class<*> */ = (0, finishers[i])(constructor);
|
||||
if (newConstructor !== undefined) {
|
||||
// NOTE: This should check if IsConstructor(newConstructor) is false.
|
||||
if (typeof newConstructor !== "function") {
|
||||
throw new TypeError("Finishers must return a constructor.");
|
||||
}
|
||||
constructor = newConstructor;
|
||||
}
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
`;
|
||||
|
||||
helpers.classPrivateMethodGet = helper("7.1.6")`
|
||||
@@ -1754,3 +1797,75 @@ helpers.classPrivateMethodSet = helper("7.1.6")`
|
||||
throw new TypeError("attempted to reassign private method");
|
||||
}
|
||||
`;
|
||||
|
||||
helpers.wrapRegExp = helper("7.2.6")`
|
||||
import wrapNativeSuper from "wrapNativeSuper";
|
||||
import getPrototypeOf from "getPrototypeOf";
|
||||
import possibleConstructorReturn from "possibleConstructorReturn";
|
||||
import inherits from "inherits";
|
||||
|
||||
export default function _wrapRegExp(re, groups) {
|
||||
_wrapRegExp = function(re, groups) {
|
||||
return new BabelRegExp(re, groups);
|
||||
};
|
||||
|
||||
var _RegExp = wrapNativeSuper(RegExp);
|
||||
var _super = RegExp.prototype;
|
||||
var _groups = new WeakMap();
|
||||
|
||||
function BabelRegExp(re, groups) {
|
||||
var _this = _RegExp.call(this, re);
|
||||
_groups.set(_this, groups);
|
||||
return _this;
|
||||
}
|
||||
inherits(BabelRegExp, _RegExp);
|
||||
|
||||
BabelRegExp.prototype.exec = function(str) {
|
||||
var result = _super.exec.call(this, str);
|
||||
if (result) result.groups = buildGroups(result, this);
|
||||
return result;
|
||||
};
|
||||
BabelRegExp.prototype[Symbol.replace] = function(str, substitution) {
|
||||
if (typeof substitution === "string") {
|
||||
var groups = _groups.get(this);
|
||||
return _super[Symbol.replace].call(
|
||||
this,
|
||||
str,
|
||||
substitution.replace(/\\$<([^>]+)>/g, function(_, name) {
|
||||
return "$" + groups[name];
|
||||
})
|
||||
);
|
||||
} else if (typeof substitution === "function") {
|
||||
var _this = this;
|
||||
return _super[Symbol.replace].call(
|
||||
this,
|
||||
str,
|
||||
function() {
|
||||
var args = [];
|
||||
args.push.apply(args, arguments);
|
||||
if (typeof args[args.length - 1] !== "object") {
|
||||
// Modern engines already pass result.groups as the last arg.
|
||||
args.push(buildGroups(args, _this));
|
||||
}
|
||||
return substitution.apply(this, args);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return _super[Symbol.replace].call(this, str, substitution);
|
||||
}
|
||||
}
|
||||
|
||||
function buildGroups(result, re) {
|
||||
// NOTE: This function should return undefined if there are no groups,
|
||||
// but in that case Babel doesn't add the wrapper anyway.
|
||||
|
||||
var g = _groups.get(re);
|
||||
return Object.keys(groups).reduce(function(groups, name) {
|
||||
groups[name] = result[g[name]];
|
||||
return groups;
|
||||
}, Object.create(null));
|
||||
}
|
||||
|
||||
return _wrapRegExp.apply(this, arguments);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@babel/parser",
|
||||
"version": "7.2.3",
|
||||
"version": "7.3.0",
|
||||
"description": "A JavaScript parser",
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
"homepage": "https://babeljs.io/",
|
||||
@@ -30,7 +30,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/helper-fixtures": "^7.2.0",
|
||||
"charcodes": "0.1.0",
|
||||
"unicode-11.0.0": "^0.7.7"
|
||||
"unicode-11.0.0": "^0.7.8"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "./bin/babel-parser.js"
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import type { Options } from "../options";
|
||||
import { reservedWords } from "../util/identifier";
|
||||
import { isES2015ReservedWord } from "../util/identifier";
|
||||
|
||||
import type State from "../tokenizer/state";
|
||||
import type { PluginsMap } from "./index";
|
||||
@@ -16,21 +16,21 @@ export default class BaseParser {
|
||||
|
||||
// Initialized by Tokenizer
|
||||
state: State;
|
||||
input: string;
|
||||
|
||||
isReservedWord(word: string): boolean {
|
||||
if (word === "await") {
|
||||
return this.inModule;
|
||||
} else {
|
||||
return reservedWords[6](word);
|
||||
return isES2015ReservedWord(word);
|
||||
}
|
||||
}
|
||||
|
||||
hasPlugin(name: string): boolean {
|
||||
return Object.hasOwnProperty.call(this.plugins, name);
|
||||
return this.plugins.has(name);
|
||||
}
|
||||
|
||||
getPluginOption(plugin: string, name: string) {
|
||||
if (this.hasPlugin(plugin)) return this.plugins[plugin][name];
|
||||
// $FlowIssue
|
||||
if (this.hasPlugin(plugin)) return this.plugins.get(plugin)[name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
import { types as tt, type TokenType } from "../tokenizer/types";
|
||||
import * as N from "../types";
|
||||
import LValParser from "./lval";
|
||||
import { reservedWords } from "../util/identifier";
|
||||
import {
|
||||
isStrictReservedWord,
|
||||
isStrictBindReservedWord,
|
||||
isKeyword,
|
||||
} from "../util/identifier";
|
||||
import type { Pos, Position } from "../util/location";
|
||||
import * as charCodes from "charcodes";
|
||||
|
||||
@@ -130,6 +134,9 @@ export default class ExpressionParser extends LValParser {
|
||||
return left;
|
||||
}
|
||||
|
||||
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
|
||||
this.state.commaAfterSpreadAt = -1;
|
||||
|
||||
let failOnShorthandAssign;
|
||||
if (refShorthandDefaultPos) {
|
||||
failOnShorthandAssign = false;
|
||||
@@ -169,21 +176,26 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
this.checkLVal(left, undefined, undefined, "assignment expression");
|
||||
|
||||
if (left.extra && left.extra.parenthesized) {
|
||||
let errorMsg;
|
||||
if (left.type === "ObjectPattern") {
|
||||
errorMsg = "`({a}) = 0` use `({a} = 0)`";
|
||||
} else if (left.type === "ArrayPattern") {
|
||||
errorMsg = "`([a]) = 0` use `([a] = 0)`";
|
||||
}
|
||||
if (errorMsg) {
|
||||
this.raise(
|
||||
left.start,
|
||||
`You're trying to assign to a parenthesized expression, eg. instead of ${errorMsg}`,
|
||||
);
|
||||
}
|
||||
let patternErrorMsg;
|
||||
let elementName;
|
||||
if (left.type === "ObjectPattern") {
|
||||
patternErrorMsg = "`({a}) = 0` use `({a} = 0)`";
|
||||
elementName = "property";
|
||||
} else if (left.type === "ArrayPattern") {
|
||||
patternErrorMsg = "`([a]) = 0` use `([a] = 0)`";
|
||||
elementName = "element";
|
||||
}
|
||||
|
||||
if (patternErrorMsg && left.extra && left.extra.parenthesized) {
|
||||
this.raise(
|
||||
left.start,
|
||||
`You're trying to assign to a parenthesized expression, eg. instead of ${patternErrorMsg}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (elementName) this.checkCommaAfterRestFromSpread(elementName);
|
||||
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
|
||||
|
||||
this.next();
|
||||
node.right = this.parseMaybeAssign(noIn);
|
||||
return this.finishNode(node, "AssignmentExpression");
|
||||
@@ -191,6 +203,8 @@ export default class ExpressionParser extends LValParser {
|
||||
this.unexpected(refShorthandDefaultPos.start);
|
||||
}
|
||||
|
||||
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
@@ -515,7 +529,7 @@ export default class ExpressionParser extends LValParser {
|
||||
} else if (this.match(tt.questionDot)) {
|
||||
this.expectPlugin("optionalChaining");
|
||||
state.optionalChainMember = true;
|
||||
if (noCalls && this.lookahead().type == tt.parenL) {
|
||||
if (noCalls && this.lookahead().type === tt.parenL) {
|
||||
state.stop = true;
|
||||
return base;
|
||||
}
|
||||
@@ -580,15 +594,13 @@ export default class ExpressionParser extends LValParser {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
node.callee = base;
|
||||
|
||||
// TODO: Clean up/merge this into `this.state` or a class like acorn's
|
||||
// `DestructuringErrors` alongside refShorthandDefaultPos and
|
||||
// refNeedsArrowPos.
|
||||
const refTrailingCommaPos: Pos = { start: -1 };
|
||||
const oldCommaAfterSpreadAt = this.state.commaAfterSpreadAt;
|
||||
this.state.commaAfterSpreadAt = -1;
|
||||
|
||||
node.arguments = this.parseCallExpressionArguments(
|
||||
tt.parenR,
|
||||
possibleAsync,
|
||||
refTrailingCommaPos,
|
||||
base.type === "Import",
|
||||
);
|
||||
if (!state.optionalChainMember) {
|
||||
this.finishCallExpression(node);
|
||||
@@ -599,12 +611,7 @@ export default class ExpressionParser extends LValParser {
|
||||
if (possibleAsync && this.shouldParseAsyncArrow()) {
|
||||
state.stop = true;
|
||||
|
||||
if (refTrailingCommaPos.start > -1) {
|
||||
this.raise(
|
||||
refTrailingCommaPos.start,
|
||||
"A trailing comma is not permitted after the rest element",
|
||||
);
|
||||
}
|
||||
this.checkCommaAfterRestFromSpread("parameter");
|
||||
|
||||
node = this.parseAsyncArrowFromCallExpression(
|
||||
this.startNodeAt(startPos, startLoc),
|
||||
@@ -621,6 +628,7 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
|
||||
this.state.maybeInArrowParameters = oldMaybeInArrowParameters;
|
||||
this.state.commaAfterSpreadAt = oldCommaAfterSpreadAt;
|
||||
|
||||
return node;
|
||||
} else if (this.match(tt.backQuote)) {
|
||||
@@ -700,7 +708,7 @@ export default class ExpressionParser extends LValParser {
|
||||
parseCallExpressionArguments(
|
||||
close: TokenType,
|
||||
possibleAsyncArrow: boolean,
|
||||
refTrailingCommaPos?: Pos,
|
||||
dynamicImport?: boolean,
|
||||
): $ReadOnlyArray<?N.Expression> {
|
||||
const elts = [];
|
||||
let innerParenStart;
|
||||
@@ -711,7 +719,15 @@ export default class ExpressionParser extends LValParser {
|
||||
first = false;
|
||||
} else {
|
||||
this.expect(tt.comma);
|
||||
if (this.eat(close)) break;
|
||||
if (this.eat(close)) {
|
||||
if (dynamicImport) {
|
||||
this.raise(
|
||||
this.state.lastTokStart,
|
||||
"Trailing comma is disallowed inside import(...) arguments",
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we need to make sure that if this is an async arrow functions,
|
||||
@@ -725,7 +741,6 @@ export default class ExpressionParser extends LValParser {
|
||||
false,
|
||||
possibleAsyncArrow ? { start: 0 } : undefined,
|
||||
possibleAsyncArrow ? { start: 0 } : undefined,
|
||||
possibleAsyncArrow ? refTrailingCommaPos : undefined,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -858,9 +873,9 @@ export default class ExpressionParser extends LValParser {
|
||||
return this.parseFunction(node, false, false, true);
|
||||
} else if (
|
||||
canBeArrow &&
|
||||
!this.canInsertSemicolon() &&
|
||||
id.name === "async" &&
|
||||
this.match(tt.name)
|
||||
this.match(tt.name) &&
|
||||
!this.canInsertSemicolon()
|
||||
) {
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
const oldInAsync = this.state.inAsync;
|
||||
@@ -875,7 +890,8 @@ export default class ExpressionParser extends LValParser {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
|
||||
if (canBeArrow && this.match(tt.arrow) && !this.canInsertSemicolon()) {
|
||||
this.next();
|
||||
const oldYOAIPAP = this.state.yieldOrAwaitInPossibleArrowParameters;
|
||||
this.state.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
this.parseArrowExpression(node, [id]);
|
||||
@@ -1135,7 +1151,11 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
const node = this.startNodeAt(startPos, startLoc);
|
||||
this.addExtra(node, "rawValue", value);
|
||||
this.addExtra(node, "raw", this.input.slice(startPos, this.state.end));
|
||||
this.addExtra(
|
||||
node,
|
||||
"raw",
|
||||
this.state.input.slice(startPos, this.state.end),
|
||||
);
|
||||
node.value = value;
|
||||
this.next();
|
||||
return this.finishNode(node, type);
|
||||
@@ -1192,14 +1212,7 @@ export default class ExpressionParser extends LValParser {
|
||||
),
|
||||
);
|
||||
|
||||
if (this.match(tt.comma)) {
|
||||
const nextTokenType = this.lookahead().type;
|
||||
const errorMessage =
|
||||
nextTokenType === tt.parenR
|
||||
? "A trailing comma is not permitted after the rest element"
|
||||
: "Rest parameter must be last formal parameter";
|
||||
this.raise(this.state.start, errorMessage);
|
||||
}
|
||||
this.checkCommaAfterRest(tt.parenR, "parameter");
|
||||
|
||||
break;
|
||||
} else {
|
||||
@@ -1312,7 +1325,10 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
|
||||
node.callee = this.parseNoCallExpr();
|
||||
if (
|
||||
|
||||
if (node.callee.type === "Import") {
|
||||
this.raise(node.callee.start, "Cannot use new with import(...)");
|
||||
} else if (
|
||||
node.callee.type === "OptionalMemberExpression" ||
|
||||
node.callee.type === "OptionalCallExpression"
|
||||
) {
|
||||
@@ -1320,13 +1336,13 @@ export default class ExpressionParser extends LValParser {
|
||||
this.state.lastTokEnd,
|
||||
"constructors in/after an Optional Chain are not allowed",
|
||||
);
|
||||
}
|
||||
if (this.eat(tt.questionDot)) {
|
||||
} else if (this.eat(tt.questionDot)) {
|
||||
this.raise(
|
||||
this.state.start,
|
||||
"constructors in/after an Optional Chain are not allowed",
|
||||
);
|
||||
}
|
||||
|
||||
this.parseNewArguments(node);
|
||||
return this.finishNode(node, "NewExpression");
|
||||
}
|
||||
@@ -1358,7 +1374,7 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
}
|
||||
elem.value = {
|
||||
raw: this.input
|
||||
raw: this.state.input
|
||||
.slice(this.state.start, this.state.end)
|
||||
.replace(/\r\n?/g, "\n"),
|
||||
cooked: this.state.value,
|
||||
@@ -1398,8 +1414,6 @@ export default class ExpressionParser extends LValParser {
|
||||
node.properties = [];
|
||||
this.next();
|
||||
|
||||
let firstRestLocation = null;
|
||||
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (first) {
|
||||
first = false;
|
||||
@@ -1435,34 +1449,14 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
if (this.match(tt.ellipsis)) {
|
||||
prop = this.parseSpread(isPattern ? { start: 0 } : undefined);
|
||||
if (isPattern) {
|
||||
this.toAssignable(prop, true, "object pattern");
|
||||
}
|
||||
node.properties.push(prop);
|
||||
if (isPattern) {
|
||||
const position = this.state.start;
|
||||
if (firstRestLocation !== null) {
|
||||
this.unexpected(
|
||||
firstRestLocation,
|
||||
"Cannot have multiple rest elements when destructuring",
|
||||
);
|
||||
} else if (this.eat(tt.braceR)) {
|
||||
break;
|
||||
} else if (
|
||||
this.match(tt.comma) &&
|
||||
this.lookahead().type === tt.braceR
|
||||
) {
|
||||
this.unexpected(
|
||||
position,
|
||||
"A trailing comma is not permitted after the rest element",
|
||||
);
|
||||
} else {
|
||||
firstRestLocation = position;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
this.toAssignable(prop, true, "object pattern");
|
||||
this.checkCommaAfterRest(tt.braceR, "property");
|
||||
this.expect(tt.braceR);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
prop.method = false;
|
||||
@@ -1519,13 +1513,6 @@ export default class ExpressionParser extends LValParser {
|
||||
node.properties.push(prop);
|
||||
}
|
||||
|
||||
if (firstRestLocation !== null) {
|
||||
this.unexpected(
|
||||
firstRestLocation,
|
||||
"The rest element has to be the last element when destructuring",
|
||||
);
|
||||
}
|
||||
|
||||
if (decorators.length) {
|
||||
this.raise(
|
||||
this.state.start,
|
||||
@@ -1923,7 +1910,6 @@ export default class ExpressionParser extends LValParser {
|
||||
allowEmpty: ?boolean,
|
||||
refShorthandDefaultPos: ?Pos,
|
||||
refNeedsArrowPos: ?Pos,
|
||||
refTrailingCommaPos?: Pos,
|
||||
): ?N.Expression {
|
||||
let elt;
|
||||
if (allowEmpty && this.match(tt.comma)) {
|
||||
@@ -1936,10 +1922,6 @@ export default class ExpressionParser extends LValParser {
|
||||
spreadNodeStartPos,
|
||||
spreadNodeStartLoc,
|
||||
);
|
||||
|
||||
if (refTrailingCommaPos && this.match(tt.comma)) {
|
||||
refTrailingCommaPos.start = this.state.start;
|
||||
}
|
||||
} else {
|
||||
elt = this.parseMaybeAssign(
|
||||
false,
|
||||
@@ -1994,7 +1976,8 @@ export default class ExpressionParser extends LValParser {
|
||||
if (
|
||||
(name === "class" || name === "function") &&
|
||||
(this.state.lastTokEnd !== this.state.lastTokStart + 1 ||
|
||||
this.input.charCodeAt(this.state.lastTokStart) !== charCodes.dot)
|
||||
this.state.input.charCodeAt(this.state.lastTokStart) !==
|
||||
charCodes.dot)
|
||||
) {
|
||||
this.state.context.pop();
|
||||
}
|
||||
@@ -2018,8 +2001,8 @@ export default class ExpressionParser extends LValParser {
|
||||
): void {
|
||||
if (
|
||||
this.state.strict &&
|
||||
(reservedWords.strict(word) ||
|
||||
(isBinding && reservedWords.strictBind(word)))
|
||||
(isStrictReservedWord(word) ||
|
||||
(isBinding && isStrictBindReservedWord(word)))
|
||||
) {
|
||||
this.raise(startLoc, word + " is a reserved word in strict mode");
|
||||
}
|
||||
@@ -2038,7 +2021,7 @@ export default class ExpressionParser extends LValParser {
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isReservedWord(word) || (checkKeywords && this.isKeyword(word))) {
|
||||
if (this.isReservedWord(word) || (checkKeywords && isKeyword(word))) {
|
||||
this.raise(startLoc, word + " is a reserved word");
|
||||
}
|
||||
}
|
||||
@@ -2098,8 +2081,8 @@ export default class ExpressionParser extends LValParser {
|
||||
this.next();
|
||||
if (
|
||||
this.match(tt.semi) ||
|
||||
this.canInsertSemicolon() ||
|
||||
(!this.match(tt.star) && !this.state.type.startsExpr)
|
||||
(!this.match(tt.star) && !this.state.type.startsExpr) ||
|
||||
this.canInsertSemicolon()
|
||||
) {
|
||||
node.delegate = false;
|
||||
node.argument = null;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -56,9 +56,13 @@ export default class LValParser extends NodeUtils {
|
||||
|
||||
case "ObjectExpression":
|
||||
node.type = "ObjectPattern";
|
||||
for (let index = 0; index < node.properties.length; index++) {
|
||||
const prop = node.properties[index];
|
||||
const isLast = index === node.properties.length - 1;
|
||||
for (
|
||||
let i = 0, length = node.properties.length, last = length - 1;
|
||||
i < length;
|
||||
i++
|
||||
) {
|
||||
const prop = node.properties[i];
|
||||
const isLast = i === last;
|
||||
this.toAssignableObjectExpressionProp(prop, isBinding, isLast);
|
||||
}
|
||||
break;
|
||||
@@ -122,10 +126,7 @@ export default class LValParser extends NodeUtils {
|
||||
|
||||
this.raise(prop.key.start, error);
|
||||
} else if (prop.type === "SpreadElement" && !isLast) {
|
||||
this.raise(
|
||||
prop.start,
|
||||
"The rest element has to be the last element when destructuring",
|
||||
);
|
||||
this.raiseRestNotLast(prop.start, "property");
|
||||
} else {
|
||||
this.toAssignable(prop, isBinding, "object destructuring pattern");
|
||||
}
|
||||
@@ -148,12 +149,10 @@ export default class LValParser extends NodeUtils {
|
||||
const arg = last.argument;
|
||||
this.toAssignable(arg, isBinding, contextDescription);
|
||||
if (
|
||||
[
|
||||
"Identifier",
|
||||
"MemberExpression",
|
||||
"ArrayPattern",
|
||||
"ObjectPattern",
|
||||
].indexOf(arg.type) === -1
|
||||
arg.type !== "Identifier" &&
|
||||
arg.type !== "MemberExpression" &&
|
||||
arg.type !== "ArrayPattern" &&
|
||||
arg.type !== "ObjectPattern"
|
||||
) {
|
||||
this.unexpected(arg.start);
|
||||
}
|
||||
@@ -162,13 +161,12 @@ export default class LValParser extends NodeUtils {
|
||||
}
|
||||
for (let i = 0; i < end; i++) {
|
||||
const elt = exprList[i];
|
||||
if (elt && elt.type === "SpreadElement") {
|
||||
this.raise(
|
||||
elt.start,
|
||||
"The rest element has to be the last element when destructuring",
|
||||
);
|
||||
if (elt) {
|
||||
this.toAssignable(elt, isBinding, contextDescription);
|
||||
if (elt.type === "RestElement") {
|
||||
this.raiseRestNotLast(elt.start, "element");
|
||||
}
|
||||
}
|
||||
if (elt) this.toAssignable(elt, isBinding, contextDescription);
|
||||
}
|
||||
return exprList;
|
||||
}
|
||||
@@ -199,10 +197,10 @@ export default class LValParser extends NodeUtils {
|
||||
|
||||
// Parses spread element.
|
||||
|
||||
parseSpread<T: RestElement | SpreadElement>(
|
||||
parseSpread(
|
||||
refShorthandDefaultPos: ?Pos,
|
||||
refNeedsArrowPos?: ?Pos,
|
||||
): T {
|
||||
): SpreadElement {
|
||||
const node = this.startNode();
|
||||
this.next();
|
||||
node.argument = this.parseMaybeAssign(
|
||||
@@ -211,6 +209,11 @@ export default class LValParser extends NodeUtils {
|
||||
undefined,
|
||||
refNeedsArrowPos,
|
||||
);
|
||||
|
||||
if (this.state.commaAfterSpreadAt === -1 && this.match(tt.comma)) {
|
||||
this.state.commaAfterSpreadAt = this.state.start;
|
||||
}
|
||||
|
||||
return this.finishNode(node, "SpreadElement");
|
||||
}
|
||||
|
||||
@@ -273,20 +276,13 @@ export default class LValParser extends NodeUtils {
|
||||
break;
|
||||
} else if (this.match(tt.ellipsis)) {
|
||||
elts.push(this.parseAssignableListItemTypes(this.parseRest()));
|
||||
if (
|
||||
this.state.inFunction &&
|
||||
this.state.inParameters &&
|
||||
this.match(tt.comma)
|
||||
) {
|
||||
const nextTokenType = this.lookahead().type;
|
||||
const errorMessage =
|
||||
nextTokenType === tt.parenR
|
||||
? "A trailing comma is not permitted after the rest element"
|
||||
: "Rest parameter must be last formal parameter";
|
||||
this.raise(this.state.start, errorMessage);
|
||||
} else {
|
||||
this.expect(close);
|
||||
}
|
||||
this.checkCommaAfterRest(
|
||||
close,
|
||||
this.state.inFunction && this.state.inParameters
|
||||
? "parameter"
|
||||
: "element",
|
||||
);
|
||||
this.expect(close);
|
||||
break;
|
||||
} else {
|
||||
const decorators = [];
|
||||
@@ -432,12 +428,35 @@ export default class LValParser extends NodeUtils {
|
||||
}
|
||||
|
||||
checkToRestConversion(node: SpreadElement): void {
|
||||
const validArgumentTypes = ["Identifier", "MemberExpression"];
|
||||
|
||||
if (validArgumentTypes.indexOf(node.argument.type) !== -1) {
|
||||
return;
|
||||
if (
|
||||
node.argument.type !== "Identifier" &&
|
||||
node.argument.type !== "MemberExpression"
|
||||
) {
|
||||
this.raise(node.argument.start, "Invalid rest operator's argument");
|
||||
}
|
||||
}
|
||||
|
||||
this.raise(node.argument.start, "Invalid rest operator's argument");
|
||||
checkCommaAfterRest(close: TokenType, kind: string): void {
|
||||
if (this.match(tt.comma)) {
|
||||
if (this.lookahead().type === close) {
|
||||
this.raiseCommaAfterRest(this.state.start, kind);
|
||||
} else {
|
||||
this.raiseRestNotLast(this.state.start, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkCommaAfterRestFromSpread(kind: string): void {
|
||||
if (this.state.commaAfterSpreadAt > -1) {
|
||||
this.raiseCommaAfterRest(this.state.commaAfterSpreadAt, kind);
|
||||
}
|
||||
}
|
||||
|
||||
raiseCommaAfterRest(pos: number, kind: string) {
|
||||
this.raise(pos, `A trailing comma is not permitted after the rest ${kind}`);
|
||||
}
|
||||
|
||||
raiseRestNotLast(pos: number, kind: string) {
|
||||
this.raise(pos, `The rest ${kind} must be the last ${kind}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
const directiveLiteral = this.startNodeAt(expr.start, expr.loc.start);
|
||||
const directive = this.startNodeAt(stmt.start, stmt.loc.start);
|
||||
|
||||
const raw = this.input.slice(expr.start, expr.end);
|
||||
const raw = this.state.input.slice(expr.start, expr.end);
|
||||
const val = (directiveLiteral.value = raw.slice(1, -1)); // remove quotes
|
||||
|
||||
this.addExtra(directiveLiteral, "raw", raw);
|
||||
@@ -106,7 +106,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
return this.parseForStatement(node);
|
||||
case tt._function:
|
||||
if (this.lookahead().type === tt.dot) break;
|
||||
if (!declaration) this.unexpected();
|
||||
if (!declaration) {
|
||||
this.raise(
|
||||
this.state.start,
|
||||
"Function declaration not allowed in this context",
|
||||
);
|
||||
}
|
||||
return this.parseFunctionStatement(node);
|
||||
|
||||
case tt._class:
|
||||
@@ -156,7 +161,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.next();
|
||||
|
||||
let result;
|
||||
if (starttype == tt._import) {
|
||||
if (starttype === tt._import) {
|
||||
result = this.parseImport(node);
|
||||
|
||||
if (
|
||||
@@ -189,7 +194,13 @@ export default class StatementParser extends ExpressionParser {
|
||||
const state = this.state.clone();
|
||||
this.next();
|
||||
if (this.match(tt._function) && !this.canInsertSemicolon()) {
|
||||
this.expect(tt._function);
|
||||
if (!declaration) {
|
||||
this.raise(
|
||||
this.state.lastTokStart,
|
||||
"Function declaration not allowed in this context",
|
||||
);
|
||||
}
|
||||
this.next();
|
||||
return this.parseFunction(node, true, false, true);
|
||||
} else {
|
||||
this.state = state;
|
||||
@@ -210,7 +221,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
expr.type === "Identifier" &&
|
||||
this.eat(tt.colon)
|
||||
) {
|
||||
return this.parseLabeledStatement(node, maybeName, expr);
|
||||
return this.parseLabeledStatement(node, maybeName, expr, declaration);
|
||||
} else {
|
||||
return this.parseExpressionStatement(node, expr);
|
||||
}
|
||||
@@ -540,7 +551,9 @@ export default class StatementParser extends ExpressionParser {
|
||||
parseThrowStatement(node: N.ThrowStatement): N.ThrowStatement {
|
||||
this.next();
|
||||
if (
|
||||
lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start))
|
||||
lineBreak.test(
|
||||
this.state.input.slice(this.state.lastTokEnd, this.state.start),
|
||||
)
|
||||
) {
|
||||
this.raise(this.state.lastTokEnd, "Illegal newline after throw");
|
||||
}
|
||||
@@ -649,6 +662,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
node: N.LabeledStatement,
|
||||
maybeName: string,
|
||||
expr: N.Identifier,
|
||||
declaration: boolean,
|
||||
): N.LabeledStatement {
|
||||
for (const label of this.state.labels) {
|
||||
if (label.name === maybeName) {
|
||||
@@ -676,12 +690,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
kind: kind,
|
||||
statementStart: this.state.start,
|
||||
});
|
||||
node.body = this.parseStatement(true);
|
||||
node.body = this.parseStatement(declaration);
|
||||
|
||||
if (
|
||||
node.body.type == "ClassDeclaration" ||
|
||||
(node.body.type == "VariableDeclaration" && node.body.kind !== "var") ||
|
||||
(node.body.type == "FunctionDeclaration" &&
|
||||
node.body.type === "ClassDeclaration" ||
|
||||
(node.body.type === "VariableDeclaration" && node.body.kind !== "var") ||
|
||||
(node.body.type === "FunctionDeclaration" &&
|
||||
(this.state.strict || node.body.generator || node.body.async))
|
||||
) {
|
||||
this.raise(node.body.start, "Invalid labeled declaration");
|
||||
@@ -851,6 +865,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
kind: TokenType,
|
||||
): N.VariableDeclaration {
|
||||
const declarations = (node.declarations = []);
|
||||
const isTypescript = this.hasPlugin("typescript");
|
||||
// $FlowFixMe
|
||||
node.kind = kind.keyword;
|
||||
for (;;) {
|
||||
@@ -865,7 +880,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
) {
|
||||
// `const` with no initializer is allowed in TypeScript.
|
||||
// It could be a declaration like `const x: number;`.
|
||||
if (!this.hasPlugin("typescript")) {
|
||||
if (!isTypescript) {
|
||||
this.unexpected();
|
||||
}
|
||||
} else if (
|
||||
@@ -994,8 +1009,16 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.next();
|
||||
this.takeDecorators(node);
|
||||
this.parseClassId(node, isStatement, optionalId);
|
||||
|
||||
// class bodies and heritages are implicitly strict
|
||||
const oldStrict = this.state.strict;
|
||||
this.state.strict = true;
|
||||
|
||||
this.parseClassSuper(node);
|
||||
this.parseClassBody(node);
|
||||
|
||||
this.state.strict = oldStrict;
|
||||
|
||||
return this.finishNode(
|
||||
node,
|
||||
isStatement ? "ClassDeclaration" : "ClassExpression",
|
||||
@@ -1020,9 +1043,6 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
parseClassBody(node: N.Class): void {
|
||||
// class bodies are implicitly strict
|
||||
const oldStrict = this.state.strict;
|
||||
this.state.strict = true;
|
||||
this.state.classLevel++;
|
||||
|
||||
const state = { hadConstructor: false };
|
||||
@@ -1087,7 +1107,6 @@ export default class StatementParser extends ExpressionParser {
|
||||
node.body = this.finishNode(classBody, "ClassBody");
|
||||
|
||||
this.state.classLevel--;
|
||||
this.state.strict = oldStrict;
|
||||
}
|
||||
|
||||
parseClassMember(
|
||||
@@ -1262,7 +1281,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
} else if (
|
||||
isSimple &&
|
||||
(key.name === "get" || key.name === "set") &&
|
||||
!(this.isLineTerminator() && this.match(tt.star))
|
||||
!(this.match(tt.star) && this.isLineTerminator())
|
||||
) {
|
||||
// `get\n*` is an uninitialized property named 'get' followed by a generator.
|
||||
// a getter or setter
|
||||
@@ -1505,7 +1524,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
isAsyncFunction() {
|
||||
if (!this.isContextual("async")) return false;
|
||||
|
||||
const { input, pos } = this.state;
|
||||
const { input, pos, length } = this.state;
|
||||
|
||||
skipWhiteSpace.lastIndex = pos;
|
||||
const skip = skipWhiteSpace.exec(input);
|
||||
@@ -1517,7 +1536,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
return (
|
||||
!lineBreak.test(input.slice(pos, next)) &&
|
||||
input.slice(next, next + 8) === "function" &&
|
||||
(next + 8 === input.length || !isIdentifierChar(input.charAt(next + 8)))
|
||||
(next + 8 === length || !isIdentifierChar(input.charCodeAt(next + 8)))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
@@ -1398,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);
|
||||
@@ -1630,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;
|
||||
}
|
||||
@@ -1922,20 +1923,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
// don't consider `void` to be a keyword as then it'll use the void token type
|
||||
// and set startExpr
|
||||
isKeyword(name: string): boolean {
|
||||
if (this.state.inType && name === "void") {
|
||||
return false;
|
||||
} else {
|
||||
return super.isKeyword(name);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that inside flow types, we bypass the jsx parser plugin
|
||||
readToken(code: number): void {
|
||||
const next = this.input.charCodeAt(this.state.pos + 1);
|
||||
if (
|
||||
getTokenFromCode(code: number): void {
|
||||
const next = this.state.input.charCodeAt(this.state.pos + 1);
|
||||
if (code === charCodes.leftCurlyBrace && next === charCodes.verticalBar) {
|
||||
return this.finishOp(tt.braceBarL, 2);
|
||||
} else if (
|
||||
this.state.inType &&
|
||||
(code === charCodes.greaterThan || code === charCodes.lessThan)
|
||||
) {
|
||||
@@ -1944,7 +1937,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.state.isIterator = true;
|
||||
return super.readWord();
|
||||
} else {
|
||||
return super.readToken(code);
|
||||
return super.getTokenFromCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2686,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 &&
|
||||
@@ -2701,6 +2694,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
super.readToken_mult_modulo(code);
|
||||
}
|
||||
|
||||
readToken_pipe_amp(code: number): void {
|
||||
const next = this.state.input.charCodeAt(this.state.pos + 1);
|
||||
if (
|
||||
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) {
|
||||
@@ -2710,11 +2717,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
skipBlockComment(): void {
|
||||
if (
|
||||
this.hasPlugin("flow") &&
|
||||
this.hasPlugin("flowComments") &&
|
||||
this.skipFlowComment()
|
||||
) {
|
||||
if (this.hasPlugin("flowComments") && this.skipFlowComment()) {
|
||||
if (this.state.hasFlowComment) {
|
||||
this.unexpected(
|
||||
null,
|
||||
@@ -2727,8 +2730,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hasPlugin("flow") && this.state.hasFlowComment) {
|
||||
const 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;
|
||||
@@ -2742,20 +2745,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
let shiftToFirstNonWhiteSpace = 2;
|
||||
while (
|
||||
[charCodes.space, charCodes.tab].includes(
|
||||
this.input.charCodeAt(pos + shiftToFirstNonWhiteSpace),
|
||||
this.state.input.charCodeAt(pos + shiftToFirstNonWhiteSpace),
|
||||
)
|
||||
) {
|
||||
shiftToFirstNonWhiteSpace++;
|
||||
}
|
||||
|
||||
const ch2 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);
|
||||
const ch3 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos + 1);
|
||||
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 shiftToFirstNonWhiteSpace + 2; // check for /*::
|
||||
}
|
||||
if (
|
||||
this.input.slice(
|
||||
this.state.input.slice(
|
||||
shiftToFirstNonWhiteSpace + pos,
|
||||
shiftToFirstNonWhiteSpace + pos + 12,
|
||||
) === "flow-include"
|
||||
@@ -2769,7 +2774,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
hasFlowCommentCompletion(): void {
|
||||
const end = this.input.indexOf("*/", this.state.pos);
|
||||
const end = this.state.input.indexOf("*/", this.state.pos);
|
||||
if (end === -1) {
|
||||
this.raise(this.state.pos, "Unterminated comment");
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
let out = "";
|
||||
let chunkStart = this.state.pos;
|
||||
for (;;) {
|
||||
if (this.state.pos >= this.input.length) {
|
||||
if (this.state.pos >= this.state.length) {
|
||||
this.raise(this.state.start, "Unterminated JSX contents");
|
||||
}
|
||||
|
||||
const ch = this.input.charCodeAt(this.state.pos);
|
||||
const ch = this.state.input.charCodeAt(this.state.pos);
|
||||
|
||||
switch (ch) {
|
||||
case charCodes.lessThan:
|
||||
@@ -93,20 +93,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
++this.state.pos;
|
||||
return this.finishToken(tt.jsxTagStart);
|
||||
}
|
||||
return this.getTokenFromCode(ch);
|
||||
return super.getTokenFromCode(ch);
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.state.pos);
|
||||
out += this.state.input.slice(chunkStart, this.state.pos);
|
||||
return this.finishToken(tt.jsxText, out);
|
||||
|
||||
case charCodes.ampersand:
|
||||
out += this.input.slice(chunkStart, this.state.pos);
|
||||
out += this.state.input.slice(chunkStart, this.state.pos);
|
||||
out += this.jsxReadEntity();
|
||||
chunkStart = this.state.pos;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.state.pos);
|
||||
out += this.state.input.slice(chunkStart, this.state.pos);
|
||||
out += this.jsxReadNewLine(true);
|
||||
chunkStart = this.state.pos;
|
||||
} else {
|
||||
@@ -117,12 +117,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
jsxReadNewLine(normalizeCRLF: boolean): string {
|
||||
const ch = this.input.charCodeAt(this.state.pos);
|
||||
const ch = this.state.input.charCodeAt(this.state.pos);
|
||||
let out;
|
||||
++this.state.pos;
|
||||
if (
|
||||
ch === charCodes.carriageReturn &&
|
||||
this.input.charCodeAt(this.state.pos) === charCodes.lineFeed
|
||||
this.state.input.charCodeAt(this.state.pos) === charCodes.lineFeed
|
||||
) {
|
||||
++this.state.pos;
|
||||
out = normalizeCRLF ? "\n" : "\r\n";
|
||||
@@ -139,25 +139,25 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
let out = "";
|
||||
let chunkStart = ++this.state.pos;
|
||||
for (;;) {
|
||||
if (this.state.pos >= this.input.length) {
|
||||
if (this.state.pos >= this.state.length) {
|
||||
this.raise(this.state.start, "Unterminated string constant");
|
||||
}
|
||||
|
||||
const ch = this.input.charCodeAt(this.state.pos);
|
||||
const ch = this.state.input.charCodeAt(this.state.pos);
|
||||
if (ch === quote) break;
|
||||
if (ch === charCodes.ampersand) {
|
||||
out += this.input.slice(chunkStart, this.state.pos);
|
||||
out += this.state.input.slice(chunkStart, this.state.pos);
|
||||
out += this.jsxReadEntity();
|
||||
chunkStart = this.state.pos;
|
||||
} else if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.state.pos);
|
||||
out += this.state.input.slice(chunkStart, this.state.pos);
|
||||
out += this.jsxReadNewLine(false);
|
||||
chunkStart = this.state.pos;
|
||||
} else {
|
||||
++this.state.pos;
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.state.pos++);
|
||||
out += this.state.input.slice(chunkStart, this.state.pos++);
|
||||
return this.finishToken(tt.string, out);
|
||||
}
|
||||
|
||||
@@ -165,11 +165,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
let str = "";
|
||||
let count = 0;
|
||||
let entity;
|
||||
let ch = this.input[this.state.pos];
|
||||
let ch = this.state.input[this.state.pos];
|
||||
|
||||
const startPos = ++this.state.pos;
|
||||
while (this.state.pos < this.input.length && count++ < 10) {
|
||||
ch = this.input[this.state.pos++];
|
||||
while (this.state.pos < this.state.length && count++ < 10) {
|
||||
ch = this.state.input[this.state.pos++];
|
||||
if (ch === ";") {
|
||||
if (str[0] === "#") {
|
||||
if (str[1] === "x") {
|
||||
@@ -208,11 +208,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
let ch;
|
||||
const start = this.state.pos;
|
||||
do {
|
||||
ch = this.input.charCodeAt(++this.state.pos);
|
||||
ch = this.state.input.charCodeAt(++this.state.pos);
|
||||
} while (isIdentifierChar(ch) || ch === charCodes.dash);
|
||||
return this.finishToken(
|
||||
tt.jsxName,
|
||||
this.input.slice(start, this.state.pos),
|
||||
this.state.input.slice(start, this.state.pos),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -520,8 +520,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
readToken(code: number): void {
|
||||
if (this.state.inPropertyName) return super.readToken(code);
|
||||
getTokenFromCode(code: number): void {
|
||||
if (this.state.inPropertyName) return super.getTokenFromCode(code);
|
||||
|
||||
const context = this.curContext();
|
||||
|
||||
@@ -557,7 +557,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.finishToken(tt.jsxTagStart);
|
||||
}
|
||||
|
||||
return super.readToken(code);
|
||||
return super.getTokenFromCode(code);
|
||||
}
|
||||
|
||||
updateContext(prevType: TokenType): void {
|
||||
|
||||
@@ -45,6 +45,8 @@ function keywordTypeFromName(
|
||||
return "TSAnyKeyword";
|
||||
case "boolean":
|
||||
return "TSBooleanKeyword";
|
||||
case "bigint":
|
||||
return "TSBigIntKeyword";
|
||||
case "never":
|
||||
return "TSNeverKeyword";
|
||||
case "number":
|
||||
@@ -218,6 +220,28 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return result;
|
||||
}
|
||||
|
||||
tsParseImportType(): N.TsImportType {
|
||||
const node: N.TsImportType = this.startNode();
|
||||
this.expect(tt._import);
|
||||
this.expect(tt.parenL);
|
||||
if (!this.match(tt.string)) {
|
||||
throw this.unexpected(
|
||||
null,
|
||||
"Argument in a type import must be a string literal",
|
||||
);
|
||||
}
|
||||
node.argument = this.parseLiteral(this.state.value, "StringLiteral");
|
||||
this.expect(tt.parenR);
|
||||
|
||||
if (this.eat(tt.dot)) {
|
||||
node.qualifier = this.tsParseEntityName(/* allowReservedWords */ true);
|
||||
}
|
||||
if (this.isRelational("<")) {
|
||||
node.typeParameters = this.tsParseTypeArguments();
|
||||
}
|
||||
return this.finishNode(node, "TSImportType");
|
||||
}
|
||||
|
||||
tsParseEntityName(allowReservedWords: boolean): N.TsEntityName {
|
||||
let entity: N.TsEntityName = this.parseIdentifier();
|
||||
while (this.eat(tt.dot)) {
|
||||
@@ -240,7 +264,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
tsParseThisTypePredicate(lhs: N.TsThisType): N.TsTypePredicate {
|
||||
this.next();
|
||||
const node: N.TsTypePredicate = this.startNode();
|
||||
const node: N.TsTypePredicate = this.startNodeAtNode(lhs);
|
||||
node.parameterName = lhs;
|
||||
node.typeAnnotation = this.tsParseTypeAnnotation(/* eatColon */ false);
|
||||
return this.finishNode(node, "TSTypePredicate");
|
||||
@@ -255,7 +279,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
tsParseTypeQuery(): N.TsTypeQuery {
|
||||
const node: N.TsTypeQuery = this.startNode();
|
||||
this.expect(tt._typeof);
|
||||
node.exprName = this.tsParseEntityName(/* allowReservedWords */ true);
|
||||
if (this.match(tt._import)) {
|
||||
node.exprName = this.tsParseImportType();
|
||||
} else {
|
||||
node.exprName = this.tsParseEntityName(/* allowReservedWords */ true);
|
||||
}
|
||||
return this.finishNode(node, "TSTypeQuery");
|
||||
}
|
||||
|
||||
@@ -370,8 +398,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
this.expect(tt.bracketL);
|
||||
const id = this.parseIdentifier();
|
||||
this.expect(tt.colon);
|
||||
id.typeAnnotation = this.tsParseTypeAnnotation(/* eatColon */ false);
|
||||
id.typeAnnotation = this.tsParseTypeAnnotation();
|
||||
this.finishNode(id, "Identifier"); // set end position to end of type
|
||||
|
||||
this.expect(tt.bracketR);
|
||||
node.parameters = [id];
|
||||
|
||||
@@ -518,17 +547,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
// No mandatory elements may follow optional elements
|
||||
// If there's a rest element, it must be at the end of the tuple
|
||||
let seenOptionalElement = false;
|
||||
node.elementTypes.forEach((elementNode, i) => {
|
||||
if (elementNode.type === "TSRestType") {
|
||||
if (i !== node.elementTypes.length - 1) {
|
||||
this.raise(
|
||||
elementNode.start,
|
||||
"A rest element must be last in a tuple type.",
|
||||
);
|
||||
}
|
||||
} else if (elementNode.type === "TSOptionalType") {
|
||||
node.elementTypes.forEach(elementNode => {
|
||||
if (elementNode.type === "TSOptionalType") {
|
||||
seenOptionalElement = true;
|
||||
} else if (seenOptionalElement) {
|
||||
} else if (seenOptionalElement && elementNode.type !== "TSRestType") {
|
||||
this.raise(
|
||||
elementNode.start,
|
||||
"A required element cannot follow an optional element.",
|
||||
@@ -545,6 +567,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
const restNode: N.TsRestType = this.startNode();
|
||||
this.next(); // skips ellipsis
|
||||
restNode.typeAnnotation = this.tsParseType();
|
||||
this.checkCommaAfterRest(tt.bracketR, "type");
|
||||
return this.finishNode(restNode, "TSRestType");
|
||||
}
|
||||
|
||||
@@ -643,6 +666,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
case tt._typeof:
|
||||
return this.tsParseTypeQuery();
|
||||
case tt._import:
|
||||
return this.tsParseImportType();
|
||||
case tt.braceL:
|
||||
return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this))
|
||||
? this.tsParseMappedType()
|
||||
@@ -894,6 +919,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
tsParseTypeAssertion(): N.TsTypeAssertion {
|
||||
const node: N.TsTypeAssertion = this.startNode();
|
||||
this.next(); // <
|
||||
// Not actually necessary to set state.inType because we never reach here if JSX plugin is enabled,
|
||||
// but need `tsInType` to satisfy the assertion in `tsParseType`.
|
||||
node.typeAnnotation = this.tsInType(() => this.tsParseType());
|
||||
@@ -902,11 +928,21 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.finishNode(node, "TSTypeAssertion");
|
||||
}
|
||||
|
||||
tsParseHeritageClause(): $ReadOnlyArray<N.TsExpressionWithTypeArguments> {
|
||||
return this.tsParseDelimitedList(
|
||||
tsParseHeritageClause(
|
||||
descriptor: string,
|
||||
): $ReadOnlyArray<N.TsExpressionWithTypeArguments> {
|
||||
const originalStart = this.state.start;
|
||||
|
||||
const delimitedList = this.tsParseDelimitedList(
|
||||
"HeritageClauseElement",
|
||||
this.tsParseExpressionWithTypeArguments.bind(this),
|
||||
);
|
||||
|
||||
if (!delimitedList.length) {
|
||||
this.raise(originalStart, `'${descriptor}' list cannot be empty.`);
|
||||
}
|
||||
|
||||
return delimitedList;
|
||||
}
|
||||
|
||||
tsParseExpressionWithTypeArguments(): N.TsExpressionWithTypeArguments {
|
||||
@@ -927,7 +963,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.id = this.parseIdentifier();
|
||||
node.typeParameters = this.tsTryParseTypeParameters();
|
||||
if (this.eat(tt._extends)) {
|
||||
node.extends = this.tsParseHeritageClause();
|
||||
node.extends = this.tsParseHeritageClause("extends");
|
||||
}
|
||||
const body: N.TSInterfaceBody = this.startNode();
|
||||
body.body = this.tsInType(this.tsParseObjectTypeMembers.bind(this));
|
||||
@@ -1151,6 +1187,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
tsTryParseDeclare(nany: any): ?N.Declaration {
|
||||
if (this.isLineTerminator()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.state.type) {
|
||||
case tt._function:
|
||||
this.next();
|
||||
@@ -1227,10 +1267,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
): ?N.Declaration {
|
||||
switch (value) {
|
||||
case "abstract":
|
||||
if (next || this.match(tt._class)) {
|
||||
if (this.tsCheckLineTerminatorAndMatch(tt._class, next)) {
|
||||
const cls: N.ClassDeclaration = node;
|
||||
cls.abstract = true;
|
||||
if (next) this.next();
|
||||
if (next) {
|
||||
this.next();
|
||||
if (!this.match(tt._class)) {
|
||||
this.unexpected(null, tt._class);
|
||||
}
|
||||
}
|
||||
return this.parseClass(
|
||||
cls,
|
||||
/* isStatement */ true,
|
||||
@@ -1247,7 +1292,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
break;
|
||||
|
||||
case "interface":
|
||||
if (next || this.match(tt.name)) {
|
||||
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
|
||||
if (next) this.next();
|
||||
return this.tsParseInterfaceDeclaration(node);
|
||||
}
|
||||
@@ -1257,20 +1302,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if (next) this.next();
|
||||
if (this.match(tt.string)) {
|
||||
return this.tsParseAmbientExternalModuleDeclaration(node);
|
||||
} else if (next || this.match(tt.name)) {
|
||||
} else if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
|
||||
return this.tsParseModuleOrNamespaceDeclaration(node);
|
||||
}
|
||||
break;
|
||||
|
||||
case "namespace":
|
||||
if (next || this.match(tt.name)) {
|
||||
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
|
||||
if (next) this.next();
|
||||
return this.tsParseModuleOrNamespaceDeclaration(node);
|
||||
}
|
||||
break;
|
||||
|
||||
case "type":
|
||||
if (next || this.match(tt.name)) {
|
||||
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
|
||||
if (next) this.next();
|
||||
return this.tsParseTypeAliasDeclaration(node);
|
||||
}
|
||||
@@ -1278,6 +1323,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
tsCheckLineTerminatorAndMatch(tokenType: TokenType, next: boolean) {
|
||||
return (next || this.match(tokenType)) && !this.isLineTerminator();
|
||||
}
|
||||
|
||||
tsTryParseGenericAsyncArrowFunction(
|
||||
startPos: number,
|
||||
startLoc: Position,
|
||||
@@ -1362,6 +1411,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
allowModifiers: ?boolean,
|
||||
decorators: N.Decorator[],
|
||||
): N.Pattern | N.TSParameterProperty {
|
||||
// Store original location/position to include modifiers in range
|
||||
const startPos = this.state.start;
|
||||
const startLoc = this.state.startLoc;
|
||||
|
||||
let accessibility: ?N.Accessibility;
|
||||
let readonly = false;
|
||||
if (allowModifiers) {
|
||||
@@ -1373,7 +1426,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.parseAssignableListItemTypes(left);
|
||||
const elt = this.parseMaybeDefault(left.start, left.loc.start, left);
|
||||
if (accessibility || readonly) {
|
||||
const pp: N.TSParameterProperty = this.startNodeAtNode(elt);
|
||||
const pp: N.TSParameterProperty = this.startNodeAt(startPos, startLoc);
|
||||
if (decorators.length) {
|
||||
pp.decorators = decorators;
|
||||
}
|
||||
@@ -1387,12 +1440,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
pp.parameter = elt;
|
||||
return this.finishNode(pp, "TSParameterProperty");
|
||||
} else {
|
||||
if (decorators.length) {
|
||||
left.decorators = decorators;
|
||||
}
|
||||
return elt;
|
||||
}
|
||||
|
||||
if (decorators.length) {
|
||||
left.decorators = decorators;
|
||||
}
|
||||
|
||||
return elt;
|
||||
}
|
||||
|
||||
parseFunctionBodyAndFinish(
|
||||
@@ -1871,7 +1925,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.superTypeParameters = this.tsParseTypeArguments();
|
||||
}
|
||||
if (this.eatContextual("implements")) {
|
||||
node.implements = this.tsParseHeritageClause();
|
||||
node.implements = this.tsParseHeritageClause("implements");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1983,10 +2037,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
// Correct TypeScript code should have at least 1 type parameter, but don't crash on bad code.
|
||||
if (typeParameters && typeParameters.params.length !== 0) {
|
||||
this.resetStartLocationFromNode(
|
||||
arrowExpression,
|
||||
typeParameters.params[0],
|
||||
);
|
||||
this.resetStartLocationFromNode(arrowExpression, typeParameters);
|
||||
}
|
||||
arrowExpression.typeParameters = typeParameters;
|
||||
return arrowExpression;
|
||||
@@ -1994,7 +2045,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
// Handle type assertions
|
||||
parseMaybeUnary(refShorthandDefaultPos?: ?Pos): N.Expression {
|
||||
if (!this.hasPlugin("jsx") && this.eatRelational("<")) {
|
||||
if (!this.hasPlugin("jsx") && this.isRelational("<")) {
|
||||
return this.tsParseTypeAssertion();
|
||||
} else {
|
||||
return super.parseMaybeUnary(refShorthandDefaultPos);
|
||||
@@ -2167,11 +2218,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
// ensure that inside types, we bypass the jsx parser plugin
|
||||
readToken(code: number): void {
|
||||
getTokenFromCode(code: number): void {
|
||||
if (this.state.inType && (code === 62 || code === 60)) {
|
||||
return this.finishOp(tt.relational, 1);
|
||||
} else {
|
||||
return super.readToken(code);
|
||||
return super.getTokenFromCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,7 +1205,9 @@ export default class Tokenizer extends LocationParser {
|
||||
case charCodes.lowercaseF:
|
||||
return "\f";
|
||||
case charCodes.carriageReturn:
|
||||
if (this.input.charCodeAt(this.state.pos) === charCodes.lineFeed) {
|
||||
if (
|
||||
this.state.input.charCodeAt(this.state.pos) === charCodes.lineFeed
|
||||
) {
|
||||
++this.state.pos;
|
||||
}
|
||||
case charCodes.lineFeed:
|
||||
@@ -1215,7 +1218,7 @@ export default class Tokenizer extends LocationParser {
|
||||
if (ch >= charCodes.digit0 && ch <= charCodes.digit7) {
|
||||
const codePos = this.state.pos - 1;
|
||||
// $FlowFixMe
|
||||
let octalStr = this.input
|
||||
let octalStr = this.state.input
|
||||
.substr(this.state.pos - 1, 3)
|
||||
.match(/^[0-7]+/)[0];
|
||||
let octal = parseInt(octalStr, 8);
|
||||
@@ -1266,23 +1269,28 @@ export default class Tokenizer extends LocationParser {
|
||||
// as a micro-optimization.
|
||||
|
||||
readWord1(): string {
|
||||
let word = "";
|
||||
this.state.containsEsc = false;
|
||||
let word = "",
|
||||
first = true,
|
||||
chunkStart = this.state.pos;
|
||||
while (this.state.pos < this.input.length) {
|
||||
const ch = this.input.codePointAt(this.state.pos);
|
||||
const start = this.state.pos;
|
||||
let chunkStart = this.state.pos;
|
||||
|
||||
while (this.state.pos < this.state.length) {
|
||||
const ch = this.state.input.codePointAt(this.state.pos);
|
||||
if (isIdentifierChar(ch)) {
|
||||
this.state.pos += ch <= 0xffff ? 1 : 2;
|
||||
} else if (this.state.isIterator && ch === charCodes.atSign) {
|
||||
this.state.pos += 1;
|
||||
++this.state.pos;
|
||||
} else if (ch === charCodes.backslash) {
|
||||
this.state.containsEsc = true;
|
||||
|
||||
word += this.input.slice(chunkStart, this.state.pos);
|
||||
word += this.state.input.slice(chunkStart, this.state.pos);
|
||||
const escStart = this.state.pos;
|
||||
const identifierCheck =
|
||||
this.state.pos === start ? isIdentifierStart : isIdentifierChar;
|
||||
|
||||
if (this.input.charCodeAt(++this.state.pos) !== charCodes.lowercaseU) {
|
||||
if (
|
||||
this.state.input.charCodeAt(++this.state.pos) !== charCodes.lowercaseU
|
||||
) {
|
||||
this.raise(
|
||||
this.state.pos,
|
||||
"Expecting Unicode escape sequence \\uXXXX",
|
||||
@@ -1291,8 +1299,11 @@ export default class Tokenizer extends LocationParser {
|
||||
|
||||
++this.state.pos;
|
||||
const esc = this.readCodePoint(true);
|
||||
// $FlowFixMe (thinks esc may be null, but throwOnInvalid is true)
|
||||
if (!(first ? isIdentifierStart : isIdentifierChar)(esc, true)) {
|
||||
|
||||
if (
|
||||
// $FlowFixMe (thinks esc may be null, but throwOnInvalid is true)
|
||||
!identifierCheck(esc, true)
|
||||
) {
|
||||
this.raise(escStart, "Invalid Unicode escape");
|
||||
}
|
||||
|
||||
@@ -1302,9 +1313,8 @@ export default class Tokenizer extends LocationParser {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
return word + this.input.slice(chunkStart, this.state.pos);
|
||||
return word + this.state.input.slice(chunkStart, this.state.pos);
|
||||
}
|
||||
|
||||
isIterator(word: string): boolean {
|
||||
@@ -1316,14 +1326,10 @@ export default class Tokenizer extends LocationParser {
|
||||
|
||||
readWord(): void {
|
||||
const word = this.readWord1();
|
||||
let type = tt.name;
|
||||
const type = keywordTypes[word] || tt.name;
|
||||
|
||||
if (this.isKeyword(word)) {
|
||||
if (this.state.containsEsc) {
|
||||
this.raise(this.state.pos, `Escape sequence in keyword ${word}`);
|
||||
}
|
||||
|
||||
type = keywordTypes[word];
|
||||
if (type.keyword && this.state.containsEsc) {
|
||||
this.raise(this.state.pos, `Escape sequence in keyword ${word}`);
|
||||
}
|
||||
|
||||
// Allow @@iterator and @@asyncIterator as a identifier only inside type
|
||||
@@ -1358,7 +1364,7 @@ export default class Tokenizer extends LocationParser {
|
||||
(prevType === tt.name && this.state.exprAllowed)
|
||||
) {
|
||||
return lineBreak.test(
|
||||
this.input.slice(this.state.lastTokEnd, this.state.start),
|
||||
this.state.input.slice(this.state.lastTokEnd, this.state.start),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,95 +6,52 @@ import { Position } from "../util/location";
|
||||
|
||||
import { types as ct, type TokContext } from "./context";
|
||||
import type { Token } from "./index";
|
||||
import { types as tt, type TokenType, type TopicContextState } from "./types";
|
||||
import { types as tt, type TokenType } from "./types";
|
||||
|
||||
type TopicContextState = {
|
||||
// When a topic binding has been currently established,
|
||||
// then this is 1. Otherwise, it is 0. This is forwards compatible
|
||||
// with a future plugin for multiple lexical topics.
|
||||
maxNumOfResolvableTopics: number,
|
||||
|
||||
// When a topic binding has been currently established, and if that binding
|
||||
// has been used as a topic reference `#`, then this is 0. Otherwise, it is
|
||||
// `null`. This is forwards compatible with a future plugin for multiple
|
||||
// lexical topics.
|
||||
maxTopicIndex: null | 0,
|
||||
};
|
||||
|
||||
export default class State {
|
||||
strict: boolean;
|
||||
input: string;
|
||||
length: number;
|
||||
|
||||
curLine: number;
|
||||
|
||||
// And, if locations are used, the {line, column} object
|
||||
// corresponding to those offsets
|
||||
startLoc: Position;
|
||||
endLoc: Position;
|
||||
|
||||
init(options: Options, input: string): void {
|
||||
this.strict =
|
||||
options.strictMode === false ? false : options.sourceType === "module";
|
||||
|
||||
this.input = input;
|
||||
this.length = input.length;
|
||||
|
||||
this.potentialArrowAt = -1;
|
||||
|
||||
this.noArrowAt = [];
|
||||
this.noArrowParamsConversionAt = [];
|
||||
|
||||
this.inMethod = false;
|
||||
this.inFunction = false;
|
||||
this.inParameters = false;
|
||||
this.maybeInArrowParameters = false;
|
||||
this.inGenerator = false;
|
||||
this.inAsync = false;
|
||||
this.inPipeline = false;
|
||||
this.inPropertyName = false;
|
||||
this.inType = false;
|
||||
this.inClassProperty = false;
|
||||
this.noAnonFunctionType = false;
|
||||
this.hasFlowComment = false;
|
||||
this.isIterator = false;
|
||||
|
||||
// Used by smartPipelines.
|
||||
this.topicContext = {
|
||||
maxNumOfResolvableTopics: 0,
|
||||
maxTopicIndex: null,
|
||||
};
|
||||
|
||||
this.classLevel = 0;
|
||||
|
||||
this.labels = [];
|
||||
|
||||
this.decoratorStack = [[]];
|
||||
|
||||
this.yieldOrAwaitInPossibleArrowParameters = null;
|
||||
|
||||
this.tokens = [];
|
||||
|
||||
this.comments = [];
|
||||
|
||||
this.trailingComments = [];
|
||||
this.leadingComments = [];
|
||||
this.commentStack = [];
|
||||
// $FlowIgnore
|
||||
this.commentPreviousNode = null;
|
||||
|
||||
this.pos = this.lineStart = 0;
|
||||
this.curLine = options.startLine;
|
||||
|
||||
this.type = tt.eof;
|
||||
this.value = null;
|
||||
this.start = this.end = this.pos;
|
||||
this.startLoc = this.endLoc = this.curPosition();
|
||||
|
||||
// $FlowIgnore
|
||||
this.lastTokEndLoc = this.lastTokStartLoc = null;
|
||||
this.lastTokStart = this.lastTokEnd = this.pos;
|
||||
|
||||
this.context = [ct.braceStatement];
|
||||
this.exprAllowed = true;
|
||||
|
||||
this.containsEsc = this.containsOctal = false;
|
||||
this.octalPosition = null;
|
||||
|
||||
this.invalidTemplateEscapePosition = null;
|
||||
|
||||
this.exportedIdentifiers = [];
|
||||
}
|
||||
|
||||
// TODO
|
||||
strict: boolean;
|
||||
|
||||
// TODO
|
||||
input: string;
|
||||
|
||||
// Used to signify the start of a potential arrow function
|
||||
potentialArrowAt: number;
|
||||
potentialArrowAt: number = -1;
|
||||
|
||||
// Used to signify the start of an expression which looks like a
|
||||
// typed arrow function, but it isn't
|
||||
// e.g. a ? (b) : c => d
|
||||
// ^
|
||||
noArrowAt: number[];
|
||||
noArrowAt: number[] = [];
|
||||
|
||||
// Used to signify the start of an expression whose params, if it looks like
|
||||
// an arrow function, shouldn't be converted to assignable nodes.
|
||||
@@ -102,40 +59,48 @@ export default class State {
|
||||
// conditional expressions.
|
||||
// e.g. a ? (b) : c => d
|
||||
// ^
|
||||
noArrowParamsConversionAt: number[];
|
||||
noArrowParamsConversionAt: number[] = [];
|
||||
|
||||
// A comma after "...a" is only allowed in spread, but not in rest.
|
||||
// Since we parse destructuring patterns as array/object literals
|
||||
// and then convert them, we need to track it.
|
||||
commaAfterSpreadAt: number = -1;
|
||||
|
||||
// Flags to track whether we are in a function, a generator.
|
||||
inFunction: boolean;
|
||||
inParameters: boolean;
|
||||
maybeInArrowParameters: boolean;
|
||||
inGenerator: boolean;
|
||||
inMethod: boolean | N.MethodKind;
|
||||
inAsync: boolean;
|
||||
inPipeline: boolean;
|
||||
inType: boolean;
|
||||
noAnonFunctionType: boolean;
|
||||
inPropertyName: boolean;
|
||||
inClassProperty: boolean;
|
||||
hasFlowComment: boolean;
|
||||
isIterator: boolean;
|
||||
inFunction: boolean = false;
|
||||
inParameters: boolean = false;
|
||||
maybeInArrowParameters: boolean = false;
|
||||
inGenerator: boolean = false;
|
||||
inMethod: boolean | N.MethodKind = false;
|
||||
inAsync: boolean = false;
|
||||
inPipeline: boolean = false;
|
||||
inType: boolean = false;
|
||||
noAnonFunctionType: boolean = false;
|
||||
inPropertyName: boolean = false;
|
||||
inClassProperty: boolean = false;
|
||||
hasFlowComment: boolean = false;
|
||||
isIterator: boolean = false;
|
||||
|
||||
// For the smartPipelines plugin:
|
||||
topicContext: TopicContextState;
|
||||
topicContext: TopicContextState = {
|
||||
maxNumOfResolvableTopics: 0,
|
||||
maxTopicIndex: null,
|
||||
};
|
||||
|
||||
// Check whether we are in a (nested) class or not.
|
||||
classLevel: number;
|
||||
classLevel: number = 0;
|
||||
|
||||
// Labels in scope.
|
||||
labels: Array<{
|
||||
kind: ?("loop" | "switch"),
|
||||
name?: ?string,
|
||||
statementStart?: number,
|
||||
}>;
|
||||
}> = [];
|
||||
|
||||
// Leading decorators. Last element of the stack represents the decorators in current context.
|
||||
// Supports nesting of decorators, e.g. @foo(@bar class inner {}) class outer {}
|
||||
// where @foo belongs to the outer class and @bar to the inner
|
||||
decoratorStack: Array<Array<N.Decorator>>;
|
||||
decoratorStack: Array<Array<N.Decorator>> = [[]];
|
||||
|
||||
// The first yield or await expression inside parenthesized expressions
|
||||
// and arrow function parameters. It is used to disallow yield and await in
|
||||
@@ -143,72 +108,69 @@ export default class State {
|
||||
yieldOrAwaitInPossibleArrowParameters:
|
||||
| N.YieldExpression
|
||||
| N.AwaitExpression
|
||||
| null;
|
||||
| null = null;
|
||||
|
||||
// Token store.
|
||||
tokens: Array<Token | N.Comment>;
|
||||
tokens: Array<Token | N.Comment> = [];
|
||||
|
||||
// Comment store.
|
||||
comments: Array<N.Comment>;
|
||||
comments: Array<N.Comment> = [];
|
||||
|
||||
// Comment attachment store
|
||||
trailingComments: Array<N.Comment>;
|
||||
leadingComments: Array<N.Comment>;
|
||||
trailingComments: Array<N.Comment> = [];
|
||||
leadingComments: Array<N.Comment> = [];
|
||||
commentStack: Array<{
|
||||
start: number,
|
||||
leadingComments: ?Array<N.Comment>,
|
||||
trailingComments: ?Array<N.Comment>,
|
||||
type: string,
|
||||
}>;
|
||||
commentPreviousNode: N.Node;
|
||||
}> = [];
|
||||
// $FlowIgnore this is initialized when the parser starts.
|
||||
commentPreviousNode: N.Node = null;
|
||||
|
||||
// The current position of the tokenizer in the input.
|
||||
pos: number;
|
||||
lineStart: number;
|
||||
curLine: number;
|
||||
pos: number = 0;
|
||||
lineStart: number = 0;
|
||||
|
||||
// Properties of the current token:
|
||||
// Its type
|
||||
type: TokenType;
|
||||
type: TokenType = tt.eof;
|
||||
|
||||
// For tokens that include more information than their type, the value
|
||||
value: any;
|
||||
value: any = null;
|
||||
|
||||
// Its start and end offset
|
||||
start: number;
|
||||
end: number;
|
||||
|
||||
// And, if locations are used, the {line, column} object
|
||||
// corresponding to those offsets
|
||||
startLoc: Position;
|
||||
endLoc: Position;
|
||||
start: number = 0;
|
||||
end: number = 0;
|
||||
|
||||
// Position information for the previous token
|
||||
lastTokEndLoc: Position;
|
||||
lastTokStartLoc: Position;
|
||||
lastTokStart: number;
|
||||
lastTokEnd: number;
|
||||
// $FlowIgnore this is initialized when generating the second token.
|
||||
lastTokEndLoc: Position = null;
|
||||
// $FlowIgnore this is initialized when generating the second token.
|
||||
lastTokStartLoc: Position = null;
|
||||
lastTokStart: number = 0;
|
||||
lastTokEnd: number = 0;
|
||||
|
||||
// The context stack is used to superficially track syntactic
|
||||
// context to predict whether a regular expression is allowed in a
|
||||
// given position.
|
||||
context: Array<TokContext>;
|
||||
exprAllowed: boolean;
|
||||
context: Array<TokContext> = [ct.braceStatement];
|
||||
exprAllowed: boolean = true;
|
||||
|
||||
// Used to signal to callers of `readWord1` whether the word
|
||||
// contained any escape sequences. This is needed because words with
|
||||
// escape sequences must not be interpreted as keywords.
|
||||
containsEsc: boolean;
|
||||
containsEsc: boolean = false;
|
||||
|
||||
// TODO
|
||||
containsOctal: boolean;
|
||||
octalPosition: ?number;
|
||||
containsOctal: boolean = false;
|
||||
octalPosition: ?number = null;
|
||||
|
||||
// Names of exports store. `default` is stored as a name for both
|
||||
// `export default foo;` and `export { foo as default };`.
|
||||
exportedIdentifiers: Array<string>;
|
||||
exportedIdentifiers: Array<string> = [];
|
||||
|
||||
invalidTemplateEscapePosition: ?number;
|
||||
invalidTemplateEscapePosition: ?number = null;
|
||||
|
||||
curPosition(): Position {
|
||||
return new Position(this.curLine, this.pos - this.lineStart);
|
||||
@@ -216,7 +178,9 @@ export default class State {
|
||||
|
||||
clone(skipArrays?: boolean): State {
|
||||
const state = new State();
|
||||
Object.keys(this).forEach(key => {
|
||||
const keys = Object.keys(this);
|
||||
for (let i = 0, length = keys.length; i < length; i++) {
|
||||
const key = keys[i];
|
||||
// $FlowIgnore
|
||||
let val = this[key];
|
||||
|
||||
@@ -226,7 +190,8 @@ export default class State {
|
||||
|
||||
// $FlowIgnore
|
||||
state[key] = val;
|
||||
});
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,12 @@
|
||||
// expressions and divisions. It is set on all token types that can
|
||||
// be followed by an expression (thus, a slash after them would be a
|
||||
// regular expression).
|
||||
//
|
||||
|
||||
// The `startsExpr` property is used to determine whether an expression
|
||||
// may be the “argument” subexpression of a `yield` expression or
|
||||
// `yield` statement. It is set on all token types that may be at the
|
||||
// start of a subexpression.
|
||||
|
||||
// `isLoop` marks a keyword as starting a loop, which is important
|
||||
// to know when parsing a label, in order to allow or disallow
|
||||
// continue jumps to that label.
|
||||
@@ -104,7 +109,7 @@ export const types: { [name: string]: TokenType } = {
|
||||
backQuote: new TokenType("`", { startsExpr }),
|
||||
dollarBraceL: new TokenType("${", { beforeExpr, startsExpr }),
|
||||
at: new TokenType("@"),
|
||||
hash: new TokenType("#"),
|
||||
hash: new TokenType("#", { startsExpr }),
|
||||
|
||||
// Special hashbang token.
|
||||
interpreterDirective: new TokenType("#!..."),
|
||||
@@ -128,20 +133,20 @@ export const types: { [name: string]: TokenType } = {
|
||||
incDec: new TokenType("++/--", { prefix, postfix, startsExpr }),
|
||||
bang: new TokenType("!", { beforeExpr, prefix, startsExpr }),
|
||||
tilde: new TokenType("~", { beforeExpr, prefix, startsExpr }),
|
||||
pipeline: new BinopTokenType("|>", 0),
|
||||
nullishCoalescing: new BinopTokenType("??", 1),
|
||||
logicalOR: new BinopTokenType("||", 1),
|
||||
logicalAND: new BinopTokenType("&&", 2),
|
||||
bitwiseOR: new BinopTokenType("|", 3),
|
||||
bitwiseXOR: new BinopTokenType("^", 4),
|
||||
bitwiseAND: new BinopTokenType("&", 5),
|
||||
equality: new BinopTokenType("==/!=", 6),
|
||||
relational: new BinopTokenType("</>", 7),
|
||||
bitShift: new BinopTokenType("<</>>", 8),
|
||||
pipeline: BinopTokenType("|>", 0),
|
||||
nullishCoalescing: BinopTokenType("??", 1),
|
||||
logicalOR: BinopTokenType("||", 1),
|
||||
logicalAND: BinopTokenType("&&", 2),
|
||||
bitwiseOR: BinopTokenType("|", 3),
|
||||
bitwiseXOR: BinopTokenType("^", 4),
|
||||
bitwiseAND: BinopTokenType("&", 5),
|
||||
equality: BinopTokenType("==/!=", 6),
|
||||
relational: BinopTokenType("</>", 7),
|
||||
bitShift: BinopTokenType("<</>>", 8),
|
||||
plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }),
|
||||
modulo: new BinopTokenType("%", 10),
|
||||
star: new BinopTokenType("*", 10),
|
||||
slash: new BinopTokenType("/", 10),
|
||||
modulo: BinopTokenType("%", 10),
|
||||
star: BinopTokenType("*", 10),
|
||||
slash: BinopTokenType("/", 10),
|
||||
exponent: new TokenType("**", {
|
||||
beforeExpr,
|
||||
binop: 11,
|
||||
@@ -149,61 +154,55 @@ export const types: { [name: string]: TokenType } = {
|
||||
}),
|
||||
};
|
||||
|
||||
export const keywords = {
|
||||
break: new KeywordTokenType("break"),
|
||||
case: new KeywordTokenType("case", { beforeExpr }),
|
||||
catch: new KeywordTokenType("catch"),
|
||||
continue: new KeywordTokenType("continue"),
|
||||
debugger: new KeywordTokenType("debugger"),
|
||||
default: new KeywordTokenType("default", { beforeExpr }),
|
||||
do: new KeywordTokenType("do", { isLoop, beforeExpr }),
|
||||
else: new KeywordTokenType("else", { beforeExpr }),
|
||||
finally: new KeywordTokenType("finally"),
|
||||
for: new KeywordTokenType("for", { isLoop }),
|
||||
function: new KeywordTokenType("function", { startsExpr }),
|
||||
if: new KeywordTokenType("if"),
|
||||
return: new KeywordTokenType("return", { beforeExpr }),
|
||||
switch: new KeywordTokenType("switch"),
|
||||
throw: new KeywordTokenType("throw", { beforeExpr, prefix, startsExpr }),
|
||||
try: new KeywordTokenType("try"),
|
||||
var: new KeywordTokenType("var"),
|
||||
let: new KeywordTokenType("let"),
|
||||
const: new KeywordTokenType("const"),
|
||||
while: new KeywordTokenType("while", { isLoop }),
|
||||
with: new KeywordTokenType("with"),
|
||||
new: new KeywordTokenType("new", { beforeExpr, startsExpr }),
|
||||
this: new KeywordTokenType("this", { startsExpr }),
|
||||
super: new KeywordTokenType("super", { startsExpr }),
|
||||
class: new KeywordTokenType("class", { startsExpr }),
|
||||
extends: new KeywordTokenType("extends", { beforeExpr }),
|
||||
export: new KeywordTokenType("export"),
|
||||
import: new KeywordTokenType("import", { startsExpr }),
|
||||
yield: new KeywordTokenType("yield", { beforeExpr, startsExpr }),
|
||||
null: new KeywordTokenType("null", { startsExpr }),
|
||||
true: new KeywordTokenType("true", { startsExpr }),
|
||||
false: new KeywordTokenType("false", { startsExpr }),
|
||||
in: new KeywordTokenType("in", { beforeExpr, binop: 7 }),
|
||||
instanceof: new KeywordTokenType("instanceof", { beforeExpr, binop: 7 }),
|
||||
typeof: new KeywordTokenType("typeof", { beforeExpr, prefix, startsExpr }),
|
||||
void: new KeywordTokenType("void", { beforeExpr, prefix, startsExpr }),
|
||||
delete: new KeywordTokenType("delete", { beforeExpr, prefix, startsExpr }),
|
||||
};
|
||||
function makeKeywordProps(
|
||||
name: string,
|
||||
conf: any,
|
||||
): PropertyDescriptor<TokenType> {
|
||||
return { value: KeywordTokenType(name, conf), enumerable: true };
|
||||
}
|
||||
|
||||
// $FlowIssue
|
||||
export const keywords = Object.create(null, {
|
||||
break: makeKeywordProps("break"),
|
||||
case: makeKeywordProps("case", { beforeExpr }),
|
||||
catch: makeKeywordProps("catch"),
|
||||
continue: makeKeywordProps("continue"),
|
||||
debugger: makeKeywordProps("debugger"),
|
||||
default: makeKeywordProps("default", { beforeExpr }),
|
||||
do: makeKeywordProps("do", { isLoop, beforeExpr }),
|
||||
else: makeKeywordProps("else", { beforeExpr }),
|
||||
finally: makeKeywordProps("finally"),
|
||||
for: makeKeywordProps("for", { isLoop }),
|
||||
function: makeKeywordProps("function", { startsExpr }),
|
||||
if: makeKeywordProps("if"),
|
||||
return: makeKeywordProps("return", { beforeExpr }),
|
||||
switch: makeKeywordProps("switch"),
|
||||
throw: makeKeywordProps("throw", { beforeExpr, prefix, startsExpr }),
|
||||
try: makeKeywordProps("try"),
|
||||
var: makeKeywordProps("var"),
|
||||
let: makeKeywordProps("let"),
|
||||
const: makeKeywordProps("const"),
|
||||
while: makeKeywordProps("while", { isLoop }),
|
||||
with: makeKeywordProps("with"),
|
||||
new: makeKeywordProps("new"),
|
||||
this: makeKeywordProps("this", { startsExpr }),
|
||||
super: makeKeywordProps("super", { startsExpr }),
|
||||
class: makeKeywordProps("class", { startsExpr }),
|
||||
extends: makeKeywordProps("extends", { beforeExpr }),
|
||||
export: makeKeywordProps("export"),
|
||||
import: makeKeywordProps("import", { startsExpr }),
|
||||
yield: makeKeywordProps("yield", { beforeExpr, startsExpr }),
|
||||
null: makeKeywordProps("null", { startsExpr }),
|
||||
true: makeKeywordProps("true", { startsExpr }),
|
||||
false: makeKeywordProps("false", { startsExpr }),
|
||||
in: makeKeywordProps("in", { beforeExpr, binop: 7 }),
|
||||
instanceof: makeKeywordProps("instanceof", { beforeExpr, binop: 7 }),
|
||||
typeof: makeKeywordProps("typeof", { beforeExpr, prefix, startsExpr }),
|
||||
void: makeKeywordProps("void", { beforeExpr, prefix, startsExpr }),
|
||||
delete: makeKeywordProps("delete", { beforeExpr, prefix, startsExpr }),
|
||||
});
|
||||
|
||||
// Map keyword names to token types.
|
||||
Object.keys(keywords).forEach(name => {
|
||||
types["_" + name] = keywords[name];
|
||||
});
|
||||
|
||||
// A type for the smartPipelines plugin.
|
||||
export type TopicContextState = {
|
||||
// When a topic binding has been currently established,
|
||||
// then this is 1. Otherwise, it is 0. This is forwards compatible
|
||||
// with a future plugin for multiple lexical topics.
|
||||
maxNumOfResolvableTopics: number,
|
||||
|
||||
// When a topic binding has been currently established, and if that binding
|
||||
// has been used as a topic reference `#`, then this is 0. Otherwise, it is
|
||||
// `null`. This is forwards compatible with a future plugin for multiple
|
||||
// lexical topics.
|
||||
maxTopicIndex: null | 0,
|
||||
};
|
||||
|
||||
@@ -1146,6 +1146,7 @@ export type TsType =
|
||||
| TsIndexedAccessType
|
||||
| TsMappedType
|
||||
| TsLiteralType
|
||||
| TsImportType
|
||||
// TODO: This probably shouldn't be included here.
|
||||
| TsTypePredicate;
|
||||
|
||||
@@ -1157,6 +1158,7 @@ export type TsKeywordTypeType =
|
||||
| "TSNumberKeyword"
|
||||
| "TSObjectKeyword"
|
||||
| "TSBooleanKeyword"
|
||||
| "TSBigIntKeyword"
|
||||
| "TSStringKeyword"
|
||||
| "TSSymbolKeyword"
|
||||
| "TSVoidKeyword"
|
||||
@@ -1200,7 +1202,7 @@ export type TsTypePredicate = TsTypeBase & {
|
||||
// `typeof` operator
|
||||
export type TsTypeQuery = TsTypeBase & {
|
||||
type: "TSTypeQuery",
|
||||
exprName: TsEntityName,
|
||||
exprName: TsEntityName | TsImportType,
|
||||
};
|
||||
|
||||
export type TsTypeLiteral = TsTypeBase & {
|
||||
@@ -1285,6 +1287,13 @@ export type TsLiteralType = TsTypeBase & {
|
||||
literal: NumericLiteral | StringLiteral | BooleanLiteral,
|
||||
};
|
||||
|
||||
export type TsImportType = TsTypeBase & {
|
||||
type: "TsImportType",
|
||||
argument: StringLiteral,
|
||||
qualifier?: TsEntityName,
|
||||
typeParameters?: TsTypeParameterInstantiation,
|
||||
};
|
||||
|
||||
// ================
|
||||
// TypeScript declarations
|
||||
// ================
|
||||
|
||||
@@ -4,28 +4,72 @@
|
||||
|
||||
import * as charCodes from "charcodes";
|
||||
|
||||
function makePredicate(words: string): (str: string) => boolean {
|
||||
const wordsArr = words.split(" ");
|
||||
return function(str) {
|
||||
return wordsArr.indexOf(str) >= 0;
|
||||
};
|
||||
}
|
||||
|
||||
// Reserved word lists for various dialects of the language
|
||||
|
||||
export const reservedWords = {
|
||||
"6": makePredicate("enum await"),
|
||||
strict: makePredicate(
|
||||
"implements interface let package private protected public static yield",
|
||||
),
|
||||
strictBind: makePredicate("eval arguments"),
|
||||
export const isES2015ReservedWord = (word: string): boolean => {
|
||||
return word === "enum" || word === "await";
|
||||
};
|
||||
|
||||
// And the keywords
|
||||
const reservedWordsStrict = new Set([
|
||||
"implements",
|
||||
"interface",
|
||||
"let",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"static",
|
||||
"yield",
|
||||
]);
|
||||
export function isStrictReservedWord(word: string): boolean {
|
||||
return reservedWordsStrict.has(word);
|
||||
}
|
||||
|
||||
export const isKeyword = makePredicate(
|
||||
"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this let const class extends export import yield super",
|
||||
);
|
||||
export function isStrictBindReservedWord(word: string): boolean {
|
||||
return word === "eval" || word === "arguments";
|
||||
}
|
||||
|
||||
const keywords = new Set([
|
||||
"break",
|
||||
"case",
|
||||
"catch",
|
||||
"continue",
|
||||
"debugger",
|
||||
"default",
|
||||
"do",
|
||||
"else",
|
||||
"finally",
|
||||
"for",
|
||||
"function",
|
||||
"if",
|
||||
"return",
|
||||
"switch",
|
||||
"throw",
|
||||
"try",
|
||||
"var",
|
||||
"while",
|
||||
"with",
|
||||
"null",
|
||||
"true",
|
||||
"false",
|
||||
"instanceof",
|
||||
"typeof",
|
||||
"void",
|
||||
"delete",
|
||||
"new",
|
||||
"in",
|
||||
"this",
|
||||
"let",
|
||||
"const",
|
||||
"class",
|
||||
"extends",
|
||||
"export",
|
||||
"import",
|
||||
"yield",
|
||||
"super",
|
||||
]);
|
||||
|
||||
export function isKeyword(word: string): boolean {
|
||||
return keywords.has(word);
|
||||
}
|
||||
|
||||
// ## Character categories
|
||||
|
||||
@@ -64,7 +108,7 @@ const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,1
|
||||
// rare.
|
||||
function isInAstralSet(code: number, set: $ReadOnlyArray<number>): boolean {
|
||||
let pos = 0x10000;
|
||||
for (let i = 0; i < set.length; i += 2) {
|
||||
for (let i = 0, length = set.length; i < length; i += 2) {
|
||||
pos += set[i];
|
||||
if (pos > code) return false;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as charCodes from "charcodes";
|
||||
|
||||
// Matches a whole line break (where CRLF is considered a single
|
||||
// line break). Used to count lines.
|
||||
export const lineBreak = /\r\n?|\n|\u2028|\u2029/;
|
||||
export const lineBreak = /\r\n?|[\n\u2028\u2029]/;
|
||||
export const lineBreakG = new RegExp(lineBreak.source, "g");
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-line-terminators
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Function declaration not allowed in this context (1:10)"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
while (1) foo: bar: function foo(){}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Function declaration not allowed in this context (1:20)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (1:18)"
|
||||
"throws": "The rest parameter must be the last parameter (1:18)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (3:13)"
|
||||
"throws": "The rest parameter must be the last parameter (3:13)"
|
||||
}
|
||||
|
||||
1
packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-rest/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[...a,] = [];
|
||||
1
packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[...a,];
|
||||
99
packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json
vendored
Normal file
99
packages/babel-parser/test/fixtures/es2015/array-rest-spread/comma-after-spread/output.json
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "ArrayExpression",
|
||||
"start": 0,
|
||||
"end": 7,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
}
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"type": "SpreadElement",
|
||||
"start": 1,
|
||||
"end": 5,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "Identifier",
|
||||
"start": 4,
|
||||
"end": 5,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 5
|
||||
},
|
||||
"identifierName": "a"
|
||||
},
|
||||
"name": "a"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "The rest element has to be the last element when destructuring (1:1)"
|
||||
"throws": "The rest element must be the last element (1:1)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "A trailing comma is not permitted after the rest element (1:8)"
|
||||
"throws": "A trailing comma is not permitted after the rest parameter (1:8)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (3:13)"
|
||||
"throws": "The rest parameter must be the last parameter (3:13)"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
(...a,) => {};
|
||||
4
packages/babel-parser/test/fixtures/es2015/class/extends-strict/input.js
vendored
Normal file
4
packages/babel-parser/test/fixtures/es2015/class/extends-strict/input.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
class C extends (function B() {
|
||||
with ({});
|
||||
return B;
|
||||
}()) {}
|
||||
3
packages/babel-parser/test/fixtures/es2015/class/extends-strict/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/es2015/class/extends-strict/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "'with' in strict mode (2:2)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (1:18)"
|
||||
"throws": "The rest parameter must be the last parameter (1:18)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (1:5)"
|
||||
"throws": "The rest parameter must be the last parameter (1:5)"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
[...a, ] = b
|
||||
@@ -1,132 +0,0 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"start": 0,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "AssignmentExpression",
|
||||
"start": 0,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
}
|
||||
},
|
||||
"operator": "=",
|
||||
"left": {
|
||||
"type": "ArrayPattern",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
}
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"type": "RestElement",
|
||||
"start": 1,
|
||||
"end": 5,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 5
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "Identifier",
|
||||
"start": 4,
|
||||
"end": 5,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 5
|
||||
},
|
||||
"identifierName": "a"
|
||||
},
|
||||
"name": "a"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"start": 11,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 11
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
},
|
||||
"identifierName": "b"
|
||||
},
|
||||
"name": "b"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"throws": "Unexpected token (1:10)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \"{\" (1:22)"
|
||||
"throws": "yield is a reserved word in strict mode (1:16)"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"throws": "Unexpected token, expected \"function\" (1:21)"
|
||||
"throws": "Unexpected token, expected \"=>\" (1:31)"
|
||||
}
|
||||
|
||||
1
packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
while (1) async function foo(){}
|
||||
3
packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Function declaration not allowed in this context (1:10)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "A trailing comma is not permitted after the rest element (1:11)"
|
||||
"throws": "A trailing comma is not permitted after the rest parameter (1:11)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "The rest element has to be the last element when destructuring (1:10)"
|
||||
"throws": "The rest property must be the last property (1:10)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "A trailing comma is not permitted after the rest element (1:16)"
|
||||
"throws": "A trailing comma is not permitted after the rest property (1:16)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Cannot have multiple rest elements when destructuring (1:13)"
|
||||
"throws": "The rest property must be the last property (1:13)"
|
||||
}
|
||||
|
||||
1
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
({...a,} = {});
|
||||
3
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-rest/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "A trailing comma is not permitted after the rest property (1:6)"
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
({...a,});
|
||||
103
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json
vendored
Normal file
103
packages/babel-parser/test/fixtures/es2018/object-rest-spread/comma-after-spread/output.json
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "ObjectExpression",
|
||||
"start": 1,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
}
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"type": "SpreadElement",
|
||||
"start": 2,
|
||||
"end": 6,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 6
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "Identifier",
|
||||
"start": 5,
|
||||
"end": 6,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 5
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 6
|
||||
},
|
||||
"identifierName": "a"
|
||||
},
|
||||
"name": "a"
|
||||
}
|
||||
}
|
||||
],
|
||||
"extra": {
|
||||
"parenthesized": true,
|
||||
"parenStart": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "The rest element has to be the last element when destructuring (1:2)"
|
||||
"throws": "The rest property must be the last property (1:2)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (1:5)"
|
||||
"throws": "The rest parameter must be the last parameter (1:5)"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Rest parameter must be last formal parameter (1:18)"
|
||||
"throws": "The rest parameter must be the last parameter (1:18)"
|
||||
}
|
||||
|
||||
1
packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-new/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-new/input.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
new import("foo");
|
||||
3
packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-new/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/experimental/dynamic-import/invalid-new/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Cannot use new with import(...) (1:4)"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import("foo",);
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Trailing comma is disallowed inside import(...) arguments (1:13)"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
async function f () {
|
||||
return x |> await #;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["pipelineOperator", { "proposal": "smart" }]]
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 46,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 46,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"start": 0,
|
||||
"end": 46,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 15,
|
||||
"end": 16,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 16
|
||||
},
|
||||
"identifierName": "f"
|
||||
},
|
||||
"name": "f"
|
||||
},
|
||||
"generator": false,
|
||||
"async": true,
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"start": 20,
|
||||
"end": 46,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"start": 24,
|
||||
"end": 44,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 22
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "BinaryExpression",
|
||||
"start": 31,
|
||||
"end": 43,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"start": 31,
|
||||
"end": 32,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
},
|
||||
"identifierName": "x"
|
||||
},
|
||||
"name": "x"
|
||||
},
|
||||
"operator": "|>",
|
||||
"right": {
|
||||
"type": "PipelineTopicExpression",
|
||||
"start": 36,
|
||||
"end": 43,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "AwaitExpression",
|
||||
"start": 36,
|
||||
"end": 43,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "PipelinePrimaryTopicReference",
|
||||
"start": 42,
|
||||
"end": 43,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 20
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
function * f () {
|
||||
return x |> (yield #);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["pipelineOperator", { "proposal": "smart" }]]
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 44,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 44,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
"start": 0,
|
||||
"end": 44,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 11,
|
||||
"end": 12,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 11
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 12
|
||||
},
|
||||
"identifierName": "f"
|
||||
},
|
||||
"name": "f"
|
||||
},
|
||||
"generator": true,
|
||||
"async": false,
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"start": 16,
|
||||
"end": 44,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 16
|
||||
},
|
||||
"end": {
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"start": 20,
|
||||
"end": 42,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 2
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 24
|
||||
}
|
||||
},
|
||||
"argument": {
|
||||
"type": "BinaryExpression",
|
||||
"start": 27,
|
||||
"end": 41,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"start": 27,
|
||||
"end": 28,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
},
|
||||
"identifierName": "x"
|
||||
},
|
||||
"name": "x"
|
||||
},
|
||||
"operator": "|>",
|
||||
"right": {
|
||||
"type": "PipelineTopicExpression",
|
||||
"start": 32,
|
||||
"end": 41,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 14
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 23
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "YieldExpression",
|
||||
"start": 33,
|
||||
"end": 40,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 22
|
||||
}
|
||||
},
|
||||
"delegate": false,
|
||||
"argument": {
|
||||
"type": "PipelinePrimaryTopicReference",
|
||||
"start": 39,
|
||||
"end": 40,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 21
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 22
|
||||
}
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"parenthesized": true,
|
||||
"parenStart": 32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@@ -45,12 +45,12 @@
|
||||
},
|
||||
"expression": {
|
||||
"type": "ArrowFunctionExpression",
|
||||
"start": 62,
|
||||
"start": 61,
|
||||
"end": 78,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 1
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
@@ -264,4 +264,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,12 +45,12 @@
|
||||
},
|
||||
"expression": {
|
||||
"type": "ArrowFunctionExpression",
|
||||
"start": 1,
|
||||
"start": 0,
|
||||
"end": 17,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
@@ -228,4 +228,4 @@
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,12 +59,12 @@
|
||||
},
|
||||
"object": {
|
||||
"type": "TSTypeAssertion",
|
||||
"start": 2,
|
||||
"start": 1,
|
||||
"end": 6,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 2
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
|
||||
@@ -80,12 +80,12 @@
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"type": "TSTypeAssertion",
|
||||
"start": 5,
|
||||
"start": 4,
|
||||
"end": 14,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 5
|
||||
"column": 4
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
|
||||
@@ -60,12 +60,12 @@
|
||||
"operator": "+=",
|
||||
"left": {
|
||||
"type": "TSTypeAssertion",
|
||||
"start": 2,
|
||||
"start": 1,
|
||||
"end": 11,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 2
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
|
||||
@@ -59,12 +59,12 @@
|
||||
},
|
||||
"left": {
|
||||
"type": "TSTypeAssertion",
|
||||
"start": 1,
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
|
||||
@@ -45,12 +45,12 @@
|
||||
},
|
||||
"expression": {
|
||||
"type": "TSTypeAssertion",
|
||||
"start": 1,
|
||||
"start": 0,
|
||||
"end": 10,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
|
||||
2
packages/babel-parser/test/fixtures/typescript/class/abstract-new-line/input.js
vendored
Normal file
2
packages/babel-parser/test/fixtures/typescript/class/abstract-new-line/input.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
abstract
|
||||
class B {}
|
||||
116
packages/babel-parser/test/fixtures/typescript/class/abstract-new-line/output.json
vendored
Normal file
116
packages/babel-parser/test/fixtures/typescript/class/abstract-new-line/output.json
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 19,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 19,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "Identifier",
|
||||
"start": 0,
|
||||
"end": 8,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 8
|
||||
},
|
||||
"identifierName": "abstract"
|
||||
},
|
||||
"name": "abstract"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start": 9,
|
||||
"end": 19,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 15,
|
||||
"end": 16,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 6
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 7
|
||||
},
|
||||
"identifierName": "B"
|
||||
},
|
||||
"name": "B"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start": 17,
|
||||
"end": 19,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"body": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
2
packages/babel-parser/test/fixtures/typescript/class/declare-new-line/input.js
vendored
Normal file
2
packages/babel-parser/test/fixtures/typescript/class/declare-new-line/input.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare
|
||||
class B {}
|
||||
116
packages/babel-parser/test/fixtures/typescript/class/declare-new-line/output.json
vendored
Normal file
116
packages/babel-parser/test/fixtures/typescript/class/declare-new-line/output.json
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start": 0,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start": 0,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ExpressionStatement",
|
||||
"start": 0,
|
||||
"end": 7,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
}
|
||||
},
|
||||
"expression": {
|
||||
"type": "Identifier",
|
||||
"start": 0,
|
||||
"end": 7,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 1,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 1,
|
||||
"column": 7
|
||||
},
|
||||
"identifierName": "declare"
|
||||
},
|
||||
"name": "declare"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start": 8,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start": 14,
|
||||
"end": 15,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 6
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 7
|
||||
},
|
||||
"identifierName": "B"
|
||||
},
|
||||
"name": "B"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start": 16,
|
||||
"end": 18,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 8
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 10
|
||||
}
|
||||
},
|
||||
"body": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@@ -94,7 +94,7 @@
|
||||
{
|
||||
"type": "Identifier",
|
||||
"start": 23,
|
||||
"end": 24,
|
||||
"end": 32,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
@@ -102,19 +102,19 @@
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 6
|
||||
"column": 14
|
||||
},
|
||||
"identifierName": "x"
|
||||
},
|
||||
"name": "x",
|
||||
"typeAnnotation": {
|
||||
"type": "TSTypeAnnotation",
|
||||
"start": 26,
|
||||
"start": 24,
|
||||
"end": 32,
|
||||
"loc": {
|
||||
"start": {
|
||||
"line": 2,
|
||||
"column": 8
|
||||
"column": 6
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
|
||||
2
packages/babel-parser/test/fixtures/typescript/class/extends-empty/input.js
vendored
Normal file
2
packages/babel-parser/test/fixtures/typescript/class/extends-empty/input.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
interface foo extends {
|
||||
}
|
||||
3
packages/babel-parser/test/fixtures/typescript/class/extends-empty/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/typescript/class/extends-empty/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "'extends' list cannot be empty. (1:22)"
|
||||
}
|
||||
2
packages/babel-parser/test/fixtures/typescript/class/extends-implements-empty/input.js
vendored
Normal file
2
packages/babel-parser/test/fixtures/typescript/class/extends-implements-empty/input.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
class Foo extends Bar implements {
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user