@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.
Files changed (80) hide show
  1. package/dist/__sw__.js +259 -5
  2. package/dist/assets/{runtime-worker-LWfW6VWE.js → runtime-worker-DBZ2flHK.js} +4000 -2944
  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 +5196 -3062
  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 +12 -1
  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 +11 -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 +18 -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 +50 -9
  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 +55 -6
  72. package/src/promise-ownership.ts +28 -0
  73. package/src/runtime.ts +90 -214
  74. package/src/shims/child_process.ts +310 -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
@@ -9,12 +9,56 @@
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';
13
- import { guessHandleTypeOfFd } from './fds';
12
+ import { LibuvStreamWrap, type WriteWrap } from './stream_wrap';
13
+ import { guessHandleTypeOfFd, handleForFd, registerFd, releaseFd } from './fds';
14
+ import { UV_EBADF, UV_EIO, UV_ENOTSUP } from './uv';
15
+
16
+ export interface TerminalState {
17
+ columns: number;
18
+ rows: number;
19
+ onResize(listener: (columns: number, rows: number) => void): () => void;
20
+ resize(columns: number, rows: number): void;
21
+ }
22
+
23
+ /** One terminal endpoint, shared by independently owned descriptors. */
24
+ class TerminalEndpoint {
25
+ readonly descriptors = new Set<TTY>();
26
+ readonly readers = new Set<TTY>();
27
+ readonly input: Uint8Array[] = [];
28
+ peer?: TerminalEndpoint;
29
+ eof = false;
30
+ scheduled = false;
31
+ constructor(readonly terminal: TerminalState, readonly slave: boolean) {}
32
+ pump(): void {
33
+ if (this.scheduled) return;
34
+ this.scheduled = true;
35
+ queueMicrotask(() => {
36
+ this.scheduled = false;
37
+ while (this.input.length) {
38
+ const reader = [...this.readers].find(handle => handle.reading && !handle.closed && !handle.descriptor.closed);
39
+ if (!reader) return;
40
+ reader.deliver(this.input.shift()!);
41
+ }
42
+ if (this.eof) for (const reader of this.readers) reader.receiveEof();
43
+ });
44
+ }
45
+ release(descriptor: TTY): void {
46
+ this.descriptors.delete(descriptor);
47
+ if (this.descriptors.size || !this.peer) return;
48
+ this.peer.eof = true;
49
+ this.peer.pump();
50
+ this.input.length = 0;
51
+ }
52
+ }
53
+
14
54
 
15
55
  /** libuv's `uv_tty_t`, over the same stream the rest of the binding is. */
