@secure-exec/core 0.2.1 → 0.3.0-rc.2

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 (248) hide show
  1. package/README.md +5 -5
  2. package/dist/binary.d.ts +4 -0
  3. package/dist/binary.js +25 -0
  4. package/dist/bytes.d.ts +2 -0
  5. package/dist/bytes.js +6 -0
  6. package/dist/callbacks.d.ts +41 -0
  7. package/dist/callbacks.js +94 -0
  8. package/dist/cargo.d.ts +2 -0
  9. package/dist/cargo.js +142 -0
  10. package/dist/correlation.d.ts +10 -0
  11. package/dist/correlation.js +49 -0
  12. package/dist/descriptors.d.ts +34 -0
  13. package/dist/descriptors.js +37 -0
  14. package/dist/event-buffer.d.ts +90 -0
  15. package/dist/event-buffer.js +313 -0
  16. package/dist/ext.d.ts +7 -0
  17. package/dist/ext.js +13 -0
  18. package/dist/filesystem.d.ts +41 -0
  19. package/dist/filesystem.js +70 -0
  20. package/dist/frame-payload-codec.d.ts +8 -0
  21. package/dist/frame-payload-codec.js +14 -0
  22. package/dist/frame-rpc.d.ts +38 -0
  23. package/dist/frame-rpc.js +73 -0
  24. package/dist/frame-stream.d.ts +27 -0
  25. package/dist/frame-stream.js +99 -0
  26. package/dist/framing.d.ts +7 -0
  27. package/dist/framing.js +22 -0
  28. package/dist/generated/AcpLimitsConfig.d.ts +4 -0
  29. package/dist/generated/AcpLimitsConfig.js +2 -0
  30. package/dist/generated/CreateVmConfig.d.ts +19 -0
  31. package/dist/generated/FsPermissionRule.d.ts +6 -0
  32. package/dist/generated/FsPermissionRuleSet.d.ts +6 -0
  33. package/dist/generated/FsPermissionRuleSet.js +1 -0
  34. package/dist/generated/FsPermissionScope.d.ts +3 -0
  35. package/dist/generated/FsPermissionScope.js +1 -0
  36. package/dist/generated/HttpLimitsConfig.d.ts +3 -0
  37. package/dist/generated/HttpLimitsConfig.js +2 -0
  38. package/dist/generated/JsModuleResolution.d.ts +1 -0
  39. package/dist/generated/JsModuleResolution.js +2 -0
  40. package/dist/generated/JsRuntimeConfig.d.ts +26 -0
  41. package/dist/generated/JsRuntimeConfig.js +1 -0
  42. package/dist/generated/JsRuntimeLimitsConfig.d.ts +7 -0
  43. package/dist/generated/JsRuntimeLimitsConfig.js +2 -0
  44. package/dist/generated/JsRuntimePlatform.d.ts +1 -0
  45. package/dist/generated/JsRuntimePlatform.js +2 -0
  46. package/dist/generated/MountPluginDescriptor.d.ts +4 -0
  47. package/dist/generated/MountPluginDescriptor.js +2 -0
  48. package/dist/generated/NativeRootFilesystemConfig.d.ts +5 -0
  49. package/dist/generated/NativeRootFilesystemConfig.js +1 -0
  50. package/dist/generated/PatternPermissionRule.d.ts +6 -0
  51. package/dist/generated/PatternPermissionRule.js +1 -0
  52. package/dist/generated/PatternPermissionRuleSet.d.ts +6 -0
  53. package/dist/generated/PatternPermissionRuleSet.js +1 -0
  54. package/dist/generated/PatternPermissionScope.d.ts +3 -0
  55. package/dist/generated/PatternPermissionScope.js +1 -0
  56. package/dist/generated/PermissionMode.d.ts +1 -0
  57. package/dist/generated/PermissionMode.js +2 -0
  58. package/dist/generated/PermissionsPolicy.d.ts +10 -0
  59. package/dist/generated/PermissionsPolicy.js +1 -0
  60. package/dist/generated/PluginLimitsConfig.d.ts +4 -0
  61. package/dist/generated/PluginLimitsConfig.js +2 -0
  62. package/dist/generated/PythonLimitsConfig.d.ts +5 -0
  63. package/dist/generated/PythonLimitsConfig.js +2 -0
  64. package/dist/generated/ResourceLimitsConfig.d.ts +22 -0
  65. package/dist/generated/ResourceLimitsConfig.js +2 -0
  66. package/dist/generated/RootFilesystemConfig.d.ts +9 -0
  67. package/dist/generated/RootFilesystemConfig.js +1 -0
  68. package/dist/generated/RootFilesystemEntry.d.ts +13 -0
  69. package/dist/generated/RootFilesystemEntry.js +1 -0
  70. package/dist/generated/RootFilesystemEntryEncoding.d.ts +1 -0
  71. package/dist/generated/RootFilesystemEntryEncoding.js +2 -0
  72. package/dist/generated/RootFilesystemEntryKind.d.ts +1 -0
  73. package/dist/generated/RootFilesystemEntryKind.js +2 -0
  74. package/dist/generated/RootFilesystemLowerDescriptor.d.ts +7 -0
  75. package/dist/generated/RootFilesystemLowerDescriptor.js +1 -0
  76. package/dist/generated/RootFilesystemMode.d.ts +1 -0
  77. package/dist/generated/RootFilesystemMode.js +2 -0
  78. package/dist/generated/ToolLimitsConfig.d.ts +10 -0
  79. package/dist/generated/ToolLimitsConfig.js +2 -0
  80. package/dist/generated/VmDnsConfig.d.ts +6 -0
  81. package/dist/generated/VmDnsConfig.js +2 -0
  82. package/dist/generated/VmLimitsConfig.d.ts +18 -0
  83. package/dist/generated/VmLimitsConfig.js +1 -0
  84. package/dist/generated/VmListenPolicyConfig.d.ts +5 -0
  85. package/dist/generated/VmListenPolicyConfig.js +2 -0
  86. package/dist/generated/WasmLimitsConfig.d.ts +5 -0
  87. package/dist/generated/WasmLimitsConfig.js +2 -0
  88. package/dist/generated-protocol.d.ts +1037 -0
  89. package/dist/generated-protocol.js +2887 -0
  90. package/dist/index.d.ts +24 -62
  91. package/dist/index.js +24 -53
  92. package/dist/json.d.ts +2 -0
  93. package/dist/json.js +20 -0
  94. package/dist/kernel-proxy.d.ts +149 -0
  95. package/dist/kernel-proxy.js +1733 -0
  96. package/dist/native-client.d.ts +41 -0
  97. package/dist/native-client.js +124 -0
  98. package/dist/node-runtime.d.ts +490 -0
  99. package/dist/node-runtime.js +585 -0
  100. package/dist/numbers.d.ts +1 -0
  101. package/dist/numbers.js +8 -0
  102. package/dist/ownership.d.ts +18 -0
  103. package/dist/ownership.js +77 -0
  104. package/dist/permissions.d.ts +29 -0
  105. package/dist/permissions.js +68 -0
  106. package/dist/process.d.ts +35 -0
  107. package/dist/process.js +125 -0
  108. package/dist/protocol-client.d.ts +46 -0
  109. package/dist/protocol-client.js +180 -0
  110. package/dist/protocol-frames.d.ts +68 -0
  111. package/dist/protocol-frames.js +139 -0
  112. package/dist/protocol-maps.d.ts +28 -0
  113. package/dist/protocol-maps.js +217 -0
  114. package/dist/protocol-schema.d.ts +10 -0
  115. package/dist/protocol-schema.js +11 -0
  116. package/dist/request-payloads.d.ts +137 -0
  117. package/dist/request-payloads.js +210 -0
  118. package/dist/response-payloads.d.ts +107 -0
  119. package/dist/response-payloads.js +161 -0
  120. package/dist/sidecar-client.d.ts +242 -0
  121. package/dist/sidecar-client.js +797 -0
  122. package/dist/state.d.ts +40 -0
  123. package/dist/state.js +44 -0
  124. package/dist/test-runtime.d.ts +526 -0
  125. package/dist/test-runtime.js +2119 -0
  126. package/dist/vm-config.d.ts +31 -0
  127. package/dist/vm-config.js +1 -0
  128. package/fixtures/alpine-defaults.json +520 -0
  129. package/fixtures/base-filesystem.json +528 -0
  130. package/package.json +193 -115
  131. package/LICENSE +0 -191
  132. package/dist/bridge-setup.d.ts +0 -6
  133. package/dist/bridge-setup.js +0 -9
  134. package/dist/esm-compiler.d.ts +0 -18
  135. package/dist/esm-compiler.js +0 -72
  136. package/dist/fs-helpers.d.ts +0 -23
  137. package/dist/fs-helpers.js +0 -41
  138. package/dist/generated/isolate-runtime.d.ts +0 -19
  139. package/dist/generated/isolate-runtime.js +0 -21
  140. package/dist/generated/polyfills.d.ts +0 -82
  141. package/dist/generated/polyfills.js +0 -82
  142. package/dist/isolate-runtime/apply-custom-global-policy.js +0 -53
  143. package/dist/isolate-runtime/apply-timing-mitigation-freeze.js +0 -130
  144. package/dist/isolate-runtime/apply-timing-mitigation-off.js +0 -14
  145. package/dist/isolate-runtime/bridge-attach.js +0 -29
  146. package/dist/isolate-runtime/bridge-initial-globals.js +0 -385
  147. package/dist/isolate-runtime/eval-script-result.js +0 -8
  148. package/dist/isolate-runtime/global-exposure-helpers.js +0 -36
  149. package/dist/isolate-runtime/init-commonjs-module-globals.js +0 -28
  150. package/dist/isolate-runtime/override-process-cwd.js +0 -8
  151. package/dist/isolate-runtime/override-process-env.js +0 -8
  152. package/dist/isolate-runtime/require-setup.js +0 -4153
  153. package/dist/isolate-runtime/set-commonjs-file-globals.js +0 -36
  154. package/dist/isolate-runtime/set-stdin-data.js +0 -10
  155. package/dist/isolate-runtime/setup-dynamic-import.js +0 -123
  156. package/dist/isolate-runtime/setup-fs-facade.js +0 -87
  157. package/dist/kernel/command-registry.d.ts +0 -44
  158. package/dist/kernel/command-registry.js +0 -114
  159. package/dist/kernel/device-backend.d.ts +0 -14
  160. package/dist/kernel/device-backend.js +0 -251
  161. package/dist/kernel/device-layer.d.ts +0 -12
  162. package/dist/kernel/device-layer.js +0 -271
  163. package/dist/kernel/dns-cache.d.ts +0 -29
  164. package/dist/kernel/dns-cache.js +0 -52
  165. package/dist/kernel/fd-table.d.ts +0 -84
  166. package/dist/kernel/fd-table.js +0 -278
  167. package/dist/kernel/file-lock.d.ts +0 -34
  168. package/dist/kernel/file-lock.js +0 -122
  169. package/dist/kernel/host-adapter.d.ts +0 -50
  170. package/dist/kernel/host-adapter.js +0 -8
  171. package/dist/kernel/index.d.ts +0 -36
  172. package/dist/kernel/index.js +0 -34
  173. package/dist/kernel/kernel.d.ts +0 -9
  174. package/dist/kernel/kernel.js +0 -1415
  175. package/dist/kernel/mount-table.d.ts +0 -75
  176. package/dist/kernel/mount-table.js +0 -353
  177. package/dist/kernel/permissions.d.ts +0 -36
  178. package/dist/kernel/permissions.js +0 -150
  179. package/dist/kernel/pipe-manager.d.ts +0 -64
  180. package/dist/kernel/pipe-manager.js +0 -267
  181. package/dist/kernel/proc-backend.d.ts +0 -30
  182. package/dist/kernel/proc-backend.js +0 -428
  183. package/dist/kernel/proc-layer.d.ts +0 -11
  184. package/dist/kernel/proc-layer.js +0 -507
  185. package/dist/kernel/process-table.d.ts +0 -126
  186. package/dist/kernel/process-table.js +0 -651
  187. package/dist/kernel/pty.d.ts +0 -109
  188. package/dist/kernel/pty.js +0 -552
  189. package/dist/kernel/socket-table.d.ts +0 -312
  190. package/dist/kernel/socket-table.js +0 -1188
  191. package/dist/kernel/timer-table.d.ts +0 -54
  192. package/dist/kernel/timer-table.js +0 -108
  193. package/dist/kernel/types.d.ts +0 -541
  194. package/dist/kernel/types.js +0 -98
  195. package/dist/kernel/user.d.ts +0 -29
  196. package/dist/kernel/user.js +0 -35
  197. package/dist/kernel/vfs.d.ts +0 -82
  198. package/dist/kernel/vfs.js +0 -25
  199. package/dist/kernel/wait.d.ts +0 -45
  200. package/dist/kernel/wait.js +0 -112
  201. package/dist/kernel/wstatus.d.ts +0 -21
  202. package/dist/kernel/wstatus.js +0 -33
  203. package/dist/module-resolver.d.ts +0 -29
  204. package/dist/module-resolver.js +0 -314
  205. package/dist/package-bundler.d.ts +0 -41
  206. package/dist/package-bundler.js +0 -497
  207. package/dist/runtime-driver.d.ts +0 -66
  208. package/dist/shared/api-types.d.ts +0 -83
  209. package/dist/shared/bridge-contract.d.ts +0 -772
  210. package/dist/shared/bridge-contract.js +0 -169
  211. package/dist/shared/console-formatter.d.ts +0 -22
  212. package/dist/shared/console-formatter.js +0 -161
  213. package/dist/shared/constants.d.ts +0 -3
  214. package/dist/shared/constants.js +0 -3
  215. package/dist/shared/errors.d.ts +0 -16
  216. package/dist/shared/errors.js +0 -21
  217. package/dist/shared/esm-utils.d.ts +0 -28
  218. package/dist/shared/esm-utils.js +0 -97
  219. package/dist/shared/global-exposure.d.ts +0 -38
  220. package/dist/shared/global-exposure.js +0 -876
  221. package/dist/shared/in-memory-fs.d.ts +0 -16
  222. package/dist/shared/in-memory-fs.js +0 -115
  223. package/dist/shared/permissions.d.ts +0 -36
  224. package/dist/shared/permissions.js +0 -314
  225. package/dist/shared/require-setup.d.ts +0 -6
  226. package/dist/shared/require-setup.js +0 -9
  227. package/dist/test/block-store-conformance.d.ts +0 -34
  228. package/dist/test/block-store-conformance.js +0 -251
  229. package/dist/test/metadata-store-conformance.d.ts +0 -37
  230. package/dist/test/metadata-store-conformance.js +0 -646
  231. package/dist/test/vfs-conformance.d.ts +0 -65
  232. package/dist/test/vfs-conformance.js +0 -842
  233. package/dist/types.d.ts +0 -98
  234. package/dist/types.js +0 -6
  235. package/dist/vfs/chunked-vfs.d.ts +0 -66
  236. package/dist/vfs/chunked-vfs.js +0 -1290
  237. package/dist/vfs/host-block-store.d.ts +0 -19
  238. package/dist/vfs/host-block-store.js +0 -97
  239. package/dist/vfs/memory-block-store.d.ts +0 -16
  240. package/dist/vfs/memory-block-store.js +0 -45
  241. package/dist/vfs/memory-metadata.d.ts +0 -75
  242. package/dist/vfs/memory-metadata.js +0 -528
  243. package/dist/vfs/sqlite-metadata.d.ts +0 -91
  244. package/dist/vfs/sqlite-metadata.js +0 -582
  245. package/dist/vfs/types.d.ts +0 -210
  246. package/dist/vfs/types.js +0 -8
  247. /package/dist/{runtime-driver.js → generated/CreateVmConfig.js} +0 -0
  248. /package/dist/{shared/api-types.js → generated/FsPermissionRule.js} +0 -0
