@nimbus-sh/worker 0.6.0 → 0.7.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 (133) hide show
  1. package/README.md +2 -2
  2. package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
  3. package/dist/cirrus-npm-cjs.generated.js +1 -1
  4. package/dist/facets/cirrus-real.d.ts.map +1 -1
  5. package/dist/facets/cirrus-real.js +6 -5
  6. package/dist/facets/compose.d.ts +148 -0
  7. package/dist/facets/compose.d.ts.map +1 -0
  8. package/dist/facets/compose.js +146 -0
  9. package/dist/facets/durable-images.d.ts +9 -5
  10. package/dist/facets/durable-images.d.ts.map +1 -1
  11. package/dist/facets/durable-images.js +17 -7
  12. package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
  13. package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
  14. package/dist/facets/esbuild-bundle-pool.js +122 -0
  15. package/dist/facets/exec-telemetry.d.ts +8 -0
  16. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  17. package/dist/facets/manager.d.ts +240 -109
  18. package/dist/facets/manager.d.ts.map +1 -1
  19. package/dist/facets/manager.js +661 -337
  20. package/dist/facets/process.d.ts +20 -16
  21. package/dist/facets/process.d.ts.map +1 -1
  22. package/dist/facets/process.js +59 -28
  23. package/dist/facets/real-vite-fs-shim.js +2 -2
  24. package/dist/facets/vite-dev-server.d.ts +25 -47
  25. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  26. package/dist/facets/vite-dev-server.js +185 -219
  27. package/dist/facets/wasm-image-digest.d.ts +25 -0
  28. package/dist/facets/wasm-image-digest.d.ts.map +1 -0
  29. package/dist/facets/wasm-image-digest.js +25 -0
  30. package/dist/facets/wasm-swap-registry.d.ts +51 -92
  31. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  32. package/dist/facets/wasm-swap-registry.js +68 -227
  33. package/dist/git/network-facet.d.ts.map +1 -1
  34. package/dist/git/network-facet.js +6 -5
  35. package/dist/loaders/child-process/spawn-pool.d.ts +3 -2
  36. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  37. package/dist/loaders/child-process/spawn-pool.js +3 -2
  38. package/dist/loaders/generated-workers.d.ts +2 -2
  39. package/dist/loaders/generated-workers.d.ts.map +1 -1
  40. package/dist/loaders/generated-workers.js +3 -3
  41. package/dist/loaders/npm-resolve-preamble.d.ts +3 -6
  42. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  43. package/dist/loaders/npm-resolve-preamble.js +34 -108
  44. package/dist/node-shims-artifact.generated.js +3 -3
  45. package/dist/npm/install-batch-facet.d.ts +3 -2
  46. package/dist/npm/install-batch-facet.d.ts.map +1 -1
  47. package/dist/npm/install-batch-facet.js +45 -15
  48. package/dist/npm/installer.d.ts +22 -17
  49. package/dist/npm/installer.d.ts.map +1 -1
  50. package/dist/npm/installer.js +209 -193
  51. package/dist/npm/pre-bundle-facet.d.ts +1 -1
  52. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  53. package/dist/npm/pre-bundle-facet.js +1 -1
  54. package/dist/npm/resolve-facet.d.ts +6 -0
  55. package/dist/npm/resolve-facet.d.ts.map +1 -1
  56. package/dist/npm/resolve-one-facet.d.ts +21 -20
  57. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  58. package/dist/npm/resolve-one-facet.js +85 -84
  59. package/dist/npm/semver.d.ts +59 -0
  60. package/dist/npm/semver.d.ts.map +1 -0
  61. package/dist/npm/semver.js +226 -0
  62. package/dist/router/remote-api.js +31 -1
  63. package/dist/runtime/html-entrypoint.d.ts +7 -0
  64. package/dist/runtime/html-entrypoint.d.ts.map +1 -1
  65. package/dist/runtime/html-entrypoint.js +18 -2
  66. package/dist/runtime/node-runner.d.ts +3 -0
  67. package/dist/runtime/node-runner.d.ts.map +1 -1
  68. package/dist/runtime/node-runner.js +7 -0
  69. package/dist/runtime/node-shims.d.ts.map +1 -1
  70. package/dist/runtime/node-shims.js +305 -29
  71. package/dist/runtime/opencode-facet-runner.js +2 -2
  72. package/dist/session/helpers.d.ts +38 -0
  73. package/dist/session/helpers.d.ts.map +1 -1
  74. package/dist/session/helpers.js +76 -0
  75. package/dist/session/init-phases.d.ts +1 -1
  76. package/dist/session/init-phases.d.ts.map +1 -1
  77. package/dist/session/init-phases.js +2 -12
  78. package/dist/session/init.d.ts +15 -1
  79. package/dist/session/init.d.ts.map +1 -1
  80. package/dist/session/init.js +82 -603
  81. package/dist/session/nimbus-session.d.ts +56 -22
  82. package/dist/session/nimbus-session.d.ts.map +1 -1
  83. package/dist/session/nimbus-session.js +130 -101
  84. package/dist/session/npm-install-port.d.ts +16 -0
  85. package/dist/session/npm-install-port.d.ts.map +1 -0
  86. package/dist/session/npm-install-port.js +37 -0
  87. package/dist/session/port-capability.d.ts +44 -0
  88. package/dist/session/port-capability.d.ts.map +1 -1
  89. package/dist/session/port-capability.js +110 -0
  90. package/dist/session/programmatic.d.ts +31 -5
  91. package/dist/session/programmatic.d.ts.map +1 -1
  92. package/dist/session/programmatic.js +94 -68
  93. package/dist/session/routes.d.ts +30 -17
  94. package/dist/session/routes.d.ts.map +1 -1
  95. package/dist/session/routes.js +42 -131
  96. package/dist/session/rpc.d.ts +15 -15
  97. package/dist/session/rpc.d.ts.map +1 -1
  98. package/dist/session/rpc.js +97 -47
  99. package/dist/session/serving-port.d.ts +27 -0
  100. package/dist/session/serving-port.d.ts.map +1 -0
  101. package/dist/session/serving-port.js +27 -0
  102. package/dist/session/start-real-vite.d.ts +12 -0
  103. package/dist/session/start-real-vite.d.ts.map +1 -1
  104. package/dist/session/start-real-vite.js +4 -4
  105. package/dist/session/supervisor-op.d.ts +2 -2
  106. package/dist/session/supervisor-op.d.ts.map +1 -1
  107. package/dist/session/supervisor-op.js +13 -7
  108. package/dist/session/supervisor-rpc.d.ts +7 -7
  109. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  110. package/dist/session/supervisor-rpc.js +4 -0
  111. package/dist/session/vite-command.d.ts +18 -0
  112. package/dist/session/vite-command.d.ts.map +1 -0
  113. package/dist/session/vite-command.js +609 -0
  114. package/dist/session/ws.d.ts +61 -0
  115. package/dist/session/ws.d.ts.map +1 -1
  116. package/dist/session/ws.js +122 -12
  117. package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
  118. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  119. package/dist/shell/npm-bin-entrypoints.js +12 -85
  120. package/package.json +24 -4
  121. package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
  122. package/public/index.html +1 -1
  123. package/scripts/bundle-facet-workers.mjs +1 -1
  124. package/scripts/bundle-npm-cjs.mjs +2 -2
  125. package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
  126. package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
  127. package/dist/facets/on-demand-bundle-gate.js +0 -125
  128. package/dist/npm/install-args.d.ts +0 -21
  129. package/dist/npm/install-args.d.ts.map +0 -1
  130. package/dist/npm/install-args.js +0 -70
  131. package/dist/npm/npm-log.d.ts +0 -31
  132. package/dist/npm/npm-log.d.ts.map +0 -1
  133. package/dist/npm/npm-log.js +0 -51
