Skip to content

Commit 55c5ef4

Browse files
authored
feat: Add node cache for faster alias resolution (#612)
1 parent ab17552 commit 55c5ef4

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

src/nodes/Alias.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Document } from '../doc/Document.ts'
33
import type { FlowScalar } from '../parse/cst.ts'
44
import type { StringifyContext } from '../stringify/stringify.ts'
55
import { visit } from '../visit.ts'
6-
import { ALIAS, isAlias, isCollection, isPair } from './identity.ts'
6+
import { ALIAS, hasAnchor, isAlias, isCollection, isPair } from './identity.ts'
77
import type { Node, Range } from './Node.ts'
88
import { NodeBase } from './Node.ts'
99
import type { Scalar } from './Scalar.ts'
@@ -38,21 +38,36 @@ export class Alias extends NodeBase {
3838
* Resolve the value of this alias within `doc`, finding the last
3939
* instance of the `source` anchor before this node.
4040
*/
41-
resolve(doc: Document): Scalar | YAMLMap | YAMLSeq | undefined {
41+
resolve(
42+
doc: Document,
43+
ctx?: ToJSContext
44+
): Scalar | YAMLMap | YAMLSeq | undefined {
45+
let nodes: Node[]
46+
if (ctx?.aliasResolveCache) {
47+
nodes = ctx.aliasResolveCache
48+
} else {
49+
nodes = []
50+
visit(doc, {
51+
Node: (_key: unknown, node: Node) => {
52+
if (isAlias(node) || hasAnchor(node)) nodes.push(node)
53+
}
54+
})
55+
if (ctx) ctx.aliasResolveCache = nodes
56+
}
57+
4258
let found: Scalar | YAMLMap | YAMLSeq | undefined = undefined
43-
visit(doc, {
44-
Node: (_key: unknown, node: Node) => {
45-
if (node === this) return visit.BREAK
46-
if (node.anchor === this.source) found = node
47-
}
48-
})
59+
for (const node of nodes) {
60+
if (node === this) break
61+
if (node.anchor === this.source) found = node
62+
}
63+
4964
return found
5065
}
5166

5267
toJSON(_arg?: unknown, ctx?: ToJSContext): unknown {
5368
if (!ctx) return { source: this.source }
5469
const { anchors, doc, maxAliasCount } = ctx
55-
const source = this.resolve(doc)
70+
const source = this.resolve(doc, ctx)
5671
if (!source) {
5772
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`
5873
throw new ReferenceError(msg)

src/nodes/toJS.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export interface AnchorData {
1010

1111
export interface ToJSContext {
1212
anchors: Map<Node, AnchorData>
13+
/** Cached anchor and alias nodes in the order they occur in the document */
14+
aliasResolveCache?: Node[]
1315
doc: Document<Node, boolean>
1416
keep: boolean
1517
mapAsMap: boolean

0 commit comments

Comments
 (0)