Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion src/nodes/Pair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class Pair<

toJS(doc: Document<DocValue>, ctx: ToJSContext): MapLike {
const pair = ctx.mapAsMap ? new Map() : {}
addPairToJSMap(doc, ctx, pair, this, true)
addPairToJSMap(doc, ctx, pair, this)
return pair
}

Expand Down
3 changes: 1 addition & 2 deletions src/nodes/Scalar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ export class Scalar<T = unknown> implements NodeBase {
doc: Document<DocValue>,
ctx: ToJSContext,
map: MapLike,
value: unknown,
isPlainObject: boolean
value: unknown
) => void

constructor(value: T) {
Expand Down
34 changes: 6 additions & 28 deletions src/nodes/YAMLMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,37 +212,15 @@ export class YAMLMap<
return this
}

/**
* A plain JavaScript representation of this node.
*
* @param Type - If set, forces the returned collection type
* @returns Instance of Type, Map, or Object
*/
toJS<T extends MapLike = Map<any, any>>(
doc: Document<DocValue>,
ctx: ToJSContext | undefined,
Type: { new (): T }
): T
toJS(doc: Document<DocValue>, ctx?: ToJSContext): any
toJS<T extends MapLike>(
/** A plain JavaScript representation of this node. */
toJS(
doc: Document<DocValue>,
ctx?: ToJSContext,
Type?: { new (): T }
) {
ctx?: ToJSContext
): Map<any, any> | Record<any, any> {
ctx ??= new ToJSContext()
let map: MapLike
let isPlainObject = false
if (Type) {
map = new Type()
} else if (ctx.mapAsMap) {
map = new Map()
} else {
map = {}
isPlainObject = true
}
const map = ctx.mapAsMap ? new Map() : {}
if (this.anchor) ctx.setAnchor(this, map)
for (const pair of this.values.values())
addPairToJSMap(doc, ctx, map, pair, isPlainObject)
for (const pair of this.values.values()) addPairToJSMap(doc, ctx, map, pair)
return map
}

Expand Down
7 changes: 3 additions & 4 deletions src/nodes/addPairToJSMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ export function addPairToJSMap(
doc: Document<DocValue>,
ctx: ToJSContext,
map: MapLike,
{ key, value }: Pair,
isPlainObject: boolean
{ key, value }: Pair
): void {
if ('addToJSMap' in key && typeof key.addToJSMap === 'function') {
key.addToJSMap(doc, ctx, map, value, isPlainObject)
key.addToJSMap(doc, ctx, map, value)
} else {
const jsKey = key.toJS(doc, ctx)
if (map instanceof Map) {
Expand All @@ -25,7 +24,7 @@ export function addPairToJSMap(
const stringKey = stringifyKey(doc, ctx, key, jsKey)
const jsValue = value ? value.toJS(doc, ctx) : value
if (
(!isPlainObject && stringKey in map) ||
(map.constructor !== Object && stringKey in map) ||
stringKey === '__proto__' ||
stringKey === 'constructor'
)
Expand Down
16 changes: 9 additions & 7 deletions src/schema/yaml-1.1/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,24 @@ function addToJSMap(
doc: Document<DocValue>,
ctx: ToJSContext,
map: MapLike,
value: unknown,
isPlainObject: boolean
value: unknown
): void {
const source = getMergeSource(doc, ctx, value)
if (Array.isArray(source)) {
for (const v of source) {
const s = getMergeSource(doc, ctx, v)
mergeValue(doc, ctx, map, s, isPlainObject)
mergeValue(doc, ctx, map, s)
}
} else {
mergeValue(doc, ctx, map, source, isPlainObject)
mergeValue(doc, ctx, map, source)
}
}

function mergeValue(
doc: Document<DocValue>,
ctx: ToJSContext,
map: MapLike,
source: unknown,
isPlainObject: boolean
source: unknown
) {
if (!(source instanceof YAMLMap))
throw new Error('Merge sources must be maps or map aliases')
Expand All @@ -77,7 +75,11 @@ function mergeValue(
} else if (map instanceof Set) {
map.add(key)
} else if (!Object.prototype.hasOwnProperty.call(map, key)) {
if (!isPlainObject || key === '__proto__' || key === 'constructor') {
if (
map.constructor !== Object ||
key === '__proto__' ||
key === 'constructor'
) {
Object.defineProperty(map, key, {
value,
writable: true,
Expand Down
8 changes: 3 additions & 5 deletions tests/doc/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1113,11 +1113,9 @@ describe('custom tags', () => {
class YAMLNullObject extends YAMLMap {
tag: string = '!nullobject'
toJS(doc: any, ctx?: any): any {
const obj = super.toJS<Record<any, any>>(
doc,
{ ...ctx, mapAsMap: false },
Object
)
ctx = Object.create(ctx)
ctx.mapAsMap = false
const obj = super.toJS(doc, ctx)
return Object.assign(Object.create(null), obj)
}
}
Expand Down
Loading