@volter/tabnode 0.4.1 → 0.5.1
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/__sw__.js +259 -5
- package/dist/assets/{runtime-worker-LWfW6VWE.js → runtime-worker-DBZ2flHK.js} +4000 -2944
- package/dist/fetch-transport.d.ts +20 -0
- package/dist/guest-timers.d.ts +15 -0
- package/dist/http-client-transport.d.ts +19 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.mjs +5196 -3062
- package/dist/native-stream-binding.d.ts +57 -0
- package/dist/native-stream-owner.d.ts +121 -0
- package/dist/node-lib/binding/duplex_stream.d.ts +26 -0
- package/dist/node-lib/binding/fds.d.ts +8 -0
- package/dist/node-lib/binding/fs.d.ts +311 -78
- package/dist/node-lib/binding/misc.d.ts +1 -0
- package/dist/node-lib/binding/pipe_wrap.d.ts +4 -4
- package/dist/node-lib/binding/process_wrap.d.ts +12 -1
- package/dist/node-lib/binding/stream_wrap.d.ts +27 -18
- package/dist/node-lib/binding/tcp_wrap.d.ts +0 -1
- package/dist/node-lib/binding/tty_wrap.d.ts +43 -2
- package/dist/node-lib/binding/util.d.ts +83 -0
- package/dist/node-lib/binding/uv.d.ts +4 -0
- package/dist/node-lib/fs-module.d.ts +1 -0
- package/dist/node-lib/internals/buffer-and-streams.d.ts +30 -17
- package/dist/node-lib/internals/index.d.ts +1 -1
- package/dist/node-lib/load.d.ts +17 -3
- package/dist/node-lib/module-hooks.d.ts +1 -0
- package/dist/node-lib/public-modules.d.ts +1 -1
- package/dist/node-lib/timers.d.ts +38 -0
- package/dist/node-process-host.d.ts +41 -0
- package/dist/process-registry.d.ts +39 -0
- package/dist/process-tokens.d.ts +11 -0
- package/dist/promise-ownership.d.ts +3 -0
- package/dist/runtime.d.ts +10 -9
- package/dist/shims/child_process.d.ts +2 -0
- package/dist/shims/crypto.d.ts +660 -119
- package/dist/shims/dns.d.ts +76 -2
- package/dist/shims/process.d.ts +1 -0
- package/dist/shims/string_decoder.d.ts +19 -3
- package/dist/shims/tls.d.ts +853 -31
- package/dist/source-edits.d.ts +7 -0
- package/package.json +1 -1
- package/src/code-transforms.ts +2 -3
- package/src/fetch-transport.ts +98 -0
- package/src/guest-timers.ts +89 -0
- package/src/http-client-transport.ts +169 -0
- package/src/index.ts +18 -0
- package/src/native-stream-binding.ts +393 -0
- package/src/native-stream-owner.ts +317 -0
- package/src/node-lib/binding/duplex_stream.ts +95 -0
- package/src/node-lib/binding/fds.ts +18 -1
- package/src/node-lib/binding/fs.ts +45 -17
- package/src/node-lib/binding/misc.ts +2 -0
- package/src/node-lib/binding/pipe_wrap.ts +35 -12
- package/src/node-lib/binding/process_wrap.ts +50 -9
- package/src/node-lib/binding/stream_wrap.ts +196 -72
- package/src/node-lib/binding/tcp_wrap.ts +43 -8
- package/src/node-lib/binding/tty_wrap.ts +135 -8
- package/src/node-lib/binding/util.ts +24 -15
- package/src/node-lib/binding/uv.ts +4 -0
- package/src/node-lib/fs-module.ts +2 -18
- package/src/node-lib/internal/navigator.js +149 -0
- package/src/node-lib/internals/buffer-and-streams.ts +50 -11
- package/src/node-lib/internals/events-util.ts +5 -0
- package/src/node-lib/internals/index.ts +12 -2
- package/src/node-lib/load.ts +170 -62
- package/src/node-lib/module-hooks.ts +5 -2
- package/src/node-lib/public-modules.ts +12 -48
- package/src/node-lib/sources.ts +4 -0
- package/src/node-lib/timers.ts +93 -0
- package/src/node-process-host.ts +124 -0
- package/src/process-registry.ts +144 -0
- package/src/process-tokens.ts +55 -6
- package/src/promise-ownership.ts +28 -0
- package/src/runtime.ts +90 -214
- package/src/shims/child_process.ts +310 -80
- package/src/shims/crypto.ts +115 -100
- package/src/shims/dns.ts +17 -1
- package/src/shims/process.ts +33 -11
- package/src/shims/string_decoder.ts +10 -6
- package/src/shims/tls.ts +49 -19
- package/src/source-edits.ts +20 -0
|
@@ -15,6 +15,7 @@ import { LibuvStreamWrap, type WriteWrap } from './stream_wrap';
|
|
|
15
15
|
import { UV_EADDRINUSE, UV_ENOENT, UV_EBADF } from './uv';
|
|
16
16
|
import { handleForFd, registerFd, releaseFd } from './fds';
|
|
17
17
|
import { __adoptHandle, ownerOf } from './handles';
|
|
18
|
+
import { nativeStreamFor, registerNativeStreamConstructor } from '../../native-stream-binding';
|
|
18
19
|
|
|
19
20
|
/** libuv's `uv_pipe_t` flavours, and the two chmod bits `listen` reads. */
|
|
20
21
|
export const constants = {
|
|
@@ -51,9 +52,12 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
51
52
|
constructor(type: number = constants.SOCKET) {
|
|
52
53
|
super();
|
|
53
54
|
this.type = type;
|
|
55
|
+
this.attachNative('pipe', type);
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
bind(path: string): number {
|
|
59
|
+
const native = nativeStreamFor(this);
|
|
60
|
+
if (native) return native.call({ operation: 'bind', id: native.descriptor.id, address: path }).status;
|
|
57
61
|
const held = boundPaths.get(path);
|
|
58
62
|
if (held && held !== this) return UV_EADDRINUSE;
|
|
59
63
|
this.path = path;
|
|
@@ -62,12 +66,20 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
listen(_backlog: number): number {
|
|
69
|
+
const native = nativeStreamFor(this);
|
|
70
|
+
if (native) {
|
|
71
|
+
const status = native.call({ operation: 'listen', id: native.descriptor.id, backlog: _backlog }).status;
|
|
72
|
+
if (status === 0) this.listening = true;
|
|
73
|
+
return status;
|
|
74
|
+
}
|
|
65
75
|
if (this.path === null) return UV_EBADF;
|
|
66
76
|
this.listening = true;
|
|
67
77
|
return 0;
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
connect(req: PipeConnectWrap, path: string): number {
|
|
81
|
+
const native = nativeStreamFor(this);
|
|
82
|
+
if (native) return native.connect(path, undefined, false, status => req.oncomplete?.(status, this, req, true, true));
|
|
71
83
|
// libuv answers a connect through the request, never from the call.
|
|
72
84
|
queueMicrotask(() => {
|
|
73
85
|
if (this.closed) return;
|
|
@@ -76,7 +88,7 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
76
88
|
req.oncomplete?.(UV_ENOENT, this, req, true, true);
|
|
77
89
|
return;
|
|
78
90
|
}
|
|
79
|
-
const accepted = new Pipe(server.type === constants.IPC ? constants.IPC : constants.SOCKET);
|
|
91
|
+
const accepted = new (server.constructor as typeof Pipe)(server.type === constants.IPC ? constants.IPC : constants.SOCKET);
|
|
80
92
|
accepted.path = path;
|
|
81
93
|
// The serving run owns what it accepted, not the connecting one.
|
|
82
94
|
__adoptHandle(accepted, ownerOf(server));
|
|
@@ -95,6 +107,12 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
95
107
|
* opened it, because a child's channel is written to before the child runs.
|
|
96
108
|
*/
|
|
97
109
|
open(fd: number): number {
|
|
110
|
+
const native = nativeStreamFor(this);
|
|
111
|
+
if (native) {
|
|
112
|
+
const status = native.call({ operation: 'open', id: native.descriptor.id, fd }).status;
|
|
113
|
+
if (status === 0) this.fd = fd;
|
|
114
|
+
return status;
|
|
115
|
+
}
|
|
98
116
|
const held = handleForFd(fd) as LibuvStreamWrap | undefined;
|
|
99
117
|
if (!held) return UV_EBADF;
|
|
100
118
|
this.takeOverFrom(held);
|
|
@@ -111,8 +129,9 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
111
129
|
|
|
112
130
|
/** libuv's `dup()`: the same pairing, under the same flavour. */
|
|
113
131
|
override duplicate(): Pipe {
|
|
114
|
-
const
|
|
115
|
-
copy.
|
|
132
|
+
const native = nativeStreamFor(this);
|
|
133
|
+
const copy = native ? native.duplicate() as Pipe : new (this.constructor as typeof Pipe)(this.type);
|
|
134
|
+
if (!native) copy.shareConnectionFrom(this);
|
|
116
135
|
return copy;
|
|
117
136
|
}
|
|
118
137
|
|
|
@@ -133,14 +152,16 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
133
152
|
*
|
|
134
153
|
* The handle becomes the receiving run's. Node's `send(message, socket)`
|
|
135
154
|
* duplicates the sender's descriptor into the other process, and from then
|
|
136
|
-
* on the socket is an active handle of that process's loop
|
|
137
|
-
*
|
|
138
|
-
*
|
|
155
|
+
* on the socket is an active handle of that process's loop. The binding
|
|
156
|
+
* duplicates the wrapper and assigns that reference to the receiver.
|
|
157
|
+
* Without that ownership, openvscode-server's extension
|
|
139
158
|
* host -- a program whose only handle is the socket its parent sent it --
|
|
140
159
|
* read as idle and was settled with exit 0.
|
|
141
160
|
*/
|
|
142
|
-
override
|
|
143
|
-
|
|
161
|
+
protected override dispatchWrite(req: WriteWrap, bytes: Uint8Array, handle?: unknown): number {
|
|
162
|
+
const native = nativeStreamFor(this);
|
|
163
|
+
if (native) return native.write(req, [bytes], handle);
|
|
164
|
+
if (handle === undefined || handle === null) return super.dispatchWrite(req, bytes);
|
|
144
165
|
// A descriptor crosses as a duplicate, as `SCM_RIGHTS` hands one over: the
|
|
145
166
|
// receiver gets its own handle on the same connection, so the sender's
|
|
146
167
|
// close on `NODE_HANDLE_ACK` -- which Node's `child_process.js` does the
|
|
@@ -148,11 +169,12 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
148
169
|
// a listening server's, has nothing to duplicate and crosses as it is.
|
|
149
170
|
const sent = handle as LibuvStreamWrap;
|
|
150
171
|
const given = sent.peer !== null ? sent.duplicate() : sent;
|
|
151
|
-
// The receiving run owns
|
|
152
|
-
//
|
|
153
|
-
// engine keeps of what holds a run open.
|
|
172
|
+
// The receiving run owns this reference; the sender retains its own until
|
|
173
|
+
// Node closes it on acknowledgement, or continues using it with keepOpen.
|
|
154
174
|
__adoptHandle(given, ownerOf(this.peer ?? this));
|
|
155
|
-
|
|
175
|
+
const status = super.dispatchWrite(req, bytes, given);
|
|
176
|
+
if (status !== 0 && given !== sent) given.close();
|
|
177
|
+
return status;
|
|
156
178
|
}
|
|
157
179
|
|
|
158
180
|
protected override onCloseHandle(): void {
|
|
@@ -163,4 +185,5 @@ export class Pipe extends LibuvStreamWrap {
|
|
|
163
185
|
}
|
|
164
186
|
}
|
|
165
187
|
|
|
188
|
+
registerNativeStreamConstructor('pipe', Pipe);
|
|
166
189
|
export default { Pipe, PipeConnectWrap, constants };
|
|
@@ -27,7 +27,9 @@ import {
|
|
|
27
27
|
registerHandle, refHandle, unrefHandle, handleHasRef, releaseHandle, __adoptHandle,
|
|
28
28
|
ownerOf, type OwnedHandle,
|
|
29
29
|
} from './handles';
|
|
30
|
-
import { __runFor, type ProcessToken } from '../../process-tokens';
|
|
30
|
+
import { __runFor, mintPid, type ProcessToken } from '../../process-tokens';
|
|
31
|
+
import { handleForFd } from './fds';
|
|
32
|
+
import { TTY, type TerminalState } from './tty_wrap';
|
|
31
33
|
|
|
32
34
|
/** One entry of Node's `options.stdio`, as `getValidStdio` builds it. */
|
|
33
35
|
export interface StdioEntry {
|
|
@@ -85,8 +87,14 @@ export interface RunRequest {
|
|
|
85
87
|
stderrIsPipe: boolean;
|
|
86
88
|
/** True when the child's fd 0 is a pipe whose writer has not closed. */
|
|
87
89
|
stdinIsPipe: boolean;
|
|
90
|
+
terminal?: TerminalState;
|
|
88
91
|
/** The IPC channel the child is started with, where it has one. */
|
|
89
92
|
channel?: RunChannel;
|
|
93
|
+
/**
|
|
94
|
+
* The child's pipes past fd 2 (`stdio: [..., 'pipe', 'pipe']`), each at the
|
|
95
|
+
* number the child reads or writes it by, with the child's end of it.
|
|
96
|
+
*/
|
|
97
|
+
descriptors: { fd: number; pipe: Pipe }[];
|
|
90
98
|
/** Called once, when the run has ended. */
|
|
91
99
|
exit(code: number, signal: string | null): void;
|
|
92
100
|
}
|
|
@@ -100,7 +108,7 @@ export interface StartedRun {
|
|
|
100
108
|
/** libuv's `uv_process_kill`: 0, or `UV_ESRCH` for a run already over. */
|
|
101
109
|
kill(signal: string): number;
|
|
102
110
|
/** Bytes the parent wrote to the child's fd 0. */
|
|
103
|
-
writeStdin(bytes: Uint8Array): void
|
|
111
|
+
writeStdin(bytes: Uint8Array): void | Promise<void>;
|
|
104
112
|
/** The parent closed the child's fd 0. */
|
|
105
113
|
endStdin(): void;
|
|
106
114
|
}
|
|
@@ -123,7 +131,6 @@ export function setProcessRunner(next: ProcessRunner): void {
|
|
|
123
131
|
runner = next;
|
|
124
132
|
}
|
|
125
133
|
|
|
126
|
-
let nextPid = 1001 + Math.floor(Math.random() * 30000);
|
|
127
134
|
let nextAsyncId = 1;
|
|
128
135
|
|
|
129
136
|
/** `envPairs` is `KEY=value` strings; the engine's shell takes a record. */
|
|
@@ -208,6 +215,7 @@ export class Process implements OwnedHandle {
|
|
|
208
215
|
private closed = false;
|
|
209
216
|
/** The stdio entries this run was started with, and their far ends. */
|
|
210
217
|
private stdio: StdioEntry[] = [];
|
|
218
|
+
private terminalEnds = new Map<number, TTY>();
|
|
211
219
|
private readonly asyncId = nextAsyncId++;
|
|
212
220
|
|
|
213
221
|
constructor() {
|
|
@@ -250,13 +258,30 @@ export class Process implements OwnedHandle {
|
|
|
250
258
|
stderr: null,
|
|
251
259
|
stderrIsPipe: false,
|
|
252
260
|
stdinIsPipe: false,
|
|
261
|
+
descriptors: [],
|
|
253
262
|
exit: (code, signal) => { this.reportExit(code, signal); },
|
|
254
263
|
};
|
|
255
264
|
|
|
256
|
-
let stdinFar:
|
|
265
|
+
let stdinFar: LibuvStreamWrap | null = null;
|
|
257
266
|
for (let index = 0; index < this.stdio.length; index += 1) {
|
|
258
267
|
const entry = this.stdio[index];
|
|
259
268
|
if (!entry) continue;
|
|
269
|
+
if (index < 3 && !entry.ipc) {
|
|
270
|
+
const descriptor = entry.type === 'fd' || entry.type === 'inherit'
|
|
271
|
+
? handleForFd(entry.fd ?? index) : entry.handle;
|
|
272
|
+
if (descriptor instanceof TTY && descriptor.slave) {
|
|
273
|
+
// Inherit an independent descriptor reference, never the parent's
|
|
274
|
+
// wrapper. Failed spawn and child exit release only this copy.
|
|
275
|
+
const inherited = descriptor.duplicate();
|
|
276
|
+
__adoptHandle(inherited, null);
|
|
277
|
+
this.terminalEnds.set(index, inherited);
|
|
278
|
+
request.terminal = inherited.terminal;
|
|
279
|
+
if (index === 0) { stdinFar = inherited; request.stdinIsPipe = true; }
|
|
280
|
+
else if (index === 1) request.stdout = text => this.toPipe(index, text);
|
|
281
|
+
else request.stderr = text => this.toPipe(index, text);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
260
285
|
const far = this.pairFarEnd(entry);
|
|
261
286
|
if (entry.ipc) {
|
|
262
287
|
if (far) {
|
|
@@ -273,7 +298,12 @@ export class Process implements OwnedHandle {
|
|
|
273
298
|
request.stdinIsPipe = far !== null;
|
|
274
299
|
continue;
|
|
275
300
|
}
|
|
276
|
-
if (index
|
|
301
|
+
if (index > 2) {
|
|
302
|
+
// A pipe past fd 2 is the child's too, at its own number: libuv
|
|
303
|
+
// hands a child every `UV_CREATE_PIPE` entry, not only stdio's three.
|
|
304
|
+
if (far) request.descriptors.push({ fd: index, pipe: far });
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
277
307
|
if (far) {
|
|
278
308
|
const to = index;
|
|
279
309
|
const write = (text: string): void => { this.toPipe(to, text); };
|
|
@@ -297,7 +327,7 @@ export class Process implements OwnedHandle {
|
|
|
297
327
|
this.run = runner.start(request);
|
|
298
328
|
// The number the parent reads off the handle is the child's own
|
|
299
329
|
// `process.pid`, as it is in Node; a runner that names none is given one.
|
|
300
|
-
this.pid = this.run.pid ??
|
|
330
|
+
this.pid = this.run.pid ?? mintPid();
|
|
301
331
|
if (stdinFar) this.readStdinFrom(stdinFar);
|
|
302
332
|
return 0;
|
|
303
333
|
}
|
|
@@ -337,7 +367,7 @@ export class Process implements OwnedHandle {
|
|
|
337
367
|
|
|
338
368
|
/** The far end of fd `index`, whoever holds it now. */
|
|
339
369
|
private farEndAt(index: number): LibuvStreamWrap | null {
|
|
340
|
-
return this.stdio[index]?.handle?.peer ?? null;
|
|
370
|
+
return this.terminalEnds.get(index) ?? this.stdio[index]?.handle?.peer ?? null;
|
|
341
371
|
}
|
|
342
372
|
|
|
343
373
|
private closeFarEnds(): void {
|
|
@@ -356,11 +386,22 @@ export class Process implements OwnedHandle {
|
|
|
356
386
|
}
|
|
357
387
|
|
|
358
388
|
/** Bytes the parent writes reach the child's fd 0; the parent's EOF ends it. */
|
|
359
|
-
private readStdinFrom(far:
|
|
389
|
+
private readStdinFrom(far: LibuvStreamWrap): void {
|
|
360
390
|
far.onread = (arrayBuffer: ArrayBuffer | null): void => {
|
|
361
391
|
const length = streamBaseState[kReadBytesOrError];
|
|
362
392
|
if (length <= 0 || arrayBuffer === null) { this.run?.endStdin(); return; }
|
|
363
|
-
|
|
393
|
+
const run = this.run;
|
|
394
|
+
const consumed = run?.writeStdin(new Uint8Array(arrayBuffer, streamBaseState[kArrayBufferOffset], length).slice());
|
|
395
|
+
if (consumed) {
|
|
396
|
+
far.readStop();
|
|
397
|
+
void consumed.then(() => {
|
|
398
|
+
if (this.run === run && !this.ended && !far.closed) far.readStart();
|
|
399
|
+
}, () => {
|
|
400
|
+
// A stopped receiver closes its input pipe. Do not resume a reader
|
|
401
|
+
// or deliver its queued bytes to a later run.
|
|
402
|
+
if (this.run === run && !this.ended) { far.close(); run?.endStdin(); }
|
|
403
|
+
});
|
|
404
|
+
}
|
|
364
405
|
};
|
|
365
406
|
far.readStart();
|
|
366
407
|
}
|