From 0cdc56a56fe25e467d0ec42426d89d248a0581ab Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Mon, 5 Oct 2026 01:03:17 +0200 Subject: [PATCH] Answer stability round 1: accept a plain object from another realm --- src/adf/document.test.ts | 2 ++ src/json-value.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/adf/document.test.ts b/src/adf/document.test.ts index 59c3141..9e986f8 100644 --- a/src/adf/document.test.ts +++ b/src/adf/document.test.ts @@ -1,5 +1,6 @@ import assert from 'node:assert/strict' import test from 'node:test' +import vm from 'node:vm' import type { JsonValue } from '../json-value.ts' import { adfDocumentFault, isAdfDocument } from './document.ts' @@ -76,6 +77,7 @@ test('accepts the JSON values an attribute may hold', () => { assert.equal(isAdfDocument({ content: [{ attrs: { a: [1, 'x', null, true, { b: 2 }] }, type: 'paragraph' }], type: 'doc', version: 1 }), true) assert.equal(isAdfDocument({ content: [{ attrs: { a: [() => 1] }, type: 'paragraph' }], type: 'doc', version: 1 }), false) assert.equal(isAdfDocument({ content: [{ attrs: { a: Object.assign(Object.create(null), { b: 1 }) }, type: 'paragraph' }], type: 'doc', version: 1 }), true) + assert.equal(isAdfDocument(vm.runInNewContext("({ content: [{ attrs: { a: { b: [1] } }, type: 'paragraph' }], type: 'doc', version: 1 })")), true) }) test('refuses an attribute value that is an object JSON does not hold', () => { diff --git a/src/json-value.ts b/src/json-value.ts index fd30061..89cef47 100644 --- a/src/json-value.ts +++ b/src/json-value.ts @@ -19,11 +19,11 @@ export function isJsonValue(value: unknown): value is JsonValue { return true } -// A Date, Map or class instance passes typeof but JSON writes it as {} or a key per element. +// Any realm's Object.prototype has a null prototype; a Date, Map or typed array would serialize as {} or a key per element. function isPlainObject(value: unknown): value is object { if (typeof value !== 'object' || value === null) return false const prototype: unknown = Object.getPrototypeOf(value) - return prototype === Object.prototype || prototype === null + return prototype === null || (typeof prototype === 'object' && Object.getPrototypeOf(prototype) === null) } export function nestingDepth(value: unknown): number {