Files
scriptc/tests/harness/static-only.test.ts
T

100 lines
3.9 KiB
TypeScript

import { spawnSync } from "node:child_process";
import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { expect, test } from "vitest";
import { analyze, compile } from "@scriptc/compiler";
const root = join(import.meta.dirname, "../..");
test.each(["build", "run", "coverage"])("%s rejects the retired --dynamic option", (command) => {
const result = spawnSync(
process.execPath,
["--import", "tsx", join(root, "packages/cli/src/main.ts"), command, "main.ts", "--dynamic"],
{ cwd: root, encoding: "utf8" },
);
expect(result.status).toBe(1);
expect(result.stderr).toContain("--dynamic");
});
test("default package compilation preserves checked values, regex, imports, and comptime without an engine", async () => {
const directory = mkdtempSync(join(tmpdir(), "scriptc-static-only-"));
try {
mkdirSync(join(directory, "node_modules"));
cpSync(
join(root, "tests/fixtures/npm-static/node_modules/slash"),
join(directory, "node_modules/slash"),
{ recursive: true },
);
writeFileSync(join(directory, "package.json"), '{"type":"module"}');
const entry = join(directory, "main.ts");
writeFileSync(
entry,
`import slash from "slash";
const answer = comptime(() => 6 * 7);
const value: any = answer;
const path = await import("node:path");
console.log(slash("a\\\\b"), /^a/.test("abc"), value + 1, path.basename("a/b"));
`,
);
const coverage = analyze(entry).coverage;
expect(coverage.diagnostics).toEqual([]);
expect(coverage.npmStatic).toEqual([{ package: "slash", status: "static" }]);
const result = await compile(entry, {
outDir: directory,
outPath: join(directory, process.platform === "win32" ? "program.exe" : "program"),
sanitize: process.env["SCRIPTC_SAN"] === "1",
});
if (!result.ok) throw new Error(JSON.stringify(result.diagnostics));
const actual = spawnSync(result.binaryPath, [], { encoding: "utf8" });
const expected = spawnSync(
process.execPath,
["--import", join(root, "tests/harness/comptime-shim.mjs"), entry],
{ encoding: "utf8" },
);
expect(actual.status, actual.stderr).toBe(expected.status);
expect(actual.stdout).toBe(expected.stdout);
const stderr =
process.env["SCRIPTC_SAN"] === "1"
? actual.stderr
.split("\n")
.filter(
(line) =>
!line.startsWith("scriptc RC audit skipped:") &&
!/^==\d+==WARNING: ASan doesn't fully support makecontext\/swapcontext/.test(line),
)
.join("\n")
: actual.stderr;
expect(stderr).toBe(expected.stderr);
expect(actual.stdout).toBe("a/b true 43 b\n");
expect(readFileSync(result.llvmPath, "utf8")).not.toMatch(/@scr_(?:island|jsval)_/);
if (process.platform !== "win32") {
const symbols = spawnSync("nm", [result.binaryPath], { encoding: "utf8" });
expect(symbols.status, symbols.stderr).toBe(0);
expect(symbols.stdout).not.toMatch(/\b_?(?:JS_NewRuntime|JS_Eval|scr_island_init)\b/);
}
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("an ineligible package fails with its package-specific native refusal", async () => {
const directory = mkdtempSync(join(tmpdir(), "scriptc-package-refusal-"));
try {
const result = await compile(join(root, "tests/fixtures/npm-static/typegap-mix.ts"), {
outDir: directory,
outPath: join(directory, "program"),
});
expect(result.ok).toBe(false);
if (!result.ok)
expect(result.diagnostics).toContainEqual(
expect.objectContaining({
code: "SC2013",
message: expect.stringContaining("cannot compile npm package 'typegapped' statically"),
}),
);
} finally {
rmSync(directory, { recursive: true, force: true });
}
});