@@ -58,6 +58,109 @@ async function __nimbusUseRpcResultUnref(promise, use) {
58
58
  finally { __nimbusDisposeRpcResult(value); }
59
59
  }
60
60
 
61
+ // ═══════════════════════════════════════════════════════════════════════
62
+ // ── Precompiled wasm ───────────────────────────────────────────────
63
+ // A wasm image can only become a WebAssembly.Module through the Worker
64
+ // Loader's module map; new WebAssembly.Module(bytes) at request time is
65
+ // refused by the runtime. A launch whose closure carries an image (its VFS
66
+ // path, or its content digest for an image inlined as base64) gets it
67
+ // compiled at load and parked here. fs.readFileSync tags the bytes it hands
68
+ // out for such a path, and the WebAssembly seam below answers a compile of
69
+ // tagged or digest-matched bytes with the module the loader already built —
70
+ // so a package's own new WebAssembly.Module(readFileSync(__dirname + '/x.wasm'))
71
+ // works unchanged.
72
+ const __nimbusPrecompiledWasm = globalThis.__nimbusPrecompiledWasm instanceof Map
73
+ ? globalThis.__nimbusPrecompiledWasm : new Map();
74
+ const __nimbusWasmModuleTag = Symbol.for("nimbus.precompiledWasmModule");
75
+ /**
76
+ * Precompiled modules keyed by a digest of their BYTES, for an image that
77
+ * never passes through the filesystem.
78
+ *
79
+ * Vite inlines es-module-lexer's parser as a base64 literal in its own source
80
+ * and compiles it at module top level — from a cell that is request time, and
81
+ * the runtime refuses it. There is no path to tag, so the launch registers
82
+ * the image by content instead and the seam recognises the same bytes when
83
+ * they arrive.
84
+ */
85
+ const __nimbusPrecompiledWasmByDigest = globalThis.__nimbusPrecompiledWasmByDigest instanceof Map
86
+ ? globalThis.__nimbusPrecompiledWasmByDigest : new Map();
87
+ /**
88
+ * A synchronous content key: length and FNV-1a over every byte.
89
+ *
90
+ * Synchronous because new WebAssembly.Module(bytes) is, and SubtleCrypto is
91
+ * not. Collisions do not matter for correctness the way they would in a
92
+ * security check: the set is the handful of images one launch registered, and
93
+ * the length is part of the key.
94
+ */
95
+ function __nimbusWasmDigest(bytes) {
96
+ const view = bytes instanceof Uint8Array
97
+ ? bytes
98
+ : (bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : null);
99
+ if (!view) return null;
100
+ let hash = 0x811c9dc5;
101
+ for (let i = 0; i < view.length; i++) {
102
+ hash ^= view[i];
103
+ hash = Math.imul(hash, 0x01000193) >>> 0;
104
+ }
105
+ return view.length + ":" + hash.toString(16);
106
+ }
107
+ (() => {
108
+ const WA = globalThis.WebAssembly;
109
+ if (!WA || WA.__nimbusPrecompiledSeam) return;
110
+ const RealModule = WA.Module;
111
+ const tagged = (bytes) => {
112
+ if (!bytes || typeof bytes !== "object") return undefined;
113
+ const byTag = bytes[__nimbusWasmModuleTag];
114
+ if (byTag !== undefined) return byTag;
115
+ if (__nimbusPrecompiledWasmByDigest.size === 0) return undefined;
116
+ const digest = __nimbusWasmDigest(bytes);
117
+ return digest === null ? undefined : __nimbusPrecompiledWasmByDigest.get(digest);
118
+ };
119
+ // The runtime compiles wasm only while the loader stages a module map; a
120
+ // compile from bytes at any later point is refused with a message that names
121
+ // neither the module nor the reason it cannot work. Say both: the caller is
122
+ // an installed package whose image has to travel as a map member (the
123
+ // closure walk registers it), or be inlined in module text the loader
124
+ // itself evaluates.
125
+ const refusal = (e, bytes) => {
126
+ const size = (bytes && typeof bytes === "object" && typeof bytes.byteLength === "number") ? bytes.byteLength : 0;
127
+ const where = globalThis.__currentModulePath ? " while loading " + globalThis.__currentModulePath : "";
128
+ return new Error(
129
+ "Nimbus: WebAssembly cannot be compiled from bytes here" + where + " (" + size + " bytes): "
130
+ + ((e && e.message) || String(e))
131
+ + ". The runtime compiles wasm only when the module loader stages it, so the image must ride in the "
132
+ + "process's module map — a launch names one via the closure's wasmImages — rather than be compiled at runtime."
133
+ + " Images this launch does carry: " + (__nimbusPrecompiledWasm.size + __nimbusPrecompiledWasmByDigest.size) + ".",
134
+ );
135
+ };
136
+ const Module = function Module(bytes) {
137
+ const compiled = tagged(bytes);
138
+ if (compiled !== undefined) return compiled;
139
+ try { return new RealModule(bytes); } catch (e) { throw refusal(e, bytes); }
140
+ };
141
+ Module.prototype = RealModule.prototype;
142
+ for (const k of ["exports", "imports", "customSections"]) Module[k] = RealModule[k];
143
+ Object.defineProperty(WA, "Module", { value: Module, writable: true, configurable: true });
144
+ const realCompile = WA.compile.bind(WA);
145
+ WA.compile = (bytes) => {
146
+ const compiled = tagged(bytes);
147
+ if (compiled !== undefined) return Promise.resolve(compiled);
148
+ return realCompile(bytes).catch((e) => { throw refusal(e, bytes); });
149
+ };
150
+ const realInstantiate = WA.instantiate.bind(WA);
151
+ WA.instantiate = (source, imports) => {
152
+ const compiled = tagged(source);
153
+ if (compiled !== undefined) {
154
+ return realInstantiate(compiled, imports).then((instance) => ({ module: compiled, instance }));
155
+ }
156
+ // A Module source instantiates; only BYTES are a compile, and only those
157
+ // can be refused for it.
158
+ if (source instanceof RealModule) return realInstantiate(source, imports);
159
+ return realInstantiate(source, imports).catch((e) => { throw refusal(e, source); });
160
+ };
161
+ WA.__nimbusPrecompiledSeam = true;
162
+ })();
163
+
61
164
  // ═══════════════════════════════════════════════════════════════════════
