space-data-module-sdk 0.8.4 → 0.8.6
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 +117 -20
- package/bin/space-data-module.js +263 -0
- package/docs/.nojekyll +1 -0
- package/docs/AGENTS.md +34 -0
- package/docs/architecture.svg +141 -0
- package/docs/browser-wasmedge-isomorphic.md +179 -0
- package/docs/flatsql-streaming-standard.md +341 -0
- package/docs/gpu-module-abi.md +193 -0
- package/docs/index.html +125 -0
- package/docs/isomorphic-pthreads.md +188 -0
- package/docs/isomorphic-sdn-runtime-plan.md +167 -0
- package/docs/language-runtime-matrix.md +82 -0
- package/docs/manifest-structure.svg +114 -0
- package/docs/module-bundle-runtime-plan.md +19 -0
- package/docs/module-lifecycle.svg +70 -0
- package/docs/module-publication-standard.md +540 -0
- package/docs/node-red-default-node-parity.md +88 -0
- package/docs/protocol-installation.md +196 -0
- package/docs/secrets-capability.md +152 -0
- package/docs/styles.css +288 -0
- package/docs/testing-harness.md +408 -0
- package/docs/tri-runtime-parity.md +132 -0
- package/docs/wallet-callback.html +2 -0
- package/package.json +25 -6
- package/schemas/HttpRequestAbi.fbs +41 -0
- package/schemas/HttpResponseAbi.fbs +36 -0
- package/schemas/PluginManifest.fbs +2 -1
- package/src/AGENTS.md +1 -1
- package/src/app/codec.js +548 -0
- package/src/app/index.js +6 -0
- package/src/browser.js +5 -0
- package/src/bundle/constants.js +1 -0
- package/src/bundle/index.js +15 -0
- package/src/bundle/sigdomain.js +179 -0
- package/src/bundle/signing.js +767 -0
- package/src/bundle/wasm.js +3 -2
- package/src/capabilities.js +3 -0
- package/src/compat/index.js +7 -0
- package/src/compat/sdnLegacy.js +449 -0
- package/src/compiler/compileModule.js +556 -55
- package/src/compiler/flatcSupport.js +41 -27
- package/src/compiler/index.d.ts +2 -0
- package/src/compiler/index.js +18 -0
- package/src/compiler/invokeGlue.js +1212 -183
- package/src/compiler/pthreadArtifactGuard.js +910 -0
- package/src/compiler/sdnShimGenerator.js +323 -0
- package/src/compiler/wasiThreadsToolchain.js +150 -0
- package/src/compliance/index.js +11 -1
- package/src/compliance/legacyWildcardPorts.js +228 -0
- package/src/compliance/pluginCompliance.js +1000 -96
- package/src/field-stream/index.d.ts +31 -0
- package/src/field-stream/index.js +119 -0
- package/src/flow/dependencyStreamBridge.js +234 -0
- package/src/flow/flatsqlLinkShim.js +304 -0
- package/src/flow/flowCodec.js +107 -0
- package/src/flow/flowCompiler.js +2900 -0
- package/src/flow/flowRuntimeHost.js +877 -0
- package/src/flow/index.d.ts +117 -0
- package/src/flow/index.js +31 -0
- package/src/flow/isomorphicFlowHost.js +384 -0
- package/src/flow/jsFlowRuntime.js +275 -0
- package/src/flow/normalize.js +294 -0
- package/src/flow/runtime-src/flow_runtime.cpp +1699 -0
- package/src/flow/vendor/sdn-flow/MethodRegistry.js +400 -0
- package/src/flow/vendor/sdn-flow/constants.js +39 -0
- package/src/flow/vendor/sdn-flow/index.js +29 -0
- package/src/flow/vendor/sdn-flow/normalize.js +506 -0
- package/src/flow/vendor/sdn-flow/wasmCompatibility.js +189 -0
- package/src/generated/http/cpp/HttpRequestAbi_generated.h +285 -0
- package/src/generated/http/cpp/HttpResponseAbi_generated.h +192 -0
- package/src/generated/http/sdn/http/http-header.js +53 -0
- package/src/generated/http/sdn/http/http-header.ts +67 -0
- package/src/generated/http/sdn/http/http-request.js +132 -0
- package/src/generated/http/sdn/http/http-request.ts +179 -0
- package/src/generated/http/sdn/http/http-response.js +144 -0
- package/src/generated/http/sdn/http/http-response.ts +168 -0
- package/src/generated/http/sdn/http.js +11 -0
- package/src/generated/http/sdn/http.ts +4 -0
- package/src/generated/orbpro/flow/backpressure-policy.d.ts +12 -0
- package/src/generated/orbpro/flow/backpressure-policy.d.ts.map +1 -0
- package/src/generated/orbpro/flow/backpressure-policy.js +17 -0
- package/src/generated/orbpro/flow/backpressure-policy.js.map +1 -0
- package/src/generated/orbpro/flow/backpressure-policy.ts +15 -0
- package/src/generated/orbpro/flow/flow-bundle-manifest.d.ts +142 -0
- package/src/generated/orbpro/flow/flow-bundle-manifest.d.ts.map +1 -0
- package/src/generated/orbpro/flow/flow-bundle-manifest.js +304 -0
- package/src/generated/orbpro/flow/flow-bundle-manifest.js.map +1 -0
- package/src/generated/orbpro/flow/flow-bundle-manifest.ts +399 -0
- package/src/generated/orbpro/flow/flow-edge.d.ts +113 -0
- package/src/generated/orbpro/flow/flow-edge.d.ts.map +1 -0
- package/src/generated/orbpro/flow/flow-edge.js +221 -0
- package/src/generated/orbpro/flow/flow-edge.js.map +1 -0
- package/src/generated/orbpro/flow/flow-edge.ts +292 -0
- package/src/generated/orbpro/flow/flow-node.d.ts +80 -0
- package/src/generated/orbpro/flow/flow-node.d.ts.map +1 -0
- package/src/generated/orbpro/flow/flow-node.js +158 -0
- package/src/generated/orbpro/flow/flow-node.js.map +1 -0
- package/src/generated/orbpro/flow/flow-node.ts +202 -0
- package/src/generated/orbpro/flow/flow-program.d.ts +164 -0
- package/src/generated/orbpro/flow/flow-program.d.ts.map +1 -0
- package/src/generated/orbpro/flow/flow-program.js +350 -0
- package/src/generated/orbpro/flow/flow-program.js.map +1 -0
- package/src/generated/orbpro/flow/flow-program.ts +477 -0
- package/src/generated/orbpro/flow/flow-trigger.d.ts +108 -0
- package/src/generated/orbpro/flow/flow-trigger.d.ts.map +1 -0
- package/src/generated/orbpro/flow/flow-trigger.js +207 -0
- package/src/generated/orbpro/flow/flow-trigger.js.map +1 -0
- package/src/generated/orbpro/flow/flow-trigger.ts +276 -0
- package/src/generated/orbpro/flow/node-kind.d.ts +13 -0
- package/src/generated/orbpro/flow/node-kind.d.ts.map +1 -0
- package/src/generated/orbpro/flow/node-kind.js +16 -0
- package/src/generated/orbpro/flow/node-kind.js.map +1 -0
- package/src/generated/orbpro/{invoke.ts → flow/node-kind.ts} +12 -2
- package/src/generated/orbpro/flow/plugin-version-binding.d.ts +52 -0
- package/src/generated/orbpro/flow/plugin-version-binding.d.ts.map +1 -0
- package/src/generated/orbpro/flow/plugin-version-binding.js +85 -0
- package/src/generated/orbpro/flow/plugin-version-binding.js.map +1 -0
- package/src/generated/orbpro/flow/plugin-version-binding.ts +121 -0
- package/src/generated/orbpro/flow/schema-hash-binding.d.ts +70 -0
- package/src/generated/orbpro/flow/schema-hash-binding.d.ts.map +1 -0
- package/src/generated/orbpro/flow/schema-hash-binding.js +143 -0
- package/src/generated/orbpro/flow/schema-hash-binding.js.map +1 -0
- package/src/generated/orbpro/flow/schema-hash-binding.ts +189 -0
- package/src/generated/orbpro/flow/trigger-binding.d.ts +71 -0
- package/src/generated/orbpro/flow/trigger-binding.d.ts.map +1 -0
- package/src/generated/orbpro/flow/trigger-binding.js +142 -0
- package/src/generated/orbpro/flow/trigger-binding.js.map +1 -0
- package/src/generated/orbpro/flow/trigger-binding.ts +181 -0
- package/src/generated/orbpro/flow/trigger-kind.d.ts +14 -0
- package/src/generated/orbpro/flow/trigger-kind.d.ts.map +1 -0
- package/src/generated/orbpro/flow/trigger-kind.js +17 -0
- package/src/generated/orbpro/flow/trigger-kind.js.map +1 -0
- package/src/generated/orbpro/flow/trigger-kind.ts +17 -0
- package/src/generated/orbpro/flow.d.ts +21 -0
- package/src/generated/orbpro/flow.d.ts.map +1 -0
- package/src/generated/orbpro/flow.js +23 -0
- package/src/generated/orbpro/flow.js.map +1 -0
- package/src/generated/orbpro/flow.ts +24 -0
- package/src/generated/orbpro/manifest/capability-kind.d.ts +2 -1
- package/src/generated/orbpro/manifest/capability-kind.js +1 -0
- package/src/generated/orbpro/manifest/capability-kind.ts +1 -0
- package/src/generated/orbpro/plugin/stream-invoke-request.d.ts +93 -0
- package/src/generated/orbpro/plugin/stream-invoke-request.js +160 -0
- package/src/generated/orbpro/plugin/stream-invoke-request.ts +211 -0
- package/src/generated/orbpro/plugin/stream-invoke-response.d.ts +99 -0
- package/src/generated/orbpro/plugin/stream-invoke-response.js +175 -0
- package/src/generated/orbpro/plugin/stream-invoke-response.ts +226 -0
- package/src/generated/orbpro/plugin.js +8 -0
- package/src/generated/orbpro/stream.d.ts +12 -0
- package/src/generated/orbpro/stream.js +14 -0
- package/src/generated/orbpro/stream.ts +15 -0
- package/src/generated/spacedatastandards/plg/EntryFunction.d.ts +52 -0
- package/src/generated/spacedatastandards/plg/EntryFunction.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/EntryFunction.js +106 -0
- package/src/generated/spacedatastandards/plg/EntryFunction.ts +162 -0
- package/src/generated/spacedatastandards/plg/FlatBufferTypeRef.d.ts +90 -0
- package/src/generated/spacedatastandards/plg/FlatBufferTypeRef.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/FlatBufferTypeRef.js +189 -0
- package/src/generated/spacedatastandards/plg/FlatBufferTypeRef.ts +270 -0
- package/src/generated/spacedatastandards/plg/PLG.d.ts +492 -0
- package/src/generated/spacedatastandards/plg/PLG.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLG.js +1139 -0
- package/src/generated/spacedatastandards/plg/PLG.ts +1600 -0
- package/src/generated/spacedatastandards/plg/PLGAcceptedTypeSet.d.ts +63 -0
- package/src/generated/spacedatastandards/plg/PLGAcceptedTypeSet.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGAcceptedTypeSet.js +138 -0
- package/src/generated/spacedatastandards/plg/PLGAcceptedTypeSet.ts +189 -0
- package/src/generated/spacedatastandards/plg/PLGBuildArtifact.d.ts +41 -0
- package/src/generated/spacedatastandards/plg/PLGBuildArtifact.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGBuildArtifact.js +104 -0
- package/src/generated/spacedatastandards/plg/PLGBuildArtifact.ts +151 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdge.d.ts +68 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdge.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdge.js +124 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdge.ts +184 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdgeContract.d.ts +58 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdgeContract.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdgeContract.js +126 -0
- package/src/generated/spacedatastandards/plg/PLGFlowEdgeContract.ts +161 -0
- package/src/generated/spacedatastandards/plg/PLGFlowNode.d.ts +82 -0
- package/src/generated/spacedatastandards/plg/PLGFlowNode.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGFlowNode.js +164 -0
- package/src/generated/spacedatastandards/plg/PLGFlowNode.ts +244 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTrigger.d.ts +55 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTrigger.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTrigger.js +105 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTrigger.ts +162 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTriggerBinding.d.ts +42 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTriggerBinding.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTriggerBinding.js +83 -0
- package/src/generated/spacedatastandards/plg/PLGFlowTriggerBinding.ts +127 -0
- package/src/generated/spacedatastandards/plg/PLGHostCapability.d.ts +36 -0
- package/src/generated/spacedatastandards/plg/PLGHostCapability.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGHostCapability.js +90 -0
- package/src/generated/spacedatastandards/plg/PLGHostCapability.ts +127 -0
- package/src/generated/spacedatastandards/plg/PLGMethodManifest.d.ts +53 -0
- package/src/generated/spacedatastandards/plg/PLGMethodManifest.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGMethodManifest.js +153 -0
- package/src/generated/spacedatastandards/plg/PLGMethodManifest.ts +210 -0
- package/src/generated/spacedatastandards/plg/PLGPortManifest.d.ts +70 -0
- package/src/generated/spacedatastandards/plg/PLGPortManifest.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGPortManifest.js +149 -0
- package/src/generated/spacedatastandards/plg/PLGPortManifest.ts +212 -0
- package/src/generated/spacedatastandards/plg/PLGProtocolSpec.d.ts +73 -0
- package/src/generated/spacedatastandards/plg/PLGProtocolSpec.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGProtocolSpec.js +199 -0
- package/src/generated/spacedatastandards/plg/PLGProtocolSpec.ts +292 -0
- package/src/generated/spacedatastandards/plg/PLGTimerSpec.d.ts +40 -0
- package/src/generated/spacedatastandards/plg/PLGTimerSpec.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PLGTimerSpec.js +103 -0
- package/src/generated/spacedatastandards/plg/PLGTimerSpec.ts +148 -0
- package/src/generated/spacedatastandards/plg/PluginCapability.d.ts +41 -0
- package/src/generated/spacedatastandards/plg/PluginCapability.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PluginCapability.js +82 -0
- package/src/generated/spacedatastandards/plg/{plugin-capability.ts → PluginCapability.ts} +55 -18
- package/src/generated/spacedatastandards/plg/PluginDependency.d.ts +42 -0
- package/src/generated/spacedatastandards/plg/PluginDependency.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/PluginDependency.js +80 -0
- package/src/generated/spacedatastandards/plg/PluginDependency.ts +124 -0
- package/src/generated/spacedatastandards/plg/TAB.d.ts +85 -0
- package/src/generated/spacedatastandards/plg/TAB.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/TAB.js +173 -0
- package/src/generated/spacedatastandards/plg/TAB.ts +228 -0
- package/src/generated/spacedatastandards/plg/bufferMutability.d.ts +18 -0
- package/src/generated/spacedatastandards/plg/bufferMutability.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/bufferMutability.js +20 -0
- package/src/generated/spacedatastandards/plg/bufferMutability.ts +23 -0
- package/src/generated/spacedatastandards/plg/bufferOwnership.d.ts +18 -0
- package/src/generated/spacedatastandards/plg/bufferOwnership.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/bufferOwnership.js +20 -0
- package/src/generated/spacedatastandards/plg/bufferOwnership.ts +23 -0
- package/src/generated/spacedatastandards/plg/drainBehavior.d.ts +20 -0
- package/src/generated/spacedatastandards/plg/drainBehavior.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/drainBehavior.js +22 -0
- package/src/generated/spacedatastandards/plg/drainBehavior.ts +25 -0
- package/src/generated/spacedatastandards/plg/flowEdgeRoutePolicy.d.ts +10 -0
- package/src/generated/spacedatastandards/plg/flowEdgeRoutePolicy.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/flowEdgeRoutePolicy.js +12 -0
- package/src/generated/spacedatastandards/plg/flowEdgeRoutePolicy.ts +13 -0
- package/src/generated/spacedatastandards/plg/hostCapabilityKind.d.ts +51 -0
- package/src/generated/spacedatastandards/plg/hostCapabilityKind.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/hostCapabilityKind.js +53 -0
- package/src/generated/spacedatastandards/plg/hostCapabilityKind.ts +55 -0
- package/src/generated/spacedatastandards/plg/invokeSurfaceKind.d.ts +15 -0
- package/src/generated/spacedatastandards/plg/invokeSurfaceKind.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/invokeSurfaceKind.js +17 -0
- package/src/generated/spacedatastandards/plg/invokeSurfaceKind.ts +19 -0
- package/src/generated/spacedatastandards/plg/main.d.ts +29 -0
- package/src/generated/spacedatastandards/plg/main.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/main.js +30 -0
- package/src/generated/spacedatastandards/plg/main.ts +32 -0
- package/src/generated/spacedatastandards/plg/payloadWireFormat.d.ts +17 -0
- package/src/generated/spacedatastandards/plg/payloadWireFormat.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/payloadWireFormat.js +19 -0
- package/src/generated/spacedatastandards/plg/payloadWireFormat.ts +21 -0
- package/src/generated/spacedatastandards/plg/pluginCategory.d.ts +82 -0
- package/src/generated/spacedatastandards/plg/pluginCategory.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/pluginCategory.js +84 -0
- package/src/generated/spacedatastandards/plg/pluginCategory.ts +103 -0
- package/src/generated/spacedatastandards/plg/publicationState.d.ts +18 -0
- package/src/generated/spacedatastandards/plg/publicationState.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/publicationState.js +20 -0
- package/src/generated/spacedatastandards/plg/purchaseTier.d.ts +18 -0
- package/src/generated/spacedatastandards/plg/purchaseTier.d.ts.map +1 -0
- package/src/generated/spacedatastandards/plg/purchaseTier.js +20 -0
- package/src/host/AGENTS.md +2 -2
- package/src/host/abi.js +53 -66
- package/src/host/browserHost.js +355 -8
- package/src/host/cpp/keyslotClient.hpp +231 -0
- package/src/host/cpp/secretsClient.hpp +583 -0
- package/src/host/hostcallWire.js +183 -0
- package/src/host/index.js +2 -0
- package/src/host/isomorphicLoader.js +44 -7
- package/src/host/nodeHost.js +227 -8
- package/src/host/sabHostcallChannel.js +206 -0
- package/src/host/timerDriver.js +203 -0
- package/src/host/wasiShim.js +41 -1
- package/src/host/wasiThreadBrowserWorker.mjs +48 -0
- package/src/host/wasiThreadHost.js +393 -0
- package/src/host/wasiThreadWorker.mjs +32 -0
- package/src/host/wasiThreadWorkerRuntime.js +93 -0
- package/src/http/index.js +339 -0
- package/src/index.d.ts +725 -11
- package/src/index.js +4 -0
- package/src/invoke/codec.js +1202 -128
- package/src/invoke/index.js +5 -1
- package/src/licensing/index.d.ts +2 -0
- package/src/licensing/index.js +2 -0
- package/src/licensing/records.js +287 -8
- package/src/manifest/codec.js +62 -14
- package/src/manifest/index.js +2 -0
- package/src/manifest/legacyToPlg.js +164 -25
- package/src/manifest/normalize.js +1 -0
- package/src/manifest/plgCodec.js +1303 -62
- package/src/manifest/typeRefs.js +162 -24
- package/src/runtime/compiledRuntimeAbi.js +47 -0
- package/src/runtime/compiledRuntimeAbi.json +33 -0
- package/src/runtime/index.d.ts +32 -0
- package/src/runtime/index.js +1 -0
- package/src/runtime-host/index.js +3 -0
- package/src/runtime-host/methodRegistry.js +55 -0
- package/src/standards/index.js +200 -56
- package/src/standards/sharedCatalog.js +16 -0
- package/src/testing/browserModuleHarness.js +604 -31
- package/src/testing/docker/wasmedge-parity.Dockerfile +39 -0
- package/src/testing/index.d.ts +151 -0
- package/src/testing/index.js +21 -0
- package/src/testing/native/wasmedge_emscripten_pthread_runner.c +25 -1
- package/src/testing/parityBrowserRunner.js +138 -0
- package/src/testing/parityHarness.js +616 -0
- package/src/testing/parityLanes.js +537 -0
- package/src/testing/processInvoke.js +29 -21
- package/src/testing/streamInvokeCodec.js +10 -175
- package/src/testing/wasmedgePin.json +6 -0
- package/src/testing/workerModuleHarness.js +242 -0
- package/src/testing/workerModuleHarnessWorker.js +176 -0
- package/src/transport/index.js +3 -0
- package/src/transport/pki.js +352 -14
- package/src/transport/records.js +16 -7
- package/src/utils/ecdsaDer.js +106 -0
- package/src/utils/wasmCrypto.js +0 -43
- package/templates/gpu-module/README.md +48 -0
- package/templates/gpu-module/include/space_data_gpu_abi.h +122 -0
- package/templates/gpu-module/manifest.json +84 -0
- package/schemas/PluginInvokeRequest.fbs +0 -18
- package/schemas/PluginInvokeResponse.fbs +0 -30
- package/schemas/spacedatastandards/PLG.fbs +0 -191
- package/src/generated/orbpro/invoke/plugin-invoke-request.d.ts +0 -51
- package/src/generated/orbpro/invoke/plugin-invoke-request.d.ts.map +0 -1
- package/src/generated/orbpro/invoke/plugin-invoke-request.js +0 -131
- package/src/generated/orbpro/invoke/plugin-invoke-request.js.map +0 -1
- package/src/generated/orbpro/invoke/plugin-invoke-request.ts +0 -173
- package/src/generated/orbpro/invoke/plugin-invoke-response.d.ts +0 -76
- package/src/generated/orbpro/invoke/plugin-invoke-response.d.ts.map +0 -1
- package/src/generated/orbpro/invoke/plugin-invoke-response.js +0 -184
- package/src/generated/orbpro/invoke/plugin-invoke-response.js.map +0 -1
- package/src/generated/orbpro/invoke/plugin-invoke-response.ts +0 -243
- package/src/generated/orbpro/invoke.d.ts +0 -3
- package/src/generated/orbpro/invoke.js +0 -5
- package/src/generated/spacedatastandards/plg/entry-function.js +0 -86
- package/src/generated/spacedatastandards/plg/entry-function.ts +0 -119
- package/src/generated/spacedatastandards/plg/index.js +0 -16
- package/src/generated/spacedatastandards/plg/index.ts +0 -11
- package/src/generated/spacedatastandards/plg/plg.js +0 -657
- package/src/generated/spacedatastandards/plg/plg.ts +0 -924
- package/src/generated/spacedatastandards/plg/plugin-capability.js +0 -66
- package/src/generated/spacedatastandards/plg/plugin-category.js +0 -15
- package/src/generated/spacedatastandards/plg/plugin-category.ts +0 -53
- package/src/generated/spacedatastandards/plg/plugin-dependency.js +0 -63
- package/src/generated/spacedatastandards/plg/plugin-dependency.ts +0 -86
- package/src/generated/spacedatastandards/plg/publication-state.js +0 -9
- package/src/generated/spacedatastandards/plg/purchase-tier.js +0 -9
- /package/src/generated/spacedatastandards/plg/{publication-state.ts → publicationState.ts} +0 -0
- /package/src/generated/spacedatastandards/plg/{purchase-tier.ts → purchaseTier.ts} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Browser-side module harness.
|
|
3
3
|
*
|
|
4
4
|
* Loads the same standalone WASI .wasm artifact that WasmEdge runs,
|
|
5
|
-
* instantiating it in the browser with the WASI shim + optional
|
|
5
|
+
* instantiating it in the browser with the WASI shim + optional space_data_module_host
|
|
6
6
|
* bridge. Matches the createModuleHarness() API surface.
|
|
7
7
|
*
|
|
8
8
|
* Supports two invoke paths:
|
|
@@ -13,10 +13,14 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { createBrowserWasiShim, WasiExitError } from "../host/wasiShim.js";
|
|
16
|
+
import {
|
|
17
|
+
createWasiThreadSpawn,
|
|
18
|
+
isWasiThreadsModule,
|
|
19
|
+
} from "../host/wasiThreadHost.js";
|
|
16
20
|
import { createBrowserHost } from "../host/browserHost.js";
|
|
17
21
|
import { getWasmWallet } from "../utils/wasmCrypto.js";
|
|
18
22
|
import {
|
|
19
|
-
|
|
23
|
+
createHostcallBridge,
|
|
20
24
|
createAsyncHostDispatcher,
|
|
21
25
|
createHostSyncDispatcher,
|
|
22
26
|
DEFAULT_HOSTCALL_IMPORT_MODULE,
|
|
@@ -26,38 +30,142 @@ import {
|
|
|
26
30
|
DefaultManifestExports,
|
|
27
31
|
} from "../runtime/constants.js";
|
|
28
32
|
import {
|
|
33
|
+
INVOKE_ARENA_ALIGNMENT,
|
|
29
34
|
encodePluginInvokeRequest,
|
|
30
35
|
decodePluginInvokeResponse,
|
|
36
|
+
writePluginInvokeRequestToArena,
|
|
31
37
|
} from "../invoke/codec.js";
|
|
38
|
+
import { toUint8Array } from "../runtime/bufferLike.js";
|
|
39
|
+
import {
|
|
40
|
+
ModuleSignatureError,
|
|
41
|
+
resolveModuleSignaturePolicy,
|
|
42
|
+
verifyModuleArtifact,
|
|
43
|
+
} from "../bundle/signing.js";
|
|
44
|
+
import { extractPublicationRecordCollection } from "../transport/records.js";
|
|
45
|
+
|
|
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
|
+
}
|
|
71
|
+
|
|
72
|
+
const STANDALONE_SHARED_MEMORY_ENV_STUBS = Object.freeze({
|
|
73
|
+
_emscripten_init_main_thread_js: () => 0,
|
|
74
|
+
_emscripten_notify_mailbox_postmessage: () => 0,
|
|
75
|
+
_emscripten_receive_on_main_thread_js: () => 0,
|
|
76
|
+
_emscripten_thread_cleanup: () => 0,
|
|
77
|
+
_emscripten_thread_mailbox_await: () => 0,
|
|
78
|
+
_emscripten_thread_set_strongref: () => 0,
|
|
79
|
+
emscripten_check_blocking_allowed: () => 0,
|
|
80
|
+
emscripten_exit_with_live_runtime: () => 0,
|
|
81
|
+
pthread_mutex_lock: () => 0,
|
|
82
|
+
pthread_mutex_unlock: () => 0,
|
|
83
|
+
pthread_cond_broadcast: () => 0,
|
|
84
|
+
pthread_cond_wait: () => 0,
|
|
85
|
+
emscripten_thread_sleep: () => {},
|
|
86
|
+
__do_set_thread_state: () => {},
|
|
87
|
+
__get_tp: () => 0,
|
|
88
|
+
});
|
|
89
|
+
const STANDALONE_SHARED_MEMORY_ENV_IMPORTS = new Set([
|
|
90
|
+
"memory",
|
|
91
|
+
...Object.keys(STANDALONE_SHARED_MEMORY_ENV_STUBS),
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
function isStandaloneSharedMemoryEnvImport(entry) {
|
|
95
|
+
return (
|
|
96
|
+
entry.module === "env" &&
|
|
97
|
+
STANDALONE_SHARED_MEMORY_ENV_IMPORTS.has(entry.name) &&
|
|
98
|
+
(entry.name === "memory"
|
|
99
|
+
? entry.kind === "memory"
|
|
100
|
+
: entry.kind === "function")
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function usesOnlyStandaloneSharedMemoryEnvImports(envImports) {
|
|
105
|
+
return (
|
|
106
|
+
envImports.length > 0 &&
|
|
107
|
+
envImports.every((entry) => isStandaloneSharedMemoryEnvImport(entry))
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function addStandaloneSharedMemoryEnvStubs(importObject, moduleImports) {
|
|
112
|
+
const envImports = moduleImports.filter((entry) => entry.module === "env");
|
|
113
|
+
if (!usesOnlyStandaloneSharedMemoryEnvImports(envImports)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const envNamespace = {
|
|
118
|
+
...(importObject.env ?? {}),
|
|
119
|
+
};
|
|
120
|
+
for (const entry of envImports) {
|
|
121
|
+
if (entry.kind !== "function") {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (typeof envNamespace[entry.name] !== "function") {
|
|
125
|
+
envNamespace[entry.name] = STANDALONE_SHARED_MEMORY_ENV_STUBS[entry.name];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
importObject.env = envNamespace;
|
|
129
|
+
}
|
|
32
130
|
|
|
33
131
|
/**
|
|
34
132
|
* Detect artifact profile from WebAssembly.Module imports.
|
|
35
|
-
* Returns "standalone" (WASI-only), "
|
|
133
|
+
* Returns "standalone" (WASI-only), "module-host-abi" (WASI + space_data_module_host),
|
|
36
134
|
* or "emscripten" (env.* with invoke trampolines).
|
|
37
135
|
*/
|
|
38
136
|
export function detectArtifactProfile(wasmModule) {
|
|
39
137
|
const imports = WebAssembly.Module.imports(wasmModule);
|
|
40
138
|
const moduleNames = new Set(imports.map((i) => i.module));
|
|
139
|
+
const envImports = imports.filter((i) => i.module === "env");
|
|
140
|
+
const usesStandaloneSharedMemoryEnv =
|
|
141
|
+
usesOnlyStandaloneSharedMemoryEnvImports(envImports);
|
|
41
142
|
|
|
42
143
|
if (moduleNames.has("env")) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
144
|
+
if (!usesStandaloneSharedMemoryEnv) {
|
|
145
|
+
const hasInvokeTrampolines = envImports.some((i) =>
|
|
146
|
+
i.name.startsWith("invoke_"),
|
|
147
|
+
);
|
|
148
|
+
const hasPthreads = envImports.some(
|
|
149
|
+
(i) => i.name.includes("pthread") || i.name.includes("thread"),
|
|
150
|
+
);
|
|
151
|
+
if (hasInvokeTrampolines || hasPthreads) {
|
|
152
|
+
return "emscripten";
|
|
153
|
+
}
|
|
50
154
|
}
|
|
51
155
|
}
|
|
52
156
|
|
|
53
157
|
if (moduleNames.has(DEFAULT_HOSTCALL_IMPORT_MODULE)) {
|
|
54
|
-
return "
|
|
158
|
+
return "module-host-abi";
|
|
55
159
|
}
|
|
56
160
|
|
|
57
161
|
if (moduleNames.has("wasi_snapshot_preview1") || moduleNames.has("wasi_unstable")) {
|
|
58
162
|
return "standalone";
|
|
59
163
|
}
|
|
60
164
|
|
|
165
|
+
if (usesStandaloneSharedMemoryEnv) {
|
|
166
|
+
return "standalone";
|
|
167
|
+
}
|
|
168
|
+
|
|
61
169
|
return "unknown";
|
|
62
170
|
}
|
|
63
171
|
|
|
@@ -65,17 +173,97 @@ async function compileWasmModule(source) {
|
|
|
65
173
|
if (source instanceof WebAssembly.Module) {
|
|
66
174
|
return source;
|
|
67
175
|
}
|
|
176
|
+
let bytes;
|
|
68
177
|
if (source instanceof Response) {
|
|
69
|
-
|
|
178
|
+
bytes = new Uint8Array(await source.arrayBuffer());
|
|
179
|
+
} else if (typeof source === "string") {
|
|
180
|
+
const response = await fetch(source);
|
|
181
|
+
if (!response.ok) {
|
|
182
|
+
throw new Error(`Failed to fetch module artifact: ${response.status}`);
|
|
183
|
+
}
|
|
184
|
+
bytes = new Uint8Array(await response.arrayBuffer());
|
|
185
|
+
} else {
|
|
186
|
+
bytes = source instanceof ArrayBuffer ? new Uint8Array(source) : source;
|
|
187
|
+
}
|
|
188
|
+
// Strip any appended publication record collection (signature/PNM/REC
|
|
189
|
+
// trailers) — wasm engines reject trailing non-section bytes.
|
|
190
|
+
return WebAssembly.compile(toLoadableWasmBytes(bytes));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const WASM_PAGE_BYTES = 65536;
|
|
194
|
+
const DEFAULT_IMPORTED_MEMORY_INITIAL_BYTES = 64 * 1024 * 1024;
|
|
195
|
+
const DEFAULT_IMPORTED_MEMORY_MAXIMUM_BYTES = 2 * 1024 * 1024 * 1024;
|
|
196
|
+
const DEFAULT_DIRECT_INVOKE_REQUEST_ARENA_BYTES = 64 * 1024;
|
|
197
|
+
const SHARED_ARRAY_BUFFER_TAG = "[object SharedArrayBuffer]";
|
|
198
|
+
|
|
199
|
+
export function isSharedArrayBufferLike(value) {
|
|
200
|
+
return (
|
|
201
|
+
value !== null &&
|
|
202
|
+
typeof value === "object" &&
|
|
203
|
+
((typeof SharedArrayBuffer === "function" &&
|
|
204
|
+
value instanceof SharedArrayBuffer) ||
|
|
205
|
+
Object.prototype.toString.call(value) === SHARED_ARRAY_BUFFER_TAG)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function bytesToPages(value, fallbackBytes) {
|
|
210
|
+
const bytes =
|
|
211
|
+
Number.isFinite(value) && value > 0 ? Number(value) : fallbackBytes;
|
|
212
|
+
return Math.ceil(bytes / WASM_PAGE_BYTES);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function createImportedMemory(options = {}) {
|
|
216
|
+
const initialPages = bytesToPages(
|
|
217
|
+
options.initialMemoryBytes,
|
|
218
|
+
DEFAULT_IMPORTED_MEMORY_INITIAL_BYTES,
|
|
219
|
+
);
|
|
220
|
+
const maximumPages = Math.max(
|
|
221
|
+
initialPages,
|
|
222
|
+
bytesToPages(
|
|
223
|
+
options.maximumMemoryBytes,
|
|
224
|
+
DEFAULT_IMPORTED_MEMORY_MAXIMUM_BYTES,
|
|
225
|
+
),
|
|
226
|
+
);
|
|
227
|
+
const descriptor = {
|
|
228
|
+
initial: initialPages,
|
|
229
|
+
maximum: maximumPages,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
if (options.sharedMemory === true) {
|
|
233
|
+
if (typeof SharedArrayBuffer !== "function") {
|
|
234
|
+
throw new Error(
|
|
235
|
+
"Browser module harness shared imported memory requires SharedArrayBuffer.",
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
descriptor.shared = true;
|
|
70
239
|
}
|
|
71
|
-
|
|
72
|
-
|
|
240
|
+
|
|
241
|
+
return new WebAssembly.Memory(descriptor);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function resolveManifestSurface(manifest) {
|
|
245
|
+
const surfaces = Array.isArray(manifest?.invokeSurfaces)
|
|
246
|
+
? manifest.invokeSurfaces
|
|
247
|
+
: [];
|
|
248
|
+
if (surfaces.includes("command")) {
|
|
249
|
+
return "command";
|
|
73
250
|
}
|
|
74
|
-
|
|
75
|
-
|
|
251
|
+
if (surfaces.includes("direct")) {
|
|
252
|
+
return "direct";
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
76
255
|
}
|
|
77
256
|
|
|
78
257
|
async function instantiateBrowserModule(options = {}) {
|
|
258
|
+
let providedMemory = options.wasmMemory ?? options.memory ?? null;
|
|
259
|
+
if (
|
|
260
|
+
providedMemory !== null &&
|
|
261
|
+
!(providedMemory instanceof WebAssembly.Memory)
|
|
262
|
+
) {
|
|
263
|
+
throw new TypeError(
|
|
264
|
+
"Browser module harness memory must be a WebAssembly.Memory.",
|
|
265
|
+
);
|
|
266
|
+
}
|
|
79
267
|
const wasi = createBrowserWasiShim({
|
|
80
268
|
args: options.args ?? [],
|
|
81
269
|
env: options.env ?? {},
|
|
@@ -88,30 +276,111 @@ async function instantiateBrowserModule(options = {}) {
|
|
|
88
276
|
const needsHostBridge = moduleImports.some(
|
|
89
277
|
(entry) => entry.module === DEFAULT_HOSTCALL_IMPORT_MODULE,
|
|
90
278
|
);
|
|
279
|
+
// Isomorphic-pthreads (wasm32-wasip1-threads) artifacts import
|
|
280
|
+
// `wasi.thread-spawn` over a SHARED imported memory. Such a module can only be
|
|
281
|
+
// instantiated with shared memory, so force it here regardless of the caller's
|
|
282
|
+
// sharedMemory flag; single-thread artifacts are unaffected.
|
|
283
|
+
const isThreaded = isWasiThreadsModule(options.wasmModule);
|
|
284
|
+
const memoryImports = moduleImports.filter((entry) => entry.kind === "memory");
|
|
285
|
+
if (!providedMemory && memoryImports.length > 0) {
|
|
286
|
+
providedMemory = createImportedMemory(
|
|
287
|
+
isThreaded ? { ...options, sharedMemory: true } : options,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
for (const entry of memoryImports) {
|
|
291
|
+
if (!providedMemory) {
|
|
292
|
+
throw new Error(
|
|
293
|
+
`Browser module imports ${entry.module}.${entry.name} memory; pass a WebAssembly.Memory as the memory option.`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
importObject[entry.module] = {
|
|
297
|
+
...(importObject[entry.module] ?? {}),
|
|
298
|
+
[entry.name]: providedMemory,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
addStandaloneSharedMemoryEnvStubs(importObject, moduleImports);
|
|
302
|
+
|
|
303
|
+
// Isomorphic-pthreads host: satisfy `wasi.thread-spawn` by running each guest
|
|
304
|
+
// pthread on a real OS thread (Node worker_threads / browser Worker) over the
|
|
305
|
+
// shared imported memory. Only wired for modules that import it.
|
|
306
|
+
let threadHost = null;
|
|
307
|
+
if (isThreaded) {
|
|
308
|
+
if (!providedMemory) {
|
|
309
|
+
throw new Error(
|
|
310
|
+
"wasi-threads module imports wasi.thread-spawn but no shared imported memory is available.",
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
threadHost = await createWasiThreadSpawn({
|
|
314
|
+
wasmModule: options.wasmModule,
|
|
315
|
+
memory: providedMemory,
|
|
316
|
+
// Browser warm-pool sizing: cap pooled workers at how many guest threads
|
|
317
|
+
// the module will actually ask for. Ignored by the Node lazy path.
|
|
318
|
+
requestedThreads: options.maxThreads,
|
|
319
|
+
hostcallChannel: options.threadHostcallChannel,
|
|
320
|
+
requiresHostcalls: needsHostBridge,
|
|
321
|
+
enableBrowserThreads: options.enableBrowserWasiThreads,
|
|
322
|
+
});
|
|
323
|
+
importObject.wasi = {
|
|
324
|
+
...(importObject.wasi ?? {}),
|
|
325
|
+
"thread-spawn": threadHost.threadSpawn,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
91
328
|
|
|
92
329
|
let instance = null;
|
|
93
330
|
let bridge = null;
|
|
331
|
+
let memory = providedMemory;
|
|
94
332
|
if (needsHostBridge) {
|
|
95
|
-
|
|
96
|
-
|
|
333
|
+
// hostcallDispatch overrides the default sync dispatcher — used by the
|
|
334
|
+
// worker harness to route guest hostcalls through the SAB channel so
|
|
335
|
+
// async host capabilities (http/ipfs/storage/pubsub) become reachable.
|
|
336
|
+
const dispatch =
|
|
337
|
+
typeof options.hostcallDispatch === "function"
|
|
338
|
+
? options.hostcallDispatch
|
|
339
|
+
: createHostSyncDispatcher(options.host);
|
|
340
|
+
bridge = createHostcallBridge({
|
|
97
341
|
dispatch,
|
|
98
|
-
getMemory: () => instance
|
|
342
|
+
getMemory: () => memory ?? instance?.exports?.memory,
|
|
99
343
|
});
|
|
100
344
|
Object.assign(importObject, bridge.imports);
|
|
101
345
|
}
|
|
102
346
|
|
|
103
347
|
instance = await WebAssembly.instantiate(options.wasmModule, importObject);
|
|
104
|
-
|
|
105
|
-
|
|
348
|
+
memory = instance.exports.memory ?? providedMemory;
|
|
349
|
+
if (memory) {
|
|
350
|
+
if (
|
|
351
|
+
options.sharedMemory === true &&
|
|
352
|
+
!isSharedArrayBufferLike(memory.buffer)
|
|
353
|
+
) {
|
|
354
|
+
throw new Error(
|
|
355
|
+
"Browser module harness sharedMemory requires shared WebAssembly.Memory backing.",
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
wasi.setMemory(memory);
|
|
106
359
|
}
|
|
107
360
|
if (instance.exports._initialize) {
|
|
108
361
|
instance.exports._initialize();
|
|
362
|
+
} else if (isThreaded && typeof instance.exports._start === "function") {
|
|
363
|
+
// wasi-threads artifacts link the wasi command crt (exports `_start`), not a
|
|
364
|
+
// reactor (`_initialize`). Run `_start` ONCE to execute global constructors
|
|
365
|
+
// + WASI init before any direct invoke. The module declares no command
|
|
366
|
+
// surface, so its main is an empty stub — `_start` runs ctors and proc_exit's
|
|
367
|
+
// out; swallow that exit. Direct-invoke exports remain callable afterward
|
|
368
|
+
// (the linear memory + globals persist).
|
|
369
|
+
try {
|
|
370
|
+
instance.exports._start();
|
|
371
|
+
} catch (error) {
|
|
372
|
+
if (!(error instanceof WasiExitError)) {
|
|
373
|
+
throw error;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
109
376
|
}
|
|
110
377
|
|
|
111
378
|
return {
|
|
112
379
|
instance,
|
|
113
380
|
bridge,
|
|
114
381
|
wasi,
|
|
382
|
+
memory,
|
|
383
|
+
threadHost,
|
|
115
384
|
};
|
|
116
385
|
}
|
|
117
386
|
|
|
@@ -124,23 +393,69 @@ async function instantiateBrowserModule(options = {}) {
|
|
|
124
393
|
* @param {Object} [options.host] - BrowserHost instance (created if omitted).
|
|
125
394
|
* @param {string[]} [options.args] - WASI args passed to the module.
|
|
126
395
|
* @param {Object} [options.env] - WASI environment variables.
|
|
396
|
+
* @param {Object} [options.manifest] - Plugin manifest used to choose the invoke surface.
|
|
127
397
|
* @param {string} [options.surface] - "direct" or "command" (default: auto-detect).
|
|
398
|
+
* @param {WebAssembly.Memory} [options.wasmMemory] - Explicit imported memory.
|
|
399
|
+
* @param {WebAssembly.Memory} [options.memory] - Alias for wasmMemory.
|
|
400
|
+
* @param {boolean} [options.sharedMemory] - Create SharedArrayBuffer-backed imported memory.
|
|
401
|
+
* @param {boolean} [options.allowRawInvoke] - Permit direct-surface raw byte-frame invoke.
|
|
402
|
+
* @param {number} [options.initialMemoryBytes] - Initial imported memory size.
|
|
403
|
+
* @param {number} [options.maximumMemoryBytes] - Maximum imported memory size.
|
|
404
|
+
* @param {number} [options.maxThreads] - Upper bound on guest threads; sizes the
|
|
405
|
+
* browser wasi-threads warm pool. Ignored by single-thread artifacts and by
|
|
406
|
+
* the Node lazy worker path.
|
|
128
407
|
*/
|
|
129
408
|
export async function createBrowserModuleHarness(options = {}) {
|
|
130
|
-
|
|
409
|
+
let wasmSource = options.wasmSource;
|
|
410
|
+
const signaturePolicy = resolveModuleSignaturePolicy(options);
|
|
411
|
+
if (signaturePolicy) {
|
|
412
|
+
if (wasmSource instanceof WebAssembly.Module) {
|
|
413
|
+
throw new ModuleSignatureError(
|
|
414
|
+
"unverifiable_source",
|
|
415
|
+
"Cannot verify a precompiled WebAssembly.Module; pass bytes, a URL, or a Response when signature verification is enabled.",
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
let artifactBytes;
|
|
419
|
+
if (wasmSource instanceof Response) {
|
|
420
|
+
artifactBytes = new Uint8Array(await wasmSource.arrayBuffer());
|
|
421
|
+
} else if (typeof wasmSource === "string") {
|
|
422
|
+
const response = await fetch(wasmSource);
|
|
423
|
+
if (!response.ok) {
|
|
424
|
+
throw new Error(
|
|
425
|
+
`Failed to fetch module artifact for verification: ${response.status}`,
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
artifactBytes = new Uint8Array(await response.arrayBuffer());
|
|
429
|
+
} else {
|
|
430
|
+
artifactBytes =
|
|
431
|
+
wasmSource instanceof ArrayBuffer
|
|
432
|
+
? new Uint8Array(wasmSource)
|
|
433
|
+
: new Uint8Array(wasmSource);
|
|
434
|
+
}
|
|
435
|
+
await verifyModuleArtifact(artifactBytes, signaturePolicy);
|
|
436
|
+
wasmSource = artifactBytes;
|
|
437
|
+
}
|
|
438
|
+
const wasmModule = await compileWasmModule(wasmSource);
|
|
131
439
|
const moduleImports = WebAssembly.Module.imports(wasmModule);
|
|
132
440
|
const needsHostBridge = moduleImports.some(
|
|
133
441
|
(entry) => entry.module === DEFAULT_HOSTCALL_IMPORT_MODULE,
|
|
134
442
|
);
|
|
443
|
+
const hasHostcallDispatch = typeof options.hostcallDispatch === "function";
|
|
135
444
|
const hostOptions =
|
|
136
|
-
!options.host &&
|
|
445
|
+
!options.host &&
|
|
446
|
+
needsHostBridge &&
|
|
447
|
+
!hasHostcallDispatch &&
|
|
448
|
+
!options.hostOptions?.wasmWallet
|
|
137
449
|
? {
|
|
138
450
|
...options.hostOptions,
|
|
139
451
|
wasmWallet: await getWasmWallet(),
|
|
140
452
|
}
|
|
141
453
|
: options.hostOptions;
|
|
142
|
-
|
|
143
|
-
|
|
454
|
+
// With an external hostcallDispatch (worker harness), the host lives on the
|
|
455
|
+
// controlling thread — skip constructing a default local host.
|
|
456
|
+
const host =
|
|
457
|
+
options.host ?? (hasHostcallDispatch ? null : createBrowserHost(hostOptions));
|
|
458
|
+
const dispatchHost = host ? createAsyncHostDispatcher(host) : null;
|
|
144
459
|
|
|
145
460
|
const profile = detectArtifactProfile(wasmModule);
|
|
146
461
|
const moduleExports = WebAssembly.Module.exports(wasmModule);
|
|
@@ -148,11 +463,14 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
148
463
|
|
|
149
464
|
const hasDirectInvoke = exportNames.has(DefaultInvokeExports.invokeSymbol);
|
|
150
465
|
const hasCommand = exportNames.has(DefaultInvokeExports.commandSymbol);
|
|
466
|
+
const manifestSurface = resolveManifestSurface(options.manifest);
|
|
151
467
|
const surface =
|
|
152
|
-
options.surface ??
|
|
468
|
+
options.surface ??
|
|
469
|
+
manifestSurface ??
|
|
470
|
+
(hasDirectInvoke ? "direct" : hasCommand ? "command" : "direct");
|
|
153
471
|
if (profile === "emscripten") {
|
|
154
472
|
throw new Error(
|
|
155
|
-
"Browser harness only supports standalone WASI or
|
|
473
|
+
"Browser harness only supports standalone WASI or space_data_module_host artifacts. " +
|
|
156
474
|
'Compile shared browser/WasmEdge modules with runtimeTargets: ["browser", "wasmedge"] ' +
|
|
157
475
|
'or override threadModel to "single-thread".',
|
|
158
476
|
);
|
|
@@ -161,19 +479,28 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
161
479
|
const activeContext = await instantiateBrowserModule({
|
|
162
480
|
wasmModule,
|
|
163
481
|
host,
|
|
482
|
+
hostcallDispatch: options.hostcallDispatch,
|
|
164
483
|
args: options.args,
|
|
165
484
|
env: options.env,
|
|
166
485
|
performance: options.performance ?? host?.performance,
|
|
167
486
|
logOutput: options.logOutput === true,
|
|
487
|
+
wasmMemory: options.wasmMemory,
|
|
488
|
+
memory: options.memory,
|
|
489
|
+
sharedMemory: options.sharedMemory,
|
|
490
|
+
initialMemoryBytes: options.initialMemoryBytes,
|
|
491
|
+
maximumMemoryBytes: options.maximumMemoryBytes,
|
|
492
|
+
maxThreads: options.maxThreads,
|
|
493
|
+
threadHostcallChannel: options.threadHostcallChannel,
|
|
494
|
+
enableBrowserWasiThreads: options.enableBrowserWasiThreads,
|
|
168
495
|
});
|
|
169
|
-
const { instance, bridge, wasi } = activeContext;
|
|
496
|
+
const { instance, bridge, wasi, memory, threadHost } = activeContext;
|
|
497
|
+
const allowRawInvoke = options.allowRawInvoke !== false;
|
|
170
498
|
|
|
171
499
|
// --- Invoke helpers ---
|
|
172
|
-
function
|
|
500
|
+
function directInvokeRuntime() {
|
|
173
501
|
const alloc = instance.exports[DefaultInvokeExports.allocSymbol];
|
|
174
502
|
const free = instance.exports[DefaultInvokeExports.freeSymbol];
|
|
175
503
|
const invokeStream = instance.exports[DefaultInvokeExports.invokeSymbol];
|
|
176
|
-
const memory = instance.exports.memory;
|
|
177
504
|
if (
|
|
178
505
|
typeof alloc !== "function" ||
|
|
179
506
|
typeof free !== "function" ||
|
|
@@ -184,9 +511,24 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
184
511
|
"Direct browser invoke requires plugin_alloc, plugin_free, plugin_invoke_stream, and memory exports.",
|
|
185
512
|
);
|
|
186
513
|
}
|
|
514
|
+
return { alloc, free, invokeStream, memory };
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
function invokeDirectRaw(requestBytes) {
|
|
518
|
+
if (!allowRawInvoke) {
|
|
519
|
+
throw new Error(
|
|
520
|
+
"Browser module harness raw direct invoke is disabled; use a SharedArrayBuffer-backed externalArena descriptor.",
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
const { alloc, free, invokeStream, memory } = directInvokeRuntime();
|
|
187
524
|
const reqLen = requestBytes.length;
|
|
188
525
|
const reqPtr = alloc(reqLen);
|
|
189
526
|
if (!reqPtr) throw new Error("plugin_alloc returned null for request.");
|
|
527
|
+
if (reqPtr % INVOKE_ARENA_ALIGNMENT !== 0) {
|
|
528
|
+
throw new Error(
|
|
529
|
+
`plugin_alloc returned a request pointer (${reqPtr}) that is not ${INVOKE_ARENA_ALIGNMENT}-byte aligned.`,
|
|
530
|
+
);
|
|
531
|
+
}
|
|
190
532
|
|
|
191
533
|
new Uint8Array(memory.buffer, reqPtr, reqLen).set(requestBytes);
|
|
192
534
|
|
|
@@ -205,21 +547,210 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
205
547
|
if (!resPtr || !resLen) {
|
|
206
548
|
throw new Error("plugin_invoke_stream returned null response.");
|
|
207
549
|
}
|
|
550
|
+
if (resPtr % INVOKE_ARENA_ALIGNMENT !== 0) {
|
|
551
|
+
throw new Error(
|
|
552
|
+
`plugin_invoke_stream returned a response pointer (${resPtr}) that is not ${INVOKE_ARENA_ALIGNMENT}-byte aligned.`,
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const responseBytes = new Uint8Array(memory.buffer, resPtr, resLen).slice();
|
|
557
|
+
free(resPtr, resLen);
|
|
558
|
+
return responseBytes;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function writeDirectInvokeRequestToModuleMemory(request) {
|
|
562
|
+
const { alloc, free, memory } = directInvokeRuntime();
|
|
563
|
+
const allocationSize = Number(
|
|
564
|
+
request?.requestEnvelopeCapacityBytes ??
|
|
565
|
+
options.directInvokeRequestArenaBytes ??
|
|
566
|
+
DEFAULT_DIRECT_INVOKE_REQUEST_ARENA_BYTES,
|
|
567
|
+
);
|
|
568
|
+
if (!Number.isInteger(allocationSize) || allocationSize <= 0) {
|
|
569
|
+
throw new Error(
|
|
570
|
+
"Direct browser invoke request arena capacity must be a positive integer.",
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
const allocationPtr = alloc(allocationSize);
|
|
574
|
+
if (!allocationPtr) {
|
|
575
|
+
throw new Error("plugin_alloc returned null for direct invoke request.");
|
|
576
|
+
}
|
|
577
|
+
if (allocationPtr % INVOKE_ARENA_ALIGNMENT !== 0) {
|
|
578
|
+
free(allocationPtr, allocationSize);
|
|
579
|
+
throw new Error(
|
|
580
|
+
`plugin_alloc returned a direct invoke request pointer (${allocationPtr}) that is not ${INVOKE_ARENA_ALIGNMENT}-byte aligned.`,
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const arena = new Uint8Array(memory.buffer, allocationPtr, allocationSize);
|
|
585
|
+
const payload = writePluginInvokeRequestToArena(request, arena);
|
|
586
|
+
if (payload.buffer !== memory.buffer) {
|
|
587
|
+
throw new Error(
|
|
588
|
+
"Direct browser invoke request was not authored in module memory.",
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
if (payload.byteOffset % INVOKE_ARENA_ALIGNMENT !== 0) {
|
|
592
|
+
throw new Error(
|
|
593
|
+
`Direct browser invoke request pointer (${payload.byteOffset}) is not ${INVOKE_ARENA_ALIGNMENT}-byte aligned.`,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
ptr: payload.byteOffset,
|
|
598
|
+
size: payload.byteLength,
|
|
599
|
+
allocationPtr,
|
|
600
|
+
allocationSize,
|
|
601
|
+
};
|
|
602
|
+
} catch (error) {
|
|
603
|
+
free(allocationPtr, allocationSize);
|
|
604
|
+
throw error;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function freeDirectInvokeRequest({ allocationPtr, allocationSize } = {}) {
|
|
609
|
+
if (
|
|
610
|
+
Number.isInteger(allocationPtr) &&
|
|
611
|
+
Number.isInteger(allocationSize) &&
|
|
612
|
+
allocationPtr > 0 &&
|
|
613
|
+
allocationSize > 0
|
|
614
|
+
) {
|
|
615
|
+
const { free } = directInvokeRuntime();
|
|
616
|
+
free(allocationPtr, allocationSize);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function invokeDirectModuleMemoryRequest({ ptr, size }) {
|
|
621
|
+
const { alloc, free, invokeStream, memory } = directInvokeRuntime();
|
|
622
|
+
if (
|
|
623
|
+
!Number.isInteger(ptr) ||
|
|
624
|
+
!Number.isInteger(size) ||
|
|
625
|
+
ptr <= 0 ||
|
|
626
|
+
size <= 0
|
|
627
|
+
) {
|
|
628
|
+
throw new Error("Direct browser invoke requires a module-memory request descriptor.");
|
|
629
|
+
}
|
|
630
|
+
if (ptr % INVOKE_ARENA_ALIGNMENT !== 0) {
|
|
631
|
+
throw new Error(
|
|
632
|
+
`Direct browser invoke request pointer (${ptr}) is not ${INVOKE_ARENA_ALIGNMENT}-byte aligned.`,
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const outLenPtr = alloc(4);
|
|
637
|
+
if (!outLenPtr) throw new Error("plugin_alloc returned null for response length.");
|
|
638
|
+
|
|
639
|
+
new DataView(memory.buffer).setUint32(outLenPtr, 0, true);
|
|
640
|
+
|
|
641
|
+
const resPtr = invokeStream(ptr, size, outLenPtr);
|
|
642
|
+
const resLen = new DataView(memory.buffer).getUint32(outLenPtr, true);
|
|
643
|
+
|
|
644
|
+
free(outLenPtr, 4);
|
|
645
|
+
|
|
646
|
+
if (!resPtr || !resLen) {
|
|
647
|
+
throw new Error("plugin_invoke_stream returned null response.");
|
|
648
|
+
}
|
|
649
|
+
if (resPtr % INVOKE_ARENA_ALIGNMENT !== 0) {
|
|
650
|
+
throw new Error(
|
|
651
|
+
`plugin_invoke_stream returned a response pointer (${resPtr}) that is not ${INVOKE_ARENA_ALIGNMENT}-byte aligned.`,
|
|
652
|
+
);
|
|
653
|
+
}
|
|
208
654
|
|
|
209
655
|
const responseBytes = new Uint8Array(memory.buffer, resPtr, resLen).slice();
|
|
210
656
|
free(resPtr, resLen);
|
|
211
657
|
return responseBytes;
|
|
212
658
|
}
|
|
213
659
|
|
|
660
|
+
function assertModuleMemoryExternalArena(externalArena, memory) {
|
|
661
|
+
if (!externalArena) {
|
|
662
|
+
throw new TypeError(
|
|
663
|
+
"Direct external arena invoke requires request.externalArena bytes.",
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
if (!isSharedArrayBufferLike(memory.buffer)) {
|
|
667
|
+
throw new Error(
|
|
668
|
+
"Direct externalArena invoke requires SharedArrayBuffer-backed module memory.",
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
if (
|
|
672
|
+
externalArena.buffer !== memory.buffer ||
|
|
673
|
+
externalArena.byteOffset !== 0 ||
|
|
674
|
+
externalArena.byteLength !== memory.buffer.byteLength
|
|
675
|
+
) {
|
|
676
|
+
throw new Error(
|
|
677
|
+
"Direct externalArena invoke requires request.externalArena to be a full Uint8Array view of module memory.",
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function externalArenaFrameDescriptor(frame, externalArena) {
|
|
683
|
+
if (frame?.payload !== undefined && frame?.payload !== null) {
|
|
684
|
+
throw new Error(
|
|
685
|
+
"Direct externalArena input frames must use offset/size descriptors, not payload bytes.",
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
const offset = Number(frame?.offset ?? frame?.OFFSET ?? 0);
|
|
689
|
+
const size = Number(frame?.size ?? frame?.SIZE ?? frame?.byteLength ?? 0);
|
|
690
|
+
if (
|
|
691
|
+
!Number.isInteger(offset) ||
|
|
692
|
+
!Number.isInteger(size) ||
|
|
693
|
+
offset < 0 ||
|
|
694
|
+
size < 0 ||
|
|
695
|
+
offset > externalArena.length ||
|
|
696
|
+
size > externalArena.length - offset
|
|
697
|
+
) {
|
|
698
|
+
throw new Error("Direct external arena frame range exceeds externalArena.");
|
|
699
|
+
}
|
|
700
|
+
return { offset, size };
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function externalArenaInputFrames(request) {
|
|
704
|
+
return Array.isArray(request?.inputs)
|
|
705
|
+
? request.inputs
|
|
706
|
+
: request?.inputFrames ?? [];
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function invokeDirectExternalArena(request) {
|
|
710
|
+
const { memory } = directInvokeRuntime();
|
|
711
|
+
const externalArena = toUint8Array(request?.externalArena);
|
|
712
|
+
assertModuleMemoryExternalArena(externalArena, memory);
|
|
713
|
+
const inputs = externalArenaInputFrames(request).map((frame) => {
|
|
714
|
+
const { offset, size } = externalArenaFrameDescriptor(frame, externalArena);
|
|
715
|
+
const nextFrame = {
|
|
716
|
+
...frame,
|
|
717
|
+
offset,
|
|
718
|
+
size,
|
|
719
|
+
};
|
|
720
|
+
delete nextFrame.payload;
|
|
721
|
+
return nextFrame;
|
|
722
|
+
});
|
|
723
|
+
const requestDescriptor = writeDirectInvokeRequestToModuleMemory({
|
|
724
|
+
...request,
|
|
725
|
+
inputs,
|
|
726
|
+
inputFrames: undefined,
|
|
727
|
+
externalArena,
|
|
728
|
+
});
|
|
729
|
+
try {
|
|
730
|
+
return invokeDirectModuleMemoryRequest(requestDescriptor);
|
|
731
|
+
} finally {
|
|
732
|
+
freeDirectInvokeRequest(requestDescriptor);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
214
736
|
async function invokeCommandRaw(stdinBytes) {
|
|
215
737
|
const commandContext = await instantiateBrowserModule({
|
|
216
738
|
wasmModule,
|
|
217
739
|
host,
|
|
740
|
+
hostcallDispatch: options.hostcallDispatch,
|
|
218
741
|
args: options.args,
|
|
219
742
|
env: options.env,
|
|
220
743
|
stdinBytes,
|
|
221
744
|
performance: options.performance ?? host?.performance,
|
|
222
745
|
logOutput: false,
|
|
746
|
+
wasmMemory: options.wasmMemory,
|
|
747
|
+
memory: options.memory,
|
|
748
|
+
sharedMemory: options.sharedMemory,
|
|
749
|
+
initialMemoryBytes: options.initialMemoryBytes,
|
|
750
|
+
maximumMemoryBytes: options.maximumMemoryBytes,
|
|
751
|
+
maxThreads: options.maxThreads,
|
|
752
|
+
threadHostcallChannel: options.threadHostcallChannel,
|
|
753
|
+
enableBrowserWasiThreads: options.enableBrowserWasiThreads,
|
|
223
754
|
});
|
|
224
755
|
try {
|
|
225
756
|
const commandExport = commandContext.instance.exports[DefaultInvokeExports.commandSymbol];
|
|
@@ -246,13 +777,44 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
246
777
|
return invokeDirectRaw(requestBytes);
|
|
247
778
|
}
|
|
248
779
|
|
|
780
|
+
async function invokeDirect(request) {
|
|
781
|
+
if (surface !== "direct") {
|
|
782
|
+
throw new Error(
|
|
783
|
+
"Browser module harness direct invoke requires the direct surface.",
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
if (request?.externalArena !== undefined) {
|
|
787
|
+
const responseBytes = invokeDirectExternalArena(request);
|
|
788
|
+
const { memory } = directInvokeRuntime();
|
|
789
|
+
const externalArena = new Uint8Array(memory.buffer);
|
|
790
|
+
assertModuleMemoryExternalArena(externalArena, memory);
|
|
791
|
+
return decodePluginInvokeResponse(responseBytes, { externalArena });
|
|
792
|
+
}
|
|
793
|
+
const requestBytes = encodePluginInvokeRequest(request);
|
|
794
|
+
const responseBytes = invokeDirectRaw(requestBytes);
|
|
795
|
+
return decodePluginInvokeResponse(responseBytes);
|
|
796
|
+
}
|
|
797
|
+
|
|
249
798
|
async function invoke(request) {
|
|
799
|
+
if (request?.externalArena !== undefined && surface === "direct") {
|
|
800
|
+
return invokeDirect(request);
|
|
801
|
+
}
|
|
802
|
+
if (request?.externalArena !== undefined) {
|
|
803
|
+
throw new Error(
|
|
804
|
+
"Browser module harness externalArena invoke requires the direct surface.",
|
|
805
|
+
);
|
|
806
|
+
}
|
|
250
807
|
const requestBytes = encodePluginInvokeRequest(request);
|
|
251
808
|
const responseBytes = await invokeRaw(requestBytes);
|
|
252
809
|
return decodePluginInvokeResponse(responseBytes);
|
|
253
810
|
}
|
|
254
811
|
|
|
255
812
|
async function callHost(operation, params = {}) {
|
|
813
|
+
if (!dispatchHost) {
|
|
814
|
+
throw new Error(
|
|
815
|
+
"callHost is unavailable: this harness routes hostcalls through an external hostcallDispatch (no local host).",
|
|
816
|
+
);
|
|
817
|
+
}
|
|
256
818
|
return dispatchHost(operation, params);
|
|
257
819
|
}
|
|
258
820
|
|
|
@@ -267,11 +829,16 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
267
829
|
const size = getSizeExport();
|
|
268
830
|
if (!ptr || !size) return null;
|
|
269
831
|
|
|
270
|
-
|
|
832
|
+
if (!memory) return null;
|
|
833
|
+
|
|
834
|
+
return new Uint8Array(memory.buffer, ptr, size).slice();
|
|
271
835
|
}
|
|
272
836
|
|
|
273
837
|
function destroy() {
|
|
274
838
|
wasi.flushOutput();
|
|
839
|
+
if (threadHost) {
|
|
840
|
+
void threadHost.terminateAll();
|
|
841
|
+
}
|
|
275
842
|
}
|
|
276
843
|
|
|
277
844
|
return {
|
|
@@ -285,7 +852,13 @@ export async function createBrowserModuleHarness(options = {}) {
|
|
|
285
852
|
host,
|
|
286
853
|
bridge,
|
|
287
854
|
wasi,
|
|
855
|
+
memory,
|
|
856
|
+
// Present only for isomorphic-pthreads (wasi-threads) artifacts: exposes the
|
|
857
|
+
// spawn host so callers can observe real thread activity
|
|
858
|
+
// (spawnCount/distinctOsThreadCount).
|
|
859
|
+
threadHost,
|
|
288
860
|
callHost,
|
|
861
|
+
invokeDirect,
|
|
289
862
|
invoke,
|
|
290
863
|
invokeRaw,
|
|
291
864
|
readManifest,
|