Refactor private name tokenizing (#13256)
* add benchmark * refactor: create tt.privateName token for private names * add backward compat privateName = hash + name to Babel 7 * perf: get private name SV from token value * chore: tweak benchmark file * chore: update test fixtures * convert tt.privateName to PrivateIdentifier * perf: avoid most isPrivateName call * Update packages/babel-parser/src/parser/expression.js Co-authored-by: Justin Ridgewell <justin@ridgewell.name> * perf: use inlinable codePointAtPos * make prettier happy Co-authored-by: Justin Ridgewell <justin@ridgewell.name>
This commit is contained in:
parent
278193b6f7
commit
a387973821
@ -173,6 +173,8 @@ function convertToken(token, source) {
|
||||
} else if (type === tt.bigint) {
|
||||
token.type = "Numeric";
|
||||
token.value = `${token.value}n`;
|
||||
} else if (type === tt.privateName) {
|
||||
token.type = "PrivateIdentifier";
|
||||
}
|
||||
if (typeof token.type !== "string") {
|
||||
// Acorn does not have rightAssociative
|
||||
|
||||
@ -320,6 +320,18 @@ describe("Babel and Espree", () => {
|
||||
expect(babylonAST.tokens[1].type).toEqual("Punctuator");
|
||||
});
|
||||
|
||||
if (process.env.BABEL_8_BREAKING) {
|
||||
it("hash (token)", () => {
|
||||
const code = "class A { #x }";
|
||||
const babylonAST = parseForESLint(code, {
|
||||
eslintVisitorKeys: true,
|
||||
eslintScopeManager: true,
|
||||
babelOptions: BABEL_OPTIONS,
|
||||
}).ast;
|
||||
expect(babylonAST.tokens[3].type).toEqual("PrivateIdentifier");
|
||||
expect(babylonAST.tokens[3].value).toEqual("x");
|
||||
});
|
||||
} else {
|
||||
// Espree doesn't support private fields yet
|
||||
it("hash (token)", () => {
|
||||
const code = "class A { #x }";
|
||||
@ -331,6 +343,7 @@ describe("Babel and Espree", () => {
|
||||
expect(babylonAST.tokens[3].type).toEqual("Punctuator");
|
||||
expect(babylonAST.tokens[3].value).toEqual("#");
|
||||
});
|
||||
}
|
||||
|
||||
it("parse to PropertyDeclaration when `classFeatures: true`", () => {
|
||||
const code = "class A { #x }";
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
import Benchmark from "benchmark";
|
||||
import baseline from "@babel-baseline/parser";
|
||||
import current from "../../lib/index.js";
|
||||
import { report } from "../util.mjs";
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
// All codepoints in [0x4e00, 0x9ffc] are valid identifier name per Unicode 13
|
||||
function createInput(length) {
|
||||
if (length > 0x9ffc - 0x4e00) {
|
||||
throw new Error(
|
||||
`Length greater than ${
|
||||
0x9ffc - 0x4e00
|
||||
} is not supported! Consider modify the \`createInput\`.`
|
||||
);
|
||||
}
|
||||
let source = "class C { ";
|
||||
for (let i = 0; i < length; i++) {
|
||||
source += "#" + String.fromCharCode(0x4e00 + i) + ";";
|
||||
}
|
||||
return source + " }";
|
||||
}
|
||||
function benchCases(name, implementation, options) {
|
||||
for (const length of [256, 512, 1024, 2048]) {
|
||||
const input = createInput(length);
|
||||
suite.add(`${name} ${length} length-1 private properties`, () => {
|
||||
implementation.parse(input, options);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
benchCases("baseline", baseline);
|
||||
benchCases("current", current);
|
||||
|
||||
suite.on("cycle", report).run();
|
||||
@ -0,0 +1,19 @@
|
||||
import Benchmark from "benchmark";
|
||||
import baseline from "@babel-baseline/parser";
|
||||
import current from "../../lib/index.js";
|
||||
import { report } from "../util.mjs";
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
|
||||
function benchCases(name, implementation, options) {
|
||||
for (const length of [256, 512, 1024, 2048]) {
|
||||
suite.add(`${name} ${length} empty statement`, () => {
|
||||
implementation.parse(";".repeat(length), options);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
benchCases("baseline", baseline);
|
||||
benchCases("current + attachComment: false", current, { attachComment: false });
|
||||
|
||||
suite.on("cycle", report).run();
|
||||
13
packages/babel-parser/benchmark/util.mjs
Normal file
13
packages/babel-parser/benchmark/util.mjs
Normal file
@ -0,0 +1,13 @@
|
||||
export function report(event) {
|
||||
const bench = event.target;
|
||||
const factor = bench.hz < 100 ? 100 : 1;
|
||||
const timeMs = bench.stats.mean * 1000;
|
||||
const time =
|
||||
timeMs < 10
|
||||
? `${Math.round(timeMs * 1000) / 1000}ms`
|
||||
: `${Math.round(timeMs)}ms`;
|
||||
const msg = `${bench.name}: ${
|
||||
Math.round(bench.hz * factor) / factor
|
||||
} ops/sec ±${Math.round(bench.stats.rme * 100) / 100}% (${time})`;
|
||||
console.log(msg);
|
||||
}
|
||||
@ -33,9 +33,11 @@
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel-baseline/parser": "npm:@babel/parser@^7.14.0",
|
||||
"@babel/code-frame": "workspace:*",
|
||||
"@babel/helper-fixtures": "workspace:*",
|
||||
"@babel/helper-validator-identifier": "workspace:*",
|
||||
"benchmark": "^2.1.4",
|
||||
"charcodes": "^0.2.0"
|
||||
},
|
||||
"bin": "./bin/babel-parser.js"
|
||||
|
||||
@ -29,7 +29,8 @@ import {
|
||||
isStrictBindReservedWord,
|
||||
isIdentifierStart,
|
||||
} from "../util/identifier";
|
||||
import type { Pos, Position } from "../util/location";
|
||||
import type { Pos } from "../util/location";
|
||||
import { Position } from "../util/location";
|
||||
import * as charCodes from "charcodes";
|
||||
import {
|
||||
BIND_OUTSIDE,
|
||||
@ -705,18 +706,19 @@ export default class ExpressionParser extends LValParser {
|
||||
const computed = this.eat(tt.bracketL);
|
||||
node.object = base;
|
||||
node.computed = computed;
|
||||
const privateName =
|
||||
!computed && this.match(tt.privateName) && this.state.value;
|
||||
const property = computed
|
||||
? this.parseExpression()
|
||||
: this.parseMaybePrivateName(true);
|
||||
: privateName
|
||||
? this.parsePrivateName()
|
||||
: this.parseIdentifier(true);
|
||||
|
||||
if (this.isPrivateName(property)) {
|
||||
if (privateName !== false) {
|
||||
if (node.object.type === "Super") {
|
||||
this.raise(startPos, Errors.SuperPrivateField);
|
||||
}
|
||||
this.classScope.usePrivateName(
|
||||
this.getPrivateNameSV(property),
|
||||
property.start,
|
||||
);
|
||||
this.classScope.usePrivateName(privateName, property.start);
|
||||
}
|
||||
node.property = property;
|
||||
|
||||
@ -1160,6 +1162,23 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
}
|
||||
|
||||
case tt.privateName: {
|
||||
// https://tc39.es/proposal-private-fields-in-in
|
||||
// RelationalExpression [In, Yield, Await]
|
||||
// [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]
|
||||
const start = this.state.start;
|
||||
const value = this.state.value;
|
||||
node = this.parsePrivateName();
|
||||
if (this.match(tt._in)) {
|
||||
this.expectPlugin("privateIn");
|
||||
this.classScope.usePrivateName(value, node.start);
|
||||
} else if (this.hasPlugin("privateIn")) {
|
||||
this.raise(this.state.start, Errors.PrivateInExpectedIn, value);
|
||||
} else {
|
||||
throw this.unexpected(start);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
case tt.hash: {
|
||||
if (this.state.inPipeline) {
|
||||
node = this.startNode();
|
||||
@ -1179,32 +1198,6 @@ export default class ExpressionParser extends LValParser {
|
||||
this.registerTopicReference();
|
||||
return this.finishNode(node, "PipelinePrimaryTopicReference");
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-private-fields-in-in
|
||||
// RelationalExpression [In, Yield, Await]
|
||||
// [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]
|
||||
const nextCh = this.input.codePointAt(this.state.end);
|
||||
if (isIdentifierStart(nextCh) || nextCh === charCodes.backslash) {
|
||||
const start = this.state.start;
|
||||
// $FlowIgnore It'll either parse a PrivateName or throw.
|
||||
node = (this.parseMaybePrivateName(true): N.PrivateName);
|
||||
if (this.match(tt._in)) {
|
||||
this.expectPlugin("privateIn");
|
||||
this.classScope.usePrivateName(
|
||||
this.getPrivateNameSV(node),
|
||||
node.start,
|
||||
);
|
||||
} else if (this.hasPlugin("privateIn")) {
|
||||
this.raise(
|
||||
this.state.start,
|
||||
Errors.PrivateInExpectedIn,
|
||||
this.getPrivateNameSV(node),
|
||||
);
|
||||
} else {
|
||||
throw this.unexpected(start);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
// fall through
|
||||
case tt.relational: {
|
||||
@ -1305,22 +1298,35 @@ export default class ExpressionParser extends LValParser {
|
||||
parseMaybePrivateName(
|
||||
isPrivateNameAllowed: boolean,
|
||||
): N.PrivateName | N.Identifier {
|
||||
const isPrivate = this.match(tt.hash);
|
||||
const isPrivate = this.match(tt.privateName);
|
||||
|
||||
if (isPrivate) {
|
||||
if (!isPrivateNameAllowed) {
|
||||
this.raise(this.state.pos, Errors.UnexpectedPrivateField);
|
||||
this.raise(this.state.start + 1, Errors.UnexpectedPrivateField);
|
||||
}
|
||||
const node = this.startNode();
|
||||
this.next();
|
||||
this.assertNoSpace("Unexpected space between # and identifier");
|
||||
node.id = this.parseIdentifier(true);
|
||||
return this.finishNode(node, "PrivateName");
|
||||
return this.parsePrivateName();
|
||||
} else {
|
||||
return this.parseIdentifier(true);
|
||||
}
|
||||
}
|
||||
|
||||
parsePrivateName(): N.PrivateName {
|
||||
const node = this.startNode();
|
||||
const id = this.startNodeAt(
|
||||
this.state.start + 1,
|
||||
// The position is hardcoded because we merge `#` and name into a single
|
||||
// tt.privateName token
|
||||
new Position(
|
||||
this.state.curLine,
|
||||
this.state.start + 1 - this.state.lineStart,
|
||||
),
|
||||
);
|
||||
const name = this.state.value;
|
||||
this.next(); // eat #name;
|
||||
node.id = this.createIdentifier(id, name);
|
||||
return this.finishNode(node, "PrivateName");
|
||||
}
|
||||
|
||||
parseFunctionOrFunctionSent(): N.FunctionExpression | N.MetaProperty {
|
||||
const node = this.startNode();
|
||||
|
||||
@ -1976,15 +1982,16 @@ export default class ExpressionParser extends LValParser {
|
||||
const oldInPropertyName = this.state.inPropertyName;
|
||||
this.state.inPropertyName = true;
|
||||
// We check if it's valid for it to be a private name when we push it.
|
||||
const type = this.state.type;
|
||||
(prop: $FlowFixMe).key =
|
||||
this.match(tt.num) ||
|
||||
this.match(tt.string) ||
|
||||
this.match(tt.bigint) ||
|
||||
this.match(tt.decimal)
|
||||
type === tt.num ||
|
||||
type === tt.string ||
|
||||
type === tt.bigint ||
|
||||
type === tt.decimal
|
||||
? this.parseExprAtom()
|
||||
: this.parseMaybePrivateName(isPrivateNameAllowed);
|
||||
|
||||
if (!this.isPrivateName(prop.key)) {
|
||||
if (type !== tt.privateName) {
|
||||
// ClassPrivateProperty is never computed, so we don't assign in that case.
|
||||
prop.computed = false;
|
||||
}
|
||||
|
||||
@ -36,6 +36,8 @@ import {
|
||||
newParameterDeclarationScope,
|
||||
} from "../util/expression-scope";
|
||||
import type { SourceType } from "../options";
|
||||
import { Token } from "../tokenizer";
|
||||
import { Position } from "../util/location";
|
||||
|
||||
const loopLabel = { kind: "loop" },
|
||||
switchLabel = { kind: "switch" };
|
||||
@ -47,6 +49,48 @@ const FUNC_NO_FLAGS = 0b000,
|
||||
|
||||
const loneSurrogate = /[\uD800-\uDFFF]/u;
|
||||
|
||||
/**
|
||||
* Convert tt.privateName to tt.hash + tt.name for backward Babel 7 compat.
|
||||
* For performance reasons this routine mutates `tokens`, it is okay
|
||||
* here since we execute `parseTopLevel` once for every file.
|
||||
* @param {*} tokens
|
||||
* @returns
|
||||
*/
|
||||
function babel7CompatTokens(tokens) {
|
||||
if (!process.env.BABEL_8_BREAKING) {
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
const token = tokens[i];
|
||||
if (token.type === tt.privateName) {
|
||||
const { loc, start, value, end } = token;
|
||||
const hashEndPos = start + 1;
|
||||
const hashEndLoc = new Position(loc.start.line, loc.start.column + 1);
|
||||
tokens.splice(
|
||||
i,
|
||||
1,
|
||||
// $FlowIgnore: hacky way to create token
|
||||
new Token({
|
||||
type: tt.hash,
|
||||
value: "#",
|
||||
start: start,
|
||||
end: hashEndPos,
|
||||
startLoc: loc.start,
|
||||
endLoc: hashEndLoc,
|
||||
}),
|
||||
// $FlowIgnore: hacky way to create token
|
||||
new Token({
|
||||
type: tt.name,
|
||||
value: value,
|
||||
start: hashEndPos,
|
||||
end: end,
|
||||
startLoc: hashEndLoc,
|
||||
endLoc: loc.end,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
export default class StatementParser extends ExpressionParser {
|
||||
// ### Statement parsing
|
||||
|
||||
@ -59,7 +103,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
file.program = this.parseProgram(program);
|
||||
file.comments = this.state.comments;
|
||||
|
||||
if (this.options.tokens) file.tokens = this.tokens;
|
||||
if (this.options.tokens) file.tokens = babel7CompatTokens(this.tokens);
|
||||
|
||||
return this.finishNode(file, "File");
|
||||
}
|
||||
@ -1366,9 +1410,10 @@ export default class StatementParser extends ExpressionParser {
|
||||
if (this.eat(tt.star)) {
|
||||
// a generator
|
||||
method.kind = "method";
|
||||
const isPrivateName = this.match(tt.privateName);
|
||||
this.parseClassElementName(method);
|
||||
|
||||
if (this.isPrivateName(method.key)) {
|
||||
if (isPrivateName) {
|
||||
// Private generator method
|
||||
this.pushClassPrivateMethod(classBody, privateMethod, true, false);
|
||||
return;
|
||||
@ -1391,8 +1436,8 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
const containsEsc = this.state.containsEsc;
|
||||
const isPrivate = this.match(tt.privateName);
|
||||
const key = this.parseClassElementName(member);
|
||||
const isPrivate = this.isPrivateName(key);
|
||||
// Check the key is not a computed expression or string literal.
|
||||
const isSimple = key.type === "Identifier";
|
||||
const maybeQuestionTokenStart = this.state.start;
|
||||
@ -1453,10 +1498,11 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
method.kind = "method";
|
||||
// The so-called parsed name would have been "async": get the real name.
|
||||
const isPrivate = this.match(tt.privateName);
|
||||
this.parseClassElementName(method);
|
||||
this.parsePostMemberNameModifiers(publicMember);
|
||||
|
||||
if (this.isPrivateName(method.key)) {
|
||||
if (isPrivate) {
|
||||
// private async method
|
||||
this.pushClassPrivateMethod(
|
||||
classBody,
|
||||
@ -1488,9 +1534,10 @@ export default class StatementParser extends ExpressionParser {
|
||||
// a getter or setter
|
||||
method.kind = key.name;
|
||||
// The so-called parsed name would have been "get/set": get the real name.
|
||||
const isPrivate = this.match(tt.privateName);
|
||||
this.parseClassElementName(publicMethod);
|
||||
|
||||
if (this.isPrivateName(method.key)) {
|
||||
if (isPrivate) {
|
||||
// private getter/setter
|
||||
this.pushClassPrivateMethod(classBody, privateMethod, false, false);
|
||||
} else {
|
||||
@ -1522,25 +1569,20 @@ export default class StatementParser extends ExpressionParser {
|
||||
|
||||
// https://tc39.es/proposal-class-fields/#prod-ClassElementName
|
||||
parseClassElementName(member: N.ClassMember): N.Expression | N.Identifier {
|
||||
const key = this.parsePropertyName(member, /* isPrivateNameAllowed */ true);
|
||||
|
||||
const { type, value, start } = this.state;
|
||||
if (
|
||||
!member.computed &&
|
||||
(type === tt.name || type === tt.string) &&
|
||||
member.static &&
|
||||
((key: $FlowSubtype<N.Identifier>).name === "prototype" ||
|
||||
(key: $FlowSubtype<N.StringLiteral>).value === "prototype")
|
||||
value === "prototype"
|
||||
) {
|
||||
this.raise(key.start, Errors.StaticPrototype);
|
||||
this.raise(start, Errors.StaticPrototype);
|
||||
}
|
||||
|
||||
if (
|
||||
this.isPrivateName(key) &&
|
||||
this.getPrivateNameSV(key) === "constructor"
|
||||
) {
|
||||
this.raise(key.start, Errors.ConstructorClassPrivateField);
|
||||
if (type === tt.privateName && value === "constructor") {
|
||||
this.raise(start, Errors.ConstructorClassPrivateField);
|
||||
}
|
||||
|
||||
return key;
|
||||
return this.parsePropertyName(member, /* isPrivateNameAllowed */ true);
|
||||
}
|
||||
|
||||
parseClassStaticBlock(
|
||||
|
||||
@ -210,7 +210,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.match(tt.braceL) ||
|
||||
this.match(tt.star) ||
|
||||
this.match(tt.ellipsis) ||
|
||||
this.match(tt.hash) ||
|
||||
this.match(tt.privateName) ||
|
||||
this.isLiteralPropertyName()) &&
|
||||
!this.hasPrecedingLineBreak()
|
||||
);
|
||||
|
||||
@ -205,6 +205,21 @@ export default class Tokenizer extends ParserErrors {
|
||||
return this.input.charCodeAt(this.nextTokenStart());
|
||||
}
|
||||
|
||||
codePointAtPos(pos: number): number {
|
||||
// The implementation is based on
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:v8/src/builtins/builtins-string-gen.cc;l=1455;drc=221e331b49dfefadbc6fa40b0c68e6f97606d0b3;bpv=0;bpt=1
|
||||
// We reimplement `codePointAt` because `codePointAt` is a V8 builtin which is not inlined by TurboFan (as of M91)
|
||||
// since `input` is mostly ASCII, an inlined `charCodeAt` wins here
|
||||
let cp = this.input.charCodeAt(pos);
|
||||
if ((cp & 0xfc00) === 0xd800 && ++pos < this.input.length) {
|
||||
const trail = this.input.charCodeAt(pos);
|
||||
if ((trail & 0xfc00) === 0xdc00) {
|
||||
cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
// Toggle strict mode. Re-reads the next number or string to please
|
||||
// pedantic tests (`"use strict"; 010;` should fail).
|
||||
|
||||
@ -244,7 +259,7 @@ export default class Tokenizer extends ParserErrors {
|
||||
if (override) {
|
||||
override(this);
|
||||
} else {
|
||||
this.getTokenFromCode(this.input.codePointAt(this.state.pos));
|
||||
this.getTokenFromCode(this.codePointAtPos(this.state.pos));
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,7 +422,7 @@ export default class Tokenizer extends ParserErrors {
|
||||
}
|
||||
|
||||
const nextPos = this.state.pos + 1;
|
||||
const next = this.input.charCodeAt(nextPos);
|
||||
const next = this.codePointAtPos(nextPos);
|
||||
if (next >= charCodes.digit0 && next <= charCodes.digit9) {
|
||||
throw this.raise(this.state.pos, Errors.UnexpectedDigitAfterHash);
|
||||
}
|
||||
@ -438,6 +453,9 @@ export default class Tokenizer extends ParserErrors {
|
||||
this.finishToken(tt.bracketHashL);
|
||||
}
|
||||
this.state.pos += 2;
|
||||
} else if (isIdentifierStart(next) || next === charCodes.backslash) {
|
||||
++this.state.pos;
|
||||
this.finishToken(tt.privateName, this.readWord1());
|
||||
} else {
|
||||
this.finishOp(tt.hash, 1);
|
||||
}
|
||||
@ -952,7 +970,7 @@ export default class Tokenizer extends ParserErrors {
|
||||
|
||||
while (this.state.pos < this.length) {
|
||||
const char = this.input[this.state.pos];
|
||||
const charCode = this.input.codePointAt(this.state.pos);
|
||||
const charCode = this.codePointAtPos(this.state.pos);
|
||||
|
||||
if (VALID_REGEX_FLAGS.has(char)) {
|
||||
if (mods.indexOf(char) > -1) {
|
||||
@ -1090,7 +1108,7 @@ export default class Tokenizer extends ParserErrors {
|
||||
throw this.raise(start, Errors.InvalidDecimal);
|
||||
}
|
||||
|
||||
if (isIdentifierStart(this.input.codePointAt(this.state.pos))) {
|
||||
if (isIdentifierStart(this.codePointAtPos(this.state.pos))) {
|
||||
throw this.raise(this.state.pos, Errors.NumberIdentifier);
|
||||
}
|
||||
|
||||
@ -1176,7 +1194,7 @@ export default class Tokenizer extends ParserErrors {
|
||||
isDecimal = true;
|
||||
}
|
||||
|
||||
if (isIdentifierStart(this.input.codePointAt(this.state.pos))) {
|
||||
if (isIdentifierStart(this.codePointAtPos(this.state.pos))) {
|
||||
throw this.raise(this.state.pos, Errors.NumberIdentifier);
|
||||
}
|
||||
|
||||
@ -1447,7 +1465,7 @@ export default class Tokenizer extends ParserErrors {
|
||||
let chunkStart = this.state.pos;
|
||||
|
||||
while (this.state.pos < this.length) {
|
||||
const ch = this.input.codePointAt(this.state.pos);
|
||||
const ch = this.codePointAtPos(this.state.pos);
|
||||
if (isIdentifierChar(ch)) {
|
||||
this.state.pos += ch <= 0xffff ? 1 : 2;
|
||||
} else if (this.state.isIterator && ch === charCodes.atSign) {
|
||||
|
||||
@ -90,6 +90,7 @@ export const types: { [name: string]: TokenType } = {
|
||||
regexp: new TokenType("regexp", { startsExpr }),
|
||||
string: new TokenType("string", { startsExpr }),
|
||||
name: new TokenType("name", { startsExpr }),
|
||||
privateName: new TokenType("#name", { startsExpr }),
|
||||
eof: new TokenType("eof"),
|
||||
|
||||
// Punctuation token types.
|
||||
|
||||
3
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true-babel-7/input.js
vendored
Normal file
3
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true-babel-7/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
#p
|
||||
}
|
||||
4
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true-babel-7/options.json
vendored
Normal file
4
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true-babel-7/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"tokens": true,
|
||||
"BABEL_8_BREAKING": false
|
||||
}
|
||||
151
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true-babel-7/output.json
vendored
Normal file
151
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true-babel-7/output.json
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"C"},
|
||||
"name": "C"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start":8,"end":16,"loc":{"start":{"line":1,"column":8},"end":{"line":3,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}},
|
||||
"static": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"p"},
|
||||
"name": "p"
|
||||
}
|
||||
},
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
},
|
||||
"tokens": [
|
||||
{
|
||||
"type": {
|
||||
"label": "class",
|
||||
"keyword": "class",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"value": "class",
|
||||
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "name",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"value": "C",
|
||||
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "{",
|
||||
"beforeExpr": true,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"start":8,"end":9,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":9}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "#",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null,
|
||||
"updateContext": null
|
||||
},
|
||||
"value": "#",
|
||||
"start":12,"end":13,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":3}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "name",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"value": "p",
|
||||
"start":13,"end":14,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "}",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": false,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"start":15,"end":16,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":1}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "eof",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": false,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null,
|
||||
"updateContext": null
|
||||
},
|
||||
"start":16,"end":16,"loc":{"start":{"line":3,"column":1},"end":{"line":3,"column":1}}
|
||||
}
|
||||
]
|
||||
}
|
||||
3
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true/input.js
vendored
Normal file
3
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
#p
|
||||
}
|
||||
4
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true/options.json
vendored
Normal file
4
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"tokens": true,
|
||||
"BABEL_8_BREAKING": true
|
||||
}
|
||||
136
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true/output.json
vendored
Normal file
136
packages/babel-parser/test/fixtures/core/opts/private-name-tokens-true/output.json
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"C"},
|
||||
"name": "C"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start":8,"end":16,"loc":{"start":{"line":1,"column":8},"end":{"line":3,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}},
|
||||
"static": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"p"},
|
||||
"name": "p"
|
||||
}
|
||||
},
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
},
|
||||
"tokens": [
|
||||
{
|
||||
"type": {
|
||||
"label": "class",
|
||||
"keyword": "class",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"value": "class",
|
||||
"start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "name",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"value": "C",
|
||||
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "{",
|
||||
"beforeExpr": true,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"start":8,"end":9,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":9}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "#name",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": true,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null,
|
||||
"updateContext": null
|
||||
},
|
||||
"value": "p",
|
||||
"start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "}",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": false,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null
|
||||
},
|
||||
"start":15,"end":16,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":1}}
|
||||
},
|
||||
{
|
||||
"type": {
|
||||
"label": "eof",
|
||||
"beforeExpr": false,
|
||||
"startsExpr": false,
|
||||
"rightAssociative": false,
|
||||
"isLoop": false,
|
||||
"isAssign": false,
|
||||
"prefix": false,
|
||||
"postfix": false,
|
||||
"binop": null,
|
||||
"updateContext": null
|
||||
},
|
||||
"start":16,"end":16,"loc":{"start":{"line":3,"column":1},"end":{"line":3,"column":1}}
|
||||
}
|
||||
]
|
||||
}
|
||||
3
packages/babel-parser/test/fixtures/es2022/class-private-methods/failure-spaces/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/es2022/class-private-methods/failure-spaces/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token (2:2)"
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":60,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
||||
"errors": [
|
||||
"SyntaxError: Unexpected space between # and identifier (2:3)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":60,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":60,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":6,"end":12,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":12},"identifierName":"Spaces"},
|
||||
"name": "Spaces"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start":13,"end":60,"loc":{"start":{"line":1,"column":13},"end":{"line":5,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateMethod",
|
||||
"start":17,"end":58,"loc":{"start":{"line":2,"column":2},"end":{"line":4,"column":3}},
|
||||
"static": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":17,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":16}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":20,"end":31,"loc":{"start":{"line":2,"column":5},"end":{"line":2,"column":16},"identifierName":"wrongSpaces"},
|
||||
"name": "wrongSpaces"
|
||||
}
|
||||
},
|
||||
"kind": "method",
|
||||
"id": null,
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"start":34,"end":58,"loc":{"start":{"line":2,"column":19},"end":{"line":4,"column":3}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ReturnStatement",
|
||||
"start":40,"end":54,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":18}},
|
||||
"argument": {
|
||||
"type": "CallExpression",
|
||||
"start":47,"end":53,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":17}},
|
||||
"callee": {
|
||||
"type": "Identifier",
|
||||
"start":47,"end":51,"loc":{"start":{"line":3,"column":11},"end":{"line":3,"column":15},"identifierName":"fail"},
|
||||
"name": "fail"
|
||||
},
|
||||
"arguments": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"throws": "Unexpected token (3:3)",
|
||||
"throws": "Unexpected token (3:2)",
|
||||
"plugins": []
|
||||
}
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token (2:2)"
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"errors": [
|
||||
"SyntaxError: Unexpected space between # and identifier (2:3)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":6,"end":12,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":12},"identifierName":"Spaces"},
|
||||
"name": "Spaces"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start":13,"end":34,"loc":{"start":{"line":1,"column":13},"end":{"line":3,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":17,"end":32,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}},
|
||||
"static": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":17,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":16}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":20,"end":31,"loc":{"start":{"line":2,"column":5},"end":{"line":2,"column":16},"identifierName":"wrongSpaces"},
|
||||
"name": "wrongSpaces"
|
||||
}
|
||||
},
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"throws": "Unexpected token (2:3)",
|
||||
"throws": "Unexpected token (2:2)",
|
||||
"plugins": []
|
||||
}
|
||||
|
||||
20
yarn.lock
20
yarn.lock
@ -5,6 +5,15 @@ __metadata:
|
||||
version: 4
|
||||
cacheKey: 7
|
||||
|
||||
"@babel-baseline/parser@npm:@babel/parser@^7.14.0, @babel/parser@npm:^7.0.0, @babel/parser@npm:^7.12.13, @babel/parser@npm:^7.12.7, @babel/parser@npm:^7.14.0":
|
||||
version: 7.14.0
|
||||
resolution: "@babel/parser@npm:7.14.0"
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
checksum: ef6165f3038b9f8761a02768ab14034f4935baf2e050a2924aa093f54e3164732bce7fee81b3c8ff3be03048091e4ea208a72b23a3715debf7fd06b79495c9e9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel-internal/runtime-integration-rollup@workspace:test/runtime-integration/rollup":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@babel-internal/runtime-integration-rollup@workspace:test/runtime-integration/rollup"
|
||||
@ -935,22 +944,15 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.12.13, @babel/parser@npm:^7.12.7, @babel/parser@npm:^7.14.0":
|
||||
version: 7.14.0
|
||||
resolution: "@babel/parser@npm:7.14.0"
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
checksum: ef6165f3038b9f8761a02768ab14034f4935baf2e050a2924aa093f54e3164732bce7fee81b3c8ff3be03048091e4ea208a72b23a3715debf7fd06b79495c9e9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/parser@workspace:*, @babel/parser@workspace:^7.12.13, @babel/parser@workspace:^7.14.0, @babel/parser@workspace:packages/babel-parser":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@babel/parser@workspace:packages/babel-parser"
|
||||
dependencies:
|
||||
"@babel-baseline/parser": "npm:@babel/parser@^7.14.0"
|
||||
"@babel/code-frame": "workspace:*"
|
||||
"@babel/helper-fixtures": "workspace:*"
|
||||
"@babel/helper-validator-identifier": "workspace:*"
|
||||
benchmark: ^2.1.4
|
||||
charcodes: ^0.2.0
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user