import { runInNewContext } from "node:vm"; import { describe, expect, it } from "vitest"; import type { ToolcraftModelPrimitive } from "./model-document"; import { encodeToolcraftModelDocument, ToolcraftModelDocumentCodecError, } from "./model-document-codec"; import { createModelPrimitive, createValidModelDocument, } from "./model-document-test-support"; import { getValidatedToolcraftModelDocumentSnapshot, ToolcraftModelDocumentValidationError, validateToolcraftModelDocument, } from "./model-document-validation"; function sharedFloat32(values: Float32Array): Float32Array { const result = new Float32Array( new SharedArrayBuffer(values.length * Float32Array.BYTES_PER_ELEMENT), ); result.set(values); return result; } function sharedUint32(values: Uint32Array): Uint32Array { const result = new Uint32Array( new SharedArrayBuffer(values.length * Uint32Array.BYTES_PER_ELEMENT), ); result.set(values); return result; } describe("canonical owned geometry snapshots", () => { it("owns geometry independently from the caller before validation returns", () => { const source = createValidModelDocument(); const snapshot = getValidatedToolcraftModelDocumentSnapshot(source); const sourcePrimitive = source.primitives[0]!; const snapshotPrimitive = snapshot.primitives[0]!; expect(snapshotPrimitive.positions).not.toBe(sourcePrimitive.positions); expect(snapshotPrimitive.positions.buffer).not.toBe( sourcePrimitive.positions.buffer, ); expect(snapshotPrimitive.indices.buffer).not.toBe( sourcePrimitive.indices.buffer, ); expect(snapshotPrimitive.normals?.buffer).not.toBe( sourcePrimitive.normals?.buffer, ); sourcePrimitive.positions[0] = 99; snapshotPrimitive.indices[0] = 2; expect(snapshotPrimitive.positions[0]).toBe(0); expect(sourcePrimitive.indices[0]).toBe(0); }); it("preflights owned geometry copies against worker memory", () => { expect( validateToolcraftModelDocument(createValidModelDocument(), { maxEstimatedWorkerBytes: 16_500, }), ).toMatchObject({ code: "estimated-worker-memory-limit-exceeded", ok: false, }); expect(() => encodeToolcraftModelDocument(createValidModelDocument(), { maxEstimatedWorkerBytes: 16_500, }), ).toThrow(ToolcraftModelDocumentCodecError); }); it.each([ ["positions", (primitive: ToolcraftModelPrimitive) => ({ ...primitive, positions: sharedFloat32(primitive.positions), })], ["normals", (primitive: ToolcraftModelPrimitive) => ({ ...primitive, normals: sharedFloat32(primitive.normals!), })], ["indices", (primitive: ToolcraftModelPrimitive) => ({ ...primitive, indices: sharedUint32(primitive.indices), })], ] as const)("rejects SharedArrayBuffer-backed %s", (field, replace) => { const primitive = replace(createModelPrimitive()); const document = createValidModelDocument({ primitives: [primitive] }); expect(validateToolcraftModelDocument(document)).toMatchObject({ code: "shared-array-buffer-geometry", ok: false, path: `primitives[0].${field}`, }); expect(() => encodeToolcraftModelDocument(document)).toThrow( ToolcraftModelDocumentValidationError, ); }); it("accepts genuine cross-realm Float32Array and Uint32Array geometry", () => { const foreign = runInNewContext(`({ indices: new Uint32Array([0, 1, 2]), normals: new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1]), positions: new Float32Array([0, 0, 0, 2, 0, 0, 0, 3, 0]) })`) as { indices: Uint32Array; normals: Float32Array; positions: Float32Array; }; const document = createValidModelDocument({ primitives: [createModelPrimitive(foreign)], }); expect(validateToolcraftModelDocument(document)).toEqual({ ok: true }); expect(() => encodeToolcraftModelDocument(document)).not.toThrow(); }); it.each([ new Float64Array(9), Object.assign(Object.create(null) as Record, { [Symbol.toStringTag]: "Float32Array", length: 9, }), ])("rejects wrong-kind and spoofed position arrays", (positions) => { const document = createValidModelDocument({ primitives: [createModelPrimitive({ positions: positions as never })], }); expect(validateToolcraftModelDocument(document)).toMatchObject({ code: "invalid-positions-type", ok: false, path: "primitives[0].positions", }); }); });