import { type RuntimeVFS } from '../../vfs.ts'; import type { SetAttrFields } from '../../../types.ts'; /** * One guest mutation, recorded in the order the script performed it. * `write` and `append` carry their bytes because the drain runs after the * script returns, when the filesystem holds only the final state: an * atomic-write (write a temp file, rename it into place) would otherwise * replay as a read of a path the rename already moved. */ export type MirageMutation = { readonly kind: 'write'; readonly path: string; readonly bytes: Uint8Array; } | { readonly kind: 'append'; readonly path: string; readonly bytes: Uint8Array; } | { readonly kind: 'mkdir'; readonly path: string; } | { readonly kind: 'unlink'; readonly path: string; } | { readonly kind: 'rmdir'; readonly path: string; } | { readonly kind: 'rename'; readonly path: string; readonly dst: string; } | { readonly kind: 'symlink'; readonly path: string; readonly target: string; } | { readonly kind: 'setattr'; readonly path: string; readonly attrs: SetAttrFields; }; /** * The write-ahead log a pyodide guest records into. * * Every mark is deliberately synchronous: the guest's close(), os.mkdir() * and os.rename() run inside sync WASM frames where awaiting a mount op * needs JSPI stack switching, which most engines do not enable. The guest * records here and the runtime replays after the script returns, where * awaiting is free. This is the one thing pyodide needs that the other * runtimes do not: quickjs suspends at the call and monty runs the op on * its own worker. */ export interface MutationJournal { /** * Args: * path: mount-prefixed path the mutation names. * bytes: the whole file for a write, the new tail for an append. */ markWrite(path: string, bytes: Uint8Array): void; markAppend(path: string, bytes: Uint8Array): void; markMkdir(path: string): void; markUnlink(path: string): void; markRmdir(path: string): void; markRename(src: string, dst: string): void; /** * Args: * path: guest-absolute path of the link. * target: what it points at, stored verbatim. */ markSymlink(path: string, target: string): void; /** * Args: * path: guest-absolute path whose metadata changed. * attrs: only the fields the guest wrote, already in the op's own * terms (ISO stamps), because the unit Emscripten passes is the * caller's fact and not the journal's. */ markSetattr(path: string, attrs: SetAttrFields): void; /** Drain the journal: every mutation in guest order, cleared. */ takeMutations(): MirageMutation[]; } export declare function createJournal(): MutationJournal; /** * Replay one recorded guest mutation against the mounts. * * Args: * vfs: the runtime's mount vocabulary to apply through. * mutation: the journal entry to apply. */ export declare function applyMutation(vfs: RuntimeVFS, mutation: MirageMutation): Promise; //# sourceMappingURL=journal.d.ts.map