xit-wasm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts ADDED
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Public entry point.
3
+ *
4
+ * The headline API is the `Archive` class — a pure in-memory, browser-safe
5
+ * wrapper that hides every wasm/host/file detail. It's what plastron uses.
6
+ *
7
+ * The lower-level loader below (`load`) is kept for the existing smoke tests
8
+ * and any consumer who wants to drive the wasm directly. Most users want
9
+ * `Archive`.
10
+ */
11
+
12
+ export { Archive, setDefaultWasmSource } from "./archive.ts";
13
+ export type { CommitOptions, LoadOptions, WasmSource } from "./archive.ts";
14
+
15
+ import { hostImports } from "./host.ts";
16
+ import type { Host } from "./host.ts";
17
+
18
+ export interface XitInstance {
19
+ memory: WebAssembly.Memory;
20
+ abiVersion(): number;
21
+ initRepo(absPath: string): number;
22
+ smokeInitAddCommit(absPath: string): number;
23
+ smokeXitInitAddCommit(absPath: string): number;
24
+ }
25
+
26
+ interface RawExports {
27
+ memory: WebAssembly.Memory;
28
+ xit_abi_version(): number;
29
+ xit_init_repo(pathPtr: number, pathLen: number): number;
30
+ xit_smoke_init_add_commit(pathPtr: number, pathLen: number): number;
31
+ xit_smoke_xit_init_add_commit(pathPtr: number, pathLen: number): number;
32
+ xit_probe_host_io(): number;
33
+ }
34
+
35
+ /**
36
+ * Load and instantiate the xit wasm module against a host implementation.
37
+ * The host provides the 24 backing functions the wasm imports — see
38
+ * src/host.ts for the surface.
39
+ *
40
+ * Note: the wasm module currently has no host-side allocation hook. Every
41
+ * call that takes a path/buffer needs to copy the bytes into wasm linear
42
+ * memory before invoking. This is fine for a spike but a real binding
43
+ * would expose `xit_alloc` and `xit_free` from the wasm side and stage
44
+ * arguments through them.
45
+ *
46
+ * For now we sneak path bytes into a fixed scratch region inside the
47
+ * wasm's memory. Wasm pages are 64 KiB; the linker reserves the first
48
+ * page for stack + globals. We borrow the second page (offset 65536+)
49
+ * for path scratch — outside any compile-time-allocated symbols. This is
50
+ * a HACK for spike testing only.
51
+ */
52
+ const SCRATCH_OFFSET = 1 << 16; // start of page 1
53
+ const SCRATCH_SIZE = 4096;
54
+
55
+ export async function load(wasmPath: string, host: Host): Promise<XitInstance> {
56
+ // Dynamic import keeps the entry module browser-clean. `load()` is a
57
+ // Node-only smoke-test helper; bundlers that statically analyze a top-
58
+ // level `node:fs/promises` import would mark the whole module as
59
+ // node-only and fail to ship a browser build of the headline `Archive`
60
+ // API alongside it. The runtime-built specifier + @vite-ignore also
61
+ // suppresses Vite's "externalized for browser compatibility" warning
62
+ // for downstream consumers — `load()` is never reachable from a
63
+ // browser build path so the warning would be noise.
64
+ const nodeFsSpecifier = "node:fs/promises";
65
+ const fs = await import(/* @vite-ignore */ nodeFsSpecifier);
66
+ const bytes = await fs.readFile(wasmPath);
67
+ const mod = await WebAssembly.compile(bytes);
68
+
69
+ let memory!: WebAssembly.Memory;
70
+ const imports = hostImports(host, () => memory);
71
+
72
+ const inst = await WebAssembly.instantiate(mod, imports);
73
+ const exp = inst.exports as unknown as RawExports;
74
+ memory = exp.memory;
75
+
76
+ const enc = new TextEncoder();
77
+ const writeScratch = (s: string): { ptr: number; len: number } => {
78
+ const bytes = enc.encode(s);
79
+ if (bytes.length > SCRATCH_SIZE) throw new Error("path too long for scratch buffer");
80
+ new Uint8Array(memory.buffer, SCRATCH_OFFSET, bytes.length).set(bytes);
81
+ return { ptr: SCRATCH_OFFSET, len: bytes.length };
82
+ };
83
+
84
+ return {
85
+ memory,
86
+ abiVersion: () => exp.xit_abi_version(),
87
+ initRepo(absPath: string) {
88
+ const { ptr, len } = writeScratch(absPath);
89
+ return exp.xit_init_repo(ptr, len);
90
+ },
91
+ smokeInitAddCommit(absPath: string) {
92
+ const { ptr, len } = writeScratch(absPath);
93
+ return exp.xit_smoke_init_add_commit(ptr, len);
94
+ },
95
+ smokeXitInitAddCommit(absPath: string) {
96
+ const { ptr, len } = writeScratch(absPath);
97
+ return exp.xit_smoke_xit_init_add_commit(ptr, len);
98
+ },
99
+ };
100
+ }
package/xit.wasm ADDED
Binary file