@volter/tabnode 0.5.9 → 0.5.11

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.
@@ -26661,11 +26661,13 @@ function createProcessStream(isWritable, writeImpl) {
26661
26661
  return stream;
26662
26662
  },
26663
26663
  // Default write implementation (no-op for readable streams)
26664
- write(_data, _encoding, callback) {
26664
+ write(_data, ...rest) {
26665
+ const callback = trailingCallback(rest);
26665
26666
  if (callback) queueMicrotask(callback);
26666
26667
  return true;
26667
26668
  },
26668
- end(_data, callback) {
26669
+ end(...rest) {
26670
+ const callback = trailingCallback(rest);
26669
26671
  if (callback) queueMicrotask(callback);
26670
26672
  },
26671
26673
  pipe(destination) {
@@ -26681,14 +26683,31 @@ function createProcessStream(isWritable, writeImpl) {
26681
26683
  }
26682
26684
  };
26683
26685
  if (writeImpl) {
26684
- stream.write = (data2, _encoding, callback) => {
26685
- const result = writeImpl(typeof data2 === "string" ? data2 : data2.toString());
26686
+ stream.write = (data2, ...rest) => {
26687
+ const result = writeImpl(textOf(data2));
26688
+ const callback = trailingCallback(rest);
26686
26689
  if (callback) queueMicrotask(callback);
26687
26690
  return result;
26688
26691
  };
26692
+ stream.end = (...args) => {
26693
+ const data2 = args[0];
26694
+ if (typeof data2 === "string" || data2 instanceof Uint8Array) writeImpl(textOf(data2));
26695
+ const callback = trailingCallback(args);
26696
+ if (callback) queueMicrotask(callback);
26697
+ };
26689
26698
  }
26690
26699
  return stream;
26691
26700
  }
26701
+ function textOf(data2) {
26702
+ return typeof data2 === "string" ? data2 : new TextDecoder().decode(data2);
26703
+ }
26704
+ function trailingCallback(args) {
26705
+ for (let index2 = args.length - 1; index2 >= 0; index2 -= 1) {
26706
+ const value = args[index2];
26707
+ if (typeof value === "function") return value;
26708
+ }
26709
+ return void 0;
26710
+ }
26692
26711
  const __substrateSignals = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGILL: 4, SIGTRAP: 5, SIGABRT: 6, SIGBUS: 7, SIGFPE: 8, SIGKILL: 9, SIGUSR1: 10, SIGSEGV: 11, SIGUSR2: 12, SIGPIPE: 13, SIGALRM: 14, SIGTERM: 15, SIGCHLD: 17, SIGCONT: 18, SIGSTOP: 19, SIGTSTP: 20, SIGTTIN: 21, SIGTTOU: 22, SIGURG: 23, SIGWINCH: 28 };
26693
26712
  const __substrateSignalNames = Object.fromEntries(Object.entries(__substrateSignals).map(([name, number]) => [number, name]));
26694
26713
  const __substrateBindingWarned = /* @__PURE__ */ new WeakSet();
@@ -15,5 +15,13 @@ export interface HttpClientExchangeResponse {
15
15
  export type HttpClientExchange = (request: HttpClientExchangeRequest) => Promise<HttpClientExchangeResponse>;
16
16
  /** Capture process attribution synchronously when the connection is requested. */
17
17
  export type HttpClientTransportFactory = () => HttpClientExchange;
18
+ export interface HttpClientTransportOptions {
19
+ /**
20
+ * Loopback ports the host itself serves (a service of the page, not a
21
+ * guest's listener). Plain HTTP to one of them goes through the host
22
+ * exchange; every other loopback port stays the engine's own network.
23
+ */
24
+ hostPorts?: () => ReadonlySet<number>;
25
+ }
18
26
  /** Host-only installation; guest modules receive Node's normal exports. */
19
- export declare function installHttpClientTransport(factory: HttpClientTransportFactory): () => void;
27
+ export declare function installHttpClientTransport(factory: HttpClientTransportFactory, transportOptions?: HttpClientTransportOptions): () => void;
package/dist/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export { createProcess } from './shims/process';
20
20
  export type { Process, ProcessEnv } from './shims/process';
21
21
  export * as path from './shims/path';
22
22
  export { httpModule as http, httpsModule as https } from './node-lib/http-module';
23
- export { installHttpClientTransport } from './http-client-transport';
23
+ export { installHttpClientTransport, type HttpClientTransportOptions } from './http-client-transport';
24
24
  export type { HttpClientExchange, HttpClientExchangeRequest, HttpClientExchangeResponse, HttpClientTransportFactory } from './http-client-transport';
25
25
  export { netModule as net } from './node-lib/net-module';
26
26
  export { eventsModule as events } from './node-lib/events-module';
package/dist/index.mjs CHANGED
@@ -26849,11 +26849,13 @@ function createProcessStream(isWritable, writeImpl) {
26849
26849
  return stream;
26850
26850
  },
26851
26851
  // Default write implementation (no-op for readable streams)
26852
- write(_data, _encoding, callback) {
26852
+ write(_data, ...rest) {
26853
+ const callback = trailingCallback(rest);
26853
26854
  if (callback) queueMicrotask(callback);
26854
26855
  return true;
26855
26856
  },
26856
- end(_data, callback) {
26857
+ end(...rest) {
26858
+ const callback = trailingCallback(rest);
26857
26859
  if (callback) queueMicrotask(callback);
26858
26860
  },
26859
26861
  pipe(destination) {
@@ -26869,14 +26871,31 @@ function createProcessStream(isWritable, writeImpl) {
26869
26871
  }
26870
26872
  };
26871
26873
  if (writeImpl) {
26872
- stream.write = (data2, _encoding, callback) => {
26873
- const result = writeImpl(typeof data2 === "string" ? data2 : data2.toString());
26874
+ stream.write = (data2, ...rest) => {
26875
+ const result = writeImpl(textOf(data2));
26876
+ const callback = trailingCallback(rest);
26874
26877
  if (callback) queueMicrotask(callback);
26875
26878
  return result;
26876
26879
  };
26880
+ stream.end = (...args) => {
26881
+ const data2 = args[0];
26882
+ if (typeof data2 === "string" || data2 instanceof Uint8Array) writeImpl(textOf(data2));
26883
+ const callback = trailingCallback(args);
26884
+ if (callback) queueMicrotask(callback);
26885
+ };
26877
26886
  }
26878
26887
  return stream;
26879
26888
  }
26889
+ function textOf(data2) {
26890
+ return typeof data2 === "string" ? data2 : new TextDecoder().decode(data2);
26891
+ }
26892
+ function trailingCallback(args) {
26893
+ for (let index2 = args.length - 1; index2 >= 0; index2 -= 1) {
26894
+ const value = args[index2];
26895
+ if (typeof value === "function") return value;
26896
+ }
26897
+ return void 0;
26898
+ }
26880
26899
  const __substrateSignals = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGILL: 4, SIGTRAP: 5, SIGABRT: 6, SIGBUS: 7, SIGFPE: 8, SIGKILL: 9, SIGUSR1: 10, SIGSEGV: 11, SIGUSR2: 12, SIGPIPE: 13, SIGALRM: 14, SIGTERM: 15, SIGCHLD: 17, SIGCONT: 18, SIGSTOP: 19, SIGTSTP: 20, SIGTTIN: 21, SIGTTOU: 22, SIGURG: 23, SIGWINCH: 28 };
26881
26900
  const __substrateSignalNames = Object.fromEntries(Object.entries(__substrateSignals).map(([name, number]) => [number, name]));
26882
26901
  const __substrateBindingWarned = /* @__PURE__ */ new WeakSet();
@@ -35709,7 +35728,7 @@ class WorkerRuntime {
35709
35728
  this.worker = new Worker(
35710
35729
  new URL(
35711
35730
  /* @vite-ignore */
35712
- "/assets/runtime-worker-CezP_cM0.js",
35731
+ "/assets/runtime-worker-C5pP4aT7.js",
35713
35732
  import.meta.url
35714
35733
  ),
35715
35734
  { type: "module" }
@@ -35927,7 +35946,7 @@ class DuplexStreamHandle extends LibuvStreamWrap {
35927
35946
  const unsupported = (detail) => Object.assign(new Error(`HTTP transport does not support ${detail}.`), { code: "ERR_HTTP_TRANSPORT_UNSUPPORTED" });
35928
35947
  const local = (host2) => host2 === "localhost" || host2 === "::1" || host2 === "[::1]" || /^127\./u.test(host2);
35929
35948
  const tlsOptions = ["ca", "cert", "key", "pfx", "passphrase", "ciphers", "secureContext", "checkServerIdentity", "minVersion", "maxVersion", "secureProtocol", "secureOptions", "session", "ALPNProtocols", "pskCallback"];
35930
- function installHttpClientTransport(factory) {
35949
+ function installHttpClientTransport(factory, transportOptions = {}) {
35931
35950
  const installed2 = /* @__PURE__ */ new WeakMap();
35932
35951
  const live = /* @__PURE__ */ new Set();
35933
35952
  const collected = new FinalizationRegistry((ref2) => live.delete(ref2));
@@ -35936,11 +35955,14 @@ function installHttpClientTransport(factory) {
35936
35955
  if (installed2.has(prototype)) return;
35937
35956
  const original = prototype.createConnection;
35938
35957
  const connect2 = function(options, callback) {
35958
+ var _a2;
35939
35959
  const host2 = String(options.hostname ?? options.host ?? "localhost").toLowerCase();
35940
- if (protocol === "http:" && (local(host2) || options.socketPath)) return original.call(this, options, callback);
35960
+ if (protocol === "http:" && (local(host2) || options.socketPath) && !(local(host2) && !options.socketPath && ((_a2 = transportOptions.hostPorts) == null ? void 0 : _a2.call(transportOptions).has(Number(options.port ?? 80))))) {
35961
+ return original.call(this, options, callback);
35962
+ }
35941
35963
  try {
35942
35964
  if (options.socketPath || options.localAddress || options.localPort || options.lookup || options.family) throw unsupported("custom socket routing");
35943
- if (tlsOptions.some((key) => options[key] !== void 0) || options.rejectUnauthorized === false || options.servername !== void 0 && options.servername !== host2) throw unsupported("custom TLS options");
35965
+ if (protocol === "https:" && (tlsOptions.some((key) => options[key] !== void 0) || options.rejectUnauthorized === false || options.servername !== void 0 && options.servername !== host2)) throw unsupported("custom TLS options");
35944
35966
  const authority = new URL(`${protocol}//${host2.includes(":") && !host2.startsWith("[") ? `[${host2}]` : host2}:${options.port ?? (protocol === "https:" ? 443 : 80)}`);
35945
35967
  return connection(authority, factory(), require2);
35946
35968
  } catch (cause) {
@@ -42,8 +42,8 @@ interface ProcessStream {
42
42
  getColorDepth: () => number;
43
43
  }
44
44
  interface ProcessWritableStream extends ProcessStream {
45
- write: (data: string | Buffer, encoding?: string, callback?: () => void) => boolean;
46
- end?: (data?: string, callback?: () => void) => void;
45
+ write: (data: string | Buffer, ...rest: unknown[]) => boolean;
46
+ end?: (...args: unknown[]) => void;
47
47
  }
48
48
  /**
49
49
  * `process.stdin` is a readable stream on Node -- a `net.Socket` when fd 0 is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/tabnode",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "Node's own library, in a browser tab.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,8 +33,17 @@ const unsupported = (detail: string): Error => Object.assign(new Error(`HTTP tra
33
33
  const local = (host: string): boolean => host === 'localhost' || host === '::1' || host === '[::1]' || /^127\./u.test(host);
34
34
  const tlsOptions = ['ca', 'cert', 'key', 'pfx', 'passphrase', 'ciphers', 'secureContext', 'checkServerIdentity', 'minVersion', 'maxVersion', 'secureProtocol', 'secureOptions', 'session', 'ALPNProtocols', 'pskCallback'];
35
35
 
36
+ export interface HttpClientTransportOptions {
37
+ /**
38
+ * Loopback ports the host itself serves (a service of the page, not a
39
+ * guest's listener). Plain HTTP to one of them goes through the host
40
+ * exchange; every other loopback port stays the engine's own network.
41
+ */
42
+ hostPorts?: () => ReadonlySet<number>;
43
+ }
44
+
36
45
  /** Host-only installation; guest modules receive Node's normal exports. */
37
- export function installHttpClientTransport(factory: HttpClientTransportFactory): () => void {
46
+ export function installHttpClientTransport(factory: HttpClientTransportFactory, transportOptions: HttpClientTransportOptions = {}): () => void {
38
47
  type AgentPrototype = { createConnection: (...args: any[]) => any };
39
48
  const installed = new WeakMap<AgentPrototype, { original: AgentPrototype['createConnection']; connect: AgentPrototype['createConnection'] }>();
40
49
  const live = new Set<WeakRef<AgentPrototype>>();
@@ -45,12 +54,16 @@ export function installHttpClientTransport(factory: HttpClientTransportFactory):
45
54
  const original = prototype.createConnection;
46
55
  const connect = function(this: unknown, options: Record<string, any>, callback: (error: Error | null, socket?: unknown) => void): unknown {
47
56
  const host = String(options.hostname ?? options.host ?? 'localhost').toLowerCase();
48
- // Plain local HTTP is the engine's existing virtual network.
49
- if (protocol === 'http:' && (local(host) || options.socketPath)) return original.call(this, options, callback);
57
+ // Plain local HTTP is the engine's existing virtual network, except a port the host serves itself.
58
+ if (protocol === 'http:' && (local(host) || options.socketPath)
59
+ && !(local(host) && !options.socketPath && transportOptions.hostPorts?.().has(Number(options.port ?? 80)))) {
60
+ return original.call(this, options, callback);
61
+ }
50
62
  try {
51
63
  if (options.socketPath || options.localAddress || options.localPort || options.lookup || options.family) throw unsupported('custom socket routing');
52
- if (tlsOptions.some(key => options[key] !== undefined) || options.rejectUnauthorized === false
53
- || (options.servername !== undefined && options.servername !== host)) throw unsupported('custom TLS options');
64
+ // Node's Agent names a servername for plain HTTP too ('' for an IP); TLS options are an https question.
65
+ if (protocol === 'https:' && (tlsOptions.some(key => options[key] !== undefined) || options.rejectUnauthorized === false
66
+ || (options.servername !== undefined && options.servername !== host))) throw unsupported('custom TLS options');
54
67
  const authority = new URL(`${protocol}//${host.includes(':') && !host.startsWith('[') ? `[${host}]` : host}:${options.port ?? (protocol === 'https:' ? 443 : 80)}`);
55
68
  return connection(authority, factory(), require);
56
69
  } catch (cause) {
package/src/index.ts CHANGED
@@ -24,7 +24,7 @@ export { createProcess } from './shims/process';
24
24
  export type { Process, ProcessEnv } from './shims/process';
25
25
  export * as path from './shims/path';
26
26
  export { httpModule as http, httpsModule as https } from './node-lib/http-module';
27
- export { installHttpClientTransport } from './http-client-transport';
27
+ export { installHttpClientTransport, type HttpClientTransportOptions } from './http-client-transport';
28
28
  export type { HttpClientExchange, HttpClientExchangeRequest, HttpClientExchangeResponse, HttpClientTransportFactory } from './http-client-transport';
29
29
  import { __releaseOwnedServers, __ownedServerPorts } from './node-lib/net-module';
30
30
  export { netModule as net } from './node-lib/net-module';
@@ -60,8 +60,8 @@ interface ProcessStream {
60
60
  }
61
61
 
62
62
  interface ProcessWritableStream extends ProcessStream {
63
- write: (data: string | Buffer, encoding?: string, callback?: () => void) => boolean;
64
- end?: (data?: string, callback?: () => void) => void;
63
+ write: (data: string | Buffer, ...rest: unknown[]) => boolean;
64
+ end?: (...args: unknown[]) => void;
65
65
  }
66
66
 
67
67
  /**
@@ -302,11 +302,13 @@ function createProcessStream(
302
302
  return stream;
303
303
  },
304
304
  // Default write implementation (no-op for readable streams)
305
- write(_data: string | Buffer, _encoding?: string, callback?: () => void) {
305
+ write(_data: string | Buffer, ...rest: unknown[]) {
306
+ const callback = trailingCallback(rest);
306
307
  if (callback) queueMicrotask(callback);
307
308
  return true;
308
309
  },
309
- end(_data?: string, callback?: () => void) {
310
+ end(...rest: unknown[]) {
311
+ const callback = trailingCallback(rest);
310
312
  if (callback) queueMicrotask(callback);
311
313
  },
312
314
  pipe(destination: unknown) {
@@ -324,16 +326,42 @@ function createProcessStream(
324
326
 
325
327
  // Override write for actual writable streams
326
328
  if (isWritable && writeImpl) {
327
- stream.write = (data: string | Buffer, _encoding?: string, callback?: () => void) => {
328
- const result = writeImpl(typeof data === 'string' ? data : data.toString());
329
+ stream.write = (data: string | Buffer, ...rest: unknown[]) => {
330
+ const result = writeImpl(textOf(data));
331
+ const callback = trailingCallback(rest);
329
332
  if (callback) queueMicrotask(callback);
330
333
  return result;
331
334
  };
335
+ stream.end = (...args: unknown[]) => {
336
+ const data = args[0];
337
+ if (typeof data === 'string' || data instanceof Uint8Array) writeImpl(textOf(data));
338
+ const callback = trailingCallback(args);
339
+ if (callback) queueMicrotask(callback);
340
+ };
332
341
  }
333
342
 
334
343
  return stream;
335
344
  }
336
345
 
346
+ /** A chunk's text: bytes, a Buffer's or a plain Uint8Array's, are UTF-8. */
347
+ function textOf(data: string | Uint8Array): string {
348
+ return typeof data === 'string' ? data : new TextDecoder().decode(data);
349
+ }
350
+
351
+ /**
352
+ * Node's `write(chunk[, encoding][, callback])` and `end([chunk][, encoding][, callback])`:
353
+ * the callback is whichever argument is a function. `stdout.write('', done)`
354
+ * is how a program waits for its output to be flushed before it exits, and a
355
+ * callback read only from the third place never ran.
356
+ */
357
+ function trailingCallback(args: readonly unknown[]): (() => void) | undefined {
358
+ for (let index = args.length - 1; index >= 0; index -= 1) {
359
+ const value = args[index];
360
+ if (typeof value === 'function') return value as () => void;
361
+ }
362
+ return undefined;
363
+ }
364
+
337
365
  /** The signal numbers a guest sees, and the signals a tab must ignore. */
338
366
  const __substrateSignals: Record<string, number> = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGILL: 4, SIGTRAP: 5, SIGABRT: 6, SIGBUS: 7, SIGFPE: 8, SIGKILL: 9, SIGUSR1: 10, SIGSEGV: 11, SIGUSR2: 12, SIGPIPE: 13, SIGALRM: 14, SIGTERM: 15, SIGCHLD: 17, SIGCONT: 18, SIGSTOP: 19, SIGTSTP: 20, SIGTTIN: 21, SIGTTOU: 22, SIGURG: 23, SIGWINCH: 28 };
339
367
  const __substrateSignalNames: Record<number, string> = Object.fromEntries(Object.entries(__substrateSignals).map(([name, number]) => [number, name]));