#!/usr/bin/env node import assert from "node:assert/strict"; import { execFileSync, spawn } from "node:child_process"; import { createHash } from "node:crypto"; import { once } from "node:events"; import { access, copyFile, mkdir, mkdtemp, readFile, rename, readdir, rm, symlink, writeFile, open, } from "node:fs/promises"; import { tmpdir } from "node:os"; import { dirname, join, parse, resolve } from "node:path"; import { pathToFileURL } from "node:url"; import { verifyWindowsProtocolInput } from "./lib/windows-protocol-input.mjs"; import { verifyWindowsJobMemoryLimit } from "./lib/windows-job-memory-limit.mjs"; if (process.platform !== "win32") throw new Error( "Windows native conformance requires a real Windows x64 host.", ); const packageRoot = resolve(process.argv[2] ?? "."); const { requireWindowsNativeAuthority } = await import( pathToFileURL(join(packageRoot, "dist/windows/WindowsNativeLoader.js")) ); const native = requireWindowsNativeAuthority(); const { WindowsPrivateRuntime, windowsPrivateRuntime } = await import( pathToFileURL(join(packageRoot, "dist/windows/WindowsPrivateRuntime.js")) ); const { ghidraSessionRoot } = await import( pathToFileURL(join(packageRoot, "dist/ghidra/GhidraSessionRoot.js")) ); const { PrivateRuntimeRoot } = await import( pathToFileURL(join(packageRoot, "dist/process/PrivateRuntimeRoot.js")) ); const { PrivateRuntimeRootUnavailableError } = await import( pathToFileURL( join(packageRoot, "dist/process/PrivateRuntimeRootUnavailableError.js"), ) ); const workspace = await mkdtemp(join(tmpdir(), "rea-native-conformance-")); const environment = Object.entries(process.env) .filter(([, value]) => value !== undefined) .map(([key, value]) => `${key}=${value}`); const quote = (value) => `"${value.replace(/(\\*)"/gu, '$1$1\\"').replace(/(\\+)$/u, "$1$1")}"`; const delay = () => new Promise((resolve) => setTimeout(resolve, 25)); const exists = (path) => access(path).then( () => true, () => false, ); const live = (pid) => { try { process.kill(pid, 0); return true; } catch { return false; } }; const launch = (arguments_) => native.call("process_spawn", [ process.execPath, [process.execPath, ...arguments_].map(quote).join(" "), workspace, environment, ]); const wait = async (child) => { let output = ""; for (let attempt = 0; attempt < 400; attempt++) { const state = native.call("process_poll", [child.handle]); output += state.stdout.toString(); if ( state.exitCode !== null && state.activeProcesses === 0 && state.stdoutEnded && state.stderrEnded ) return { ...state, output }; await delay(); } throw new Error("Owned job did not settle within the fixture deadline."); }; const report = { ok: false, artifact: "verified", controls: {}, processes: {} }; try { // Exercise the loader in a process whose image is not named node.exe. The // ordinary Windows lane otherwise cannot detect eager Node-API imports. const renamedHost = join(workspace, "rea-renamed-node.exe"); const renamedHostFixture = join(workspace, "renamed-host.mjs"); const loaderUrl = pathToFileURL( join(packageRoot, "dist/windows/WindowsNativeLoader.js"), ).href; await copyFile(process.execPath, renamedHost); await writeFile( renamedHostFixture, `import {basename} from 'node:path'; import {requireWindowsNativeAuthority} from ${JSON.stringify(loaderUrl)}; const {inspection}=requireWindowsNativeAuthority(); process.stdout.write(JSON.stringify({executable:basename(process.execPath),abiVersion:inspection.abiVersion}));\n`, ); const renamedHostResult = execFileSync(renamedHost, [renamedHostFixture], { encoding: "utf8", timeout: 20_000, windowsHide: true, }); assert.deepEqual(JSON.parse(renamedHostResult), { executable: "rea-renamed-node.exe", abiVersion: 1, }); report.controls.renamedHostNodeApi = true; const sourceDirectory = join(workspace, "source"); await mkdir(sourceDirectory); const source = join(sourceDirectory, "target.bin"); await writeFile(source, Buffer.alloc(1024 * 1024, 0x37)); const sourceIdentity = native.call("open", [source]); try { for (const requested of [ source.replaceAll("\\", "/"), source.replace(/\\/u, "/"), ]) { const admitted = native.call("open", [requested]); try { assert.equal(admitted.requestedPath, requested); assert.equal(admitted.finalPath, sourceIdentity.finalPath); assert.equal(admitted.fileId, sourceIdentity.fileId); assert.equal(native.call("read", [admitted.handle, 0, 1])[0], 0x37); } finally { native.call("close", [admitted.handle]); } } } finally { native.call("close", [sourceIdentity.handle]); } for (const rejected of [ source.replace(/^([A-Za-z]):\\/u, "$1:"), `${sourceDirectory}/../source/target.bin`, `${sourceDirectory}//target.bin`, `${source}:stream`, `\\\\?\\${source.replaceAll("\\", "/")}`, "//localhost/share/target.bin", ]) assert.throws(() => native.call("open", [rejected])); report.controls.ordinaryDriveSeparatorsAndRequestedIdentity = true; // An owned runtime's DELETE lease conflicts with a fresh parent admission. // This produces a genuine sharing failure after successful authority caching, // without another executable, and proves that no child runtime was created. const sharingParent = WindowsPrivateRuntime.create( workspace, "rea-sharing-parent-", ); try { await assert.rejects( PrivateRuntimeRoot.create({ parent: sharingParent.observation.path }), (failure) => { assert.ok(failure instanceof PrivateRuntimeRootUnavailableError); assert.equal(failure.retryable, true); assert.ok(failure.cause instanceof Error); assert.equal(failure.cause.win32Code, 32); assert.equal(failure.cause.runtimeAllocation, "not-started"); return true; }, ); assert.deepEqual(await readdir(sharingParent.observation.path), []); report.controls.transientRuntimeAdmissionBeforeAllocation = true; } finally { await sharingParent.close(); } const driveRoot = parse(workspace).root; const runtimeParent = ghidraSessionRoot({ base: join(driveRoot, ".Tmp", "scratch"), }); assert.equal(runtimeParent, driveRoot); const driveRootRuntime = native.call("runtime_create", [ runtimeParent, "rea-drive-root-", ]); try { assert.equal(driveRootRuntime.path.startsWith(`${driveRoot}\\`), false); assert.equal(dirname(driveRootRuntime.path), driveRoot); const snapshot = await native.call("runtime_snapshot", [ driveRootRuntime.handle, source, "probe.bin", ]); const sourceBytes = await readFile(source); assert.equal( snapshot.sha256, createHash("sha256").update(sourceBytes).digest("hex"), ); assert.equal(snapshot.source.requestedPath, source); const readback = native.call("runtime_open", [ driveRootRuntime.handle, "probe.bin", ]); try { assert.equal(readback.size, sourceBytes.byteLength); assert.deepEqual( native.call("read", [readback.handle, 0, 65536]), sourceBytes.subarray(0, 65536), ); } finally { native.call("close", [readback.handle]); } } finally { native.call("runtime_close", [driveRootRuntime.handle]); } assert.equal(await exists(driveRootRuntime.path), false); report.controls.driveRootRuntimeParent = true; const snapshotOwner = WindowsPrivateRuntime.create( workspace.replace(/\\/u, "/"), "single-flight-", ); try { const rejectedController = new AbortController(); const requestedSource = source.replaceAll("\\", "/"); const accepted = snapshotOwner.snapshot(requestedSource, "accepted.bin"); const rejected = snapshotOwner.snapshot( source, "rejected.bin", rejectedController.signal, ); rejectedController.abort(); await assert.rejects(rejected, /Runtime snapshot is still pending/u); const completed = await accepted; assert.equal(completed.source.requestedPath, requestedSource); assert.equal( completed.sha256, createHash("sha256") .update(await readFile(source)) .digest("hex"), ); assert.equal( await exists(join(snapshotOwner.observation.path, "rejected.bin")), false, ); report.controls.singleFlightCancellationOwnership = true; } finally { await snapshotOwner.close(); } const unrelatedFile = join(workspace, "unrelated-file"); await writeFile(unrelatedFile, "preserve unrelated writes"); const admitted = native.call("open", [source]); try { await assert.rejects( rename(sourceDirectory, `${sourceDirectory}-replacement`), ); await assert.rejects(open(source, "r+")); await rename(unrelatedFile, `${unrelatedFile}-renamed`); if (process.argv[3] !== undefined) { const observation = JSON.parse( execFileSync( resolve(process.argv[3]), ["reparse-directory", sourceDirectory, workspace], { encoding: "utf8" }, ), ); assert.equal( observation.reparseConversionDenied, true, "An admitted ancestor was converted into a junction.", ); report.controls.inPlaceAncestorReparseDenied = true; } assert.throws(() => native.call("read", [{}, 0, 1])); assert.throws(() => native.call("read", [admitted.handle, NaN, 1])); assert.equal(native.call("read", [admitted.handle, 0, 1])[0], 0x37); } finally { native.call("close", [admitted.handle]); } assert.throws(() => native.call("read", [admitted.handle, 0, 1])); const junction = join(workspace, "junction"); await symlink(sourceDirectory, junction, "junction"); assert.throws( () => native.call("open", [join(junction, "target.bin")]), /Reparse/u, ); assert.throws(() => native.call("open", [source + ":stream"])); const runtime = native.call("runtime_create", [ workspace.replaceAll("\\", "/"), "private root with spaces-", ]); const sentinel = join(sourceDirectory, "sentinel"); await writeFile(sentinel, "preserve"); try { const acl = JSON.parse( execFileSync( "powershell.exe", [ "-NoProfile", "-NonInteractive", "-Command", "$a=Get-Acl -LiteralPath $env:REA_TEST_PRIVATE_RUNTIME_PATH; $u=[Security.Principal.WindowsIdentity]::GetCurrent().User; @{protected=$a.AreAccessRulesProtected; ownerMatchesUser=($a.GetOwner([Security.Principal.SecurityIdentifier]).Value -eq $u.Value); trusteesOnlyUserAndSystem=(@($a.GetAccessRules($true,$true,[Security.Principal.SecurityIdentifier]) | Where-Object {$_.IdentityReference.Value -ne $u.Value -and $_.IdentityReference.Value -ne 'S-1-5-18'}).Count -eq 0); count=@($a.Access).Count} | ConvertTo-Json -Compress", ], { encoding: "utf8", // A pwsh caller can supply module paths incompatible with the // Windows PowerShell observer. Let that observer build its own path. env: { ...Object.fromEntries( Object.entries(process.env).filter( ([name]) => name.toLowerCase() !== "psmodulepath", ), ), REA_TEST_PRIVATE_RUNTIME_PATH: runtime.path, }, }, ), ); assert.deepEqual(acl, { protected: true, ownerMatchesUser: true, trusteesOnlyUserAndSystem: true, count: 2, }); native.call("runtime_mkdir", [runtime.handle, "inputs"]); native.call("runtime_write", [ runtime.handle, "descriptor.json", Buffer.from("fixture"), ]); assert.throws(() => native.call("runtime_write", [ runtime.handle, "descriptor.json", Buffer.from("replace"), ]), ); assert.throws(() => native.call("runtime_mkdir", [runtime.handle, "..\\escape"]), ); const pending = native.call("runtime_snapshot", [ runtime.handle, source, "inputs\\target.bin", ]); assert.ok(pending instanceof Promise); assert.throws( () => native.call("runtime_close", [runtime.handle]), /pending/u, ); const snapshot = await pending; assert.equal( snapshot.sha256, createHash("sha256") .update(await readFile(source)) .digest("hex"), ); assert.equal(snapshot.source.requestedPath, source); await assert.rejects( writeFile(join(runtime.path, "inputs", "target.bin"), "replace"), ); await symlink( sourceDirectory, join(runtime.path, "outside-junction"), "junction", ); const cancelled = native.call("runtime_snapshot", [ runtime.handle, source, "cancelled.bin", ]); native.call("runtime_snapshot_cancel", [runtime.handle]); await assert.rejects(cancelled, /cancelled/u); assert.equal(await exists(join(runtime.path, "cancelled.bin")), false); const readbackRuntime = WindowsPrivateRuntime.create( workspace.replaceAll("\\", "/"), "readback-", ); try { readbackRuntime.writeFile("written.txt", "runtime-write-readback"); assert.equal( readbackRuntime.readFile("written.txt"), "runtime-write-readback", ); const readbackSnapshot = await readbackRuntime.snapshot( source, "snapshot.bin", ); assert.equal( readbackSnapshot.sha256, createHash("sha256") .update(await readFile(source)) .digest("hex"), ); assert.equal( readbackRuntime.readFile("snapshot.bin"), await readFile(source, "utf8"), ); const writtenPath = join(readbackRuntime.observation.path, "written.txt"); await assert.rejects(writeFile(writtenPath, "replace")); await assert.rejects(rename(writtenPath, `${writtenPath}.renamed`)); await assert.rejects(rm(writtenPath)); assert.equal( readbackRuntime.readFile("written.txt"), "runtime-write-readback", ); const snapshotPath = join( readbackRuntime.observation.path, "snapshot.bin", ); // Java RandomAccessFile uses read/write sharing without delete sharing. // Exercise that independent Win32 reader contract without requiring Java. const readerDigest = execFileSync( "powershell.exe", [ "-NoProfile", "-NonInteractive", "-Command", "$ErrorActionPreference = 'Stop'; " + "$stream = [IO.File]::Open($env:REA_SNAPSHOT_READER_PATH, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite); " + "$hash = [Security.Cryptography.SHA256]::Create(); " + "try { [BitConverter]::ToString($hash.ComputeHash($stream)).Replace('-', '').ToLowerInvariant() } " + "finally { $hash.Dispose(); $stream.Dispose() }", ], { encoding: "utf8", timeout: 15_000, env: { ...process.env, REA_SNAPSHOT_READER_PATH: snapshotPath }, }, ).trim(); assert.equal(readerDigest, readbackSnapshot.sha256); await assert.rejects(writeFile(snapshotPath, "replace")); await assert.rejects(rename(snapshotPath, `${snapshotPath}.renamed`)); await assert.rejects(rm(snapshotPath)); assert.equal( readbackRuntime.readFile("snapshot.bin"), await readFile(source, "utf8"), ); report.controls = { ...report.controls, completedRuntimeFileReadback: true, completedRuntimeFileMutationDenied: true, snapshotReadWriteSharingReader: true, }; } finally { await readbackRuntime.close(); } const retryRuntime = WindowsPrivateRuntime.create( workspace, "cleanup-retry-", ); const heldPath = join(retryRuntime.observation.path, "snapshot.bin"); await retryRuntime.snapshot(source, "snapshot.bin"); const holder = spawn( "powershell.exe", [ "-NoProfile", "-NonInteractive", "-Command", "$ErrorActionPreference = 'Stop'; " + "$stream = [IO.File]::Open($env:REA_CLEANUP_HELD_PATH, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite); " + "try { [Console]::WriteLine('ready'); [Console]::In.ReadLine() | Out-Null } " + "finally { $stream.Dispose() }", ], { env: { ...process.env, REA_CLEANUP_HELD_PATH: heldPath }, stdio: ["pipe", "pipe", "pipe"], }, ); const holderClosed = once(holder, "close"); void holderClosed.catch(() => undefined); try { const [ready] = await once(holder.stdout, "data", { signal: AbortSignal.timeout(15_000), }); assert.equal(String(ready).trim(), "ready"); // The reader denies delete sharing. Cleanup must retain ownership when // its handle-relative open receives ERROR_SHARING_VIOLATION (32). await assert.rejects(retryRuntime.close(), { win32Code: 32 }); assert.equal( windowsPrivateRuntime(retryRuntime.observation.path), retryRuntime, ); assert.equal(await exists(heldPath), true); assert.throws( () => retryRuntime.writeFile("after-close.txt", "forbidden"), /cleanup is pending/u, ); holder.stdin.end("\n"); const [exitCode] = await holderClosed; assert.equal(exitCode, 0); await retryRuntime.close(); await retryRuntime.close(); assert.equal(await exists(retryRuntime.observation.path), false); assert.throws( () => windowsPrivateRuntime(retryRuntime.observation.path), /No native private runtime/u, ); report.controls.cleanupFailureRetainsOwnershipForRetry = true; } finally { holder.kill(); await holderClosed.catch(() => undefined); await retryRuntime.close(); } report.controls = { ...report.controls, protectedDaclReadback: true, sourceReplacementDenied: true, sourceWriteDenied: true, unrelatedFilesystemRenamePreserved: true, junctionAdmissionDenied: true, alternateStreamsDenied: true, forgedAndClosedHandlesDenied: true, immutableSnapshotDigest: true, asynchronousSnapshot: true, snapshotCancellation: true, }; } finally { native.call("runtime_close", [runtime.handle]); } assert.equal(await exists(runtime.path), false); assert.equal(await readFile(sentinel, "utf8"), "preserve"); report.controls.cleanupDoesNotTraverseJunctions = true; const fixture = join(workspace, "tree.mjs"); await writeFile( fixture, `import {spawn} from 'node:child_process'; import {writeFileSync} from 'node:fs'; const depth=Number(process.argv[2]); writeFileSync(process.argv[3]+depth,String(process.pid)); if(depth>0)spawn(process.execPath,[import.meta.filename,String(depth-1),process.argv[3]],{detached:true,stdio:'ignore'}); setInterval(()=>{},1000);\n`, ); const pidPrefix = join(workspace, "pid-"); const child = launch(["--max-old-space-size=128", fixture, "2", pidPrefix]); const unrelated = spawn( process.execPath, ["--max-old-space-size=128", "-e", "setInterval(()=>{},1000)"], { stdio: "ignore" }, ); try { for ( let attempt = 0; attempt < 200 && !(await exists(pidPrefix + "0")); attempt++ ) await delay(); const pids = await Promise.all( [0, 1, 2].map(async (depth) => Number(await readFile(pidPrefix + depth, "utf8")), ), ); assert.ok(native.call("process_poll", [child.handle]).activeProcesses >= 3); native.call("process_terminate", [child.handle]); assert.equal((await wait(child)).activeProcesses, 0); assert.equal(pids.some(live), false); assert.ok(unrelated.pid !== undefined && live(unrelated.pid)); report.processes.descendantsAndDetachedDescendantsTerminated = true; report.processes.unrelatedProcessPreserved = true; } finally { native.call("process_terminate", [child.handle]); await wait(child); native.call("process_close", [child.handle]); if (unrelated.exitCode === null) { const closed = new Promise((resolve) => unrelated.once("close", resolve)); unrelated.kill(); await closed; } } const ownerClose = launch([ "--max-old-space-size=128", fixture, "0", join(workspace, "owner-close-"), ]); native.call("process_close", [ownerClose.handle]); for (let attempt = 0; attempt < 100 && live(ownerClose.pid); attempt++) await delay(); assert.equal(live(ownerClose.pid), false); report.processes.killOnOwnerClose = true; report.processes.protocolInput = await verifyWindowsProtocolInput( packageRoot, workspace, ); report.processes.jobMemoryLimit = await verifyWindowsJobMemoryLimit( packageRoot, workspace, ); const exited = launch([ "--max-old-space-size=128", "-e", "console.log('observed');process.exit(7)", ]); const settled = await wait(exited); assert.equal(settled.exitCode, 7); assert.match(settled.output, /observed/u); native.call("process_close", [exited.handle]); report.processes.normalExitAndOutput = true; const forwardCommand = process.execPath.replaceAll("\\", "/"); const forwardProcess = native.call("process_spawn", [ forwardCommand, [forwardCommand, "-e", "console.log('forward executable')"] .map(quote) .join(" "), workspace, environment, ]); try { const completed = await wait(forwardProcess); assert.equal(completed.exitCode, 0); assert.match(completed.output, /forward executable/u); report.processes.ordinaryDriveSeparators = true; } finally { native.call("process_close", [forwardProcess.handle]); } const boundaryFixture = process.argv[3]; if (boundaryFixture !== undefined) { const before = JSON.parse( execFileSync(boundaryFixture, [], { encoding: "utf8" }), ); const boundary = native.call("process_spawn", [ boundaryFixture, `${quote(boundaryFixture)} breakaway`, workspace, environment, ]); const denied = await wait(boundary); native.call("process_close", [boundary.handle]); assert.equal(JSON.parse(denied.output).breakawayDenied, true); const tokenChild = native.call("process_spawn", [ boundaryFixture, quote(boundaryFixture), workspace, environment, ]); const observed = await wait(tokenChild); native.call("process_close", [tokenChild.handle]); assert.equal(JSON.parse(observed.output).defaultOwnerIsUser, true); const after = JSON.parse( execFileSync(boundaryFixture, [], { encoding: "utf8" }), ); assert.deepEqual(after, before); report.processes.breakawayDenied = true; report.processes.childOwnerNormalizedWithoutChangingCaller = true; report.callerToken = before; const environmentChild = native.call("process_spawn", [ boundaryFixture, `${quote(boundaryFixture)} environment`, workspace, [ "z_REA=z", "_REA=underscore", "A_REA=a", "REA_CASE=first", "rea_case=last", "REA_ß=sharp", "REA_SS=double", ], ]); const childEnvironment = await wait(environmentChild); native.call("process_close", [environmentChild.handle]); assert.deepEqual(JSON.parse(childEnvironment.output), { ordinallySorted: true, lastDuplicateSelected: true, unicodeNamesPreserved: true, }); report.processes.windowsEnvironmentSemantics = true; // Observed through this process's own id: a separate probe process would // get its own processor group, so it cannot stand in for the process that // spawns the child. const callerAffinity = JSON.parse( execFileSync(boundaryFixture, ["affinity", String(process.pid)], { encoding: "utf8", }), ); const affinityChild = native.call("process_spawn", [ boundaryFixture, `${quote(boundaryFixture)} affinity`, workspace, environment, ]); const observedAffinity = await wait(affinityChild); native.call("process_close", [affinityChild.handle]); assert.equal(observedAffinity.exitCode, 0); const childAffinity = JSON.parse(observedAffinity.output); // Masks cross as hexadecimal strings because a mask can exceed the // safe-integer range. Sharing one processor group makes the caller's mask // applicable, so it must be inherited exactly. Windows placing the child in // another group is only permitted when the caller asked for no bound of its // own, which its group's whole active set establishes; a narrower mask has // to fail the spawn rather than widen to that group's default. const sharedGroup = callerAffinity.singleProcessorGroup && childAffinity.singleProcessorGroup && callerAffinity.processorGroup === childAffinity.processorGroup; if (sharedGroup) assert.equal(childAffinity.affinityMask, callerAffinity.affinityMask); else assert.equal(callerAffinity.affinityMask, callerAffinity.systemMask); report.processes.callerAffinityBoundsOwnedProcessOrRefusesToWiden = true; report.callerAffinity = { ...callerAffinity, sharedGroupWithChild: sharedGroup, }; } const ownerFixture = join(workspace, "owner.mjs"); const ownerPidFile = join(workspace, "crash-child.pid"); const moduleUrl = pathToFileURL( join(packageRoot, "dist/windows/WindowsNativeLoader.js"), ).href; await writeFile( ownerFixture, `import {writeFileSync} from 'node:fs'; import {requireWindowsNativeAuthority} from ${JSON.stringify(moduleUrl)}; const native=requireWindowsNativeAuthority(); const env=Object.entries(process.env).map(([k,v])=>k+'='+v); const child=native.call('process_spawn',[process.execPath,${JSON.stringify([process.execPath, "--max-old-space-size=128", fixture, "0", join(workspace, "crash-descendant-")].map(quote).join(" "))},${JSON.stringify(workspace)},env]); writeFileSync(${JSON.stringify(ownerPidFile)},String(child.pid));setInterval(()=>{},1000);\n`, ); const owner = spawn( process.execPath, ["--max-old-space-size=128", ownerFixture], { stdio: "ignore" }, ); try { for ( let attempt = 0; attempt < 200 && !(await exists(ownerPidFile)); attempt++ ) await delay(); const pid = Number(await readFile(ownerPidFile, "utf8")); const closed = new Promise((resolve) => owner.once("close", resolve)); owner.kill("SIGKILL"); await closed; for (let attempt = 0; attempt < 100 && live(pid); attempt++) await delay(); assert.equal(live(pid), false); report.processes.ownerForcedExitKillsOwnedChild = true; } finally { if (owner.exitCode === null && owner.signalCode === null) { const closed = new Promise((resolve) => owner.once("close", resolve)); owner.kill("SIGKILL"); await closed; } } report.ok = true; if (process.argv[4] !== undefined) await writeFile(process.argv[4], `${JSON.stringify(report)}\n`); process.stdout.write(`${JSON.stringify(report)}\n`); } catch (cause) { console.error( "Native conformance failed", cause.code ?? cause.name, cause.constraint ?? "assertion", ); throw cause; } finally { await rm(workspace, { recursive: true, force: true }).catch((cause) => console.error("Fixture cleanup failed", cause.code), ); }