@nimbus-sh/core 0.3.0 → 0.5.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/LICENSE +21 -0
- package/README.md +140 -0
- package/dist/_shared/error-text.d.ts +15 -0
- package/dist/_shared/error-text.d.ts.map +1 -0
- package/dist/_shared/error-text.js +21 -0
- package/dist/_shared/exports-resolver.d.ts +19 -7
- package/dist/_shared/exports-resolver.d.ts.map +1 -1
- package/dist/_shared/exports-resolver.js +1 -1
- package/dist/_shared/retry.d.ts.map +1 -1
- package/dist/_shared/retry.js +3 -1
- package/dist/_shared/tarball-stream.d.ts +93 -0
- package/dist/_shared/tarball-stream.d.ts.map +1 -0
- package/dist/_shared/tarball-stream.js +235 -0
- package/dist/_shared/tarball.d.ts +17 -0
- package/dist/_shared/tarball.d.ts.map +1 -0
- package/dist/_shared/tarball.js +39 -0
- package/dist/_shared/w7-frame.js +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +30 -16
- package/dist/observability/oom-classify.d.ts +1 -1
- package/dist/observability/oom-classify.d.ts.map +1 -1
- package/dist/observability/oom-classify.js +7 -0
- package/dist/observability/oom-discriminator.d.ts +1 -1
- package/dist/runtime/clang-runner.d.ts +38 -0
- package/dist/runtime/clang-runner.d.ts.map +1 -0
- package/dist/runtime/clang-runner.js +866 -0
- package/dist/runtime/esbuild-service.d.ts +4 -3
- package/dist/runtime/esbuild-service.d.ts.map +1 -1
- package/dist/runtime/esbuild-service.js +9 -4
- package/dist/runtime/facet-host.d.ts +12 -0
- package/dist/runtime/facet-host.d.ts.map +1 -1
- package/dist/runtime/installed-runtimes.d.ts +4 -3
- package/dist/runtime/installed-runtimes.d.ts.map +1 -1
- package/dist/runtime/local-facet-host.d.ts.map +1 -1
- package/dist/runtime/local-facet-host.js +29 -9
- package/dist/runtime/long-running-handle.d.ts +3 -3
- package/dist/runtime/long-running-handle.d.ts.map +1 -1
- package/dist/runtime/os-contracts.d.ts +7 -5
- package/dist/runtime/os-contracts.d.ts.map +1 -1
- package/dist/runtime/port-registry.d.ts +28 -0
- package/dist/runtime/port-registry.d.ts.map +1 -1
- package/dist/runtime/port-registry.js +79 -9
- package/dist/runtime/process-logs.d.ts +9 -1
- package/dist/runtime/process-logs.d.ts.map +1 -1
- package/dist/runtime/project-detect.d.ts +6 -1
- package/dist/runtime/project-detect.d.ts.map +1 -1
- package/dist/runtime/require-resolver.d.ts.map +1 -1
- package/dist/runtime/require-resolver.js +3 -4
- package/dist/runtime/ruby-gems.d.ts +30 -0
- package/dist/runtime/ruby-gems.d.ts.map +1 -0
- package/dist/runtime/ruby-gems.js +636 -0
- package/dist/runtime/ruby-runner.d.ts +127 -0
- package/dist/runtime/ruby-runner.d.ts.map +1 -0
- package/dist/runtime/ruby-runner.js +1357 -0
- package/dist/runtime/runtime-registry.d.ts +4 -3
- package/dist/runtime/runtime-registry.d.ts.map +1 -1
- package/dist/runtime/runtime-registry.js +2 -1
- package/dist/runtime/session-process-supervisor.d.ts +15 -0
- package/dist/runtime/session-process-supervisor.d.ts.map +1 -1
- package/dist/runtime/session-process-supervisor.js +30 -0
- package/dist/runtime/sqlite-runtime-fs-bridge.js +1 -5
- package/dist/runtime/virtual-socket-kernel.d.ts.map +1 -1
- package/dist/runtime/virtual-socket-kernel.generated.d.ts +1 -1
- package/dist/runtime/virtual-socket-kernel.generated.d.ts.map +1 -1
- package/dist/runtime/virtual-socket-kernel.generated.js +2 -2
- package/dist/runtime/virtual-socket-kernel.js +10 -5
- package/dist/runtime/wasm-runner.d.ts.map +1 -1
- package/dist/runtime/wasm-runner.js +22 -14
- package/dist/shell/features.d.ts.map +1 -1
- package/dist/shell/features.js +5 -4
- package/dist/shell/unix-commands.d.ts +14 -1
- package/dist/shell/unix-commands.d.ts.map +1 -1
- package/dist/shell/unix-commands.js +115 -69
- package/dist/substrate/lifo/commands/net/ip.d.ts.map +1 -1
- package/dist/substrate/lifo/commands/system/ps.d.ts +2 -1
- package/dist/substrate/lifo/commands/system/ps.d.ts.map +1 -1
- package/dist/substrate/lifo/kernel/ServiceManager.d.ts.map +1 -1
- package/dist/substrate/lifo/kernel/ServiceManager.js +0 -2
- package/dist/substrate/lifo/kernel/network/NetworkStack.d.ts +22 -11
- package/dist/substrate/lifo/kernel/network/NetworkStack.d.ts.map +1 -1
- package/dist/substrate/lifo/kernel/network/NetworkStack.js +0 -2
- package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.d.ts +2 -1
- package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.d.ts.map +1 -1
- package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.js +3 -4
- package/dist/substrate/lifo/kernel/vfs/VFS.d.ts +17 -0
- package/dist/substrate/lifo/kernel/vfs/VFS.d.ts.map +1 -1
- package/dist/substrate/lifo/kernel/vfs/VFS.js +33 -0
- package/dist/substrate/lifo/node-compat/esbuild.d.ts.map +1 -1
- package/dist/substrate/lifo/node-compat/esbuild.js +2 -4
- package/dist/substrate/lifo/node-compat/index.d.ts.map +1 -1
- package/dist/substrate/lifo/node-compat/index.js +3 -2
- package/dist/substrate/lifo/node-compat/loose-equality.d.ts +19 -0
- package/dist/substrate/lifo/node-compat/loose-equality.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/loose-equality.js +91 -0
- package/dist/substrate/lifo/node-compat/process.d.ts.map +1 -1
- package/dist/substrate/lifo/node-compat/process.js +6 -3
- package/dist/substrate/lifo/shell/Shell.d.ts +19 -0
- package/dist/substrate/lifo/shell/Shell.d.ts.map +1 -1
- package/dist/substrate/lifo/shell/Shell.js +86 -75
- package/dist/substrate/lifo/shell/lexer.d.ts +9 -0
- package/dist/substrate/lifo/shell/lexer.d.ts.map +1 -1
- package/dist/substrate/lifo/shell/lexer.js +40 -0
- package/dist/vfs/seed-project.d.ts.map +1 -1
- package/dist/vfs/seed-project.js +8 -2
- package/dist/vfs/sqlite-vfs.d.ts +61 -1
- package/dist/vfs/sqlite-vfs.d.ts.map +1 -1
- package/dist/vfs/sqlite-vfs.js +199 -35
- package/dist/workspace/nimbus-workspace.d.ts.map +1 -1
- package/dist/workspace/nimbus-workspace.js +9 -2
- package/package.json +4 -2
- package/src/_shared/error-text.ts +21 -0
- package/src/_shared/exports-resolver.ts +24 -4
- package/src/_shared/retry.ts +4 -2
- package/src/_shared/tarball-stream.ts +263 -0
- package/src/_shared/tarball.ts +46 -0
- package/src/_shared/w7-frame.ts +2 -1
- package/src/constants.ts +30 -16
- package/src/observability/oom-classify.ts +7 -0
- package/src/observability/oom-discriminator.ts +1 -1
- package/src/runtime/clang-runner.ts +924 -0
- package/src/runtime/esbuild-service.ts +16 -11
- package/src/runtime/facet-host.ts +12 -0
- package/src/runtime/installed-runtimes.ts +4 -3
- package/src/runtime/local-facet-host.ts +28 -8
- package/src/runtime/long-running-handle.ts +3 -3
- package/src/runtime/os-contracts.ts +7 -5
- package/src/runtime/port-registry.ts +97 -9
- package/src/runtime/process-logs.ts +12 -3
- package/src/runtime/project-detect.ts +7 -1
- package/src/runtime/require-resolver.ts +7 -7
- package/src/runtime/ruby-gems.ts +682 -0
- package/src/runtime/ruby-runner.ts +1484 -0
- package/src/runtime/runtime-registry.ts +9 -7
- package/src/runtime/session-process-supervisor.ts +27 -0
- package/src/runtime/sqlite-runtime-fs-bridge.ts +9 -6
- package/src/runtime/virtual-socket-kernel.generated.ts +2 -2
- package/src/runtime/virtual-socket-kernel.ts +10 -5
- package/src/runtime/wasm-runner.ts +55 -29
- package/src/shell/features.ts +5 -4
- package/src/shell/unix-commands.ts +273 -128
- package/src/substrate/lifo/commands/net/ip.ts +15 -15
- package/src/substrate/lifo/commands/system/ps.ts +2 -1
- package/src/substrate/lifo/kernel/ServiceManager.ts +0 -2
- package/src/substrate/lifo/kernel/network/NetworkStack.ts +24 -17
- package/src/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.ts +37 -12
- package/src/substrate/lifo/kernel/vfs/VFS.ts +34 -0
- package/src/substrate/lifo/node-compat/esbuild.ts +16 -8
- package/src/substrate/lifo/node-compat/index.ts +3 -2
- package/src/substrate/lifo/node-compat/loose-equality.ts +81 -0
- package/src/substrate/lifo/node-compat/process.ts +5 -2
- package/src/substrate/lifo/shell/Shell.ts +92 -70
- package/src/substrate/lifo/shell/lexer.ts +38 -0
- package/src/vfs/seed-project.ts +10 -3
- package/src/vfs/sqlite-vfs.ts +209 -36
- package/src/workspace/nimbus-workspace.ts +10 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketTunnel.d.ts","sourceRoot":"","sources":["../../../../../../src/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"WebSocketTunnel.d.ts","sourceRoot":"","sources":["../../../../../../src/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AA4B5D;;;;;;;;;;;GAWG;AACH,qBAAa,eAAgB,SAAQ,UAAU;IAC9C,IAAI,EAAE,KAAK,CAAS;IAEpB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,YAAY,CAAC,CAAqC;IAC1D,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAC,CAAgC;IACvD,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,gBAAgB,CAAuC;gBAG9D,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,YAAY,EAC1B,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,EACjD,SAAS,SAAY,EACrB,WAAW,GAAE,MAAM,GAAG,IAAW;IAgBlC,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC;;OAEG;IACY,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAUlC;;OAEG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBpC;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBzC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAc7B;;OAEG;YACW,OAAO;IA4CrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;YACW,iBAAiB;IAyE/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAK1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;OAEG;IACH,OAAO,CAAC,SAAS;IAgBjB;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;OAEG;IACM,QAAQ,IAAI,MAAM;IAQ3B;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,cAAc,IAAI,MAAM,EAAE;CAG1B"}
|
|
@@ -202,13 +202,12 @@ export class WebSocketTunnel extends BaseTunnel {
|
|
|
202
202
|
port = parseInt(match[1], 10);
|
|
203
203
|
path = match[2] || '/';
|
|
204
204
|
}
|
|
205
|
-
// Check if
|
|
206
|
-
|
|
205
|
+
// Check if a server is listening on the port
|
|
206
|
+
const handler = this.portRegistry?.get(port);
|
|
207
|
+
if (!handler) {
|
|
207
208
|
this.sendError(requestId, 404, `No server listening on port ${port}`);
|
|
208
209
|
return;
|
|
209
210
|
}
|
|
210
|
-
// Get handler
|
|
211
|
-
const handler = this.portRegistry.get(port);
|
|
212
211
|
// Create virtual request/response
|
|
213
212
|
const vReq = {
|
|
214
213
|
method,
|
|
@@ -77,6 +77,23 @@ export declare class VFS {
|
|
|
77
77
|
private rewriteFile;
|
|
78
78
|
appendFile(path: string, content: string | Uint8Array): void;
|
|
79
79
|
exists(path: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Type probes, mount-aware through {@link stat}.
|
|
82
|
+
*
|
|
83
|
+
* `CredentialedVfs` declares these and the durable coreutils call them on
|
|
84
|
+
* whatever `ctx.vfs` is, so a view that omitted them was not merely missing
|
|
85
|
+
* a convenience: `touch` on an existing file died with
|
|
86
|
+
* `targetVfs.isDirectory is not a function`, because `&&` short-circuited
|
|
87
|
+
* past the call whenever the file was absent — which is why creating a file
|
|
88
|
+
* worked and touching one did not.
|
|
89
|
+
*
|
|
90
|
+
* A structural miss answers false, the way `fs.existsSync` does. A denial
|
|
91
|
+
* still throws: traverse-x enforcement must not be maskable into a quiet
|
|
92
|
+
* false, which is the rule `SqliteVFS.probeInode` already follows.
|
|
93
|
+
*/
|
|
94
|
+
isDirectory(path: string): boolean;
|
|
95
|
+
isFile(path: string): boolean;
|
|
96
|
+
private probeType;
|
|
80
97
|
access(path: string, mode: number): void;
|
|
81
98
|
stat(path: string): Stat;
|
|
82
99
|
unlink(path: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VFS.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/kernel/vfs/VFS.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VFS.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/kernel/vfs/VFS.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAuB,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACtG,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,YAAY,EAAmB,MAAM,4BAA4B,CAAC;AAE3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AA6CnE,qBAAa,GAAG;IACd,OAAO,CAAC,IAAI,CAAQ;IACpB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,OAAO,CAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB,2FAA2F;IAC3F,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,OAAO,CAAC,IAAI,CAAC,CAAU;gBAEX,YAAY,CAAC,EAAE,YAAY;IAKvC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG;IAYtB,KAAK,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAC7C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAwB3D,OAAO,CAAC,MAAM;IAOd;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,aAAa,GAAG,IAAI;IAepE;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAS3B;;;OAGG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAIjE,OAAO,IAAI,KAAK;IAIhB,kBAAkB,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI;IAMrC;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,WAAW;IAqBnB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,UAAU;IAMlB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAoBlC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAOpC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAqC3D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgBxB;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU;IAanE;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAUjE,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAU1C,OAAO,CAAC,aAAa;IAKrB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAkCnB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAa5D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAY7B;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIlC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,OAAO,CAAC,SAAS;IAYjB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAkBxC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkBxB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA8B1B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAqC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAgBzC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAiBvC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAajE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgBzB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IA2C5D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA4BzB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IA0C/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IA+B/C;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAiBnC"}
|
|
@@ -384,6 +384,39 @@ export class VFS {
|
|
|
384
384
|
return false;
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Type probes, mount-aware through {@link stat}.
|
|
389
|
+
*
|
|
390
|
+
* `CredentialedVfs` declares these and the durable coreutils call them on
|
|
391
|
+
* whatever `ctx.vfs` is, so a view that omitted them was not merely missing
|
|
392
|
+
* a convenience: `touch` on an existing file died with
|
|
393
|
+
* `targetVfs.isDirectory is not a function`, because `&&` short-circuited
|
|
394
|
+
* past the call whenever the file was absent — which is why creating a file
|
|
395
|
+
* worked and touching one did not.
|
|
396
|
+
*
|
|
397
|
+
* A structural miss answers false, the way `fs.existsSync` does. A denial
|
|
398
|
+
* still throws: traverse-x enforcement must not be maskable into a quiet
|
|
399
|
+
* false, which is the rule `SqliteVFS.probeInode` already follows.
|
|
400
|
+
*/
|
|
401
|
+
isDirectory(path) {
|
|
402
|
+
return this.probeType(path) === 'directory';
|
|
403
|
+
}
|
|
404
|
+
isFile(path) {
|
|
405
|
+
return this.probeType(path) === 'file';
|
|
406
|
+
}
|
|
407
|
+
probeType(path) {
|
|
408
|
+
try {
|
|
409
|
+
return this.stat(path).type;
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
if (error !== null && typeof error === 'object' && 'code' in error) {
|
|
413
|
+
const code = error.code;
|
|
414
|
+
if (code === 'ENOENT' || code === 'ENOTDIR')
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
387
420
|
access(path, mode) {
|
|
388
421
|
const vp = this.getProvider(path);
|
|
389
422
|
if (vp) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esbuild.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/esbuild.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"esbuild.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/esbuild.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsCH,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+CvD"}
|
|
@@ -9,10 +9,8 @@
|
|
|
9
9
|
const ESBUILD_WASM_VERSION = '0.24.2';
|
|
10
10
|
const ESBUILD_WASM_URL = `https://unpkg.com/esbuild-wasm@${ESBUILD_WASM_VERSION}/esbuild.wasm`;
|
|
11
11
|
const ESBUILD_ESM_URL = `https://unpkg.com/esbuild-wasm@${ESBUILD_WASM_VERSION}/esm/browser.min.js`;
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
12
|
let esbuildModule = null;
|
|
14
13
|
let initPromise = null;
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
14
|
async function ensureInitialized() {
|
|
17
15
|
if (esbuildModule)
|
|
18
16
|
return esbuildModule;
|
|
@@ -25,10 +23,10 @@ async function ensureInitialized() {
|
|
|
25
23
|
wasmURL: ESBUILD_WASM_URL,
|
|
26
24
|
});
|
|
27
25
|
esbuildModule = mod;
|
|
26
|
+
return mod;
|
|
28
27
|
})();
|
|
29
28
|
}
|
|
30
|
-
await initPromise;
|
|
31
|
-
return esbuildModule;
|
|
29
|
+
return await initPromise;
|
|
32
30
|
}
|
|
33
31
|
export function createEsbuild() {
|
|
34
32
|
const mod = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAShE,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAShE,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAgBhF,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,CAiQ/E;AAED,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -19,6 +19,7 @@ import { createModuleShim } from './module.js';
|
|
|
19
19
|
import * as readlineModule from './readline.js';
|
|
20
20
|
import { createRimraf } from './rimraf.js';
|
|
21
21
|
import { createEsbuild } from './esbuild.js';
|
|
22
|
+
import { assertEqualHolds } from './loose-equality.js';
|
|
22
23
|
export function createModuleMap(ctx) {
|
|
23
24
|
const map = {
|
|
24
25
|
fs: () => createFs(ctx.vfs, ctx.cwd),
|
|
@@ -89,11 +90,11 @@ export function createModuleMap(ctx) {
|
|
|
89
90
|
throw new Error(message || 'AssertionError');
|
|
90
91
|
};
|
|
91
92
|
assert.ok = assert;
|
|
92
|
-
assert.equal = (a, b, msg) => { if (a
|
|
93
|
+
assert.equal = (a, b, msg) => { if (!assertEqualHolds(a, b))
|
|
93
94
|
throw new Error(msg || `${a} != ${b}`); };
|
|
94
95
|
assert.strictEqual = (a, b, msg) => { if (a !== b)
|
|
95
96
|
throw new Error(msg || `${a} !== ${b}`); };
|
|
96
|
-
assert.notEqual = (a, b, msg) => { if (a
|
|
97
|
+
assert.notEqual = (a, b, msg) => { if (assertEqualHolds(a, b))
|
|
97
98
|
throw new Error(msg || `${a} == ${b}`); };
|
|
98
99
|
assert.notStrictEqual = (a, b, msg) => { if (a === b)
|
|
99
100
|
throw new Error(msg || `${a} === ${b}`); };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loose-equality.ts — the `==` coercions, spelled out.
|
|
3
|
+
*
|
|
4
|
+
* `assert.equal`/`assert.notEqual` are specified against the `==` operator —
|
|
5
|
+
* Node's own docs call it "shallow, coercive equality between the actual and
|
|
6
|
+
* expected parameters using the == operator" — and since Node 14 both also
|
|
7
|
+
* treat two NaNs as identical, which `==` on its own does not. Guest code
|
|
8
|
+
* inside the sandbox sees those semantics, so the shim carries them here
|
|
9
|
+
* instead of the strict comparison a reader would expect of new code.
|
|
10
|
+
*/
|
|
11
|
+
/** IsLooselyEqual — what `a == b` answers. */
|
|
12
|
+
export declare function looseEqual(a: unknown, b: unknown): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether Node's legacy assertions call these equal: `==`, widened by the
|
|
15
|
+
* both-sides-NaN case Node folded into `assert.equal` in v14. Node reaches
|
|
16
|
+
* for the non-coercing `Number.isNaN`, so a string spelling "NaN" is not it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertEqualHolds(a: unknown, b: unknown): boolean;
|
|
19
|
+
//# sourceMappingURL=loose-equality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loose-equality.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/loose-equality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsCH,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAoB1D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAKhE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loose-equality.ts — the `==` coercions, spelled out.
|
|
3
|
+
*
|
|
4
|
+
* `assert.equal`/`assert.notEqual` are specified against the `==` operator —
|
|
5
|
+
* Node's own docs call it "shallow, coercive equality between the actual and
|
|
6
|
+
* expected parameters using the == operator" — and since Node 14 both also
|
|
7
|
+
* treat two NaNs as identical, which `==` on its own does not. Guest code
|
|
8
|
+
* inside the sandbox sees those semantics, so the shim carries them here
|
|
9
|
+
* instead of the strict comparison a reader would expect of new code.
|
|
10
|
+
*/
|
|
11
|
+
/** The spec's Object type: everything callable or keyed, null excluded. */
|
|
12
|
+
function isObject(value) {
|
|
13
|
+
return value !== null && (typeof value === 'object' || typeof value === 'function');
|
|
14
|
+
}
|
|
15
|
+
/** ToPrimitive(value) with the default hint. */
|
|
16
|
+
function toPrimitive(value) {
|
|
17
|
+
if (Symbol.toPrimitive in value) {
|
|
18
|
+
const exotic = value[Symbol.toPrimitive];
|
|
19
|
+
if (typeof exotic === 'function')
|
|
20
|
+
return exotic.call(value, 'default');
|
|
21
|
+
}
|
|
22
|
+
for (const method of ['valueOf', 'toString']) {
|
|
23
|
+
if (!(method in value))
|
|
24
|
+
continue;
|
|
25
|
+
const convert = value[method];
|
|
26
|
+
if (typeof convert !== 'function')
|
|
27
|
+
continue;
|
|
28
|
+
const primitive = convert.call(value);
|
|
29
|
+
if (!isObject(primitive))
|
|
30
|
+
return primitive;
|
|
31
|
+
}
|
|
32
|
+
throw new TypeError('Cannot convert object to primitive value');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A bigint compares against the mathematical value of its counterpart, so a
|
|
36
|
+
* fractional number, a non-finite one, or a string naming no integer can
|
|
37
|
+
* never match one.
|
|
38
|
+
*/
|
|
39
|
+
function bigIntLooseEqual(big, other) {
|
|
40
|
+
if (typeof other === 'number')
|
|
41
|
+
return Number.isInteger(other) && BigInt(other) === big;
|
|
42
|
+
if (typeof other !== 'string')
|
|
43
|
+
return false;
|
|
44
|
+
try {
|
|
45
|
+
return BigInt(other) === big;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** IsLooselyEqual — what `a == b` answers. */
|
|
52
|
+
export function looseEqual(a, b) {
|
|
53
|
+
if (a === null || a === undefined)
|
|
54
|
+
return b === null || b === undefined;
|
|
55
|
+
if (b === null || b === undefined)
|
|
56
|
+
return false;
|
|
57
|
+
// Two objects match only as the same reference; an object against a
|
|
58
|
+
// primitive matches on the object's own primitive value.
|
|
59
|
+
if (isObject(a)) {
|
|
60
|
+
return isObject(b) ? a === b : looseEqual(toPrimitive(a), b);
|
|
61
|
+
}
|
|
62
|
+
if (isObject(b))
|
|
63
|
+
return looseEqual(a, toPrimitive(b));
|
|
64
|
+
const aType = typeof a;
|
|
65
|
+
const bType = typeof b;
|
|
66
|
+
if (aType === bType)
|
|
67
|
+
return a === b;
|
|
68
|
+
if (aType === 'boolean')
|
|
69
|
+
return looseEqual(Number(a), b);
|
|
70
|
+
if (bType === 'boolean')
|
|
71
|
+
return looseEqual(a, Number(b));
|
|
72
|
+
if (aType === 'symbol' || bType === 'symbol')
|
|
73
|
+
return false;
|
|
74
|
+
if (typeof a === 'bigint')
|
|
75
|
+
return bigIntLooseEqual(a, b);
|
|
76
|
+
if (typeof b === 'bigint')
|
|
77
|
+
return bigIntLooseEqual(b, a);
|
|
78
|
+
return Number(a) === Number(b);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Whether Node's legacy assertions call these equal: `==`, widened by the
|
|
82
|
+
* both-sides-NaN case Node folded into `assert.equal` in v14. Node reaches
|
|
83
|
+
* for the non-coercing `Number.isNaN`, so a string spelling "NaN" is not it.
|
|
84
|
+
*/
|
|
85
|
+
export function assertEqualHolds(a, b) {
|
|
86
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
87
|
+
if (Number.isNaN(a) && Number.isNaN(b))
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return looseEqual(a, b);
|
|
91
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,EAAE,MAAM,CAAC;gBACL,IAAI,EAAE,MAAM;CAKzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc;;;;;;;kBAShC,MAAM;;;sBAQJ,MAAM;;;;;;;;;sBASN,MAAM;;;;;;;;;;;;;;;;;;cAkBD,MAAM;UACZ,MAAM;;;;;;;;;;qBAWX,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,CAAC,MAAM,EAAE,MAAM,CAAC;sBAa7B,MAAM;;mBAGP,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,WAAW,OAAO,EAAE;;;;;;;;;;;;;uBAgB5C,MAAM;;;;;mBAMV,MAAM;oBAEL,MAAM;wBAGA,MAAM;;;;;;;;;;;;;;;;;;gBAShB,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;yBAK/B,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;kBAG/C,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;iBAOzC,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;4BAM7B,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;iCACnC,MAAM;
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/node-compat/process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,EAAE,MAAM,CAAC;gBACL,IAAI,EAAE,MAAM;CAKzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc;;;;;;;kBAShC,MAAM;;;sBAQJ,MAAM;;;;;;;;;sBASN,MAAM;;;;;;;;;;;;;;;;;;cAkBD,MAAM;UACZ,MAAM;;;;;;;;;;qBAWX,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,CAAC,MAAM,EAAE,MAAM,CAAC;sBAa7B,MAAM;;mBAGP,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,WAAW,OAAO,EAAE;;;;;;;;;;;;;uBAgB5C,MAAM;;;;;mBAMV,MAAM;oBAEL,MAAM;wBAGA,MAAM;;;;;;;;;;;;;;;;;;gBAShB,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;yBAK/B,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;kBAG/C,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;iBAOzC,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;4BAM7B,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;iCACnC,MAAM;uBAQhB,MAAM,gBAxIqB,OAAO,EAAE,KAAK,IAAI;kBAyIlD,MAAM,WAAW,OAAO,EAAE;2BAMjB,MAAM;;;6BAGJ,MAAM,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;0BAK3C,MAAM,gBAvJkB,OAAO,EAAE,KAAK,IAAI;;;;;;;;;;;;EA+JnE"}
|
|
@@ -139,10 +139,13 @@ export function createProcess(opts) {
|
|
|
139
139
|
},
|
|
140
140
|
removeListener: (event, fn) => proc.off(event, fn),
|
|
141
141
|
removeAllListeners: (event) => {
|
|
142
|
-
if (event)
|
|
142
|
+
if (event) {
|
|
143
143
|
delete listeners[event];
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
for (const k of Object.keys(listeners))
|
|
147
|
+
delete listeners[k];
|
|
148
|
+
}
|
|
146
149
|
return proc;
|
|
147
150
|
},
|
|
148
151
|
listeners: (event) => listeners[event] ? [...listeners[event]] : [],
|
|
@@ -69,6 +69,12 @@ export declare class Shell {
|
|
|
69
69
|
private commandIdentity;
|
|
70
70
|
private tabCount;
|
|
71
71
|
pasteQueue: string[];
|
|
72
|
+
/**
|
|
73
|
+
* Accepted lines that do not form a complete command yet: an unclosed
|
|
74
|
+
* quote or a trailing `\` keeps the shell reading under PS2, as bash
|
|
75
|
+
* does, instead of executing a truncated command.
|
|
76
|
+
*/
|
|
77
|
+
private pendingLine;
|
|
72
78
|
/**
|
|
73
79
|
* Keystrokes that arrived while a foreground command owned the terminal and
|
|
74
80
|
* nothing was reading stdin. A tty buffers type-ahead and hands it to the
|
|
@@ -86,6 +92,12 @@ export declare class Shell {
|
|
|
86
92
|
setCwd(cwd: string): void;
|
|
87
93
|
getEnv(): Record<string, string>;
|
|
88
94
|
getVfs(): VFS;
|
|
95
|
+
/**
|
|
96
|
+
* The `runAs` host this shell re-credentials through. A caller building a
|
|
97
|
+
* second Shell over the same kernel needs it, or its commands lose the
|
|
98
|
+
* identity-transition path `sudo` and `su` are dispatched on.
|
|
99
|
+
*/
|
|
100
|
+
getRunAsHost(): CommandRunAsHost | undefined;
|
|
89
101
|
getRegistry(): CommandRegistry;
|
|
90
102
|
/**
|
|
91
103
|
* Programmatic command execution with captured stdout/stderr.
|
|
@@ -121,6 +133,13 @@ export declare class Shell {
|
|
|
121
133
|
private moveCursorEnd;
|
|
122
134
|
private historyUp;
|
|
123
135
|
private historyDown;
|
|
136
|
+
/**
|
|
137
|
+
* A line the user finished with Enter. If it leaves a quote open or ends
|
|
138
|
+
* in a line continuation it is not a command yet: bash buffers it, shows
|
|
139
|
+
* PS2 and keeps reading, and so does this shell. A `\<newline>` join drops
|
|
140
|
+
* both characters; a quoted join keeps the newline in the string.
|
|
141
|
+
*/
|
|
142
|
+
private acceptLine;
|
|
124
143
|
executeLine(line: string): Promise<void>;
|
|
125
144
|
private builtinCd;
|
|
126
145
|
private builtinPwd;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Shell.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/shell/Shell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAkB,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAIhE,OAAO,EAML,KAAK,YAAY,EACjB,KAAK,eAAe,EAErB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA2BvD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGlF;
|
|
1
|
+
{"version":3,"file":"Shell.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/shell/Shell.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { resolve } from '../utils/path.js';
|
|
|
2
2
|
import { BOLD, GREEN, BLUE, RESET } from '../utils/colors.js';
|
|
3
3
|
import { VFSError } from '../kernel/vfs/index.js';
|
|
4
4
|
import { ExitSignal, Interpreter, assignScalar, } from './interpreter.js';
|
|
5
|
-
import { lex } from './lexer.js';
|
|
5
|
+
import { continuationState, lex } from './lexer.js';
|
|
6
6
|
import { TokenKind } from './types.js';
|
|
7
7
|
import { HistoryManager } from './history.js';
|
|
8
8
|
import { JobTable } from './jobs.js';
|
|
@@ -31,6 +31,8 @@ export function formatShellPrompt(env, cwd) {
|
|
|
31
31
|
const { displayPath, user, host } = shellPromptParts(env, cwd);
|
|
32
32
|
return `${BOLD}${GREEN}${user}@${host}${RESET}:${BOLD}${BLUE}${displayPath}${RESET}$ `;
|
|
33
33
|
}
|
|
34
|
+
/** PS2 — shown while an accepted line has not closed into a command yet. */
|
|
35
|
+
const CONTINUATION_PROMPT = '> ';
|
|
34
36
|
export class Shell {
|
|
35
37
|
terminal;
|
|
36
38
|
vfs;
|
|
@@ -74,6 +76,12 @@ export class Shell {
|
|
|
74
76
|
tabCount = 0;
|
|
75
77
|
// Paste queue for multiline paste support
|
|
76
78
|
pasteQueue = [];
|
|
79
|
+
/**
|
|
80
|
+
* Accepted lines that do not form a complete command yet: an unclosed
|
|
81
|
+
* quote or a trailing `\` keeps the shell reading under PS2, as bash
|
|
82
|
+
* does, instead of executing a truncated command.
|
|
83
|
+
*/
|
|
84
|
+
pendingLine = null;
|
|
77
85
|
/**
|
|
78
86
|
* Keystrokes that arrived while a foreground command owned the terminal and
|
|
79
87
|
* nothing was reading stdin. A tty buffers type-ahead and hands it to the
|
|
@@ -181,6 +189,14 @@ export class Shell {
|
|
|
181
189
|
getVfs() {
|
|
182
190
|
return this.vfs;
|
|
183
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* The `runAs` host this shell re-credentials through. A caller building a
|
|
194
|
+
* second Shell over the same kernel needs it, or its commands lose the
|
|
195
|
+
* identity-transition path `sudo` and `su` are dispatched on.
|
|
196
|
+
*/
|
|
197
|
+
getRunAsHost() {
|
|
198
|
+
return this.commandIdentity.runAs;
|
|
199
|
+
}
|
|
184
200
|
getRegistry() {
|
|
185
201
|
return this.registry;
|
|
186
202
|
}
|
|
@@ -341,6 +357,10 @@ export class Shell {
|
|
|
341
357
|
}
|
|
342
358
|
}
|
|
343
359
|
printPrompt() {
|
|
360
|
+
if (this.pendingLine !== null) {
|
|
361
|
+
this.terminal.write(CONTINUATION_PROMPT);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
344
364
|
// Report finished background jobs from JobTable (legacy)
|
|
345
365
|
const doneJobs = this.jobTable.collectDone();
|
|
346
366
|
for (const job of doneJobs) {
|
|
@@ -357,61 +377,32 @@ export class Shell {
|
|
|
357
377
|
this.terminalStdin.feed(data);
|
|
358
378
|
return;
|
|
359
379
|
}
|
|
360
|
-
// Multiline paste detection: if data contains newlines and has multiple
|
|
361
|
-
// split into lines and
|
|
380
|
+
// Multiline paste detection: if data contains newlines and has multiple
|
|
381
|
+
// chars, split into lines and accept them sequentially via the paste
|
|
382
|
+
// queue. Middle segments are queued even when empty — a blank pasted
|
|
383
|
+
// line is a newline inside an open quote; only the tail after the final
|
|
384
|
+
// newline is dropped when empty, because no Enter followed it.
|
|
362
385
|
if (!this.running && data.length > 1 && /[\r\n]/.test(data)) {
|
|
363
386
|
const lines = data.split(/\r\n|\r|\n/);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (segment) {
|
|
369
|
-
this.lineBuffer = this.lineBuffer.slice(0, this.cursorPos) + segment + this.lineBuffer.slice(this.cursorPos);
|
|
370
|
-
this.cursorPos += segment.length;
|
|
371
|
-
}
|
|
372
|
-
if (i < lines.length - 1) {
|
|
373
|
-
// There's a newline after this segment, execute it
|
|
374
|
-
this.redrawLine();
|
|
375
|
-
this.terminal.write('\r\n');
|
|
376
|
-
const line = this.lineBuffer.trim();
|
|
377
|
-
this.lineBuffer = '';
|
|
378
|
-
this.cursorPos = 0;
|
|
379
|
-
this.historyIndex = -1;
|
|
380
|
-
if (line) {
|
|
381
|
-
this.history.push(line);
|
|
382
|
-
// Queue remaining lines before executing
|
|
383
|
-
for (let j = 1; j < lines.length - 1; j++) {
|
|
384
|
-
if (lines[j])
|
|
385
|
-
this.pasteQueue.push(lines[j]);
|
|
386
|
-
}
|
|
387
|
-
// Last segment (after final newline) goes into lineBuffer without executing
|
|
388
|
-
const lastSegment = lines[lines.length - 1];
|
|
389
|
-
if (lastSegment) {
|
|
390
|
-
this.pasteQueue.push(lastSegment);
|
|
391
|
-
}
|
|
392
|
-
this.executeLine(line);
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
// Empty first line, queue the rest
|
|
397
|
-
for (let j = 1; j < lines.length - 1; j++) {
|
|
398
|
-
if (lines[j])
|
|
399
|
-
this.pasteQueue.push(lines[j]);
|
|
400
|
-
}
|
|
401
|
-
const lastSegment = lines[lines.length - 1];
|
|
402
|
-
if (lastSegment) {
|
|
403
|
-
this.pasteQueue.push(lastSegment);
|
|
404
|
-
}
|
|
405
|
-
this.drainPasteQueue();
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
387
|
+
const first = lines[0];
|
|
388
|
+
if (first) {
|
|
389
|
+
this.lineBuffer = this.lineBuffer.slice(0, this.cursorPos) + first + this.lineBuffer.slice(this.cursorPos);
|
|
390
|
+
this.cursorPos += first.length;
|
|
410
391
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
392
|
+
this.redrawLine();
|
|
393
|
+
this.terminal.write('\r\n');
|
|
394
|
+
const line = this.lineBuffer;
|
|
395
|
+
this.lineBuffer = '';
|
|
396
|
+
this.cursorPos = 0;
|
|
397
|
+
this.historyIndex = -1;
|
|
398
|
+
for (let j = 1; j < lines.length - 1; j++) {
|
|
399
|
+
this.pasteQueue.push(lines[j]);
|
|
400
|
+
}
|
|
401
|
+
const lastSegment = lines[lines.length - 1];
|
|
402
|
+
if (lastSegment) {
|
|
403
|
+
this.pasteQueue.push(lastSegment);
|
|
404
|
+
}
|
|
405
|
+
this.acceptLine(line);
|
|
415
406
|
return;
|
|
416
407
|
}
|
|
417
408
|
// ESC sequences. Cursor motion and history are line EDITING, so they only
|
|
@@ -457,6 +448,7 @@ export class Shell {
|
|
|
457
448
|
}
|
|
458
449
|
else if (signal === 'INT') {
|
|
459
450
|
this.terminal.write('^C\r\n');
|
|
451
|
+
this.pendingLine = null;
|
|
460
452
|
this.lineBuffer = '';
|
|
461
453
|
this.cursorPos = 0;
|
|
462
454
|
this.screenCursorRow = 0;
|
|
@@ -517,18 +509,12 @@ export class Shell {
|
|
|
517
509
|
// Enter
|
|
518
510
|
if (data === '\r') {
|
|
519
511
|
this.terminal.write('\r\n');
|
|
520
|
-
const line = this.lineBuffer
|
|
512
|
+
const line = this.lineBuffer;
|
|
521
513
|
this.lineBuffer = '';
|
|
522
514
|
this.cursorPos = 0;
|
|
523
515
|
this.screenCursorRow = 0;
|
|
524
516
|
this.historyIndex = -1;
|
|
525
|
-
|
|
526
|
-
this.history.push(line);
|
|
527
|
-
this.executeLine(line);
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
this.printPrompt();
|
|
531
|
-
}
|
|
517
|
+
this.acceptLine(line);
|
|
532
518
|
return;
|
|
533
519
|
}
|
|
534
520
|
// Backspace
|
|
@@ -698,6 +684,8 @@ export class Shell {
|
|
|
698
684
|
this.redrawLine();
|
|
699
685
|
}
|
|
700
686
|
getPromptWidth() {
|
|
687
|
+
if (this.pendingLine !== null)
|
|
688
|
+
return CONTINUATION_PROMPT.length;
|
|
701
689
|
const { displayPath, user, host } = shellPromptParts(this.env, this.cwd);
|
|
702
690
|
// "user@host:path$ " — count visible chars only (no ANSI codes)
|
|
703
691
|
return user.length + 1 + host.length + 1 + displayPath.length + 2;
|
|
@@ -714,7 +702,7 @@ export class Shell {
|
|
|
714
702
|
// Clear from here to end of screen
|
|
715
703
|
this.terminal.write('\x1b[J');
|
|
716
704
|
// Rewrite prompt + buffer
|
|
717
|
-
this.terminal.write(formatShellPrompt(this.env, this.cwd));
|
|
705
|
+
this.terminal.write(this.pendingLine === null ? formatShellPrompt(this.env, this.cwd) : CONTINUATION_PROMPT);
|
|
718
706
|
this.terminal.write(this.lineBuffer);
|
|
719
707
|
// After writing all content, figure out which row the cursor is on.
|
|
720
708
|
// If content exactly fills N rows, the terminal auto-wraps cursor to the next row.
|
|
@@ -755,19 +743,11 @@ export class Shell {
|
|
|
755
743
|
}
|
|
756
744
|
drainPasteQueue() {
|
|
757
745
|
const next = this.pasteQueue.shift();
|
|
758
|
-
if (next
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
this.history.push(line);
|
|
764
|
-
this.executeLine(line);
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
// Skip empty lines, try next
|
|
768
|
-
this.drainPasteQueue();
|
|
769
|
-
}
|
|
770
|
-
}
|
|
746
|
+
if (next === undefined)
|
|
747
|
+
return;
|
|
748
|
+
this.terminal.write(next);
|
|
749
|
+
this.terminal.write('\r\n');
|
|
750
|
+
this.acceptLine(next);
|
|
771
751
|
}
|
|
772
752
|
moveCursorLeft() {
|
|
773
753
|
if (this.cursorPos > 0) {
|
|
@@ -825,6 +805,37 @@ export class Shell {
|
|
|
825
805
|
this.cursorPos = this.lineBuffer.length;
|
|
826
806
|
this.redrawLine();
|
|
827
807
|
}
|
|
808
|
+
/**
|
|
809
|
+
* A line the user finished with Enter. If it leaves a quote open or ends
|
|
810
|
+
* in a line continuation it is not a command yet: bash buffers it, shows
|
|
811
|
+
* PS2 and keeps reading, and so does this shell. A `\<newline>` join drops
|
|
812
|
+
* both characters; a quoted join keeps the newline in the string.
|
|
813
|
+
*/
|
|
814
|
+
acceptLine(rawLine) {
|
|
815
|
+
let command;
|
|
816
|
+
if (this.pendingLine === null) {
|
|
817
|
+
command = rawLine.trim();
|
|
818
|
+
if (!command) {
|
|
819
|
+
this.printPrompt();
|
|
820
|
+
this.drainPasteQueue();
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
else {
|
|
825
|
+
command = continuationState(this.pendingLine) === 'backslash'
|
|
826
|
+
? this.pendingLine.slice(0, -1) + rawLine
|
|
827
|
+
: this.pendingLine + '\n' + rawLine;
|
|
828
|
+
}
|
|
829
|
+
if (continuationState(command) !== null) {
|
|
830
|
+
this.pendingLine = command;
|
|
831
|
+
this.printPrompt();
|
|
832
|
+
this.drainPasteQueue();
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
this.pendingLine = null;
|
|
836
|
+
this.history.push(command);
|
|
837
|
+
this.executeLine(command);
|
|
838
|
+
}
|
|
828
839
|
async executeLine(line) {
|
|
829
840
|
// History expansion
|
|
830
841
|
const expanded = this.historyManager.expand(line);
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { type Token } from './types.js';
|
|
2
2
|
export declare function lex(input: string): Token[];
|
|
3
|
+
export type ContinuationState = 'single' | 'double' | 'backslash';
|
|
4
|
+
/**
|
|
5
|
+
* How `input` leaves the lexer at end of input: inside an unclosed single or
|
|
6
|
+
* double quote, or ending in a `\` line continuation (which bash also honors
|
|
7
|
+
* inside double quotes, where `\<newline>` is removed). The interactive shell
|
|
8
|
+
* uses this to keep reading (PS2) instead of executing a truncated command.
|
|
9
|
+
* Comments are skipped exactly where lex() treats `#` as one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function continuationState(input: string): ContinuationState | null;
|
|
3
12
|
/**
|
|
4
13
|
* The full `${...}` span starting at `pos`. Quotes, nested braces and command
|
|
5
14
|
* substitutions inside it belong to the expansion, not to the surrounding
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/shell/lexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,KAAK,EAAiB,MAAM,YAAY,CAAC;AAElE,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,CAmE1C;AA8hBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAG9C"}
|
|
1
|
+
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../../src/substrate/lifo/shell/lexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,KAAK,EAAiB,MAAM,YAAY,CAAC;AAElE,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,CAmE1C;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CA2BzE;AA8hBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAG9C"}
|