@nimbus-sh/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_shared/ai-egress.d.ts +73 -0
- package/dist/_shared/ai-egress.d.ts.map +1 -0
- package/dist/_shared/ai-egress.js +88 -0
- package/dist/_shared/byte-stream.d.ts +59 -0
- package/dist/_shared/byte-stream.d.ts.map +1 -0
- package/dist/_shared/byte-stream.js +77 -0
- package/dist/_shared/bytes.d.ts +18 -0
- package/dist/_shared/bytes.d.ts.map +1 -0
- package/dist/_shared/bytes.js +17 -0
- package/dist/_shared/cache-stats.d.ts +145 -0
- package/dist/_shared/cache-stats.d.ts.map +1 -0
- package/dist/_shared/cache-stats.js +161 -0
- package/dist/_shared/crypto.d.ts +17 -0
- package/dist/_shared/crypto.d.ts.map +1 -0
- package/dist/_shared/crypto.js +131 -0
- package/dist/_shared/esbuild-facet-shim.d.ts +21 -0
- package/dist/_shared/esbuild-facet-shim.d.ts.map +1 -0
- package/dist/_shared/esbuild-facet-shim.js +22 -0
- package/dist/_shared/exports-resolver.d.ts +74 -0
- package/dist/_shared/exports-resolver.d.ts.map +1 -0
- package/dist/_shared/exports-resolver.js +284 -0
- package/dist/_shared/facet-vfs-cursor.d.ts +48 -0
- package/dist/_shared/facet-vfs-cursor.d.ts.map +1 -0
- package/dist/_shared/facet-vfs-cursor.js +51 -0
- package/dist/_shared/install-phase.d.ts +47 -0
- package/dist/_shared/install-phase.d.ts.map +1 -0
- package/dist/_shared/install-phase.js +1 -0
- package/dist/_shared/lru-map.d.ts +25 -0
- package/dist/_shared/lru-map.d.ts.map +1 -0
- package/dist/_shared/lru-map.js +57 -0
- package/dist/_shared/real-node-imports.d.ts +43 -0
- package/dist/_shared/real-node-imports.d.ts.map +1 -0
- package/dist/_shared/real-node-imports.js +52 -0
- package/dist/_shared/retry.d.ts +92 -0
- package/dist/_shared/retry.d.ts.map +1 -0
- package/dist/_shared/retry.js +155 -0
- package/dist/_shared/rpc-dispose.d.ts +4 -0
- package/dist/_shared/rpc-dispose.d.ts.map +1 -0
- package/dist/_shared/rpc-dispose.js +30 -0
- package/dist/_shared/terminal.d.ts +2 -0
- package/dist/_shared/terminal.d.ts.map +1 -0
- package/dist/_shared/terminal.js +3 -0
- package/dist/_shared/typescript-specifiers.d.ts +58 -0
- package/dist/_shared/typescript-specifiers.d.ts.map +1 -0
- package/dist/_shared/typescript-specifiers.js +84 -0
- package/dist/_shared/untrusted-request.d.ts +34 -0
- package/dist/_shared/untrusted-request.d.ts.map +1 -0
- package/dist/_shared/untrusted-request.js +74 -0
- package/dist/_shared/vfs-write-ledger.d.ts +3 -0
- package/dist/_shared/vfs-write-ledger.d.ts.map +1 -0
- package/dist/_shared/vfs-write-ledger.js +439 -0
- package/dist/_shared/w7-frame.d.ts +79 -0
- package/dist/_shared/w7-frame.d.ts.map +1 -0
- package/dist/_shared/w7-frame.js +839 -0
- package/dist/_shared/weighted-credit-pool.d.ts +61 -0
- package/dist/_shared/weighted-credit-pool.d.ts.map +1 -0
- package/dist/_shared/weighted-credit-pool.js +196 -0
- package/dist/constants.d.ts +64 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +264 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/observability/diag-counters.d.ts +236 -0
- package/dist/observability/diag-counters.d.ts.map +1 -0
- package/dist/observability/diag-counters.js +195 -0
- package/dist/observability/heap-estimate.d.ts +225 -0
- package/dist/observability/heap-estimate.d.ts.map +1 -0
- package/dist/observability/heap-estimate.js +185 -0
- package/dist/observability/heavy-alloc-coord.d.ts +93 -0
- package/dist/observability/heavy-alloc-coord.d.ts.map +1 -0
- package/dist/observability/heavy-alloc-coord.js +181 -0
- package/dist/observability/oom-classify.d.ts +138 -0
- package/dist/observability/oom-classify.d.ts.map +1 -0
- package/dist/observability/oom-classify.js +261 -0
- package/dist/observability/oom-discriminator.d.ts +176 -0
- package/dist/observability/oom-discriminator.d.ts.map +1 -0
- package/dist/observability/oom-discriminator.js +272 -0
- package/dist/runtime/assets-loader.d.ts +71 -0
- package/dist/runtime/assets-loader.d.ts.map +1 -0
- package/dist/runtime/assets-loader.js +139 -0
- package/dist/runtime/barrel-detect.d.ts +46 -0
- package/dist/runtime/barrel-detect.d.ts.map +1 -0
- package/dist/runtime/barrel-detect.js +73 -0
- package/dist/runtime/bash/preamble.d.ts +2 -0
- package/dist/runtime/bash/preamble.d.ts.map +1 -0
- package/dist/runtime/bash/preamble.js +1849 -0
- package/dist/runtime/bash/types.d.ts +433 -0
- package/dist/runtime/bash/types.d.ts.map +1 -0
- package/dist/runtime/bash/types.js +1 -0
- package/dist/runtime/bundle-profile.d.ts +14 -0
- package/dist/runtime/bundle-profile.d.ts.map +1 -0
- package/dist/runtime/bundle-profile.js +20 -0
- package/dist/runtime/cirrus-vite-config-rewriter.d.ts +2 -0
- package/dist/runtime/cirrus-vite-config-rewriter.d.ts.map +1 -0
- package/dist/runtime/cirrus-vite-config-rewriter.js +28 -0
- package/dist/runtime/cli-flags.d.ts +2 -0
- package/dist/runtime/cli-flags.d.ts.map +1 -0
- package/dist/runtime/cli-flags.js +11 -0
- package/dist/runtime/comment-strip.d.ts +37 -0
- package/dist/runtime/comment-strip.d.ts.map +1 -0
- package/dist/runtime/comment-strip.js +74 -0
- package/dist/runtime/cpython-preamble.d.ts +32 -0
- package/dist/runtime/cpython-preamble.d.ts.map +1 -0
- package/dist/runtime/cpython-preamble.js +296 -0
- package/dist/runtime/esbuild-service.d.ts +242 -0
- package/dist/runtime/esbuild-service.d.ts.map +1 -0
- package/dist/runtime/esbuild-service.js +1452 -0
- package/dist/runtime/framework-detect.d.ts +70 -0
- package/dist/runtime/framework-detect.d.ts.map +1 -0
- package/dist/runtime/framework-detect.js +177 -0
- package/dist/runtime/import-meta-transform.d.ts +3 -0
- package/dist/runtime/import-meta-transform.d.ts.map +1 -0
- package/dist/runtime/import-meta-transform.js +15 -0
- package/dist/runtime/javascript-ast.d.ts +13 -0
- package/dist/runtime/javascript-ast.d.ts.map +1 -0
- package/dist/runtime/javascript-ast.js +57 -0
- package/dist/runtime/long-running-handle.d.ts +119 -0
- package/dist/runtime/long-running-handle.d.ts.map +1 -0
- package/dist/runtime/long-running-handle.js +169 -0
- package/dist/runtime/module-source-rewriter.d.ts +11 -0
- package/dist/runtime/module-source-rewriter.d.ts.map +1 -0
- package/dist/runtime/module-source-rewriter.js +61 -0
- package/dist/runtime/opentui-wasm-backend.d.ts +160 -0
- package/dist/runtime/opentui-wasm-backend.d.ts.map +1 -0
- package/dist/runtime/opentui-wasm-backend.js +416 -0
- package/dist/runtime/os-contracts.d.ts +436 -0
- package/dist/runtime/os-contracts.d.ts.map +1 -0
- package/dist/runtime/os-contracts.js +101 -0
- package/dist/runtime/port-registry.d.ts +100 -0
- package/dist/runtime/port-registry.d.ts.map +1 -0
- package/dist/runtime/port-registry.js +265 -0
- package/dist/runtime/process-input-routing.d.ts +33 -0
- package/dist/runtime/process-input-routing.d.ts.map +1 -0
- package/dist/runtime/process-input-routing.js +59 -0
- package/dist/runtime/process-input.d.ts +39 -0
- package/dist/runtime/process-input.d.ts.map +1 -0
- package/dist/runtime/process-input.js +117 -0
- package/dist/runtime/process-io-protocol.d.ts +90 -0
- package/dist/runtime/process-io-protocol.d.ts.map +1 -0
- package/dist/runtime/process-io-protocol.js +81 -0
- package/dist/runtime/process-logs.d.ts +352 -0
- package/dist/runtime/process-logs.d.ts.map +1 -0
- package/dist/runtime/process-logs.js +750 -0
- package/dist/runtime/process-table.d.ts +101 -0
- package/dist/runtime/process-table.d.ts.map +1 -0
- package/dist/runtime/process-table.js +175 -0
- package/dist/runtime/project-detect.d.ts +21 -0
- package/dist/runtime/project-detect.d.ts.map +1 -0
- package/dist/runtime/project-detect.js +46 -0
- package/dist/runtime/python-server-adapter.d.ts +33 -0
- package/dist/runtime/python-server-adapter.d.ts.map +1 -0
- package/dist/runtime/python-server-adapter.js +132 -0
- package/dist/runtime/require-resolver.d.ts +44 -0
- package/dist/runtime/require-resolver.d.ts.map +1 -0
- package/dist/runtime/require-resolver.js +698 -0
- package/dist/runtime/router-basename.d.ts +36 -0
- package/dist/runtime/router-basename.d.ts.map +1 -0
- package/dist/runtime/router-basename.js +310 -0
- package/dist/runtime/ruby-green-threads.d.ts +136 -0
- package/dist/runtime/ruby-green-threads.d.ts.map +1 -0
- package/dist/runtime/ruby-green-threads.js +904 -0
- package/dist/runtime/ruby-socket-shim.d.ts +2 -0
- package/dist/runtime/ruby-socket-shim.d.ts.map +1 -0
- package/dist/runtime/ruby-socket-shim.js +548 -0
- package/dist/runtime/session-process-supervisor.d.ts +156 -0
- package/dist/runtime/session-process-supervisor.d.ts.map +1 -0
- package/dist/runtime/session-process-supervisor.js +238 -0
- package/dist/runtime/sqlite-runtime-fs-bridge.d.ts +70 -0
- package/dist/runtime/sqlite-runtime-fs-bridge.d.ts.map +1 -0
- package/dist/runtime/sqlite-runtime-fs-bridge.js +425 -0
- package/dist/runtime/streams.d.ts +13 -0
- package/dist/runtime/streams.d.ts.map +1 -0
- package/dist/runtime/streams.js +546 -0
- package/dist/runtime/undici-shim.d.ts +62 -0
- package/dist/runtime/undici-shim.d.ts.map +1 -0
- package/dist/runtime/undici-shim.js +516 -0
- package/dist/runtime/vfs-manifest.d.ts +63 -0
- package/dist/runtime/vfs-manifest.d.ts.map +1 -0
- package/dist/runtime/vfs-manifest.js +141 -0
- package/dist/runtime/vfs-snapshot.d.ts +75 -0
- package/dist/runtime/vfs-snapshot.d.ts.map +1 -0
- package/dist/runtime/vfs-snapshot.js +220 -0
- package/dist/runtime/virtual-socket-kernel.d.ts +252 -0
- package/dist/runtime/virtual-socket-kernel.d.ts.map +1 -0
- package/dist/runtime/virtual-socket-kernel.js +1143 -0
- package/dist/runtime/vite-config-parser.d.ts +13 -0
- package/dist/runtime/vite-config-parser.d.ts.map +1 -0
- package/dist/runtime/vite-config-parser.js +258 -0
- package/dist/runtime/wasi/types.d.ts +347 -0
- package/dist/runtime/wasi/types.d.ts.map +1 -0
- package/dist/runtime/wasi/types.js +1 -0
- package/dist/runtime/wasi-instance.d.ts +215 -0
- package/dist/runtime/wasi-instance.d.ts.map +1 -0
- package/dist/runtime/wasi-instance.generated.d.ts +14 -0
- package/dist/runtime/wasi-instance.generated.d.ts.map +1 -0
- package/dist/runtime/wasi-instance.generated.js +13 -0
- package/dist/runtime/wasi-instance.js +179 -0
- package/dist/runtime/wasi-threads.d.ts +169 -0
- package/dist/runtime/wasi-threads.d.ts.map +1 -0
- package/dist/runtime/wasi-threads.js +669 -0
- package/dist/runtime/wasm-memory.d.ts +84 -0
- package/dist/runtime/wasm-memory.d.ts.map +1 -0
- package/dist/runtime/wasm-memory.js +235 -0
- package/dist/shell/elevation-commands.d.ts +5 -0
- package/dist/shell/elevation-commands.d.ts.map +1 -0
- package/dist/shell/elevation-commands.js +109 -0
- package/dist/shell/exec-dispatch.d.ts +57 -0
- package/dist/shell/exec-dispatch.d.ts.map +1 -0
- package/dist/shell/exec-dispatch.js +181 -0
- package/dist/shell/features.d.ts +154 -0
- package/dist/shell/features.d.ts.map +1 -0
- package/dist/shell/features.js +792 -0
- package/dist/shell/shell-entrypoints.d.ts +55 -0
- package/dist/shell/shell-entrypoints.d.ts.map +1 -0
- package/dist/shell/shell-entrypoints.js +230 -0
- package/dist/shell/shell-invocation.d.ts +36 -0
- package/dist/shell/shell-invocation.d.ts.map +1 -0
- package/dist/shell/shell-invocation.js +148 -0
- package/dist/shell/unix-accounts.d.ts +27 -0
- package/dist/shell/unix-accounts.d.ts.map +1 -0
- package/dist/shell/unix-accounts.js +105 -0
- package/dist/shell/unix-commands.d.ts +15 -0
- package/dist/shell/unix-commands.d.ts.map +1 -0
- package/dist/shell/unix-commands.js +4702 -0
- package/dist/substrate/lifo/commands/archive/gunzip.d.ts +4 -0
- package/dist/substrate/lifo/commands/archive/gunzip.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/archive/gunzip.js +58 -0
- package/dist/substrate/lifo/commands/archive/gzip.d.ts +4 -0
- package/dist/substrate/lifo/commands/archive/gzip.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/archive/gzip.js +73 -0
- package/dist/substrate/lifo/commands/archive/tar.d.ts +4 -0
- package/dist/substrate/lifo/commands/archive/tar.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/archive/tar.js +158 -0
- package/dist/substrate/lifo/commands/archive/unzip.d.ts +4 -0
- package/dist/substrate/lifo/commands/archive/unzip.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/archive/unzip.js +114 -0
- package/dist/substrate/lifo/commands/archive/zip.d.ts +4 -0
- package/dist/substrate/lifo/commands/archive/zip.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/archive/zip.js +58 -0
- package/dist/substrate/lifo/commands/fs/basename.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/basename.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/basename.js +12 -0
- package/dist/substrate/lifo/commands/fs/cat.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/cat.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/cat.js +52 -0
- package/dist/substrate/lifo/commands/fs/chmod.d.ts +25 -0
- package/dist/substrate/lifo/commands/fs/chmod.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/chmod.js +97 -0
- package/dist/substrate/lifo/commands/fs/chown.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/chown.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/chown.js +41 -0
- package/dist/substrate/lifo/commands/fs/cp.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/cp.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/cp.js +29 -0
- package/dist/substrate/lifo/commands/fs/df.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/df.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/df.js +52 -0
- package/dist/substrate/lifo/commands/fs/dirname.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/dirname.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/dirname.js +12 -0
- package/dist/substrate/lifo/commands/fs/du.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/du.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/du.js +104 -0
- package/dist/substrate/lifo/commands/fs/file.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/file.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/file.js +84 -0
- package/dist/substrate/lifo/commands/fs/find.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/find.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/find.js +72 -0
- package/dist/substrate/lifo/commands/fs/ln.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/ln.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/ln.js +15 -0
- package/dist/substrate/lifo/commands/fs/ls.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/ls.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/ls.js +146 -0
- package/dist/substrate/lifo/commands/fs/mkdir.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/mkdir.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/mkdir.js +31 -0
- package/dist/substrate/lifo/commands/fs/mktemp.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/mktemp.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/mktemp.js +48 -0
- package/dist/substrate/lifo/commands/fs/mv.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/mv.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/mv.js +113 -0
- package/dist/substrate/lifo/commands/fs/realpath.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/realpath.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/realpath.js +27 -0
- package/dist/substrate/lifo/commands/fs/rm.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/rm.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/rm.js +48 -0
- package/dist/substrate/lifo/commands/fs/rmdir.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/rmdir.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/rmdir.js +44 -0
- package/dist/substrate/lifo/commands/fs/stat.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/stat.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/stat.js +35 -0
- package/dist/substrate/lifo/commands/fs/touch.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/touch.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/touch.js +26 -0
- package/dist/substrate/lifo/commands/fs/tree.d.ts +4 -0
- package/dist/substrate/lifo/commands/fs/tree.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/fs/tree.js +69 -0
- package/dist/substrate/lifo/commands/index.d.ts +3 -0
- package/dist/substrate/lifo/commands/index.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/index.js +1 -0
- package/dist/substrate/lifo/commands/io/dd.d.ts +4 -0
- package/dist/substrate/lifo/commands/io/dd.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/io/dd.js +256 -0
- package/dist/substrate/lifo/commands/io/printf.d.ts +4 -0
- package/dist/substrate/lifo/commands/io/printf.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/io/printf.js +82 -0
- package/dist/substrate/lifo/commands/io/tee.d.ts +4 -0
- package/dist/substrate/lifo/commands/io/tee.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/io/tee.js +31 -0
- package/dist/substrate/lifo/commands/io/xargs.d.ts +4 -0
- package/dist/substrate/lifo/commands/io/xargs.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/io/xargs.js +44 -0
- package/dist/substrate/lifo/commands/io/yes.d.ts +4 -0
- package/dist/substrate/lifo/commands/io/yes.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/io/yes.js +10 -0
- package/dist/substrate/lifo/commands/net/curl.d.ts +6 -0
- package/dist/substrate/lifo/commands/net/curl.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/curl.js +617 -0
- package/dist/substrate/lifo/commands/net/dig.d.ts +4 -0
- package/dist/substrate/lifo/commands/net/dig.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/dig.js +77 -0
- package/dist/substrate/lifo/commands/net/forward.d.ts +14 -0
- package/dist/substrate/lifo/commands/net/forward.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/forward.js +80 -0
- package/dist/substrate/lifo/commands/net/host.d.ts +14 -0
- package/dist/substrate/lifo/commands/net/host.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/host.js +160 -0
- package/dist/substrate/lifo/commands/net/ifconfig.d.ts +8 -0
- package/dist/substrate/lifo/commands/net/ifconfig.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/ifconfig.js +120 -0
- package/dist/substrate/lifo/commands/net/ip.d.ts +14 -0
- package/dist/substrate/lifo/commands/net/ip.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/ip.js +508 -0
- package/dist/substrate/lifo/commands/net/netstat.d.ts +8 -0
- package/dist/substrate/lifo/commands/net/netstat.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/netstat.js +94 -0
- package/dist/substrate/lifo/commands/net/ping.d.ts +4 -0
- package/dist/substrate/lifo/commands/net/ping.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/ping.js +64 -0
- package/dist/substrate/lifo/commands/net/ports.d.ts +8 -0
- package/dist/substrate/lifo/commands/net/ports.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/ports.js +36 -0
- package/dist/substrate/lifo/commands/net/route.d.ts +8 -0
- package/dist/substrate/lifo/commands/net/route.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/route.js +128 -0
- package/dist/substrate/lifo/commands/net/tunnel-v2.d.ts +4 -0
- package/dist/substrate/lifo/commands/net/tunnel-v2.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/tunnel-v2.js +141 -0
- package/dist/substrate/lifo/commands/net/tunnel.d.ts +6 -0
- package/dist/substrate/lifo/commands/net/tunnel.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/tunnel.js +232 -0
- package/dist/substrate/lifo/commands/net/wget.d.ts +4 -0
- package/dist/substrate/lifo/commands/net/wget.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/net/wget.js +78 -0
- package/dist/substrate/lifo/commands/registry.d.ts +15 -0
- package/dist/substrate/lifo/commands/registry.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/registry.js +120 -0
- package/dist/substrate/lifo/commands/signal.d.ts +12 -0
- package/dist/substrate/lifo/commands/signal.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/signal.js +47 -0
- package/dist/substrate/lifo/commands/system/bc.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/bc.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/bc.js +243 -0
- package/dist/substrate/lifo/commands/system/cal.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/cal.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/cal.js +81 -0
- package/dist/substrate/lifo/commands/system/date.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/date.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/date.js +79 -0
- package/dist/substrate/lifo/commands/system/env.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/env.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/env.js +7 -0
- package/dist/substrate/lifo/commands/system/fastfetch.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/fastfetch.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/fastfetch.js +385 -0
- package/dist/substrate/lifo/commands/system/free.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/free.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/free.js +36 -0
- package/dist/substrate/lifo/commands/system/help.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/help.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/help.js +46 -0
- package/dist/substrate/lifo/commands/system/hostname.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/hostname.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/hostname.js +6 -0
- package/dist/substrate/lifo/commands/system/kill.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/kill.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/kill.js +76 -0
- package/dist/substrate/lifo/commands/system/lifo.d.ts +41 -0
- package/dist/substrate/lifo/commands/system/lifo.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/lifo.js +446 -0
- package/dist/substrate/lifo/commands/system/logout.d.ts +5 -0
- package/dist/substrate/lifo/commands/system/logout.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/logout.js +15 -0
- package/dist/substrate/lifo/commands/system/man.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/man.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/man.js +144 -0
- package/dist/substrate/lifo/commands/system/node.d.ts +6 -0
- package/dist/substrate/lifo/commands/system/node.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/node.js +1241 -0
- package/dist/substrate/lifo/commands/system/npm.d.ts +26 -0
- package/dist/substrate/lifo/commands/system/npm.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/npm.js +934 -0
- package/dist/substrate/lifo/commands/system/pkg.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/pkg.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/pkg.js +97 -0
- package/dist/substrate/lifo/commands/system/ps.d.ts +5 -0
- package/dist/substrate/lifo/commands/system/ps.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/ps.js +35 -0
- package/dist/substrate/lifo/commands/system/registry-schemas.d.ts +44 -0
- package/dist/substrate/lifo/commands/system/registry-schemas.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/registry-schemas.js +28 -0
- package/dist/substrate/lifo/commands/system/sha256sum.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/sha256sum.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/sha256sum.js +86 -0
- package/dist/substrate/lifo/commands/system/sl.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/sl.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/sl.js +204 -0
- package/dist/substrate/lifo/commands/system/sleep.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/sleep.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/sleep.js +27 -0
- package/dist/substrate/lifo/commands/system/stty.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/stty.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/stty.js +61 -0
- package/dist/substrate/lifo/commands/system/systemctl.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/systemctl.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/systemctl.js +164 -0
- package/dist/substrate/lifo/commands/system/top.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/top.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/top.js +38 -0
- package/dist/substrate/lifo/commands/system/uname.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/uname.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/uname.js +55 -0
- package/dist/substrate/lifo/commands/system/uptime.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/uptime.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/uptime.js +16 -0
- package/dist/substrate/lifo/commands/system/watch.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/watch.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/watch.js +53 -0
- package/dist/substrate/lifo/commands/system/which.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/which.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/which.js +45 -0
- package/dist/substrate/lifo/commands/system/whoami.d.ts +4 -0
- package/dist/substrate/lifo/commands/system/whoami.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/system/whoami.js +6 -0
- package/dist/substrate/lifo/commands/text/awk.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/awk.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/awk.js +200 -0
- package/dist/substrate/lifo/commands/text/base64.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/base64.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/base64.js +102 -0
- package/dist/substrate/lifo/commands/text/cut.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/cut.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/cut.js +91 -0
- package/dist/substrate/lifo/commands/text/diff.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/diff.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/diff.js +292 -0
- package/dist/substrate/lifo/commands/text/grep.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/grep.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/grep.js +189 -0
- package/dist/substrate/lifo/commands/text/head.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/head.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/head.js +111 -0
- package/dist/substrate/lifo/commands/text/less.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/less.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/less.js +335 -0
- package/dist/substrate/lifo/commands/text/nano.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/nano.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/nano.js +510 -0
- package/dist/substrate/lifo/commands/text/nl.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/nl.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/nl.js +64 -0
- package/dist/substrate/lifo/commands/text/rev.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/rev.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/rev.js +41 -0
- package/dist/substrate/lifo/commands/text/sed.d.ts +21 -0
- package/dist/substrate/lifo/commands/text/sed.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/sed.js +248 -0
- package/dist/substrate/lifo/commands/text/seq.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/seq.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/seq.js +69 -0
- package/dist/substrate/lifo/commands/text/sort.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/sort.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/sort.js +90 -0
- package/dist/substrate/lifo/commands/text/strings.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/strings.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/strings.js +69 -0
- package/dist/substrate/lifo/commands/text/tac.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/tac.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/tac.js +32 -0
- package/dist/substrate/lifo/commands/text/tail.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/tail.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/tail.js +64 -0
- package/dist/substrate/lifo/commands/text/tr.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/tr.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/tr.js +180 -0
- package/dist/substrate/lifo/commands/text/uniq.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/uniq.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/uniq.js +82 -0
- package/dist/substrate/lifo/commands/text/wc.d.ts +4 -0
- package/dist/substrate/lifo/commands/text/wc.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/text/wc.js +107 -0
- package/dist/substrate/lifo/commands/types.d.ts +49 -0
- package/dist/substrate/lifo/commands/types.d.ts.map +1 -0
- package/dist/substrate/lifo/commands/types.js +1 -0
- package/dist/substrate/lifo/index.d.ts +67 -0
- package/dist/substrate/lifo/index.d.ts.map +1 -0
- package/dist/substrate/lifo/index.js +66 -0
- package/dist/substrate/lifo/kernel/ServiceManager.d.ts +51 -0
- package/dist/substrate/lifo/kernel/ServiceManager.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/ServiceManager.js +302 -0
- package/dist/substrate/lifo/kernel/index.d.ts +40 -0
- package/dist/substrate/lifo/kernel/index.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/index.js +170 -0
- package/dist/substrate/lifo/kernel/network/Bridge.d.ts +110 -0
- package/dist/substrate/lifo/kernel/network/Bridge.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/Bridge.js +278 -0
- package/dist/substrate/lifo/kernel/network/DNSResolver.d.ts +50 -0
- package/dist/substrate/lifo/kernel/network/DNSResolver.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/DNSResolver.js +135 -0
- package/dist/substrate/lifo/kernel/network/NetworkInterface.d.ts +83 -0
- package/dist/substrate/lifo/kernel/network/NetworkInterface.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/NetworkInterface.js +183 -0
- package/dist/substrate/lifo/kernel/network/NetworkNamespace.d.ts +98 -0
- package/dist/substrate/lifo/kernel/network/NetworkNamespace.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/NetworkNamespace.js +149 -0
- package/dist/substrate/lifo/kernel/network/NetworkStack.d.ts +178 -0
- package/dist/substrate/lifo/kernel/network/NetworkStack.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/NetworkStack.js +460 -0
- package/dist/substrate/lifo/kernel/network/PortBridge.d.ts +44 -0
- package/dist/substrate/lifo/kernel/network/PortBridge.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/PortBridge.js +158 -0
- package/dist/substrate/lifo/kernel/network/RoutingTable.d.ts +55 -0
- package/dist/substrate/lifo/kernel/network/RoutingTable.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/RoutingTable.js +167 -0
- package/dist/substrate/lifo/kernel/network/Socket.d.ts +65 -0
- package/dist/substrate/lifo/kernel/network/Socket.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/Socket.js +201 -0
- package/dist/substrate/lifo/kernel/network/index.d.ts +11 -0
- package/dist/substrate/lifo/kernel/network/index.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/index.js +9 -0
- package/dist/substrate/lifo/kernel/network/tunnel/BaseTunnel.d.ts +55 -0
- package/dist/substrate/lifo/kernel/network/tunnel/BaseTunnel.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/tunnel/BaseTunnel.js +88 -0
- package/dist/substrate/lifo/kernel/network/tunnel/VETHPair.d.ts +71 -0
- package/dist/substrate/lifo/kernel/network/tunnel/VETHPair.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/tunnel/VETHPair.js +191 -0
- package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.d.ts +89 -0
- package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.js +324 -0
- package/dist/substrate/lifo/kernel/network/types.d.ts +159 -0
- package/dist/substrate/lifo/kernel/network/types.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/network/types.js +5 -0
- package/dist/substrate/lifo/kernel/persistence/PersistenceManager.d.ts +12 -0
- package/dist/substrate/lifo/kernel/persistence/PersistenceManager.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/persistence/PersistenceManager.js +47 -0
- package/dist/substrate/lifo/kernel/persistence/backends.d.ts +15 -0
- package/dist/substrate/lifo/kernel/persistence/backends.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/persistence/backends.js +18 -0
- package/dist/substrate/lifo/kernel/persistence/index.d.ts +6 -0
- package/dist/substrate/lifo/kernel/persistence/index.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/persistence/index.js +3 -0
- package/dist/substrate/lifo/kernel/persistence/serializer.d.ts +21 -0
- package/dist/substrate/lifo/kernel/persistence/serializer.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/persistence/serializer.js +99 -0
- package/dist/substrate/lifo/kernel/samples.d.ts +3 -0
- package/dist/substrate/lifo/kernel/samples.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/samples.js +930 -0
- package/dist/substrate/lifo/kernel/storage/BlobStore.d.ts +22 -0
- package/dist/substrate/lifo/kernel/storage/BlobStore.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/storage/BlobStore.js +84 -0
- package/dist/substrate/lifo/kernel/storage/ContentStore.d.ts +54 -0
- package/dist/substrate/lifo/kernel/storage/ContentStore.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/storage/ContentStore.js +120 -0
- package/dist/substrate/lifo/kernel/storage/index.d.ts +6 -0
- package/dist/substrate/lifo/kernel/storage/index.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/storage/index.js +3 -0
- package/dist/substrate/lifo/kernel/unit-parser.d.ts +22 -0
- package/dist/substrate/lifo/kernel/unit-parser.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/unit-parser.js +80 -0
- package/dist/substrate/lifo/kernel/vfs/VFS.d.ts +99 -0
- package/dist/substrate/lifo/kernel/vfs/VFS.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/vfs/VFS.js +679 -0
- package/dist/substrate/lifo/kernel/vfs/index.d.ts +8 -0
- package/dist/substrate/lifo/kernel/vfs/index.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/vfs/index.js +5 -0
- package/dist/substrate/lifo/kernel/vfs/providers/DevProvider.d.ts +21 -0
- package/dist/substrate/lifo/kernel/vfs/providers/DevProvider.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/vfs/providers/DevProvider.js +137 -0
- package/dist/substrate/lifo/kernel/vfs/providers/NativeFsProvider.d.ts +63 -0
- package/dist/substrate/lifo/kernel/vfs/providers/NativeFsProvider.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/vfs/providers/NativeFsProvider.js +175 -0
- package/dist/substrate/lifo/kernel/vfs/providers/ProcProvider.d.ts +14 -0
- package/dist/substrate/lifo/kernel/vfs/providers/ProcProvider.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/vfs/providers/ProcProvider.js +126 -0
- package/dist/substrate/lifo/kernel/vfs/types.d.ts +117 -0
- package/dist/substrate/lifo/kernel/vfs/types.d.ts.map +1 -0
- package/dist/substrate/lifo/kernel/vfs/types.js +42 -0
- package/dist/substrate/lifo/node-compat/buffer.d.ts +44 -0
- package/dist/substrate/lifo/node-compat/buffer.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/buffer.js +331 -0
- package/dist/substrate/lifo/node-compat/child_process.d.ts +10 -0
- package/dist/substrate/lifo/node-compat/child_process.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/child_process.js +42 -0
- package/dist/substrate/lifo/node-compat/console.d.ts +21 -0
- package/dist/substrate/lifo/node-compat/console.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/console.js +68 -0
- package/dist/substrate/lifo/node-compat/crypto.d.ts +24 -0
- package/dist/substrate/lifo/node-compat/crypto.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/crypto.js +216 -0
- package/dist/substrate/lifo/node-compat/dns.d.ts +117 -0
- package/dist/substrate/lifo/node-compat/dns.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/dns.js +144 -0
- package/dist/substrate/lifo/node-compat/esbuild.d.ts +10 -0
- package/dist/substrate/lifo/node-compat/esbuild.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/esbuild.js +70 -0
- package/dist/substrate/lifo/node-compat/events.d.ts +19 -0
- package/dist/substrate/lifo/node-compat/events.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/events.js +83 -0
- package/dist/substrate/lifo/node-compat/fs.d.ts +195 -0
- package/dist/substrate/lifo/node-compat/fs.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/fs.js +624 -0
- package/dist/substrate/lifo/node-compat/http.d.ts +133 -0
- package/dist/substrate/lifo/node-compat/http.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/http.js +452 -0
- package/dist/substrate/lifo/node-compat/index.d.ts +20 -0
- package/dist/substrate/lifo/node-compat/index.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/index.js +291 -0
- package/dist/substrate/lifo/node-compat/module.d.ts +55 -0
- package/dist/substrate/lifo/node-compat/module.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/module.js +124 -0
- package/dist/substrate/lifo/node-compat/os.d.ts +39 -0
- package/dist/substrate/lifo/node-compat/os.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/os.js +45 -0
- package/dist/substrate/lifo/node-compat/path.d.ts +86 -0
- package/dist/substrate/lifo/node-compat/path.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/path.js +49 -0
- package/dist/substrate/lifo/node-compat/process.d.ts +127 -0
- package/dist/substrate/lifo/node-compat/process.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/process.js +173 -0
- package/dist/substrate/lifo/node-compat/readline.d.ts +85 -0
- package/dist/substrate/lifo/node-compat/readline.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/readline.js +205 -0
- package/dist/substrate/lifo/node-compat/rimraf.d.ts +30 -0
- package/dist/substrate/lifo/node-compat/rimraf.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/rimraf.js +63 -0
- package/dist/substrate/lifo/node-compat/stream.d.ts +36 -0
- package/dist/substrate/lifo/node-compat/stream.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/stream.js +90 -0
- package/dist/substrate/lifo/node-compat/string_decoder.d.ts +11 -0
- package/dist/substrate/lifo/node-compat/string_decoder.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/string_decoder.js +23 -0
- package/dist/substrate/lifo/node-compat/timers.d.ts +16 -0
- package/dist/substrate/lifo/node-compat/timers.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/timers.js +18 -0
- package/dist/substrate/lifo/node-compat/tty.d.ts +32 -0
- package/dist/substrate/lifo/node-compat/tty.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/tty.js +76 -0
- package/dist/substrate/lifo/node-compat/url.d.ts +37 -0
- package/dist/substrate/lifo/node-compat/url.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/url.js +65 -0
- package/dist/substrate/lifo/node-compat/util.d.ts +42 -0
- package/dist/substrate/lifo/node-compat/util.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/util.js +132 -0
- package/dist/substrate/lifo/node-compat/zlib.d.ts +66 -0
- package/dist/substrate/lifo/node-compat/zlib.d.ts.map +1 -0
- package/dist/substrate/lifo/node-compat/zlib.js +80 -0
- package/dist/substrate/lifo/pkg/PackageManager.d.ts +19 -0
- package/dist/substrate/lifo/pkg/PackageManager.d.ts.map +1 -0
- package/dist/substrate/lifo/pkg/PackageManager.js +97 -0
- package/dist/substrate/lifo/pkg/lifo-dev.d.ts +38 -0
- package/dist/substrate/lifo/pkg/lifo-dev.d.ts.map +1 -0
- package/dist/substrate/lifo/pkg/lifo-dev.js +98 -0
- package/dist/substrate/lifo/pkg/lifo-runtime.d.ts +44 -0
- package/dist/substrate/lifo/pkg/lifo-runtime.d.ts.map +1 -0
- package/dist/substrate/lifo/pkg/lifo-runtime.js +372 -0
- package/dist/substrate/lifo/pkg/loader.d.ts +4 -0
- package/dist/substrate/lifo/pkg/loader.d.ts.map +1 -0
- package/dist/substrate/lifo/pkg/loader.js +24 -0
- package/dist/substrate/lifo/sandbox/HeadlessTerminal.d.ts +18 -0
- package/dist/substrate/lifo/sandbox/HeadlessTerminal.d.ts.map +1 -0
- package/dist/substrate/lifo/sandbox/HeadlessTerminal.js +28 -0
- package/dist/substrate/lifo/sandbox/Sandbox.d.ts +59 -0
- package/dist/substrate/lifo/sandbox/Sandbox.d.ts.map +1 -0
- package/dist/substrate/lifo/sandbox/Sandbox.js +234 -0
- package/dist/substrate/lifo/sandbox/SandboxCommands.d.ts +18 -0
- package/dist/substrate/lifo/sandbox/SandboxCommands.d.ts.map +1 -0
- package/dist/substrate/lifo/sandbox/SandboxCommands.js +64 -0
- package/dist/substrate/lifo/sandbox/SandboxFs.d.ts +43 -0
- package/dist/substrate/lifo/sandbox/SandboxFs.d.ts.map +1 -0
- package/dist/substrate/lifo/sandbox/SandboxFs.js +136 -0
- package/dist/substrate/lifo/sandbox/index.d.ts +3 -0
- package/dist/substrate/lifo/sandbox/index.d.ts.map +1 -0
- package/dist/substrate/lifo/sandbox/index.js +1 -0
- package/dist/substrate/lifo/sandbox/types.d.ts +116 -0
- package/dist/substrate/lifo/sandbox/types.d.ts.map +1 -0
- package/dist/substrate/lifo/sandbox/types.js +1 -0
- package/dist/substrate/lifo/shell/ProcessRegistry.d.ts +142 -0
- package/dist/substrate/lifo/shell/ProcessRegistry.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/ProcessRegistry.js +256 -0
- package/dist/substrate/lifo/shell/Shell.d.ts +170 -0
- package/dist/substrate/lifo/shell/Shell.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/Shell.js +1863 -0
- package/dist/substrate/lifo/shell/completer.d.ts +19 -0
- package/dist/substrate/lifo/shell/completer.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/completer.js +164 -0
- package/dist/substrate/lifo/shell/default-shell.d.ts +9 -0
- package/dist/substrate/lifo/shell/default-shell.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/default-shell.js +53 -0
- package/dist/substrate/lifo/shell/expander.d.ts +48 -0
- package/dist/substrate/lifo/shell/expander.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/expander.js +1204 -0
- package/dist/substrate/lifo/shell/history.d.ts +22 -0
- package/dist/substrate/lifo/shell/history.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/history.js +121 -0
- package/dist/substrate/lifo/shell/interpreter.d.ts +257 -0
- package/dist/substrate/lifo/shell/interpreter.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/interpreter.js +1490 -0
- package/dist/substrate/lifo/shell/jobs.d.ts +21 -0
- package/dist/substrate/lifo/shell/jobs.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/jobs.js +48 -0
- package/dist/substrate/lifo/shell/lexer.d.ts +13 -0
- package/dist/substrate/lifo/shell/lexer.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/lexer.js +614 -0
- package/dist/substrate/lifo/shell/parser.d.ts +7 -0
- package/dist/substrate/lifo/shell/parser.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/parser.js +573 -0
- package/dist/substrate/lifo/shell/pipe.d.ts +15 -0
- package/dist/substrate/lifo/shell/pipe.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/pipe.js +86 -0
- package/dist/substrate/lifo/shell/signals.d.ts +11 -0
- package/dist/substrate/lifo/shell/signals.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/signals.js +57 -0
- package/dist/substrate/lifo/shell/terminal-stdin.d.ts +28 -0
- package/dist/substrate/lifo/shell/terminal-stdin.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/terminal-stdin.js +100 -0
- package/dist/substrate/lifo/shell/test-builtin.d.ts +16 -0
- package/dist/substrate/lifo/shell/test-builtin.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/test-builtin.js +237 -0
- package/dist/substrate/lifo/shell/types.d.ts +140 -0
- package/dist/substrate/lifo/shell/types.d.ts.map +1 -0
- package/dist/substrate/lifo/shell/types.js +25 -0
- package/dist/substrate/lifo/terminal/ITerminal.d.ts +10 -0
- package/dist/substrate/lifo/terminal/ITerminal.d.ts.map +1 -0
- package/dist/substrate/lifo/terminal/ITerminal.js +1 -0
- package/dist/substrate/lifo/utils/archive.d.ts +28 -0
- package/dist/substrate/lifo/utils/archive.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/archive.js +323 -0
- package/dist/substrate/lifo/utils/args.d.ts +18 -0
- package/dist/substrate/lifo/utils/args.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/args.js +73 -0
- package/dist/substrate/lifo/utils/colors.d.ts +27 -0
- package/dist/substrate/lifo/utils/colors.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/colors.js +26 -0
- package/dist/substrate/lifo/utils/encoding.d.ts +4 -0
- package/dist/substrate/lifo/utils/encoding.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/encoding.js +18 -0
- package/dist/substrate/lifo/utils/glob.d.ts +12 -0
- package/dist/substrate/lifo/utils/glob.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/glob.js +150 -0
- package/dist/substrate/lifo/utils/mime.d.ts +4 -0
- package/dist/substrate/lifo/utils/mime.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/mime.js +107 -0
- package/dist/substrate/lifo/utils/path.d.ts +12 -0
- package/dist/substrate/lifo/utils/path.d.ts.map +1 -0
- package/dist/substrate/lifo/utils/path.js +82 -0
- package/dist/vfs/events.d.ts +51 -0
- package/dist/vfs/events.d.ts.map +1 -0
- package/dist/vfs/events.js +127 -0
- package/dist/vfs/path.d.ts +46 -0
- package/dist/vfs/path.d.ts.map +1 -0
- package/dist/vfs/path.js +69 -0
- package/dist/vfs/seed-project.d.ts +62 -0
- package/dist/vfs/seed-project.d.ts.map +1 -0
- package/dist/vfs/seed-project.js +1054 -0
- package/dist/vfs/sqlite-vfs.d.ts +821 -0
- package/dist/vfs/sqlite-vfs.d.ts.map +1 -0
- package/dist/vfs/sqlite-vfs.js +4135 -0
- package/dist/vfs/symlink-registry.d.ts +60 -0
- package/dist/vfs/symlink-registry.d.ts.map +1 -0
- package/dist/vfs/symlink-registry.js +162 -0
- package/dist/workspace/nimbus-workspace.d.ts +94 -0
- package/dist/workspace/nimbus-workspace.d.ts.map +1 -0
- package/dist/workspace/nimbus-workspace.js +167 -0
- package/package.json +69 -0
- package/src/_shared/ai-egress.ts +91 -0
- package/src/_shared/byte-stream.ts +97 -0
- package/src/_shared/bytes.ts +19 -0
- package/src/_shared/cache-stats.ts +231 -0
- package/src/_shared/crypto.ts +184 -0
- package/src/_shared/esbuild-facet-shim.ts +22 -0
- package/src/_shared/exports-resolver.ts +308 -0
- package/src/_shared/facet-vfs-cursor.ts +58 -0
- package/src/_shared/install-phase.ts +56 -0
- package/src/_shared/lru-map.ts +59 -0
- package/src/_shared/real-node-imports.ts +53 -0
- package/src/_shared/retry.ts +202 -0
- package/src/_shared/rpc-dispose.ts +31 -0
- package/src/_shared/terminal.ts +3 -0
- package/src/_shared/typescript-specifiers.ts +86 -0
- package/src/_shared/untrusted-request.ts +75 -0
- package/src/_shared/vfs-write-ledger.ts +440 -0
- package/src/_shared/w7-frame.ts +1012 -0
- package/src/_shared/weighted-credit-pool.ts +244 -0
- package/src/constants.ts +285 -0
- package/src/index.ts +22 -0
- package/src/observability/diag-counters.ts +343 -0
- package/src/observability/heap-estimate.ts +331 -0
- package/src/observability/heavy-alloc-coord.ts +241 -0
- package/src/observability/oom-classify.ts +253 -0
- package/src/observability/oom-discriminator.ts +405 -0
- package/src/runtime/assets-loader.ts +189 -0
- package/src/runtime/barrel-detect.ts +69 -0
- package/src/runtime/bash/preamble.ts +1519 -0
- package/src/runtime/bash/types.ts +497 -0
- package/src/runtime/bundle-profile.ts +32 -0
- package/src/runtime/cirrus-vite-config-rewriter.ts +28 -0
- package/src/runtime/cli-flags.ts +11 -0
- package/src/runtime/comment-strip.ts +73 -0
- package/src/runtime/cpython-preamble.ts +298 -0
- package/src/runtime/esbuild-service.ts +1470 -0
- package/src/runtime/framework-detect.ts +245 -0
- package/src/runtime/import-meta-transform.ts +16 -0
- package/src/runtime/javascript-ast.ts +66 -0
- package/src/runtime/long-running-handle.ts +185 -0
- package/src/runtime/module-source-rewriter.ts +95 -0
- package/src/runtime/opentui-wasm-backend.ts +608 -0
- package/src/runtime/os-contracts.ts +529 -0
- package/src/runtime/port-registry.ts +298 -0
- package/src/runtime/process-input-routing.ts +92 -0
- package/src/runtime/process-input.ts +148 -0
- package/src/runtime/process-io-protocol.ts +97 -0
- package/src/runtime/process-logs.ts +882 -0
- package/src/runtime/process-table.ts +225 -0
- package/src/runtime/project-detect.ts +42 -0
- package/src/runtime/python-server-adapter.ts +133 -0
- package/src/runtime/require-resolver.ts +760 -0
- package/src/runtime/router-basename.ts +279 -0
- package/src/runtime/ruby-green-threads.ts +904 -0
- package/src/runtime/ruby-socket-shim.ts +548 -0
- package/src/runtime/session-process-supervisor.ts +323 -0
- package/src/runtime/sqlite-runtime-fs-bridge.ts +468 -0
- package/src/runtime/streams.ts +547 -0
- package/src/runtime/undici-shim.ts +517 -0
- package/src/runtime/vfs-manifest.ts +170 -0
- package/src/runtime/vfs-snapshot.ts +273 -0
- package/src/runtime/virtual-socket-kernel.ts +1370 -0
- package/src/runtime/vite-config-parser.ts +273 -0
- package/src/runtime/wasi/types.ts +448 -0
- package/src/runtime/wasi-instance.generated.ts +14 -0
- package/src/runtime/wasi-instance.ts +259 -0
- package/src/runtime/wasi-threads.ts +682 -0
- package/src/runtime/wasm-memory.ts +261 -0
- package/src/shell/elevation-commands.ts +117 -0
- package/src/shell/exec-dispatch.ts +201 -0
- package/src/shell/features.ts +870 -0
- package/src/shell/shell-entrypoints.ts +323 -0
- package/src/shell/shell-invocation.ts +181 -0
- package/src/shell/unix-accounts.ts +128 -0
- package/src/shell/unix-commands.ts +4335 -0
- package/src/substrate/lifo/UPSTREAM.md +14 -0
- package/src/substrate/lifo/commands/archive/gunzip.ts +63 -0
- package/src/substrate/lifo/commands/archive/gzip.ts +76 -0
- package/src/substrate/lifo/commands/archive/tar.ts +157 -0
- package/src/substrate/lifo/commands/archive/unzip.ts +112 -0
- package/src/substrate/lifo/commands/archive/zip.ts +70 -0
- package/src/substrate/lifo/commands/fs/basename.ts +16 -0
- package/src/substrate/lifo/commands/fs/cat.ts +54 -0
- package/src/substrate/lifo/commands/fs/chmod.ts +110 -0
- package/src/substrate/lifo/commands/fs/chown.ts +45 -0
- package/src/substrate/lifo/commands/fs/cp.ts +33 -0
- package/src/substrate/lifo/commands/fs/df.ts +56 -0
- package/src/substrate/lifo/commands/fs/dirname.ts +16 -0
- package/src/substrate/lifo/commands/fs/du.ts +100 -0
- package/src/substrate/lifo/commands/fs/file.ts +90 -0
- package/src/substrate/lifo/commands/fs/find.ts +76 -0
- package/src/substrate/lifo/commands/fs/ln.ts +19 -0
- package/src/substrate/lifo/commands/fs/ls.ts +164 -0
- package/src/substrate/lifo/commands/fs/mkdir.ts +37 -0
- package/src/substrate/lifo/commands/fs/mktemp.ts +56 -0
- package/src/substrate/lifo/commands/fs/mv.ts +111 -0
- package/src/substrate/lifo/commands/fs/realpath.ts +31 -0
- package/src/substrate/lifo/commands/fs/rm.ts +53 -0
- package/src/substrate/lifo/commands/fs/rmdir.ts +50 -0
- package/src/substrate/lifo/commands/fs/stat.ts +39 -0
- package/src/substrate/lifo/commands/fs/touch.ts +30 -0
- package/src/substrate/lifo/commands/fs/tree.ts +76 -0
- package/src/substrate/lifo/commands/index.ts +2 -0
- package/src/substrate/lifo/commands/io/dd.ts +289 -0
- package/src/substrate/lifo/commands/io/printf.ts +78 -0
- package/src/substrate/lifo/commands/io/tee.ts +37 -0
- package/src/substrate/lifo/commands/io/xargs.ts +49 -0
- package/src/substrate/lifo/commands/io/yes.ts +15 -0
- package/src/substrate/lifo/commands/net/curl.ts +739 -0
- package/src/substrate/lifo/commands/net/dig.ts +99 -0
- package/src/substrate/lifo/commands/net/forward.ts +90 -0
- package/src/substrate/lifo/commands/net/host.ts +182 -0
- package/src/substrate/lifo/commands/net/ifconfig.ts +139 -0
- package/src/substrate/lifo/commands/net/ip.ts +633 -0
- package/src/substrate/lifo/commands/net/netstat.ts +106 -0
- package/src/substrate/lifo/commands/net/ping.ts +74 -0
- package/src/substrate/lifo/commands/net/ports.ts +45 -0
- package/src/substrate/lifo/commands/net/route.ts +153 -0
- package/src/substrate/lifo/commands/net/tunnel-v2.ts +183 -0
- package/src/substrate/lifo/commands/net/tunnel.ts +272 -0
- package/src/substrate/lifo/commands/net/wget.ts +88 -0
- package/src/substrate/lifo/commands/registry.ts +141 -0
- package/src/substrate/lifo/commands/signal.ts +65 -0
- package/src/substrate/lifo/commands/system/bc.ts +265 -0
- package/src/substrate/lifo/commands/system/cal.ts +90 -0
- package/src/substrate/lifo/commands/system/date.ts +59 -0
- package/src/substrate/lifo/commands/system/env.ts +10 -0
- package/src/substrate/lifo/commands/system/fastfetch.ts +428 -0
- package/src/substrate/lifo/commands/system/free.ts +38 -0
- package/src/substrate/lifo/commands/system/help.ts +53 -0
- package/src/substrate/lifo/commands/system/hostname.ts +9 -0
- package/src/substrate/lifo/commands/system/kill.ts +89 -0
- package/src/substrate/lifo/commands/system/lifo.ts +525 -0
- package/src/substrate/lifo/commands/system/logout.ts +17 -0
- package/src/substrate/lifo/commands/system/man.ts +167 -0
- package/src/substrate/lifo/commands/system/node.ts +1305 -0
- package/src/substrate/lifo/commands/system/npm.ts +1078 -0
- package/src/substrate/lifo/commands/system/pkg.ts +111 -0
- package/src/substrate/lifo/commands/system/ps.ts +46 -0
- package/src/substrate/lifo/commands/system/registry-schemas.ts +33 -0
- package/src/substrate/lifo/commands/system/sha256sum.ts +89 -0
- package/src/substrate/lifo/commands/system/sl.ts +249 -0
- package/src/substrate/lifo/commands/system/sleep.ts +36 -0
- package/src/substrate/lifo/commands/system/stty.ts +69 -0
- package/src/substrate/lifo/commands/system/systemctl.ts +184 -0
- package/src/substrate/lifo/commands/system/top.ts +53 -0
- package/src/substrate/lifo/commands/system/uname.ts +59 -0
- package/src/substrate/lifo/commands/system/uptime.ts +19 -0
- package/src/substrate/lifo/commands/system/watch.ts +67 -0
- package/src/substrate/lifo/commands/system/which.ts +51 -0
- package/src/substrate/lifo/commands/system/whoami.ts +9 -0
- package/src/substrate/lifo/commands/text/awk.ts +210 -0
- package/src/substrate/lifo/commands/text/base64.ts +102 -0
- package/src/substrate/lifo/commands/text/cut.ts +92 -0
- package/src/substrate/lifo/commands/text/diff.ts +314 -0
- package/src/substrate/lifo/commands/text/grep.ts +170 -0
- package/src/substrate/lifo/commands/text/head.ts +95 -0
- package/src/substrate/lifo/commands/text/less.ts +335 -0
- package/src/substrate/lifo/commands/text/nano.ts +513 -0
- package/src/substrate/lifo/commands/text/nl.ts +74 -0
- package/src/substrate/lifo/commands/text/rev.ts +46 -0
- package/src/substrate/lifo/commands/text/sed.ts +297 -0
- package/src/substrate/lifo/commands/text/seq.ts +76 -0
- package/src/substrate/lifo/commands/text/sort.ts +88 -0
- package/src/substrate/lifo/commands/text/strings.ts +73 -0
- package/src/substrate/lifo/commands/text/tac.ts +37 -0
- package/src/substrate/lifo/commands/text/tail.ts +63 -0
- package/src/substrate/lifo/commands/text/tr.ts +192 -0
- package/src/substrate/lifo/commands/text/uniq.ts +77 -0
- package/src/substrate/lifo/commands/text/wc.ts +104 -0
- package/src/substrate/lifo/commands/types.ts +58 -0
- package/src/substrate/lifo/index.ts +173 -0
- package/src/substrate/lifo/kernel/ServiceManager.ts +371 -0
- package/src/substrate/lifo/kernel/index.ts +209 -0
- package/src/substrate/lifo/kernel/network/Bridge.ts +336 -0
- package/src/substrate/lifo/kernel/network/DNSResolver.ts +158 -0
- package/src/substrate/lifo/kernel/network/NetworkInterface.ts +235 -0
- package/src/substrate/lifo/kernel/network/NetworkNamespace.ts +182 -0
- package/src/substrate/lifo/kernel/network/NetworkStack.ts +590 -0
- package/src/substrate/lifo/kernel/network/PortBridge.ts +182 -0
- package/src/substrate/lifo/kernel/network/RoutingTable.ts +209 -0
- package/src/substrate/lifo/kernel/network/Socket.ts +245 -0
- package/src/substrate/lifo/kernel/network/index.ts +29 -0
- package/src/substrate/lifo/kernel/network/tunnel/BaseTunnel.ts +124 -0
- package/src/substrate/lifo/kernel/network/tunnel/VETHPair.ts +227 -0
- package/src/substrate/lifo/kernel/network/tunnel/WebSocketTunnel.ts +387 -0
- package/src/substrate/lifo/kernel/network/types.ts +178 -0
- package/src/substrate/lifo/kernel/persistence/PersistenceManager.ts +50 -0
- package/src/substrate/lifo/kernel/persistence/backends.ts +36 -0
- package/src/substrate/lifo/kernel/persistence/index.ts +5 -0
- package/src/substrate/lifo/kernel/persistence/serializer.ts +127 -0
- package/src/substrate/lifo/kernel/samples.ts +966 -0
- package/src/substrate/lifo/kernel/storage/BlobStore.ts +114 -0
- package/src/substrate/lifo/kernel/storage/ContentStore.ts +150 -0
- package/src/substrate/lifo/kernel/storage/index.ts +5 -0
- package/src/substrate/lifo/kernel/unit-parser.ts +95 -0
- package/src/substrate/lifo/kernel/vfs/VFS.ts +768 -0
- package/src/substrate/lifo/kernel/vfs/index.ts +9 -0
- package/src/substrate/lifo/kernel/vfs/providers/DevProvider.ts +172 -0
- package/src/substrate/lifo/kernel/vfs/providers/NativeFsProvider.ts +198 -0
- package/src/substrate/lifo/kernel/vfs/providers/ProcProvider.ts +144 -0
- package/src/substrate/lifo/kernel/vfs/types.ts +145 -0
- package/src/substrate/lifo/node-compat/buffer.ts +357 -0
- package/src/substrate/lifo/node-compat/child_process.ts +52 -0
- package/src/substrate/lifo/node-compat/console.ts +70 -0
- package/src/substrate/lifo/node-compat/crypto.ts +186 -0
- package/src/substrate/lifo/node-compat/dns.ts +214 -0
- package/src/substrate/lifo/node-compat/esbuild.ts +85 -0
- package/src/substrate/lifo/node-compat/events.ts +94 -0
- package/src/substrate/lifo/node-compat/fs.ts +762 -0
- package/src/substrate/lifo/node-compat/http.ts +561 -0
- package/src/substrate/lifo/node-compat/index.ts +300 -0
- package/src/substrate/lifo/node-compat/module.ts +148 -0
- package/src/substrate/lifo/node-compat/os.ts +44 -0
- package/src/substrate/lifo/node-compat/path.ts +74 -0
- package/src/substrate/lifo/node-compat/process.ts +178 -0
- package/src/substrate/lifo/node-compat/readline.ts +244 -0
- package/src/substrate/lifo/node-compat/rimraf.ts +80 -0
- package/src/substrate/lifo/node-compat/stream.ts +98 -0
- package/src/substrate/lifo/node-compat/string_decoder.ts +26 -0
- package/src/substrate/lifo/node-compat/timers.ts +21 -0
- package/src/substrate/lifo/node-compat/tty.ts +83 -0
- package/src/substrate/lifo/node-compat/url.ts +76 -0
- package/src/substrate/lifo/node-compat/util.ts +133 -0
- package/src/substrate/lifo/node-compat/zlib.ts +94 -0
- package/src/substrate/lifo/pkg/PackageManager.ts +105 -0
- package/src/substrate/lifo/pkg/lifo-dev.ts +130 -0
- package/src/substrate/lifo/pkg/lifo-runtime.ts +473 -0
- package/src/substrate/lifo/pkg/loader.ts +33 -0
- package/src/substrate/lifo/platform-globals.d.ts +41 -0
- package/src/substrate/lifo/sandbox/HeadlessTerminal.ts +38 -0
- package/src/substrate/lifo/sandbox/Sandbox.ts +279 -0
- package/src/substrate/lifo/sandbox/SandboxCommands.ts +74 -0
- package/src/substrate/lifo/sandbox/SandboxFs.ts +160 -0
- package/src/substrate/lifo/sandbox/index.ts +8 -0
- package/src/substrate/lifo/sandbox/types.ts +117 -0
- package/src/substrate/lifo/shell/ProcessRegistry.ts +379 -0
- package/src/substrate/lifo/shell/Shell.ts +2048 -0
- package/src/substrate/lifo/shell/completer.ts +212 -0
- package/src/substrate/lifo/shell/default-shell.ts +63 -0
- package/src/substrate/lifo/shell/expander.ts +1349 -0
- package/src/substrate/lifo/shell/history.ts +138 -0
- package/src/substrate/lifo/shell/interpreter.ts +1754 -0
- package/src/substrate/lifo/shell/jobs.ts +64 -0
- package/src/substrate/lifo/shell/lexer.ts +698 -0
- package/src/substrate/lifo/shell/parser.ts +711 -0
- package/src/substrate/lifo/shell/pipe.ts +92 -0
- package/src/substrate/lifo/shell/signals.ts +70 -0
- package/src/substrate/lifo/shell/terminal-stdin.ts +109 -0
- package/src/substrate/lifo/shell/test-builtin.ts +316 -0
- package/src/substrate/lifo/shell/types.ts +166 -0
- package/src/substrate/lifo/terminal/ITerminal.ts +9 -0
- package/src/substrate/lifo/utils/archive.ts +389 -0
- package/src/substrate/lifo/utils/args.ts +89 -0
- package/src/substrate/lifo/utils/colors.ts +29 -0
- package/src/substrate/lifo/utils/encoding.ts +21 -0
- package/src/substrate/lifo/utils/glob.ts +172 -0
- package/src/substrate/lifo/utils/mime.ts +114 -0
- package/src/substrate/lifo/utils/path.ts +83 -0
- package/src/types/assets.d.ts +4 -0
- package/src/vfs/events.ts +134 -0
- package/src/vfs/path.ts +71 -0
- package/src/vfs/seed-project.ts +1094 -0
- package/src/vfs/sqlite-vfs.ts +5035 -0
- package/src/vfs/symlink-registry.ts +172 -0
- package/src/workspace/nimbus-workspace.ts +213 -0
|
@@ -0,0 +1,1754 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ScriptNode,
|
|
3
|
+
ListNode,
|
|
4
|
+
PipelineNode,
|
|
5
|
+
SimpleCommandNode,
|
|
6
|
+
CompoundCommandNode,
|
|
7
|
+
DoubleBracketNode,
|
|
8
|
+
IfNode,
|
|
9
|
+
ForNode,
|
|
10
|
+
WhileNode,
|
|
11
|
+
UntilNode,
|
|
12
|
+
CaseNode,
|
|
13
|
+
FunctionDefNode,
|
|
14
|
+
GroupNode,
|
|
15
|
+
SubshellNode,
|
|
16
|
+
RedirectionNode,
|
|
17
|
+
AssignmentNode,
|
|
18
|
+
} from './types.js';
|
|
19
|
+
import type { VFS } from '../kernel/vfs/index.js';
|
|
20
|
+
import type { CommandRegistry } from '../commands/registry.js';
|
|
21
|
+
import type {
|
|
22
|
+
CommandOutputStream,
|
|
23
|
+
CommandInputStream,
|
|
24
|
+
CommandContext,
|
|
25
|
+
CommandRunAsHost,
|
|
26
|
+
TerminalInputStream,
|
|
27
|
+
} from '../commands/types.js';
|
|
28
|
+
import type { VfsCred } from '../../../runtime/os-contracts.js';
|
|
29
|
+
import { lex } from './lexer.js';
|
|
30
|
+
import { parse } from './parser.js';
|
|
31
|
+
import {
|
|
32
|
+
expandWords, expandWord, evaluateSubscript, ExpansionError,
|
|
33
|
+
type ExpandContext, type CapturedCommand,
|
|
34
|
+
} from './expander.js';
|
|
35
|
+
import { evaluateDoubleBracketWords } from './test-builtin.js';
|
|
36
|
+
import { PipeChannel } from './pipe.js';
|
|
37
|
+
import { JobTable } from './jobs.js';
|
|
38
|
+
import { ProcessRegistry } from './ProcessRegistry.js';
|
|
39
|
+
import { exitCodeForAbortSignal } from './signals.js';
|
|
40
|
+
import { resolve } from '../utils/path.js';
|
|
41
|
+
import { encode } from '../utils/encoding.js';
|
|
42
|
+
import { globMatch } from '../utils/glob.js';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Bytes a file-backed descriptor holds before committing. Matches the stream
|
|
46
|
+
* chunk size used elsewhere and keeps a line-at-a-time producer from paying a
|
|
47
|
+
* store write per line.
|
|
48
|
+
*/
|
|
49
|
+
const FILE_WRITE_BLOCK_BYTES = 64 * 1024;
|
|
50
|
+
|
|
51
|
+
function concatBytes(parts: Uint8Array[], total: number): Uint8Array {
|
|
52
|
+
const out = new Uint8Array(total);
|
|
53
|
+
let at = 0;
|
|
54
|
+
for (const part of parts) { out.set(part, at); at += part.length; }
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ─── Signal classes for control flow ───
|
|
59
|
+
|
|
60
|
+
export class BreakSignal {
|
|
61
|
+
constructor(public levels: number) {}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class ContinueSignal {
|
|
65
|
+
constructor(public levels: number) {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class ReturnSignal {
|
|
69
|
+
constructor(public exitCode: number) {}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export class ErrexitSignal {
|
|
73
|
+
constructor(public exitCode: number) {}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class ExitSignal {
|
|
77
|
+
constructor(public exitCode: number) {}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
class RedirectionOpenError extends Error {
|
|
81
|
+
constructor(
|
|
82
|
+
readonly target: string,
|
|
83
|
+
readonly fsError: unknown,
|
|
84
|
+
) {
|
|
85
|
+
super(fsError instanceof Error ? fsError.message : String(fsError));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function redirectionDiagnostic(error: RedirectionOpenError): string {
|
|
90
|
+
const code = typeof error.fsError === 'object' && error.fsError !== null
|
|
91
|
+
&& 'code' in error.fsError && typeof error.fsError.code === 'string'
|
|
92
|
+
? error.fsError.code
|
|
93
|
+
: /^([A-Z][A-Z0-9]+):/.exec(error.message)?.[1];
|
|
94
|
+
const reason = code === 'EACCES' || code === 'EPERM'
|
|
95
|
+
? 'Permission denied'
|
|
96
|
+
: code === 'ENOENT'
|
|
97
|
+
? 'No such file or directory'
|
|
98
|
+
: code === 'ENOTDIR'
|
|
99
|
+
? 'Not a directory'
|
|
100
|
+
: code === 'EISDIR'
|
|
101
|
+
? 'Is a directory'
|
|
102
|
+
: error.message;
|
|
103
|
+
return `sh: ${error.target}: ${reason}\n`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface ShellOptions {
|
|
107
|
+
errexit: boolean;
|
|
108
|
+
nounset: boolean;
|
|
109
|
+
pipefail: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface TrapTable {
|
|
113
|
+
get(signal: string): string | undefined;
|
|
114
|
+
set(signal: string, action: string): void;
|
|
115
|
+
delete(signal: string): void;
|
|
116
|
+
entries(): IterableIterator<[string, string]>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface BuiltinExecutionContext {
|
|
120
|
+
vfs: VFS;
|
|
121
|
+
/** The working directory a builtin resolves its relative path operands against. */
|
|
122
|
+
cwd: string;
|
|
123
|
+
stdin?: CommandInputStream;
|
|
124
|
+
stdout: CommandOutputStream;
|
|
125
|
+
stderr: CommandOutputStream;
|
|
126
|
+
terminalStdin?: TerminalInputStream;
|
|
127
|
+
terminalFds: TerminalFdState;
|
|
128
|
+
scriptMode?: boolean;
|
|
129
|
+
isFdTerminal(fd: number): boolean;
|
|
130
|
+
getPositionals(): readonly string[];
|
|
131
|
+
setPositionals(args: string[]): void;
|
|
132
|
+
executeInline(input: string, options?: InlineExecutionOptions): Promise<number>;
|
|
133
|
+
/** Bind a name to the running function. False outside one, where it is an error. */
|
|
134
|
+
declareLocal(name: string): boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface InlineExecutionOptions {
|
|
138
|
+
positionals?: string[];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export type BuiltinFn = (
|
|
142
|
+
args: string[],
|
|
143
|
+
stdout: CommandOutputStream,
|
|
144
|
+
stderr: CommandOutputStream,
|
|
145
|
+
stdin?: CommandInputStream,
|
|
146
|
+
context?: BuiltinExecutionContext,
|
|
147
|
+
) => Promise<number>;
|
|
148
|
+
|
|
149
|
+
type FdState = {
|
|
150
|
+
outputFds: Map<number, CommandOutputStream>;
|
|
151
|
+
inputFds: Map<number, CommandInputStream | undefined>;
|
|
152
|
+
terminalOutputFds: Set<number>;
|
|
153
|
+
terminalInputFds: Set<number>;
|
|
154
|
+
changedOutputFds: Set<number>;
|
|
155
|
+
changedInputFds: Set<number>;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
type OutputTarget = {
|
|
159
|
+
stream: CommandOutputStream;
|
|
160
|
+
terminal: boolean;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
type InputTarget = {
|
|
164
|
+
stream: CommandInputStream | undefined;
|
|
165
|
+
terminal: boolean;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
type ExecutionIo = {
|
|
169
|
+
stdin?: CommandInputStream;
|
|
170
|
+
stdout?: CommandOutputStream;
|
|
171
|
+
stderr?: CommandOutputStream;
|
|
172
|
+
/**
|
|
173
|
+
* Per-execution sink for shell-level direct-terminal writes (the
|
|
174
|
+
* `/dev/tty` target and the late-bound command-stdout fallback). Scoping
|
|
175
|
+
* this through `io` keeps a nested `Shell.execute` capture isolated: the
|
|
176
|
+
* parent command's closures resolve to the parent's terminal writer, never
|
|
177
|
+
* to a field a nested execute reassigns.
|
|
178
|
+
*/
|
|
179
|
+
writeToTerminal?: (text: string) => void;
|
|
180
|
+
terminalStdin?: TerminalInputStream;
|
|
181
|
+
terminalFds?: TerminalFdState;
|
|
182
|
+
scriptMode?: boolean;
|
|
183
|
+
signal?: AbortSignal;
|
|
184
|
+
registerProcess?: boolean;
|
|
185
|
+
positionals?: PositionalFrame;
|
|
186
|
+
/** Host-supplied fields merged into each command's CommandContext. */
|
|
187
|
+
commandContext?: Record<string, unknown>;
|
|
188
|
+
commandIdentity?: {
|
|
189
|
+
pid: number;
|
|
190
|
+
cred: VfsCred;
|
|
191
|
+
setUmask(mask: number): void;
|
|
192
|
+
};
|
|
193
|
+
runAs?: CommandRunAsHost;
|
|
194
|
+
vfs?: VFS;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export type TerminalFdState = {
|
|
198
|
+
stdin?: boolean;
|
|
199
|
+
stdout?: boolean;
|
|
200
|
+
stderr?: boolean;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
type PositionalFrame = {
|
|
204
|
+
args: string[];
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** A variable's complete binding: its scalar value, or its array, or neither. */
|
|
208
|
+
type SavedVariable = {
|
|
209
|
+
scalar: string | undefined;
|
|
210
|
+
array: (string | undefined)[] | undefined;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export interface InterpreterConfig {
|
|
214
|
+
env: Record<string, string>;
|
|
215
|
+
/**
|
|
216
|
+
* Indexed arrays; `env` holds the scalars. A name lives in exactly one of
|
|
217
|
+
* them, so `$arr` and `${arr[0]}` cannot disagree, and only `unset` moves a
|
|
218
|
+
* name from one to the other.
|
|
219
|
+
*/
|
|
220
|
+
arrays: Map<string, (string | undefined)[]>;
|
|
221
|
+
getCwd: () => string;
|
|
222
|
+
setCwd: (cwd: string) => void;
|
|
223
|
+
vfs: VFS;
|
|
224
|
+
registry: CommandRegistry;
|
|
225
|
+
builtins: Map<string, BuiltinFn>;
|
|
226
|
+
jobTable: JobTable;
|
|
227
|
+
processRegistry: ProcessRegistry;
|
|
228
|
+
writeToTerminal: (text: string) => void;
|
|
229
|
+
aliases?: Map<string, string>;
|
|
230
|
+
/** Returns the current abort signal for foreground commands */
|
|
231
|
+
getAbortSignal?: () => AbortSignal;
|
|
232
|
+
options: ShellOptions;
|
|
233
|
+
traps: TrapTable;
|
|
234
|
+
readonlyNames: ReadonlySet<string>;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Assign a plain value to a name. A name that already holds an array keeps it:
|
|
239
|
+
* `a=(x y); a=plain` sets `a[0]` and leaves `a[1]` alone, which is bash's rule
|
|
240
|
+
* and the reason a variable's type only changes through `unset`.
|
|
241
|
+
*/
|
|
242
|
+
export function assignScalar(
|
|
243
|
+
env: Record<string, string>,
|
|
244
|
+
arrays: Map<string, (string | undefined)[]>,
|
|
245
|
+
name: string,
|
|
246
|
+
value: string,
|
|
247
|
+
): void {
|
|
248
|
+
const array = arrays.get(name);
|
|
249
|
+
if (array === undefined) env[name] = value;
|
|
250
|
+
else array[0] = value;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export class Interpreter {
|
|
254
|
+
private config: InterpreterConfig;
|
|
255
|
+
private lastExitCode = 0;
|
|
256
|
+
private functions = new Map<string, CompoundCommandNode>();
|
|
257
|
+
private persistentOutputFds = new Map<number, CommandOutputStream>();
|
|
258
|
+
private persistentInputFds = new Map<number, CommandInputStream | undefined>();
|
|
259
|
+
private persistentTerminalOutputFds = new Set<number>();
|
|
260
|
+
private persistentTerminalInputFds = new Set<number>();
|
|
261
|
+
private errexitSuppressionDepth = 0;
|
|
262
|
+
private exitTrapDepth = 0;
|
|
263
|
+
/** One frame per running function call, holding the bindings `local` shadowed. */
|
|
264
|
+
private localFrames: Array<Map<string, SavedVariable>> = [];
|
|
265
|
+
|
|
266
|
+
constructor(config: InterpreterConfig) {
|
|
267
|
+
this.config = config;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
getLastExitCode(): number {
|
|
271
|
+
return this.lastExitCode;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async executeScript(script: ScriptNode, terminalStdin?: TerminalInputStream): Promise<number> {
|
|
275
|
+
return this.executeScriptWithIo(script, this.createTerminalIo(terminalStdin));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private async executeScriptWithIo(script: ScriptNode, io: ExecutionIo): Promise<number> {
|
|
279
|
+
let exitCode = 0;
|
|
280
|
+
try {
|
|
281
|
+
for (const list of script.lists) {
|
|
282
|
+
exitCode = await this.executeList(list, io);
|
|
283
|
+
}
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (error instanceof ErrexitSignal) {
|
|
286
|
+
exitCode = error.exitCode;
|
|
287
|
+
} else if (error instanceof ExitSignal) {
|
|
288
|
+
exitCode = error.exitCode;
|
|
289
|
+
} else {
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
this.lastExitCode = exitCode;
|
|
294
|
+
return exitCode;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async executeLine(
|
|
298
|
+
input: string,
|
|
299
|
+
terminalStdin?: TerminalInputStream,
|
|
300
|
+
options?: {
|
|
301
|
+
runExitTrap?: boolean;
|
|
302
|
+
stdin?: CommandInputStream;
|
|
303
|
+
stdout?: CommandOutputStream;
|
|
304
|
+
stderr?: CommandOutputStream;
|
|
305
|
+
writeToTerminal?: (text: string) => void;
|
|
306
|
+
terminalFds?: TerminalFdState;
|
|
307
|
+
scriptMode?: boolean;
|
|
308
|
+
commandContext?: Record<string, unknown>;
|
|
309
|
+
commandIdentity?: {
|
|
310
|
+
pid: number;
|
|
311
|
+
cred: VfsCred;
|
|
312
|
+
setUmask(mask: number): void;
|
|
313
|
+
};
|
|
314
|
+
runAs?: CommandRunAsHost;
|
|
315
|
+
signal?: AbortSignal;
|
|
316
|
+
},
|
|
317
|
+
): Promise<number> {
|
|
318
|
+
const io = this.createTerminalIo(
|
|
319
|
+
terminalStdin,
|
|
320
|
+
options?.terminalFds,
|
|
321
|
+
options?.scriptMode === true,
|
|
322
|
+
options?.stdin,
|
|
323
|
+
);
|
|
324
|
+
if (options?.stdout) io.stdout = options.stdout;
|
|
325
|
+
if (options?.stderr) io.stderr = options.stderr;
|
|
326
|
+
if (options?.writeToTerminal) io.writeToTerminal = options.writeToTerminal;
|
|
327
|
+
if (options?.commandContext) io.commandContext = options.commandContext;
|
|
328
|
+
if (options?.commandIdentity) io.commandIdentity = options.commandIdentity;
|
|
329
|
+
if (options?.runAs) io.runAs = options.runAs;
|
|
330
|
+
if (options?.signal) io.signal = options.signal;
|
|
331
|
+
if (options?.commandIdentity) io.vfs = this.config.vfs.as(options.commandIdentity.cred);
|
|
332
|
+
try {
|
|
333
|
+
const tokens = lex(input);
|
|
334
|
+
const script = parse(tokens);
|
|
335
|
+
const exitCode = await this.executeScriptWithIo(script, io);
|
|
336
|
+
return await this.runExitTrap(exitCode, io, options?.runExitTrap === true);
|
|
337
|
+
} catch (e) {
|
|
338
|
+
if (e instanceof BreakSignal || e instanceof ContinueSignal || e instanceof ReturnSignal) {
|
|
339
|
+
throw e;
|
|
340
|
+
}
|
|
341
|
+
if (e instanceof ErrexitSignal) {
|
|
342
|
+
this.lastExitCode = e.exitCode;
|
|
343
|
+
return e.exitCode;
|
|
344
|
+
}
|
|
345
|
+
if (e instanceof Error) {
|
|
346
|
+
this.writeTerminal(io, `${e.message}\n`);
|
|
347
|
+
}
|
|
348
|
+
// A failed expansion aborts with 1, the way bash does; 2 is reserved for
|
|
349
|
+
// the shell's own usage errors (syntax, bad builtin invocation).
|
|
350
|
+
const exitCode = e instanceof ExpansionError ? 1 : 2;
|
|
351
|
+
this.lastExitCode = exitCode;
|
|
352
|
+
return exitCode;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private async executeList(list: ListNode, io: ExecutionIo = {}): Promise<number> {
|
|
357
|
+
const abortCode = this.abortExitCode(io);
|
|
358
|
+
if (abortCode !== null) return abortCode;
|
|
359
|
+
|
|
360
|
+
if (list.background) {
|
|
361
|
+
const abortController = new AbortController();
|
|
362
|
+
const commandText = this.getListCommandText(list);
|
|
363
|
+
const backgroundIo = this.createCommandIo(io);
|
|
364
|
+
backgroundIo.signal = abortController.signal;
|
|
365
|
+
backgroundIo.registerProcess = false;
|
|
366
|
+
backgroundIo.positionals = this.forkPositionals(io);
|
|
367
|
+
|
|
368
|
+
const promise = (async (): Promise<number> => {
|
|
369
|
+
return await this.executeListEntries(list.entries, backgroundIo);
|
|
370
|
+
})();
|
|
371
|
+
|
|
372
|
+
const pid = this.config.processRegistry.spawn({
|
|
373
|
+
command: commandText.split(' ')[0] || 'unknown',
|
|
374
|
+
args: commandText.split(' '),
|
|
375
|
+
cwd: this.config.getCwd(),
|
|
376
|
+
env: { ...this.config.env },
|
|
377
|
+
isForeground: false,
|
|
378
|
+
promise,
|
|
379
|
+
abortController,
|
|
380
|
+
});
|
|
381
|
+
const waitable = this.config.processRegistry.get(pid)?.promise ?? promise;
|
|
382
|
+
const jobId = this.config.jobTable.add(commandText, waitable, abortController);
|
|
383
|
+
this.config.env['!'] = String(pid);
|
|
384
|
+
|
|
385
|
+
this.writeTerminal(io, `[${jobId}] ${pid} (background)\n`);
|
|
386
|
+
|
|
387
|
+
// Don't auto-reap - let Shell collect zombies before next prompt
|
|
388
|
+
// This matches Linux behavior where zombies persist until reaped
|
|
389
|
+
|
|
390
|
+
return 0;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return this.executeListEntries(list.entries, io);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private getListCommandText(list: ListNode): string {
|
|
397
|
+
return list.entries.map((e) =>
|
|
398
|
+
e.pipeline.commands.map((c) => {
|
|
399
|
+
if (c.type === 'simple_command') {
|
|
400
|
+
return c.words.map((w) => w.map((p) => p.text).join('')).join(' ');
|
|
401
|
+
}
|
|
402
|
+
return c.type;
|
|
403
|
+
}).join(' | '),
|
|
404
|
+
).join(' ');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
private async executeListEntries(entries: ListNode['entries'], io: ExecutionIo = {}): Promise<number> {
|
|
408
|
+
let exitCode = 0;
|
|
409
|
+
let skipNext = false;
|
|
410
|
+
|
|
411
|
+
for (const entry of entries) {
|
|
412
|
+
const abortCode = this.abortExitCode(io);
|
|
413
|
+
if (abortCode !== null) return abortCode;
|
|
414
|
+
|
|
415
|
+
if (!skipNext) {
|
|
416
|
+
exitCode = await this.executePipeline(entry.pipeline, io);
|
|
417
|
+
}
|
|
418
|
+
skipNext = false;
|
|
419
|
+
|
|
420
|
+
this.enforceErrexit(entry.connector, exitCode);
|
|
421
|
+
|
|
422
|
+
if (entry.connector === '&&' && exitCode !== 0) {
|
|
423
|
+
skipNext = true;
|
|
424
|
+
} else if (entry.connector === '||' && exitCode === 0) {
|
|
425
|
+
skipNext = true;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this.lastExitCode = exitCode;
|
|
430
|
+
return exitCode;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private async executePipeline(pipeline: PipelineNode, io: ExecutionIo = {}): Promise<number> {
|
|
434
|
+
const abortCode = this.abortExitCode(io);
|
|
435
|
+
if (abortCode !== null) return abortCode;
|
|
436
|
+
|
|
437
|
+
const commands = pipeline.commands;
|
|
438
|
+
|
|
439
|
+
let exitCode: number;
|
|
440
|
+
|
|
441
|
+
if (commands.length === 1) {
|
|
442
|
+
// Single command -- no piping needed
|
|
443
|
+
exitCode = await this.executeCommand(commands[0], io);
|
|
444
|
+
} else {
|
|
445
|
+
exitCode = await this.executePipelineCommands(commands, io);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (pipeline.negated) {
|
|
449
|
+
exitCode = exitCode === 0 ? 1 : 0;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return exitCode;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private async executePipelineCommands(commands: CompoundCommandNode[], io: ExecutionIo): Promise<number> {
|
|
456
|
+
const pipes: PipeChannel[] = [];
|
|
457
|
+
const promises: Promise<number>[] = [];
|
|
458
|
+
const pipelineAbortController = new AbortController();
|
|
459
|
+
const parentSignal = io.signal ?? this.config.getAbortSignal?.();
|
|
460
|
+
let unlinkParentSignal: (() => void) | undefined;
|
|
461
|
+
|
|
462
|
+
if (parentSignal?.aborted) {
|
|
463
|
+
pipelineAbortController.abort(parentSignal.reason);
|
|
464
|
+
} else if (parentSignal) {
|
|
465
|
+
unlinkParentSignal = linkAbortSignal(parentSignal, pipelineAbortController);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
for (let i = 0; i < commands.length; i++) {
|
|
470
|
+
const abortCode = this.abortExitCode(io);
|
|
471
|
+
if (abortCode !== null) return abortCode;
|
|
472
|
+
|
|
473
|
+
const stdin = i > 0 ? pipes[i - 1].reader : undefined;
|
|
474
|
+
let stdout: CommandOutputStream | undefined;
|
|
475
|
+
|
|
476
|
+
if (i < commands.length - 1) {
|
|
477
|
+
const pipe = new PipeChannel();
|
|
478
|
+
pipes.push(pipe);
|
|
479
|
+
stdout = pipe.writer;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const cmd = commands[i];
|
|
483
|
+
const isLast = i === commands.length - 1;
|
|
484
|
+
const commandStdin = stdin ?? (i === 0 ? io.stdin : undefined);
|
|
485
|
+
const commandStdout = stdout ?? (isLast ? io.stdout : undefined);
|
|
486
|
+
const cmdIo = this.createCommandIo(io);
|
|
487
|
+
if (commandStdin) cmdIo.stdin = commandStdin;
|
|
488
|
+
else delete cmdIo.stdin;
|
|
489
|
+
if (commandStdout) cmdIo.stdout = commandStdout;
|
|
490
|
+
else delete cmdIo.stdout;
|
|
491
|
+
cmdIo.terminalFds = {
|
|
492
|
+
stdin: stdin ? false : io.terminalFds?.stdin,
|
|
493
|
+
stdout: stdout ? false : io.terminalFds?.stdout,
|
|
494
|
+
stderr: io.terminalFds?.stderr,
|
|
495
|
+
};
|
|
496
|
+
cmdIo.signal = pipelineAbortController.signal;
|
|
497
|
+
cmdIo.positionals = this.forkPositionals(io);
|
|
498
|
+
const cmdPromise = (async (): Promise<number> => {
|
|
499
|
+
try {
|
|
500
|
+
return await this.executeCommand(cmd, cmdIo);
|
|
501
|
+
} catch (e) {
|
|
502
|
+
if (e instanceof ExitSignal) {
|
|
503
|
+
return e.exitCode;
|
|
504
|
+
}
|
|
505
|
+
throw e;
|
|
506
|
+
} finally {
|
|
507
|
+
if (i < commands.length - 1) {
|
|
508
|
+
pipes[i].close();
|
|
509
|
+
}
|
|
510
|
+
if (isLast) {
|
|
511
|
+
pipelineAbortController.abort();
|
|
512
|
+
for (const pipe of pipes) pipe.close();
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
})();
|
|
516
|
+
|
|
517
|
+
promises.push(cmdPromise);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const results = await Promise.all(promises);
|
|
521
|
+
if (this.config.options.pipefail) {
|
|
522
|
+
for (let i = results.length - 1; i >= 0; i--) {
|
|
523
|
+
if (results[i] !== 0) return results[i] ?? 1;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return results[results.length - 1] ?? 0;
|
|
527
|
+
} finally {
|
|
528
|
+
unlinkParentSignal?.();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
private async executeCommand(
|
|
533
|
+
cmd: CompoundCommandNode,
|
|
534
|
+
io: ExecutionIo = {},
|
|
535
|
+
): Promise<number> {
|
|
536
|
+
const abortCode = this.abortExitCode(io);
|
|
537
|
+
if (abortCode !== null) return abortCode;
|
|
538
|
+
|
|
539
|
+
switch (cmd.type) {
|
|
540
|
+
case 'simple_command':
|
|
541
|
+
return this.executeSimpleCommand(cmd, io);
|
|
542
|
+
case 'double_bracket':
|
|
543
|
+
return this.executeDoubleBracket(cmd, io);
|
|
544
|
+
case 'if':
|
|
545
|
+
return this.executeIf(cmd, io);
|
|
546
|
+
case 'for':
|
|
547
|
+
return this.executeFor(cmd, io);
|
|
548
|
+
case 'while':
|
|
549
|
+
return this.executeWhile(cmd, io);
|
|
550
|
+
case 'until':
|
|
551
|
+
return this.executeUntil(cmd, io);
|
|
552
|
+
case 'case':
|
|
553
|
+
return this.executeCase(cmd, io);
|
|
554
|
+
case 'group':
|
|
555
|
+
return this.executeGroup(cmd, io);
|
|
556
|
+
case 'subshell':
|
|
557
|
+
return this.executeSubshell(cmd, io);
|
|
558
|
+
case 'function_def':
|
|
559
|
+
return this.executeFunctionDef(cmd);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
private async executeIf(node: IfNode, io: ExecutionIo): Promise<number> {
|
|
564
|
+
return this.executeWithRedirections(node.redirections, io, async (redirIo) => {
|
|
565
|
+
let exitCode = 0;
|
|
566
|
+
|
|
567
|
+
for (const clause of node.clauses) {
|
|
568
|
+
const condCode = await this.withErrexitSuppressed(() => this.executeCompoundList(clause.condition, redirIo));
|
|
569
|
+
if (condCode === 0) {
|
|
570
|
+
exitCode = await this.executeCompoundList(clause.body, redirIo);
|
|
571
|
+
this.lastExitCode = exitCode;
|
|
572
|
+
return exitCode;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (node.elseBody) {
|
|
577
|
+
exitCode = await this.executeCompoundList(node.elseBody, redirIo);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
this.lastExitCode = exitCode;
|
|
581
|
+
return exitCode;
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
private async executeDoubleBracket(node: DoubleBracketNode, io: ExecutionIo): Promise<number> {
|
|
586
|
+
return this.executeWithRedirections(node.redirections, io, async (redirIo) => {
|
|
587
|
+
const stdout = redirIo.stdout ?? this.terminalSink(redirIo);
|
|
588
|
+
const stderr = redirIo.stderr ?? this.terminalSink(redirIo);
|
|
589
|
+
const fds = this.createCommandFds(stdout, stderr, redirIo.stdin, redirIo);
|
|
590
|
+
const builtinIo = this.createIoFromFds(redirIo, fds);
|
|
591
|
+
const exitCode = await this.withFdFlush(fds, () => evaluateDoubleBracketWords(
|
|
592
|
+
node.words,
|
|
593
|
+
this.createExpandContext(redirIo),
|
|
594
|
+
redirIo.vfs ?? this.config.vfs,
|
|
595
|
+
stderr,
|
|
596
|
+
{
|
|
597
|
+
vfs: builtinIo.vfs ?? this.config.vfs,
|
|
598
|
+
cwd: this.config.getCwd(),
|
|
599
|
+
stdin: builtinIo.stdin,
|
|
600
|
+
stdout,
|
|
601
|
+
stderr,
|
|
602
|
+
terminalStdin: redirIo.terminalStdin,
|
|
603
|
+
terminalFds: {
|
|
604
|
+
stdin: fds.terminalInputFds.has(0),
|
|
605
|
+
stdout: fds.terminalOutputFds.has(1),
|
|
606
|
+
stderr: fds.terminalOutputFds.has(2),
|
|
607
|
+
},
|
|
608
|
+
scriptMode: redirIo.scriptMode,
|
|
609
|
+
isFdTerminal: (fd) => this.isFdTerminal(fds, fd),
|
|
610
|
+
getPositionals: () => this.readPositionals(builtinIo),
|
|
611
|
+
setPositionals: (nextArgs) => this.writePositionals(builtinIo, nextArgs),
|
|
612
|
+
executeInline: (input, options) => this.executeInline(input, builtinIo, options),
|
|
613
|
+
declareLocal: (name) => this.declareLocal(name),
|
|
614
|
+
},
|
|
615
|
+
));
|
|
616
|
+
this.lastExitCode = exitCode;
|
|
617
|
+
return exitCode;
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
private async executeFor(node: ForNode, io: ExecutionIo): Promise<number> {
|
|
622
|
+
return this.executeWithRedirections(node.redirections, io, async (redirIo) => {
|
|
623
|
+
const expandCtx = this.createExpandContext(redirIo);
|
|
624
|
+
let exitCode = 0;
|
|
625
|
+
|
|
626
|
+
let values: string[];
|
|
627
|
+
if (node.words !== null) {
|
|
628
|
+
values = await expandWords(node.words, expandCtx);
|
|
629
|
+
} else {
|
|
630
|
+
values = [...this.readPositionals(redirIo)];
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
for (const val of values) {
|
|
634
|
+
const abortCode = this.abortExitCode(redirIo);
|
|
635
|
+
if (abortCode !== null) return abortCode;
|
|
636
|
+
|
|
637
|
+
if (!this.assignEnv(node.variable, val)) {
|
|
638
|
+
this.writeTerminal(redirIo, `${node.variable}: readonly variable\n`);
|
|
639
|
+
return 1;
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
exitCode = await this.executeCompoundList(node.body, redirIo);
|
|
643
|
+
} catch (e) {
|
|
644
|
+
if (e instanceof BreakSignal) {
|
|
645
|
+
if (e.levels > 1) throw new BreakSignal(e.levels - 1);
|
|
646
|
+
break;
|
|
647
|
+
}
|
|
648
|
+
if (e instanceof ContinueSignal) {
|
|
649
|
+
if (e.levels > 1) throw new ContinueSignal(e.levels - 1);
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
throw e;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
this.lastExitCode = exitCode;
|
|
657
|
+
return exitCode;
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
private async executeWhile(node: WhileNode, io: ExecutionIo): Promise<number> {
|
|
662
|
+
return this.executeWithRedirections(node.redirections, io, async (redirIo) => {
|
|
663
|
+
let exitCode = 0;
|
|
664
|
+
|
|
665
|
+
while (true) {
|
|
666
|
+
const abortCode = this.abortExitCode(redirIo);
|
|
667
|
+
if (abortCode !== null) return abortCode;
|
|
668
|
+
|
|
669
|
+
const condCode = await this.withErrexitSuppressed(() => this.executeCompoundList(node.condition, redirIo));
|
|
670
|
+
if (condCode !== 0) break;
|
|
671
|
+
|
|
672
|
+
try {
|
|
673
|
+
exitCode = await this.executeCompoundList(node.body, redirIo);
|
|
674
|
+
} catch (e) {
|
|
675
|
+
if (e instanceof BreakSignal) {
|
|
676
|
+
if (e.levels > 1) throw new BreakSignal(e.levels - 1);
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
if (e instanceof ContinueSignal) {
|
|
680
|
+
if (e.levels > 1) throw new ContinueSignal(e.levels - 1);
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
throw e;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
this.lastExitCode = exitCode;
|
|
688
|
+
return exitCode;
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
private async executeUntil(node: UntilNode, io: ExecutionIo): Promise<number> {
|
|
693
|
+
return this.executeWithRedirections(node.redirections, io, async (redirIo) => {
|
|
694
|
+
let exitCode = 0;
|
|
695
|
+
|
|
696
|
+
while (true) {
|
|
697
|
+
const abortCode = this.abortExitCode(redirIo);
|
|
698
|
+
if (abortCode !== null) return abortCode;
|
|
699
|
+
|
|
700
|
+
const condCode = await this.withErrexitSuppressed(() => this.executeCompoundList(node.condition, redirIo));
|
|
701
|
+
if (condCode === 0) break;
|
|
702
|
+
|
|
703
|
+
try {
|
|
704
|
+
exitCode = await this.executeCompoundList(node.body, redirIo);
|
|
705
|
+
} catch (e) {
|
|
706
|
+
if (e instanceof BreakSignal) {
|
|
707
|
+
if (e.levels > 1) throw new BreakSignal(e.levels - 1);
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
710
|
+
if (e instanceof ContinueSignal) {
|
|
711
|
+
if (e.levels > 1) throw new ContinueSignal(e.levels - 1);
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
throw e;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
this.lastExitCode = exitCode;
|
|
719
|
+
return exitCode;
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
private async executeCase(node: CaseNode, io: ExecutionIo): Promise<number> {
|
|
724
|
+
return this.executeWithRedirections(node.redirections, io, async (redirIo) => {
|
|
725
|
+
const expandCtx = this.createExpandContext(redirIo);
|
|
726
|
+
const wordValue = await expandWord(node.word, expandCtx);
|
|
727
|
+
let exitCode = 0;
|
|
728
|
+
|
|
729
|
+
for (const item of node.items) {
|
|
730
|
+
for (const pattern of item.patterns) {
|
|
731
|
+
const patternValue = await expandWord(pattern, expandCtx);
|
|
732
|
+
if (globMatch(patternValue, wordValue)) {
|
|
733
|
+
exitCode = await this.executeCompoundList(item.body, redirIo);
|
|
734
|
+
this.lastExitCode = exitCode;
|
|
735
|
+
return exitCode;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
this.lastExitCode = exitCode;
|
|
741
|
+
return exitCode;
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
private async executeFunctionDef(node: FunctionDefNode): Promise<number> {
|
|
746
|
+
this.functions.set(node.name, node.body);
|
|
747
|
+
return 0;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
private async executeGroup(node: GroupNode, io: ExecutionIo): Promise<number> {
|
|
751
|
+
const exitCode = await this.executeWithRedirections(
|
|
752
|
+
node.redirections,
|
|
753
|
+
io,
|
|
754
|
+
(redirIo) => this.executeCompoundList(node.body, redirIo),
|
|
755
|
+
);
|
|
756
|
+
this.lastExitCode = exitCode;
|
|
757
|
+
return exitCode;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
private async executeSubshell(node: SubshellNode, io: ExecutionIo): Promise<number> {
|
|
761
|
+
const savedCwd = this.config.getCwd();
|
|
762
|
+
const savedEnv = { ...this.config.env };
|
|
763
|
+
const savedArrays = new Map<string, (string | undefined)[]>();
|
|
764
|
+
for (const [name, elements] of this.config.arrays) savedArrays.set(name, [...elements]);
|
|
765
|
+
let exitCode = 0;
|
|
766
|
+
const subshellIo = this.createCommandIo(io);
|
|
767
|
+
subshellIo.positionals = this.forkPositionals(io);
|
|
768
|
+
try {
|
|
769
|
+
exitCode = await this.executeWithRedirections(
|
|
770
|
+
node.redirections,
|
|
771
|
+
subshellIo,
|
|
772
|
+
(redirIo) => this.executeCompoundList(node.body, redirIo),
|
|
773
|
+
);
|
|
774
|
+
} catch (e) {
|
|
775
|
+
if (e instanceof ExitSignal) {
|
|
776
|
+
exitCode = e.exitCode;
|
|
777
|
+
} else {
|
|
778
|
+
throw e;
|
|
779
|
+
}
|
|
780
|
+
} finally {
|
|
781
|
+
this.config.setCwd(savedCwd);
|
|
782
|
+
for (const key of Object.keys(this.config.env)) delete this.config.env[key];
|
|
783
|
+
Object.assign(this.config.env, savedEnv);
|
|
784
|
+
this.config.arrays.clear();
|
|
785
|
+
for (const [name, elements] of savedArrays) this.config.arrays.set(name, elements);
|
|
786
|
+
}
|
|
787
|
+
this.lastExitCode = exitCode;
|
|
788
|
+
return exitCode;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
private async executeCompoundList(lists: ListNode[], io: ExecutionIo): Promise<number> {
|
|
792
|
+
let exitCode = 0;
|
|
793
|
+
for (const list of lists) {
|
|
794
|
+
const abortCode = this.abortExitCode(io);
|
|
795
|
+
if (abortCode !== null) return abortCode;
|
|
796
|
+
exitCode = await this.executeList(list, io);
|
|
797
|
+
}
|
|
798
|
+
return exitCode;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
private async executeSimpleCommand(
|
|
802
|
+
cmd: SimpleCommandNode,
|
|
803
|
+
io: ExecutionIo,
|
|
804
|
+
): Promise<number> {
|
|
805
|
+
const abortCode = this.abortExitCode(io);
|
|
806
|
+
if (abortCode !== null) return abortCode;
|
|
807
|
+
|
|
808
|
+
const expandCtx = this.createExpandContext(io);
|
|
809
|
+
|
|
810
|
+
// Expand words
|
|
811
|
+
const expandedArgs = await expandWords(cmd.words, expandCtx);
|
|
812
|
+
if (expandedArgs.length === 0 && cmd.assignments.length > 0) {
|
|
813
|
+
// Bare assignment -- set env vars
|
|
814
|
+
for (const assign of cmd.assignments) {
|
|
815
|
+
if (!await this.applyAssignment(assign, expandCtx)) {
|
|
816
|
+
this.writeTerminal(io, `${assign.name}: readonly variable\n`);
|
|
817
|
+
if (io.scriptMode === true) throw new ErrexitSignal(1);
|
|
818
|
+
return 1;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
// A command that is only assignments exits with the status of the last
|
|
822
|
+
// command substitution it ran, so `out="$(cmd)" || die` sees cmd fail.
|
|
823
|
+
return expandCtx.lastSubstitutionExitCode ?? 0;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
if (expandedArgs.length === 0) {
|
|
827
|
+
return 0;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
const [name, ...args] = expandedArgs;
|
|
831
|
+
|
|
832
|
+
// Check alias expansion
|
|
833
|
+
const aliases = this.config.aliases;
|
|
834
|
+
if (aliases) {
|
|
835
|
+
const aliasValue = aliases.get(name);
|
|
836
|
+
if (aliasValue !== undefined) {
|
|
837
|
+
// Rebuild the command line with the alias expanded
|
|
838
|
+
const expandedLine = aliasValue + (args.length > 0 ? ' ' + args.join(' ') : '');
|
|
839
|
+
return this.executeLineWithIo(expandedLine, io);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Apply per-command assignments (temporary env)
|
|
844
|
+
const saved = new Map<string, SavedVariable>();
|
|
845
|
+
for (const assign of cmd.assignments) {
|
|
846
|
+
if (!saved.has(assign.name)) saved.set(assign.name, this.saveVariable(assign.name));
|
|
847
|
+
if (!await this.applyAssignment(assign, expandCtx)) {
|
|
848
|
+
(io.stderr ?? this.terminalSink(io)).write(`${assign.name}: readonly variable\n`);
|
|
849
|
+
return 1;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Set up stdout/stderr (per-execution io target, then the terminal sink)
|
|
854
|
+
let stdout: CommandOutputStream = io.stdout ?? this.terminalSink(io);
|
|
855
|
+
let stderr: CommandOutputStream = io.stderr ?? this.terminalSink(io);
|
|
856
|
+
let stdin: CommandInputStream | undefined = io.stdin;
|
|
857
|
+
const fds = this.createCommandFds(stdout, stderr, stdin, io);
|
|
858
|
+
try {
|
|
859
|
+
await this.applyRedirections(cmd.redirections, fds, expandCtx, io, io.terminalStdin);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
const redirStderr = fds.outputFds.get(2) ?? stderr;
|
|
862
|
+
redirStderr.write(error instanceof RedirectionOpenError
|
|
863
|
+
? redirectionDiagnostic(error)
|
|
864
|
+
: `${error instanceof Error ? error.message : String(error)}\n`);
|
|
865
|
+
this.lastExitCode = 1;
|
|
866
|
+
return 1;
|
|
867
|
+
}
|
|
868
|
+
stdout = fds.outputFds.get(1) ?? this.createNullWriter();
|
|
869
|
+
stderr = fds.outputFds.get(2) ?? this.createNullWriter();
|
|
870
|
+
stdin = fds.inputFds.get(0);
|
|
871
|
+
|
|
872
|
+
// If no stdin from pipe or redirect, fall back to terminal stdin
|
|
873
|
+
if (!stdin && io.terminalStdin) {
|
|
874
|
+
stdin = io.terminalStdin;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
let exitCode: number;
|
|
878
|
+
|
|
879
|
+
try {
|
|
880
|
+
// Check for break/continue/return builtins
|
|
881
|
+
if (name === 'break') {
|
|
882
|
+
const levels = args[0] ? parseInt(args[0], 10) : 1;
|
|
883
|
+
throw new BreakSignal(levels);
|
|
884
|
+
}
|
|
885
|
+
if (name === 'continue') {
|
|
886
|
+
const levels = args[0] ? parseInt(args[0], 10) : 1;
|
|
887
|
+
throw new ContinueSignal(levels);
|
|
888
|
+
}
|
|
889
|
+
if (name === 'return') {
|
|
890
|
+
const code = args[0] ? parseInt(args[0], 10) : this.lastExitCode;
|
|
891
|
+
throw new ReturnSignal(code);
|
|
892
|
+
}
|
|
893
|
+
if (name === 'exec' && args.length === 0) {
|
|
894
|
+
this.persistFdState(fds);
|
|
895
|
+
exitCode = 0;
|
|
896
|
+
} else {
|
|
897
|
+
// Check functions
|
|
898
|
+
const funcBody = this.functions.get(name);
|
|
899
|
+
if (funcBody) {
|
|
900
|
+
exitCode = await this.executeFunction(funcBody, args, this.createIoFromFds(io, fds));
|
|
901
|
+
} else {
|
|
902
|
+
// Check builtins
|
|
903
|
+
const builtin = this.config.builtins.get(name);
|
|
904
|
+
if (builtin) {
|
|
905
|
+
const builtinIo = this.createIoFromFds(io, fds);
|
|
906
|
+
exitCode = await builtin(args, stdout, stderr, stdin, {
|
|
907
|
+
vfs: builtinIo.vfs ?? this.config.vfs,
|
|
908
|
+
cwd: this.config.getCwd(),
|
|
909
|
+
stdin,
|
|
910
|
+
stdout,
|
|
911
|
+
stderr,
|
|
912
|
+
terminalStdin: io.terminalStdin,
|
|
913
|
+
terminalFds: {
|
|
914
|
+
stdin: fds.terminalInputFds.has(0),
|
|
915
|
+
stdout: fds.terminalOutputFds.has(1),
|
|
916
|
+
stderr: fds.terminalOutputFds.has(2),
|
|
917
|
+
},
|
|
918
|
+
scriptMode: io.scriptMode,
|
|
919
|
+
isFdTerminal: (fd) => this.isFdTerminal(fds, fd),
|
|
920
|
+
getPositionals: () => this.readPositionals(builtinIo),
|
|
921
|
+
setPositionals: (nextArgs) => this.writePositionals(builtinIo, nextArgs),
|
|
922
|
+
executeInline: (input, options) => this.executeInline(input, builtinIo, options),
|
|
923
|
+
declareLocal: (name) => this.declareLocal(name),
|
|
924
|
+
});
|
|
925
|
+
} else {
|
|
926
|
+
// Check registry
|
|
927
|
+
const command = await this.config.registry.resolve(name);
|
|
928
|
+
if (!command) {
|
|
929
|
+
stderr.write(`${name}: command not found\n`);
|
|
930
|
+
exitCode = 127;
|
|
931
|
+
} else {
|
|
932
|
+
const shouldRegister = io.registerProcess !== false;
|
|
933
|
+
let pid: number | undefined;
|
|
934
|
+
const abortController = new AbortController();
|
|
935
|
+
let unlinkShellSignal: (() => void) | undefined;
|
|
936
|
+
|
|
937
|
+
const shellSignal = io.signal ?? this.config.getAbortSignal?.() ?? new AbortController().signal;
|
|
938
|
+
unlinkShellSignal = linkAbortSignal(shellSignal, abortController);
|
|
939
|
+
|
|
940
|
+
const terminalStdin = io.terminalStdin;
|
|
941
|
+
const identity = io.commandIdentity;
|
|
942
|
+
if (!identity) throw new Error('shell command identity is unavailable');
|
|
943
|
+
let ctx: CommandContext;
|
|
944
|
+
ctx = {
|
|
945
|
+
...io.commandContext,
|
|
946
|
+
pid: identity.pid,
|
|
947
|
+
cred: identity.cred,
|
|
948
|
+
args,
|
|
949
|
+
env: { ...this.config.env },
|
|
950
|
+
cwd: this.config.getCwd(),
|
|
951
|
+
vfs: io.vfs ?? this.config.vfs,
|
|
952
|
+
stdout,
|
|
953
|
+
stderr,
|
|
954
|
+
signal: abortController.signal,
|
|
955
|
+
stdin,
|
|
956
|
+
terminalStdin,
|
|
957
|
+
setRawMode: terminalStdin
|
|
958
|
+
? (v: boolean) => { terminalStdin.rawMode = v; }
|
|
959
|
+
: undefined,
|
|
960
|
+
getRawMode: terminalStdin
|
|
961
|
+
? () => terminalStdin.rawMode
|
|
962
|
+
: undefined,
|
|
963
|
+
isFdTerminal: (fd: number) => this.isFdTerminal(fds, fd),
|
|
964
|
+
setUmask: identity.setUmask,
|
|
965
|
+
runAs: (cred, argv) => io.runAs
|
|
966
|
+
? io.runAs(ctx, cred, argv)
|
|
967
|
+
: Promise.resolve(126),
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
// Register process BEFORE executing so ps can see itself
|
|
971
|
+
let commandPromise: Promise<number>;
|
|
972
|
+
|
|
973
|
+
if (shouldRegister) {
|
|
974
|
+
let resolvePromise: ((code: number) => void) | undefined;
|
|
975
|
+
let rejectPromise: ((err: unknown) => void) | undefined;
|
|
976
|
+
const registeredPromise = new Promise<number>((resolve, reject) => {
|
|
977
|
+
resolvePromise = resolve;
|
|
978
|
+
rejectPromise = reject;
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
pid = this.config.processRegistry.spawn({
|
|
982
|
+
command: name,
|
|
983
|
+
args: [name, ...args],
|
|
984
|
+
cwd: this.config.getCwd(),
|
|
985
|
+
env: { ...this.config.env },
|
|
986
|
+
isForeground: true,
|
|
987
|
+
promise: registeredPromise,
|
|
988
|
+
abortController,
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
commandPromise = command(ctx).then(
|
|
992
|
+
(code) => {
|
|
993
|
+
resolvePromise?.(code);
|
|
994
|
+
return code;
|
|
995
|
+
},
|
|
996
|
+
(err) => {
|
|
997
|
+
rejectPromise?.(err);
|
|
998
|
+
if (err instanceof Error && err.name === 'AbortError') return 130;
|
|
999
|
+
// Surface the failure: this rejection handler resolves
|
|
1000
|
+
// commandPromise to an exit code, so the catch below
|
|
1001
|
+
// never sees the error — without this write a throwing
|
|
1002
|
+
// registered command dies silently at the prompt.
|
|
1003
|
+
stderr.write(`${name}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
1004
|
+
return 1;
|
|
1005
|
+
}
|
|
1006
|
+
);
|
|
1007
|
+
} else {
|
|
1008
|
+
commandPromise = command(ctx);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
try {
|
|
1012
|
+
exitCode = await commandPromise;
|
|
1013
|
+
} catch (e) {
|
|
1014
|
+
if (e instanceof Error && e.name === 'AbortError') {
|
|
1015
|
+
exitCode = 130;
|
|
1016
|
+
} else {
|
|
1017
|
+
stderr.write(`${name}: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
1018
|
+
exitCode = 1;
|
|
1019
|
+
}
|
|
1020
|
+
} finally {
|
|
1021
|
+
unlinkShellSignal?.();
|
|
1022
|
+
if (shouldRegister && pid !== undefined) {
|
|
1023
|
+
await Promise.resolve();
|
|
1024
|
+
this.config.processRegistry.reap(pid);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// A signalled command reports the SIGNAL's status, not whatever
|
|
1029
|
+
// code it returned on its way out: `sleep` observes only that
|
|
1030
|
+
// ctx.signal aborted, and cannot tell SIGINT (130) from
|
|
1031
|
+
// SIGQUIT (131). The shell holds the reason, so it decides.
|
|
1032
|
+
const signalledCode = this.abortExitCode(io);
|
|
1033
|
+
if (signalledCode !== null) exitCode = signalledCode;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
} finally {
|
|
1039
|
+
this.flushFds(fds);
|
|
1040
|
+
// Restore env from per-command assignments
|
|
1041
|
+
for (const [name, value] of saved) this.restoreVariable(name, value);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
const fatalSpecialBuiltin = io.scriptMode === true
|
|
1045
|
+
&& exitCode !== 0
|
|
1046
|
+
&& isFatalSpecialBuiltin(name);
|
|
1047
|
+
this.lastExitCode = exitCode;
|
|
1048
|
+
if (fatalSpecialBuiltin) throw new ErrexitSignal(exitCode);
|
|
1049
|
+
return exitCode;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
private assignEnv(name: string, value: string): boolean {
|
|
1053
|
+
if (this.config.readonlyNames.has(name)) return false;
|
|
1054
|
+
assignScalar(this.config.env, this.config.arrays, name, value);
|
|
1055
|
+
return true;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* `name=value`, `name+=value`, `name[expr]=value` and `name=(word …)`.
|
|
1060
|
+
* Returns false when the name is readonly, which the caller reports.
|
|
1061
|
+
*/
|
|
1062
|
+
private async applyAssignment(assign: AssignmentNode, ctx: ExpandContext): Promise<boolean> {
|
|
1063
|
+
const { name } = assign;
|
|
1064
|
+
if (this.config.readonlyNames.has(name)) return false;
|
|
1065
|
+
|
|
1066
|
+
if (assign.elements !== undefined) {
|
|
1067
|
+
const values = await expandWords(assign.elements, ctx);
|
|
1068
|
+
const existing = assign.append ? this.config.arrays.get(name) ?? [] : [];
|
|
1069
|
+
delete this.config.env[name];
|
|
1070
|
+
this.config.arrays.set(name, [...existing, ...values]);
|
|
1071
|
+
return true;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
const value = await expandWord(assign.value, ctx);
|
|
1075
|
+
|
|
1076
|
+
if (assign.subscript !== undefined) {
|
|
1077
|
+
const array = this.arrayFor(name);
|
|
1078
|
+
const index = await evaluateSubscript(assign.subscript, array.length, ctx);
|
|
1079
|
+
array[index] = assign.append ? (array[index] ?? '') + value : value;
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// A plain assignment to an array name lands on its first element, and
|
|
1084
|
+
// `arr+=x` appends to that element rather than adding one.
|
|
1085
|
+
const array = this.config.arrays.get(name);
|
|
1086
|
+
if (array !== undefined) {
|
|
1087
|
+
array[0] = assign.append ? (array[0] ?? '') + value : value;
|
|
1088
|
+
return true;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
this.config.env[name] = assign.append ? (this.config.env[name] ?? '') + value : value;
|
|
1092
|
+
return true;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/** One variable's whole binding, so a scope can put it back exactly. */
|
|
1096
|
+
private saveVariable(name: string): SavedVariable {
|
|
1097
|
+
return { scalar: this.config.env[name], array: this.config.arrays.get(name) };
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
private restoreVariable(name: string, saved: SavedVariable): void {
|
|
1101
|
+
if (saved.array === undefined) this.config.arrays.delete(name);
|
|
1102
|
+
else this.config.arrays.set(name, saved.array);
|
|
1103
|
+
if (saved.scalar === undefined) delete this.config.env[name];
|
|
1104
|
+
else this.config.env[name] = saved.scalar;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/** The array behind a subscripted assignment, promoting a scalar if needed. */
|
|
1108
|
+
private arrayFor(name: string): (string | undefined)[] {
|
|
1109
|
+
const existing = this.config.arrays.get(name);
|
|
1110
|
+
if (existing !== undefined) return existing;
|
|
1111
|
+
const scalar = this.config.env[name];
|
|
1112
|
+
const array: (string | undefined)[] = scalar === undefined ? [] : [scalar];
|
|
1113
|
+
delete this.config.env[name];
|
|
1114
|
+
this.config.arrays.set(name, array);
|
|
1115
|
+
return array;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
private async executeFunction(body: CompoundCommandNode, args: string[], io: ExecutionIo): Promise<number> {
|
|
1119
|
+
let exitCode: number;
|
|
1120
|
+
const functionIo = this.createCommandIo(io);
|
|
1121
|
+
functionIo.positionals = { args: [...args] };
|
|
1122
|
+
this.localFrames.push(new Map());
|
|
1123
|
+
try {
|
|
1124
|
+
exitCode = await this.executeCommand(body, functionIo);
|
|
1125
|
+
} catch (e) {
|
|
1126
|
+
if (e instanceof ReturnSignal) {
|
|
1127
|
+
exitCode = e.exitCode;
|
|
1128
|
+
} else {
|
|
1129
|
+
throw e;
|
|
1130
|
+
}
|
|
1131
|
+
} finally {
|
|
1132
|
+
const frame = this.localFrames.pop();
|
|
1133
|
+
if (frame !== undefined) {
|
|
1134
|
+
for (const [name, saved] of frame) this.restoreVariable(name, saved);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
this.lastExitCode = exitCode;
|
|
1139
|
+
return exitCode;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Bind a name to the running function, unset, so an assignment to it does
|
|
1144
|
+
* not outlive the call. Shell variables are dynamically scoped, so a callee
|
|
1145
|
+
* still sees its caller's locals — which is what bash does. Returns false
|
|
1146
|
+
* outside a function, where `local` is an error.
|
|
1147
|
+
*/
|
|
1148
|
+
private declareLocal(name: string): boolean {
|
|
1149
|
+
const frame = this.localFrames[this.localFrames.length - 1];
|
|
1150
|
+
if (frame === undefined) return false;
|
|
1151
|
+
if (!frame.has(name)) frame.set(name, this.saveVariable(name));
|
|
1152
|
+
delete this.config.env[name];
|
|
1153
|
+
this.config.arrays.delete(name);
|
|
1154
|
+
return true;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
async executeCapture(input: string, io: ExecutionIo = {}): Promise<CapturedCommand> {
|
|
1158
|
+
let captured = '';
|
|
1159
|
+
const stdout: CommandOutputStream = {
|
|
1160
|
+
write: (text: string) => { captured += text; },
|
|
1161
|
+
};
|
|
1162
|
+
|
|
1163
|
+
const captureIo = this.createCommandIo(io);
|
|
1164
|
+
captureIo.stdout = stdout;
|
|
1165
|
+
captureIo.positionals = this.forkPositionals(io);
|
|
1166
|
+
const exitCode = await this.executeLineWithIo(input, captureIo);
|
|
1167
|
+
|
|
1168
|
+
return { output: captured, exitCode };
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
private async executeInline(
|
|
1172
|
+
input: string,
|
|
1173
|
+
io: ExecutionIo,
|
|
1174
|
+
options: InlineExecutionOptions = {},
|
|
1175
|
+
): Promise<number> {
|
|
1176
|
+
const inlineIo = this.createCommandIo(io);
|
|
1177
|
+
if (options.positionals !== undefined) {
|
|
1178
|
+
inlineIo.positionals = { args: [...options.positionals] };
|
|
1179
|
+
}
|
|
1180
|
+
return this.executeLineWithIo(input, inlineIo);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
private async executeLineWithIo(input: string, io: ExecutionIo): Promise<number> {
|
|
1184
|
+
const tokens = lex(input);
|
|
1185
|
+
const script = parse(tokens);
|
|
1186
|
+
return this.executeScriptWithIo(script, io);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
private async runExitTrap(exitCode: number, io: ExecutionIo, enabled: boolean): Promise<number> {
|
|
1190
|
+
if (!enabled || this.exitTrapDepth > 0) return exitCode;
|
|
1191
|
+
const action = this.config.traps.get('EXIT');
|
|
1192
|
+
if (action === undefined) return exitCode;
|
|
1193
|
+
|
|
1194
|
+
const savedLastExitCode = this.lastExitCode;
|
|
1195
|
+
this.lastExitCode = exitCode;
|
|
1196
|
+
this.exitTrapDepth++;
|
|
1197
|
+
try {
|
|
1198
|
+
await this.executeLineWithIo(action, io);
|
|
1199
|
+
} finally {
|
|
1200
|
+
this.exitTrapDepth--;
|
|
1201
|
+
this.lastExitCode = savedLastExitCode;
|
|
1202
|
+
}
|
|
1203
|
+
return exitCode;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
private createTerminalIo(
|
|
1207
|
+
terminalStdin?: TerminalInputStream,
|
|
1208
|
+
terminalFds?: TerminalFdState,
|
|
1209
|
+
scriptMode?: boolean,
|
|
1210
|
+
stdin?: CommandInputStream,
|
|
1211
|
+
): ExecutionIo {
|
|
1212
|
+
const io: ExecutionIo = {};
|
|
1213
|
+
if (stdin) io.stdin = stdin;
|
|
1214
|
+
if (terminalStdin) io.terminalStdin = terminalStdin;
|
|
1215
|
+
if (terminalFds) io.terminalFds = terminalFds;
|
|
1216
|
+
if (scriptMode) io.scriptMode = true;
|
|
1217
|
+
return io;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
private createCommandIo(io: ExecutionIo): ExecutionIo {
|
|
1221
|
+
const next: ExecutionIo = {};
|
|
1222
|
+
if (io.stdin) next.stdin = io.stdin;
|
|
1223
|
+
if (io.stdout) next.stdout = io.stdout;
|
|
1224
|
+
if (io.stderr) next.stderr = io.stderr;
|
|
1225
|
+
if (io.writeToTerminal) next.writeToTerminal = io.writeToTerminal;
|
|
1226
|
+
if (io.terminalStdin) next.terminalStdin = io.terminalStdin;
|
|
1227
|
+
if (io.terminalFds) next.terminalFds = io.terminalFds;
|
|
1228
|
+
if (io.scriptMode) next.scriptMode = true;
|
|
1229
|
+
if (io.signal) next.signal = io.signal;
|
|
1230
|
+
if (io.registerProcess === false) next.registerProcess = false;
|
|
1231
|
+
if (io.positionals) next.positionals = io.positionals;
|
|
1232
|
+
if (io.commandContext) next.commandContext = io.commandContext;
|
|
1233
|
+
if (io.commandIdentity) next.commandIdentity = io.commandIdentity;
|
|
1234
|
+
if (io.runAs) next.runAs = io.runAs;
|
|
1235
|
+
if (io.vfs) next.vfs = io.vfs;
|
|
1236
|
+
return next;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/** Per-execution direct-terminal write, isolated from a nested capture. */
|
|
1240
|
+
private writeTerminal(io: ExecutionIo, text: string): void {
|
|
1241
|
+
(io.writeToTerminal ?? this.config.writeToTerminal)(text);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/** Late-bound fallback sink for command stdout/stderr with no fd target. */
|
|
1245
|
+
private terminalSink(io: ExecutionIo): CommandOutputStream {
|
|
1246
|
+
return { write: (text: string) => this.writeTerminal(io, text) };
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
private forkPositionals(io: ExecutionIo): PositionalFrame {
|
|
1250
|
+
return { args: [...this.readPositionals(io)] };
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
private createExpandContext(io: ExecutionIo = {}): ExpandContext {
|
|
1254
|
+
return {
|
|
1255
|
+
env: this.config.env,
|
|
1256
|
+
arrays: this.config.arrays,
|
|
1257
|
+
positionals: this.readPositionals(io),
|
|
1258
|
+
lastExitCode: this.lastExitCode,
|
|
1259
|
+
cwd: this.config.getCwd(),
|
|
1260
|
+
vfs: io.vfs ?? this.config.vfs,
|
|
1261
|
+
options: this.config.options,
|
|
1262
|
+
executeCapture: (input) => this.executeCapture(input, io),
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
private createIoFromFds(io: ExecutionIo, fds: FdState): ExecutionIo {
|
|
1267
|
+
const next = this.createCommandIo(io);
|
|
1268
|
+
next.stdout = fds.outputFds.get(1) ?? this.createNullWriter();
|
|
1269
|
+
next.stderr = fds.outputFds.get(2) ?? this.createNullWriter();
|
|
1270
|
+
const stdin = fds.inputFds.get(0);
|
|
1271
|
+
if (stdin) next.stdin = stdin;
|
|
1272
|
+
else delete next.stdin;
|
|
1273
|
+
next.terminalFds = {
|
|
1274
|
+
stdin: fds.terminalInputFds.has(0),
|
|
1275
|
+
stdout: fds.terminalOutputFds.has(1),
|
|
1276
|
+
stderr: fds.terminalOutputFds.has(2),
|
|
1277
|
+
};
|
|
1278
|
+
return next;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
private readPositionals(io: ExecutionIo): readonly string[] {
|
|
1282
|
+
if (io.positionals) return io.positionals.args;
|
|
1283
|
+
const count = Number.parseInt(this.config.env['#'] ?? '0', 10);
|
|
1284
|
+
const args: string[] = [];
|
|
1285
|
+
for (let i = 1; i <= count; i++) {
|
|
1286
|
+
args.push(this.config.env[String(i)] ?? '');
|
|
1287
|
+
}
|
|
1288
|
+
return args;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
private writePositionals(io: ExecutionIo, args: string[]): void {
|
|
1292
|
+
if (io.positionals) {
|
|
1293
|
+
io.positionals.args = [...args];
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
for (const key of Object.keys(this.config.env)) {
|
|
1297
|
+
if (key === '@' || key === '#' || /^[1-9][0-9]*$/.test(key)) {
|
|
1298
|
+
delete this.config.env[key];
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
this.config.env['#'] = String(args.length);
|
|
1302
|
+
this.config.env['@'] = args.join(' ');
|
|
1303
|
+
for (let i = 0; i < args.length; i++) {
|
|
1304
|
+
this.config.env[String(i + 1)] = args[i];
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
private createCommandFds(
|
|
1309
|
+
stdout: CommandOutputStream,
|
|
1310
|
+
stderr: CommandOutputStream,
|
|
1311
|
+
stdin: CommandInputStream | undefined,
|
|
1312
|
+
io: ExecutionIo,
|
|
1313
|
+
): FdState {
|
|
1314
|
+
const outputFds = new Map<number, CommandOutputStream>([
|
|
1315
|
+
[1, stdout],
|
|
1316
|
+
[2, stderr],
|
|
1317
|
+
...this.persistentOutputFds,
|
|
1318
|
+
]);
|
|
1319
|
+
const inputFds = new Map<number, CommandInputStream | undefined>([
|
|
1320
|
+
[0, stdin],
|
|
1321
|
+
...this.persistentInputFds,
|
|
1322
|
+
]);
|
|
1323
|
+
const terminalOutputFds = new Set<number>(this.persistentTerminalOutputFds);
|
|
1324
|
+
setMembership(
|
|
1325
|
+
terminalOutputFds,
|
|
1326
|
+
1,
|
|
1327
|
+
io.terminalFds?.stdout ?? !io.stdout,
|
|
1328
|
+
);
|
|
1329
|
+
setMembership(
|
|
1330
|
+
terminalOutputFds,
|
|
1331
|
+
2,
|
|
1332
|
+
io.terminalFds?.stderr ?? !io.stderr,
|
|
1333
|
+
);
|
|
1334
|
+
const terminalInputFds = new Set<number>(this.persistentTerminalInputFds);
|
|
1335
|
+
setMembership(
|
|
1336
|
+
terminalInputFds,
|
|
1337
|
+
0,
|
|
1338
|
+
io.terminalFds?.stdin ?? (!stdin && Boolean(io.terminalStdin)),
|
|
1339
|
+
);
|
|
1340
|
+
if (io.terminalStdin) {
|
|
1341
|
+
for (const fd of terminalInputFds) {
|
|
1342
|
+
inputFds.set(fd, io.terminalStdin);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return {
|
|
1346
|
+
outputFds,
|
|
1347
|
+
inputFds,
|
|
1348
|
+
terminalOutputFds,
|
|
1349
|
+
terminalInputFds,
|
|
1350
|
+
changedOutputFds: new Set(),
|
|
1351
|
+
changedInputFds: new Set(),
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
private async executeWithRedirections(
|
|
1356
|
+
redirections: RedirectionNode[],
|
|
1357
|
+
io: ExecutionIo,
|
|
1358
|
+
execute: (io: ExecutionIo) => Promise<number>,
|
|
1359
|
+
): Promise<number> {
|
|
1360
|
+
if (redirections.length === 0) {
|
|
1361
|
+
return execute(io);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
const expandCtx = this.createExpandContext(io);
|
|
1365
|
+
const stdout = io.stdout ?? this.terminalSink(io);
|
|
1366
|
+
const stderr = io.stderr ?? this.terminalSink(io);
|
|
1367
|
+
const fds = this.createCommandFds(stdout, stderr, io.stdin, io);
|
|
1368
|
+
try {
|
|
1369
|
+
await this.applyRedirections(redirections, fds, expandCtx, io, io.terminalStdin);
|
|
1370
|
+
} catch (error) {
|
|
1371
|
+
if (!(error instanceof RedirectionOpenError)) throw error;
|
|
1372
|
+
const redirStderr = fds.outputFds.get(2) ?? stderr;
|
|
1373
|
+
redirStderr.write(redirectionDiagnostic(error));
|
|
1374
|
+
this.lastExitCode = 1;
|
|
1375
|
+
return 1;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
return this.withFdFlush(fds, () => execute(this.createIoFromFds(io, fds)));
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
private async applyRedirections(
|
|
1382
|
+
redirections: RedirectionNode[],
|
|
1383
|
+
fds: FdState,
|
|
1384
|
+
expandCtx: ExpandContext,
|
|
1385
|
+
io: ExecutionIo,
|
|
1386
|
+
terminalStdin?: TerminalInputStream,
|
|
1387
|
+
): Promise<void> {
|
|
1388
|
+
for (const redir of redirections) {
|
|
1389
|
+
if (redir.operator === 'heredoc') {
|
|
1390
|
+
const heredoc = redir.heredoc ?? { body: '', quoted: false, stripTabs: false };
|
|
1391
|
+
const body = heredoc.quoted
|
|
1392
|
+
? heredoc.body
|
|
1393
|
+
: await expandWord([{ text: heredoc.body, quoted: 'double' }], expandCtx);
|
|
1394
|
+
this.setInputFd(fds, redir.fd ?? 0, { stream: this.createStringReader(body), terminal: false });
|
|
1395
|
+
continue;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
const target = await expandWord(redir.target, expandCtx);
|
|
1399
|
+
switch (redir.operator) {
|
|
1400
|
+
case 'write':
|
|
1401
|
+
this.setOutputFd(fds, redir.fd ?? 1, this.openOutputTarget(io, target, 'write', fds, terminalStdin));
|
|
1402
|
+
break;
|
|
1403
|
+
case 'append':
|
|
1404
|
+
this.setOutputFd(fds, redir.fd ?? 1, this.openOutputTarget(io, target, 'append', fds, terminalStdin));
|
|
1405
|
+
break;
|
|
1406
|
+
case 'read':
|
|
1407
|
+
this.setInputFd(fds, redir.fd ?? 0, this.openInputTarget(io, target, fds, terminalStdin));
|
|
1408
|
+
break;
|
|
1409
|
+
case 'readWrite': {
|
|
1410
|
+
const fd = redir.fd ?? 0;
|
|
1411
|
+
this.setInputFd(fds, fd, this.openInputTarget(io, target, fds, terminalStdin));
|
|
1412
|
+
this.setOutputFd(fds, fd, this.openOutputTarget(io, target, 'append', fds, terminalStdin));
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
case 'writeAll': {
|
|
1416
|
+
const writer = this.openOutputTarget(io, target, 'write', fds, terminalStdin);
|
|
1417
|
+
this.setOutputFd(fds, 1, writer);
|
|
1418
|
+
this.setOutputFd(fds, 2, writer);
|
|
1419
|
+
break;
|
|
1420
|
+
}
|
|
1421
|
+
case 'dupOutput':
|
|
1422
|
+
this.dupOutputFd(fds, redir.fd ?? 1, target);
|
|
1423
|
+
break;
|
|
1424
|
+
case 'dupInput':
|
|
1425
|
+
this.dupInputFd(fds, redir.fd ?? 0, target);
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
private persistFdState(fds: FdState): void {
|
|
1432
|
+
for (const fd of fds.changedOutputFds) {
|
|
1433
|
+
const stream = fds.outputFds.get(fd);
|
|
1434
|
+
if (stream) this.persistentOutputFds.set(fd, stream);
|
|
1435
|
+
else this.persistentOutputFds.delete(fd);
|
|
1436
|
+
if (fds.terminalOutputFds.has(fd)) this.persistentTerminalOutputFds.add(fd);
|
|
1437
|
+
else this.persistentTerminalOutputFds.delete(fd);
|
|
1438
|
+
}
|
|
1439
|
+
for (const fd of fds.changedInputFds) {
|
|
1440
|
+
const isTerminal = fds.terminalInputFds.has(fd);
|
|
1441
|
+
if (fds.inputFds.has(fd)) {
|
|
1442
|
+
this.persistentInputFds.set(fd, isTerminal ? undefined : fds.inputFds.get(fd));
|
|
1443
|
+
} else {
|
|
1444
|
+
this.persistentInputFds.delete(fd);
|
|
1445
|
+
}
|
|
1446
|
+
if (isTerminal) this.persistentTerminalInputFds.add(fd);
|
|
1447
|
+
else this.persistentTerminalInputFds.delete(fd);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
private setOutputFd(fds: FdState, fd: number, target: OutputTarget): void {
|
|
1452
|
+
fds.outputFds.set(fd, target.stream);
|
|
1453
|
+
setMembership(fds.terminalOutputFds, fd, target.terminal);
|
|
1454
|
+
fds.changedOutputFds.add(fd);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
private setInputFd(fds: FdState, fd: number, target: InputTarget): void {
|
|
1458
|
+
fds.inputFds.set(fd, target.stream);
|
|
1459
|
+
setMembership(fds.terminalInputFds, fd, target.terminal);
|
|
1460
|
+
fds.changedInputFds.add(fd);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
private dupOutputFd(fds: FdState, fd: number, target: string): void {
|
|
1464
|
+
fds.changedOutputFds.add(fd);
|
|
1465
|
+
if (target === '-') {
|
|
1466
|
+
fds.outputFds.delete(fd);
|
|
1467
|
+
fds.terminalOutputFds.delete(fd);
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
const resolved = this.resolveOutputFd(target, fds.outputFds, fds.terminalOutputFds);
|
|
1471
|
+
fds.outputFds.set(fd, resolved.stream);
|
|
1472
|
+
setMembership(fds.terminalOutputFds, fd, resolved.terminal);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
private dupInputFd(fds: FdState, fd: number, target: string): void {
|
|
1476
|
+
fds.changedInputFds.add(fd);
|
|
1477
|
+
if (target === '-') {
|
|
1478
|
+
fds.inputFds.delete(fd);
|
|
1479
|
+
fds.terminalInputFds.delete(fd);
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
const resolved = this.resolveInputFd(target, fds.inputFds, fds.terminalInputFds);
|
|
1483
|
+
fds.inputFds.set(fd, resolved.stream);
|
|
1484
|
+
setMembership(fds.terminalInputFds, fd, resolved.terminal);
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
private openOutputTarget(
|
|
1488
|
+
io: ExecutionIo,
|
|
1489
|
+
target: string,
|
|
1490
|
+
mode: 'write' | 'append',
|
|
1491
|
+
fds: FdState,
|
|
1492
|
+
terminalStdin?: TerminalInputStream,
|
|
1493
|
+
): OutputTarget {
|
|
1494
|
+
if (target === '/dev/null') return { stream: this.createNullWriter(), terminal: false };
|
|
1495
|
+
if (target === '/dev/tty') {
|
|
1496
|
+
if (!terminalStdin) throw new Error('/dev/tty: no controlling terminal');
|
|
1497
|
+
return { stream: this.terminalSink(io), terminal: true };
|
|
1498
|
+
}
|
|
1499
|
+
// /dev/stdout and /dev/stderr name the process's own descriptors, not
|
|
1500
|
+
// files. Writing them into the device provider would silently discard.
|
|
1501
|
+
if (target === '/dev/stdout') return this.resolveOutputFd('1', fds.outputFds, fds.terminalOutputFds);
|
|
1502
|
+
if (target === '/dev/stderr') return this.resolveOutputFd('2', fds.outputFds, fds.terminalOutputFds);
|
|
1503
|
+
const targetPath = resolve(this.config.getCwd(), target);
|
|
1504
|
+
const vfs = io.vfs ?? this.config.vfs;
|
|
1505
|
+
try {
|
|
1506
|
+
if (mode === 'write') {
|
|
1507
|
+
vfs.writeFile(targetPath, '');
|
|
1508
|
+
return { stream: this.createFileWriter(vfs, targetPath, 'truncate'), terminal: false };
|
|
1509
|
+
}
|
|
1510
|
+
if (vfs.exists(targetPath)) {
|
|
1511
|
+
if (vfs.stat(targetPath).type === 'directory') {
|
|
1512
|
+
throw Object.assign(new Error(`EISDIR: ${targetPath}`), { code: 'EISDIR' });
|
|
1513
|
+
}
|
|
1514
|
+
vfs.access(targetPath, 0o2);
|
|
1515
|
+
} else {
|
|
1516
|
+
vfs.writeFile(targetPath, '');
|
|
1517
|
+
}
|
|
1518
|
+
return { stream: this.createFileWriter(vfs, targetPath, 'append'), terminal: false };
|
|
1519
|
+
} catch (error) {
|
|
1520
|
+
throw new RedirectionOpenError(target, error);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
private openInputTarget(
|
|
1525
|
+
io: ExecutionIo,
|
|
1526
|
+
target: string,
|
|
1527
|
+
fds: FdState,
|
|
1528
|
+
terminalStdin?: TerminalInputStream,
|
|
1529
|
+
): InputTarget {
|
|
1530
|
+
if (target === '/dev/null') return { stream: this.createEmptyReader(), terminal: false };
|
|
1531
|
+
if (target === '/dev/tty') {
|
|
1532
|
+
if (!terminalStdin) throw new Error('/dev/tty: no controlling terminal');
|
|
1533
|
+
return { stream: terminalStdin, terminal: true };
|
|
1534
|
+
}
|
|
1535
|
+
if (target === '/dev/stdin') return this.resolveInputFd('0', fds.inputFds, fds.terminalInputFds);
|
|
1536
|
+
try {
|
|
1537
|
+
return {
|
|
1538
|
+
stream: this.createFileReader(io.vfs ?? this.config.vfs, resolve(this.config.getCwd(), target)),
|
|
1539
|
+
terminal: false,
|
|
1540
|
+
};
|
|
1541
|
+
} catch (error) {
|
|
1542
|
+
throw new RedirectionOpenError(target, error);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/**
|
|
1547
|
+
* A file-backed descriptor: an open file plus a write offset.
|
|
1548
|
+
*
|
|
1549
|
+
* Each write lands at the offset and advances it, the way write(2) does.
|
|
1550
|
+
* Restating the whole file per write — which is what this used to do —
|
|
1551
|
+
* makes every multi-write producer (`cat a b c`, a streaming `curl`, any
|
|
1552
|
+
* line-at-a-time filter) persist only its final write and silently drop
|
|
1553
|
+
* everything before it.
|
|
1554
|
+
*
|
|
1555
|
+
* Writes buffer to a block, as stdio does, so a line-at-a-time producer
|
|
1556
|
+
* costs one store write per block rather than one per line. `mode`
|
|
1557
|
+
* distinguishes `>` (a plain offset from the truncation point) from `>>`,
|
|
1558
|
+
* which is O_APPEND: every block lands at whatever the current end is, so
|
|
1559
|
+
* two descriptors appending to one file cannot overwrite each other.
|
|
1560
|
+
*/
|
|
1561
|
+
private createFileWriter(vfs: VFS, path: string, mode: 'truncate' | 'append'): CommandOutputStream {
|
|
1562
|
+
let offset = 0;
|
|
1563
|
+
let pending: Uint8Array[] = [];
|
|
1564
|
+
let pendingBytes = 0;
|
|
1565
|
+
|
|
1566
|
+
const endOfFile = (): number => (vfs.exists(path) ? vfs.stat(path).size : 0);
|
|
1567
|
+
|
|
1568
|
+
const flush = (): void => {
|
|
1569
|
+
if (pendingBytes === 0) return;
|
|
1570
|
+
const block = pending.length === 1 ? pending[0] : concatBytes(pending, pendingBytes);
|
|
1571
|
+
pending = [];
|
|
1572
|
+
pendingBytes = 0;
|
|
1573
|
+
const at = mode === 'append' ? endOfFile() : offset;
|
|
1574
|
+
vfs.writeRange(path, at, block);
|
|
1575
|
+
offset = at + block.length;
|
|
1576
|
+
};
|
|
1577
|
+
|
|
1578
|
+
const push = (bytes: Uint8Array): void => {
|
|
1579
|
+
if (bytes.length === 0) return;
|
|
1580
|
+
pending.push(bytes);
|
|
1581
|
+
pendingBytes += bytes.length;
|
|
1582
|
+
if (pendingBytes >= FILE_WRITE_BLOCK_BYTES) flush();
|
|
1583
|
+
};
|
|
1584
|
+
|
|
1585
|
+
return {
|
|
1586
|
+
write: (text: string) => push(encode(text)),
|
|
1587
|
+
writeBytes: (bytes: Uint8Array) => push(bytes),
|
|
1588
|
+
flush,
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/**
|
|
1593
|
+
* Run `body` and commit every file-backed descriptor it wrote through,
|
|
1594
|
+
* whether it returned or threw. This is the close(2) side of the buffering
|
|
1595
|
+
* in createFileWriter: buffered bytes must reach the store before the next
|
|
1596
|
+
* command can read the file.
|
|
1597
|
+
*/
|
|
1598
|
+
private async withFdFlush<T>(fds: FdState, body: () => Promise<T>): Promise<T> {
|
|
1599
|
+
try {
|
|
1600
|
+
return await body();
|
|
1601
|
+
} finally {
|
|
1602
|
+
this.flushFds(fds);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
private flushFds(fds: FdState): void {
|
|
1607
|
+
for (const stream of fds.outputFds.values()) stream.flush?.();
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
private createFileReader(vfs: VFS, path: string): CommandInputStream {
|
|
1611
|
+
const content = vfs.readFileString(path);
|
|
1612
|
+
return this.createStringReader(content);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
private createStringReader(content: string): CommandInputStream {
|
|
1616
|
+
let offset = 0;
|
|
1617
|
+
return {
|
|
1618
|
+
read: async () => {
|
|
1619
|
+
if (offset >= content.length) return null;
|
|
1620
|
+
const chunk = content.slice(offset);
|
|
1621
|
+
offset = content.length;
|
|
1622
|
+
return chunk;
|
|
1623
|
+
},
|
|
1624
|
+
readAll: async () => {
|
|
1625
|
+
if (offset >= content.length) return '';
|
|
1626
|
+
const chunk = content.slice(offset);
|
|
1627
|
+
offset = content.length;
|
|
1628
|
+
return chunk;
|
|
1629
|
+
},
|
|
1630
|
+
readLine: async () => {
|
|
1631
|
+
if (offset >= content.length) return null;
|
|
1632
|
+
const newline = content.indexOf('\n', offset);
|
|
1633
|
+
if (newline < 0) {
|
|
1634
|
+
const line = content.slice(offset);
|
|
1635
|
+
offset = content.length;
|
|
1636
|
+
return line;
|
|
1637
|
+
}
|
|
1638
|
+
const line = content.slice(offset, newline);
|
|
1639
|
+
offset = newline + 1;
|
|
1640
|
+
return line;
|
|
1641
|
+
},
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
private resolveOutputFd(
|
|
1646
|
+
target: string,
|
|
1647
|
+
outputFds: Map<number, CommandOutputStream>,
|
|
1648
|
+
terminalOutputFds: Set<number>,
|
|
1649
|
+
): OutputTarget {
|
|
1650
|
+
if (target === '-') return { stream: this.createNullWriter(), terminal: false };
|
|
1651
|
+
const fd = this.parseFdTarget(target);
|
|
1652
|
+
const stream = outputFds.get(fd);
|
|
1653
|
+
if (!stream) throw new Error(`bad output file descriptor: ${target}`);
|
|
1654
|
+
return { stream, terminal: terminalOutputFds.has(fd) };
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
private resolveInputFd(
|
|
1658
|
+
target: string,
|
|
1659
|
+
inputFds: Map<number, CommandInputStream | undefined>,
|
|
1660
|
+
terminalInputFds: Set<number>,
|
|
1661
|
+
): InputTarget {
|
|
1662
|
+
if (target === '-') return { stream: this.createEmptyReader(), terminal: false };
|
|
1663
|
+
const fd = this.parseFdTarget(target);
|
|
1664
|
+
if (!inputFds.has(fd)) throw new Error(`bad input file descriptor: ${target}`);
|
|
1665
|
+
return { stream: inputFds.get(fd), terminal: terminalInputFds.has(fd) };
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
private parseFdTarget(target: string): number {
|
|
1669
|
+
if (!isDecimalInteger(target)) throw new Error(`bad file descriptor: ${target}`);
|
|
1670
|
+
return Number.parseInt(target, 10);
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
private createNullWriter(): CommandOutputStream {
|
|
1674
|
+
return { write: () => {}, writeBytes: () => {} };
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
private createEmptyReader(): CommandInputStream {
|
|
1678
|
+
return { read: async () => null, readAll: async () => '', readLine: async () => null };
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
private isFdTerminal(fds: FdState, fd: number): boolean {
|
|
1682
|
+
if (fd === 0) return fds.terminalInputFds.has(fd);
|
|
1683
|
+
return fds.terminalOutputFds.has(fd);
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
private enforceErrexit(connector: '&&' | '||' | null, exitCode: number): void {
|
|
1687
|
+
if (!this.config.options.errexit) return;
|
|
1688
|
+
if (this.errexitSuppressionDepth > 0) return;
|
|
1689
|
+
if (exitCode === 0) return;
|
|
1690
|
+
if (connector === '&&' || connector === '||') return;
|
|
1691
|
+
throw new ErrexitSignal(exitCode);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
private async withErrexitSuppressed<T>(fn: () => Promise<T>): Promise<T> {
|
|
1695
|
+
this.errexitSuppressionDepth++;
|
|
1696
|
+
try {
|
|
1697
|
+
return await fn();
|
|
1698
|
+
} finally {
|
|
1699
|
+
this.errexitSuppressionDepth--;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
private abortExitCode(io: ExecutionIo): number | null {
|
|
1704
|
+
const signal = io.signal ?? this.config.getAbortSignal?.();
|
|
1705
|
+
return signal?.aborted ? exitCodeForAbortSignal(signal) : null;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
function setMembership(set: Set<number>, value: number, present: boolean): void {
|
|
1710
|
+
if (present) set.add(value);
|
|
1711
|
+
else set.delete(value);
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
function isDecimalInteger(value: string): boolean {
|
|
1715
|
+
if (value.length === 0) return false;
|
|
1716
|
+
for (let i = 0; i < value.length; i++) {
|
|
1717
|
+
const code = value.charCodeAt(i);
|
|
1718
|
+
if (code < 48 || code > 57) return false;
|
|
1719
|
+
}
|
|
1720
|
+
return true;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
function isFatalSpecialBuiltin(name: string): boolean {
|
|
1724
|
+
switch (name) {
|
|
1725
|
+
case ':':
|
|
1726
|
+
case '.':
|
|
1727
|
+
case 'break':
|
|
1728
|
+
case 'continue':
|
|
1729
|
+
case 'eval':
|
|
1730
|
+
case 'exec':
|
|
1731
|
+
case 'exit':
|
|
1732
|
+
case 'export':
|
|
1733
|
+
case 'readonly':
|
|
1734
|
+
case 'return':
|
|
1735
|
+
case 'set':
|
|
1736
|
+
case 'shift':
|
|
1737
|
+
case 'times':
|
|
1738
|
+
case 'trap':
|
|
1739
|
+
case 'unset':
|
|
1740
|
+
return true;
|
|
1741
|
+
default:
|
|
1742
|
+
return false;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
function linkAbortSignal(parent: AbortSignal, child: AbortController): () => void {
|
|
1747
|
+
if (parent.aborted) {
|
|
1748
|
+
child.abort(parent.reason);
|
|
1749
|
+
return () => {};
|
|
1750
|
+
}
|
|
1751
|
+
const onAbort = () => child.abort(parent.reason);
|
|
1752
|
+
parent.addEventListener('abort', onAbort, { once: true });
|
|
1753
|
+
return () => parent.removeEventListener('abort', onAbort);
|
|
1754
|
+
}
|