Skip to content

Commit

Permalink
Store _children in a WeakMap
Browse files Browse the repository at this point in the history
  • Loading branch information
jakebailey committed Apr 4, 2024
1 parent 60e7976 commit 2c02eeb
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/compiler/_namespaces/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export * from "../factory/nodeFactory";
export * from "../factory/emitNode";
export * from "../factory/emitHelpers";
export * from "../factory/nodeTests";
export * from "../factory/nodeChildren";
export * from "../factory/utilities";
export * from "../factory/utilitiesPublic";
export * from "../parser";
Expand Down
27 changes: 27 additions & 0 deletions src/compiler/factory/nodeChildren.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Node } from "../_namespaces/ts";

const nodeChildren = new WeakMap<Node, Node[] | undefined>();

/** @internal */
export function getNodeChildren(node: Node): Node[] | undefined {
return nodeChildren.get(node);
}

/** @internal */
export function setNodeChildren(node: Node, children: Node[]) {
nodeChildren.set(node, children);
}

/** @internal */
export function unsetNodeChildren(node: Node) {
nodeChildren.delete(node);
}

/** @internal */
export function getOrSetNodeChildren(node: Node, fn: () => Node[]): Node[] {
let children = getNodeChildren(node);
if (children === undefined) {
setNodeChildren(node, children = fn());
}
return children;
}
3 changes: 2 additions & 1 deletion src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ import {
setEmitFlags,
setIdentifierAutoGenerate,
setIdentifierTypeArguments,
setNodeChildren,
setParent,
setTextRange,
ShorthandPropertyAssignment,
Expand Down Expand Up @@ -6210,7 +6211,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
// @api
function createSyntaxList(children: Node[]) {
const node = createBaseNode<SyntaxList>(SyntaxKind.SyntaxList);
node._children = children;
setNodeChildren(node, children);
return node;
}

Expand Down
8 changes: 3 additions & 5 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ import {
unescapeLeadingUnderscores,
UnionOrIntersectionTypeNode,
UnionTypeNode,
unsetNodeChildren,
UpdateExpression,
VariableDeclaration,
VariableDeclarationList,
Expand Down Expand Up @@ -10002,9 +10003,7 @@ namespace IncrementalParser {

// Ditch any existing LS children we may have created. This way we can avoid
// moving them forward.
if (node._children) {
node._children = undefined;
}
unsetNodeChildren(node);

setTextRangePosEnd(node, node.pos + delta, node.end + delta);

Expand Down Expand Up @@ -10160,7 +10159,7 @@ namespace IncrementalParser {
const fullEnd = child.end;
if (fullEnd >= changeStart) {
child.intersectsChange = true;
child._children = undefined;
unsetNodeChildren(child);

// Adjust the pos or end (or both) of the intersecting element accordingly.
adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
Expand Down Expand Up @@ -10349,7 +10348,6 @@ namespace IncrementalParser {

export interface IncrementalNode extends Node, IncrementalElement {
hasBeenIncrementallyParsed: boolean;
_children: Node[] | undefined;
}

interface IncrementalNodeArray extends NodeArray<IncrementalNode>, IncrementalElement {
Expand Down
1 change: 0 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9666,7 +9666,6 @@ export interface DiagnosticCollection {
// SyntaxKind.SyntaxList
export interface SyntaxList extends Node {
kind: SyntaxKind.SyntaxList;
_children: Node[];
}

// dprint-ignore
Expand Down
9 changes: 6 additions & 3 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ import {
getLineStarts,
getModeForUsageLocation,
getNameOfDeclaration,
getNodeChildren,
getNormalizedAbsolutePath,
getNormalizedPathComponents,
getOwnKeys,
Expand Down Expand Up @@ -510,7 +511,6 @@ import {
SymbolFlags,
SymbolTable,
SyntaxKind,
SyntaxList,
TaggedTemplateExpression,
TemplateExpression,
TemplateLiteral,
Expand Down Expand Up @@ -1161,8 +1161,11 @@ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, inclu
// the syntax list itself considers them as normal trivia. Therefore if we simply skip
// trivia for the list, we may have skipped the JSDocComment as well. So we should process its
// first child to determine the actual position of its first token.
if (node.kind === SyntaxKind.SyntaxList && (node as SyntaxList)._children.length > 0) {
return getTokenPosOfNode((node as SyntaxList)._children[0], sourceFile, includeJsDoc);
if (node.kind === SyntaxKind.SyntaxList) {
const first = firstOrUndefined(getNodeChildren(node));
if (first) {
return getTokenPosOfNode(first, sourceFile, includeJsDoc);
}
}

return skipTrivia(
Expand Down
15 changes: 8 additions & 7 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import {
getNonAssignedNameOfDeclaration,
getNormalizedAbsolutePath,
getObjectFlags,
getOrSetNodeChildren,
getQuotePreference,
getScriptKind,
getSetExternalModuleIndicator,
Expand Down Expand Up @@ -266,6 +267,7 @@ import {
ScriptTarget,
SelectionRange,
SemanticClassificationFormat,
setNodeChildren,
setObjectAllocator,
Signature,
SignatureDeclaration,
Expand Down Expand Up @@ -357,7 +359,6 @@ class NodeObject<TKind extends SyntaxKind> implements Node {
public symbol!: Symbol; // Actually optional, but it was too annoying to access `node.symbol!` everywhere since in many cases we know it must be defined
public jsDoc?: JSDoc[];
public original?: Node;
private _children: Node[] | undefined;
public id?: number;
public emitNode?: EmitNode;

Expand All @@ -373,7 +374,6 @@ class NodeObject<TKind extends SyntaxKind> implements Node {
this.parent = undefined!;
this.original = undefined;
this.emitNode = undefined;
this._children = undefined;
}

private assertHasRealPosition(message?: string) {
Expand Down Expand Up @@ -438,7 +438,7 @@ class NodeObject<TKind extends SyntaxKind> implements Node {

public getChildren(sourceFile?: SourceFileLike): Node[] {
this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine");
return this._children || (this._children = createChildren(this, sourceFile));
return getOrSetNodeChildren(this, () => createChildren(this, sourceFile));
}

public getFirstToken(sourceFile?: SourceFileLike): Node | undefined {
Expand Down Expand Up @@ -533,14 +533,15 @@ function addSyntheticNodes(nodes: Node[], pos: number, end: number, parent: Node

function createSyntaxList(nodes: NodeArray<Node>, parent: Node): Node {
const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, parent) as any as SyntaxList;
list._children = [];
const children: Node[] = [];
let pos = nodes.pos;
for (const node of nodes) {
addSyntheticNodes(list._children, pos, node.pos, parent);
list._children.push(node);
addSyntheticNodes(children, pos, node.pos, parent);
children.push(node);
pos = node.end;
}
addSyntheticNodes(list._children, pos, nodes.end, parent);
addSyntheticNodes(children, pos, nodes.end, parent);
setNodeChildren(list, children);
return list;
}

Expand Down
1 change: 0 additions & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7985,7 +7985,6 @@ declare namespace ts {
}
interface SyntaxList extends Node {
kind: SyntaxKind.SyntaxList;
_children: Node[];
}
enum ListFormat {
None = 0,
Expand Down

0 comments on commit 2c02eeb

Please sign in to comment.