@volter/tabnode 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/__sw__.js +259 -5
  2. package/dist/assets/{runtime-worker-DoV8lqBn.js → runtime-worker-B9buriZs.js} +4021 -2961
  3. package/dist/fetch-transport.d.ts +20 -0
  4. package/dist/guest-timers.d.ts +15 -0
  5. package/dist/http-client-transport.d.ts +19 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.mjs +5204 -3057
  8. package/dist/native-stream-binding.d.ts +57 -0
  9. package/dist/native-stream-owner.d.ts +121 -0
  10. package/dist/node-lib/binding/duplex_stream.d.ts +26 -0
  11. package/dist/node-lib/binding/fds.d.ts +8 -0
  12. package/dist/node-lib/binding/fs.d.ts +311 -78
  13. package/dist/node-lib/binding/misc.d.ts +1 -0
  14. package/dist/node-lib/binding/pipe_wrap.d.ts +4 -4
  15. package/dist/node-lib/binding/process_wrap.d.ts +13 -2
  16. package/dist/node-lib/binding/stream_wrap.d.ts +27 -18
  17. package/dist/node-lib/binding/tcp_wrap.d.ts +0 -1
  18. package/dist/node-lib/binding/tty_wrap.d.ts +43 -2
  19. package/dist/node-lib/binding/util.d.ts +83 -0
  20. package/dist/node-lib/binding/uv.d.ts +4 -0
  21. package/dist/node-lib/fs-module.d.ts +1 -0
  22. package/dist/node-lib/internals/buffer-and-streams.d.ts +30 -17
  23. package/dist/node-lib/internals/index.d.ts +1 -1
  24. package/dist/node-lib/load.d.ts +17 -3
  25. package/dist/node-lib/module-hooks.d.ts +1 -0
  26. package/dist/node-lib/public-modules.d.ts +1 -1
  27. package/dist/node-lib/timers.d.ts +38 -0
  28. package/dist/node-process-host.d.ts +41 -0
  29. package/dist/process-registry.d.ts +39 -0
  30. package/dist/process-tokens.d.ts +16 -0
  31. package/dist/promise-ownership.d.ts +3 -0
  32. package/dist/runtime.d.ts +10 -9
  33. package/dist/shims/child_process.d.ts +2 -0
  34. package/dist/shims/crypto.d.ts +660 -119
  35. package/dist/shims/dns.d.ts +76 -2
  36. package/dist/shims/process.d.ts +1 -0
  37. package/dist/shims/string_decoder.d.ts +19 -3
  38. package/dist/shims/tls.d.ts +853 -31
  39. package/dist/source-edits.d.ts +7 -0
  40. package/package.json +1 -1
  41. package/src/code-transforms.ts +2 -3
  42. package/src/fetch-transport.ts +98 -0
  43. package/src/guest-timers.ts +89 -0
  44. package/src/http-client-transport.ts +169 -0
  45. package/src/index.ts +12 -0
  46. package/src/native-stream-binding.ts +393 -0
  47. package/src/native-stream-owner.ts +317 -0
  48. package/src/node-lib/binding/duplex_stream.ts +95 -0
  49. package/src/node-lib/binding/fds.ts +18 -1
  50. package/src/node-lib/binding/fs.ts +45 -17
  51. package/src/node-lib/binding/misc.ts +2 -0
  52. package/src/node-lib/binding/pipe_wrap.ts +35 -12
  53. package/src/node-lib/binding/process_wrap.ts +72 -18
  54. package/src/node-lib/binding/stream_wrap.ts +196 -72
  55. package/src/node-lib/binding/tcp_wrap.ts +43 -8
  56. package/src/node-lib/binding/tty_wrap.ts +135 -8
  57. package/src/node-lib/binding/util.ts +24 -15
  58. package/src/node-lib/binding/uv.ts +4 -0
  59. package/src/node-lib/fs-module.ts +2 -18
  60. package/src/node-lib/internal/navigator.js +149 -0
  61. package/src/node-lib/internals/buffer-and-streams.ts +50 -11
  62. package/src/node-lib/internals/events-util.ts +5 -0
  63. package/src/node-lib/internals/index.ts +12 -2
  64. package/src/node-lib/load.ts +170 -62
  65. package/src/node-lib/module-hooks.ts +5 -2
  66. package/src/node-lib/public-modules.ts +12 -48
  67. package/src/node-lib/sources.ts +4 -0
  68. package/src/node-lib/timers.ts +93 -0
  69. package/src/node-process-host.ts +124 -0
  70. package/src/process-registry.ts +144 -0
  71. package/src/process-tokens.ts +60 -6
  72. package/src/promise-ownership.ts +28 -0
  73. package/src/runtime.ts +90 -214
  74. package/src/shims/child_process.ts +313 -80
  75. package/src/shims/crypto.ts +115 -100
  76. package/src/shims/dns.ts +17 -1
  77. package/src/shims/process.ts +33 -11
  78. package/src/shims/string_decoder.ts +10 -6
  79. package/src/shims/tls.ts +49 -19
  80. package/src/source-edits.ts +20 -0
@@ -21,7 +21,8 @@
21
21
  import { LibuvStreamWrap } from './stream_wrap';