16
56
  export class TTY extends LibuvStreamWrap {
17
- readonly fdNumber: number;
57
+ get fdNumber(): number { return this.fd; }
58
+ readonly descriptor: TTY;
59
+ private endpoint?: TerminalEndpoint;
60
+ get terminal(): TerminalState | undefined { return this.endpoint?.terminal; }
61
+ get slave(): boolean { return this.endpoint?.slave === true; }
18
62
 
19
63
  /**
20
64
  * Node's `new TTY(fd, ctx)` writes an errno onto `ctx` when the fd is not
@@ -24,8 +68,11 @@ export class TTY extends LibuvStreamWrap {
24
68
  */
25
69
  constructor(fd: number, ctx?: { code?: string } | boolean) {
26
70
  super();
27
- this.fdNumber = fd;
28
71
  this.fd = fd;
72
+ const held = handleForFd(fd);
73
+ this.descriptor = held instanceof TTY ? held.descriptor : this;
74
+ this.endpoint = held instanceof TTY ? held.endpoint : undefined;
75
+ this.endpoint?.readers.add(this);
29
76
  if (ctx && typeof ctx === 'object' && !isTTY(fd)) {
30
77
  ctx.code = 'ENOTTY';
31
78
  }
@@ -33,16 +80,96 @@ export class TTY extends LibuvStreamWrap {
33
80
 
34
81
  /** A terminal the engine does not own has one size and no mode to set. */
35
82
  getWindowSize(out: number[]): number {
36
- out[0] = 80;
37
- out[1] = 24;
83
+ out[0] = this.terminal?.columns ?? 80;
84
+ out[1] = this.terminal?.rows ?? 24;
38
85
  return 0;
39
86
  }
40
87
 
41
88
  setRawMode(_raw: number): number {
42
- return 0;
89
+ // ADR-0023: this host has no termios. Do not claim a mode change.
90
+ return this.endpoint ? UV_ENOTSUP : 0;
91
+ }
92
+
93
+ static allocate(endpoint: TerminalEndpoint): TTY {
94
+ const handle = new TTY(-1);
95
+ handle.endpoint = endpoint;
96
+ handle.fd = registerFd('TTY', handle);
97
+ endpoint.descriptors.add(handle);
98
+ endpoint.readers.add(handle);
99
+ return handle;
100
+ }
101
+
102
+ /** Inheritance duplicates the fd; neither process owns the other's ref. */
103
+ duplicate(): TTY {
104
+ if (!this.endpoint || this.closed || this.descriptor.closed) throw Object.assign(new Error('Bad terminal descriptor'), { code: 'EBADF' });
105
+ return TTY.allocate(this.endpoint);
106
+ }
107
+
108
+ readStart(): number {
109
+ if (this.descriptor.closed) return UV_EBADF;
110
+ const result = super.readStart();
111
+ this.endpoint?.pump();
112
+ return result;
113
+ }
114
+
115
+ /** Delivered into Node's existing stream binding, preserving backpressure. */
116
+ deliver(bytes: Uint8Array): void { this.receive(bytes); this.flushInbound(); }
117
+
118
+ protected dispatchWrite(req: WriteWrap, bytes: Uint8Array): number {
119
+ if (!this.endpoint) return super.dispatchWrite(req, bytes);
120
+ if (this.closed || this.descriptor.closed) return UV_EBADF;
121
+ if (!this.endpoint.peer?.descriptors.size) return UV_EIO;
122
+ // Let the base binding set Node's synchronous-write accounting, while
123
+ // the shared endpoint, rather than a replaceable handle, owns the bytes.
124
+ const status = super.dispatchWrite(req, bytes);
125
+ if (bytes.byteLength) this.endpoint.peer.input.push(bytes.slice());
126
+ this.endpoint.peer.pump();
127
+ return status;
128
+ }
129
+
130
+ protected onCloseHandle(): void {
131
+ this.endpoint?.readers.delete(this);
132
+ if (this.descriptor !== this) { this.descriptor.close(); return; }
133
+ releaseFd(this.fd);
134
+ this.endpoint?.release(this);
135
+ for (const reader of this.endpoint?.readers ?? []) {
136
+ if (reader.descriptor === this) reader.close();
137
+ }
43
138
  }
44
139
  }
45
140
 
141
+ /** Host OS adapter door. The process host retains terminal behavior. */
142
+ export function openPty(columns: number, rows: number): { master: number; slave: number; pty: string } {
143
+ validSize(columns, rows);
144
+ const listeners = new Set<(columns: number, rows: number) => void>();
145
+ const terminal: TerminalState = {
146
+ columns, rows,
147
+ onResize(listener) { listeners.add(listener); return () => { listeners.delete(listener); }; },
148
+ resize(columns, rows) {
149
+ validSize(columns, rows);
150
+ this.columns = columns; this.rows = rows;
151
+ for (const listener of listeners) listener(columns, rows);
152
+ },
153
+ };
154
+ const master = new TerminalEndpoint(terminal, false);
155
+ const slave = new TerminalEndpoint(terminal, true);
156
+ master.peer = slave; slave.peer = master;
157
+ const masterFd = TTY.allocate(master).fd;
158
+ const slaveFd = TTY.allocate(slave).fd;
159
+ return { master: masterFd, slave: slaveFd, pty: `/dev/pts/${slaveFd}` };
160
+ }
161
+
162
+ function validSize(columns: number, rows: number): void {
163
+ if (![columns, rows].every(value => Number.isInteger(value) && value > 0)) throw Object.assign(new Error('Invalid terminal size'), { code: 'EINVAL' });
164
+ }
165
+
166
+ export function resizePty(fd: number, columns: number, rows: number): void {
167
+ const terminal = handleForFd(fd);
168
+ if (!(terminal instanceof TTY) || terminal.closed) throw Object.assign(new Error('Bad terminal descriptor'), { code: 'EBADF' });
169
+ terminal.terminal?.resize(columns, rows);
170
+ }
171
+
172
+
46
173
  /** libuv's `uv_guess_handle(fd) === UV_TTY`, as the running program sees it. */
47
174
  export function isTTY(fd: number): boolean {
48
175
  if (fd !== 0 && fd !== 1 && fd !== 2) return guessHandleTypeOfFd(fd) === 'TTY';
@@ -53,4 +180,4 @@ export function isTTY(fd: number): boolean {
53
180
  return stream?.isTTY === true;
54
181
  }
55
182
 
56
- export default { TTY, isTTY };
183
+ export default { TTY, isTTY, openPty, resizePty };
@@ -152,21 +152,7 @@ export const utilBinding = {
152
152
  * the module the first time it is read, so a builtin that exposes another
153
153
  * builtin's class does not load it to say so.
154
154
  */
155
- defineLazyProperties: (target: object, id: string, keys: string[], writable = true): void => {
156
- for (const key of keys) {
157
- let built: unknown;
158
- let ready = false;
159
- Object.defineProperty(target, key, {
160
- configurable: true,
161
- enumerable: true,
162
- get() {
163
- if (!ready) { ready = true; built = (nodeLibInternalRequire(id) as Record<string, unknown>)[key]; }
164
- return built;
165
- },
166
- set: writable ? (value: unknown) => { built = value; ready = true; } : void 0,
167
- });
168
- }
169
- },
155
+ defineLazyProperties: lazyProperties(nodeLibInternalRequire),
170
156
 
171
157
  /**
172
158
  * The stack, as `util.getCallSites()` reports it: one entry per frame with
@@ -272,3 +258,26 @@ export const utilBinding = {
272
258
  };
273
259
 
274
260
  export default utilBinding;
261
+
262
+ function lazyProperties(require: (name: string) => unknown) {
263
+ return (target: object, id: string, keys: string[], writable = true): void => {
264
+ for (const key of keys) {
265
+ let built: unknown;
266
+ let ready = false;
267
+ Object.defineProperty(target, key, {
268
+ configurable: true,
269
+ enumerable: true,
270
+ get() {
271
+ if (!ready) { ready = true; built = (require(id) as Record<string, unknown>)[key]; }
272
+ return built;
273
+ },
274
+ set: writable ? (value: unknown) => { built = value; ready = true; } : void 0,
275
+ });
276
+ }
277
+ };
278
+ }
279
+
280
+ /** Lazy builtin exports must resolve inside the requesting process. */
281
+ export function createUtilBinding(require: (name: string) => unknown) {
282
+ return { ...utilBinding, defineLazyProperties: lazyProperties(require) };
283
+ }
@@ -93,10 +93,14 @@ export const UV_ENOTCONN = codes.UV_ENOTCONN[0];
93
93
  export const UV_ECANCELED = codes.UV_ECANCELED[0];
94
94
  export const UV_ENOTSUP = codes.UV_ENOTSUP[0];
95
95
  export const UV_EBADF = codes.UV_EBADF[0];
96
+ export const UV_EIO = codes.UV_EIO[0];
96
97
  export const UV_ENOSYS = codes.UV_ENOSYS[0];
97
98
  export const UV_EADDRNOTAVAIL = codes.UV_EADDRNOTAVAIL[0];
98
99
  export const UV_EACCES = codes.UV_EACCES[0];
99
100
  export const UV_ENOBUFS = codes.UV_ENOBUFS[0];
101
+ export const UV_EMFILE = codes.UV_EMFILE[0];
102
+ export const UV_EBUSY = codes.UV_EBUSY[0];
103
+ export const UV_EALREADY = codes.UV_EALREADY[0];
100
104
  export const UV_ESRCH = codes.UV_ESRCH[0];
101
105
 
102
106
  export default uvBinding;
@@ -19,25 +19,9 @@ import { loadNodeLibFor } from './load';
19
19
  export const fsModule = lazyModule<Record<string, unknown>>('fs');
20
20
  export const fsPromisesModule = lazyModule<Record<string, unknown>>('internal/fs/promises');
21
21
 
22
- /**
23
- * `require('fs')` for one guest process. The first process in the realm is
24
- * handed the already-built module; a later process gets a file compiled for
25
- * it, so a tag on the module object is that process's.
26
- */
27
- const byProcess = new WeakMap<object, unknown>();
28
- let firstProcess: object | null = null;
22
+ /** Every guest, including the first, owns its builtin graph. */
29
23
  export function fsModuleFor(process: object): unknown {
30
- const held = byProcess.get(process);
31
- if (held !== undefined) return held;
32
- let module: unknown;
33
- if (firstProcess === null || firstProcess === process) {
34
- firstProcess = process;
35
- module = fsModule;
36
- } else {
37
- module = loadNodeLibFor(process, 'fs');
38
- }
39
- byProcess.set(process, module);
40
- return module;
24
+ return loadNodeLibFor(process, 'fs');
41
25
  }
42
26
 
43
27
  export default fsModule;
@@ -0,0 +1,149 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ ObjectDefineProperties,
5
+ ObjectFreeze,
6
+ StringPrototypeIndexOf,
7
+ StringPrototypeSlice,
8
+ StringPrototypeToUpperCase,
9
+ Symbol,
10
+ } = primordials;
11
+
12
+ const {
13
+ ERR_ILLEGAL_CONSTRUCTOR,
14
+ } = require('internal/errors').codes;
15
+
16
+ const {
17
+ kEnumerableProperty,
18
+ } = require('internal/util');
19
+
20
+ const {
21
+ getAvailableParallelism,
22
+ } = internalBinding('os');
23
+
24
+ const kInitialize = Symbol('kInitialize');
25
+
26
+ const {
27
+ platform,
28
+ arch,
29
+ version: nodeVersion,
30
+ } = require('internal/process/per_thread');
31
+
32
+ const {
33
+ getDefaultLocale,
34
+ } = internalBinding('config');
35
+
36
+ /**
37
+ * @param {string} arch
38
+ * @param {string} platform
39
+ * @returns {string}
40
+ */
41
+ function getNavigatorPlatform(arch, platform) {
42
+ if (platform === 'darwin') {
43
+ // On macOS, modern browsers return 'MacIntel' even if running on Apple Silicon.
44
+ return 'MacIntel';
45
+ } else if (platform === 'win32') {
46
+ // On Windows, modern browsers return 'Win32' even if running on a 64-bit version of Windows.
47
+ // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#usage_notes
48
+ return 'Win32';
49
+ } else if (platform === 'linux') {
50
+ if (arch === 'ia32') {
51
+ return 'Linux i686';
52
+ } else if (arch === 'x64') {
53
+ return 'Linux x86_64';
54
+ }
55
+ return `Linux ${arch}`;
56
+ } else if (platform === 'freebsd') {
57
+ if (arch === 'ia32') {
58
+ return 'FreeBSD i386';
59
+ } else if (arch === 'x64') {
60
+ return 'FreeBSD amd64';
61
+ }
62
+ return `FreeBSD ${arch}`;
63
+ } else if (platform === 'openbsd') {
64
+ if (arch === 'ia32') {
65
+ return 'OpenBSD i386';
66
+ } else if (arch === 'x64') {
67
+ return 'OpenBSD amd64';
68
+ }
69
+ return `OpenBSD ${arch}`;
70
+ } else if (platform === 'sunos') {
71
+ if (arch === 'ia32') {
72
+ return 'SunOS i86pc';
73
+ }
74
+ return `SunOS ${arch}`;
75
+ } else if (platform === 'aix') {
76
+ return 'AIX';
77
+ }
78
+ return `${StringPrototypeToUpperCase(platform[0])}${StringPrototypeSlice(platform, 1)} ${arch}`;
79
+ }
80
+
81
+ class Navigator {
82
+ // Private properties are used to avoid brand validations.
83
+ #availableParallelism;
84
+ #userAgent;
85
+ #platform;
86
+ #languages;
87
+
88
+ constructor() {
89
+ if (arguments[0] === kInitialize) {
90
+ return;
91
+ }
92
+ throw new ERR_ILLEGAL_CONSTRUCTOR();
93
+ }
94
+
95
+ /**
96
+ * @return {number}
97
+ */
98
+ get hardwareConcurrency() {
99
+ this.#availableParallelism ??= getAvailableParallelism();
100
+ return this.#availableParallelism;
101
+ }
102
+
103
+ /**
104
+ * @return {string}
105
+ */
106
+ get language() {
107
+ // The default locale might be changed dynamically, so always invoke the
108
+ // binding.
109
+ return getDefaultLocale() || 'en-US';
110
+ }
111
+
112
+ /**
113
+ * @return {Array<string>}
114
+ */
115
+ get languages() {
116
+ this.#languages ??= ObjectFreeze([this.language]);
117
+ return this.#languages;
118
+ }
119
+
120
+ /**
121
+ * @return {string}
122
+ */
123
+ get userAgent() {
124
+ this.#userAgent ??= `Node.js/${StringPrototypeSlice(nodeVersion, 1, StringPrototypeIndexOf(nodeVersion, '.'))}`;
125
+ return this.#userAgent;
126
+ }
127
+
128
+ /**
129
+ * @return {string}
130
+ */
131
+ get platform() {
132
+ this.#platform ??= getNavigatorPlatform(arch, platform);
133
+ return this.#platform;
134
+ }
135
+ }
136
+
137
+ ObjectDefineProperties(Navigator.prototype, {
138
+ hardwareConcurrency: kEnumerableProperty,
139
+ language: kEnumerableProperty,
140
+ languages: kEnumerableProperty,
141
+ userAgent: kEnumerableProperty,
142
+ platform: kEnumerableProperty,
143
+ });
144
+
145
+ module.exports = {
146
+ getNavigatorPlatform,
147
+ navigator: new Navigator(kInitialize),
148
+ Navigator,
149
+ };
@@ -118,26 +118,62 @@ export const internalFile = {
118
118
  */
119
119
  type AnyStream = Record<string, (...args: never[]) => unknown> & Record<string, unknown>;
120
120
 
121
+ /** Capture the owning graph; callbacks must not fall back to the host loader. */
122
+ export function createWebStreamsAdapters(require: (name: string) => unknown = libRequire) {
121
123
  function streamModule(): Record<string, new (options?: unknown) => AnyStream> {
122
- return libRequire('stream') as Record<string, new (options?: unknown) => AnyStream>;
124
+ return require('stream') as Record<string, new (options?: unknown) => AnyStream>;
123
125
  }
124
126
 
125
- function newReadableStreamFromStreamReadable(readable: AnyStream): ReadableStream {
127
+ function newReadableStreamFromStreamReadable(readable: AnyStream, options?: { strategy?: QueuingStrategy }): ReadableStream {
128
+ // Node v22.18's webstreams/adapters owns this boundary's semantics: pause
129
+ // at the Web queue's high-water mark, resume on pull, and let Node's own
130
+ // finished()/destroy() handle premature close and cancellation. The old
131
+ // adapter attached a flowing data listener with no pressure, buffering an
132
+ // entire HTTP upload while the host was still deciding whether to admit it.
133
+ const streams = require('stream') as {
134
+ finished(stream: AnyStream, callback: (error?: Error | null) => void): () => void;
135
+ destroy(stream: AnyStream, error?: unknown): void;
136
+ };
137
+ if (typeof readable?._readableState !== 'object') {
138
+ throw Object.assign(new TypeError('streamReadable must be a stream.Readable'), { code: 'ERR_INVALID_ARG_TYPE' });
139
+ }
140
+ if (readable.destroyed || (readable as Record<string, unknown>).readable === false) return new ReadableStream({ start(controller) { controller.close(); } });
141
+ const objectMode = Boolean(readable.readableObjectMode);
142
+ const highWaterMark = Number(readable.readableHighWaterMark);
143
+ const strategy = options?.strategy ?? (objectMode
144
+ ? new CountQueuingStrategy({ highWaterMark }) : new ByteLengthQueuingStrategy({ highWaterMark }));
145
+ let canceled = false;
146
+ let complete = false;
147
+ let controller: ReadableStreamDefaultController;
148
+ const on = readable.on as (event: string, listener: (...args: any[]) => void) => void;
149
+ const onData = (chunk: unknown): void => {
150
+ if (complete || canceled) return;
151
+ // Detach binary chunks from Node's reusable Buffer pool; retain objects.
152
+ controller.enqueue(!objectMode && chunk instanceof Uint8Array ? new Uint8Array(chunk) : chunk);
153
+ if ((controller.desiredSize ?? 0) <= 0) (readable.pause as () => void)();
154
+ };
155
+ (readable.pause as () => void)();
126
156
  return new ReadableStream({
127
- start(controller) {
128
- (readable.on as (e: string, l: (v: unknown) => void) => void)('data', (chunk) => {
129
- controller.enqueue(chunk instanceof Uint8Array ? chunk : new Uint8Array(Buffer_from(chunk)));
157
+ start(output) {
158
+ controller = output;
159
+ const cleanup = streams.finished(readable, (error) => {
160
+ complete = true;
161
+ cleanup();
162
+ (readable.removeListener as (event: string, listener: (...args: any[]) => void) => void)('data', onData);
163
+ on.call(readable, 'error', () => {});
164
+ if (canceled) return;
165
+ if (error) controller.error(error); else controller.close();
130
166
  });
131
- (readable.on as (e: string, l: () => void) => void)('end', () => { try { controller.close(); } catch { /* a stream closed twice is closed */ } });
132
- (readable.on as (e: string, l: (v: unknown) => void) => void)('error', (error) => { try { controller.error(error); } catch { /* likewise */ } });
167
+ on.call(readable, 'data', onData);
133
168
  },
134
- cancel() { (readable.destroy as () => void)(); },
135
- });
169
+ pull() { if (!complete && !canceled) (readable.resume as () => void)(); },
170
+ cancel(reason) { canceled = true; streams.destroy(readable, reason); },
171
+ }, strategy);
136
172
  }
137
173
 
138
174
  /** The bytes of a chunk that is not already one, without importing `buffer` at load. */
139
175
  function Buffer_from(chunk: unknown): Uint8Array {
140
- const { Buffer } = libRequire('buffer') as { Buffer: { from(value: unknown): Uint8Array } };
176
+ const { Buffer } = require('buffer') as { Buffer: { from(value: unknown): Uint8Array } };
141
177
  return Buffer.from(chunk);
142
178
  }
143
179
 
@@ -214,7 +250,7 @@ function newStreamDuplexFromReadableWritablePair(pair: { readable: ReadableStrea
214
250
  return duplex;
215
251
  }
216
252
 
217
- export const internalWebStreamsAdapters = {
253
+ return {
218
254
  newReadableStreamFromStreamReadable,
219
255
  newStreamReadableFromReadableStream,
220
256
  newWritableStreamFromStreamWritable,
@@ -222,3 +258,6 @@ export const internalWebStreamsAdapters = {
222
258
  newReadableWritablePairFromDuplex,
223
259
  newStreamDuplexFromReadableWritablePair,
224
260
  };
261
+
262
+ }
263
+ export const internalWebStreamsAdapters = createWebStreamsAdapters();
@@ -13,6 +13,11 @@ import { readlineModule as nodeLibPublicReadline } from './readline-access';
13
13
  /** `internal/console/global`: the realm's console, which `util.debuglog` logs through. */
14
14
  export const internalConsoleGlobal = new Proxy({} as Record<string, unknown>, {
15
15
  get: (_target, key) => Reflect.get(globalThis.console as unknown as object, key),
16
+ ownKeys: () => Reflect.ownKeys(globalThis.console),
17
+ getOwnPropertyDescriptor: (_target, key) => ({
18
+ configurable: true, enumerable: true,
19
+ get: () => Reflect.get(globalThis.console as unknown as object, key),
20
+ }),
16
21
  });
17
22
 
18
23
  /**
@@ -23,14 +23,24 @@ import {
23
23
  import { internalSocketAddress, internalBlockList } from './addresses';
24
24
  import { internalFsUtils, internalDgram } from './child-process';
25
25
  import {
26
- internalAbortController, internalBlob, internalFile, internalWebStreamsAdapters,
26
+ internalAbortController, internalBlob, internalFile, internalWebStreamsAdapters, createWebStreamsAdapters,
27
27
  } from './buffer-and-streams';
28
28
  import { internalBootstrapRealm, internalUrl, internalEncoding } from './modules';
29
29
 
30
30
  /** Built on the first ask, for the reason `./binding/index.ts` gives. */
31
31
  // eslint-disable-next-line no-var, vars-on-top
32
32
  var __table: Record<string, () => unknown> | undefined;
33
- export function nodeLibInternal(name: string): (() => unknown) | undefined {
33
+ export function nodeLibInternal(name: string, require?: (name: string) => any, process?: any): (() => unknown) | undefined {
34
+ if (require && name === 'internal/webstreams/adapters') return () => createWebStreamsAdapters(require);
35
+ if (process && name === 'internal/process/per_thread') return () => ({
36
+ platform: process.platform, arch: process.arch, version: process.version,
37
+ });
38
+ if (process && name === 'internal/process/execution') return () => ({
39
+ tryGetCwd() { try { return process.cwd(); } catch { return ''; } },
40
+ });
41
+ if (process && name === 'internal/process/warning') return () => ({
42
+ emitWarningSync: (...args: unknown[]) => process.emitWarning(...args),
43
+ });
34
44
  __table ??= {
35
45
  'internal/util/types': () => internalUtilTypes,
36
46
  'internal/async_hooks': () => internalAsyncHooks,