Files

15 lines
1.3 KiB
JavaScript

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {detachJsonData,hasDetachedJsonData} from '../../src/lib/canvas-core/json-data.ts';
test('JSON detachment owns only its copied immutable result and preserves JSON semantics',()=>{
let calls=0;const external={nested:{text:'before'},date:new Date('2026-01-01Z'),custom:{toJSON(){calls++;return{value:2};}},array:[,undefined,NaN],['__proto__']:{safe:true}};
const value=detachJsonData(external);assert.equal(calls,1);assert.equal(hasDetachedJsonData(value),true);assert.equal(hasDetachedJsonData(external),false);
external.nested.text='after';external.date.setUTCFullYear(2027);
assert.equal(value.nested.text,'before');assert.equal(value.date,'2026-01-01T00:00:00.000Z');assert.deepEqual(value.array,[null,null,null]);assert.equal(Object.hasOwn(value,'__proto__'),true);
assert.ok(Object.isFrozen(value.nested));assert.throws(()=>{value.nested.text='mutate';},TypeError);
assert.equal(hasDetachedJsonData(Object.freeze({...value})),false);assert.equal(hasDetachedJsonData(structuredClone(value)),false);
assert.equal(hasDetachedJsonData(Object.freeze({nested:{mutable:true}})),false);
const cycle={};cycle.self=cycle;assert.throws(()=>detachJsonData(cycle));assert.throws(()=>detachJsonData({big:1n}));
});