@@ -1,507 +0,0 @@
1
- import { KernelError } from "./types.js";
2
- const S_IFREG = 0o100000;
3
- const S_IFDIR = 0o040000;
4
- const S_IFLNK = 0o120000;
5
- const PROC_INO_BASE = 0xfffe_0000;
6
- const PROC_SELF_PREFIX = "/proc/self";
7
- const PROC_SYS_PREFIX = "/proc/sys";
8
- const PROC_SYS_KERNEL_PREFIX = "/proc/sys/kernel";
9
- const PROC_SYS_KERNEL_HOSTNAME_PATH = "/proc/sys/kernel/hostname";
10
- const PROC_PID_ENTRIES = [
11
- { name: "fd", isDirectory: true },
12
- { name: "cwd", isDirectory: false, isSymbolicLink: true },
13
- { name: "exe", isDirectory: false, isSymbolicLink: true },
14
- { name: "environ", isDirectory: false },
15
- ];
16
- const PROC_ROOT_ENTRIES = [
17
- { name: "self", isDirectory: false, isSymbolicLink: true },
18
- { name: "sys", isDirectory: true },
19
- ];
20
- const PROC_SYS_ENTRIES = [
21
- { name: "kernel", isDirectory: true },
22
- ];
23
- const PROC_SYS_KERNEL_ENTRIES = [
24
- { name: "hostname", isDirectory: false },
25
- ];
26
- function normalizePath(path) {
27
- if (!path)
28
- return "/";
29
- let normalized = path.startsWith("/") ? path : `/${path}`;
30
- normalized = normalized.replace(/\/+/g, "/");
31
- if (normalized.length > 1 && normalized.endsWith("/")) {
32
- normalized = normalized.slice(0, -1);
33
- }
34
- const parts = normalized.split("/");
35
- const resolved = [];
36
- for (const part of parts) {
37
- if (!part || part === ".")
38
- continue;
39
- if (part === "..") {
40
- resolved.pop();
41
- continue;
42
- }
43
- resolved.push(part);
44
- }
45
- return resolved.length === 0 ? "/" : `/${resolved.join("/")}`;
46
- }
47
- function isProcPath(path) {
48
- const normalized = normalizePath(path);
49
- return normalized === "/proc" || normalized.startsWith("/proc/");
50
- }
51
- function procIno(seed) {
52
- let hash = 0;
53
- for (let i = 0; i < seed.length; i++) {
54
- hash = ((hash * 33) ^ seed.charCodeAt(i)) >>> 0;
55
- }
56
- return PROC_INO_BASE + (hash & 0xffff);
57
- }
58
- function dirStat(seed) {
59
- const now = Date.now();
60
- return {
61
- mode: S_IFDIR | 0o555,
62
- size: 0,
63
- isDirectory: true,
64
- isSymbolicLink: false,
65
- atimeMs: now,
66
- mtimeMs: now,
67
- ctimeMs: now,
68
- birthtimeMs: now,
69
- ino: procIno(seed),
70
- nlink: 2,
71
- uid: 0,
72
- gid: 0,
73
- };
74
- }
75
- function fileStat(seed, size) {
76
- const now = Date.now();
77
- return {
78
- mode: S_IFREG | 0o444,
79
- size,
80
- isDirectory: false,
81
- isSymbolicLink: false,
82
- atimeMs: now,
83
- mtimeMs: now,
84
- ctimeMs: now,
85
- birthtimeMs: now,
86
- ino: procIno(seed),
87
- nlink: 1,
88
- uid: 0,
89
- gid: 0,
90
- };
91
- }
92
- function linkStat(seed, target) {
93
- const now = Date.now();
94
- return {
95
- mode: S_IFLNK | 0o777,
96
- size: target.length,
97
- isDirectory: false,
98
- isSymbolicLink: true,
99
- atimeMs: now,
100
- mtimeMs: now,
101
- ctimeMs: now,
102
- birthtimeMs: now,
103
- ino: procIno(seed),
104
- nlink: 1,
105
- uid: 0,
106
- gid: 0,
107
- };
108
- }
109
- function parseProcPath(path) {
110
- const normalized = normalizePath(path);
111
- if (normalized === "/proc" || normalized === PROC_SELF_PREFIX || !normalized.startsWith("/proc/")) {
112
- return null;
113
- }
114
- const parts = normalized.slice("/proc/".length).split("/");
115
- const pid = Number(parts[0]);
116
- if (!Number.isInteger(pid) || pid < 0)
117
- return null;
118
- return { pid, tail: parts.slice(1) };
119
- }
120
- function encodeText(content) {
121
- return new TextEncoder().encode(content);
122
- }
123
- function encodeEnviron(env) {
124
- const entries = Object.entries(env);
125
- if (entries.length === 0)
126
- return new Uint8Array(0);
127
- return encodeText(entries.map(([key, value]) => `${key}=${value}`).join("\0") + "\0");
128
- }
129
- function resolveExecPath(command) {
130
- if (!command)
131
- return "";
132
- return command.startsWith("/") ? command : `/bin/${command}`;
133
- }
134
- function clonePathArg(path, normalized) {
135
- return path === normalized ? path : normalized;
136
- }
137
- export function resolveProcSelfPath(path, pid) {
138
- const normalized = normalizePath(path);
139
- if (normalized === PROC_SELF_PREFIX)
140
- return `/proc/${pid}`;
141
- if (normalized.startsWith(`${PROC_SELF_PREFIX}/`)) {
142
- return `/proc/${pid}${normalized.slice(PROC_SELF_PREFIX.length)}`;
143
- }
144
- return normalized;
145
- }
146
- export function createProcessScopedFileSystem(vfs, pid) {
147
- const selfTarget = `/proc/${pid}`;
148
- return {
149
- readFile: (path) => vfs.readFile(resolveProcSelfPath(path, pid)),
150
- readTextFile: (path) => vfs.readTextFile(resolveProcSelfPath(path, pid)),
151
- readDir: (path) => vfs.readDir(resolveProcSelfPath(path, pid)),
152
- readDirWithTypes: (path) => vfs.readDirWithTypes(resolveProcSelfPath(path, pid)),
153
- writeFile: (path, content) => vfs.writeFile(resolveProcSelfPath(path, pid), content),
154
- createDir: (path) => vfs.createDir(resolveProcSelfPath(path, pid)),
155
- mkdir: (path, options) => vfs.mkdir(resolveProcSelfPath(path, pid), options),
156
- exists: (path) => vfs.exists(resolveProcSelfPath(path, pid)),
157
- stat: (path) => vfs.stat(resolveProcSelfPath(path, pid)),
158
- removeFile: (path) => vfs.removeFile(resolveProcSelfPath(path, pid)),
159
- removeDir: (path) => vfs.removeDir(resolveProcSelfPath(path, pid)),
160
- rename: (oldPath, newPath) => vfs.rename(resolveProcSelfPath(oldPath, pid), resolveProcSelfPath(newPath, pid)),
161
- realpath: async (path) => {
162
- const normalized = normalizePath(path);
163
- if (normalized === PROC_SELF_PREFIX)
164
- return selfTarget;
165
- return vfs.realpath(resolveProcSelfPath(path, pid));
166
- },
167
- symlink: (target, linkPath) => vfs.symlink(target, resolveProcSelfPath(linkPath, pid)),
168
- readlink: async (path) => {
169
- const normalized = normalizePath(path);
170
- if (normalized === PROC_SELF_PREFIX)
171
- return selfTarget;
172
- return vfs.readlink(resolveProcSelfPath(path, pid));
173
- },
174
- lstat: async (path) => {
175
- const normalized = normalizePath(path);
176
- if (normalized === PROC_SELF_PREFIX)
177
- return linkStat("self", selfTarget);
178
- return vfs.lstat(resolveProcSelfPath(path, pid));
179
- },
180
- link: (oldPath, newPath) => vfs.link(resolveProcSelfPath(oldPath, pid), resolveProcSelfPath(newPath, pid)),
181
- chmod: (path, mode) => vfs.chmod(resolveProcSelfPath(path, pid), mode),
182
- chown: (path, uid, gid) => vfs.chown(resolveProcSelfPath(path, pid), uid, gid),
183
- utimes: (path, atime, mtime) => vfs.utimes(resolveProcSelfPath(path, pid), atime, mtime),
184
- truncate: (path, length) => vfs.truncate(resolveProcSelfPath(path, pid), length),
185
- pread: (path, offset, length) => vfs.pread(resolveProcSelfPath(path, pid), offset, length),
186
- pwrite: (path, offset, data) => vfs.pwrite(resolveProcSelfPath(path, pid), offset, data),
187
- };
188
- }
189
- export function createProcLayer(vfs, options) {
190
- const syncVfs = vfs;
191
- const kernelHostname = encodeText(`${options.hostname ?? "sandbox"}\n`);
192
- const getProcess = (pid) => {
193
- const entry = options.processTable.get(pid);
194
- if (!entry)
195
- throw new KernelError("ENOENT", `no such process ${pid}`);
196
- return entry;
197
- };
198
- const getFdEntry = (pid, fd) => {
199
- const table = options.fdTableManager.get(pid);
200
- const entry = table?.get(fd);
201
- if (!entry)
202
- throw new KernelError("ENOENT", `no such fd ${fd} for process ${pid}`);
203
- return entry;
204
- };
205
- const listPids = () => Array.from(options.processTable.listProcesses().keys()).sort((a, b) => a - b);
206
- const listOpenFds = (pid) => {
207
- const table = options.fdTableManager.get(pid);
208
- if (!table)
209
- return [];
210
- const fds = [];
211
- for (const entry of table)
212
- fds.push(entry.fd);
213
- return fds.sort((a, b) => a - b);
214
- };
215
- const getLinkTarget = (pid, tail) => {
216
- if (tail.length === 1 && tail[0] === "cwd")
217
- return getProcess(pid).cwd;
218
- if (tail.length === 1 && tail[0] === "exe")
219
- return resolveExecPath(getProcess(pid).command);
220
- if (tail.length === 2 && tail[0] === "fd") {
221
- const fd = Number(tail[1]);
222
- if (!Number.isInteger(fd) || fd < 0)
223
- throw new KernelError("ENOENT", `invalid fd ${tail[1]}`);
224
- return getFdEntry(pid, fd).description.path;
225
- }
226
- throw new KernelError("ENOENT", `unsupported proc link ${tail.join("/")}`);
227
- };
228
- const getProcFile = (pid, tail) => {
229
- if (tail.length === 1 && tail[0] === "cwd")
230
- return encodeText(getProcess(pid).cwd);
231
- if (tail.length === 1 && tail[0] === "exe")
232
- return encodeText(resolveExecPath(getProcess(pid).command));
233
- if (tail.length === 1 && tail[0] === "environ")
234
- return encodeEnviron(getProcess(pid).env);
235
- if (tail.length === 2 && tail[0] === "fd")
236
- return encodeText(getLinkTarget(pid, tail));
237
- throw new KernelError("ENOENT", `unsupported proc file ${tail.join("/")}`);
238
- };
239
- const getProcStat = async (path, followSymlinks) => {
240
- const normalized = normalizePath(path);
241
- if (normalized === "/proc")
242
- return dirStat("proc");
243
- if (normalized === PROC_SYS_PREFIX)
244
- return dirStat("proc:sys");
245
- if (normalized === PROC_SYS_KERNEL_PREFIX)
246
- return dirStat("proc:sys:kernel");
247
- if (normalized === PROC_SYS_KERNEL_HOSTNAME_PATH) {
248
- return fileStat("proc:sys:kernel:hostname", kernelHostname.length);
249
- }
250
- if (normalized === PROC_SELF_PREFIX) {
251
- return followSymlinks ? dirStat("proc-self") : linkStat("proc-self-link", PROC_SELF_PREFIX);
252
- }
253
- const parsed = parseProcPath(normalized);
254
- if (!parsed)
255
- throw new KernelError("ENOENT", `no such file or directory: ${normalized}`);
256
- const { pid, tail } = parsed;
257
- getProcess(pid);
258
- if (tail.length === 0)
259
- return dirStat(`proc:${pid}`);
260
- if (tail.length === 1 && tail[0] === "fd")
261
- return dirStat(`proc:${pid}:fd`);
262
- if (tail.length === 1 && tail[0] === "environ") {
263
- return fileStat(`proc:${pid}:environ`, encodeEnviron(getProcess(pid).env).length);
264
- }
265
- if ((tail.length === 1 && (tail[0] === "cwd" || tail[0] === "exe"))
266
- || (tail.length === 2 && tail[0] === "fd")) {
267
- const target = getLinkTarget(pid, tail);
268
- if (!followSymlinks)
269
- return linkStat(`proc:${pid}:${tail.join(":")}`, target);
270
- if (target.startsWith("/proc/")) {
271
- return getProcStat(target, true);
272
- }
273
- try {
274
- return await vfs.stat(target);
275
- }
276
- catch {
277
- return linkStat(`proc:${pid}:${tail.join(":")}`, target);
278
- }
279
- }
280
- throw new KernelError("ENOENT", `no such proc entry: ${normalized}`);
281
- };
282
- const rejectMutation = (path) => {
283
- if (isProcPath(path))
284
- throw new KernelError("EPERM", `cannot modify ${normalizePath(path)}`);
285
- };
286
- const wrapped = {
287
- prepareOpenSync(path, flags) {
288
- const normalized = normalizePath(path);
289
- if (isProcPath(normalized))
290
- return false;
291
- return syncVfs.prepareOpenSync?.(clonePathArg(path, normalized), flags) ?? false;
292
- },
293
- async readFile(path) {
294
- const normalized = normalizePath(path);
295
- if (!isProcPath(normalized))
296
- return vfs.readFile(clonePathArg(path, normalized));
297
- if (normalized === "/proc" || normalized === PROC_SELF_PREFIX) {
298
- throw new KernelError("EISDIR", `illegal operation on a directory, read '${normalized}'`);
299
- }
300
- if (normalized === PROC_SYS_PREFIX || normalized === PROC_SYS_KERNEL_PREFIX) {
301
- throw new KernelError("EISDIR", `illegal operation on a directory, read '${normalized}'`);
302
- }
303
- if (normalized === PROC_SYS_KERNEL_HOSTNAME_PATH) {
304
- return kernelHostname;
305
- }
306
- const parsed = parseProcPath(normalized);
307
- if (!parsed)
308
- throw new KernelError("ENOENT", `no such file or directory: ${normalized}`);
309
- const { pid, tail } = parsed;
310
- if (tail.length === 0 || (tail.length === 1 && tail[0] === "fd")) {
311
- throw new KernelError("EISDIR", `illegal operation on a directory, read '${normalized}'`);
312
- }
313
- return getProcFile(pid, tail);
314
- },
315
- async pread(path, offset, length) {
316
- const content = await this.readFile(path);
317
- if (offset >= content.length)
318
- return new Uint8Array(0);
319
- return content.slice(offset, offset + length);
320
- },
321
- async readTextFile(path) {
322
- const content = await this.readFile(path);
323
- return new TextDecoder().decode(content);
324
- },
325
- async readDir(path) {
326
- return (await this.readDirWithTypes(path)).map((entry) => entry.name);
327
- },
328
- async readDirWithTypes(path) {
329
- const normalized = normalizePath(path);
330
- if (!isProcPath(normalized))
331
- return vfs.readDirWithTypes(clonePathArg(path, normalized));
332
- if (normalized === "/proc") {
333
- return [
334
- ...PROC_ROOT_ENTRIES,
335
- ...listPids().map((pid) => ({ name: String(pid), isDirectory: true })),
336
- ];
337
- }
338
- if (normalized === PROC_SYS_PREFIX) {
339
- return PROC_SYS_ENTRIES;
340
- }
341
- if (normalized === PROC_SYS_KERNEL_PREFIX) {
342
- return PROC_SYS_KERNEL_ENTRIES;
343
- }
344
- if (normalized === PROC_SELF_PREFIX) {
345
- throw new KernelError("ENOENT", `no such file or directory: ${normalized}`);
346
- }
347
- const parsed = parseProcPath(normalized);
348
- if (!parsed)
349
- throw new KernelError("ENOENT", `no such file or directory: ${normalized}`);
350
- const { pid, tail } = parsed;
351
- getProcess(pid);
352
- if (tail.length === 0)
353
- return PROC_PID_ENTRIES;
354
- if (tail.length === 1 && tail[0] === "fd") {
355
- return listOpenFds(pid).map((fd) => ({ name: String(fd), isDirectory: false, isSymbolicLink: true }));
356
- }
357
- throw new KernelError("ENOTDIR", `not a directory: ${normalized}`);
358
- },
359
- async writeFile(path, content) {
360
- const normalized = normalizePath(path);
361
- rejectMutation(normalized);
362
- return vfs.writeFile(clonePathArg(path, normalized), content);
363
- },
364
- async createDir(path) {
365
- const normalized = normalizePath(path);
366
- rejectMutation(normalized);
367
- return vfs.createDir(clonePathArg(path, normalized));
368
- },
369
- async mkdir(path, optionsArg) {
370
- const normalized = normalizePath(path);
371
- rejectMutation(normalized);
372
- return vfs.mkdir(clonePathArg(path, normalized), optionsArg);
373
- },
374
- async exists(path) {
375
- const normalized = normalizePath(path);
376
- if (!isProcPath(normalized))
377
- return vfs.exists(clonePathArg(path, normalized));
378
- if (normalized === "/proc" ||
379
- normalized === PROC_SELF_PREFIX ||
380
- normalized === PROC_SYS_PREFIX ||
381
- normalized === PROC_SYS_KERNEL_PREFIX ||
382
- normalized === PROC_SYS_KERNEL_HOSTNAME_PATH) {
383
- return true;
384
- }
385
- const parsed = parseProcPath(normalized);
386
- if (!parsed)
387
- return false;
388
- const { pid, tail } = parsed;
389
- if (!options.processTable.get(pid))
390
- return false;
391
- if (tail.length === 0 || (tail.length === 1 && tail[0] === "fd"))
392
- return true;
393
- if (tail.length === 1 && (tail[0] === "cwd" || tail[0] === "exe" || tail[0] === "environ"))
394
- return true;
395
- if (tail.length === 2 && tail[0] === "fd") {
396
- const fd = Number(tail[1]);
397
- return Number.isInteger(fd) && fd >= 0 && options.fdTableManager.get(pid)?.get(fd) !== undefined;
398
- }
399
- return false;
400
- },
401
- async stat(path) {
402
- const normalized = normalizePath(path);
403
- if (!isProcPath(normalized))
404
- return vfs.stat(clonePathArg(path, normalized));
405
- return getProcStat(normalized, true);
406
- },
407
- async removeFile(path) {
408
- const normalized = normalizePath(path);
409
- rejectMutation(normalized);
410
- return vfs.removeFile(clonePathArg(path, normalized));
411
- },
412
- async removeDir(path) {
413
- const normalized = normalizePath(path);
414
- rejectMutation(normalized);
415
- return vfs.removeDir(clonePathArg(path, normalized));
416
- },
417
- async rename(oldPath, newPath) {
418
- const normalizedOld = normalizePath(oldPath);
419
- const normalizedNew = normalizePath(newPath);
420
- rejectMutation(normalizedOld);
421
- rejectMutation(normalizedNew);
422
- return vfs.rename(clonePathArg(oldPath, normalizedOld), clonePathArg(newPath, normalizedNew));
423
- },
424
- async realpath(path) {
425
- const normalized = normalizePath(path);
426
- if (!isProcPath(normalized))
427
- return vfs.realpath(clonePathArg(path, normalized));
428
- if (normalized === "/proc" ||
429
- normalized === PROC_SELF_PREFIX ||
430
- normalized === PROC_SYS_PREFIX ||
431
- normalized === PROC_SYS_KERNEL_PREFIX ||
432
- normalized === PROC_SYS_KERNEL_HOSTNAME_PATH) {
433
- return normalized;
434
- }
435
- const parsed = parseProcPath(normalized);
436
- if (!parsed)
437
- throw new KernelError("ENOENT", `no such file or directory: ${normalized}`);
438
- const { pid, tail } = parsed;
439
- getProcess(pid);
440
- if (tail.length === 0 || (tail.length === 1 && tail[0] === "fd"))
441
- return normalized;
442
- if (tail.length === 1 && tail[0] === "environ")
443
- return normalized;
444
- if ((tail.length === 1 && (tail[0] === "cwd" || tail[0] === "exe"))
445
- || (tail.length === 2 && tail[0] === "fd")) {
446
- return getLinkTarget(pid, tail);
447
- }
448
- throw new KernelError("ENOENT", `no such file or directory: ${normalized}`);
449
- },
450
- async symlink(target, linkPath) {
451
- const normalized = normalizePath(linkPath);
452
- rejectMutation(normalized);
453
- return vfs.symlink(target, clonePathArg(linkPath, normalized));
454
- },
455
- async readlink(path) {
456
- const normalized = normalizePath(path);
457
- if (!isProcPath(normalized))
458
- return vfs.readlink(clonePathArg(path, normalized));
459
- if (normalized === PROC_SELF_PREFIX)
460
- return PROC_SELF_PREFIX;
461
- const parsed = parseProcPath(normalized);
462
- if (!parsed)
463
- throw new KernelError("EINVAL", `invalid argument: ${normalized}`);
464
- const { pid, tail } = parsed;
465
- return getLinkTarget(pid, tail);
466
- },
467
- async lstat(path) {
468
- const normalized = normalizePath(path);
469
- if (!isProcPath(normalized))
470
- return vfs.lstat(clonePathArg(path, normalized));
471
- return getProcStat(normalized, false);
472
- },
473
- async link(oldPath, newPath) {
474
- const normalizedOld = normalizePath(oldPath);
475
- const normalizedNew = normalizePath(newPath);
476
- rejectMutation(normalizedOld);
477
- rejectMutation(normalizedNew);
478
- return vfs.link(clonePathArg(oldPath, normalizedOld), clonePathArg(newPath, normalizedNew));
479
- },
480
- async chmod(path, mode) {
481
- const normalized = normalizePath(path);
482
- rejectMutation(normalized);
483
- return vfs.chmod(clonePathArg(path, normalized), mode);
484
- },
485
- async chown(path, uid, gid) {
486
- const normalized = normalizePath(path);
487
- rejectMutation(normalized);
488
- return vfs.chown(clonePathArg(path, normalized), uid, gid);
489
- },
490
- async utimes(path, atime, mtime) {
491
- const normalized = normalizePath(path);
492
- rejectMutation(normalized);
493
- return vfs.utimes(clonePathArg(path, normalized), atime, mtime);
494
- },
495
- async truncate(path, length) {
496
- const normalized = normalizePath(path);
497
- rejectMutation(normalized);
498
- return vfs.truncate(clonePathArg(path, normalized), length);
499
- },
500
- async pwrite(path, offset, data) {
501
- const normalized = normalizePath(path);
502
- rejectMutation(normalized);
503
- return vfs.pwrite(clonePathArg(path, normalized), offset, data);
504
- },
505
- };
506
- return wrapped;
507
- }
@@ -1,126 +0,0 @@
1
- /**
2
- * Process table.
3
- *
4
- * Universal process tracking across all runtimes. Owns PID allocation,
5
- * parent-child relationships, waitpid, and signal routing. A WasmVM
6
- * shell can waitpid on a Node child process.
7
- */
8
- import type { DriverProcess, ProcessContext, ProcessEntry, ProcessInfo, SignalHandler, ProcessSignalState, KernelLogger } from "./types.js";
9
- export declare class ProcessTable {
10
- private entries;
11
- private nextPid;
12
- private waiters;
13
- private zombieTimers;
14
- /** Pending alarm timers per PID: { timer, scheduledAt (ms epoch) }. */
15
- private alarmTimers;
16
- private log;
17
- /** Called when a process exits, before waiters are notified. */
18
- onProcessExit: ((pid: number) => void) | null;
19
- /** Called when a zombie process is reaped (removed from the table). */
20
- onProcessReap: ((pid: number) => void) | null;
21
- constructor(logger?: KernelLogger);
22
- /** Atomically allocate the next PID. */
23
- allocatePid(): number;
24
- /** Register a process with a pre-allocated PID. */
25
- register(pid: number, driver: string, command: string, args: string[], ctx: ProcessContext, driverProcess: DriverProcess): ProcessEntry;
26
- get(pid: number): ProcessEntry | undefined;
27
- /** Count pending zombie cleanup timers (test observability). */
28
- get zombieTimerCount(): number;
29
- /** Count running (non-exited) processes. */
30
- runningCount(): number;
31
- /** Mark a process as exited with the given code. Notifies waiters. */
32
- markExited(pid: number, exitCode: number): void;
33
- /**
34
- * Wait for a process to exit.
35
- * If already exited, resolves immediately. Otherwise blocks until exit.
36
- * With WNOHANG option, returns null immediately if process is still running.
37
- */
38
- waitpid(pid: number, options?: number): Promise<{
39
- pid: number;
40
- status: number;
41
- termSignal: number;
42
- } | null>;
43
- /**
44
- * Send a signal to a process or process group.
45
- * If pid > 0, signal a single process.
46
- * If pid < 0, signal all processes in process group abs(pid).
47
- */
48
- kill(pid: number, signal: number): void;
49
- /**
50
- * Deliver a signal to a process, respecting handlers, blocking, and coalescing.
51
- *
52
- * SIGKILL and SIGSTOP cannot be caught, blocked, or ignored (POSIX).
53
- * Blocked signals are queued in pendingSignals; standard signals (1-31) coalesce.
54
- * If a handler is registered, it is invoked with sa_mask temporarily blocked.
55
- */
56
- private deliverSignal;
57
- /**
58
- * Dispatch a signal to a process — check handler, then apply.
59
- * Called for unblocked signals and when delivering pending signals.
60
- */
61
- private dispatchSignal;
62
- /** Wake signal-aware waiters after a signal has been dispatched. */
63
- private recordSignalDelivery;
64
- /** Apply the kernel default action for a signal. */
65
- private applyDefaultAction;
66
- /** Deliver pending signals that are no longer blocked (lowest signal number first). */
67
- private deliverPendingSignals;
68
- /**
69
- * Schedule SIGALRM delivery after `seconds`. Returns previous alarm remaining (0 if none).
70
- * alarm(pid, 0) cancels any pending alarm. A new alarm replaces the previous one.
71
- */
72
- alarm(pid: number, seconds: number): number;
73
- /**
74
- * Register a signal handler (POSIX sigaction).
75
- * Returns the previous handler for the signal, or undefined if none was set.
76
- * SIGKILL and SIGSTOP cannot be caught or ignored.
77
- */
78
- sigaction(pid: number, signal: number, handler: SignalHandler): SignalHandler | undefined;
79
- /**
80
- * Modify the blocked signal mask (POSIX sigprocmask).
81
- * Returns the previous blocked set.
82
- * SIGKILL and SIGSTOP cannot be blocked.
83
- */
84
- sigprocmask(pid: number, how: number, set: Set<number>): Set<number>;
85
- /** Get the signal state for a process (read-only view). */
86
- getSignalState(pid: number): ProcessSignalState;
87
- /** Suspend a process (SIGTSTP/SIGSTOP). Sets status to 'stopped'. */
88
- stop(pid: number): void;
89
- /** Resume a stopped process (SIGCONT). Sets status back to 'running'. */
90
- cont(pid: number): void;
91
- /** Cancel a pending alarm for a process. */
92
- private cancelAlarm;
93
- /** Set process group ID. Process can join existing group or create new one. */
94
- setpgid(pid: number, pgid: number): void;
95
- /** Get process group ID. */
96
- getpgid(pid: number): number;
97
- /** Create a new session. Process becomes session leader and process group leader. */
98
- setsid(pid: number): number;
99
- /** Get session ID. */
100
- getsid(pid: number): number;
101
- /** Get the parent PID for a process. */
102
- getppid(pid: number): number;
103
- /**
104
- * Send a signal to a process group, skipping session leaders.
105
- * Returns count of processes actually signaled.
106
- * Used for PTY-originated SIGINT where the session leader (shell)
107
- * cannot handle signals gracefully (WasmVM worker.terminate()).
108
- */
109
- killGroupExcludeLeaders(pgid: number, signal: number): number;
110
- /** Check if any running process belongs to the given process group. */
111
- hasProcessGroup(pgid: number): boolean;
112
- /** Get a read-only view of process info for all processes. */
113
- listProcesses(): Map<number, ProcessInfo>;
114
- /** Remove a zombie process. */
115
- private reap;
116
- /** Register an active handle for a process. Throws EAGAIN if budget exceeded. */
117
- registerHandle(pid: number, id: string, description: string): void;
118
- /** Unregister an active handle. Throws EBADF if handle not found. */
119
- unregisterHandle(pid: number, id: string): void;
120
- /** Set the maximum number of active handles for a process. 0 = unlimited. */
121
- setHandleLimit(pid: number, limit: number): void;
122
- /** Get the active handles for a process (read-only copy). */
123
- getHandles(pid: number): Map<string, string>;
124
- /** Terminate all running processes and clear pending timers. */
125
- terminateAll(): Promise<void>;
126
- }