Files
rea/src/native/NativeUiHelperRuntime.ts
T
morluto e7f54b3310 refactor(runtime): centralize safe JSON parsing and preserve error causes (#629)
* refactor(domain): consolidate canonical ordering and digest helpers (#624)

* refactor(domain): consolidate canonical ordering and digest helpers

Single owner for code-point ordering (domain/canonicalOrdering.ts)
and canonical JSON digests (domain/comparisonSemantics.ts). Delete
all local compareCodePoints/compareText/digestCanonical duplicates
and migrate every importer. No re-export shims.

* fix(ci): allow slower real browser startup

* chore(config): remove dead eslint, dedupe scripts, cacheable turbo tasks

Delete eslint.config.js (oxlint is the linter), drop lint:dead alias,
pin smol-toml, fold jscpd/scan:todos into check:pr, make test:run
cacheable, align oxlint ignores.

* fix(config): hash all test inputs for cached runs

* docs: fix architecture diagram and pretty-print tool catalog

Drop dangling REPLAY edges, add dotnet/reference/error/evaluation
nodes. Emit 2-space JSON from the catalog generator and regenerate.

* test: extract shared fixtures, drop knip carve-outs

Dedupe android/apple session tests, bundler adapter headers, and
reconstruction helpers into tests/support fixtures. Delete unused
type aliases and the knip ignoreIssues block. Lower jscpd threshold
2.7 to 2.5.

* refactor(app): split Setup and ProcessOwnership modules

Extract SetupTypes/SetupHost from Setup.ts and move observation
helpers into ProcessOwnershipObservation/ProcessTree. Migrate all
importers including CLI commands. No re-export shims.

* refactor(runtime): centralize safe JSON parsing and preserve error causes

Add domain/safeJson.safeParseJson and migrate all raw JSON.parse
call sites. Name catch causes and preserve failure reasons instead
of swallowing; annotate genuine best-effort cleanup.

* fix(runtime): retain JSON parse error causes
2026-10-06 05:00:54 +08:00

60 lines
1.8 KiB
TypeScript

import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import { execFileOutput } from "../process/ExecFileOutput.js";
import { safeParseJson } from "../domain/safeJson.js";
import type { NativeUiHelper } from "./NativeUiObservation.js";
/** Lazily compile one owned helper per observation/scenario and remove its compiler cache. */
export const createNativeUiHelperRuntime = () => {
let root: string | undefined;
let executable: string | undefined;
const invoke: NativeUiHelper = async (parameters, signal) => {
if (executable === undefined) {
root = await mkdtemp(join(tmpdir(), "rea-native-ui-"));
const output = join(root, "observer");
await execFileOutput(
"/usr/bin/xcrun",
[
"swiftc",
"-module-cache-path",
join(root, "modules"),
fileURLToPath(
new URL("../../bridge/native/ReaNativeUI.swift", import.meta.url),
),
"-o",
output,
],
{
timeout: 60_000,
maxBuffer: 1024 * 1024,
...(signal === undefined ? {} : { signal }),
},
);
executable = output;
}
const output = await execFileOutput(
executable,
[JSON.stringify(parameters)],
{
timeout: 30_000,
maxBuffer: 16 * 1024 * 1024,
...(signal === undefined ? {} : { signal }),
},
);
const parsed = safeParseJson(output.stdout);
if (!parsed.ok)
throw new Error(`Native helper returned invalid JSON: ${parsed.error}`, {
cause: parsed.cause,
});
return parsed.value;
};
return {
invoke,
close: async () => {
if (root !== undefined) await rm(root, { recursive: true, force: true });
},
};
};