@volter/browser-wali 0.1.5 → 0.1.6

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.
Files changed (158) hide show
  1. package/README.md +73 -0
  2. package/dist/browser-wali-command.d.ts +3 -0
  3. package/dist/browser-wali-command.d.ts.map +1 -1
  4. package/dist/browser-wali-command.js +2 -1
  5. package/dist/browser-wali-command.js.map +1 -1
  6. package/dist/capabilities.d.ts +73 -1
  7. package/dist/capabilities.d.ts.map +1 -1
  8. package/dist/capabilities.js +86 -2
  9. package/dist/capabilities.js.map +1 -1
  10. package/dist/child-processes.d.ts +24 -0
  11. package/dist/child-processes.d.ts.map +1 -0
  12. package/dist/child-processes.js +134 -0
  13. package/dist/child-processes.js.map +1 -0
  14. package/dist/codec-protocol.d.ts +66 -0
  15. package/dist/codec-protocol.d.ts.map +1 -0
  16. package/dist/codec-protocol.js +59 -0
  17. package/dist/codec-protocol.js.map +1 -0
  18. package/dist/codec-remote.d.ts +33 -0
  19. package/dist/codec-remote.d.ts.map +1 -0
  20. package/dist/codec-remote.js +190 -0
  21. package/dist/codec-remote.js.map +1 -0
  22. package/dist/codec-worker.d.ts +2 -0
  23. package/dist/codec-worker.d.ts.map +1 -0
  24. package/dist/codec-worker.js +438 -0
  25. package/dist/codec-worker.js.map +1 -0
  26. package/dist/coherent-file-locks.d.ts.map +1 -1
  27. package/dist/coherent-file-locks.js +17 -5
  28. package/dist/coherent-file-locks.js.map +1 -1
  29. package/dist/descriptors.d.ts +49 -0
  30. package/dist/descriptors.d.ts.map +1 -0
  31. package/dist/descriptors.js +115 -0
  32. package/dist/descriptors.js.map +1 -0
  33. package/dist/events.d.ts.map +1 -1
  34. package/dist/events.js +2 -2
  35. package/dist/events.js.map +1 -1
  36. package/dist/filesystem-protocol.d.ts +28 -1
  37. package/dist/filesystem-protocol.d.ts.map +1 -1
  38. package/dist/filesystem-protocol.js +18 -0
  39. package/dist/filesystem-protocol.js.map +1 -1
  40. package/dist/filesystem-remote.d.ts +26 -2
  41. package/dist/filesystem-remote.d.ts.map +1 -1
  42. package/dist/filesystem-remote.js +132 -23
  43. package/dist/filesystem-remote.js.map +1 -1
  44. package/dist/filesystem-worker.js +274 -34
  45. package/dist/filesystem-worker.js.map +1 -1
  46. package/dist/filesystem.d.ts +30 -1
  47. package/dist/filesystem.d.ts.map +1 -1
  48. package/dist/filesystem.js +180 -50
  49. package/dist/filesystem.js.map +1 -1
  50. package/dist/fork-worker.d.ts +2 -0
  51. package/dist/fork-worker.d.ts.map +1 -0
  52. package/dist/fork-worker.js +52 -0
  53. package/dist/fork-worker.js.map +1 -0
  54. package/dist/host.d.ts +36 -0
  55. package/dist/host.d.ts.map +1 -0
  56. package/dist/host.js +153 -0
  57. package/dist/host.js.map +1 -0
  58. package/dist/loopback-host.d.ts +25 -1
  59. package/dist/loopback-host.d.ts.map +1 -1
  60. package/dist/loopback-host.js +447 -13
  61. package/dist/loopback-host.js.map +1 -1
  62. package/dist/memory.d.ts +65 -2
  63. package/dist/memory.d.ts.map +1 -1
  64. package/dist/memory.js +306 -49
  65. package/dist/memory.js.map +1 -1
  66. package/dist/module-layout.d.ts +2 -0
  67. package/dist/module-layout.d.ts.map +1 -1
  68. package/dist/module-layout.js +4 -2
  69. package/dist/module-layout.js.map +1 -1
  70. package/dist/monotonic-clock.d.ts +12 -0
  71. package/dist/monotonic-clock.d.ts.map +1 -0
  72. package/dist/monotonic-clock.js +14 -0
  73. package/dist/monotonic-clock.js.map +1 -0
  74. package/dist/network-protocol.d.ts +12 -1
  75. package/dist/network-protocol.d.ts.map +1 -1
  76. package/dist/network-protocol.js +6 -0
  77. package/dist/network-protocol.js.map +1 -1
  78. package/dist/network-worker.js +149 -20
  79. package/dist/network-worker.js.map +1 -1
  80. package/dist/network.d.ts +15 -3
  81. package/dist/network.d.ts.map +1 -1
  82. package/dist/network.js +74 -39
  83. package/dist/network.js.map +1 -1
  84. package/dist/process-adapter.d.ts +4 -1
  85. package/dist/process-adapter.d.ts.map +1 -1
  86. package/dist/process-adapter.js +3 -3
  87. package/dist/process-adapter.js.map +1 -1
  88. package/dist/process-bridge.d.ts +43 -0
  89. package/dist/process-bridge.d.ts.map +1 -1
  90. package/dist/process-bridge.js +30 -1
  91. package/dist/process-bridge.js.map +1 -1
  92. package/dist/program.d.ts +60 -1
  93. package/dist/program.d.ts.map +1 -1
  94. package/dist/program.js +92 -31
  95. package/dist/program.js.map +1 -1
  96. package/dist/runtime.d.ts.map +1 -1
  97. package/dist/runtime.js +491 -134
  98. package/dist/runtime.js.map +1 -1
  99. package/dist/select.d.ts +16 -0
  100. package/dist/select.d.ts.map +1 -0
  101. package/dist/select.js +100 -0
  102. package/dist/select.js.map +1 -0
  103. package/dist/shared-pipes.d.ts +17 -6
  104. package/dist/shared-pipes.d.ts.map +1 -1
  105. package/dist/shared-pipes.js +94 -70
  106. package/dist/shared-pipes.js.map +1 -1
  107. package/dist/signals.d.ts +48 -0
  108. package/dist/signals.d.ts.map +1 -0
  109. package/dist/signals.js +232 -0
  110. package/dist/signals.js.map +1 -0
  111. package/dist/snapshot-filesystem.d.ts +128 -2
  112. package/dist/snapshot-filesystem.d.ts.map +1 -1
  113. package/dist/snapshot-filesystem.js +481 -53
  114. package/dist/snapshot-filesystem.js.map +1 -1
  115. package/dist/spawn-policy.d.ts +5 -0
  116. package/dist/spawn-policy.d.ts.map +1 -0
  117. package/dist/spawn-policy.js +29 -0
  118. package/dist/spawn-policy.js.map +1 -0
  119. package/dist/stdin.d.ts +2 -0
  120. package/dist/stdin.d.ts.map +1 -1
  121. package/dist/stdin.js +4 -0
  122. package/dist/stdin.js.map +1 -1
  123. package/dist/symlink.d.ts +8 -0
  124. package/dist/symlink.d.ts.map +1 -1
  125. package/dist/symlink.js +13 -0
  126. package/dist/symlink.js.map +1 -1
  127. package/dist/system.d.ts +152 -1
  128. package/dist/system.d.ts.map +1 -1
  129. package/dist/system.js +226 -7
  130. package/dist/system.js.map +1 -1
  131. package/dist/thread-coordinator-worker.d.ts +1 -0
  132. package/dist/thread-coordinator-worker.d.ts.map +1 -1
  133. package/dist/thread-coordinator-worker.js +1 -0
  134. package/dist/thread-coordinator-worker.js.map +1 -1
  135. package/dist/thread-worker.js +241 -122
  136. package/dist/thread-worker.js.map +1 -1
  137. package/dist/threads.d.ts +12 -2
  138. package/dist/threads.d.ts.map +1 -1
  139. package/dist/threads.js +30 -10
  140. package/dist/threads.js.map +1 -1
  141. package/dist/types.d.ts +39 -0
  142. package/dist/types.d.ts.map +1 -1
  143. package/dist/websocket-peer.d.ts.map +1 -1
  144. package/dist/websocket-peer.js +4 -14
  145. package/dist/websocket-peer.js.map +1 -1
  146. package/dist/worker-program-protocol.d.ts +70 -3
  147. package/dist/worker-program-protocol.d.ts.map +1 -1
  148. package/dist/worker-program-worker.js +115 -23
  149. package/dist/worker-program-worker.js.map +1 -1
  150. package/dist/worker-program.d.ts +25 -1
  151. package/dist/worker-program.d.ts.map +1 -1
  152. package/dist/worker-program.js +470 -61
  153. package/dist/worker-program.js.map +1 -1
  154. package/dist/worker-standby.d.ts +3 -0
  155. package/dist/worker-standby.d.ts.map +1 -0
  156. package/dist/worker-standby.js +17 -0
  157. package/dist/worker-standby.js.map +1 -0
  158. package/package.json +20 -6