22
22
  import { Pipe } from './pipe_wrap';
23
23
  import { type OwnedHandle } from './handles';
24
- import type { ProcessToken } from '../../process-tokens';
24
+ import { type ProcessToken } from '../../process-tokens';
25
+ import { type TerminalState } from './tty_wrap';
25
26
  /** One entry of Node's `options.stdio`, as `getValidStdio` builds it. */
26
27
  export interface StdioEntry {
27
28
  type: 'pipe' | 'overlapped' | 'ignore' | 'inherit' | 'fd' | 'wrap';
@@ -75,8 +76,17 @@ export interface RunRequest {
75
76
  stderrIsPipe: boolean;
76
77
  /** True when the child's fd 0 is a pipe whose writer has not closed. */
77
78
  stdinIsPipe: boolean;
79
+ terminal?: TerminalState;
78
80
  /** The IPC channel the child is started with, where it has one. */
79
81
  channel?: RunChannel;
82
+ /**
83
+ * The child's pipes past fd 2 (`stdio: [..., 'pipe', 'pipe']`), each at the
84
+ * number the child reads or writes it by, with the child's end of it.
85
+ */
86
+ descriptors: {
87
+ fd: number;
88
+ pipe: Pipe;
89
+ }[];
80
90
  /** Called once, when the run has ended. */
81
91
  exit(code: number, signal: string | null): void;
82
92
  }
@@ -89,7 +99,7 @@ export interface StartedRun {
89
99
  /** libuv's `uv_process_kill`: 0, or `UV_ESRCH` for a run already over. */
90
100
  kill(signal: string): number;
91
101
  /** Bytes the parent wrote to the child's fd 0. */
92
- writeStdin(bytes: Uint8Array): void;
102
+ writeStdin(bytes: Uint8Array): void | Promise<void>;
93
103
  /** The parent closed the child's fd 0. */
94
104
  endStdin(): void;
95
105
  }
@@ -126,6 +136,7 @@ export declare class Process implements OwnedHandle {
126
136
  private closed;
127
137
  /** The stdio entries this run was started with, and their far ends. */
128
138
  private stdio;
139
+ private terminalEnds;
129
140
  private readonly asyncId;
130
141
  constructor();
131
142
  getAsyncId(): number;
@@ -37,11 +37,10 @@ interface Inbound {
37
37
  * The base every `TCP` and `Pipe` extends, as `LibuvStreamWrap` is the base of
38
38
  * libuv's `uv_stream_t` wrappers.
39
39
  *
40
- * A pairing is two of these with `peer` pointing at each other. A write copies
41
- * its bytes and hands them to the peer on a microtask, because libuv never
42
- * delivers a read inside the write that caused it; the peer delivers them to
43
- * `onread` while it is reading and holds them while it is not, which is what
44
- * `readStart` and `readStop` mean.
40
+ * A pairing joins two connection endpoints. Duplicated wrappers reference the
41
+ * same endpoint and consume its bytes once. A write queues a copy at the peer;
42
+ * reads are delivered on its own turn while a wrapper is reading, which is
43
+ * what `readStart` and `readStop` mean.
45
44
  */
46
45
  export declare class LibuvStreamWrap implements OwnedHandle {
47
46
  /** Set by `net.js` to `onStreamRead`; the only way bytes reach a stream. */
@@ -54,8 +53,9 @@ export declare class LibuvStreamWrap implements OwnedHandle {
54
53
  writeQueueSize: number;
55
54
  /** The engine has no descriptors for a paired handle, as libuv reports -1 for one it has no fd for. */
56
55
  fd: number;
57
- /** The other end of the pairing, once there is one. */
58
- peer: LibuvStreamWrap | null;
56
+ private streamEndpoint;
57
+ /** A live wrapper on the other end, including after the original was closed. */
58
+ get peer(): LibuvStreamWrap | null;
59
59
  /** True once `close()` has been called; a closed handle carries nothing. */
60
60
  closed: boolean;
61
61
  /**
@@ -64,13 +64,14 @@ export declare class LibuvStreamWrap implements OwnedHandle {
64
64
  * thing in a pipe's pending-handle queue.
65
65
  */
66
66
  pendingHandle: unknown;
67
- protected inbound: Inbound[];
68
- protected inboundEof: boolean;
69
- protected inboundError: number | null;
67
+ protected get inbound(): Inbound[];
68
+ protected get inboundEof(): boolean;
69
+ protected get inboundError(): number | null;
70
70
  protected eofDelivered: boolean;
71
71
  protected userBuffer: Uint8Array | null;
72
72
  protected readonly asyncId: number;
73
73
  constructor();
74
+ protected attachNative(kind: 'tcp' | 'pipe', type: number): void;
74
75
  getAsyncId(): number;
75
76
  ref(): void;
76
77
  unref(): void;
@@ -84,18 +85,19 @@ export declare class LibuvStreamWrap implements OwnedHandle {
84
85
  * reads EOF. The request completes on its own turn, as libuv's does.
85
86
  */
86
87
  shutdown(req: ShutdownWrap): number;
87
- writeBuffer(req: WriteWrap, buffer: Uint8Array): number;
88
+ writeBuffer(req: WriteWrap, buffer: Uint8Array, handle?: unknown): number;
88
89
  writev(req: WriteWrap, chunks: unknown[], allBuffers: boolean): number;
89
90
  writeUtf8String(req: WriteWrap, text: string, handle?: unknown): number;
90
91
  writeAsciiString(req: WriteWrap, text: string): number;
91
92
  writeLatin1String(req: WriteWrap, text: string): number;
92
93
  writeUcs2String(req: WriteWrap, text: string): number;
93
94
  /**
94
- * libuv's `uv_close`. The peer reads EOF, as it does when the other end of a
95
- * socket goes; the callback runs on its own turn, because `net.js` emits
95
+ * libuv's `uv_close`. The peer reads EOF when the last descriptor closes;
96
+ * the callback runs on its own turn, because `net.js` emits
96
97
  * `close` from it and Node emits that after the turn that destroyed.
97
98
  */
98
99
  close(callback?: () => void): void;
100
+ private closeLocal;
99
101
  /** What a `TCP` or a `Pipe` gives up beyond the stream: a port, a path. */
100
102
  protected onCloseHandle(): void;
101
103
  /**
@@ -108,14 +110,22 @@ export declare class LibuvStreamWrap implements OwnedHandle {
108
110
  * for both, that close ended the connection the child had just been given
109
111
  * and its first write was `EBADF`.
110
112
  *
111
- * The duplicate takes over this end of the pairing and this end is left
112
- * peerless, so closing it announces nothing -- the sender has already given
113
- * the socket up (`handleConversion`'s `send` sets `socket._handle = null`
114
- * and silences its reads before the write).
113
+ * Both descriptors share the connection and its unread bytes. Node may
114
+ * close the sender on acknowledgement or keep it open; the binding must
115
+ * support either, without knowing the child_process option that chose it.
115
116
  */
116
117
  duplicate(): LibuvStreamWrap;
117
118
  /** Two handles become each other's peer; what one writes the other reads. */
118
119
  static pair(a: LibuvStreamWrap, b: LibuvStreamWrap): void;
120
+ /** A fresh wrapper acquires a descriptor reference on this connection. */
121
+ protected shareConnectionFrom(other: LibuvStreamWrap): void;
122
+ /** Native connection resources outlive individual duplicated wrappers. */
123
+ protected onLastReferenceClose(callback: () => void): void;
124
+ /** Host transports bound copies waiting in the native receiving queue. */
125
+ get peerQueuedBytes(): number;
126
+ get peerQueuedHandles(): number;
127
+ /** Changes to the same connection end, even after its wrapper is replaced. */
128
+ onPeerReadCapacity(listener: () => void): () => void;
119
129
  /**
120
130
  * Take over another handle's end of a pairing, with everything that arrived
121
131
  * on it while nobody was holding it. This is what opening a descriptor is
@@ -167,7 +177,6 @@ export declare class LibuvStreamWrap implements OwnedHandle {
167
177
  * libuv's loop reads in: everything a writer did in one turn is read in the
168
178
  * order it did it, and never from inside the call that did it.
169
179
  */
170
- private flushScheduled;
171
180
  protected scheduleFlush(): void;
172
181
  /**
173
182
  * Hand what has arrived to `onStreamRead`, in libuv's shape: the byte count
@@ -53,7 +53,6 @@ export declare class TCP extends LibuvStreamWrap {
53
53
  onconnection: ((status: number, clientHandle: TCP) => void) | null;
54
54
  private local;
55
55
  private remote;
56
- private ephemeral;
57
56
  constructor(type?: number);
58
57
  bind(address: string, port: number, _flags?: number): number;
59
58
  bind6(address: string, port: number, _flags?: number): number;
@@ -9,10 +9,34 @@
9
9
  * when the running program's own `process.stdout.isTTY` says so -- which is
10
10
  * what a held run gets, and what a program reads to decide on colour.
11
11
  */
12
- import { LibuvStreamWrap } from './stream_wrap';
12
+ import { LibuvStreamWrap, type WriteWrap } from './stream_wrap';
13
+ export interface TerminalState {
14
+ columns: number;
15
+ rows: number;
16
+ onResize(listener: (columns: number, rows: number) => void): () => void;
17
+ resize(columns: number, rows: number): void;
18
+ }
19
+ /** One terminal endpoint, shared by independently owned descriptors. */
20
+ declare class TerminalEndpoint {
21
+ readonly terminal: TerminalState;
22
+ readonly slave: boolean;
23
+ readonly descriptors: Set<TTY>;
24
+ readonly readers: Set<TTY>;
25
+ readonly input: Uint8Array[];
26
+ peer?: TerminalEndpoint;
27
+ eof: boolean;
28
+ scheduled: boolean;
29
+ constructor(terminal: TerminalState, slave: boolean);
30
+ pump(): void;
31
+ release(descriptor: TTY): void;
32
+ }
13
33
  /** libuv's `uv_tty_t`, over the same stream the rest of the binding is. */
14
34
  export declare class TTY extends LibuvStreamWrap {
15
- readonly fdNumber: number;
35
+ get fdNumber(): number;
36
+ readonly descriptor: TTY;
37
+ private endpoint?;
38
+ get terminal(): TerminalState | undefined;
39
+ get slave(): boolean;
16
40
  /**
17
41
  * Node's `new TTY(fd, ctx)` writes an errno onto `ctx` when the fd is not
18
42
  * a terminal, so `tty.WriteStream` refuses to wrap a pipe. A run's stdout
@@ -25,11 +49,28 @@ export declare class TTY extends LibuvStreamWrap {
25
49
  /** A terminal the engine does not own has one size and no mode to set. */
26
50
  getWindowSize(out: number[]): number;
27
51
  setRawMode(_raw: number): number;
52
+ static allocate(endpoint: TerminalEndpoint): TTY;
53
+ /** Inheritance duplicates the fd; neither process owns the other's ref. */
54
+ duplicate(): TTY;
55
+ readStart(): number;
56
+ /** Delivered into Node's existing stream binding, preserving backpressure. */
57
+ deliver(bytes: Uint8Array): void;
58
+ protected dispatchWrite(req: WriteWrap, bytes: Uint8Array): number;
59
+ protected onCloseHandle(): void;
28
60
  }
61
+ /** Host OS adapter door. The process host retains terminal behavior. */
62
+ export declare function openPty(columns: number, rows: number): {
63
+ master: number;
64
+ slave: number;
65
+ pty: string;
66
+ };
67
+ export declare function resizePty(fd: number, columns: number, rows: number): void;
29
68
  /** libuv's `uv_guess_handle(fd) === UV_TTY`, as the running program sees it. */
30
69
  export declare function isTTY(fd: number): boolean;
31
70
  declare const _default: {
32
71
  TTY: typeof TTY;
33
72
  isTTY: typeof isTTY;
73
+ openPty: typeof openPty;
74
+ resizePty: typeof resizePty;
34
75
  };
35
76
  export default _default;
@@ -123,3 +123,86 @@ export declare const utilBinding: {
123
123
  sleep: (milliseconds: number) => void;
124
124
  };
125
125
  export default utilBinding;
126
+ /** Lazy builtin exports must resolve inside the requesting process. */
127
+ export declare function createUtilBinding(require: (name: string) => unknown): {
128
+ defineLazyProperties: (target: object, id: string, keys: string[], writable?: boolean) => void;
129
+ privateSymbols: {
130
+ arrow_message_private_symbol: symbol;
131
+ decorated_private_symbol: symbol;
132
+ untransferable_object_private_symbol: symbol;
133
+ host_defined_option_symbol: symbol;
134
+ transfer_mode_private_symbol: symbol;
135
+ };
136
+ constants: {
137
+ ALL_PROPERTIES: number;
138
+ ONLY_WRITABLE: number;
139
+ ONLY_ENUMERABLE: number;
140
+ ONLY_CONFIGURABLE: number;
141
+ SKIP_STRINGS: number;
142
+ SKIP_SYMBOLS: number;
143
+ kPending: number;
144
+ kFulfilled: number;
145
+ kRejected: number;
146
+ };
147
+ /** Node warns differently for a deprecation raised inside a dependency; nothing here is. */
148
+ isInsideNodeModules: () => boolean;
149
+ /**
150
+ * An object's own properties that are not array indices, filtered the way
151
+ * V8's `GetOwnNonIndexProperties` filters: `ONLY_ENUMERABLE` keeps the
152
+ * enumerable ones, `SKIP_SYMBOLS` and `SKIP_STRINGS` drop a kind outright.
153
+ * `inspect` asks for this to list an array's non-index keys and a typed
154
+ * array's own properties without walking its elements.
155
+ */
156
+ getOwnNonIndexProperties: (target: object, filter?: number) => Array<string | symbol>;
157
+ /** The promise loss named at the top of this file. */
158
+ getPromiseDetails: () => [number];
159
+ /** The proxy loss named at the top of this file. */
160
+ getProxyDetails: () => undefined;
161
+ /**
162
+ * The entries inside a `Map` or a `Set`, which `inspect` prints. V8 reads
163
+ * them out of the object's own storage; this reads them the way any program
164
+ * does, which answers for a real map or set. An ITERATOR over one keeps its
165
+ * position in V8's own state and cannot be previewed without consuming it,
166
+ * so an iterator previews as empty rather than being spent -- a printed
167
+ * value is not worth destroying the thing printed.
168
+ */
169
+ previewEntries: (value: unknown, isIterator?: boolean) => [unknown[], boolean];
170
+ /**
171
+ * The name of the constructor that made a value, as V8 reports it: the
172
+ * first prototype in the chain with an own `constructor` whose name is not
173
+ * empty. `inspect` prints it before an object's braces.
174
+ */
175
+ getConstructorName: (value: object) => string;
176
+ /** A pointer's value, printed for an external. A tab has no externals. */
177
+ getExternalValue: () => bigint;
178
+ /** What kind of thing a descriptor is, out of the engine's own table. */
179
+ guessHandleType: typeof guessHandleTypeOfFd;
180
+ /**
181
+ * The stack, as `util.getCallSites()` reports it: one entry per frame with
182
+ * the function's name, the script it is in, and where in that script. V8's
183
+ * own structured-stack door is what Node reads too -- `Error
184
+ * .prepareStackTrace` handed an array of call sites -- so this asks the
185
+ * realm the same question and shapes the answer the same way. The harness
186
+ * of Node's own tests calls it on every `mustNotCall`, which is why a
187
+ * missing one showed up as thirty test files at once.
188
+ */
189
+ getCallSites: (frameCount?: number) => Array<Record<string, unknown>>;
190
+ /**
191
+ * A `.env` file's contents as an object, which `util.parseEnv` returns and
192
+ * which `--env-file` loads a process's environment from. Node parses it in
193
+ * C++; the rules are the ones its own fixture states, and they are the
194
+ * whole of the format: a `KEY=VALUE` per line, `export ` allowed in front
195
+ * of the key and dropped, a `#` starting a comment outside quotes wherever
196
+ * it stands -- `a#b` is `a`, no space needed -- and a
197
+ * value that may be wrapped in single quotes, double quotes or backticks --
198
+ * a quoted value keeps its spaces and may run over several lines, and only
199
+ * a double-quoted one expands `\n` and `\r`.
200
+ */
201
+ parseEnv: (content: string) => Record<string, string>;
202
+ /**
203
+ * A blocking sleep. A tab has one thread and nothing else can run while
204
+ * this spins, which is exactly what a blocking sleep is; only a program
205
+ * that asked for one gets it.
206
+ */
207
+ sleep: (milliseconds: number) => void;
208
+ };
@@ -23,9 +23,13 @@ export declare const UV_ENOTCONN: number;
23
23
  export declare const UV_ECANCELED: number;
24
24
  export declare const UV_ENOTSUP: number;
25
25
  export declare const UV_EBADF: number;
26
+ export declare const UV_EIO: number;
26
27
  export declare const UV_ENOSYS: number;
27
28
  export declare const UV_EADDRNOTAVAIL: number;
28
29
  export declare const UV_EACCES: number;
29
30
  export declare const UV_ENOBUFS: number;
31
+ export declare const UV_EMFILE: number;
32
+ export declare const UV_EBUSY: number;
33
+ export declare const UV_EALREADY: number;
30
34
  export declare const UV_ESRCH: number;
31
35
  export default uvBinding;
@@ -1,4 +1,5 @@
1
1
  export declare const fsModule: Record<string, unknown>;
2
2
  export declare const fsPromisesModule: Record<string, unknown>;
3
+ /** Every guest, including the first, owns its builtin graph. */
3
4
  export declare function fsModuleFor(process: object): unknown;
4
5
  export default fsModule;
@@ -72,24 +72,37 @@ export declare const internalFile: {
72
72
  * not guessed at.
73
73
  */
74
74
  type AnyStream = Record<string, (...args: never[]) => unknown> & Record<string, unknown>;
75
- declare function newReadableStreamFromStreamReadable(readable: AnyStream): ReadableStream;
76
- declare function newStreamReadableFromReadableStream(web: ReadableStream): AnyStream;
77
- declare function newWritableStreamFromStreamWritable(writable: AnyStream): WritableStream;
78
- declare function newStreamWritableFromWritableStream(web: WritableStream): AnyStream;
79
- declare function newReadableWritablePairFromDuplex(duplex: AnyStream): {
80
- readable: ReadableStream;
81
- writable: WritableStream;
75
+ /** Capture the owning graph; callbacks must not fall back to the host loader. */
76
+ export declare function createWebStreamsAdapters(require?: (name: string) => unknown): {
77
+ newReadableStreamFromStreamReadable: (readable: AnyStream, options?: {
78
+ strategy?: QueuingStrategy;
79
+ }) => ReadableStream;
80
+ newStreamReadableFromReadableStream: (web: ReadableStream) => AnyStream;
81
+ newWritableStreamFromStreamWritable: (writable: AnyStream) => WritableStream;
82
+ newStreamWritableFromWritableStream: (web: WritableStream) => AnyStream;
83
+ newReadableWritablePairFromDuplex: (duplex: AnyStream) => {
84
+ readable: ReadableStream;
85
+ writable: WritableStream;
86
+ };
87
+ newStreamDuplexFromReadableWritablePair: (pair: {
88
+ readable: ReadableStream;
89
+ writable: WritableStream;
90
+ }) => AnyStream;
82
91
  };
83
- declare function newStreamDuplexFromReadableWritablePair(pair: {
84
- readable: ReadableStream;
85
- writable: WritableStream;
86
- }): AnyStream;
87
92
  export declare const internalWebStreamsAdapters: {
88
- newReadableStreamFromStreamReadable: typeof newReadableStreamFromStreamReadable;
89
- newStreamReadableFromReadableStream: typeof newStreamReadableFromReadableStream;
90
- newWritableStreamFromStreamWritable: typeof newWritableStreamFromStreamWritable;
91
- newStreamWritableFromWritableStream: typeof newStreamWritableFromWritableStream;
92
- newReadableWritablePairFromDuplex: typeof newReadableWritablePairFromDuplex;
93
- newStreamDuplexFromReadableWritablePair: typeof newStreamDuplexFromReadableWritablePair;
93
+ newReadableStreamFromStreamReadable: (readable: AnyStream, options?: {
94
+ strategy?: QueuingStrategy;
95
+ }) => ReadableStream;
96
+ newStreamReadableFromReadableStream: (web: ReadableStream) => AnyStream;
97
+ newWritableStreamFromStreamWritable: (writable: AnyStream) => WritableStream;
98
+ newStreamWritableFromWritableStream: (web: WritableStream) => AnyStream;
99
+ newReadableWritablePairFromDuplex: (duplex: AnyStream) => {
100
+ readable: ReadableStream;
101
+ writable: WritableStream;
102
+ };
103
+ newStreamDuplexFromReadableWritablePair: (pair: {
104
+ readable: ReadableStream;
105
+ writable: WritableStream;
106
+ }) => AnyStream;
94
107
  };
95
108
  export {};
@@ -1 +1 @@
1
- export declare function nodeLibInternal(name: string): (() => unknown) | undefined;
1
+ export declare function nodeLibInternal(name: string, require?: (name: string) => any, process?: any): (() => unknown) | undefined;
@@ -7,11 +7,24 @@ export declare function nodeLibProcessOf(): Record<string, unknown>;
7
7
  * partly-filled `exports` rather than looping.
8
8
  */
9
9
  export declare function loadNodeLib(name: string): unknown;
10
- export declare function esmNamespaceOf(mod: unknown): Record<string, unknown>;
10
+ export declare function esmNamespaceOf(mod: unknown, owner?: object): Record<string, unknown>;
11
11
  /** Node's `module.syncBuiltinESMExports`: newly assigned CJS keys appear on the namespace. */
12
- export declare function syncBuiltinESMExports(): void;
12
+ export declare function syncBuiltinESMExports(owner?: object): void;
13
13
  export declare function loadNodeLibInstance(name: string): unknown;
14
- export declare function loadNodeLibFor(owner: object, name: string): unknown;
14
+ /**
15
+ * Each guest owns one recursively resolved builtin graph. The default loader
16
+ * is private to the engine; guest monkey patches never reach it or siblings.
17
+ * Native bindings retain the shared OS registries beneath those graphs.
18
+ */
19
+ export type NodeLibRequire = (name: string) => any;
20
+ type ModuleInitializer = (name: string, value: any, require: NodeLibRequire) => void;
21
+ /** Host bootstrap adapters are applied to each newly compiled builtin. */
22
+ export declare function onNodeLibLoaded(initialize: ModuleInitializer): () => void;
23
+ /** Native implementations can be shared; their exported module records cannot. */
24
+ export declare function moduleSurface(value: any, seen?: Map<object, any>): any;
25
+ export declare function loadNodeLibFor(owner: object, name: string): any;
26
+ export declare function hasNodeLibModule(name: string): boolean;
27
+ export declare function nativeModuleFor(owner: object, name: string, create: () => unknown): unknown;
15
28
  /**
16
29
  * What a hand-bound internal, a binding or `./lazy.ts` calls to reach a
17
30
  * vendored file.
@@ -24,3 +37,4 @@ export declare function loadNodeLibFor(owner: object, name: string): unknown;
24
37
  * in its temporal dead zone and the engine failed to load at all.
25
38
  */
26
39
  export declare function nodeLibInternalRequire(specifier: string): unknown;
40
+ export {};
@@ -47,6 +47,7 @@ export declare class RunModuleHooks {
47
47
  #private;
48
48
  /** The vendored file's own instance, this run's alone. */
49
49
  readonly sync: CustomizationHooks;
50
+ constructor(process: object);
50
51
  /**
51
52
  * Which chain has anything in it. The loader asks before it builds
52
53
  * anything: a run that registered no hook pays for none, which is the fast
@@ -1 +1 @@
1
- export declare function nodeLibPublic(name: string): (() => unknown) | undefined;
1
+ export declare function nodeLibPublic(name: string, require?: (name: string) => any, _process?: object): (() => unknown) | undefined;
@@ -16,3 +16,41 @@
16
16
  export declare function nodeTimeout(id: unknown): unknown;
17
17
  /** The realm's own id inside a {@link nodeTimeout}, for the clear that takes one. */
18
18
  export declare function timerHandleOf(id: unknown): unknown;
19
+ /** Native timers surface shared by both builtin loaders, fresh for each graph. */
20
+ export declare function createTimersModule(owned?: {
21
+ setTimeout(fn: (...args: unknown[]) => void, ms?: number, ...args: unknown[]): unknown;
22
+ clearTimeout(id: unknown): void;
23
+ setInterval(fn: (...args: unknown[]) => void, ms?: number, ...args: unknown[]): unknown;
24
+ clearInterval(id: unknown): void;
25
+ }): {
26
+ active: (item: {
27
+ _onTimeout?: () => void;
28
+ _idleTimeout?: number;
29
+ _idleTimeoutId?: unknown;
30
+ }) => void;
31
+ enroll: (item: {
32
+ _onTimeout?: () => void;
33
+ _idleTimeout?: number;
34
+ _idleTimeoutId?: unknown;
35
+ }, msecs: number) => void;
36
+ unenroll: (item: {
37
+ _onTimeout?: () => void;
38
+ _idleTimeout?: number;
39
+ _idleTimeoutId?: unknown;
40
+ }) => void;
41
+ promises: {
42
+ setTimeout: (delay: any, value: any, options: any) => Promise<unknown>;
43
+ setImmediate: (value: any, options: any) => Promise<unknown>;
44
+ setInterval: (delay: any, value: any, options: any) => AsyncGenerator<any, void, unknown>;
45
+ scheduler: {
46
+ wait: (delay: any, options: any) => Promise<unknown>;
47
+ yield: () => Promise<unknown>;
48
+ };
49
+ };
50
+ setImmediate: (fn: (...a: unknown[]) => void, ...args: unknown[]) => unknown;
51
+ clearImmediate: (id: unknown) => void;
52
+ setTimeout: (fn: (...args: unknown[]) => void, ms?: number, ...args: unknown[]) => unknown;
53
+ clearTimeout: (id: unknown) => void;
54
+ setInterval: (fn: (...a: unknown[]) => void, ms?: number, ...rest: unknown[]) => unknown;
55
+ clearInterval: (id: unknown) => void;
56
+ };
@@ -0,0 +1,41 @@
1
+ import type { ProcessIdentity } from './process-registry';
2
+ import type { NativeStreamDescriptor } from './native-stream-owner';
3
+ import type { RunStreams } from './shims/child_process';
4
+ import type { VirtualFS } from './virtual-fs';
5
+ /** Trusted launch data, before Node options or the script execute in a realm. */
6
+ export interface NodeProcessLaunch {
7
+ token: string;
8
+ identity: ProcessIdentity;
9
+ /** Arguments after the Node executable, preserving each parsed word. */
10
+ argv: readonly string[];
11
+ cwd: string;
12
+ /** This entry's filesystem view, including any host-prepared entry wrapper. */
13
+ filesystem: VirtualFS;
14
+ env: Record<string, string>;
15
+ stdin?: string;
16
+ stdinStream?: AsyncIterable<Uint8Array>;
17
+ streams?: RunStreams;
18
+ inherited: readonly {
19
+ fd: number;
20
+ handle: NativeStreamDescriptor;
21
+ }[];
22
+ }
23
+ export interface NodeProcessHost {
24
+ run(launch: NodeProcessLaunch): Promise<{
25
+ stdout: string;
26
+ stderr: string;
27
+ exitCode: number;
28
+ }>;
29
+ }
30
+ export declare function nodeProcessHostInstalled(): boolean;
31
+ /** Only a worker with one admitted local entry has an unambiguous realm owner. */
32
+ export declare function nodeProcessRealmToken(): string | null;
33
+ /** Adapt the engine's push sink to the worker bridge's pull-based input. */
34
+ export declare function nodeProcessInput(streams: RunStreams | undefined): {
35
+ stream?: AsyncIterable<Uint8Array>;
36
+ dispose(): void;
37
+ };
38
+ /** Host bootstrap only. A process worker admits exactly one local Node entry. */
39
+ export declare function installNodeProcessHost(next: NodeProcessHost, token?: string): void;
40
+ /** Called by the common Node command entry, including engine-first forks. */
41
+ export declare function nodeProcessHostFor(token: string | null): NodeProcessHost | undefined;
@@ -0,0 +1,39 @@
1
+ /** Native process identity shared by the container's worker realms. */
2
+ export interface ProcessIdentity {
3
+ readonly pid: number;
4
+ readonly ppid: number;
5
+ }
6
+ /** A run already admitted by the container owner into this realm's scope. */
7
+ export interface InitialProcessRegistration {
8
+ readonly token: string;
9
+ readonly identity: ProcessIdentity;
10
+ }
11
+ /** Installed by the trusted embedding host before this realm starts runs. */
12
+ export interface ProcessRegistry {
13
+ allocate(): number;
14
+ publish(token: string, identity: ProcessIdentity): void;
15
+ forget(token: string): void;
16
+ lookup(pid: number): ProcessIdentity | undefined;
17
+ /**
18
+ * `kill(pid, signal)` for a live process of another realm in this container:
19
+ * whether a process there took the signal. A machine lets a process signal
20
+ * any process of its user, including one its parent left behind.
21
+ */
22
+ signal(pid: number, signal: string): boolean;
23
+ }
24
+ export interface ProcessRegistryScope extends ProcessRegistry {
25
+ /** Trusted owner only: how this realm answers a signal sent to one of its processes. */
26
+ receiveSignals(handler: (pid: number, signal: string) => boolean): void;
27
+ /** Trusted owner handoff before the destination worker starts; not a guest operation. */
28
+ adoptRun(source: ProcessRegistryScope, sourceToken: string, token: string, parentPid?: number): ProcessIdentity;
29
+ /** Ends this realm's registrations, including after abrupt worker death. */
30
+ dispose(): void;
31
+ }
32
+ /**
33
+ * One container owns the counter and live table. Each realm receives a scope,
34
+ * so identical local run tokens cannot overwrite or release another realm's
35
+ * process. Allocation alone does not announce a live process.
36
+ */
37
+ export declare function createProcessRegistryOwner(): {
38
+ createScope(): ProcessRegistryScope;
39
+ };
@@ -14,12 +14,18 @@
14
14
  * for both. The guest never sees the variable: the environment the `node`
15
15
  * command gives its process has it removed.
16
16
  */
17
+ import type { Process } from './shims/process';
18
+ import { type ProcessRegistry, type ProcessRegistryScope, type InitialProcessRegistration } from './process-registry';
17
19
  /** Whatever the embedding runtime uses to name one guest process. */
18
20
  export type ProcessToken = string;
19
21
  /** The environment variable a run's name travels in, from `exec` to `node`. */
20
22
  export declare const PROCESS_TOKEN_ENV = "__TABNODE_PROCESS_TOKEN";
21
23
  /** What the engine can answer about one named run. */
22
24
  export interface OwnedRun {
25
+ /** The guest whose cwd and inherited streams belong to this run. */
26
+ process: Process;
27
+ stdout(text: string): void;
28
+ stderr(text: string): void;
23
29
  /** The timers the run's guest still holds, as Node's loop counts them. */
24
30
  pendingTimers(): number;
25
31
  /** Clear those timers, as ending the process clears them. */
@@ -38,6 +44,8 @@ export declare function enterRun<T>(token: ProcessToken, fn: () => T): T;
38
44
  * releasing twice is harmless, as a run ends once.
39
45
  */
40
46
  export declare function __recordRun(token: ProcessToken, run: OwnedRun): () => void;
47
+ /** Bound guest globals retain their actual process across native await turns. */
48
+ export declare function __tokenForProcess(process: Process): ProcessToken | null;
41
49
  /** The run recorded under this name, while it lasts. */
42
50
  export declare function __runFor(token: ProcessToken): OwnedRun | undefined;
43
51
  /**
@@ -56,6 +64,12 @@ export declare function __currentProcessToken(): ProcessToken | null;
56
64
  * half, `__releaseOwnedServers`, which calls this for the timers.
57
65
  */
58
66
  export declare function __stopOwnedProcess(token: ProcessToken): void;
67
+ /** Each child realm gets its own registration authority in this container. */
68
+ export declare function createProcessRegistryScope(): ProcessRegistryScope;
69
+ /** Trusted container owner only; worker clients cannot expose their authority. */
70
+ export declare function ownerProcessRegistryScope(): ProcessRegistryScope;
71
+ /** Startup-only host seam; never swap identity authorities under live runs. */
72
+ export declare function installProcessRegistry(registry: ProcessRegistry, initial?: InitialProcessRegistration): void;
59
73
  /** The next process number this engine hands out. */
60
74
  export declare function mintPid(): number;
61
75
  /** Record the numbers a named run was started with, for the run to read back. */
@@ -69,6 +83,8 @@ export declare function runPid(token: ProcessToken | null | undefined): {
69
83
  export declare function forgetRunPid(token: ProcessToken): void;
70
84
  /** Whether a live run carries this number, which is what `kill(pid, 0)` asks. */
71
85
  export declare function pidIsLive(pid: number): boolean;
86
+ /** `kill(pid, signal)` to another realm's live process; whether one took it. */
87
+ export declare function signalPid(pid: number, signal: string): boolean;
72
88
  /** The numbers a live process carries, looked up by its own pid. */
73
89
  export declare function processByPid(pid: number): {
74
90
  pid: number;
@@ -0,0 +1,3 @@
1
+ export declare const intrinsicPromise: PromiseConstructor;
2
+ export declare function promiseOwner(promise: unknown): object | undefined;
3
+ export declare function guestPromise(owner: object): PromiseConstructor;
package/dist/runtime.d.ts CHANGED
@@ -7,15 +7,7 @@
7
7
  import { VirtualFS } from './virtual-fs';
8
8
  import type { IExecuteResult } from './runtime-interface';
9
9
  import { Process } from './shims/process';
10
- export declare function pendingGuestTimers(process: Process): number;
11
- /**
12
- * Clear every timer a guest still holds, as ending a Node process clears the
13
- * ones its loop was waiting on. The ids were made by the host's own
14
- * `setTimeout`/`setInterval` through the guest's global view, so the host's
15
- * own clears end them; a `Timeout` is cleared by either in Node, and either
16
- * refusing an id of the other kind is not an error here.
17
- */
18
- export declare function stopGuestTimers(process: Process): void;
10
+ export { pendingGuestTimers, stopGuestTimers } from './guest-timers';
19
11
  export declare function __substratePendingOf(value: unknown): Promise<void> | undefined;
20
12
  export interface Module {
21
13
  id: string;
@@ -69,6 +61,15 @@ export declare class Runtime {
69
61
  exports: unknown;
70
62
  module: Module;
71
63
  };
64
+ /**
65
+ * Runs source that is not a file of the tree -- `node -e`'s, named
66
+ * `[eval]` in the directory it runs in, as Node names it -- the way
67
+ * `execute` runs a file's, without writing it anywhere.
68
+ */
69
+ evaluate(code: string, filename: string): {
70
+ exports: unknown;
71
+ module: Module;
72
+ };
72
73
  /**
73
74
  * Execute code as a module (async version for IRuntime interface)
74
75
  * Alias: executeSync() is the same as execute() for backward compatibility