Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Use a WeakMap to associate indexes to Positions until we decide wheth…
…er to make index an actual property in the next minor release.

Reviewed by @tolmasky.
  • Loading branch information
tolmasky committed Jan 17, 2022
commit 22d311261203b76e5b6d977219cb75094dfa55ee
7 changes: 4 additions & 3 deletions packages/babel-parser/src/parser/error.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
/* eslint sort-keys: "error" */
import { type Position } from "../util/location";
import { type Position, indexes } from "../util/location";
import CommentsParser from "./comments";
import { type ErrorCode, ErrorCodes } from "./error-codes";
import { type Node } from "../types";
Expand Down Expand Up @@ -111,7 +111,8 @@ export default class ParserError extends CommentsParser {
{ code, template }: ErrorTemplate,
...params: any
): Error | empty {
const pos = loc.index;
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
const pos: number = indexes.get(loc);
const message =
template.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
Expand All @@ -138,7 +139,7 @@ export default class ParserError extends CommentsParser {
errorTemplate: string,
...params: any
): Error | empty {
const pos = loc.index;
const pos = indexes.get(loc);
const message =
errorTemplate.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
Expand Down
17 changes: 12 additions & 5 deletions packages/babel-parser/src/parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ import {
isIdentifierStart,
canBeReservedWord,
} from "../util/identifier";
import { Position, createPositionWithColumnOffset } from "../util/location";
import {
indexes,
Position,
createPositionWithColumnOffset,
} from "../util/location";
import * as charCodes from "charcodes";
import {
BIND_OUTSIDE,
Expand Down Expand Up @@ -313,13 +317,15 @@ export default class ExpressionParser extends LValParser {

if (
refExpressionErrors.doubleProtoLoc != null &&
refExpressionErrors.doubleProtoLoc.index >= startPos
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
indexes.get(refExpressionErrors.doubleProtoLoc) >= startPos
) {
refExpressionErrors.doubleProtoLoc = null; // reset because double __proto__ is valid in assignment expression
}
if (
refExpressionErrors.shorthandAssignLoc != null &&
refExpressionErrors.shorthandAssignLoc.index >= startPos
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
indexes.get(refExpressionErrors.shorthandAssignLoc) >= startPos
) {
refExpressionErrors.shorthandAssignLoc = null; // reset because shorthand default was used correctly
}
Expand Down Expand Up @@ -912,7 +918,7 @@ export default class ExpressionParser extends LValParser {
return (
base.type === "Identifier" &&
base.name === "async" &&
this.state.lastTokEndLoc.index === base.end &&
indexes.get(this.state.lastTokEndLoc) === base.end &&
!this.canInsertSemicolon() &&
// check there are no escape sequences, such as \u{61}sync
base.end - base.start === 5 &&
Expand Down Expand Up @@ -1764,7 +1770,8 @@ export default class ExpressionParser extends LValParser {
this.takeSurroundingComments(
val,
startPos,
this.state.lastTokEndLoc.index,
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
indexes.get(this.state.lastTokEndLoc),
);

return val;
Expand Down
11 changes: 6 additions & 5 deletions packages/babel-parser/src/parser/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import type Parser from "./index";
import UtilParser from "./util";
import { SourceLocation, type Position } from "../util/location";
import { indexes, type Position, SourceLocation } from "../util/location";
import type { Comment, Node as NodeType, NodeBase } from "../types";

// Start an AST node, attaching a start offset.
Expand Down Expand Up @@ -126,9 +126,9 @@ export class NodeUtils extends UtilParser {
);
}
node.type = type;
node.end = endLoc.index;
node.end = indexes.get(endLoc);
node.loc.end = endLoc;
if (this.options.ranges) node.range[1] = endLoc.index;
if (this.options.ranges) node.range[1] = node.end;
if (this.options.attachComment) this.processComment(node);
return node;
}
Expand All @@ -143,9 +143,10 @@ export class NodeUtils extends UtilParser {
node: NodeBase,
endLoc?: Position = this.state.lastTokEndLoc,
): void {
node.end = endLoc.index;
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
node.end = indexes.get(endLoc);
node.loc.end = endLoc;
if (this.options.ranges) node.range[1] = endLoc.index;
if (this.options.ranges) node.range[1] = node.end;
}

/**
Expand Down
7 changes: 4 additions & 3 deletions packages/babel-parser/src/parser/util.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow

import { type Position } from "../util/location";
import { indexes, type Position } from "../util/location";
import {
tokenIsLiteralPropertyName,
tokenLabelName,
Expand Down Expand Up @@ -120,7 +120,7 @@ export default class UtilParser extends Tokenizer {

hasPrecedingLineBreak(): boolean {
return lineBreak.test(
this.input.slice(this.state.lastTokEndLoc.index, this.state.start),
this.input.slice(indexes.get(this.state.lastTokEndLoc), this.state.start),
);
}

Expand Down Expand Up @@ -152,7 +152,8 @@ export default class UtilParser extends Tokenizer {

// Throws if the current token and the prev one are separated by a space.
assertNoSpace(message: string = "Unexpected space."): void {
if (this.state.start > this.state.lastTokEndLoc.index) {
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
if (this.state.start > indexes.get(this.state.lastTokEndLoc)) {
/* eslint-disable @babel/development-internal/dry-error-messages */
this.raise(
{
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-parser/src/plugins/flow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
tokenIsFlowInterfaceOrTypeOrOpaque,
} from "../../tokenizer/types";
import * as N from "../../types";
import { Position } from "../../util/location";
import { indexes, Position } from "../../util/location";
import { types as tc } from "../../tokenizer/context";
import * as charCodes from "charcodes";
import { isIteratorStart } from "../../util/identifier";
Expand Down Expand Up @@ -269,7 +269,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.next(); // eat `%`
this.expectContextual(tt._checks);
// Force '%' and 'checks' to be adjacent
if (this.state.lastTokStart > moduloLoc.index + 1) {
if (this.state.lastTokStart > indexes.get(moduloLoc) + 1) {
this.raise(FlowErrors.UnexpectedSpaceBetweenModuloChecks, {
at: moduloLoc,
});
Expand Down
5 changes: 3 additions & 2 deletions packages/babel-parser/src/plugins/jsx/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { TokContext, types as tc } from "../../tokenizer/context";
import * as N from "../../types";
import { isIdentifierChar, isIdentifierStart } from "../../util/identifier";
import type { Position } from "../../util/location";
import { indexes, type Position } from "../../util/location";
import { isNewLine } from "../../util/whitespace";
import { Errors, makeErrorTemplates, ErrorCodes } from "../../parser/error";

Expand Down Expand Up @@ -327,7 +327,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>

jsxParseEmptyExpression(): N.JSXEmptyExpression {
const node = this.startNodeAt(
this.state.lastTokEndLoc.index,
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
indexes.get(this.state.lastTokEndLoc),
this.state.lastTokEndLoc,
);
return this.finishNodeAt(node, "JSXEmptyExpression", this.state.startLoc);
Expand Down
17 changes: 12 additions & 5 deletions packages/babel-parser/src/tokenizer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
/*:: declare var invariant; */

import type { Options } from "../options";
import { Position, createPositionWithColumnOffset } from "../util/location";
import {
indexes,
Position,
createPositionWithColumnOffset,
} from "../util/location";
import * as N from "../types";
import * as charCodes from "charcodes";
import { isIdentifierStart, isIdentifierChar } from "../util/identifier";
Expand Down Expand Up @@ -1249,7 +1253,7 @@ export default class Tokenizer extends ParserErrors {

if (isBigInt) {
const str = this.input
.slice(startLoc.index, this.state.pos)
.slice(indexes.get(startLoc), this.state.pos)
.replace(/[_n]/g, "");
this.finishToken(tt.bigint, str);
return;
Expand Down Expand Up @@ -1494,10 +1498,12 @@ export default class Tokenizer extends ParserErrors {
}

recordStrictModeErrors(message: ErrorTemplate, loc: Position) {
if (this.state.strict && !this.state.strictErrors.has(loc.index)) {
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
const index: number = indexes.get(loc);
if (this.state.strict && !this.state.strictErrors.has(index)) {
this.raise(message, { at: loc });
} else {
this.state.strictErrors.set(loc.index, { loc, message });
this.state.strictErrors.set(index, { loc, message });
}
}

Expand Down Expand Up @@ -1607,7 +1613,8 @@ export default class Tokenizer extends ParserErrors {
if (throwOnInvalid) {
this.raise(Errors.InvalidEscapeSequence, { at: codeLoc });
} else {
this.state.pos = codeLoc.index - 1;
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
this.state.pos = indexes.get(codeLoc) - 1;
}
}
return n;
Expand Down
8 changes: 5 additions & 3 deletions packages/babel-parser/src/util/expression-scope.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow

import type { ErrorData, ErrorTemplate, raiseFunction } from "../parser/error";
import { Position } from "./location";
import { indexes, Position } from "./location";

/*:: declare var invariant; */
/**
Expand Down Expand Up @@ -80,10 +80,12 @@ class ArrowHeadParsingScope extends ExpressionScope {
super(type);
}
recordDeclarationError(message: ErrorTemplate, loc: Position) {
this.errors.set(loc.index, { message, loc });
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
this.errors.set(indexes.get(loc), { message, loc });
}
clearDeclarationError(loc: Position) {
this.errors.delete(loc.index);
// $FlowIgnore[incompatible-type] We know this exists, so it can't be undefined.
this.errors.delete(indexes.get(loc));
}
iterateErrors(iterator: (data: ErrorData) => void) {
this.errors.forEach(iterator);
Expand Down
13 changes: 10 additions & 3 deletions packages/babel-parser/src/util/location.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export class Position {
this.column = col;

// this.index = index;
Object.defineProperty(this, "index", { enumerable: false, value: index });
// Object.defineProperty(this, "index", { enumerable: false, value: index });
indexes.set(this, index);
}
}

Expand All @@ -34,6 +35,8 @@ export class SourceLocation {
}
}

export const indexes: WeakMap<Position, number> = new WeakMap();

/**
* creates a new position with a non-zero column offset from the given position.
* This function should be only be used when we create AST node out of the token
Expand All @@ -49,6 +52,10 @@ export function createPositionWithColumnOffset(
position: Position,
columnOffset: number,
) {
const { line, column, index } = position;
return new Position(line, column + columnOffset, index + columnOffset);
const { line, column } = position;
return new Position(
line,
column + columnOffset,
indexes.get(position) + columnOffset,
);
}