@crowdedkingdoms/crowdyjs 8.17.0 → 8.18.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/index.d.ts CHANGED
@@ -45,7 +45,7 @@
45
45
  * or internal tooling, never an untrusted browser.
46
46
  */
47
47
  /** The published package version. Mirrors `package.json`. */
48
- export declare const VERSION = "8.15.0";
48
+ export declare const VERSION = "8.18.0";
49
49
  export { LbCookieStore } from './lb-cookie-store.js';
50
50
  export { CrowdyClient, createCrowdyClient, type CrowdyClientConfig, } from './crowdy-client.js';
51
51
  export { BrowserLocalStorageTokenStore, SessionStore, type SessionListener, type TokenStore, } from './session.js';
@@ -94,7 +94,9 @@ export { PlayerWalletAPI } from './domains/playerWallet.js';
94
94
  export { MarketplaceAPI } from './domains/marketplace.js';
95
95
  export { PlayerModelAPI } from './domains/playerModel.js';
96
96
  export { PlayerCodeBroker, type PlayerCodeBrokerOptions, type PlayerCodeGridBounds, type PlayerCodeHostCall, type PlayerCodeWorkerLike, type PlayerCodePresentation, } from './player-runtime/player-code-broker.js';
97
- export { GLUE_HOST_FUNCTIONS, buildImportObject, parseFuelBudget, runWithWatchdog, type GlueInitMessage, type GlueDispatchResult, } from './player-runtime/player-glue-worker.js';
97
+ export { GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, GlueRuntime, startGlueWorker, type GlueInitMessage, type GlueDispatchResult, } from './player-runtime/player-glue-worker.js';
98
+ export { type GuestExports, type GlueRuntimeOptions, } from './player-runtime/glue-runtime.js';
99
+ export { createGlueSab, wrapGlueSab, armGlueRequest, waitAndReadGlueReply, writeGlueResult, writeGlueReply, glueEncoder, glueDecoder, type GlueSab, } from './player-runtime/glue-sab.js';
98
100
  export { LiveCodingController, type LiveCodingControllerOptions, type LiveCodingStatus, type LiveCodingTarget, } from './live-coding/live-coding-controller.js';
99
101
  export { mountLiveCoding, type MountLiveCodingOptions, type LiveCodingHandle, } from './live-coding/mount.js';
100
102
  export { PLAYER_CODE_TEMPLATES, templateById, type PlayerCodeTemplate, } from './live-coding/templates.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -45,7 +45,7 @@
45
45
  * or internal tooling, never an untrusted browser.
46
46
  */
47
47
  /** The published package version. Mirrors `package.json`. */
48
- export const VERSION = '8.15.0';
48
+ export const VERSION = '8.18.0';
49
49
  export { LbCookieStore } from './lb-cookie-store.js';
50
50
  export { CrowdyClient, createCrowdyClient, } from './crowdy-client.js';
51
51
  export { BrowserLocalStorageTokenStore, SessionStore, } from './session.js';
@@ -97,7 +97,8 @@ export { PlayerWalletAPI } from './domains/playerWallet.js';
97
97
  export { MarketplaceAPI } from './domains/marketplace.js';
98
98
  export { PlayerModelAPI } from './domains/playerModel.js';
99
99
  export { PlayerCodeBroker, } from './player-runtime/player-code-broker.js';
100
- export { GLUE_HOST_FUNCTIONS, buildImportObject, parseFuelBudget, runWithWatchdog, } from './player-runtime/player-glue-worker.js';
100
+ export { GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, GlueRuntime, startGlueWorker, } from './player-runtime/player-glue-worker.js';
101
+ export { createGlueSab, wrapGlueSab, armGlueRequest, waitAndReadGlueReply, writeGlueResult, writeGlueReply, glueEncoder, glueDecoder, } from './player-runtime/glue-sab.js';
101
102
  export { LiveCodingController, } from './live-coding/live-coding-controller.js';
102
103
  export { mountLiveCoding, } from './live-coding/mount.js';
103
104
  export { PLAYER_CODE_TEMPLATES, templateById, } from './live-coding/templates.js';
