Files
scriptc/tests/harness/three-library.test.ts
Chris Tate a07998f667 Expand static three.js workflows and host integration (#621)
* Expand static three.js workflows and host integration

* Preserve JavaScript class state in static three.js workflows

* Preserve inferred JavaScript behavior across static workflows

* Preserve inferred callables and native compatibility boundaries

* Retain annotated JavaScript factory exports and bootstrap-safe call spreads

* Preserve Buffer and child callback identities in static packages

* Clarify JavaScript symbol spread support
2026-10-02 19:56:34 -05:00

38 lines
2.4 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { compileLibrary } from "@scriptc/compiler";
import { expect, test } from "vitest";
const fixture = join(import.meta.dirname, "../library-mode/wasm");
const hasClang = spawnSync("clang", ["--version"]).status === 0;
test.skipIf(!hasClang).each(["dev", "release"] as const)("three.js sends animated geometry, materials and resource lifecycle to a native host in %s", async (optimization) => {
const directory = await mkdtemp("/tmp/scriptc-three-library-");
const sanitize = process.env["SCRIPTC_SAN"] === "1";
try {
const profile = JSON.parse(await readFile(join(fixture, "three.json"), "utf8"));
const profilePath = join(directory, "profile.json");
await writeFile(profilePath, JSON.stringify({ ...profile, name: "three-native-embedding", entry: join(fixture, "three.mjs"), optimization }));
const built = await compileLibrary({ profilePath, outDir: directory, sanitize });
if (!built.ok) throw new Error(built.diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).join("\n"));
const binary = join(directory, "host");
const linked = spawnSync("clang", ["-std=c11", ...(sanitize ? ["-fsanitize=address,undefined"] : []), join(fixture, "three-native.c"), built.archivePath, "-lm", "-o", binary], { encoding: "utf8" });
expect(linked.status, linked.stderr).toBe(0);
const actual = spawnSync(binary, [], { encoding: "utf8", timeout: 30_000 });
expect(actual.status, actual.stderr).toBe(0);
const reference = spawnSync(process.execPath, ["--no-warnings", "--input-type=module", "-e", `
const events=[];
for (const name of ["vertex","surface","resource"]) globalThis[name]=(...values)=>events.push([name,...values.map(value=>Number(value.toFixed(9)))]);
const {frame,dispose}=await import(${JSON.stringify(join(fixture, "three.mjs"))});
for (const time of [0,123,2000]) frame(time,1.5);
dispose();
console.log(JSON.stringify(events));
`], { encoding: "utf8" });
expect(reference.status, reference.stderr).toBe(0);
const events = JSON.parse(reference.stdout);
expect(actual.stdout.trim().split("\n").map((line) => JSON.parse(line))).toEqual([...events, ...events]);
} finally {
await rm(directory, { recursive: true, force: true });
}
}, 600_000);