62
165
  // ── fetch default User-Agent ───────────────────────────────────────
63
166
  // workerd's global fetch sends no User-Agent by default, but Node's
@@ -405,6 +508,33 @@ const __BufferMod = (() => {
405
508
  return B;
406
509
  })();
407
510
 
511
+ // ═══════════════════════════════════════════════════════════════════════
512
+ // ── Process output is bytes ─────────────────────────────────────────
513
+ // ═══════════════════════════════════════════════════════════════════════
514
+ // A process's stdout and stderr are byte streams: esbuild's service protocol
515
+ // is binary packets, and so is any program piping an image or an archive.
516
+ // The relay to the supervisor carries Uint8Array; a text producer encodes
517
+ // at its own edge, and the facet's REPORTED result — the `stdout`/`stderr`
518
+ // strings the wrapper declares — decodes at its edge with one streaming
519
+ // decoder per stream, so a multibyte character split across two writes
520
+ // still reads as one character.
521
+ const __nimbusOutEnc = new TextEncoder();
522
+ const __nimbusOutDec = { stdout: new TextDecoder("utf-8"), stderr: new TextDecoder("utf-8") };
523
+ /** `process.stdout.write(d, enc)` payload as bytes. */
524
+ function __nimbusOutBytes(d, enc) {
525
+ if (d instanceof Uint8Array) return d;
526
+ if (typeof d === "string") {
527
+ return typeof enc === "string" && enc !== "utf8" && enc !== "utf-8"
528
+ ? __BufferMod.from(d, enc)
529
+ : __nimbusOutEnc.encode(d);
530
+ }
531
+ return __nimbusOutEnc.encode(String(d));
532
+ }
533
+ /** Decode one stream's bytes into its text accumulator, streaming. */
534
+ function __nimbusOutText(streamName, bytes) {
535
+ return __nimbusOutDec[streamName === "stderr" ? "stderr" : "stdout"].decode(bytes, { stream: true });
536
+ }
537
+
408
538
  /**
409
539
  * What the resident set holds under a directory prefix — the ONE question the
410
540
  * shims ask of it that a plain object cannot answer cheaply.
@@ -2274,8 +2404,14 @@ const __fsMod = (() => {
2274
2404
  return _asString(content);
2275
2405
  }
2276
2406
  // No encoding requested — produce a Buffer-shaped Uint8Array.
2277
- if (_isBytes(content)) return __BufferMod.from(content);
2278
- return __BufferMod.from(content);
2407
+ const bytes = __BufferMod.from(content);
2408
+ // A wasm image the launch compiled through the module map is tagged on
2409
+ // the way out, so the WebAssembly seam below can answer the package's own
2410
+ // new WebAssembly.Module(readFileSync(...)) with the compiled module —
2411
+ // request-time compilation from bytes is refused by the runtime.
2412
+ const precompiled = __nimbusPrecompiledWasm.get(_strip(absPath));
2413
+ if (precompiled !== undefined) bytes[__nimbusWasmModuleTag] = precompiled;
2414
+ return bytes;
2279
2415
  }
2280
2416
 
2281
2417
  // ── writeFileSync ──
@@ -3036,9 +3172,8 @@ const __fsMod = (() => {
3036
3172
  function writeSync(fd, data, a, b, c) {
3037
3173
  const n = Number(fd);
3038
3174
  if (n === 1 || n === 2) {
3039
- // The stream shim stringifies whatever it is given, so decode first.
3040
3175
  const bytes = _normWriteArgs(data, a, b, c).bytes;
3041
- (n === 2 ? __processMod.stderr : __processMod.stdout).write(_dec.decode(bytes));
3176
+ (n === 2 ? __processMod.stderr : __processMod.stdout).write(bytes);
3042
3177
  return bytes.byteLength;
3043
3178
  }
3044
3179
  if (n === 0) throw _fsErr("EBADF", "write", fd);
@@ -5483,6 +5618,106 @@ const __utilMod = {
5483
5618
  }
5484
5619
  return opens + String(text) + closes;
5485
5620
  },
5621
+ // util.parseArgs({ args, options, strict, allowPositionals, allowNegative })
5622
+ // — Node 18.3+. The CLI argument parser modern npm bins reach for instead
5623
+ // of a dependency: json-server's lib/bin.js destructures it at module
5624
+ // init, so its absence crashed the bin at "parseArgs is not a function"
5625
+ // before --version could answer. Node's contract, minus the tokens
5626
+ // debugging output:
5627
+ // - --name, --name=value, --name value for string options;
5628
+ // - -s, -s value, -svalue, and grouped booleans -abc for shorts;
5629
+ // - --no-name sets a boolean false when allowNegative is on;
5630
+ // - -- ends option parsing, the rest are positionals;
5631
+ // - strict (default true) throws Node's own error codes for an unknown
5632
+ // option, a string option with no value, or a positional when they
5633
+ // are not allowed; lax mode records unknown options as booleans.
5634
+ parseArgs: (config) => {
5635
+ const cfg = config || {};
5636
+ const args = Array.isArray(cfg.args) ? cfg.args.slice() : (__processMod.argv || []).slice(2);
5637
+ const options = cfg.options || {};
5638
+ const strict = cfg.strict !== false;
5639
+ const allowPositionals = cfg.allowPositionals === undefined ? !strict : !!cfg.allowPositionals;
5640
+ const allowNegative = !!cfg.allowNegative;
5641
+ const values = {};
5642
+ const positionals = [];
5643
+ const err = (code, message) => { const e = new TypeError(message); e.code = code; return e; };
5644
+ const shortToLong = {};
5645
+ for (const [name, spec] of Object.entries(options)) {
5646
+ if (!spec || (spec.type !== "string" && spec.type !== "boolean")) {
5647
+ throw err("ERR_INVALID_ARG_TYPE", "The \"options." + name + ".type\" property must be one of: 'string', 'boolean'.");
5648
+ }
5649
+ if (spec.short) shortToLong[spec.short] = name;
5650
+ if (spec.default !== undefined) values[name] = spec.default;
5651
+ }
5652
+ const store = (name, value) => {
5653
+ const spec = options[name];
5654
+ if (spec && spec.multiple) {
5655
+ if (!Array.isArray(values[name]) || (spec.default !== undefined && values[name] === spec.default)) values[name] = [];
5656
+ values[name].push(value);
5657
+ } else {
5658
+ values[name] = value;
5659
+ }
5660
+ };
5661
+ const optionValue = (name, inlineValue, next, raw) => {
5662
+ const spec = options[name];
5663
+ if (!spec) {
5664
+ if (strict) throw err("ERR_PARSE_ARGS_UNKNOWN_OPTION", "Unknown option '" + raw + "'." + (allowPositionals ? " To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- \"" + raw + "\"'." : ""));
5665
+ if (inlineValue !== undefined) return { value: inlineValue, consumed: 0 };
5666
+ return { value: true, consumed: 0 };
5667
+ }
5668
+ if (spec.type === "boolean") {
5669
+ if (inlineValue !== undefined && strict) throw err("ERR_PARSE_ARGS_INVALID_OPTION_VALUE", "Option '" + raw + "' does not take an argument.");
5670
+ return { value: inlineValue !== undefined ? inlineValue : true, consumed: 0 };
5671
+ }
5672
+ if (inlineValue !== undefined) return { value: inlineValue, consumed: 0 };
5673
+ if (next === undefined || (strict && next.startsWith("-") && next !== "-")) {
5674
+ if (strict) throw err("ERR_PARSE_ARGS_INVALID_OPTION_VALUE", "Option '" + raw + " <value>' argument missing");
5675
+ return { value: undefined, consumed: 0 };
5676
+ }
5677
+ return { value: next, consumed: 1 };
5678
+ };
5679
+ for (let i = 0; i < args.length; i++) {
5680
+ const arg = args[i];
5681
+ if (arg === "--") { positionals.push(...args.slice(i + 1)); break; }
5682
+ if (arg.startsWith("--") && arg.length > 2) {
5683
+ const eq = arg.indexOf("=");
5684
+ let name = eq === -1 ? arg.slice(2) : arg.slice(2, eq);
5685
+ const inline = eq === -1 ? undefined : arg.slice(eq + 1);
5686
+ if (allowNegative && name.startsWith("no-") && options[name.slice(3)] && options[name.slice(3)].type === "boolean") {
5687
+ store(name.slice(3), false);
5688
+ continue;
5689
+ }
5690
+ const r = optionValue(name, inline, args[i + 1], "--" + name);
5691
+ store(name, r.value);
5692
+ i += r.consumed;
5693
+ continue;
5694
+ }
5695
+ if (arg.startsWith("-") && arg.length > 1 && arg !== "-") {
5696
+ // Short: -s, -s value, -svalue (string) or grouped -abc (booleans).
5697
+ const first = arg[1];
5698
+ const long = shortToLong[first] || first;
5699
+ const spec = options[long];
5700
+ if (spec && spec.type === "string") {
5701
+ const inline = arg.length > 2 ? arg.slice(2) : undefined;
5702
+ const r = optionValue(long, inline, args[i + 1], "-" + first);
5703
+ store(long, r.value);
5704
+ i += r.consumed;
5705
+ continue;
5706
+ }
5707
+ for (const ch of arg.slice(1)) {
5708
+ const l = shortToLong[ch] || ch;
5709
+ const r = optionValue(l, undefined, undefined, "-" + ch);
5710
+ store(l, r.value);
5711
+ }
5712
+ continue;
5713
+ }
5714
+ if (!allowPositionals) {
5715
+ throw err("ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL", "Unexpected argument '" + arg + "'. This command does not take positional arguments");
5716
+ }
5717
+ positionals.push(arg);
5718
+ }
5719
+ return { values, positionals };
5720
+ },
5486
5721
  };
5487
5722
 
5488
5723
  // ═══════════════════════════════════════════════════════════════════════
@@ -5919,27 +6154,34 @@ const __childProcessMod = (() => {
5919
6154
  const HAS_SUPERVISOR = !!(__supervisor && typeof __supervisor.cpSpawn === "function");
5920
6155
 
5921
6156
  /**
5922
- * Child stdout/stderr. Defaults to utf8 so consumers see strings (the
5923
- * common cross-spawn / husky pattern); callers override via
5924
- * .setEncoding('hex'), .setEncoding(null), etc. Flowing-mode resumption
5925
- * and encoding are the Readable base class's job — see streams.ts.
6157
+ * Child stdout/stderr. Bytes, as Node's: a 'data' listener sees a Buffer
6158
+ * until the consumer calls .setEncoding(), which is how a binary protocol
6159
+ * (esbuild's service) reads its packets and how a text consumer opts into
6160
+ * text. It used to default to utf8 for the cross-spawn / husky pattern;
6161
+ * that pattern reads `String(chunk)` and works on a Buffer, and the
6162
+ * default turned every byte above 0x7f into U+FFFD for everyone else.
6163
+ * Flowing-mode resumption and encoding are the Readable base class's job —
6164
+ * see streams.ts.
5926
6165
  */
