@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 +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/live-coding/live-coding-controller.d.ts +2 -0
- package/dist/live-coding/live-coding-controller.d.ts.map +1 -1
- package/dist/live-coding/live-coding-controller.js +1 -0
- package/dist/player-runtime/glue-runtime.d.ts +92 -0
- package/dist/player-runtime/glue-runtime.d.ts.map +1 -0
- package/dist/player-runtime/glue-runtime.js +222 -0
- package/dist/player-runtime/glue-sab.d.ts +55 -0
- package/dist/player-runtime/glue-sab.d.ts.map +1 -0
- package/dist/player-runtime/glue-sab.js +79 -0
- package/dist/player-runtime/player-code-broker.d.ts +16 -0
- package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
- package/dist/player-runtime/player-code-broker.js +38 -3
- package/dist/player-runtime/player-glue-worker.d.ts +26 -54
- package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
- package/dist/player-runtime/player-glue-worker.js +130 -111
- package/package.json +1 -1
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.
|
|
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,
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,6DAA6D;AAC7D,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,6BAA6B,EAC7B,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,cAAc,EACd,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EACL,SAAS,EACT,QAAQ,EACR,UAAU,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,OAAO,EACP,SAAS,EACT,UAAU,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,OAAO,EACP,OAAO,EACP,UAAU,EACV,OAAO,EACP,QAAQ,EACR,cAAc,EACd,SAAS,EACT,SAAS,EACT,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,aAAa,EACb,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,cAAc,EACd,UAAU,EACV,2BAA2B,EAC3B,kBAAkB,EAClB,0BAA0B,EAC1B,cAAc,EACd,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,uBAAuB,EACvB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,cAAc,EACnB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AAQxB,YAAY,EACV,UAAU,EACV,MAAM,EACN,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAOpB,YAAY,EACV,MAAM,EACN,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO1C,OAAO,EACL,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EACL,SAAS,EACT,uBAAuB,EACvB,0BAA0B,EAC1B,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,WAAW,EACX,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,WAAW,EACX,WAAW,EACX,KAAK,OAAO,GACb,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,KAAK,kBAAkB,GACxB,MAAM,4BAA4B,CAAC;AAOpC,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACxB,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAG1B,mBAAmB,EAEnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,eAAe,EACf,+BAA+B,EAC/B,oBAAoB,EACpB,YAAY,EACZ,eAAe,EAEf,KAAK,EACL,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,EACzB,KAAK,EACL,8BAA8B,EAC9B,uBAAuB,EACvB,wBAAwB,EACxB,KAAK,EACL,MAAM,EACN,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,QAAQ,EACR,4BAA4B,EAG5B,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EACpB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,YAAY,EACZ,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EAEvB,OAAO,GACR,MAAM,wBAAwB,CAAC;AAMhC,YAAY,EACV,cAAc,EACd,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC"}
|
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.
|
|
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,
|
|
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;
|
|
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":"
|
|
1
|
+
{"version":3,"file":"player-code-broker.d.ts","sourceRoot":"","sources":["../../src/player-runtime/player-code-broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
-
|
|
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.
|
|
197
|
+
this.reply(raw.reply, id, { type: 'hostcall-result', id, ok: true, data });
|
|
182
198
|
}
|
|
183
199
|
catch (error) {
|
|
184
|
-
this.
|
|
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
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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
|
-
*
|
|
26
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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
|
-
*
|
|
26
|
-
*
|
|
19
|
+
* Re-exports the pure helpers + the runtime so tests and bundlers can use
|
|
20
|
+
* them without touching worker globals.
|
|
27
21
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
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
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
}
|