import { afterEach, beforeEach, describe, it } from "@std/testing/bdd";
import { expect } from "@std/expect";
import { Identity } from "@commonfabric/identity";
import { popFrame, pushFrame } from "../src/builder/pattern.ts";
import type { Pattern } from "../src/builder/types.ts";
import type { RuntimeProgram } from "../src/harness/types.ts";
import { parseLink } from "../src/link-utils.ts";
import { Runtime } from "../src/runtime.ts";
import { StorageManager } from "../src/storage/cache.deno.ts";
const signer = await Identity.fromPassphrase("module evaluation frame");
const home = signer.did();
const elsewhere =
(await Identity.fromPassphrase("module evaluation frame elsewhere"))
.did();
// A pattern whose body mints an internal cell and binds it into its UI, the
// shape of home.tsx's `defaultAppUrl` and `activeTab`.
const PROGRAM: RuntimeProgram = {
main: "/main.tsx",
files: [{
name: "/main.tsx",
contents: [
"import { NAME, UI, pattern, Writable } from 'commonfabric';",
"export default pattern(() => {",
" const draft = new Writable('').for('draft');",
" return {",
" [NAME]: 'draft holder',",
" [UI]: ,",
" };",
"});",
].join("\n"),
}],
};
describe("module evaluation frame", () => {
let storageManager: ReturnType;
let runtime: Runtime;
beforeEach(() => {
storageManager = StorageManager.emulate({ as: signer });
runtime = new Runtime({
apiUrl: new URL(import.meta.url),
storageManager,
});
});
afterEach(async () => {
await runtime.dispose();
await storageManager.close();
});
it("does not take the space of an action suspended beneath it", async () => {
// An awaiting handler keeps its frame on the stack, and a module can be
// evaluated while it waits. Cells the pattern body mints belong to each
// instance, so they must not be bound to the waiting handler's space.
const suspendedTx = runtime.edit();
const suspended = pushFrame({
runtime,
space: elsewhere,
tx: suspendedTx,
cause: "suspended handler",
inHandler: true,
});
let pattern: Pattern;
try {
const { main } = await runtime.harness.compileAndEvaluateModules(
PROGRAM,
);
pattern = (main as { default: Pattern }).default;
} finally {
popFrame(suspended);
suspendedTx.abort();
}
const result = runtime.getCell(
home,
"module evaluation frame result",
);
await runtime.runSynced(result, pattern, {});
const rendered = result.getRaw() as {
$UI: { props: { $value: unknown } };
};
const bound = parseLink(rendered.$UI.props.$value, result);
expect(bound?.space).toBe(home);
});
});