package/README.md CHANGED
@@ -11,6 +11,11 @@ vault, exposes only declared network hosts and browser URLs, and invokes named
11
11
  actions. Grok and Codex are therefore data under `programs/`; this package has
12
12
  no provider-specific execution path.
13
13
 
14
+ Program runs use `terminal: { columns, rows }` to attach a terminal. Direct
15
+ `BrowserWaliRuntime.run` calls use `terminal: true`; a supplied `WaliStdin`
16
+ can provide its dimensions through `terminalSize()`. Without this opt-in,
17
+ stdio is headless and terminal queries return `ENOTTY`, including in pthreads.
18
+
14
19
  Missing syscalls and undeclared capabilities fail closed. Native TCP/TLS is
15
20
  forwarded as opaque records by the optional bounded gateway; TLS still
16
21
  terminates inside the unchanged program.
@@ -18,3 +23,71 @@ terminates inside the unchanged program.
18
23
  WALI toolchain pins and reusable compatibility patches live in
19
24
  `toolchains/wali`. Program-specific build recipes and upstream locks live in
20
25
  `programs/<id>/<version>`.
26
+
27
+ The Rust toolchain's browser spawn bridge supports argv, environment, cwd and
28
+ stdio, but cannot execute child-only `pre_exec` hooks or change child user/group
29
+ credentials. New builds reject those requests with `ErrorKind::Unsupported`
30
+ before dispatch instead of silently skipping them or running them in the
31
+ parent. This does not implement Landlock. Existing WASM artifacts must be
32
+ rebuilt to receive this toolchain fix.
33
+
34
+ Native programs can explicitly import `wali.SYS_browser_spawn_confined_v1`.
35
+ It takes the original seven `SYS_browser_spawn` arguments, followed by an i32
36
+ pointer and byte length for UTF-8 JSON `{ "writableRoots": ["/workspace"] }`.
37
+ An empty list is read-only. The policy is limited to 64 KiB and the runtime's
38
+ 128-root limit. Invalid policy data returns `-22`, invalid policy memory ranges
39
+ return `-14`, and an unnegotiated bridge returns `-95`. Successful dispatch
40
+ returns a child PID; ordinary `wait4` observes its completion.
41
+
42
+ The patched Rust standard library exposes the same request on `CommandExt`,
43
+ only for the WALI target, behind its `wali_browser_spawn` feature:
44
+
45
+ ```rust
46
+ #![feature(wali_browser_spawn)]
47
+ use std::os::unix::process::CommandExt;
48
+ use std::process::Command;
49
+
50
+ let output = Command::new("sh")
51
+ .args(["-c", "printf allowed > /workspace/result.txt"])
52
+ .browser_filesystem_policy_json(br#"{"writableRoots":["/workspace"]}"#)
53
+ .output()?;
54
+ ```
55
+
56
+ The command owns a copy of the policy bytes; changing its environment cannot
57
+ clear them. `spawn`, `status` and `output` use the confined operation, including
58
+ when Tokio wraps the standard command. Invalid policies fail at spawn. `exec`
59
+ with a policy, unsupported hooks and credential changes refuse. New binaries
60
+ require a runtime that supplies the new import; existing artifacts are unchanged.
61
+ Child launch checkpoints pending parent writes through the ordered filesystem
62
+ channel before dispatch. Reaping imports child patches atomically with their
63
+ original metadata instead of replaying them as new parent writes.
64
+ Child ownership and pidfds are shared across pthreads. `wait4` applies the child
65
+ filesystem patch once; `poll` and `epoll` observe completion without a consumer
66
+ timer. The host requires `Atomics.waitAsync` for child execution. Tokio uses its
67
+ upstream Linux process implementation, including with its `time` feature disabled.
68
+ Cooperative SIGCHLD delivery lets upstream Tokio reap abandoned children and
69
+ commit their writes. Signal dispositions are shared; thread masks are inherited.
70
+ Unblocked pending signals interrupt shared `poll`/`epoll` waits. Delivery occurs
71
+ at syscall boundaries, without CPU-loop preemption or a native register context.
72
+ Alternate stacks, recursive handlers and SIGCHLD auto-reap dispositions refuse;
73
+ other blocking syscalls are not yet signal-interruptible.
74
+ The linker-supplied syscall entry requires the
75
+ updated runtime when rebuilt; older artifacts are unchanged.
76
+
77
+ `BrowserWaliWorkerProgram` negotiates this operation only when its `spawn`
78
+ backend declares `capabilities.filesystemPolicy: true`; the receiver validates
79
+ and forwards the policy to that backend. A direct `BrowserWaliRuntime` embedder
80
+ can declare `browserProcess.filesystemPolicyVersion: 1` only if its `spawn`
81
+ callback enforces the requested policy. Root and pthread callers use the same
82
+ contract. The shell and WALI child engines enforce it; Node and Python still
83
+ refuse it. This operation does not add Landlock or automatically convert a Rust
84
+ `pre_exec` hook into a policy.
85
+
86
+ WALI program/command handles expose `capabilities.filesystemPolicy: true` for
87
+ registration with the process host. Their `run` options accept the same
88
+ `filesystemPolicy`; direct `BrowserWaliRuntime.run` accepts it as well. Guest
89
+ write opens, mutations, metadata and mapped-file writeback are checked on the
90
+ process-wide filesystem owner for root and pthread callers. Reads remain broad.
91
+ Descendants inherit the grant even through ordinary spawn; additional requests
92
+ can only narrow it. Host bootstrap and peer restoration are separate from guest
93
+ authority. This does not add OS hard-link isolation or durable confined jobs.
@@ -18,6 +18,9 @@ export interface BrowserWaliCommandOptions {
18
18
  export declare class BrowserWaliCommand {
19
19
  private readonly filesystem;
20
20
  private readonly options;
21
+ readonly capabilities: Readonly<{
22
+ filesystemPolicy: true;
23
+ }>;
21
24
  constructor(filesystem: BrowserFileSystem, options?: BrowserWaliCommandOptions);
22
25
  run: (argv: readonly string[], runOptions?: BrowserProcessRunOptions) => Promise<BrowserProcessResult>;
23
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"browser-wali-command.d.ts","sourceRoot":"","sources":["../src/browser-wali-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AACvF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAGxG,MAAM,WAAW,yBAAyB;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7G,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,iFAAiF;AACjF,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,UAAU,EAAE,iBAAiB,EAC7B,OAAO,GAAE,yBAA8B;IAG1D,GAAG,GACD,MAAM,SAAS,MAAM,EAAE,EACvB,aAAY,wBAA6B,KACxC,OAAO,CAAC,oBAAoB,CAAC,CAmC9B;CACH"}
1
+ {"version":3,"file":"browser-wali-command.d.ts","sourceRoot":"","sources":["../src/browser-wali-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AACvF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAGxG,MAAM,WAAW,yBAAyB;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7G,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,iFAAiF;AACjF,qBAAa,kBAAkB;IAG3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAH1B,QAAQ,CAAC,YAAY;;OAAsD;gBAExD,UAAU,EAAE,iBAAiB,EAC7B,OAAO,GAAE,yBAA8B;IAG1D,GAAG,GACD,MAAM,SAAS,MAAM,EAAE,EACvB,aAAY,wBAA6B,KACxC,OAAO,CAAC,oBAAoB,CAAC,CAmC9B;CACH"}
@@ -3,6 +3,7 @@ import { BrowserWaliWorkerProgram } from "./worker-program.js";
3
3
  export class BrowserWaliCommand {
4
4
  filesystem;
5
5
  options;
6
+ capabilities = Object.freeze({ filesystemPolicy: true });
6
7
  constructor(filesystem, options = {}) {
7
8
  this.filesystem = filesystem;
8
9
  this.options = options;
@@ -16,7 +17,7 @@ export class BrowserWaliCommand {
16
17
  if (!this.filesystem.existsSync(path) || !this.filesystem.statSync(path).isFile()) {
17
18
  return { stdout: "", stderr: `wali: ${path}: file not found\n`, exitCode: 127 };
18
19
  }
19
- const source = this.filesystem.readFileSync(path);
20
+ const source = await this.filesystem.readFile(path);
20
21
  const bytes = new Uint8Array(source.byteLength);
21
22
  bytes.set(source);
22
23
  const url = URL.createObjectURL(new Blob([bytes], { type: "application/wasm" }));
@@ -1 +1 @@
1
- {"version":3,"file":"browser-wali-command.js","sourceRoot":"","sources":["../src/browser-wali-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-wali-command.js","sourceRoot":"","sources":["../src/browser-wali-command.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,75 @@
1
- export declare const WALI_IMPLEMENTED_IMPORTS: Set<"__init" | "__deinit" | "__proc_exit" | "__cl_get_argc" | "__cl_get_argv_len" | "__cl_copy_argv" | "__get_init_envfile" | "SYS_access" | "SYS_brk" | "SYS_chdir" | "SYS_clock_getres" | "SYS_clock_gettime" | "SYS_clock_nanosleep" | "SYS_close" | "SYS_dup" | "SYS_dup2" | "SYS_dup3" | "SYS_epoll_create" | "SYS_epoll_create1" | "SYS_epoll_ctl" | "SYS_epoll_pwait" | "SYS_epoll_wait" | "SYS_eventfd" | "SYS_eventfd2" | "SYS_exit" | "SYS_exit_group" | "SYS_faccessat" | "SYS_faccessat2" | "SYS_fchdir" | "SYS_fcntl" | "SYS_fdatasync" | "SYS_flock" | "SYS_fstat" | "SYS_fsync" | "SYS_ftruncate" | "SYS_getcwd" | "SYS_getdents64" | "SYS_getegid" | "SYS_geteuid" | "SYS_getgid" | "SYS_futex" | "SYS_getpid" | "SYS_getppid" | "SYS_getrandom" | "SYS_getrlimit" | "SYS_getrusage" | "SYS_gettid" | "SYS_gettimeofday" | "SYS_getuid" | "SYS_ioctl" | "SYS_lseek" | "SYS_lstat" | "SYS_mkdir" | "SYS_mkdirat" | "SYS_mmap" | "SYS_mprotect" | "SYS_mremap" | "SYS_munmap" | "SYS_nanosleep" | "SYS_newfstatat" | "SYS_open" | "SYS_openat" | "SYS_poll" | "SYS_pread64" | "SYS_pwrite64" | "SYS_read" | "SYS_readlink" | "SYS_readlinkat" | "SYS_readv" | "SYS_symlink" | "SYS_symlinkat" | "SYS_prctl" | "SYS_prlimit64" | "SYS_rename" | "SYS_rmdir" | "SYS_rt_sigaction" | "SYS_rt_sigprocmask" | "SYS_sched_getaffinity" | "SYS_sched_setscheduler" | "SYS_sched_yield" | "SYS_set_robust_list" | "SYS_set_tid_address" | "SYS_setrlimit" | "SYS_sigaltstack" | "SYS_stat" | "SYS_sysinfo" | "SYS_umask" | "SYS_uname" | "SYS_unlink" | "SYS_unlinkat" | "SYS_socketpair" | "SYS_tkill" | "SYS_write" | "SYS_writev" | "__wasm_thread_spawn" | "SYS_timerfd_create" | "SYS_timerfd_settime" | "SYS_browser_spawn" | "SYS_pipe" | "SYS_pipe2" | "SYS_wait4" | "SYS_kill" | "SYS_setpgid" | "SYS_getpgid" | "SYS_getsid" | "SYS_chmod" | "SYS_fchmod" | "SYS_fchmodat" | "SYS_utimensat" | "SYS_statfs" | "SYS_fstatfs" | "SYS_inotify_init" | "SYS_inotify_init1" | "SYS_inotify_add_watch" | "SYS_inotify_rm_watch" | "SYS_socket" | "SYS_connect" | "SYS_bind" | "SYS_send" | "SYS_sendto" | "SYS_recv" | "SYS_recvfrom" | "SYS_sendmsg" | "SYS_recvmsg" | "SYS_shutdown" | "SYS_setsockopt" | "SYS_getsockopt" | "SYS_getsockname" | "SYS_getpeername" | "SYS_madvise" | "SYS_msync">;
1
+ export declare const WALI_IMPLEMENTED_IMPORTS: Set<"SYS_pipe" | "SYS_pipe2" | "SYS_close" | "SYS_read" | "SYS_pread64" | "SYS_write" | "SYS_pwrite64" | "SYS_readv" | "SYS_writev" | "SYS_lseek" | "SYS_fstat" | "SYS_dup" | "SYS_dup2" | "SYS_dup3" | "SYS_fcntl" | "SYS_poll" | "SYS_brk" | "SYS_mmap" | "SYS_mprotect" | "SYS_munmap" | "SYS_mremap" | "SYS_madvise" | "SYS_msync" | "SYS_rt_sigaction" | "SYS_rt_sigprocmask" | "SYS_rt_sigpending" | "__init" | "__deinit" | "__proc_exit" | "__cl_get_argc" | "__cl_get_argv_len" | "__cl_copy_argv" | "__get_init_envfile" | "SYS_access" | "SYS_chdir" | "SYS_clock_getres" | "SYS_clock_gettime" | "SYS_clock_nanosleep" | "SYS_epoll_create" | "SYS_epoll_create1" | "SYS_epoll_ctl" | "SYS_epoll_pwait" | "SYS_epoll_wait" | "SYS_eventfd" | "SYS_eventfd2" | "SYS_exit" | "SYS_exit_group" | "SYS_faccessat" | "SYS_faccessat2" | "SYS_fchdir" | "SYS_fdatasync" | "SYS_flock" | "SYS_fsync" | "SYS_ftruncate" | "SYS_getcwd" | "SYS_getdents64" | "SYS_getegid" | "SYS_geteuid" | "SYS_getgid" | "SYS_futex" | "SYS_getpid" | "SYS_getppid" | "SYS_getrandom" | "SYS_getrlimit" | "SYS_getrusage" | "SYS_gettid" | "SYS_gettimeofday" | "SYS_getuid" | "SYS_ioctl" | "SYS_lstat" | "SYS_mkdir" | "SYS_mkdirat" | "SYS_nanosleep" | "SYS_newfstatat" | "SYS_open" | "SYS_openat" | "SYS_readlink" | "SYS_readlinkat" | "SYS_symlink" | "SYS_symlinkat" | "SYS_prctl" | "SYS_prlimit64" | "SYS_rename" | "SYS_rmdir" | "SYS_sched_getaffinity" | "SYS_sched_setscheduler" | "SYS_sched_yield" | "SYS_set_robust_list" | "SYS_set_tid_address" | "SYS_setrlimit" | "SYS_sigaltstack" | "SYS_stat" | "SYS_sysinfo" | "SYS_umask" | "SYS_uname" | "SYS_unlink" | "SYS_unlinkat" | "SYS_socketpair" | "SYS_tkill" | "__wasm_thread_spawn" | "SYS_timerfd_create" | "SYS_timerfd_settime" | "SYS_browser_spawn" | "SYS_browser_spawn_confined_v1" | "SYS_wait4" | "SYS_pidfd_open" | "SYS_kill" | "SYS_setpgid" | "SYS_getpgid" | "SYS_getsid" | "SYS_chmod" | "SYS_fchmod" | "SYS_fchmodat" | "SYS_utimensat" | "SYS_statfs" | "SYS_fstatfs" | "SYS_inotify_init" | "SYS_inotify_init1" | "SYS_inotify_add_watch" | "SYS_inotify_rm_watch" | "SYS_socket" | "SYS_connect" | "SYS_bind" | "SYS_send" | "SYS_sendto" | "SYS_recv" | "SYS_recvfrom" | "SYS_sendmsg" | "SYS_recvmsg" | "SYS_shutdown" | "SYS_setsockopt" | "SYS_getsockopt" | "SYS_getsockname" | "SYS_getpeername" | "setjmp" | "longjmp" | "SYS_select" | "SYS_browser_codec_query_v1" | "SYS_browser_codec_open_v1" | "SYS_browser_codec_push_v1" | "SYS_browser_codec_pull_v1" | "SYS_browser_codec_flush_v1" | "SYS_browser_codec_close_v1">;
2
2
  export declare function missingWaliImports(importNames: Iterable<string>): string[];
3
+ /**
4
+ * AN UNIMPLEMENTED SYSCALL ANSWERS `-ENOSYS`; THESE FOUR STILL TRAP.
5
+ *
6
+ * A Linux kernel that does not implement a syscall returns `-ENOSYS`. It does
7
+ * not kill the process, and programs are written for that answer: this very
8
+ * musl branches on it BY NAME in 51 of its source files -- `ppoll.c`,
9
+ * `select.c`, `sigtimedwait.c`, `statx`/`renameat2`/`copy_file_range`
10
+ * fallbacks, `setxid.c`, which returns `-ENOSYS` itself for a setxid number it
11
+ * cannot dispatch. ENOSYS is not an exotic failure on this ABI; it is the
12
+ * ordinary answer to "your kernel is older than this syscall", and the libc
13
+ * under every WALI program already carries the path for it.
14
+ *
15
+ * Trapping instead inverts that: `platform.platform()` shells out to `uname`,
16
+ * `subprocess` raises `OSError`, `platform._syscmd_uname` catches it and falls
17
+ * back to a default string -- a caller behaving correctly, killed by the
18
+ * runtime for asking. Measured 2026-09-19: the scene battery's
19
+ * `17-workshop-interior` died at sequence 2 on `SYS_fork` for exactly that.
20
+ *
21
+ * THE RULE, and it is the reason the list below is four names and not forty:
22
+ * a syscall may be answered with an errno WHEN A CALLER CAN ACT ON IT. It must
23
+ * trap when the errno cannot reach a caller that can do anything but ask
24
+ * again. Two shapes fail that test and no others do:
25
+ *
26
+ * 1. THE CALL DOES NOT RETURN TO ITS CALLER. `rt_sigreturn` replaces the
27
+ * interrupted context; it has no error channel, and any value at all
28
+ * resumes execution on a frame that was meant to be popped.
29
+ * 2. THE CALL'S WHOLE CONTRACT IS TO BLOCK UNTIL AN EXTERNAL EVENT. A
30
+ * correct caller's only response to "I did not block" is to re-check its
31
+ * predicate and call again, so an error return is a live-lock by
32
+ * construction -- a spinning core in a worker, undiagnosable from
33
+ * outside, which is worse than dying. This is not a prediction: musl's
34
+ * own `src/thread/__wait.c` is
35
+ * while (*addr==val) {
36
+ * __syscall_SYS_futex(...) != -ENOSYS || __syscall_SYS_futex(...);
37
+ * }
38
+ * An ENOSYS futex makes that a tight infinite spin.
39
+ *
40
+ * WHAT DOES NOT EARN A TRAP, because both readings were considered and lost:
41
+ * - "the caller will abort anyway" (libc++'s `condition_variable::wait` is
42
+ * `noexcept`). A caller that checks an error and dies is a caller HANDLING
43
+ * it; the trap buys only a better message. `futex` is on this list for
44
+ * shape 2, which is a hang, not for that.
45
+ * - "this syscall is privileged" (`setuid`, `chroot`, `unshare`). A kernel
46
+ * already answers those `EPERM`, so a caller that ignores the errno is
47
+ * already wrong on real Linux. Ours is not a new class of lie.
48
+ * - a timeout argument settles shape 2: `ppoll`, `pselect6` and
49
+ * `rt_sigtimedwait` can all return without the event on a real kernel, so
50
+ * their callers must already distinguish that from an error -- and musl's
51
+ * wrappers for all three branch on `-ENOSYS` explicitly.
52
+ *
53
+ * SCOPE, measured on `blender.wasm` (`sha256-hsUYCtV0…`) rather than assumed:
54
+ * all 181 `SYS_*` imports return `i64`, and every non-`SYS_` import
55
+ * (`__init`, `__cl_get_argc`, `setjmp`, `longjmp`, `__proc_exit`) returns
56
+ * `i32` or nothing. Only a `SYS_*` name is a syscall with an errno channel, so
57
+ * only a `SYS_*` name may be answered `-ENOSYS`; an unimplemented ABI hook
58
+ * still traps, and handing `-38n` to an `i32` slot would have trapped anyway
59
+ * with a worse message.
60
+ *
61
+ * ADDING A NAME HERE IS THE EXCEPTION, NOT THE HABIT: say which of the two
62
+ * shapes it is, and cite the caller.
63
+ */
64
+ export declare const WALI_TRAPPING_IMPORTS: Set<"SYS_futex" | "SYS_rt_sigreturn" | "SYS_pause" | "SYS_rt_sigsuspend">;
65
+ /** Linux's answer for a syscall the kernel does not implement. */
66
+ export declare const WALI_ENOSYS = -38n;
67
+ /**
68
+ * What the runtime installs for an import it has no handler for: a trap, or
69
+ * the kernel's own `-ENOSYS`. Both instance halves ask this one question --
70
+ * the root (`runtime.ts`) and every pthread (`thread-worker.ts`) -- because a
71
+ * program whose survival depended on WHICH THREAD made the call is the defect
72
+ * this function exists to prevent. It was exactly that until 2026-09-19.
73
+ */
74
+ export declare function waliUnimplementedTraps(name: string): boolean;
3
75
  //# sourceMappingURL=capabilities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,+qEAkB1B,CAAC;AAEZ,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAE1E"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,u9EAqB1B,CAAC;AAEZ,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAE1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,eAAO,MAAM,qBAAqB,2EAOvB,CAAC;AAEZ,kEAAkE;AAClE,eAAO,MAAM,WAAW,OAAO,CAAC;AAEhC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D"}
@@ -6,18 +6,102 @@ export const WALI_IMPLEMENTED_IMPORTS = new Set([
6
6
  "SYS_fdatasync", "SYS_flock", "SYS_fstat", "SYS_fsync", "SYS_ftruncate", "SYS_getcwd", "SYS_getdents64", "SYS_getegid", "SYS_geteuid", "SYS_getgid",
7
7
  "SYS_futex", "SYS_getpid", "SYS_getppid", "SYS_getrandom", "SYS_getrlimit", "SYS_getrusage", "SYS_gettid", "SYS_gettimeofday", "SYS_getuid", "SYS_ioctl", "SYS_lseek",
8
8
  "SYS_lstat", "SYS_mkdir", "SYS_mkdirat", "SYS_mmap", "SYS_mprotect", "SYS_mremap", "SYS_munmap", "SYS_nanosleep", "SYS_newfstatat", "SYS_open", "SYS_openat", "SYS_poll", "SYS_pread64", "SYS_pwrite64", "SYS_read", "SYS_readlink", "SYS_readlinkat", "SYS_readv", "SYS_symlink", "SYS_symlinkat",
9
- "SYS_prctl", "SYS_prlimit64", "SYS_rename", "SYS_rmdir", "SYS_rt_sigaction", "SYS_rt_sigprocmask", "SYS_sched_getaffinity", "SYS_sched_setscheduler", "SYS_sched_yield",
9
+ "SYS_prctl", "SYS_prlimit64", "SYS_rename", "SYS_rmdir", "SYS_rt_sigaction", "SYS_rt_sigpending", "SYS_rt_sigprocmask", "SYS_sched_getaffinity", "SYS_sched_setscheduler", "SYS_sched_yield",
10
10
  "SYS_set_robust_list", "SYS_set_tid_address", "SYS_setrlimit", "SYS_sigaltstack", "SYS_stat", "SYS_sysinfo", "SYS_umask", "SYS_uname", "SYS_unlink", "SYS_unlinkat",
11
11
  "SYS_socketpair", "SYS_tkill", "SYS_write", "SYS_writev", "__wasm_thread_spawn",
12
12
  "SYS_timerfd_create", "SYS_timerfd_settime",
13
- "SYS_browser_spawn", "SYS_pipe", "SYS_pipe2", "SYS_wait4", "SYS_kill", "SYS_setpgid", "SYS_getpgid", "SYS_getsid",
13
+ "SYS_browser_spawn", "SYS_browser_spawn_confined_v1", "SYS_pipe", "SYS_pipe2", "SYS_wait4", "SYS_pidfd_open", "SYS_kill", "SYS_setpgid", "SYS_getpgid", "SYS_getsid",
14
14
  "SYS_chmod", "SYS_fchmod", "SYS_fchmodat", "SYS_utimensat",
15
15
  "SYS_statfs", "SYS_fstatfs", "SYS_inotify_init", "SYS_inotify_init1", "SYS_inotify_add_watch", "SYS_inotify_rm_watch",
16
16
  "SYS_socket", "SYS_connect", "SYS_bind", "SYS_send", "SYS_sendto", "SYS_recv", "SYS_recvfrom",
17
17
  "SYS_sendmsg", "SYS_recvmsg", "SYS_shutdown", "SYS_setsockopt", "SYS_getsockopt", "SYS_getsockname", "SYS_getpeername",
18
18
  "SYS_madvise", "SYS_msync",
19
+ "setjmp", "longjmp", "SYS_select",
20
+ "SYS_browser_codec_query_v1", "SYS_browser_codec_open_v1", "SYS_browser_codec_push_v1",
21
+ "SYS_browser_codec_pull_v1", "SYS_browser_codec_flush_v1", "SYS_browser_codec_close_v1",
19
22
  ]);
20
23
  export function missingWaliImports(importNames) {
21
24
  return [...new Set(importNames)].filter((name) => !WALI_IMPLEMENTED_IMPORTS.has(name)).sort();
22
25
  }
26
+ /**
27
+ * AN UNIMPLEMENTED SYSCALL ANSWERS `-ENOSYS`; THESE FOUR STILL TRAP.
28
+ *
29
+ * A Linux kernel that does not implement a syscall returns `-ENOSYS`. It does
30
+ * not kill the process, and programs are written for that answer: this very
31
+ * musl branches on it BY NAME in 51 of its source files -- `ppoll.c`,
32
+ * `select.c`, `sigtimedwait.c`, `statx`/`renameat2`/`copy_file_range`
33
+ * fallbacks, `setxid.c`, which returns `-ENOSYS` itself for a setxid number it
34
+ * cannot dispatch. ENOSYS is not an exotic failure on this ABI; it is the
35
+ * ordinary answer to "your kernel is older than this syscall", and the libc
36
+ * under every WALI program already carries the path for it.
37
+ *
38
+ * Trapping instead inverts that: `platform.platform()` shells out to `uname`,
39
+ * `subprocess` raises `OSError`, `platform._syscmd_uname` catches it and falls
40
+ * back to a default string -- a caller behaving correctly, killed by the
41
+ * runtime for asking. Measured 2026-09-19: the scene battery's
42
+ * `17-workshop-interior` died at sequence 2 on `SYS_fork` for exactly that.
43
+ *
44
+ * THE RULE, and it is the reason the list below is four names and not forty:
45
+ * a syscall may be answered with an errno WHEN A CALLER CAN ACT ON IT. It must
46
+ * trap when the errno cannot reach a caller that can do anything but ask
47
+ * again. Two shapes fail that test and no others do:
48
+ *
49
+ * 1. THE CALL DOES NOT RETURN TO ITS CALLER. `rt_sigreturn` replaces the
50
+ * interrupted context; it has no error channel, and any value at all
51
+ * resumes execution on a frame that was meant to be popped.
52
+ * 2. THE CALL'S WHOLE CONTRACT IS TO BLOCK UNTIL AN EXTERNAL EVENT. A
53
+ * correct caller's only response to "I did not block" is to re-check its
54
+ * predicate and call again, so an error return is a live-lock by
55
+ * construction -- a spinning core in a worker, undiagnosable from
56
+ * outside, which is worse than dying. This is not a prediction: musl's
57
+ * own `src/thread/__wait.c` is
58
+ * while (*addr==val) {
59
+ * __syscall_SYS_futex(...) != -ENOSYS || __syscall_SYS_futex(...);
60
+ * }
61
+ * An ENOSYS futex makes that a tight infinite spin.
62
+ *
63
+ * WHAT DOES NOT EARN A TRAP, because both readings were considered and lost:
64
+ * - "the caller will abort anyway" (libc++'s `condition_variable::wait` is
65
+ * `noexcept`). A caller that checks an error and dies is a caller HANDLING
66
+ * it; the trap buys only a better message. `futex` is on this list for
67
+ * shape 2, which is a hang, not for that.
68
+ * - "this syscall is privileged" (`setuid`, `chroot`, `unshare`). A kernel
69
+ * already answers those `EPERM`, so a caller that ignores the errno is
70
+ * already wrong on real Linux. Ours is not a new class of lie.
71
+ * - a timeout argument settles shape 2: `ppoll`, `pselect6` and
72
+ * `rt_sigtimedwait` can all return without the event on a real kernel, so
73
+ * their callers must already distinguish that from an error -- and musl's
74
+ * wrappers for all three branch on `-ENOSYS` explicitly.
75
+ *
76
+ * SCOPE, measured on `blender.wasm` (`sha256-hsUYCtV0…`) rather than assumed:
77
+ * all 181 `SYS_*` imports return `i64`, and every non-`SYS_` import
78
+ * (`__init`, `__cl_get_argc`, `setjmp`, `longjmp`, `__proc_exit`) returns
79
+ * `i32` or nothing. Only a `SYS_*` name is a syscall with an errno channel, so
80
+ * only a `SYS_*` name may be answered `-ENOSYS`; an unimplemented ABI hook
81
+ * still traps, and handing `-38n` to an `i32` slot would have trapped anyway
82
+ * with a worse message.
83
+ *
84
+ * ADDING A NAME HERE IS THE EXCEPTION, NOT THE HABIT: say which of the two
85
+ * shapes it is, and cite the caller.
86
+ */
87
+ export const WALI_TRAPPING_IMPORTS = new Set([
88
+ // Shape 1 — no return to a caller.
89
+ "SYS_rt_sigreturn",
90
+ // Shape 2 — block until an external event; an errno is a live-lock.
91
+ "SYS_futex",
92
+ "SYS_pause",
93
+ "SYS_rt_sigsuspend",
94
+ ]);
95
+ /** Linux's answer for a syscall the kernel does not implement. */
96
+ export const WALI_ENOSYS = -38n;
97
+ /**
98
+ * What the runtime installs for an import it has no handler for: a trap, or
99
+ * the kernel's own `-ENOSYS`. Both instance halves ask this one question --
100
+ * the root (`runtime.ts`) and every pthread (`thread-worker.ts`) -- because a
101
+ * program whose survival depended on WHICH THREAD made the call is the defect
102
+ * this function exists to prevent. It was exactly that until 2026-09-19.
103
+ */
104
+ export function waliUnimplementedTraps(name) {
105
+ return !name.startsWith("SYS_") || WALI_TRAPPING_IMPORTS.has(name);
106
+ }
23
107
  //# sourceMappingURL=capabilities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC;IAC9C,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,oBAAoB;IACjH,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU;IACpJ,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc;IAC5H,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW;IAC1F,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY;IACnJ,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW;IACrK,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe;IAClS,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,iBAAiB;IACvK,qBAAqB,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc;IACnK,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB;IAC/E,oBAAoB,EAAE,qBAAqB;IAC3C,mBAAmB,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY;IACjH,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe;IAC1D,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,sBAAsB;IACrH,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc;IAC7F,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB;IACtH,aAAa,EAAE,WAAW;CAClB,CAAC,CAAC;AAEZ,MAAM,UAAU,kBAAkB,CAAC,WAA6B;IAC9D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC,IAAa,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACzG,CAAC"}
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { BrowserProcessSharedState } from "./process-bridge.js";
2
+ /** Process-wide child ownership, shared by every guest pthread through the event worker. */
3
+ export declare class WaliChildProcesses {
4
+ private readonly allocateFd;
5
+ private readonly onExit?;
6
+ private readonly children;
7
+ private readonly descriptors;
8
+ private readonly listeners;
9
+ constructor(allocateFd: (minimum?: number) => number, onExit?: ((pid: number, status: number) => void) | undefined);
10
+ private changed;
11
+ /** Wakes a blocked `wait` to look again: a signal arrived. */
12
+ wake(): void;
13
+ onChange(listener: () => void): () => void;
14
+ register(pid: number, state: BrowserProcessSharedState): number;
15
+ forget(pid: number): number;
16
+ has(pid: number): boolean;
17
+ wait(pid: number, options: number, destination: BrowserProcessSharedState, interrupted?: () => boolean): Promise<number>;
18
+ open(pid: number, flags: number): number;
19
+ owns(fd: number): boolean;
20
+ poll(fd: number, events: number): number | undefined;
21
+ close(fd: number): number;
22
+ fcntl(fd: number, command: number, argument: number): number;
23
+ }
24
+ //# sourceMappingURL=child-processes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-processes.d.ts","sourceRoot":"","sources":["../src/child-processes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAOrE,4FAA4F;AAC5F,qBAAa,kBAAkB;IAM3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAN1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8E;IAC1G,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;gBAGhC,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,EACxC,MAAM,CAAC,GAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,aAAA;IAGjE,OAAO,CAAC,OAAO;IAEf,8DAA8D;IAC9D,IAAI,IAAI,IAAI;IAEZ,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAK1C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,yBAAyB,GAAG,MAAM;IAuB/D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAY3B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAEnB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,yBAAyB,EAAE,WAAW,GAAE,MAAM,OAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IA4B3I,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IASxC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAEzB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOpD,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAMzB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;CAc7D"}
@@ -0,0 +1,134 @@
1
+ /** Process-wide child ownership, shared by every guest pthread through the event worker. */
2
+ export class WaliChildProcesses {
3
+ allocateFd;
4
+ onExit;
5
+ children = new Map();
6
+ descriptors = new Map();
7
+ listeners = new Set();
8
+ constructor(allocateFd, onExit) {
9
+ this.allocateFd = allocateFd;
10
+ this.onExit = onExit;
11
+ }
12
+ changed() { for (const listener of [...this.listeners])
13
+ listener(); }
14
+ /** Wakes a blocked `wait` to look again: a signal arrived. */
15
+ wake() { this.changed(); }
16
+ onChange(listener) {
17
+ this.listeners.add(listener);
18
+ return () => { this.listeners.delete(listener); };
19
+ }
20
+ register(pid, state) {
21
+ if (pid <= 0 || this.children.has(pid))
22
+ return -22;
23
+ const waitAsync = Atomics.waitAsync;
24
+ if (!waitAsync)
25
+ return -38;
26
+ const child = { state, reaped: false };
27
+ this.children.set(pid, child);
28
+ const control = new Int32Array(state.control);
29
+ // Completion is published after the exit code and filesystem patch. The
30
+ // equality check in waitAsync closes the completion-before-subscription race.
31
+ const watch = async () => {
32
+ while (Atomics.load(control, 0) === 0 && !child.reaped) {
33
+ await waitAsync(control, 0, 0).value;
34
+ }
35
+ if (!child.reaped)
36
+ this.onExit?.(pid, Atomics.load(control, 1));
37
+ this.changed();
38
+ };
39
+ void watch();
40
+ this.changed();
41
+ return 0;
42
+ }
43
+ forget(pid) {
44
+ const child = this.children.get(pid);
45
+ if (!child)
46
+ return -3;
47
+ child.reaped = true;
48
+ this.children.delete(pid);
49
+ // Failed dispatches have no producer left to notify a completion watcher.
50
+ Atomics.store(new Int32Array(child.state.control), 0, 1);
51
+ Atomics.notify(new Int32Array(child.state.control), 0);
52
+ this.changed();
53
+ return 0;
54
+ }
55
+ has(pid) { return this.children.has(pid); }
56
+ async wait(pid, options, destination, interrupted = () => false) {
57
+ if (pid === 0 || pid < -1 || (options & ~1) !== 0)
58
+ return -22;
59
+ for (;;) {
60
+ const candidates = pid === -1 ? [...this.children.entries()]
61
+ : this.children.has(pid) ? [[pid, this.children.get(pid)]] : [];
62
+ if (candidates.length === 0)
63
+ return -10;
64
+ const completed = candidates.find(([, child]) => Atomics.load(new Int32Array(child.state.control), 0) !== 0);
65
+ if (completed) {
66
+ const [childPid, child] = completed;
67
+ const source = new Int32Array(child.state.control);
68
+ const length = Atomics.load(source, 2);
69
+ if (length < 0 || length > child.state.response.byteLength || length > destination.response.byteLength)
70
+ return -5;
71
+ new Uint8Array(destination.response).set(new Uint8Array(child.state.response, 0, length));
72
+ new Int32Array(destination.control).set(source);
73
+ child.reaped = true;
74
+ this.children.delete(childPid);
75
+ this.changed();
76
+ return childPid;
77
+ }
78
+ if (options & 1)
79
+ return 0;
80
+ // a blocked wait4 returns -EINTR for a signal the caller does not block, so its handler runs
81
+ if (interrupted())
82
+ return -4;
83
+ await new Promise((resolve) => {
84
+ const unsubscribe = this.onChange(() => { unsubscribe(); resolve(); });
85
+ });
86
+ }
87
+ }
88
+ open(pid, flags) {
89
+ if (pid <= 0 || (flags & ~0x800) !== 0)
90
+ return -22;
91
+ const child = this.children.get(pid);
92
+ if (!child)
93
+ return -3;
94
+ const fd = this.allocateFd();
95
+ this.descriptors.set(fd, { child, flags, cloexec: true });
96
+ return fd;
97
+ }
98
+ owns(fd) { return this.descriptors.has(fd); }
99
+ poll(fd, events) {
100
+ const descriptor = this.descriptors.get(fd);
101
+ if (!descriptor)
102
+ return;
103
+ return (descriptor.child.reaped ? 0x10 : 0)
104
+ | ((events & 1) && Atomics.load(new Int32Array(descriptor.child.state.control), 0) !== 0 ? 1 : 0);
105
+ }
106
+ close(fd) {
107
+ if (!this.descriptors.delete(fd))
108
+ return -9;
109
+ this.changed();
110
+ return 0;
111
+ }
112
+ fcntl(fd, command, argument) {
113
+ const descriptor = this.descriptors.get(fd);
114
+ if (!descriptor)
115
+ return -9;
116
+ if (command === 0 || command === 1030) {
117
+ if (argument < 0)
118
+ return -22;
119
+ const duplicate = this.allocateFd(argument);
120
+ this.descriptors.set(duplicate, { ...descriptor, cloexec: command === 1030 });
121
+ return duplicate;
122
+ }
123
+ if (command === 1)
124
+ return descriptor.cloexec ? 1 : 0;
125
+ if (command === 2) {
126
+ descriptor.cloexec = Boolean(argument & 1);
127
+ return 0;
128
+ }
129
+ if (command === 3)
130
+ return descriptor.flags;
131
+ return -22;
132
+ }
133
+ }
134
+ //# sourceMappingURL=child-processes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-processes.js","sourceRoot":"","sources":["../src/child-processes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The shared-memory protocol between a WALI guest thread and the process's
3
+ * codec worker. The C side of the ABI is
4
+ * `toolchains/wali/runtime/wali-browser-codec.h`; the field meanings are
5
+ * `programs/ffmpeg/SPEC.md` §3.3.
6
+ *
7
+ * A request carries no payload buffer: the codec worker holds the process's
8
+ * `WebAssembly.Memory` and reads and writes the guest's own pointers, which
9
+ * stay valid because the calling thread is parked inside the import for the
10
+ * whole call. Everything a request needs therefore fits in the control words.
11
+ */
12
+ export declare const CODEC_ABI_VERSION = 1;
13
+ export declare const CODEC_JSON_MAX: number;
14
+ export declare const CODEC_MAX_HANDLES = 64;
15
+ /** Inputs a handle may hold undelivered before `push` answers -EAGAIN. */
16
+ export declare const CODEC_MAX_INFLIGHT = 8;
17
+ /** Outputs a handle may hold before the worker stops accepting inputs. */
18
+ export declare const CODEC_MAX_OUTPUTS = 32;
19
+ /** How long a waiting `pull` blocks before -ETIMEDOUT. */
20
+ export declare const CODEC_WAIT_MS = 10000;
21
+ export declare const enum CodecOperation {
22
+ Query = 1,
23
+ Open = 2,
24
+ Push = 3,
25
+ Pull = 4,
26
+ Flush = 5,
27
+ Close = 6
28
+ }
29
+ export declare const enum CodecKind {
30
+ VideoDecoder = 0,
31
+ VideoEncoder = 1,
32
+ AudioDecoder = 2,
33
+ AudioEncoder = 3
34
+ }
35
+ /** `pull` flag bit 0: block until an output, end of stream, or the wait expiry. */
36
+ export declare const CODEC_PULL_WAIT = 1;
37
+ /**
38
+ * Control words of one channel. Word 0 is the generation word every waiter
39
+ * sleeps on: 0 idle, `requestId` in flight, `-requestId` retired by a
40
+ * timed-out caller, `requestId + 1` complete.
41
+ */
42
+ export declare const enum CodecControl {
43
+ State = 0,
44
+ Operation = 1,
45
+ Result = 2,
46
+ Argument0 = 3,
47
+ Argument1 = 4,
48
+ Argument2 = 5,
49
+ Argument3 = 6,
50
+ Argument4 = 7,
51
+ Argument5 = 8
52
+ }
53
+ /** Six arguments is the widest request (`pull`). */
54
+ export declare const CODEC_ARGUMENTS = 6;
55
+ export declare const CODEC_CONTROL_WORDS = 9;
56
+ export interface WaliCodecChannel {
57
+ port: MessagePort;
58
+ control: SharedArrayBuffer;
59
+ }
60
+ export type CodecWorkerMessage = {
61
+ kind: "initialize";
62
+ memory: WebAssembly.Memory;
63
+ } | ({
64
+ kind: "attach";
65
+ } & WaliCodecChannel);
66
+ //# sourceMappingURL=codec-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec-protocol.d.ts","sourceRoot":"","sources":["../src/codec-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,cAAc,QAAY,CAAC;AACxC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,0DAA0D;AAC1D,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC,0BAAkB,cAAc;IAC9B,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;IACT,KAAK,IAAI;CACV;AAED,0BAAkB,SAAS;IACzB,YAAY,IAAI;IAChB,YAAY,IAAI;IAChB,YAAY,IAAI;IAChB,YAAY,IAAI;CACjB;AAED,mFAAmF;AACnF,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;GAIG;AACH,0BAAkB,YAAY;IAC5B,KAAK,IAAI;IACT,SAAS,IAAI;IACb,MAAM,IAAI;IACV,SAAS,IAAI;IACb,SAAS,IAAI;IACb,SAAS,IAAI;IACb,SAAS,IAAI;IACb,SAAS,IAAI;IACb,SAAS,IAAI;CACd;AAED,oDAAoD;AACpD,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAA;CAAE,GAClD,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,gBAAgB,CAAC,CAAC"}