101 lines
3.3 KiB
JavaScript
101 lines
3.3 KiB
JavaScript
import { createRequire } from "node:module";
|
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
/** Compile source-owned fixtures using explicitly supplied, pinned toolchains. */
|
|
export async function buildRecoveryFixtures(root, prefix) {
|
|
if (!prefix)
|
|
throw new Error(
|
|
"verify:javascript:recovery requires REA_JAVASCRIPT_FIXTURE_TOOLS pointing to the isolated esbuild/webpack installation",
|
|
);
|
|
const require = createRequire(join(prefix, "package.json"));
|
|
const esbuild = require("esbuild");
|
|
const webpack = require("webpack");
|
|
const webpackVersion = require("webpack/package.json").version;
|
|
if (esbuild.version !== "0.25.10" || webpackVersion !== "5.101.3")
|
|
throw new Error(
|
|
"Fixture compilers must be esbuild 0.25.10 and webpack 5.101.3",
|
|
);
|
|
const source = fileURLToPath(new URL("./entry.mjs", import.meta.url));
|
|
const webpackOutput = join(root, "webpack");
|
|
await mkdir(webpackOutput);
|
|
await new Promise((resolve, reject) => {
|
|
const compiler = webpack({
|
|
mode: "production",
|
|
entry: source,
|
|
parallelism: 1,
|
|
optimization: { concatenateModules: false },
|
|
output: { path: webpackOutput, filename: "bundle.js" },
|
|
});
|
|
compiler.run((error, stats) => {
|
|
compiler.close((closeError) => {
|
|
if (error || closeError) return reject(error ?? closeError);
|
|
if (!stats || stats.hasErrors())
|
|
return reject(new Error(stats?.toString() ?? "No webpack stats"));
|
|
resolve();
|
|
});
|
|
});
|
|
});
|
|
const esbuildPath = join(root, "esbuild.js");
|
|
await esbuild.build({
|
|
entryPoints: [source],
|
|
outfile: esbuildPath,
|
|
bundle: true,
|
|
format: "iife",
|
|
minify: true,
|
|
logLevel: "silent",
|
|
});
|
|
// One self-contained source fixture avoids unresolved imports in the oracle.
|
|
const helperSource = await readFile(
|
|
fileURLToPath(new URL("./helpers.mjs", import.meta.url)),
|
|
"utf8",
|
|
);
|
|
const plain = await esbuild.transform(
|
|
helperSource.replaceAll("export ", "") +
|
|
"\nglobalThis.recoveryFixture = {greet, total};",
|
|
{ minify: true },
|
|
);
|
|
const minifiedPath = join(root, "minified.js");
|
|
await writeFile(minifiedPath, plain.code);
|
|
if (plain.code.length === 0)
|
|
throw new Error("Expected a real minifier output");
|
|
return {
|
|
files: [
|
|
{
|
|
name: "minified",
|
|
path: minifiedPath,
|
|
expectedFormat: "unknown",
|
|
expectedModules: 1,
|
|
},
|
|
{
|
|
name: "webpack",
|
|
path: join(webpackOutput, "bundle.js"),
|
|
expectedFormat: "webpack5",
|
|
expectedModules: 2,
|
|
},
|
|
{
|
|
name: "esbuild-scope-hoisted",
|
|
path: esbuildPath,
|
|
expectedFormat: "unknown",
|
|
expectedModules: 1,
|
|
},
|
|
{
|
|
name: "heuristic-aggressive",
|
|
path: minifiedPath,
|
|
expectedFormat: "unknown",
|
|
expectedModules: 1,
|
|
options: { extraction_mode: "heuristic", rewrite_level: "aggressive" },
|
|
},
|
|
{
|
|
name: "inspection-minimal",
|
|
path: join(webpackOutput, "bundle.js"),
|
|
expectedFormat: "webpack5",
|
|
expectedModules: 2,
|
|
options: { extraction_mode: "inspection", rewrite_level: "minimal" },
|
|
},
|
|
],
|
|
toolchains: { esbuild: esbuild.version, webpack: webpackVersion },
|
|
};
|
|
}
|