5927
6166
  function _makeReadable() {
5928
- return new __streamMod.PassThrough({ encoding: "utf8" });
6167
+ return new __streamMod.PassThrough();
5929
6168
  }
5930
6169
 
5931
6170
  /**
5932
6171
  * Create a workerd-Writable backed by cpStdinWrite RPC.
5933
- * Decodes Uint8Array chunks to UTF-8 strings before pushing to RPC
5934
- * (workerd's Writable encodes string→bytes internally; we need to
5935
- * round-trip back to a string for the supervisor's stdin queue).
6172
+ *
6173
+ * A child's stdin is BYTES. esbuild's service protocol is binary packets,
6174
+ * and so is anything piping an image or an archive to a child. The relay
6175
+ * used to decode each chunk to a UTF-8 string here, which turned every
6176
+ * byte sequence that is not valid UTF-8 into U+FFFD — unrecoverable, and
6177
+ * measured at twice the length for a buffer covering all 256 values. The
6178
+ * queue and the RPC carry Uint8Array now; text callers encode at this
6179
+ * edge, which is the only place that knows it had text.
5936
6180
  */
5937
- function _toUtf8(chunk) {
5938
- if (typeof chunk === "string") return chunk;
5939
- if (chunk instanceof Uint8Array) {
5940
- try { return new TextDecoder("utf-8").decode(chunk); } catch { return String(chunk); }
5941
- }
5942
- return String(chunk);
6181
+ function _toBytes(chunk) {
6182
+ if (chunk instanceof Uint8Array) return chunk;
6183
+ if (typeof chunk === "string") return new TextEncoder().encode(chunk);
6184
+ return new TextEncoder().encode(String(chunk));
5943
6185
  }
5944
6186
  function _queueStdinWrite(child, data) {
5945
6187
  if (!child.pid) {
@@ -5971,8 +6213,7 @@ const __childProcessMod = (() => {
5971
6213
  function _makeWritable(child) {
5972
6214
  const w = new __streamMod.Writable({
5973
6215
  write(chunk, enc, cb) {
5974
- const s = _toUtf8(chunk);
5975
- _queueStdinWrite(child, s)
6216
+ _queueStdinWrite(child, _toBytes(chunk))
5976
6217
  .then(() => cb())
5977
6218
  .catch((e) => cb(e));
5978
6219
  },
@@ -6120,7 +6361,9 @@ const __childProcessMod = (() => {
6120
6361
  if (r && Array.isArray(r.chunks) && r.chunks.length > 0) {
6121
6362
  backoff = 100; // reset — child is producing
6122
6363
  for (const c of r.chunks) {
6123
- stream.write(c.data);
6364
+ // The queue hands back bytes; a Readable given a string would
6365
+ // encode it again.
6366
+ stream.write(__BufferMod.from(c.data));
6124
6367
  if (typeof c.seq === "number" && c.seq > sinceSeqRef.value) {
6125
6368
  sinceSeqRef.value = c.seq;
6126
6369
  }
@@ -6489,11 +6732,11 @@ const __childProcessMod = (() => {
6489
6732
  __supervisor.cpDrainOutput(pid),
6490
6733
  (result) => result,
6491
6734
  );
6492
- if (r && r.stdout && child.stdout) {
6493
- try { child.stdout.write(r.stdout); } catch {}
6735
+ if (r && r.stdout && r.stdout.byteLength > 0 && child.stdout) {
6736
+ try { child.stdout.write(__BufferMod.from(r.stdout)); } catch {}
6494
6737
  }
6495
- if (r && r.stderr && child.stderr) {
6496
- try { child.stderr.write(r.stderr); } catch {}
6738
+ if (r && r.stderr && r.stderr.byteLength > 0 && child.stderr) {
6739
+ try { child.stderr.write(__BufferMod.from(r.stderr)); } catch {}
6497
6740
  }
6498
6741
  // Force-close streams so listeners receive 'end'. The 'end'
6499
6742
  // event listeners in _makeChild flip _stdoutEnded/_stderrEnded.
@@ -6711,7 +6954,11 @@ function __makeProcessStdin() {
6711
6954
  throw new __ProcessExit(code);
6712
6955
  }
6713
6956
  }
6714
- if (packet && packet.data) r.write(packet.data);
6957
+ // The queue hands back bytes; a Readable given a string would encode
6958
+ // it again.
6959
+ if (packet && packet.data && packet.data.byteLength > 0) {
6960
+ r.write(__BufferMod.from(packet.data));
6961
+ }
6715
6962
  if (packet && packet.ended) {
6716
6963
  r.end();
6717
6964
  break;
@@ -6736,7 +6983,7 @@ function __makeProcessStdin() {
6736
6983
  }
6737
6984
  const trace = (e && e.stack) || (e && e.message) || String(e);
6738
6985
  stderr += trace + "\n";
6739
- try { __nimbusUseRpcResult(__supervisor.stderr(trace + "\n"), () => undefined).catch(() => {}); } catch {}
6986
+ try { __nimbusUseRpcResult(__supervisor.stderr(__nimbusOutEnc.encode(trace + "\n")), () => undefined).catch(() => {}); } catch {}
6740
6987
  try { __nimbusUseRpcResult(__supervisor.reportExit(1, trace + "\n"), () => undefined).catch(() => {}); } catch {}
6741
6988
  try { r.end(); } catch {}
6742
6989
  });
@@ -6807,7 +7054,8 @@ function __makeProcessOutputStream(streamName) {
6807
7054
  errored: null,
6808
7055
  write(d, enc, cb) {
6809
7056
  if (typeof enc === "function") cb = enc;
6810
- const s = String(d);
7057
+ // The reported result is text; decode the bytes at this edge only.
7058
+ const s = __nimbusOutText(streamName, __nimbusOutBytes(d, enc));
6811
7059
  if (streamName === "stderr") stderr += s;
6812
7060
  else stdout += s;
6813
7061
  if (typeof cb === "function") queueMicrotask(cb);
@@ -6998,7 +7246,7 @@ function __nimbusFailUnhandledAsync(error, kind) {
6998
7246
  const line = label + __nimbusRuntimeErrorTrace(error) + "\n";
6999
7247
  stderr += line;
7000
7248
  if (__supervisor && typeof __supervisor.stderr === "function") {
7001
- try { __nimbusUseRpcResult(__supervisor.stderr(line), () => undefined).catch(() => {}); } catch {}
7249
+ try { __nimbusUseRpcResult(__supervisor.stderr(__nimbusOutEnc.encode(line)), () => undefined).catch(() => {}); } catch {}
7002
7250
  }
7003
7251
  __nimbusReportProcessExit(1, line);
7004
7252
  }
@@ -8133,6 +8381,34 @@ builtins["node:util/types"] = builtins["util/types"];
8133
8381
  // skips it via the same FACET_PROVIDED_PACKAGES list.
8134
8382
  builtins.undici = __undiciMod;
8135
8383
 
8384
+ /**
8385
+ * A cell's dynamic import() call.
8386
+ *
8387
+ * A cell is compiled with new Function, so an import() left in its body
8388
+ * is the RUNTIME's: it resolves against the module map and hands back the
8389
+ * platform's own builtins, not this process's. Real Vite reaches
8390
+ * node:http that way (config.js:14968), got a server whose listen bound no
8391
+ * port here, and the facet exited with no handles the moment boot returned.
8392
+ *
8393
+ * The ESM→CJS rewriter routes those calls here with the cell's own
8394
+ * require, so resolution is the one the process already has. The result is
8395
+ * shaped as a module namespace, since import() resolves to one and callers
8396
+ * destructure named exports off it.
8397
+ */
8398
+ globalThis.__nimbusCellImport = (req, id) => Promise.resolve().then(() => {
8399
+ const loaded = req(id);
8400
+ if (loaded && (loaded.__esModule || loaded[Symbol.toStringTag] === "Module")) return loaded;
8401
+ // A CJS module's exports ARE the namespace's named exports, with the whole
8402
+ // object as the default export — what an ESM importer of a CJS module sees.
8403
+ if (loaded && (typeof loaded === "object" || typeof loaded === "function")) {
8404
+ const ns = Object.create(null);
8405
+ for (const key of Object.keys(loaded)) ns[key] = loaded[key];
8406
+ if (!("default" in ns)) ns.default = loaded;
8407
+ Object.defineProperty(ns, Symbol.toStringTag, { value: "Module" });
8408
+ return ns;
8409
+ }
8410
+ return { default: loaded };
8411
+ });
8136
8412
  // ═══════════════════════════════════════════════════════════════════════
8137
8413
  // ── require() — full Node.js module resolution ─────────────────────
8138
8414
  // ═══════════════════════════════════════════════════════════════════════
package/public/index.html CHANGED
@@ -677,7 +677,7 @@
677
677
  <div class="terminal-frame">
678
678
  <div class="terminal-chrome">
679
679
  <span class="tc-dot r"></span><span class="tc-dot y"></span><span class="tc-dot g"></span>
680
- <span class="tc-title">nimbus — ~/app</span>
680
+ <span class="tc-title">nimbus — ~/example-app</span>
681
681
  </div>
682
682
  <pre class="terminal-body" id="demo-body"></pre>
683
683
  </div>
@@ -297,7 +297,7 @@ async function main() {
297
297
  ' * helpers by name.',
298
298
  ' *',
299
299
  ' * Tar-stream symbols: parseTarHeader, streamTarEntries,',
300
- ' * readableStreamToAsyncIterable, MAX_FILE_BYTES.',
300
+ ' * streamPackageEntries, readableStreamToAsyncIterable, MAX_FILE_BYTES.',
301
301
  ' * W7-frame symbols: encodeWriteBatchStream, decodeWriteBatchStream,',
302
302
  ' * W7_MAGIC, W7_MAX_RECORD_BYTES.',
303
303
  ' *',
@@ -13,7 +13,7 @@
13
13
  * Solution: bundle the common CJS packages at build time into ESM
14
14
  * artifacts, emit them as LOADER modules alongside plugin-react,
15
15
  * and rewrite the Vite resolver's output so that
16
- * /home/user/app/node_modules/react/index.js
16
+ * /home/user/example-app/node_modules/react/index.js
17
17
  * maps to the pre-bundled
18
18
  * cirrus-npm/react.js
19
19
  * at facet load time.
@@ -350,7 +350,7 @@ async function main() {
350
350
  * (react, react-dom, scheduler). Ships as a static Worker asset alongside
351
351
  * cirrus-plugin-react.
352
352
  * Consumed by src/cirrus-real.ts — injected as LOADER modules, and
353
- * the Vite resolver's output (e.g. /home/user/app/node_modules/react/index.js)
353
+ * the Vite resolver's output (e.g. /home/user/example-app/node_modules/react/index.js)
354
354
  * is rewritten to point at one of these bundles at request time.
355
355
  */
356
356
 
@@ -1,65 +0,0 @@
1
- /**
2
- * OnDemandBundleGate — memory-bounded admission control for on-demand
3
- * /@modules/ bundling.
4
- *
5
- * Why this exists
6
- * ───────────────
7
- * The dev server bundles user packages on demand by building a file
8
- * "slice" in the supervisor heap (up to SLICE_CAP_BYTES ≈ 28 MiB) and
9
- * shipping it to a facet isolate over RPC. The facet RPC round-trip is
10
- * the dominant wall time; the supervisor just holds the slice array
11
- * alive until the clone completes. A fresh React app first-load requests
12
- * many distinct /@modules/ concurrently, so the naive path either:
13
- * - builds all slices at once → peak heap = N × 28 MiB → supervisor
14
- * OOM on a shared DO isolate (the install-time pre-bundler proved
15
- * concurrency=2 of max slices crashes a Mossaic-scale isolate), or
16
- * - serializes everything behind one slot → multi-second first load.
17
- *
18
- * This gate threads the needle: it bounds the TOTAL slice BYTES resident
19
- * at once (not a count), so many SMALL slices' RPC round-trips overlap
20
- * while a single LARGE slice still serializes the rest — peak resident
21
- * slice bytes never exceed `budgetBytes`, which is set to one slice cap.
22
- *
23
- * How it bounds peak heap
24
- * ───────────────────────
25
- * - Only ONE slice is ever mid-BUILD (a build lock): the slice array
26
- * does not exist until built, so we can't reserve its real size up
27
- * front. Serializing the (fast, synchronous) build means at most one
28
- * un-accounted slice exists at any instant.
29
- * - The moment a build finishes, the caller `admit(realBytes)`s: that
30
- * reserves the slice's actual size against the byte budget (blocking
31
- * if the budget is full) and only THEN releases the build lock for
32
- * the next builder.
33
- * - Reserved bytes are released when the caller's work (the facet
34
- * submit) settles.
35
- *
36
- * Invariant: at any instant, Σ(reserved bytes of in-flight submits) +
37
- * (one building slice, already counted the moment it admits) ≤
38
- * budgetBytes. With budgetBytes = SLICE_CAP_BYTES the peak matches the
39
- * single-slot serialization it replaces — no heap regression — while
40
- * small slices proceed concurrently.
41
- */
42
- export declare class OnDemandBundleGate {
43
- private readonly budgetBytes;
44
- private buildLock;
45
- private reservedBytes;
46
- /** FIFO queue of callers blocked on byte-budget headroom. */
47
- private byteWaiters;
48
- constructor(budgetBytes: number);
49
- /**
50
- * Run a build-then-submit job under the gate.
51
- *
52
- * `job` receives an `admit(bytes)` callback it MUST call exactly once,
53
- * after its slice is built and its real byte size is known, before the
54
- * long-running submit. `admit` reserves the bytes and releases the
55
- * build lock so the next job can start building. Jobs that bail before
56
- * building a slice (early return / error) simply never call `admit`;
57
- * the build lock is released when `job` settles either way.
58
- */
59
- run<T>(job: (admit: (bytes: number) => Promise<void>) => Promise<T>): Promise<T>;
60
- private acquireBytes;
61
- private releaseBytes;
62
- /** Test/diagnostic snapshot. */
63
- get inFlightBytes(): number;
64
- }
65
- //# sourceMappingURL=on-demand-bundle-gate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"on-demand-bundle-gate.d.ts","sourceRoot":"","sources":["../../src/facets/on-demand-bundle-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,kBAAkB;IAMjB,OAAO,CAAC,QAAQ,CAAC,WAAW;IALxC,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,aAAa,CAAK;IAC1B,6DAA6D;IAC7D,OAAO,CAAC,WAAW,CAAqD;gBAE3C,WAAW,EAAE,MAAM;IAIhD;;;;;;;;;OASG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA8BtF,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,YAAY;IAepB,gCAAgC;IAChC,IAAI,aAAa,IAAI,MAAM,CAA+B;CAC3D"}