@nimbus-sh/worker 0.12.0 → 0.13.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.
- package/dist/esbuild-cli-artifact.generated.d.ts +1 -1
- package/dist/esbuild-cli-artifact.generated.js +4 -4
- package/dist/esbuild-wasm-bundle.generated.d.ts +11 -10
- package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -1
- package/dist/esbuild-wasm-bundle.generated.js +11 -10
- package/dist/facets/build-facet.d.ts +53 -0
- package/dist/facets/build-facet.d.ts.map +1 -0
- package/dist/facets/build-facet.js +346 -0
- package/dist/facets/cirrus-real.d.ts +3 -0
- package/dist/facets/cirrus-real.d.ts.map +1 -1
- package/dist/facets/cirrus-real.js +1 -2
- package/dist/facets/compose.d.ts +1 -0
- package/dist/facets/compose.d.ts.map +1 -1
- package/dist/facets/compose.js +3 -0
- package/dist/facets/data-plan.d.ts +14 -30
- package/dist/facets/data-plan.d.ts.map +1 -1
- package/dist/facets/data-plan.js +153 -13
- package/dist/facets/dev-stylesheet.d.ts +27 -0
- package/dist/facets/dev-stylesheet.d.ts.map +1 -0
- package/dist/facets/dev-stylesheet.js +65 -0
- package/dist/facets/esbuild-transform.d.ts +23 -18
- package/dist/facets/esbuild-transform.d.ts.map +1 -1
- package/dist/facets/esbuild-transform.js +63 -109
- package/dist/facets/manager.d.ts +49 -9
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +238 -69
- package/dist/facets/oxc-transform.d.ts +29 -0
- package/dist/facets/oxc-transform.d.ts.map +1 -0
- package/dist/facets/oxc-transform.js +198 -0
- package/dist/facets/prebundle-pool.d.ts +23 -0
- package/dist/facets/prebundle-pool.d.ts.map +1 -0
- package/dist/facets/prebundle-pool.js +55 -0
- package/dist/facets/process.d.ts +13 -6
- package/dist/facets/process.d.ts.map +1 -1
- package/dist/facets/process.js +37 -31
- package/dist/facets/transform-store.d.ts +4 -4
- package/dist/facets/transform-store.js +4 -4
- package/dist/facets/vite-dev-server.d.ts +89 -12
- package/dist/facets/vite-dev-server.d.ts.map +1 -1
- package/dist/facets/vite-dev-server.js +66 -43
- package/dist/hosted/commands.d.ts.map +1 -1
- package/dist/hosted/commands.js +20 -4
- package/dist/hosted/runtime.d.ts.map +1 -1
- package/dist/hosted/runtime.js +7 -2
- package/dist/hosted/services.d.ts +3 -3
- package/dist/hosted/services.d.ts.map +1 -1
- package/dist/hosted/services.js +102 -95
- package/dist/hosted/session.d.ts +1 -0
- package/dist/hosted/session.d.ts.map +1 -1
- package/dist/loaders/generated-workers.d.ts +3 -0
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +3 -0
- package/dist/napi-wasm-artifacts.generated.js +2 -2
- package/dist/node-shims-artifact.generated.d.ts +14 -1
- package/dist/node-shims-artifact.generated.d.ts.map +1 -1
- package/dist/node-shims-artifact.generated.js +23 -10
- package/dist/npm/bin-links.d.ts +7 -4
- package/dist/npm/bin-links.d.ts.map +1 -1
- package/dist/npm/bin-links.js +14 -55
- package/dist/npm/cache.d.ts +6 -0
- package/dist/npm/cache.d.ts.map +1 -1
- package/dist/npm/cache.js +26 -4
- package/dist/npm/installer.d.ts +1 -1
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +26 -52
- package/dist/npm/pre-bundle-facet.d.ts +15 -117
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
- package/dist/npm/pre-bundle-facet.js +13 -511
- package/dist/oxc-facet-artifact.generated.d.ts +18 -0
- package/dist/oxc-facet-artifact.generated.d.ts.map +1 -0
- package/dist/oxc-facet-artifact.generated.js +17 -0
- package/dist/oxc-wasm-artifact.generated.d.ts +20 -0
- package/dist/oxc-wasm-artifact.generated.d.ts.map +1 -0
- package/dist/oxc-wasm-artifact.generated.js +19 -0
- package/dist/rolldown-facet-artifact.generated.d.ts +18 -0
- package/dist/rolldown-facet-artifact.generated.d.ts.map +1 -0
- package/dist/rolldown-facet-artifact.generated.js +17 -0
- package/dist/router/remote-api.d.ts.map +1 -1
- package/dist/router/remote-api.js +9 -0
- package/dist/runtime/bash-repl.d.ts.map +1 -1
- package/dist/runtime/bash-repl.js +1 -4
- package/dist/runtime/cpython-resident.d.ts.map +1 -1
- package/dist/runtime/cpython-resident.js +1 -0
- package/dist/runtime/esbuild-wasm-bytes.d.ts +25 -23
- package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/esbuild-wasm-bytes.js +30 -25
- package/dist/runtime/facet-loader-host.d.ts +5 -4
- package/dist/runtime/facet-loader-host.d.ts.map +1 -1
- package/dist/runtime/facet-loader-host.js +5 -4
- package/dist/runtime/node-runner.d.ts +2 -0
- package/dist/runtime/node-runner.d.ts.map +1 -1
- package/dist/runtime/node-runner.js +1 -0
- package/dist/runtime/node-shims-artifact.d.ts +8 -1
- package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
- package/dist/runtime/node-shims-artifact.js +32 -4
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +145 -109
- package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
- package/dist/runtime/opencode-facet-runner.js +6 -2
- package/dist/runtime/oxc-wasm-bytes.d.ts +19 -0
- package/dist/runtime/oxc-wasm-bytes.d.ts.map +1 -0
- package/dist/runtime/oxc-wasm-bytes.js +39 -0
- package/dist/runtime/package-manager.js +1 -1
- package/dist/runtime/process-logs-api.d.ts.map +1 -1
- package/dist/runtime/process-logs-api.js +2 -0
- package/dist/runtime/project-fs.d.ts +8 -1
- package/dist/runtime/project-fs.d.ts.map +1 -1
- package/dist/runtime/project-fs.js +15 -1
- package/dist/runtime/python-repl.d.ts +40 -1
- package/dist/runtime/python-repl.d.ts.map +1 -1
- package/dist/runtime/python-repl.js +19 -11
- package/dist/runtime/ruby-repl.d.ts +38 -0
- package/dist/runtime/ruby-repl.d.ts.map +1 -1
- package/dist/runtime/ruby-repl.js +24 -5
- package/dist/runtime/ruby-resident.d.ts.map +1 -1
- package/dist/runtime/ruby-resident.js +2 -0
- package/dist/session/nimbus-session.d.ts +13 -8
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +11 -5
- package/dist/session/programmatic.d.ts +25 -30
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +65 -93
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +23 -7
- package/dist/session/rpc.d.ts +16 -6
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +53 -13
- package/dist/session/start-real-vite.d.ts +24 -9
- package/dist/session/start-real-vite.d.ts.map +1 -1
- package/dist/session/start-real-vite.js +40 -4
- package/dist/session/supervisor-op.d.ts +14 -0
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +49 -0
- package/dist/session/supervisor-rpc.d.ts +11 -0
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +18 -0
- package/dist/session/vite-command.d.ts.map +1 -1
- package/dist/session/vite-command.js +23 -19
- package/dist/session/ws-relay.d.ts.map +1 -1
- package/dist/session/ws-relay.js +13 -1
- package/dist/shell/npm-bin-entrypoints.d.ts +3 -1
- package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
- package/dist/shell/npm-bin-entrypoints.js +53 -25
- package/dist/vfs/facet-resident-store.d.ts.map +1 -1
- package/dist/vfs/facet-resident-store.js +11 -5
- package/dist/wrangler/nimbus-wrangler.d.ts +8 -0
- package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
- package/dist/wrangler/nimbus-wrangler.js +54 -57
- package/package.json +6 -4
- package/public/_assets/esbuild-0.24.2.wasm +0 -0
- package/public/_assets/napi-wasm/loader/{99efae93dd1dcc2b → ab7e57fe9e8750c2}/napi-wasm-loader.mjs +4 -4
- package/public/_assets/napi-wasm/loader/{99efae93dd1dcc2b → ab7e57fe9e8750c2}/provenance.json +2 -2
- package/public/_assets/oxc/nimbus-oxc-1aa8c4c7057c6c28.provenance.json +72 -0
- package/public/_assets/oxc/nimbus-oxc-1aa8c4c7057c6c28.wasm +0 -0
- package/public/_assets/runtime/esbuild-cli-f13e6a112b03ac07.js +1143 -0
- package/public/_assets/runtime/js-interpreter-3c37c48024f0f651.js +23 -0
- package/public/_assets/runtime/js-interpreter-ops-2f4dfec6798e70fc.js +290 -0
- package/public/_assets/runtime/js-interpreter-primordials-e620a61b7e9800fa.js +1 -0
- package/public/_assets/runtime/{node-shims-f92f16c7d7c532e9.js → node-shims-e3adc4576da31e6e.js} +651 -103
- package/public/_assets/runtime/{esbuild-cli-b7aecffd4c6a36fe.js → oxc-facet-fd86fefcdf16bf9c.js} +217 -1047
- package/public/_assets/runtime/{resident-store-92386265e8b306dc.js → resident-store-009f39539ac989fc.js} +11 -5
- package/public/_assets/runtime/rolldown-facet-09983434e2dbe93e.js +15165 -0
- package/public/_assets/runtime/{vfs-write-ledger-d33ee0034446c3e0.js → vfs-write-ledger-9e9594591425a9b8.js} +4 -1
- package/scripts/acorn-primordials.mjs +637 -0
- package/scripts/bundle-esbuild-wasm.mjs +42 -50
- package/scripts/bundle-facet-workers.mjs +247 -18
- package/scripts/bundle-node-shims.mjs +29 -2
- package/scripts/bundle-oxc-wasm.mjs +105 -0
- package/scripts/interpreter-bundle.mjs +105 -0
- package/scripts/napi-wasm/build.mjs +4 -1
- package/scripts/napi-wasm/loader/napi-wasm-loader.ts +38 -3
- package/scripts/oxc-wasm/Cargo.lock +1246 -0
- package/scripts/oxc-wasm/Cargo.toml +30 -0
- package/scripts/oxc-wasm/build.mjs +249 -0
- package/scripts/oxc-wasm/examples/memory.rs +51 -0
- package/scripts/oxc-wasm/examples/transform.rs +20 -0
- package/scripts/oxc-wasm/inputs.mjs +32 -0
- package/scripts/oxc-wasm/rust-toolchain.toml +5 -0
- package/scripts/oxc-wasm/src/abi.rs +136 -0
- package/scripts/oxc-wasm/src/diagnostics.rs +49 -0
- package/scripts/oxc-wasm/src/helpers.rs +139 -0
- package/scripts/oxc-wasm/src/lib.rs +247 -0
- package/scripts/oxc-wasm/src/module.rs +978 -0
- package/scripts/oxc-wasm/src/names.rs +175 -0
- package/scripts/oxc-wasm/src/options.rs +154 -0
- package/scripts/parser-audit.mjs +492 -0
- package/scripts/rolldown-facet/entry.mjs +21 -0
- package/scripts/rolldown-facet/shims.mjs +64 -0
- package/dist/facets/esbuild-bundle-pool.d.ts +0 -43
- package/dist/facets/esbuild-bundle-pool.d.ts.map +0 -1
- package/dist/facets/esbuild-bundle-pool.js +0 -80
- package/dist/loaders/pre-bundle-preamble.d.ts +0 -44
- package/dist/loaders/pre-bundle-preamble.d.ts.map +0 -1
- package/dist/loaders/pre-bundle-preamble.js +0 -116
- package/dist/runtime/host-wasm.d.ts +0 -8
- package/dist/runtime/host-wasm.d.ts.map +0 -1
- package/dist/runtime/host-wasm.js +0 -33
- /package/public/_assets/napi-wasm/loader/{99efae93dd1dcc2b → ab7e57fe9e8750c2}/wasi-trampoline.wasm +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* bundle-oxc-wasm.mjs — stage Nimbus's Oxc transform for the transform facet.
|
|
4
|
+
*
|
|
5
|
+
* scripts/oxc-wasm/build.mjs builds the crate in scripts/oxc-wasm into
|
|
6
|
+
*
|
|
7
|
+
* nimbus-oxc.wasm, provenance.json
|
|
8
|
+
*
|
|
9
|
+
* This script does NOT rebuild (that needs the pinned Rust toolchain), and
|
|
10
|
+
* refuses a wasm whose provenance records other inputs than the tree's
|
|
11
|
+
* (scripts/oxc-wasm/inputs.mjs: the crate, its lockfile and toolchain pin,
|
|
12
|
+
* the recipe and its compiler wrapper), so a Rust change cannot ship the
|
|
13
|
+
* previous build. It stages that pair into the static-assets layer under a name carrying a
|
|
14
|
+
* prefix of the wasm's digest, so no cache layer can serve another build's
|
|
15
|
+
* bytes under it, and pins the digest and size in
|
|
16
|
+
* src/oxc-wasm-artifact.generated.ts, which runtime/oxc-wasm-bytes.ts verifies
|
|
17
|
+
* on every fetch:
|
|
18
|
+
*
|
|
19
|
+
* public/_assets/oxc/nimbus-oxc-<build id>.wasm
|
|
20
|
+
* public/_assets/oxc/nimbus-oxc-<build id>.provenance.json
|
|
21
|
+
*
|
|
22
|
+
* Source: NIMBUS_OXC_WASM_ARTIFACTS (a build.mjs --out directory), else the
|
|
23
|
+
* committed public/_assets/oxc/ (the artifact is tracked, so a checkout
|
|
24
|
+
* without the Rust build re-derives the same generated module).
|
|
25
|
+
*
|
|
26
|
+
* Run via: node scripts/bundle-oxc-wasm.mjs (wired into `bundle`).
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { promises as fs } from 'node:fs';
|
|
30
|
+
import path from 'node:path';
|
|
31
|
+
import { createHash } from 'node:crypto';
|
|
32
|
+
import { fileURLToPath } from 'node:url';
|
|
33
|
+
import { changedInputs, oxcWasmInputs } from './oxc-wasm/inputs.mjs';
|
|
34
|
+
|
|
35
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
37
|
+
const ASSETS = path.join(ROOT, 'public', '_assets', 'oxc');
|
|
38
|
+
const OUT_TS = path.join(ROOT, 'src', 'oxc-wasm-artifact.generated.ts');
|
|
39
|
+
|
|
40
|
+
const sha256 = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
41
|
+
const fail = (message) => { throw new Error(`[bundle-oxc-wasm] ${message}`); };
|
|
42
|
+
|
|
43
|
+
/** The wasm and its provenance: a fresh build's, or the committed stage's. */
|
|
44
|
+
async function source() {
|
|
45
|
+
const built = process.env.NIMBUS_OXC_WASM_ARTIFACTS;
|
|
46
|
+
if (built) {
|
|
47
|
+
const dir = path.resolve(built);
|
|
48
|
+
return { wasm: path.join(dir, 'nimbus-oxc.wasm'), provenance: path.join(dir, 'provenance.json') };
|
|
49
|
+
}
|
|
50
|
+
const staged = (await fs.readdir(ASSETS).catch(() => [])).filter((e) => e.endsWith('.wasm'));
|
|
51
|
+
if (staged.length !== 1) fail(`expected one staged wasm under ${ASSETS}, found ${JSON.stringify(staged)}; set NIMBUS_OXC_WASM_ARTIFACTS`);
|
|
52
|
+
const wasm = path.join(ASSETS, staged[0]);
|
|
53
|
+
return { wasm, provenance: wasm.replace(/\.wasm$/, '.provenance.json') };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const src = await source();
|
|
57
|
+
const wasm = await fs.readFile(src.wasm);
|
|
58
|
+
const provenanceText = await fs.readFile(src.provenance, 'utf8');
|
|
59
|
+
const provenance = JSON.parse(provenanceText);
|
|
60
|
+
const digest = sha256(wasm);
|
|
61
|
+
if (provenance.artifact !== 'nimbus-oxc') fail(`${src.provenance} describes ${provenance.artifact}, not nimbus-oxc`);
|
|
62
|
+
if (provenance.outputs?.['nimbus-oxc.wasm']?.sha256 !== digest) {
|
|
63
|
+
fail(`${src.wasm} sha256 ${digest} does not match its provenance.json (${provenance.outputs?.['nimbus-oxc.wasm']?.sha256})`);
|
|
64
|
+
}
|
|
65
|
+
const stale = changedInputs(provenance.source?.inputs, await oxcWasmInputs());
|
|
66
|
+
if (stale.length) {
|
|
67
|
+
fail(`${src.wasm} was built from other inputs than this tree's (${stale.join(', ')}); rebuild it with scripts/oxc-wasm/build.mjs and stage that build`);
|
|
68
|
+
}
|
|
69
|
+
const memoryPages = provenance.wasm?.memoryInitialPages;
|
|
70
|
+
if (!Number.isInteger(memoryPages) || memoryPages <= 0) fail(`${src.provenance} records no memoryInitialPages`);
|
|
71
|
+
|
|
72
|
+
const buildId = digest.slice(0, 16);
|
|
73
|
+
const wasmName = `nimbus-oxc-${buildId}.wasm`;
|
|
74
|
+
const provenanceName = `nimbus-oxc-${buildId}.provenance.json`;
|
|
75
|
+
await fs.mkdir(ASSETS, { recursive: true });
|
|
76
|
+
for (const entry of await fs.readdir(ASSETS)) {
|
|
77
|
+
if (entry !== wasmName && entry !== provenanceName) await fs.rm(path.join(ASSETS, entry), { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
if (path.resolve(src.wasm) !== path.join(ASSETS, wasmName)) {
|
|
80
|
+
await fs.writeFile(path.join(ASSETS, wasmName), wasm);
|
|
81
|
+
await fs.writeFile(path.join(ASSETS, provenanceName), provenanceText);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await fs.writeFile(OUT_TS, `/**
|
|
85
|
+
* oxc-wasm-artifact.generated.ts — AUTO-GENERATED by scripts/bundle-oxc-wasm.mjs
|
|
86
|
+
* DO NOT EDIT.
|
|
87
|
+
*
|
|
88
|
+
* Nimbus's Oxc transform (scripts/oxc-wasm, built by its build.mjs; inputs in
|
|
89
|
+
* the staged provenance.json), staged under public/_assets/oxc/. The transform
|
|
90
|
+
* facet's builder (runtime/oxc-wasm-bytes.ts) fetches it and verifies it
|
|
91
|
+
* against OXC_WASM_SHA256 before the loader compiles it. The module imports
|
|
92
|
+
* nothing; its memory starts at OXC_WASM_MEMORY_PAGES pages (stack and static
|
|
93
|
+
* data) and grows only while a transform runs.
|
|
94
|
+
*
|
|
95
|
+
* oxc ${provenance.oxc}, ${provenance.toolchain.split('\n')[0]}, ${(wasm.length / 1048576).toFixed(2)} MiB
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
export const OXC_VERSION: string = ${JSON.stringify(provenance.oxc)};
|
|
99
|
+
export const OXC_WASM_ASSET_PATH: string = ${JSON.stringify(`/_assets/oxc/${wasmName}`)};
|
|
100
|
+
export const OXC_WASM_BUILD_ID: string = ${JSON.stringify(buildId)};
|
|
101
|
+
export const OXC_WASM_SHA256: string = ${JSON.stringify(digest)};
|
|
102
|
+
export const OXC_WASM_BYTES: number = ${wasm.length};
|
|
103
|
+
export const OXC_WASM_MEMORY_PAGES: number = ${memoryPages};
|
|
104
|
+
`);
|
|
105
|
+
console.log(`[bundle-oxc-wasm] staged /_assets/oxc/${wasmName} (${wasm.length} bytes, sha256 ${digest})`);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* interpreter-bundle.mjs — the runtime-code interpreter (@nimbus-sh/core
|
|
3
|
+
* src/interpreter) as a node launch's map carries it: three CommonJS modules.
|
|
4
|
+
*
|
|
5
|
+
* - The primordials (primordials.ts): the built-ins the interpreter calls,
|
|
6
|
+
* captured when the launch starts, before any program code runs. The
|
|
7
|
+
* launch's runtime loads it at its start; the interpreter requires it.
|
|
8
|
+
* - The interpreter, bundled with acorn into one module. It loads late,
|
|
9
|
+
* after a program may have replaced built-ins, so its code must call
|
|
10
|
+
* none while it loads or parses: acorn is bundled rewritten to reach the
|
|
11
|
+
* realm only through captures (acorn-primordials.mjs, parser-realm.ts),
|
|
12
|
+
* and esbuild's CommonJS output would reach it too (its interop
|
|
13
|
+
* helpers capture Object.defineProperty and walk export lists with
|
|
14
|
+
* for-of), so it is bundled as an ES module, which needs no helpers, and
|
|
15
|
+
* its one import and its export statement are then rewritten, by their
|
|
16
|
+
* syntax tree, to a require and a `module.exports` assignment. The
|
|
17
|
+
* bundle states strict mode, which ES modules had implicitly; the
|
|
18
|
+
* interpreter's closures depend on it (an assignment to a read-only
|
|
19
|
+
* property throws, `this` is not coerced).
|
|
20
|
+
* - The host module it runs on (HOST_OPS_SOURCE), which is sloppy at its
|
|
21
|
+
* top level so that interpreted sloppy functions are native sloppy
|
|
22
|
+
* functions; it cannot be part of a strict bundle.
|
|
23
|
+
*
|
|
24
|
+
* esbuild compiles core's TypeScript itself, so all three are built from core
|
|
25
|
+
* src: bundle-node-shims.mjs stages them, and the tests build them the same
|
|
26
|
+
* way to test the source they sit beside.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { parse } from 'acorn';
|
|
30
|
+
import { build } from 'esbuild';
|
|
31
|
+
import { readFile } from 'node:fs/promises';
|
|
32
|
+
import { join } from 'node:path';
|
|
33
|
+
|
|
34
|
+
import { primordialAcorn } from './acorn-primordials.mjs';
|
|
35
|
+
import { resolvePackageDir } from './resolve-package-dir.mjs';
|
|
36
|
+
|
|
37
|
+
/** How the interpreter requires its primordials: the module beside it. */
|
|
38
|
+
export const PRIMORDIALS_FILE = 'interpreter-primordials.js';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The interpreter's ES module bundle as a CommonJS module: its import of the
|
|
42
|
+
* primordials becomes a require, its export statement `module.exports`.
|
|
43
|
+
*/
|
|
44
|
+
function asCommonJs(esm) {
|
|
45
|
+
const program = parse(esm, { ecmaVersion: 'latest', sourceType: 'module' });
|
|
46
|
+
const edits = [];
|
|
47
|
+
for (const node of program.body) {
|
|
48
|
+
if (node.type === 'ImportDeclaration') {
|
|
49
|
+
if (node.source.value !== `./${PRIMORDIALS_FILE}` || node.specifiers.length !== 1 || node.specifiers[0].type !== 'ImportNamespaceSpecifier') {
|
|
50
|
+
throw new Error(`[interpreter-bundle] the interpreter imports ${node.source.value} unexpectedly`);
|
|
51
|
+
}
|
|
52
|
+
edits.push({ start: node.start, end: node.end, text: `const ${node.specifiers[0].local.name} = require(${JSON.stringify(`./${PRIMORDIALS_FILE}`)});` });
|
|
53
|
+
} else if (node.type === 'ExportNamedDeclaration' && !node.declaration && !node.source) {
|
|
54
|
+
const fields = node.specifiers.map((s) => `${JSON.stringify(s.exported.name)}: ${s.local.name}`);
|
|
55
|
+
edits.push({ start: node.start, end: node.end, text: `module.exports = { ${fields.join(', ')} };` });
|
|
56
|
+
} else if (node.type.startsWith('Export')) {
|
|
57
|
+
throw new Error(`[interpreter-bundle] the interpreter bundle has an unexpected ${node.type}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
let text = esm;
|
|
61
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) text = text.slice(0, edit.start) + edit.text + text.slice(edit.end);
|
|
62
|
+
return `"use strict";\n${text}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {{ start: string }} options `start`: a directory @nimbus-sh/core resolves from.
|
|
67
|
+
* @returns {Promise<{ primordials: string, interpreter: string, ops: string, parser: string }>}
|
|
68
|
+
* `parser`: acorn's module as the rewrite made it, before bundling.
|
|
69
|
+
*/
|
|
70
|
+
export async function bundleInterpreter({ start }) {
|
|
71
|
+
const src = join(resolvePackageDir('@nimbus-sh/core', { start }), 'src/interpreter');
|
|
72
|
+
const common = { bundle: true, platform: 'neutral', target: 'esnext', mainFields: ['module', 'main'], minify: true, legalComments: 'none', write: false, metafile: true };
|
|
73
|
+
// esbuild states strict mode in the CommonJS it makes of an ES module.
|
|
74
|
+
const primordials = await build({ ...common, entryPoints: [join(src, 'primordials.ts')], format: 'cjs' });
|
|
75
|
+
let parser = null;
|
|
76
|
+
const interpreter = await build({
|
|
77
|
+
...common,
|
|
78
|
+
entryPoints: [join(src, 'index.ts')],
|
|
79
|
+
format: 'esm',
|
|
80
|
+
plugins: [{
|
|
81
|
+
name: 'primordials',
|
|
82
|
+
setup(b) {
|
|
83
|
+
b.onResolve({ filter: /^\.\/primordials\.js$/ }, () => ({ path: `./${PRIMORDIALS_FILE}`, external: true }));
|
|
84
|
+
// acorn, rewritten to reach the realm only through parser-realm.ts.
|
|
85
|
+
b.onLoad({ filter: /[\\/]acorn[\\/]dist[\\/]acorn\.mjs$/ }, async (args) => {
|
|
86
|
+
if (parser !== null) throw new Error(`[interpreter-bundle] acorn loaded twice (${args.path})`);
|
|
87
|
+
parser = primordialAcorn(await readFile(args.path, 'utf8'), join(src, 'parser-realm.ts')).code;
|
|
88
|
+
return { contents: parser, loader: 'js' };
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
}],
|
|
92
|
+
});
|
|
93
|
+
const inputs = Object.keys(interpreter.metafile.inputs);
|
|
94
|
+
const acornInputs = inputs.filter((path) => /(^|[\\/])acorn[\\/]/.test(path));
|
|
95
|
+
if (parser === null || acornInputs.length !== 1) {
|
|
96
|
+
throw new Error(`[interpreter-bundle] acorn must be bundled once, from dist/acorn.mjs, rewritten; bundled ${acornInputs.join(', ') || 'none'}`);
|
|
97
|
+
}
|
|
98
|
+
// HOST_OPS_SOURCE is built when its module loads: compile and load it to read it.
|
|
99
|
+
const ops = await build({ entryPoints: [join(src, 'host-ops.ts')], bundle: true, format: 'esm', platform: 'neutral', write: false });
|
|
100
|
+
const { HOST_OPS_SOURCE } = await import(`data:text/javascript;base64,${Buffer.from(ops.outputFiles[0].text).toString('base64')}`);
|
|
101
|
+
if (typeof HOST_OPS_SOURCE !== 'string' || HOST_OPS_SOURCE.length === 0) {
|
|
102
|
+
throw new Error('[interpreter-bundle] core src/interpreter/host-ops.ts has no HOST_OPS_SOURCE');
|
|
103
|
+
}
|
|
104
|
+
return { primordials: primordials.outputFiles[0].text, interpreter: asCommonJs(interpreter.outputFiles[0].text), ops: HOST_OPS_SOURCE, parser };
|
|
105
|
+
}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* bun packages/worker/scripts/napi-wasm/build.mjs --work <dir> --out <dir> [--spec rolldown,satteri]
|
|
7
7
|
*
|
|
8
|
+
* `--spec none` builds the loader alone (no Rust toolchain needed).
|
|
9
|
+
*
|
|
8
10
|
* Keep this Bun orchestrator at <=4 GiB. If Cargo needs a separate 16 GiB
|
|
9
11
|
* cgroup, name the bounded runner explicitly; builds remain serial:
|
|
10
12
|
* NIMBUS_CARGO_RUNNER=/mnt/scratch/nimbus/run-bounded \
|
|
@@ -60,7 +62,8 @@ function arg(name, required = true) {
|
|
|
60
62
|
}
|
|
61
63
|
const WORK = path.resolve(arg('--work'));
|
|
62
64
|
const OUT = path.resolve(arg('--out'));
|
|
63
|
-
const
|
|
65
|
+
const specArg = arg('--spec', false) ?? Object.keys(SPECS).join(',');
|
|
66
|
+
const SELECTED = specArg === 'none' ? [] : specArg.split(',');
|
|
64
67
|
for (const name of SELECTED) if (!SPECS[name]) throw new Error(`napi-wasm: no spec named ${name}`);
|
|
65
68
|
|
|
66
69
|
const sha256 = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
@@ -63,8 +63,22 @@ export interface NapiWasmBindingHost {
|
|
|
63
63
|
trampoline: WebAssembly.Module;
|
|
64
64
|
/** Wasm pages the binding's imported memory starts at (its declared minimum). */
|
|
65
65
|
memoryPages: number;
|
|
66
|
+
/**
|
|
67
|
+
* The binding's linear memory, when the host makes it (to watch what the
|
|
68
|
+
* binding grows to): `memoryPages` initial pages, maximum 65536, unshared.
|
|
69
|
+
* Absent: the loader makes it.
|
|
70
|
+
*/
|
|
71
|
+
memory?: WebAssembly.Memory;
|
|
66
72
|
/** The binding's name, for diagnostics. */
|
|
67
73
|
name: string;
|
|
74
|
+
/**
|
|
75
|
+
* Called once if the binding dies: a trap (a Rust panic aborts), or the
|
|
76
|
+
* host's stack overflowing inside it (a RangeError). The instance is
|
|
77
|
+
* unusable from then on and no promise it holds will settle, so the host
|
|
78
|
+
* settles its own callers and drops the binding. Absent: the error is
|
|
79
|
+
* thrown as an uncaught one.
|
|
80
|
+
*/
|
|
81
|
+
onFatal?(error: unknown): void;
|
|
68
82
|
}
|
|
69
83
|
|
|
70
84
|
/** What the loader calls on the binding instance besides napi. */
|
|
@@ -500,7 +514,7 @@ export function createNapiWasmBinding(host: NapiWasmBindingHost): Record<string,
|
|
|
500
514
|
// stack may suspend, so only such a binding takes the JSPI trampoline.
|
|
501
515
|
const pumped = WebAssembly.Module.exports(host.binding).some((e) => e.name === 'nimbus_napi_pump');
|
|
502
516
|
const jspi = pumped && typeof WebAssembly.Suspending === 'function' && typeof WebAssembly.promising === 'function';
|
|
503
|
-
const memory = new WebAssembly.Memory({ initial: host.memoryPages, maximum: 65536 });
|
|
517
|
+
const memory = host.memory ?? new WebAssembly.Memory({ initial: host.memoryPages, maximum: 65536 });
|
|
504
518
|
const getMemory = () => memory;
|
|
505
519
|
const fds = new Map<number, FilesystemFd>([
|
|
506
520
|
[0, { kind: 'stdin' }],
|
|
@@ -562,9 +576,15 @@ export function createNapiWasmBinding(host: NapiWasmBindingHost): Record<string,
|
|
|
562
576
|
let fatal: unknown = null;
|
|
563
577
|
|
|
564
578
|
const die = (error: unknown) => {
|
|
579
|
+
if (fatal !== null) return;
|
|
565
580
|
fatal = error;
|
|
566
|
-
|
|
567
|
-
//
|
|
581
|
+
while (waiting > 0) context.decreaseWaitingRequestCounter();
|
|
582
|
+
// A trap or a stack overflow leaves the instance unusable: tell the host,
|
|
583
|
+
// or surface it as an uncaught error.
|
|
584
|
+
if (host.onFatal) {
|
|
585
|
+
host.onFatal(error);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
568
588
|
queueMicrotask(() => {
|
|
569
589
|
throw error;
|
|
570
590
|
});
|
|
@@ -636,6 +656,21 @@ export function createNapiWasmBinding(host: NapiWasmBindingHost): Record<string,
|
|
|
636
656
|
};
|
|
637
657
|
|
|
638
658
|
const context = createContext();
|
|
659
|
+
// What the binding holds open (threadsafe functions, async work) holds a
|
|
660
|
+
// Node host's event loop open until released; a dead binding releases
|
|
661
|
+
// nothing, so a fatal error lets go of it all.
|
|
662
|
+
let waiting = 0;
|
|
663
|
+
const increaseWaiting = context.increaseWaitingRequestCounter.bind(context);
|
|
664
|
+
const decreaseWaiting = context.decreaseWaitingRequestCounter.bind(context);
|
|
665
|
+
context.increaseWaitingRequestCounter = () => {
|
|
666
|
+
waiting++;
|
|
667
|
+
increaseWaiting();
|
|
668
|
+
};
|
|
669
|
+
context.decreaseWaitingRequestCounter = () => {
|
|
670
|
+
if (waiting === 0) return;
|
|
671
|
+
waiting--;
|
|
672
|
+
decreaseWaiting();
|
|
673
|
+
};
|
|
639
674
|
const { napiModule } = instantiateNapiModuleSync(host.binding, {
|
|
640
675
|
context,
|
|
641
676
|
asyncWorkPoolSize: 0,
|