diff --git a/src/nodes/Pair.ts b/src/nodes/Pair.ts index 18ddad34..72f642c3 100644 --- a/src/nodes/Pair.ts +++ b/src/nodes/Pair.ts @@ -36,7 +36,9 @@ export class Pair< doc: Document, ctx: ToJSContext ): ReturnType { - const pair = ctx.mapAsMap ? new Map() : {} + const pair = ctx.mapAsMap + ? new Map() + : (Object.create(null) as Record) return addPairToJSMap(doc, ctx, pair, this) } diff --git a/src/nodes/YAMLMap.ts b/src/nodes/YAMLMap.ts index b2075041..c0e9f86b 100644 --- a/src/nodes/YAMLMap.ts +++ b/src/nodes/YAMLMap.ts @@ -235,7 +235,11 @@ export class YAMLMap< Type?: { new (): T } ) { ctx ??= new ToJSContext() - const map = Type ? new Type() : ctx?.mapAsMap ? new Map() : {} + const map = Type + ? new Type() + : ctx?.mapAsMap + ? new Map() + : (Object.create(null) as Record) if (this.anchor) ctx.setAnchor(this, map) for (const pair of this.values.values()) addPairToJSMap(doc, ctx, map, pair) return map diff --git a/tests/node-to-js.ts b/tests/node-to-js.ts index 170cd309..0878e0f3 100644 --- a/tests/node-to-js.ts +++ b/tests/node-to-js.ts @@ -17,12 +17,16 @@ describe('scalars', () => { describe('collections', () => { test('map', () => { const doc = parseDocument('key: 42') - expect(doc.value.toJS(doc)).toMatchObject({ key: 42 }) + expect(doc.value.toJS(doc)).toStrictEqual( + Object.assign(Object.create(null), { key: 42 }) + ) }) test('map in seq', () => { const doc = parseDocument('- key: 42') - expect(doc.get(0).toJS(doc)).toMatchObject({ key: 42 }) + expect(doc.get(0).toJS(doc)).toStrictEqual( + Object.assign(Object.create(null), { key: 42 }) + ) }) }) @@ -51,7 +55,11 @@ describe('alias', () => { two: &b { key: *a } three: *b `) - expect(doc.get('three').toJS(doc)).toMatchObject({ key: 42 }) + expect(doc.get('three').toJS(doc)).toStrictEqual( + Object.assign(Object.create(null), { + key: 42 + }) + ) }) test('missing anchor', () => { diff --git a/tests/properties.ts b/tests/properties.ts index 9950f964..b82ae3ab 100644 --- a/tests/properties.ts +++ b/tests/properties.ts @@ -1,6 +1,23 @@ import * as fc from 'fast-check' import { parse, stringify } from 'yaml' +/** Set pojo prototypes to `null` recursively */ +function nullifyProto(value: unknown): unknown { + if (typeof value !== 'object' || value == null) { + return value + } + if (Array.isArray(value)) { + return value.map(nullifyProto) + } + const result: Record = Object.create(null) + for (const key in value) { + if (Object.hasOwn(value, key)) { + result[key] = nullifyProto((value as Record)[key]) + } + } + return result +} + describe('properties', () => { test('parse stringified object', () => { const key = fc.fullUnicodeString() @@ -25,7 +42,9 @@ describe('properties', () => { fc.assert( fc.property(yamlArbitrary, optionsArbitrary, (obj, opts) => { - expect(parse(stringify(obj, opts), opts)).toStrictEqual(obj) + expect(parse(stringify(obj, opts), opts)).toStrictEqual( + nullifyProto(obj) + ) }) ) })