space-data-module-sdk 0.8.6 → 0.8.8
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/README.md +13 -0
- package/docs/AGENTS.md +5 -0
- package/docs/browser-wasmedge-isomorphic.md +65 -1
- package/docs/language-runtime-matrix.md +2 -2
- package/docs/provider-access-abi.md +600 -0
- package/package.json +15 -6
- package/schemas/orbpro/Propagator.fbs +19 -3
- package/src/browser.js +14 -4
- package/src/bundle/artifactBytes.js +44 -0
- package/src/bundle/index.js +1 -0
- package/src/compiler/compileModule.js +24 -1
- package/src/flow/flowCompiler.js +141 -2
- package/src/flow/flowRuntimeHost.js +7 -1
- package/src/flow/isomorphicFlowHost.js +1 -1
- package/src/flow/vendor/sdn-flow/MethodRegistry.js +6 -1
- package/src/generated/orbpro/propagator/propagator-source-description.js +2 -2
- package/src/generated/orbpro/propagator/propagator-source-description.ts +2 -2
- package/src/generated/orbpro/propagator/propagator-source-kind.js +13 -2
- package/src/generated/orbpro/propagator/propagator-source-kind.ts +13 -2
- package/src/generated/spacedatastandards/plg/pluginCategory.d.ts +18 -1
- package/src/generated/spacedatastandards/plg/pluginCategory.d.ts.map +1 -1
- package/src/generated/spacedatastandards/plg/pluginCategory.js +17 -0
- package/src/generated/spacedatastandards/plg/pluginCategory.ts +21 -1
- package/src/{testing → host}/browserModuleHarness.js +69 -34
- package/src/host/index.js +6 -0
- package/src/host/isomorphicLoader.js +17 -45
- package/src/host/isomorphicLoaderBrowser.js +47 -0
- package/src/host/isomorphicLoaderCore.js +58 -0
- package/src/host/nodeBuiltinSpecifier.js +43 -0
- package/src/host/providerAccess.js +727 -0
- package/src/host/providerAccessAbi.js +403 -0
- package/src/host/providerAccessEngineAdapter.js +338 -0
- package/src/host/providerAccessFixtureAdapter.js +444 -0
- package/src/host/providerAccessTileStoreAdapter.js +366 -0
- package/src/host/sabHostcallChannel.js +1 -1
- package/src/host/terrainSourceSeam.js +205 -0
- package/src/host/wasiThreadHost.js +11 -1
- package/src/{testing → host}/workerModuleHarness.js +45 -12
- package/src/{testing → host}/workerModuleHarnessWorker.js +6 -5
- package/src/index.d.ts +29 -2
- package/src/standards/browser.js +95 -0
- package/src/standards/catalogCore.js +290 -0
- package/src/standards/index.js +27 -251
- package/src/testing/AGENTS.md +25 -2
- package/src/testing/browser.js +32 -0
- package/src/testing/index.d.ts +12 -1
- package/src/testing/index.js +3 -3
- package/src/testing/parityBrowserRunner.js +9 -2
- package/src/testing/parityHarness.js +1 -1
- package/templates/provider-access-module/include/space_data_provider_abi.h +227 -0
- /package/src/{testing → host}/moduleFlatbufferStreamPump.js +0 -0
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser
|
|
2
|
+
* Browser module host — the browser leg of the tri-runtime contract.
|
|
3
3
|
*
|
|
4
|
-
* Loads the same standalone WASI .wasm artifact that WasmEdge
|
|
5
|
-
* instantiating it in the browser with the WASI
|
|
6
|
-
* bridge. Matches the
|
|
4
|
+
* Loads the same standalone WASI .wasm artifact that native WasmEdge and the
|
|
5
|
+
* Docker WasmEdge container run, instantiating it in the browser with the WASI
|
|
6
|
+
* shim + optional space_data_module_host bridge. Matches the
|
|
7
|
+
* createModuleHarness() API surface.
|
|
8
|
+
*
|
|
9
|
+
* This is PRODUCTION runtime surface, published as
|
|
10
|
+
* `space-data-module-sdk/host/browser-module`. It lived under `src/testing/`
|
|
11
|
+
* until 2026-08-07, which made every browser consumer import a test-harness
|
|
12
|
+
* subpath to load a module and let the Node harnesses next door reach a browser
|
|
13
|
+
* bundle (`orbpro-engine-bundle-ships-node-builtins`). Nothing browser-facing
|
|
14
|
+
* lives under `src/testing/` any more.
|
|
7
15
|
*
|
|
8
16
|
* Supports two invoke paths:
|
|
9
17
|
* 1. "direct" — call plugin_invoke_stream(ptr, len, &outLen) and read
|
|
@@ -12,19 +20,19 @@
|
|
|
12
20
|
* stdout for the response bytes.
|
|
13
21
|
*/
|
|
14
22
|
|
|
15
|
-
import { createBrowserWasiShim, WasiExitError } from "
|
|
23
|
+
import { createBrowserWasiShim, WasiExitError } from "./wasiShim.js";
|
|
16
24
|
import {
|
|
17
25
|
createWasiThreadSpawn,
|
|
18
26
|
isWasiThreadsModule,
|
|
19
|
-
} from "
|
|
20
|
-
import { createBrowserHost } from "
|
|
27
|
+
} from "./wasiThreadHost.js";
|
|
28
|
+
import { createBrowserHost } from "./browserHost.js";
|
|
21
29
|
import { getWasmWallet } from "../utils/wasmCrypto.js";
|
|
22
30
|
import {
|
|
23
31
|
createHostcallBridge,
|
|
24
32
|
createAsyncHostDispatcher,
|
|
25
33
|
createHostSyncDispatcher,
|
|
26
34
|
DEFAULT_HOSTCALL_IMPORT_MODULE,
|
|
27
|
-
} from "
|
|
35
|
+
} from "./abi.js";
|
|
28
36
|
import {
|
|
29
37
|
DefaultInvokeExports,
|
|
30
38
|
DefaultManifestExports,
|
|
@@ -41,33 +49,12 @@ import {
|
|
|
41
49
|
resolveModuleSignaturePolicy,
|
|
42
50
|
verifyModuleArtifact,
|
|
43
51
|
} from "../bundle/signing.js";
|
|
44
|
-
|
|
52
|
+
// Artifact byte reduction is an ARTIFACT concern shared by all three runtimes,
|
|
53
|
+
// so it lives on `space-data-module-sdk/bundle`. Re-exported here because a
|
|
54
|
+
// caller loading a module in the browser needs it in the same breath.
|
|
55
|
+
import { toLoadableWasmBytes } from "../bundle/artifactBytes.js";
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
* Reduce a module artifact to the bytes a wasm engine can compile.
|
|
48
|
-
*
|
|
49
|
-
* Signed/published artifacts carry an appended publication record collection
|
|
50
|
-
* (MBL bundle with the sds.signature entry, PNM/REC trailers). Wasm engines
|
|
51
|
-
* reject those trailing bytes ("unknown section code"), so the canonical
|
|
52
|
-
* module payload must be extracted before compile. ENC-protected payloads
|
|
53
|
-
* cannot be loaded here — decryption is a host concern.
|
|
54
|
-
*
|
|
55
|
-
* @param {Uint8Array} bytes - raw artifact bytes
|
|
56
|
-
* @returns {Uint8Array} compilable wasm bytes
|
|
57
|
-
*/
|
|
58
|
-
export function toLoadableWasmBytes(bytes) {
|
|
59
|
-
const publication = extractPublicationRecordCollection(bytes);
|
|
60
|
-
if (!publication) {
|
|
61
|
-
return bytes;
|
|
62
|
-
}
|
|
63
|
-
if (publication.enc) {
|
|
64
|
-
throw new ModuleSignatureError(
|
|
65
|
-
"encrypted_artifact",
|
|
66
|
-
"Module artifact payload is ENC-protected; decrypt it before loading.",
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
return publication.payloadBytes;
|
|
70
|
-
}
|
|
57
|
+
export { toLoadableWasmBytes };
|
|
71
58
|
|
|
72
59
|
const STANDALONE_SHARED_MEMORY_ENV_STUBS = Object.freeze({
|
|
73
60
|
_emscripten_init_main_thread_js: () => 0,
|
|
@@ -196,6 +183,37 @@ const DEFAULT_IMPORTED_MEMORY_MAXIMUM_BYTES = 2 * 1024 * 1024 * 1024;
|
|
|
196
183
|
const DEFAULT_DIRECT_INVOKE_REQUEST_ARENA_BYTES = 64 * 1024;
|
|
197
184
|
const SHARED_ARRAY_BUFFER_TAG = "[object SharedArrayBuffer]";
|
|
198
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Overwrite a plaintext wasm buffer in place. Best-effort by contract: a
|
|
188
|
+
* detached (transferred) buffer, a frozen typed array, or a runtime without
|
|
189
|
+
* writable views must not turn a successful module load into a thrown error.
|
|
190
|
+
*
|
|
191
|
+
* @param {Uint8Array|ArrayBuffer|ArrayBufferView|null|undefined} bytes
|
|
192
|
+
* @returns {number} bytes actually overwritten
|
|
193
|
+
*/
|
|
194
|
+
export function zeroWasmBytes(bytes) {
|
|
195
|
+
if (!bytes) {
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const view =
|
|
200
|
+
bytes instanceof Uint8Array
|
|
201
|
+
? bytes
|
|
202
|
+
: bytes instanceof ArrayBuffer
|
|
203
|
+
? new Uint8Array(bytes)
|
|
204
|
+
: ArrayBuffer.isView(bytes)
|
|
205
|
+
? new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
206
|
+
: null;
|
|
207
|
+
if (!view || view.byteLength === 0) {
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
view.fill(0);
|
|
211
|
+
return view.byteLength;
|
|
212
|
+
} catch {
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
199
217
|
export function isSharedArrayBufferLike(value) {
|
|
200
218
|
return (
|
|
201
219
|
value !== null &&
|
|
@@ -408,6 +426,11 @@ async function instantiateBrowserModule(options = {}) {
|
|
|
408
426
|
export async function createBrowserModuleHarness(options = {}) {
|
|
409
427
|
let wasmSource = options.wasmSource;
|
|
410
428
|
const signaturePolicy = resolveModuleSignaturePolicy(options);
|
|
429
|
+
// Bytes THIS function materializes itself (Response/URL fetch, or the
|
|
430
|
+
// ArrayBuffer/array copy taken for signature verification) — never a
|
|
431
|
+
// caller-owned buffer, which this function neither created nor may safely
|
|
432
|
+
// scrub. Zeroed below once the module is compiled.
|
|
433
|
+
let ownedArtifactBytes = null;
|
|
411
434
|
if (signaturePolicy) {
|
|
412
435
|
if (wasmSource instanceof WebAssembly.Module) {
|
|
413
436
|
throw new ModuleSignatureError(
|
|
@@ -434,8 +457,20 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
434
457
|
}
|
|
435
458
|
await verifyModuleArtifact(artifactBytes, signaturePolicy);
|
|
436
459
|
wasmSource = artifactBytes;
|
|
460
|
+
ownedArtifactBytes = artifactBytes;
|
|
437
461
|
}
|
|
438
462
|
const wasmModule = await compileWasmModule(wasmSource);
|
|
463
|
+
// Plaintext hygiene (wasm-plaintext-memory-hygiene): nothing needs the
|
|
464
|
+
// source bytes past this point. Scrub whatever THIS function materialized
|
|
465
|
+
// itself, then drop every local/options reference to the source — a
|
|
466
|
+
// caller-supplied Uint8Array/ArrayBuffer must not outlive this call by
|
|
467
|
+
// being pinned via closure over `options` for the harness's entire
|
|
468
|
+
// lifetime (the returned harness closes over `options` for many other,
|
|
469
|
+
// unrelated fields).
|
|
470
|
+
zeroWasmBytes(ownedArtifactBytes);
|
|
471
|
+
ownedArtifactBytes = null;
|
|
472
|
+
wasmSource = null;
|
|
473
|
+
options.wasmSource = null;
|
|
439
474
|
const moduleImports = WebAssembly.Module.imports(wasmModule);
|
|
440
475
|
const needsHostBridge = moduleImports.some(
|
|
441
476
|
(entry) => entry.module === DEFAULT_HOSTCALL_IMPORT_MODULE,
|
package/src/host/index.js
CHANGED
|
@@ -7,3 +7,9 @@ export * from "./isomorphicLoader.js";
|
|
|
7
7
|
export * from "./abi.js";
|
|
8
8
|
export * from "./sabHostcallChannel.js";
|
|
9
9
|
export * from "./timerDriver.js";
|
|
10
|
+
export * from "./providerAccessAbi.js";
|
|
11
|
+
export * from "./providerAccess.js";
|
|
12
|
+
export * from "./providerAccessFixtureAdapter.js";
|
|
13
|
+
export * from "./providerAccessEngineAdapter.js";
|
|
14
|
+
export * from "./providerAccessTileStoreAdapter.js";
|
|
15
|
+
export * from "./terrainSourceSeam.js";
|
|
@@ -1,43 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Isomorphic module loader.
|
|
2
|
+
* Isomorphic module loader — NODE/WasmEdge leg (the `default` condition).
|
|
3
3
|
*
|
|
4
4
|
* Unified entry point that detects the runtime environment and artifact
|
|
5
5
|
* profile, then loads the module through the appropriate path:
|
|
6
|
-
* - Browser
|
|
7
|
-
* - Node/WasmEdge: createModuleHarness (subprocess)
|
|
6
|
+
* - Browser (jsdom/embedded window under Node): createBrowserModuleHarness
|
|
7
|
+
* - Node/WasmEdge: createModuleHarness (subprocess) or the WasmEdge command
|
|
8
|
+
* harness below
|
|
8
9
|
*
|
|
9
|
-
* The same compiled .wasm artifact works in
|
|
10
|
+
* The same compiled .wasm artifact works in every environment; only HOW it is
|
|
11
|
+
* launched differs, and that difference is absorbed here — never in a guest.
|
|
12
|
+
*
|
|
13
|
+
* A browser resolves `./host/isomorphic` to `isomorphicLoaderBrowser.js`
|
|
14
|
+
* instead, via the package's `browser` export condition. The two legs share
|
|
15
|
+
* `isomorphicLoaderCore.js` so the runtime-independent half cannot drift. The
|
|
16
|
+
* split is what keeps a browser bundle from statically resolving the
|
|
17
|
+
* node:child_process/os/path/fs imports below
|
|
18
|
+
* (`module-sdk-browser-entry-node-builtins`).
|
|
10
19
|
*/
|
|
11
20
|
|
|
12
21
|
import {
|
|
13
22
|
createBrowserModuleHarness,
|
|
14
|
-
detectArtifactProfile,
|
|
15
23
|
toLoadableWasmBytes,
|
|
16
|
-
} from "
|
|
17
|
-
import { createAsyncHostDispatcher } from "./abi.js";
|
|
24
|
+
} from "./browserModuleHarness.js";
|
|
18
25
|
import {
|
|
19
26
|
resolveModuleSignaturePolicy,
|
|
20
27
|
verifyModuleArtifact,
|
|
21
28
|
} from "../bundle/signing.js";
|
|
29
|
+
import { attachHostDispatch, inspectModule } from "./isomorphicLoaderCore.js";
|
|
30
|
+
|
|
31
|
+
export { inspectModule, attachHostDispatch };
|
|
22
32
|
|
|
23
33
|
const isBrowser =
|
|
24
34
|
typeof globalThis.window !== "undefined" &&
|
|
25
35
|
typeof globalThis.document !== "undefined";
|
|
26
36
|
|
|
27
|
-
function attachHostDispatch(harness, host) {
|
|
28
|
-
if (!host || typeof host !== "object") {
|
|
29
|
-
return harness;
|
|
30
|
-
}
|
|
31
|
-
const dispatchHost = createAsyncHostDispatcher(host);
|
|
32
|
-
return {
|
|
33
|
-
...harness,
|
|
34
|
-
host,
|
|
35
|
-
async callHost(operation, params = {}) {
|
|
36
|
-
return dispatchHost(operation, params);
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
37
|
async function createWasmEdgeCommandHarness(options = {}) {
|
|
42
38
|
const [
|
|
43
39
|
{ spawn },
|
|
@@ -269,27 +265,3 @@ export async function loadModule(options = {}) {
|
|
|
269
265
|
options.host ?? null,
|
|
270
266
|
);
|
|
271
267
|
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Inspect a WASM module's artifact profile without instantiating it.
|
|
275
|
-
*
|
|
276
|
-
* @param {Uint8Array|ArrayBuffer|WebAssembly.Module} source
|
|
277
|
-
* @returns {Promise<{profile: string, exports: string[], imports: Array}>}
|
|
278
|
-
*/
|
|
279
|
-
export async function inspectModule(source) {
|
|
280
|
-
let wasmModule;
|
|
281
|
-
if (source instanceof WebAssembly.Module) {
|
|
282
|
-
wasmModule = source;
|
|
283
|
-
} else {
|
|
284
|
-
const bytes =
|
|
285
|
-
source instanceof ArrayBuffer ? new Uint8Array(source) : source;
|
|
286
|
-
// Tolerate signed/published artifacts (appended publication records).
|
|
287
|
-
wasmModule = await WebAssembly.compile(toLoadableWasmBytes(bytes));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const profile = detectArtifactProfile(wasmModule);
|
|
291
|
-
const exports = WebAssembly.Module.exports(wasmModule).map((e) => e.name);
|
|
292
|
-
const imports = WebAssembly.Module.imports(wasmModule);
|
|
293
|
-
|
|
294
|
-
return { profile, exports, imports };
|
|
295
|
-
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isomorphic module loader — BROWSER leg.
|
|
3
|
+
*
|
|
4
|
+
* The target of the `browser` export condition on
|
|
5
|
+
* `space-data-module-sdk/host/isomorphic`, and the loader re-exported by the
|
|
6
|
+
* package's own `browser` entry (`src/browser.js`).
|
|
7
|
+
*
|
|
8
|
+
* Same public surface as the Node leg — `loadModule` and `inspectModule` — and
|
|
9
|
+
* for a browser it does EXACTLY what the Node leg's `isBrowser` branch did
|
|
10
|
+
* before the split: hand the artifact to `createBrowserModuleHarness`. What it
|
|
11
|
+
* does not carry is the WasmEdge subprocess path, because a browser can never
|
|
12
|
+
* take it and a bundler resolves it anyway.
|
|
13
|
+
*
|
|
14
|
+
* Asking this leg for a server runtime is a defect, not a fallback: it throws.
|
|
15
|
+
* A caller that legitimately needs both is running under Node and resolves the
|
|
16
|
+
* Node leg through the same subpath.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { createBrowserModuleHarness } from "./browserModuleHarness.js";
|
|
20
|
+
import { resolveModuleSignaturePolicy } from "../bundle/signing.js";
|
|
21
|
+
import { attachHostDispatch, inspectModule } from "./isomorphicLoaderCore.js";
|
|
22
|
+
|
|
23
|
+
export { inspectModule, attachHostDispatch };
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Load a WASM module in the browser.
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} options - see the Node leg for the full option list; the
|
|
29
|
+
* browser leg accepts the same object and honours the browser-relevant keys.
|
|
30
|
+
* @returns {Promise<Object>} Harness with invoke(), readManifest(), destroy().
|
|
31
|
+
*/
|
|
32
|
+
export async function loadModule(options = {}) {
|
|
33
|
+
// Resolved for the same reason the Node leg resolves it: an invalid policy is
|
|
34
|
+
// a caller error that must surface identically in every runtime, before any
|
|
35
|
+
// artifact work happens.
|
|
36
|
+
resolveModuleSignaturePolicy(options);
|
|
37
|
+
|
|
38
|
+
const runtimeKind = options.runtimeKind;
|
|
39
|
+
if (typeof runtimeKind === "string" && runtimeKind !== "browser") {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`The browser isomorphic loader cannot run runtimeKind "${runtimeKind}"; ` +
|
|
42
|
+
"that artifact must be loaded from a Node/WasmEdge host.",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return createBrowserModuleHarness(options);
|
|
47
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isomorphic loader — the runtime-independent half.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is byte-identical work that every runtime does: reduce the
|
|
5
|
+
* artifact, compile it, read its profile/exports/imports, attach the host
|
|
6
|
+
* dispatcher. `isomorphicLoader.js` (Node/WasmEdge) and
|
|
7
|
+
* `isomorphicLoaderBrowser.js` (browser) both build on this, so the two legs of
|
|
8
|
+
* `./host/isomorphic` cannot drift apart on the parts that must not differ.
|
|
9
|
+
*
|
|
10
|
+
* The split exists because a browser BUNDLER resolves every branch statically:
|
|
11
|
+
* one file holding both legs put node:child_process/os/path/fs into every
|
|
12
|
+
* browser bundle of the SDK's own `browser` export condition
|
|
13
|
+
* (`module-sdk-browser-entry-node-builtins`). The runtime difference is now
|
|
14
|
+
* absorbed by the package's export conditions — a host-shim concern — instead
|
|
15
|
+
* of by a runtime check inside one file.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { detectArtifactProfile } from "./browserModuleHarness.js";
|
|
19
|
+
import { createAsyncHostDispatcher } from "./abi.js";
|
|
20
|
+
import { toLoadableWasmBytes } from "../bundle/artifactBytes.js";
|
|
21
|
+
|
|
22
|
+
export function attachHostDispatch(harness, host) {
|
|
23
|
+
if (!host || typeof host !== "object") {
|
|
24
|
+
return harness;
|
|
25
|
+
}
|
|
26
|
+
const dispatchHost = createAsyncHostDispatcher(host);
|
|
27
|
+
return {
|
|
28
|
+
...harness,
|
|
29
|
+
host,
|
|
30
|
+
async callHost(operation, params = {}) {
|
|
31
|
+
return dispatchHost(operation, params);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Inspect a WASM module's artifact profile without instantiating it.
|
|
38
|
+
*
|
|
39
|
+
* @param {Uint8Array|ArrayBuffer|WebAssembly.Module} source
|
|
40
|
+
* @returns {Promise<{profile: string, exports: string[], imports: Array}>}
|
|
41
|
+
*/
|
|
42
|
+
export async function inspectModule(source) {
|
|
43
|
+
let wasmModule;
|
|
44
|
+
if (source instanceof WebAssembly.Module) {
|
|
45
|
+
wasmModule = source;
|
|
46
|
+
} else {
|
|
47
|
+
const bytes =
|
|
48
|
+
source instanceof ArrayBuffer ? new Uint8Array(source) : source;
|
|
49
|
+
// Tolerate signed/published artifacts (appended publication records).
|
|
50
|
+
wasmModule = await WebAssembly.compile(toLoadableWasmBytes(bytes));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const profile = detectArtifactProfile(wasmModule);
|
|
54
|
+
const exports = WebAssembly.Module.exports(wasmModule).map((e) => e.name);
|
|
55
|
+
const imports = WebAssembly.Module.imports(wasmModule);
|
|
56
|
+
|
|
57
|
+
return { profile, exports, imports };
|
|
58
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque Node builtin specifiers for isomorphic host shims.
|
|
3
|
+
*
|
|
4
|
+
* A host shim that serves BOTH runtimes needs a Node-only branch that is dead
|
|
5
|
+
* in a browser. Writing that branch as a literal `import("node:worker_threads")`
|
|
6
|
+
* does not work: esbuild/vite/rollup resolve dynamic imports STATICALLY, so a
|
|
7
|
+
* branch that can never run still fails — or, worse, is emitted as an external
|
|
8
|
+
* `node:` specifier that the browser then tries to FETCH, which is how the
|
|
9
|
+
* whole OrbPro gallery went dark (`orbpro-engine-bundle-ships-node-builtins`).
|
|
10
|
+
*
|
|
11
|
+
* Assembling the specifier at runtime keeps it opaque to the bundler. This is
|
|
12
|
+
* host-shim code absorbing a runtime difference, which is the only place the
|
|
13
|
+
* tri-runtime contract allows a difference to be absorbed; no guest module ever
|
|
14
|
+
* gains a runtime check.
|
|
15
|
+
*
|
|
16
|
+
* Use it ONLY behind a runtime check that is false in a browser, and only in
|
|
17
|
+
* `src/host/**` — a module that needs a Node builtin unconditionally belongs on
|
|
18
|
+
* a Node-only subpath instead.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Split so no bundler's `node:`-prefix scanner sees a literal here either.
|
|
22
|
+
const NODE_BUILTIN_PREFIX = "no" + "de:";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {string} name - builtin name without the `node:` prefix
|
|
26
|
+
* @returns {string} the specifier, assembled at runtime
|
|
27
|
+
*/
|
|
28
|
+
export function nodeBuiltinSpecifier(name) {
|
|
29
|
+
return NODE_BUILTIN_PREFIX + name;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Import a Node builtin from an isomorphic host shim.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} name - builtin name without the `node:` prefix
|
|
36
|
+
* @returns {Promise<any>} the builtin's module namespace
|
|
37
|
+
*/
|
|
38
|
+
export async function importNodeBuiltin(name) {
|
|
39
|
+
const specifier = nodeBuiltinSpecifier(name);
|
|
40
|
+
return import(/* @vite-ignore */ /* webpackIgnore: true */ specifier);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { NODE_BUILTIN_PREFIX };
|