Files
scriptc/tests/harness/ffi-memory.test.ts
Chris Tate c08ab955ae Enforce linting and consistent source formatting
- Enforce oxlint and oxfmt for owned JavaScript and TypeScript with independent CI checks.
- Preserve compiler import boundaries and protected fixtures while cleaning up lint findings.
- Standardize source formatting and validate import, fixture, and embedded-source protections.
2026-10-05 17:51:24 -05:00

58 lines
2.7 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, test } from "vitest";
import { compile } from "@scriptc/compiler";
const fixture = join(import.meta.dirname, "../ffi/memory.mjs");
const sanitize = process.env["SCRIPTC_SAN"] === "1";
const oracle = process.env["SCRIPTC_NODE_FFI_ORACLE"];
const expected =
"bigint true\n10,99,30,40 99,30\n10,99,30,40 55,99,30,40\ntrue\n231\n0\n" +
"TypeError ERR_INVALID_ARG_VALUE The first argument must be a non-negative bigint\n".repeat(2) +
"Error ERR_FFI_INVALID_POINTER Cannot create an ArrayBuffer from a null pointer\n" +
"TypeError ERR_INVALID_ARG_VALUE The length must be a non-negative integer\n".repeat(2) +
"TypeError ERR_INVALID_ARG_VALUE The pointer and length exceed the platform address range\n" +
"RangeError ERR_OUT_OF_RANGE The length is too large\nError ERR_BUFFER_TOO_LARGE Buffer is too large\n" +
"true\ntrue\ntrue\ntrue\nfalse\nfalse\n";
describe.each(["llvm"] as const)("native FFI memory, %s", (backend) => {
test("aliases native memory and copies on request without an engine", async () => {
const outDir = mkdtempSync(join(tmpdir(), "scriptc-ffi-memory-"));
// Both loader spellings must keep real storage; bare `require` also
// participates in the compiler's CommonJS alias recognition.
for (const loader of ["require", "requireModule"]) {
const entry = join(outDir, `${loader}.mjs`);
writeFileSync(entry, readFileSync(fixture, "utf8").replaceAll("require", loader));
const result = await compile(entry, {
backend,
dynamic: false,
sanitize,
outDir,
outPath: join(outDir, loader),
});
if (!result.ok)
throw new Error(result.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n"));
const native = spawnSync(result.binaryPath, [], { encoding: "utf8", timeout: 10_000 });
expect(native.error).toBeUndefined();
expect(native.stderr).toBe("");
expect(native.status).toBe(0);
expect(native.stdout).toBe(expected);
// Node 24 remains the repository oracle; node:ffi first shipped in
// Node 26.1. An explicit Node 26 path enables direct parity here.
if (oracle) {
const node = spawnSync(
oracle,
["--disable-warning=ExperimentalWarning", "--experimental-ffi", entry],
{ encoding: "utf8" },
);
expect(node.error).toBeUndefined();
expect(node.stderr).toBe(native.stderr);
expect(node.status).toBe(native.status);
expect(node.stdout).toBe(native.stdout);
}
}
});
});