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
3 changes: 2 additions & 1 deletion src/doc/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,8 @@ export class Document<
keep: !json,
mapAsMap: mapAsMap === true,
mapKeyWarned: false,
maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100
maxAliasCount: typeof maxAliasCount === 'number' ? maxAliasCount : 100,
anchorAndAliasNodes: []
}
const res = toJS(this.contents, jsonArg ?? '', ctx)
if (typeof onAnchor === 'function')
Expand Down
12 changes: 11 additions & 1 deletion src/nodes/Alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,17 @@ export class Alias extends NodeBase {
toJSON(_arg?: unknown, ctx?: ToJSContext): unknown {
if (!ctx) return { source: this.source }
const { anchors, doc, maxAliasCount } = ctx
const source = this.resolve(doc)

let source: Scalar | YAMLMap | YAMLSeq | undefined = undefined
if (ctx.anchorAndAliasNodes) {
for (const node of ctx.anchorAndAliasNodes) {
if (node === this) break
if (node.anchor === this.source) source = node
}
} else {
source = this.resolve(doc)
}
Comment thread
eemeli marked this conversation as resolved.
Outdated

if (!source) {
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`
throw new ReferenceError(msg)
Expand Down
21 changes: 19 additions & 2 deletions src/nodes/toJS.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { Document } from '../doc/Document.ts'
import { hasAnchor } from './identity.ts'
import { hasAnchor, isAlias } from './identity.ts'
import type { Node } from './Node.ts'
import type { Alias } from './Alias.ts'
import type { Scalar } from './Scalar.ts'
import type { YAMLMap } from './YAMLMap.ts'
import type { YAMLSeq } from './YAMLSeq.ts'

export interface AnchorData {
aliasCount: number
Expand All @@ -10,6 +14,8 @@ export interface AnchorData {

export interface ToJSContext {
anchors: Map<Node, AnchorData>
/** Cached anchor and allias nodes in the order they occurred in the document */
anchorAndAliasNodes?: (Alias | Scalar | YAMLMap | YAMLSeq)[]
Comment thread
eemeli marked this conversation as resolved.
Outdated
doc: Document<Node, boolean>
keep: boolean
mapAsMap: boolean
Expand All @@ -33,13 +39,24 @@ export function toJS(value: any, arg: string | null, ctx?: ToJSContext): any {
if (Array.isArray(value)) return value.map((v, i) => toJS(v, String(i), ctx))
if (value && typeof value.toJSON === 'function') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
if (!ctx || !hasAnchor(value)) return value.toJSON(arg, ctx)
if (!ctx) return value.toJSON(arg, ctx)

if (!hasAnchor(value)) {
if (ctx.anchorAndAliasNodes && isAlias(value))
ctx.anchorAndAliasNodes.push(value)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
return value.toJSON(arg, ctx)
}
Comment thread
eemeli marked this conversation as resolved.
Outdated

const data: AnchorData = { aliasCount: 0, count: 1, res: undefined }
ctx.anchors.set(value, data)
ctx.onCreate = res => {
data.res = res
delete ctx.onCreate
}

if (ctx.anchorAndAliasNodes) ctx.anchorAndAliasNodes.push(value)

const res = value.toJSON(arg, ctx)
if (ctx.onCreate) ctx.onCreate(res)
return res
Expand Down