chore(vendor): import pi 1.3.0

Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
alexion committed 2026-10-15 17:58:48 -04:00
1 parent 719370c8f7
commit 6081e3e325
1743 files changed
+205459 -131704

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
// A link wrapper that counts what crosses it, per direction: frames by type and bytes (JSON text length). It can also
// hold back the acknowledgements its own side sends (`paused`), to fill the peer's flow-control window.
import type { Frame, Link } from "../../src/index.ts";
export class CountingLink implements Link {
readonly inner: Link;
/** Frames this side sent, in order. */
readonly sent: Frame[] = [];
/** Frames this side received, in order. */
readonly received: Frame[] = [];
sentBytes = 0;
receivedBytes = 0;
/** Acknowledgements are held back (the peer's window fills up). */
paused = false;
#held: Frame | undefined;
constructor(inner: Link) {
this.inner = inner;
}
get closed(): boolean {
return this.inner.closed;
}
send(frame: Frame): number | undefined {
if (frame.t === "ack" && this.paused) {
this.#held = frame;
return 0;
}
this.sent.push(frame);
this.sentBytes += JSON.stringify(frame).length;
return this.inner.send(frame);
}
/** Lets the held acknowledgement through and stops holding them. */
release(): void {
this.paused = false;
const held = this.#held;
this.#held = undefined;
if (held !== undefined) this.inner.send(held);
}
receive(handler: (frame: Frame) => void): void {
this.inner.receive((frame) => {
this.received.push(frame);
this.receivedBytes += JSON.stringify(frame).length;
handler(frame);
});
}
onClose(handler: (reason: string) => void): void {
this.inner.onClose(handler);
}
close(reason?: string): void {
this.inner.close(reason);
}
/** Frames of type `t` this side sent (`sent`) or received (`received`). */
count(direction: "sent" | "received", t: Frame["t"]): number {
return this[direction].filter((frame) => frame.t === t).length;
}
/** Frames this side sent or received, except pings, pongs and acknowledgements. */
traffic(direction: "sent" | "received"): Frame[] {
return this[direction].filter((frame) => frame.t !== "ping" && frame.t !== "pong" && frame.t !== "ack");
}
}
export type StateFrame = Extract<Frame, { t: "state" }>;
export const stateFrames = (frames: readonly Frame[]): StateFrame[] =>
frames.filter((frame): frame is StateFrame => frame.t === "state");
+11
View File
@@ -0,0 +1,11 @@
import { Type } from "typebox";
import { hostNamed, method, remote } from "../../src/index.ts";
export const Echo = remote("t.echo", {
version: 1,
input: Type.Object({}),
host: hostNamed("w1"),
variants: {
main: { methods: { echo: method(Type.String(), Type.String()), pid: method(undefined, Type.Number()) } },
},
});
+81
View File
@@ -0,0 +1,81 @@
// Runs the node loader outside vitest: its module runner bypasses the Node resolve hooks the loader installs.
import assert from "node:assert/strict";
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { Type } from "typebox";
import { createHost, local, method } from "../../src/index.ts";
import { nodeLoader } from "../../src/loader.ts";
// Plugin modules live under the package so bare imports (typebox) resolve; removed afterwards.
const dir = fileURLToPath(new URL(`../.tmp-plugins-${process.pid}/`, import.meta.url));
// Separate from `dir`, which becomes a reload root once its facet loads.
const plugins = fileURLToPath(new URL(`../.tmp-plugins-${process.pid}-order/`, import.meta.url));
const chord = new URL("../../src/index.ts", import.meta.url).href;
// The test's own copy of the plugin's contract: binding is by description, not object identity.
const Hello = local("t.hello", {
version: 1,
input: Type.Object({}),
members: { greet: method(Type.String(), Type.String()) },
});
const facetSource = `
import { Type } from "typebox";
import { defineFacet, local, method } from ${JSON.stringify(chord)};
import { greeting } from "./greeting.ts";
const Hello = local("t.hello", {
version: 1,
input: Type.Object({}),
members: { greet: method(Type.String(), Type.String()) },
});
export default defineFacet((host) => {
host.serve(Hello, () => ({ greet: (name) => greeting + " " + name }));
});
`;
const writeGreeting = (text: string) =>
writeFileSync(`${dir}greeting.ts`, `export const greeting = ${JSON.stringify(text)};\n`);
try {
mkdirSync(dir, { recursive: true });
writeFileSync(`${dir}facet.ts`, facetSource);
writeGreeting("v1");
const host = createHost({ self: { kind: "host" }, loader: nodeLoader, onError: () => {} });
await host.load([`${dir}facet.ts`]);
const ref = host.hold(Hello, {});
assert.equal(await ref.greet("x"), "v1 x");
writeGreeting("v2");
const report = await host.reload([`${dir}facet.ts`]);
assert.deepEqual(report.changed, ["t.hello"]);
assert.equal(await ref.greet("x"), "v2 x");
await host.close();
// A facet listed first that imports a later facet's directory shares that facet's copy of the module.
const Shared = local("t.shared", {
version: 1,
input: Type.Object({}),
members: { same: method(undefined, Type.Boolean()) },
});
mkdirSync(`${plugins}a`, { recursive: true });
mkdirSync(`${plugins}b`, { recursive: true });
writeFileSync(`${plugins}b/state.ts`, "export const state = {};\n");
writeFileSync(
`${plugins}b/facet.ts`,
`import { defineFacet } from ${JSON.stringify(chord)};\nimport { state } from "./state.ts";\nexport const own = state;\nexport default defineFacet(() => {});\n`,
);
writeFileSync(
`${plugins}a/facet.ts`,
`import { Type } from "typebox";\nimport { defineFacet, local, method } from ${JSON.stringify(chord)};\nimport { state } from "../b/state.ts";\n` +
`const Shared = local("t.shared", { version: 1, input: Type.Object({}), members: { same: method(undefined, Type.Boolean()) } });\n` +
`export default defineFacet((host) => host.serve(Shared, () => ({ same: async () => (await import(new URL("../b/facet.ts", import.meta.url).href)).own === state })));\n`,
);
const ordered = createHost({ self: { kind: "host" }, loader: nodeLoader, onError: () => {} });
await ordered.load([`${plugins}a/facet.ts`, `${plugins}b/facet.ts`]);
assert.equal(await ordered.hold(Shared, {}).same(), true);
await ordered.close();
} finally {
rmSync(dir, { recursive: true, force: true });
rmSync(plugins, { recursive: true, force: true });
}
+41
View File
@@ -0,0 +1,41 @@
// Child host for manager tests. FIXTURE_MODE: normal | ignore-shutdown | fatal.
import { spawn } from "node:child_process";
import { writeFileSync } from "node:fs";
import { createHost, type IpcChannel, ipcLink } from "../../src/index.ts";
import { childControl } from "../../src/manager.ts";
import { Echo } from "./echo.ts";
const mode = process.env.FIXTURE_MODE ?? "normal";
const control = childControl();
if (mode === "fatal") {
control.fatal(new Error("fixture refuses to start"));
setTimeout(() => process.exit(1), 200);
} else {
// Before anything that owns data: the kernel lock (if the manager configured one).
await control.lock().catch(() => {
setTimeout(() => process.exit(1), 200);
return new Promise<never>(() => {});
});
const host = createHost({
self: { kind: "host" },
name: process.env.HOST_NAME ?? "worker",
upstream: { link: ipcLink(process as unknown as IpcChannel), principal: { kind: "server" } },
onError: () => {},
});
const init = (await control.init) as { greeting: string };
host.serve(Echo, () => ({
variant: "main",
echo: (text: string) => `${init.greeting} ${text} from ${process.pid}`,
pid: () => process.pid,
}));
if (process.env.GRANDCHILD_FILE) {
const grandchild = spawn(process.execPath, ["-e", "setInterval(() => {}, 1000)"], { stdio: "ignore" });
writeFileSync(process.env.GRANDCHILD_FILE, String(grandchild.pid));
}
control.onShutdown(async () => {
if (mode === "ignore-shutdown") return;
await host.close();
process.exit(0);
});
control.ready();
}