@@ -29,6 +29,8 @@ export interface LiveCodingControllerOptions {
29
29
  /** Page-side host-call router for the broker (World Stores reads + owner effects). */
30
30
  onHostCall: PlayerCodeBrokerOptions['onHostCall'];
31
31
  onPresentation?: PlayerCodeBrokerOptions['onPresentation'];
32
+ /** Client tick cadence (ms); the worker self-drives `tick` for HUD-style mods. */
33
+ clientTickIntervalMs?: number;
32
34
  onStatus?: (status: LiveCodingStatus) => void;
33
35
  /** Poll interval for compile status (ms). */
34
36
  pollMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"live-coding-controller.d.ts","sourceRoot":"","sources":["../../src/live-coding/live-coding-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,yCAAyC,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EACD,MAAM,GACN,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,UAAU,GACV,SAAS,GACT,OAAO,CAAC;IACZ,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,sEAAsE;IACtE,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,IAAI,CACjB,gBAAgB,EAChB,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CACnF,CAAC;IACF,YAAY,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAChD,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,oBAAoB,CAAC;IAC3B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC;IACxB,sFAAsF;IACtF,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,cAAc,CAAC,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;IAC3D,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,gBAAgB,CAAC;CACxE;AAED;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAInB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,MAAM,CAAyD;gBAE1C,OAAO,EAAE,2BAA2B;IAEjE,SAAS,IAAI,gBAAgB;IAI7B,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,KAAK;IAMb,oDAAoD;IAC9C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBnC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,gBAAgB,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;YA6CH,WAAW;YAoBX,SAAS;IA2BvB,IAAI,IAAI,IAAI;CAKb"}
1
+ {"version":3,"file":"live-coding-controller.d.ts","sourceRoot":"","sources":["../../src/live-coding/live-coding-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,yCAAyC,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EACD,MAAM,GACN,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,UAAU,GACV,SAAS,GACT,OAAO,CAAC;IACZ,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,sEAAsE;IACtE,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC;CACH;AAED,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,IAAI,CACjB,gBAAgB,EAChB,QAAQ,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CACnF,CAAC;IACF,YAAY,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAChD,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,oBAAoB,CAAC;IAC3B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC;IACxB,sFAAsF;IACtF,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,cAAc,CAAC,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;IAC3D,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,gBAAgB,CAAC;CACxE;AAED;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAInB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,MAAM,CAAyD;gBAE1C,OAAO,EAAE,2BAA2B;IAEjE,SAAS,IAAI,gBAAgB;IAI7B,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,KAAK;IAMb,oDAAoD;IAC9C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBnC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,gBAAgB,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;YA6CH,WAAW;YAoBX,SAAS;IA4BvB,IAAI,IAAI,IAAI;CAKb"}
@@ -119,6 +119,7 @@ export class LiveCodingController {
119
119
  fuelPerDispatch: artifact.fuelPerDispatch,
120
120
  onHostCall: this.options.onHostCall,
121
121
  onPresentation: this.options.onPresentation,
122
+ tickIntervalMs: this.options.clientTickIntervalMs ?? 1000,
122
123
  };
123
124
  const broker = this.options.brokerFactory?.(options) ?? new PlayerCodeBroker(options);
124
125
  if (this.broker) {
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Factored, environment-agnostic core of the platform glue (player compute
3
+ * P3/P5). This is the ONLY platform code that shares an execution context
4
+ * with an untrusted player module, so it is deliberately tiny and auditable
5
+ * and has NO dependency on worker globals, the DOM, or the SDK client — the
6
+ * browser worker entry ([player-glue-worker.ts]) and the Node integration
7
+ * test both drive this same core.
8
+ *
9
+ * ABI (matches crowdy-compute-sdk `lib.rs`): the guest imports module `ck`
10
+ * with `log`, `now_ms`, `state_get`, `state_set`, and the JSON gateway
11
+ * `host_call(ptr,len) -> u64` (packed `resp_ptr<<32 | resp_len`, guest frees
12
+ * with `ck_free`), plus `wasi_snapshot_preview1.random_get`. The guest
13
+ * exports `memory`, `ck_alloc`, `ck_free`, and the module hooks `init`,
14
+ * `tick(dt_ms)`, `handle_invoke(ptr,len)->u64`, optional `on_event(ptr,len)`.
15
+ *
16
+ * `host_call` is SYNCHRONOUS from the guest's view. The single synchronous
17
+ * dependency this core takes is `hostCallSync(reqBytes) -> respBytes`; the
18
+ * browser/Node entry realizes it with a SharedArrayBuffer + `Atomics.wait`
19
+ * (the worker blocks; the page/broker services the async SDK call and writes
20
+ * the reply back). Everything else here is pure.
21
+ */
22
+ /** The host-call names surfaced to a guest (mirrors the broker allowlist). */
23
+ export declare const GLUE_HOST_FUNCTIONS: readonly ["container_create", "container_get", "containers_list", "container_delete", "property_set", "model_invoke", "user_state_get", "user_state_set", "grid_state_get", "grid_state_set", "chunk_get", "voxels_list", "actors_list", "actors_list_radius", "voxel_set", "emit_spatial", "hud_set", "overlay_draw", "grid_permission_check"];
24
+ export interface GlueInitMessage {
25
+ type: 'init';
26
+ artifact: ArrayBuffer;
27
+ authority: 'player';
28
+ fuelPerDispatch?: string;
29
+ watchdogMs?: number;
30
+ /** Local client tick cadence in ms (0/undefined => no self-tick). */
31
+ tickIntervalMs?: number;
32
+ }
33
+ /** Parse the fuel budget the broker forwards; undefined/invalid => unbounded (server still meters). */
34
+ export declare function parseFuelBudget(raw: string | undefined): bigint | null;
35
+ /** A dispatch outcome the worker reports back to the broker. */
36
+ export type GlueDispatchResult = {
37
+ ok: true;
38
+ } | {
39
+ ok: false;
40
+ reason: 'fuel' | 'watchdog' | 'trap';
41
+ detail?: string;
42
+ };
43
+ /**
44
+ * Wrap a single guest dispatch with the wall-clock watchdog. The fuel trap is
45
+ * enforced inside the gas-injected module; this guards against a hang that
46
+ * spins without consuming fuel. Pure and unit-testable.
47
+ */
48
+ export declare function runWithWatchdog(dispatch: () => unknown, watchdogMs: number, now?: () => number): Promise<GlueDispatchResult>;
49
+ /** The minimal guest-instance surface the runtime drives (a real WebAssembly.Instance satisfies it). */
50
+ export interface GuestExports {
51
+ memory: {
52
+ buffer: ArrayBuffer;
53
+ };
54
+ ck_alloc(len: number): number;
55
+ ck_free?(ptr: number, len: number): void;
56
+ init?(): void;
57
+ tick?(dtMs: number): void;
58
+ handle_invoke?(ptr: number, len: number): bigint | number;
59
+ on_event?(ptr: number, len: number): void;
60
+ }
61
+ export interface GlueRuntimeOptions {
62
+ /** Synchronous host-API gateway: JSON request bytes in, SDK Response-envelope bytes out. */
63
+ hostCallSync: (reqBytes: Uint8Array) => Uint8Array;
64
+ /** debug/info/warn/error sink for guest `ck.log` (optional). */
65
+ onLog?: (level: number, message: string) => void;
66
+ /** Deterministic-enough randomness for the guest `random_get` (defaults to crypto). */
67
+ randomFill?: (buf: Uint8Array) => void;
68
+ now?: () => number;
69
+ }
70
+ /**
71
+ * Drives one untrusted guest module: builds the `ck` + wasi import table,
72
+ * instantiates the artifact, and marshals the synchronous `host_call`
73
+ * gateway across guest linear memory. Durable client state is kept in-worker
74
+ * (a client module's blob is ephemeral per session — the durable store is a
75
+ * host_call away for anything that must survive).
76
+ */
77
+ export declare class GlueRuntime {
78
+ private readonly options;
79
+ private exports;
80
+ private stateBlob;
81
+ constructor(options: GlueRuntimeOptions);
82
+ /** The import object handed to `WebAssembly.instantiate`. Guest sees only these. */
83
+ buildImports(getExports: () => GuestExports | null): WebAssembly.Imports;
84
+ instantiate(artifact: ArrayBuffer): Promise<void>;
85
+ /** Run the module's `init` export (once, after instantiate). */
86
+ init(): void;
87
+ /** Run one `tick(dt_ms)`. Throws propagate to the caller's watchdog wrapper. */
88
+ tick(dtMs: number): void;
89
+ /** Invoke the module with an opaque payload; returns the reply bytes (copied out). */
90
+ invoke(payload: Uint8Array): Uint8Array;
91
+ }
92
+ //# sourceMappingURL=glue-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glue-runtime.d.ts","sourceRoot":"","sources":["../../src/player-runtime/glue-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,iVAoBtB,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQtE;AAED,gEAAgE;AAChE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,OAAO,EACvB,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAM,MAAyB,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED,wGAAwG;AACxG,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1D,QAAQ,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,4FAA4F;IAC5F,YAAY,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,UAAU,CAAC;IACnD,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,uFAAuF;IACvF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAgBD;;;;;;GAMG;AACH,qBAAa,WAAW;IAIV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAiC;gBAErB,OAAO,EAAE,kBAAkB;IAExD,oFAAoF;IACpF,YAAY,CAAC,UAAU,EAAE,MAAM,YAAY,GAAG,IAAI,GAAG,WAAW,CAAC,OAAO;IAkFlE,WAAW,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvD,gEAAgE;IAChE,IAAI,IAAI,IAAI;IAIZ,gFAAgF;IAChF,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxB,sFAAsF;IACtF,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU;CAcxC"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Factored, environment-agnostic core of the platform glue (player compute
3
+ * P3/P5). This is the ONLY platform code that shares an execution context
4
+ * with an untrusted player module, so it is deliberately tiny and auditable
5
+ * and has NO dependency on worker globals, the DOM, or the SDK client — the
6
+ * browser worker entry ([player-glue-worker.ts]) and the Node integration
7
+ * test both drive this same core.
8
+ *
9
+ * ABI (matches crowdy-compute-sdk `lib.rs`): the guest imports module `ck`
10
+ * with `log`, `now_ms`, `state_get`, `state_set`, and the JSON gateway
11
+ * `host_call(ptr,len) -> u64` (packed `resp_ptr<<32 | resp_len`, guest frees
12
+ * with `ck_free`), plus `wasi_snapshot_preview1.random_get`. The guest
13
+ * exports `memory`, `ck_alloc`, `ck_free`, and the module hooks `init`,
14
+ * `tick(dt_ms)`, `handle_invoke(ptr,len)->u64`, optional `on_event(ptr,len)`.
15
+ *
16
+ * `host_call` is SYNCHRONOUS from the guest's view. The single synchronous
17
+ * dependency this core takes is `hostCallSync(reqBytes) -> respBytes`; the
18
+ * browser/Node entry realizes it with a SharedArrayBuffer + `Atomics.wait`
19
+ * (the worker blocks; the page/broker services the async SDK call and writes
20
+ * the reply back). Everything else here is pure.
21
+ */
22
+ /** The host-call names surfaced to a guest (mirrors the broker allowlist). */
23
+ export const GLUE_HOST_FUNCTIONS = [
24
+ 'container_create',
25
+ 'container_get',
26
+ 'containers_list',
27
+ 'container_delete',
28
+ 'property_set',
29
+ 'model_invoke',
30
+ 'user_state_get',
31
+ 'user_state_set',
32
+ 'grid_state_get',
33
+ 'grid_state_set',
34
+ 'chunk_get',
35
+ 'voxels_list',
36
+ 'actors_list',
37
+ 'actors_list_radius',
38
+ 'voxel_set',
39
+ 'emit_spatial',
40
+ 'hud_set',
41
+ 'overlay_draw',
42
+ 'grid_permission_check',
43
+ ];
44
+ /** Parse the fuel budget the broker forwards; undefined/invalid => unbounded (server still meters). */
45
+ export function parseFuelBudget(raw) {
46
+ if (raw == null)
47
+ return null;
48
+ try {
49
+ const v = BigInt(raw);
50
+ return v > 0n ? v : null;
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ /**
57
+ * Wrap a single guest dispatch with the wall-clock watchdog. The fuel trap is
58
+ * enforced inside the gas-injected module; this guards against a hang that
59
+ * spins without consuming fuel. Pure and unit-testable.
60
+ */
61
+ export async function runWithWatchdog(dispatch, watchdogMs, now = () => Date.now()) {
62
+ const start = now();
63
+ try {
64
+ dispatch();
65
+ }
66
+ catch (err) {
67
+ const message = err.message ?? 'trap';
68
+ if (/fuel|gas|unreachable/i.test(message)) {
69
+ return { ok: false, reason: 'fuel', detail: message };
70
+ }
71
+ return { ok: false, reason: 'trap', detail: message };
72
+ }
73
+ if (now() - start > watchdogMs) {
74
+ return { ok: false, reason: 'watchdog' };
75
+ }
76
+ return { ok: true };
77
+ }
78
+ const textDecoder = new TextDecoder();
79
+ function defaultRandomFill(buf) {
80
+ const c = globalThis.crypto;
81
+ if (c?.getRandomValues) {
82
+ // getRandomValues caps at 65536 bytes per call.
83
+ for (let off = 0; off < buf.length; off += 65536) {
84
+ c.getRandomValues(buf.subarray(off, Math.min(off + 65536, buf.length)));
85
+ }
86
+ }
87
+ else {
88
+ for (let i = 0; i < buf.length; i++)
89
+ buf[i] = (Math.random() * 256) | 0;
90
+ }
91
+ }
92
+ /**
93
+ * Drives one untrusted guest module: builds the `ck` + wasi import table,
94
+ * instantiates the artifact, and marshals the synchronous `host_call`
95
+ * gateway across guest linear memory. Durable client state is kept in-worker
96
+ * (a client module's blob is ephemeral per session — the durable store is a
97
+ * host_call away for anything that must survive).
98
+ */
99
+ export class GlueRuntime {
100
+ constructor(options) {
101
+ this.options = options;
102
+ this.exports = null;
103
+ this.stateBlob = new Uint8Array(0);
104
+ }
105
+ /** The import object handed to `WebAssembly.instantiate`. Guest sees only these. */
106
+ buildImports(getExports) {
107
+ const mem = () => {
108
+ const ex = getExports();
109
+ if (!ex)
110
+ throw new Error('guest not instantiated');
111
+ return new DataView(ex.memory.buffer);
112
+ };
113
+ const bytesAt = (ptr, len) => {
114
+ const ex = getExports();
115
+ if (!ex)
116
+ throw new Error('guest not instantiated');
117
+ // Copy into a fresh ArrayBuffer-backed view — the guest buffer may
118
+ // detach/grow between calls (and may be a SharedArrayBuffer).
119
+ const out = new Uint8Array(len);
120
+ out.set(new Uint8Array(ex.memory.buffer, ptr, len));
121
+ return out;
122
+ };
123
+ const writeAt = (ptr, src) => {
124
+ const ex = getExports();
125
+ if (!ex)
126
+ throw new Error('guest not instantiated');
127
+ new Uint8Array(ex.memory.buffer, ptr, src.length).set(src);
128
+ };
129
+ const now = this.options.now ?? (() => Date.now());
130
+ const randomFill = this.options.randomFill ?? defaultRandomFill;
131
+ const ck = {
132
+ log: (level, ptr, len) => {
133
+ if (this.options.onLog) {
134
+ this.options.onLog(level, textDecoder.decode(bytesAt(ptr, len)));
135
+ }
136
+ },
137
+ now_ms: () => BigInt(now()),
138
+ state_get: (dest, cap) => {
139
+ const len = this.stateBlob.length;
140
+ if (dest !== 0 && cap > 0) {
141
+ writeAt(dest, this.stateBlob.subarray(0, Math.min(len, cap)));
142
+ }
143
+ return len;
144
+ },
145
+ state_set: (ptr, len) => {
146
+ this.stateBlob = bytesAt(ptr, len);
147
+ return 0;
148
+ },
149
+ host_call: (ptr, len) => {
150
+ const reqBytes = bytesAt(ptr, len);
151
+ const respBytes = this.options.hostCallSync(reqBytes);
152
+ const ex = getExports();
153
+ if (!ex)
154
+ throw new Error('guest not instantiated');
155
+ const outPtr = ex.ck_alloc(respBytes.length);
156
+ writeAt(outPtr, respBytes);
157
+ // Packed (ptr << 32 | len); the guest reads then ck_frees it.
158
+ return (BigInt(outPtr) << 32n) | BigInt(respBytes.length >>> 0);
159
+ },
160
+ };
161
+ const wasi = {
162
+ random_get: (ptr, len) => {
163
+ const buf = new Uint8Array(len);
164
+ randomFill(buf);
165
+ writeAt(ptr, buf);
166
+ return 0;
167
+ },
168
+ // A player artifact may pull in a few benign wasi stubs; keep them inert.
169
+ proc_exit: () => {
170
+ throw new Error('proc_exit called (guest trap)');
171
+ },
172
+ fd_write: () => 0,
173
+ environ_get: () => 0,
174
+ environ_sizes_get: (envcPtr, envBufSzPtr) => {
175
+ const dv = mem();
176
+ dv.setUint32(envcPtr, 0, true);
177
+ dv.setUint32(envBufSzPtr, 0, true);
178
+ return 0;
179
+ },
180
+ };
181
+ return {
182
+ ck,
183
+ wasi_snapshot_preview1: wasi,
184
+ // Some toolchains name the module `wasi_unstable`; alias defensively.
185
+ wasi_unstable: wasi,
186
+ };
187
+ }
188
+ async instantiate(artifact) {
189
+ const importObject = this.buildImports(() => this.exports);
190
+ const { instance } = await WebAssembly.instantiate(artifact, importObject);
191
+ const ex = instance.exports;
192
+ if (!ex.memory || typeof ex.ck_alloc !== 'function') {
193
+ throw new Error('artifact is missing the ck ABI (memory / ck_alloc)');
194
+ }
195
+ this.exports = ex;
196
+ }
197
+ /** Run the module's `init` export (once, after instantiate). */
198
+ init() {
199
+ this.exports?.init?.();
200
+ }
201
+ /** Run one `tick(dt_ms)`. Throws propagate to the caller's watchdog wrapper. */
202
+ tick(dtMs) {
203
+ this.exports?.tick?.(dtMs);
204
+ }
205
+ /** Invoke the module with an opaque payload; returns the reply bytes (copied out). */
206
+ invoke(payload) {
207
+ const ex = this.exports;
208
+ if (!ex || typeof ex.handle_invoke !== 'function')
209
+ return new Uint8Array(0);
210
+ const ptr = ex.ck_alloc(payload.length);
211
+ new Uint8Array(ex.memory.buffer, ptr, payload.length).set(payload);
212
+ const packed = BigInt(ex.handle_invoke(ptr, payload.length));
213
+ ex.ck_free?.(ptr, payload.length);
214
+ const outPtr = Number(packed >> 32n);
215
+ const outLen = Number(packed & 0xffffffffn);
216
+ if (outLen === 0)
217
+ return new Uint8Array(0);
218
+ const out = new Uint8Array(ex.memory.buffer, outPtr, outLen).slice();
219
+ ex.ck_free?.(outPtr, outLen);
220
+ return out;
221
+ }
222
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The synchronous host-call transport for browser-target player WASM
3
+ * (player compute P5). WASM imports are synchronous, but the host-call
4
+ * handler (the server-authorized SDK path) is async and lives on the page,
5
+ * while the guest runs in a Worker. The only correct bridge is a
6
+ * SharedArrayBuffer the worker blocks on with `Atomics.wait`: the worker
7
+ * writes the request, posts a wake to the page, and blocks; the page
8
+ * services the async call and writes the reply back into the SAB, then
9
+ * `Atomics.notify` wakes the worker. (A worker blocked in `Atomics.wait`
10
+ * cannot receive `postMessage`, which is exactly why the reply must return
11
+ * through the SAB, not a message.)
12
+ *
13
+ * SharedArrayBuffer + Atomics require cross-origin isolation
14
+ * (COOP: same-origin + COEP: require-corp) in the browser; Node worker
15
+ * threads have them unconditionally, which is how this is integration-tested.
16
+ *
17
+ * Layout: [ state:i32, len:i32 ] header, then a byte data region.
18
+ * state: 0 IDLE, 1 PENDING (worker waiting), 2 DONE.
19
+ * The request travels to the page as a normal postMessage (before the
20
+ * worker blocks); only the reply uses the SAB.
21
+ */
22
+ export declare const SAB_STATE_IDLE = 0;
23
+ export declare const SAB_STATE_PENDING = 1;
24
+ export declare const SAB_STATE_DONE = 2;
25
+ export declare const SAB_HEADER_BYTES: number;
26
+ /** 1 MiB reply region — host-call replies (chunk/actor reads) are well under this. */
27
+ export declare const SAB_DATA_BYTES: number;
28
+ export interface GlueSab {
29
+ sab: SharedArrayBuffer;
30
+ header: Int32Array;
31
+ data: Uint8Array;
32
+ }
33
+ export declare function createGlueSab(dataBytes?: number): GlueSab;
34
+ export declare function wrapGlueSab(sab: SharedArrayBuffer): GlueSab;
35
+ declare const encoder: TextEncoder;
36
+ declare const decoder: TextDecoder;
37
+ /**
38
+ * Responder side (page/broker): write the reply envelope bytes into the SAB
39
+ * and wake the blocked worker. `respBytes` must already be the SDK Response
40
+ * envelope (`{ok,data}` / `{ok:false,error}`) the guest expects.
41
+ */
42
+ export declare function writeGlueReply(view: GlueSab, respBytes: Uint8Array): void;
43
+ /** Convenience for responders holding a plain object result. */
44
+ export declare function writeGlueResult(view: GlueSab, result: unknown): void;
45
+ /**
46
+ * Requester side (worker): mark PENDING before posting the wake, block until
47
+ * the page flips the state to DONE, then read the reply bytes out. The
48
+ * caller is responsible for posting the request message between `arm()` and
49
+ * `waitAndRead()` — that ordering (post, then wait) is what lets the page
50
+ * see the request while the worker is blocked.
51
+ */
52
+ export declare function armGlueRequest(view: GlueSab): void;
53
+ export declare function waitAndReadGlueReply(view: GlueSab, timeoutMs?: number): Uint8Array;
54
+ export { encoder as glueEncoder, decoder as glueDecoder };
55
+ //# sourceMappingURL=glue-sab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glue-sab.d.ts","sourceRoot":"","sources":["../../src/player-runtime/glue-sab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,cAAc,IAAI,CAAC;AAGhC,eAAO,MAAM,gBAAgB,QAAiB,CAAC;AAC/C,sFAAsF;AACtF,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,iBAAiB,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,SAAS,SAAiB,GAAG,OAAO,CAGjE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAM3D;AAED,QAAA,MAAM,OAAO,aAAoB,CAAC;AAClC,QAAA,MAAM,OAAO,aAAoB,CAAC;AAElC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,IAAI,CAMzE;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGlD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,SAAO,GAAG,UAAU,CAShF;AAED,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The synchronous host-call transport for browser-target player WASM
3
+ * (player compute P5). WASM imports are synchronous, but the host-call
4
+ * handler (the server-authorized SDK path) is async and lives on the page,
5
+ * while the guest runs in a Worker. The only correct bridge is a
6
+ * SharedArrayBuffer the worker blocks on with `Atomics.wait`: the worker
7
+ * writes the request, posts a wake to the page, and blocks; the page
8
+ * services the async call and writes the reply back into the SAB, then
9
+ * `Atomics.notify` wakes the worker. (A worker blocked in `Atomics.wait`
10
+ * cannot receive `postMessage`, which is exactly why the reply must return
11
+ * through the SAB, not a message.)
12
+ *
13
+ * SharedArrayBuffer + Atomics require cross-origin isolation
14
+ * (COOP: same-origin + COEP: require-corp) in the browser; Node worker
15
+ * threads have them unconditionally, which is how this is integration-tested.
16
+ *
17
+ * Layout: [ state:i32, len:i32 ] header, then a byte data region.
18
+ * state: 0 IDLE, 1 PENDING (worker waiting), 2 DONE.
19
+ * The request travels to the page as a normal postMessage (before the
20
+ * worker blocks); only the reply uses the SAB.
21
+ */
22
+ export const SAB_STATE_IDLE = 0;
23
+ export const SAB_STATE_PENDING = 1;
24
+ export const SAB_STATE_DONE = 2;
25
+ const HEADER_I32 = 2; // state, len
26
+ export const SAB_HEADER_BYTES = HEADER_I32 * 4;
27
+ /** 1 MiB reply region — host-call replies (chunk/actor reads) are well under this. */
28
+ export const SAB_DATA_BYTES = 1024 * 1024;
29
+ export function createGlueSab(dataBytes = SAB_DATA_BYTES) {
30
+ const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + dataBytes);
31
+ return wrapGlueSab(sab);
32
+ }
33
+ export function wrapGlueSab(sab) {
34
+ return {
35
+ sab,
36
+ header: new Int32Array(sab, 0, HEADER_I32),
37
+ data: new Uint8Array(sab, SAB_HEADER_BYTES),
38
+ };
39
+ }
40
+ const encoder = new TextEncoder();
41
+ const decoder = new TextDecoder();
42
+ /**
43
+ * Responder side (page/broker): write the reply envelope bytes into the SAB
44
+ * and wake the blocked worker. `respBytes` must already be the SDK Response
45
+ * envelope (`{ok,data}` / `{ok:false,error}`) the guest expects.
46
+ */
47
+ export function writeGlueReply(view, respBytes) {
48
+ const len = Math.min(respBytes.length, view.data.length);
49
+ view.data.set(respBytes.subarray(0, len));
50
+ Atomics.store(view.header, 1, len);
51
+ Atomics.store(view.header, 0, SAB_STATE_DONE);
52
+ Atomics.notify(view.header, 0, 1);
53
+ }
54
+ /** Convenience for responders holding a plain object result. */
55
+ export function writeGlueResult(view, result) {
56
+ writeGlueReply(view, encoder.encode(JSON.stringify(result)));
57
+ }
58
+ /**
59
+ * Requester side (worker): mark PENDING before posting the wake, block until
60
+ * the page flips the state to DONE, then read the reply bytes out. The
61
+ * caller is responsible for posting the request message between `arm()` and
62
+ * `waitAndRead()` — that ordering (post, then wait) is what lets the page
63
+ * see the request while the worker is blocked.
64
+ */
65
+ export function armGlueRequest(view) {
66
+ Atomics.store(view.header, 1, 0);
67
+ Atomics.store(view.header, 0, SAB_STATE_PENDING);
68
+ }
69
+ export function waitAndReadGlueReply(view, timeoutMs = 5000) {
70
+ const res = Atomics.wait(view.header, 0, SAB_STATE_PENDING, timeoutMs);
71
+ if (res === 'timed-out') {
72
+ throw new Error('host call timed out');
73
+ }
74
+ const len = Atomics.load(view.header, 1);
75
+ const out = view.data.slice(0, len);
76
+ Atomics.store(view.header, 0, SAB_STATE_IDLE);
77
+ return out;
78
+ }
79
+ export { encoder as glueEncoder, decoder as glueDecoder };
@@ -51,6 +51,12 @@ export interface PlayerCodeBrokerOptions {
51
51
  hashArtifact?: (artifact: ArrayBuffer) => Promise<string>;
52
52
  /** Wall-clock ms allowed per dispatch before the broker recycles the worker. */
53
53
  dispatchWatchdogMs?: number;
54
+ /**
55
+ * Local tick cadence (ms) for a client mod: the worker self-drives `tick`
56
+ * at this interval. Omit/0 for invoke-only mods (no periodic tick). A HUD
57
+ * mod typically ticks ~1 Hz; the per-dispatch watchdog still bounds each.
58
+ */
59
+ tickIntervalMs?: number;
54
60
  }
55
61
  /**
56
62
  * Page-side security broker for browser-target player WASM (production shape,
@@ -92,6 +98,16 @@ export declare class PlayerCodeBroker {
92
98
  /** Clear a tripped circuit so the caller can start again after a fix. */
93
99
  resetCircuit(): void;
94
100
  private handleMessage;
101
+ /**
102
+ * Deliver a host-call reply. Always posts the message (the offline test
103
+ * shape + any async-transport consumer), and — when the worker shared a
104
+ * SharedArrayBuffer for this call — ALSO writes the SDK Response envelope
105
+ * into it and wakes the worker blocked in Atomics.wait. The synchronous
106
+ * guest can only receive the reply through the SAB (a blocked worker never
107
+ * runs its message handler), so the SAB write is the load-bearing path in
108
+ * the browser; the postMessage is harmless there.
109
+ */
110
+ private reply;
95
111
  private enforceRate;
96
112
  private recordTrap;
97
113
  private assertGridScope;
@@ -1 +1 @@
1
- {"version":3,"file":"player-code-broker.d.ts","sourceRoot":"","sources":["../../src/player-runtime/player-code-broker.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,IAAI,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAC/D,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,IAAI,GAC/C,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,IAAI,GAC/C,IAAI,CAAC;IACR,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,KAAK,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC;IACxB,IAAI,EAAE,oBAAoB,CAAC;IAC3B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,iFAAiF;IACjF,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAChE,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,KAAK,oBAAoB,CAAC;IAC5D,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA+DD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAExB;gBAE2B,OAAO,EAAE,uBAAuB;IAE7D;;;;OAIG;IACG,KAAK,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCjD,4EAA4E;IACtE,OAAO,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,IAAI,IAAI,IAAI;IAOZ,yEAAyE;IACzE,YAAY,IAAI,IAAI;YAMN,aAAa;IAkD3B,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,WAAW;YAiBL,IAAI;CAOnB"}
1
+ {"version":3,"file":"player-code-broker.d.ts","sourceRoot":"","sources":["../../src/player-runtime/player-code-broker.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,IAAI,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAC/D,gBAAgB,CACd,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,IAAI,GAC/C,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,IAAI,GAC/C,IAAI,CAAC;IACR,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,KAAK,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC;IACxB,IAAI,EAAE,oBAAoB,CAAC;IAC3B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,iFAAiF;IACjF,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAChE,iFAAiF;IACjF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,KAAK,oBAAoB,CAAC;IAC5D,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAiED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAExB;gBAE2B,OAAO,EAAE,uBAAuB;IAE7D;;;;OAIG;IACG,KAAK,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCjD,4EAA4E;IACtE,OAAO,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,IAAI,IAAI,IAAI;IAOZ,yEAAyE;IACzE,YAAY,IAAI,IAAI;YAMN,aAAa;IA8D3B;;;;;;;;OAQG;IACH,OAAO,CAAC,KAAK;IAeb,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,WAAW;YAiBL,IAAI;CAOnB"}
@@ -1,3 +1,4 @@
1
+ import { wrapGlueSab, writeGlueResult } from './glue-sab.js';
1
2
  /**
2
3
  * Deny-by-default host-call allowlist, grouped by capability (04 §4). Only
3
4
  * owner-lawful reads and effects cross the bridge; auth, admin, authoring,
@@ -28,7 +29,9 @@ const ALLOWED_HOST_CALLS = {
28
29
  world_write: new Set(['voxel_set']),
29
30
  egress: new Set(['emit_spatial']),
30
31
  present: new Set(['hud_set', 'overlay_draw']),
31
- meta: new Set(['grid_permission_check']),
32
+ // grid_info is answered by the broker itself (the mod's own clamped bounds),
33
+ // so a client mod can address its grid without a server round-trip.
34
+ meta: new Set(['grid_permission_check', 'grid_info']),
32
35
  };
33
36
  /** Per-call-family rate caps (calls per rolling second); flood one, others hold. */
34
37
  const RATE_CAPS = {
@@ -114,6 +117,7 @@ export class PlayerCodeBroker {
114
117
  ? this.options.fuelPerDispatch.toString()
115
118
  : undefined,
116
119
  watchdogMs: this.options.dispatchWatchdogMs ?? 250,
120
+ tickIntervalMs: this.options.tickIntervalMs ?? 0,
117
121
  }, [artifact]);
118
122
  }
119
123
  /** Terminate + respawn on a fresh artifact — the client hot-reload path. */
@@ -166,6 +170,18 @@ export class PlayerCodeBroker {
166
170
  this.enforceRate(group, raw.fn);
167
171
  this.assertGridScope(raw.fn, args);
168
172
  let data;
173
+ if (raw.fn === 'grid_info') {
174
+ // Answered locally: the mod's own clamped grid bounds, so it can
175
+ // address its chunks without knowing world coordinates or a server
176
+ // round-trip. Chunk coords cross as decimal strings (may exceed 2^53).
177
+ const { low, high } = this.options.grid;
178
+ data = {
179
+ low: { x: low.x.toString(), y: low.y.toString(), z: low.z.toString() },
180
+ high: { x: high.x.toString(), y: high.y.toString(), z: high.z.toString() },
181
+ };
182
+ this.reply(raw.reply, id, { type: 'hostcall-result', id, ok: true, data });
183
+ return;
184
+ }
169
185
  if (PRESENTATION_FUNCTIONS.has(raw.fn)) {
170
186
  // Presentation never reaches the SDK/server: it goes only to the
171
187
  // game-declared channel. A game that offers no sink silently drops it.
@@ -178,10 +194,10 @@ export class PlayerCodeBroker {
178
194
  else {
179
195
  data = await this.options.onHostCall({ fn: raw.fn, args });
180
196
  }
181
- this.worker?.postMessage({ type: 'hostcall-result', id, ok: true, data });
197
+ this.reply(raw.reply, id, { type: 'hostcall-result', id, ok: true, data });
182
198
  }
183
199
  catch (error) {
184
- this.worker?.postMessage({
200
+ this.reply(raw.reply, id, {
185
201
  type: 'hostcall-result',
186
202
  id,
187
203
  ok: false,
@@ -189,6 +205,25 @@ export class PlayerCodeBroker {
189
205
  });
190
206
  }
191
207
  }
208
+ /**
209
+ * Deliver a host-call reply. Always posts the message (the offline test
210
+ * shape + any async-transport consumer), and — when the worker shared a
211
+ * SharedArrayBuffer for this call — ALSO writes the SDK Response envelope
212
+ * into it and wakes the worker blocked in Atomics.wait. The synchronous
213
+ * guest can only receive the reply through the SAB (a blocked worker never
214
+ * runs its message handler), so the SAB write is the load-bearing path in
215
+ * the browser; the postMessage is harmless there.
216
+ */
217
+ reply(replyBuffer, _id, message) {
218
+ this.worker?.postMessage(message);
219
+ if (typeof SharedArrayBuffer !== 'undefined' && replyBuffer instanceof SharedArrayBuffer) {
220
+ const view = wrapGlueSab(replyBuffer);
221
+ const envelope = message.ok
222
+ ? { ok: true, data: message.data }
223
+ : { ok: false, error: message.error };
224
+ writeGlueResult(view, envelope);
225
+ }
226
+ }
192
227
  enforceRate(group, fn) {
193
228
  const cap = RATE_CAPS[group] ?? 60;
194
229
  const now = Date.now();
@@ -1,62 +1,34 @@
1
1
  /**
2
- * Platform glue worker for browser-target player WASM (player compute P3).
3
- *
4
- * This is the ONLY platform code that shares an execution context with an
5
- * untrusted player module. It runs inside a dedicated Web Worker and is
6
- * deliberately tiny and auditable:
2
+ * Browser Web Worker entry for browser-target player WASM (player compute
3
+ * P3/P5). This is the ONLY platform code that shares an execution context
4
+ * with an untrusted player module. It is intentionally thin: the auditable
5
+ * runtime + ABI marshalling live in [glue-runtime.ts] and the synchronous
6
+ * host-call transport in [glue-sab.ts]; this file only wires them to the
7
+ * worker message loop.
7
8
  *
8
9
  * - it instantiates the gas-injected player artifact with an import table
9
- * that exposes ONLY the `ck.*` host functions (every one forwards to the
10
- * page-side broker; nothing else is importable),
11
- * - it never has the DOM, `window`, auth tokens, `fetch`, or `importScripts`
12
- * of third-party code,
13
- * - it enforces a per-dispatch wall-clock watchdog and forwards the fuel
14
- * budget so a runaway dispatch traps locally (the fuel counter itself is
15
- * injected into the artifact by the server compile pipeline),
16
- * - it reports traps to the broker, which owns the local circuit breaker.
17
- *
18
- * Host calls are synchronous from the guest's perspective. In a worker that
19
- * is realized with a SharedArrayBuffer control block plus Atomics.wait: the
20
- * guest's import stub writes the request, wakes the page, and blocks until
21
- * the broker writes the reply. The message/really-shared plumbing lives in
22
- * buildImportObject / the init handler below; the pure, testable pieces
23
- * (budget parsing, host-fn table) are exported.
10
+ * that exposes ONLY `ck.*` + inert wasi stubs (nothing else importable),
11
+ * - it never has the DOM, `window`, auth tokens, `fetch`, or third-party
12
+ * `importScripts`,
13
+ * - `ck.host_call` blocks the worker on a SharedArrayBuffer while the
14
+ * page-side broker services the (async) server-authorized call and writes
15
+ * the reply back, so the guest sees a synchronous gateway,
16
+ * - it enforces a per-dispatch wall-clock watchdog and reports traps to the
17
+ * broker, which owns the local circuit breaker.
24
18
  *
25
- * This module is bundled to a standalone worker asset; it must not import
26
- * anything that pulls in the SDK client, DOM types, or Node built-ins.
27
- */
28
- /** The exact host-call names the glue exposes to the guest (mirrors the broker allowlist). */
29
- export declare const GLUE_HOST_FUNCTIONS: readonly ["container_create", "container_get", "containers_list", "container_delete", "property_set", "model_invoke", "user_state_get", "user_state_set", "grid_state_get", "grid_state_set", "chunk_get", "voxels_list", "actors_list", "actors_list_radius", "voxel_set", "emit_spatial", "hud_set", "overlay_draw", "grid_permission_check"];
30
- export interface GlueInitMessage {
31
- type: 'init';
32
- artifact: ArrayBuffer;
33
- authority: 'player';
34
- fuelPerDispatch?: string;
35
- watchdogMs?: number;
36
- }
37
- /** Parse the fuel budget the broker forwards; undefined/invalid => unbounded (server still meters). */
38
- export declare function parseFuelBudget(raw: string | undefined): bigint | null;
39
- /** A dispatch outcome the worker reports back to the broker. */
40
- export type GlueDispatchResult = {
41
- ok: true;
42
- } | {
43
- ok: false;
44
- reason: 'fuel' | 'watchdog' | 'trap';
45
- detail?: string;
46
- };
47
- /**
48
- * Wrap a single guest dispatch with the wall-clock watchdog. The fuel trap is
49
- * enforced inside the gas-injected module; this guards against a hang that
50
- * spins without consuming fuel (e.g. a tight host-call loop the broker rate
51
- * cap already bounds, belt-and-suspenders). Pure and unit-testable.
19
+ * Re-exports the pure helpers + the runtime so tests and bundlers can use
20
+ * them without touching worker globals.
52
21
  */
53
- export declare function runWithWatchdog(dispatch: () => unknown, watchdogMs: number, now?: () => number): Promise<GlueDispatchResult>;
22
+ import { GlueRuntime, GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, type GlueInitMessage, type GlueDispatchResult } from './glue-runtime.js';
23
+ export { GlueRuntime, GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, type GlueInitMessage, type GlueDispatchResult, };
54
24
  /**
55
- * Build the guest import object. Every entry is a `ck.*` host stub that
56
- * forwards to the broker; the function set is fixed at build time, so a guest
57
- * cannot import anything outside GLUE_HOST_FUNCTIONS. `invokeHostCall` is the
58
- * synchronous bridge (SharedArrayBuffer + Atomics in the browser; injectable
59
- * for tests).
25
+ * Wire the glue runtime to a worker-like message port. Exported (not just
26
+ * run at import) so the Node integration test can drive the identical wiring
27
+ * over a `worker_threads` port.
60
28
  */
61
- export declare function buildImportObject(invokeHostCall: (fn: string, argsJson: string) => string): WebAssembly.Imports;
29
+ export declare function startGlueWorker(port: {
30
+ addEventListener?: (t: string, l: (e: MessageEvent) => void) => void;
31
+ on?: (t: string, l: (data: unknown) => void) => void;
32
+ postMessage: (message: unknown) => void;
33
+ }): void;
62
34
  //# sourceMappingURL=player-glue-worker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"player-glue-worker.d.ts","sourceRoot":"","sources":["../../src/player-runtime/player-glue-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,8FAA8F;AAC9F,eAAO,MAAM,mBAAmB,iVAoBtB,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQtE;AAED,gEAAgE;AAChE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,OAAO,EACvB,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAM,MAAyB,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GACvD,WAAW,CAAC,OAAO,CAgBrB"}
1
+ {"version":3,"file":"player-glue-worker.d.ts","sourceRoot":"","sources":["../../src/player-runtime/player-glue-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,CAAC;AAOF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,KAAK,IAAI,CAAC;IACrE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC,GAAG,IAAI,CAuGP"}
@@ -1,127 +1,146 @@
1
1
  /**
2
- * Platform glue worker for browser-target player WASM (player compute P3).
3
- *
4
- * This is the ONLY platform code that shares an execution context with an
5
- * untrusted player module. It runs inside a dedicated Web Worker and is
6
- * deliberately tiny and auditable:
2
+ * Browser Web Worker entry for browser-target player WASM (player compute
3
+ * P3/P5). This is the ONLY platform code that shares an execution context
4
+ * with an untrusted player module. It is intentionally thin: the auditable
5
+ * runtime + ABI marshalling live in [glue-runtime.ts] and the synchronous
6
+ * host-call transport in [glue-sab.ts]; this file only wires them to the
7
+ * worker message loop.
7
8
  *
8
9
  * - it instantiates the gas-injected player artifact with an import table
9
- * that exposes ONLY the `ck.*` host functions (every one forwards to the
10
- * page-side broker; nothing else is importable),
11
- * - it never has the DOM, `window`, auth tokens, `fetch`, or `importScripts`
12
- * of third-party code,
13
- * - it enforces a per-dispatch wall-clock watchdog and forwards the fuel
14
- * budget so a runaway dispatch traps locally (the fuel counter itself is
15
- * injected into the artifact by the server compile pipeline),
16
- * - it reports traps to the broker, which owns the local circuit breaker.
17
- *
18
- * Host calls are synchronous from the guest's perspective. In a worker that
19
- * is realized with a SharedArrayBuffer control block plus Atomics.wait: the
20
- * guest's import stub writes the request, wakes the page, and blocks until
21
- * the broker writes the reply. The message/really-shared plumbing lives in
22
- * buildImportObject / the init handler below; the pure, testable pieces
23
- * (budget parsing, host-fn table) are exported.
10
+ * that exposes ONLY `ck.*` + inert wasi stubs (nothing else importable),
11
+ * - it never has the DOM, `window`, auth tokens, `fetch`, or third-party
12
+ * `importScripts`,
13
+ * - `ck.host_call` blocks the worker on a SharedArrayBuffer while the
14
+ * page-side broker services the (async) server-authorized call and writes
15
+ * the reply back, so the guest sees a synchronous gateway,
16
+ * - it enforces a per-dispatch wall-clock watchdog and reports traps to the
17
+ * broker, which owns the local circuit breaker.
24
18
  *
25
- * This module is bundled to a standalone worker asset; it must not import
26
- * anything that pulls in the SDK client, DOM types, or Node built-ins.
19
+ * Re-exports the pure helpers + the runtime so tests and bundlers can use
20
+ * them without touching worker globals.
27
21
  */
28
- /** The exact host-call names the glue exposes to the guest (mirrors the broker allowlist). */
29
- export const GLUE_HOST_FUNCTIONS = [
30
- 'container_create',
31
- 'container_get',
32
- 'containers_list',
33
- 'container_delete',
34
- 'property_set',
35
- 'model_invoke',
36
- 'user_state_get',
37
- 'user_state_set',
38
- 'grid_state_get',
39
- 'grid_state_set',
40
- 'chunk_get',
41
- 'voxels_list',
42
- 'actors_list',
43
- 'actors_list_radius',
44
- 'voxel_set',
45
- 'emit_spatial',
46
- 'hud_set',
47
- 'overlay_draw',
48
- 'grid_permission_check',
49
- ];
50
- /** Parse the fuel budget the broker forwards; undefined/invalid => unbounded (server still meters). */
51
- export function parseFuelBudget(raw) {
52
- if (raw == null)
53
- return null;
54
- try {
55
- const v = BigInt(raw);
56
- return v > 0n ? v : null;
57
- }
58
- catch {
59
- return null;
60
- }
61
- }
22
+ import { GlueRuntime, GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, } from './glue-runtime.js';
23
+ import { createGlueSab, armGlueRequest, waitAndReadGlueReply, } from './glue-sab.js';
24
+ export { GlueRuntime, GLUE_HOST_FUNCTIONS, parseFuelBudget, runWithWatchdog, };
62
25
  /**
63
- * Wrap a single guest dispatch with the wall-clock watchdog. The fuel trap is
64
- * enforced inside the gas-injected module; this guards against a hang that
65
- * spins without consuming fuel (e.g. a tight host-call loop the broker rate
66
- * cap already bounds, belt-and-suspenders). Pure and unit-testable.
26
+ * Wire the glue runtime to a worker-like message port. Exported (not just
27
+ * run at import) so the Node integration test can drive the identical wiring
28
+ * over a `worker_threads` port.
67
29
  */
68
- export async function runWithWatchdog(dispatch, watchdogMs, now = () => Date.now()) {
69
- const start = now();
70
- try {
71
- dispatch();
72
- }
73
- catch (err) {
74
- const message = err.message ?? 'trap';
75
- if (/fuel|gas|unreachable/i.test(message)) {
76
- return { ok: false, reason: 'fuel', detail: message };
30
+ export function startGlueWorker(port) {
31
+ let runtime = null;
32
+ let sab = null;
33
+ let hostCallId = 0;
34
+ let watchdogMs = 250;
35
+ let ticking = false;
36
+ const post = (message) => port.postMessage(message);
37
+ // Synchronous gateway: post the request (so the page can see it), then
38
+ // block on the SAB until the broker writes the reply.
39
+ const hostCallSync = (reqBytes) => {
40
+ if (!sab)
41
+ throw new Error('host-call transport not initialized');
42
+ let parsed;
43
+ try {
44
+ parsed = JSON.parse(new TextDecoder().decode(reqBytes));
77
45
  }
78
- return { ok: false, reason: 'trap', detail: message };
79
- }
80
- if (now() - start > watchdogMs) {
81
- return { ok: false, reason: 'watchdog' };
82
- }
83
- return { ok: true };
84
- }
85
- /**
86
- * Build the guest import object. Every entry is a `ck.*` host stub that
87
- * forwards to the broker; the function set is fixed at build time, so a guest
88
- * cannot import anything outside GLUE_HOST_FUNCTIONS. `invokeHostCall` is the
89
- * synchronous bridge (SharedArrayBuffer + Atomics in the browser; injectable
90
- * for tests).
91
- */
92
- export function buildImportObject(invokeHostCall) {
93
- const ck = {};
94
- for (const fn of GLUE_HOST_FUNCTIONS) {
95
- ck[fn] = (argsPtr, argsLen, outPtr) => {
96
- // The real ABI marshals argsPtr/argsLen out of guest memory and writes
97
- // the reply back at outPtr; the memory plumbing is wired in the init
98
- // handler where the instance's memory export is available. This stub
99
- // documents the fixed surface and the synchronous forward.
100
- void argsPtr;
101
- void argsLen;
102
- void outPtr;
103
- const reply = invokeHostCall(fn, '');
104
- return reply.length;
46
+ catch {
47
+ throw new Error('host_call request was not valid JSON');
48
+ }
49
+ const id = ++hostCallId;
50
+ armGlueRequest(sab);
51
+ post({
52
+ type: 'hostcall',
53
+ id,
54
+ fn: parsed.fn,
55
+ args: parsed.args ?? {},
56
+ reply: sab.sab,
57
+ });
58
+ return waitAndReadGlueReply(sab);
59
+ };
60
+ const onInit = async (init) => {
61
+ watchdogMs = init.watchdogMs ?? 250;
62
+ void parseFuelBudget(init.fuelPerDispatch);
63
+ sab = createGlueSab();
64
+ runtime = new GlueRuntime({
65
+ hostCallSync,
66
+ onLog: (level, message) => post({ type: 'log', level, message }),
67
+ });
68
+ try {
69
+ await runtime.instantiate(init.artifact);
70
+ const initResult = await runWithWatchdog(() => runtime.init(), watchdogMs);
71
+ report(initResult);
72
+ if ((init.tickIntervalMs ?? 0) > 0)
73
+ startTicking(init.tickIntervalMs);
74
+ post({ type: 'ready' });
75
+ }
76
+ catch (err) {
77
+ post({ type: 'trap', reason: 'trap', detail: err.message });
78
+ }
79
+ };
80
+ const report = (result) => {
81
+ if (result.ok)
82
+ post({ type: 'dispatch-ok' });
83
+ else
84
+ post({ type: 'trap', reason: result.reason, detail: result.detail });
85
+ };
86
+ const startTicking = (intervalMs) => {
87
+ if (ticking)
88
+ return;
89
+ ticking = true;
90
+ let last = Date.now();
91
+ const loop = () => {
92
+ if (!ticking || !runtime)
93
+ return;
94
+ const nowT = Date.now();
95
+ const dt = nowT - last;
96
+ last = nowT;
97
+ void runWithWatchdog(() => runtime.tick(dt), watchdogMs).then(report);
98
+ setTimeout(loop, intervalMs);
105
99
  };
100
+ setTimeout(loop, intervalMs);
101
+ };
102
+ const handle = (data) => {
103
+ if (!data || typeof data !== 'object')
104
+ return;
105
+ const msg = data;
106
+ if (msg.type === 'init')
107
+ void onInit(msg);
108
+ else if (msg.type === 'tick' && runtime) {
109
+ void runWithWatchdog(() => runtime.tick(typeof msg.dtMs === 'number' ? msg.dtMs : 0), watchdogMs).then(report);
110
+ }
111
+ else if (msg.type === 'invoke' && runtime) {
112
+ const payload = msg.payload instanceof Uint8Array ? msg.payload : new Uint8Array(0);
113
+ try {
114
+ const out = runtime.invoke(payload);
115
+ post({ type: 'invoke-result', id: msg.id, ok: true, payload: out });
116
+ }
117
+ catch (err) {
118
+ post({
119
+ type: 'invoke-result',
120
+ id: msg.id,
121
+ ok: false,
122
+ error: err.message,
123
+ });
124
+ }
125
+ }
126
+ else if (msg.type === 'stop') {
127
+ ticking = false;
128
+ }
129
+ };
130
+ if (port.addEventListener) {
131
+ port.addEventListener('message', (e) => handle(e.data));
132
+ }
133
+ else if (port.on) {
134
+ port.on('message', (d) => handle(d));
106
135
  }
107
- return { ck };
108
136
  }
137
+ // Auto-start when loaded as a real browser Web Worker (has addEventListener,
138
+ // no window). Guarded so importing for the pure helpers never touches globals.
109
139
  if (typeof self !== 'undefined' &&
110
140
  typeof self.addEventListener === 'function' &&
111
141
  typeof self.window === 'undefined') {
112
- self.addEventListener('message', (event) => {
113
- const data = event.data;
114
- if (!data || typeof data !== 'object')
115
- return;
116
- if (data.type === 'init') {
117
- const init = data;
118
- // The synchronous host-call bridge (SharedArrayBuffer + Atomics) is set
119
- // up here from init.fuelPerDispatch/watchdogMs; instantiation uses
120
- // buildImportObject so the guest sees only ck.* host functions.
121
- void parseFuelBudget(init.fuelPerDispatch);
122
- void (init.watchdogMs ?? 250);
123
- self.postMessage?.({ type: 'ready' });
124
- return;
125
- }
142
+ startGlueWorker({
143
+ addEventListener: self.addEventListener.bind(self),
144
+ postMessage: (m) => self.postMessage?.(m),
126
145
  });
127
146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdedkingdoms/crowdyjs",
3
- "version": "8.17.0",
3
+ "version": "8.18.0",
4
4
  "description": "Client SDK for Crowded Kingdoms GraphQL API with UDP proxy support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",