@spearwolf/shadow-objects 0.33.0 → 0.34.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.
Files changed (210) hide show
  1. package/CHANGELOG.md +320 -61
  2. package/README.md +57 -13
  3. package/bundle.js +5 -54
  4. package/package.json +7 -3
  5. package/src/ChangeTrailRefusedError.d.ts +27 -0
  6. package/src/ChangeTrailRefusedError.d.ts.map +1 -0
  7. package/src/ChangeTrailRefusedError.js +12 -0
  8. package/src/ChangeTrailRefusedError.js.map +7 -0
  9. package/src/EntityUuidInUseError.d.ts +19 -0
  10. package/src/EntityUuidInUseError.d.ts.map +1 -0
  11. package/src/EntityUuidInUseError.js +11 -0
  12. package/src/EntityUuidInUseError.js.map +7 -0
  13. package/src/WorkerTimeoutError.d.ts +25 -0
  14. package/src/WorkerTimeoutError.d.ts.map +1 -0
  15. package/src/WorkerTimeoutError.js +12 -0
  16. package/src/WorkerTimeoutError.js.map +7 -0
  17. package/src/bundle.d.ts +1 -1
  18. package/src/bundle.d.ts.map +1 -1
  19. package/src/bundle.js +1 -1
  20. package/src/bundle.js.map +2 -2
  21. package/src/constants.d.ts +9 -2
  22. package/src/constants.d.ts.map +1 -1
  23. package/src/constants.js +1 -1
  24. package/src/constants.js.map +2 -2
  25. package/src/create-worker.bundle.d.ts +1 -1
  26. package/src/create-worker.bundle.d.ts.map +1 -1
  27. package/src/create-worker.bundle.js.map +1 -1
  28. package/src/create-worker.d.ts +1 -1
  29. package/src/create-worker.d.ts.map +1 -1
  30. package/src/create-worker.js.map +1 -1
  31. package/src/elements/ShaeElement.d.ts +70 -2
  32. package/src/elements/ShaeElement.d.ts.map +1 -1
  33. package/src/elements/ShaeElement.js +129 -25
  34. package/src/elements/ShaeElement.js.map +3 -3
  35. package/src/elements/ShaeEntElement.d.ts +39 -1
  36. package/src/elements/ShaeEntElement.d.ts.map +1 -1
  37. package/src/elements/ShaeEntElement.js +397 -167
  38. package/src/elements/ShaeEntElement.js.map +2 -2
  39. package/src/elements/ShaeLifecycleElement.d.ts +71 -0
  40. package/src/elements/ShaeLifecycleElement.d.ts.map +1 -0
  41. package/src/elements/ShaeLifecycleElement.js +83 -0
  42. package/src/elements/ShaeLifecycleElement.js.map +7 -0
  43. package/src/elements/ShaePropElement.d.ts +52 -2
  44. package/src/elements/ShaePropElement.d.ts.map +1 -1
  45. package/src/elements/ShaePropElement.js +240 -219
  46. package/src/elements/ShaePropElement.js.map +2 -2
  47. package/src/elements/ShaeWorkerElement.d.ts +49 -5
  48. package/src/elements/ShaeWorkerElement.d.ts.map +1 -1
  49. package/src/elements/ShaeWorkerElement.js +204 -73
  50. package/src/elements/ShaeWorkerElement.js.map +2 -2
  51. package/src/elements/constants.d.ts +6 -0
  52. package/src/elements/constants.d.ts.map +1 -1
  53. package/src/elements/constants.js +12 -0
  54. package/src/elements/constants.js.map +2 -2
  55. package/src/elements/deferredTeardown.d.ts +24 -0
  56. package/src/elements/deferredTeardown.d.ts.map +1 -0
  57. package/src/elements/deferredTeardown.js +30 -0
  58. package/src/elements/deferredTeardown.js.map +7 -0
  59. package/src/elements/displayContentsRule.d.ts +25 -0
  60. package/src/elements/displayContentsRule.d.ts.map +1 -0
  61. package/src/elements/displayContentsRule.js +37 -0
  62. package/src/elements/displayContentsRule.js.map +7 -0
  63. package/src/elements/events.d.ts +10 -7
  64. package/src/elements/events.d.ts.map +1 -1
  65. package/src/elements/forwardCustomEvents.d.ts +19 -0
  66. package/src/elements/forwardCustomEvents.d.ts.map +1 -0
  67. package/src/elements/forwardCustomEvents.js +47 -0
  68. package/src/elements/forwardCustomEvents.js.map +7 -0
  69. package/src/elements/hostedSlots.d.ts +36 -0
  70. package/src/elements/hostedSlots.d.ts.map +1 -0
  71. package/src/elements/hostedSlots.js +118 -0
  72. package/src/elements/hostedSlots.js.map +7 -0
  73. package/src/elements/parentRemoval.d.ts +18 -0
  74. package/src/elements/parentRemoval.d.ts.map +1 -0
  75. package/src/elements/parentRemoval.js +60 -0
  76. package/src/elements/parentRemoval.js.map +7 -0
  77. package/src/elements/propValueConverters.d.ts +3 -0
  78. package/src/elements/propValueConverters.d.ts.map +1 -0
  79. package/src/elements/propValueConverters.js +54 -0
  80. package/src/elements/propValueConverters.js.map +7 -0
  81. package/src/elements/requestEntAncestor.d.ts +32 -0
  82. package/src/elements/requestEntAncestor.d.ts.map +1 -0
  83. package/src/elements/requestEntAncestor.js +16 -0
  84. package/src/elements/requestEntAncestor.js.map +7 -0
  85. package/src/elements.js.map +1 -1
  86. package/src/in-the-dark/Entity.d.ts +113 -3
  87. package/src/in-the-dark/Entity.d.ts.map +1 -1
  88. package/src/in-the-dark/Entity.js +292 -63
  89. package/src/in-the-dark/Entity.js.map +3 -3
  90. package/src/in-the-dark/Kernel.d.ts +76 -17
  91. package/src/in-the-dark/Kernel.d.ts.map +1 -1
  92. package/src/in-the-dark/Kernel.js +410 -378
  93. package/src/in-the-dark/Kernel.js.map +3 -3
  94. package/src/in-the-dark/Registry.d.ts.map +1 -1
  95. package/src/in-the-dark/Registry.js +83 -14
  96. package/src/in-the-dark/Registry.js.map +2 -2
  97. package/src/in-the-dark/ShadowObject.d.ts.map +1 -1
  98. package/src/in-the-dark/ShadowObject.js +1 -0
  99. package/src/in-the-dark/ShadowObject.js.map +2 -2
  100. package/src/in-the-dark/ShadowObjectCreationScope.d.ts +126 -0
  101. package/src/in-the-dark/ShadowObjectCreationScope.d.ts.map +1 -0
  102. package/src/in-the-dark/ShadowObjectCreationScope.js +596 -0
  103. package/src/in-the-dark/ShadowObjectCreationScope.js.map +7 -0
  104. package/src/in-the-dark/SignalsPath.d.ts.map +1 -1
  105. package/src/in-the-dark/SignalsPath.js +2 -2
  106. package/src/in-the-dark/SignalsPath.js.map +2 -2
  107. package/src/in-the-dark/events.js.map +1 -1
  108. package/src/in-the-dark/importModule.d.ts +7 -0
  109. package/src/in-the-dark/importModule.d.ts.map +1 -1
  110. package/src/in-the-dark/importModule.js +5 -2
  111. package/src/in-the-dark/importModule.js.map +2 -2
  112. package/src/index.d.ts +7 -1
  113. package/src/index.d.ts.map +1 -1
  114. package/src/index.js +5 -1
  115. package/src/index.js.map +2 -2
  116. package/src/shadow-objects.d.ts +2 -0
  117. package/src/shadow-objects.d.ts.map +1 -1
  118. package/src/shadow-objects.js +2 -0
  119. package/src/shadow-objects.js.map +2 -2
  120. package/src/shadow-objects.worker.js +0 -1
  121. package/src/shadow-objects.worker.js.map +2 -2
  122. package/src/shae-ent.js.map +1 -1
  123. package/src/shae-prop.js +2 -2
  124. package/src/shae-prop.js.map +2 -2
  125. package/src/shae-worker.js.map +1 -1
  126. package/src/types.d.ts +35 -4
  127. package/src/types.d.ts.map +1 -1
  128. package/src/utils/ConsoleLogger.d.ts +45 -10
  129. package/src/utils/ConsoleLogger.d.ts.map +1 -1
  130. package/src/utils/ConsoleLogger.js +51 -26
  131. package/src/utils/ConsoleLogger.js.map +2 -2
  132. package/src/utils/FrameLoop.d.ts +42 -3
  133. package/src/utils/FrameLoop.d.ts.map +1 -1
  134. package/src/utils/FrameLoop.js +71 -10
  135. package/src/utils/FrameLoop.js.map +2 -2
  136. package/src/utils/MicrotaskCollector.d.ts +45 -0
  137. package/src/utils/MicrotaskCollector.d.ts.map +1 -0
  138. package/src/utils/MicrotaskCollector.js +33 -0
  139. package/src/utils/MicrotaskCollector.js.map +7 -0
  140. package/src/utils/MicrotaskGate.d.ts +17 -0
  141. package/src/utils/MicrotaskGate.d.ts.map +1 -0
  142. package/src/utils/MicrotaskGate.js +20 -0
  143. package/src/utils/MicrotaskGate.js.map +7 -0
  144. package/src/utils/array-utils.js.map +1 -1
  145. package/src/utils/attr-utils.d.ts +6 -0
  146. package/src/utils/attr-utils.d.ts.map +1 -1
  147. package/src/utils/attr-utils.js +3 -1
  148. package/src/utils/attr-utils.js.map +2 -2
  149. package/src/utils/constants.js.map +1 -1
  150. package/src/utils/generateUUID.d.ts +11 -0
  151. package/src/utils/generateUUID.d.ts.map +1 -1
  152. package/src/utils/generateUUID.js +31 -266
  153. package/src/utils/generateUUID.js.map +2 -2
  154. package/src/utils/props-utils.d.ts +3 -2
  155. package/src/utils/props-utils.d.ts.map +1 -1
  156. package/src/utils/props-utils.js +13 -24
  157. package/src/utils/props-utils.js.map +2 -2
  158. package/src/utils/runGuarded.d.ts +27 -0
  159. package/src/utils/runGuarded.d.ts.map +1 -0
  160. package/src/utils/runGuarded.js +11 -0
  161. package/src/utils/runGuarded.js.map +7 -0
  162. package/src/utils/toMaybe.d.ts.map +1 -1
  163. package/src/utils/toMaybe.js.map +1 -1
  164. package/src/utils/toNamespace.d.ts.map +1 -1
  165. package/src/utils/toNamespace.js.map +1 -1
  166. package/src/utils/toUrlString.d.ts +12 -0
  167. package/src/utils/toUrlString.d.ts.map +1 -1
  168. package/src/utils/toUrlString.js.map +2 -2
  169. package/src/utils/waitForMessageOfType.d.ts +12 -1
  170. package/src/utils/waitForMessageOfType.d.ts.map +1 -1
  171. package/src/utils/waitForMessageOfType.js +16 -1
  172. package/src/utils/waitForMessageOfType.js.map +2 -2
  173. package/src/view/ComponentChanges.d.ts +88 -1
  174. package/src/view/ComponentChanges.d.ts.map +1 -1
  175. package/src/view/ComponentChanges.js +243 -73
  176. package/src/view/ComponentChanges.js.map +2 -2
  177. package/src/view/ComponentContext.d.ts +206 -16
  178. package/src/view/ComponentContext.d.ts.map +1 -1
  179. package/src/view/ComponentContext.js +548 -91
  180. package/src/view/ComponentContext.js.map +2 -2
  181. package/src/view/ComponentMemory.d.ts +3 -3
  182. package/src/view/ComponentMemory.d.ts.map +1 -1
  183. package/src/view/ComponentMemory.js.map +1 -1
  184. package/src/view/IShadowObjectEnvProxy.d.ts +29 -3
  185. package/src/view/IShadowObjectEnvProxy.d.ts.map +1 -1
  186. package/src/view/LocalShadowObjectEnv.d.ts +1 -1
  187. package/src/view/LocalShadowObjectEnv.d.ts.map +1 -1
  188. package/src/view/LocalShadowObjectEnv.js +8 -6
  189. package/src/view/LocalShadowObjectEnv.js.map +2 -2
  190. package/src/view/RemoteWorkerEnv.d.ts +89 -5
  191. package/src/view/RemoteWorkerEnv.d.ts.map +1 -1
  192. package/src/view/RemoteWorkerEnv.js +195 -77
  193. package/src/view/RemoteWorkerEnv.js.map +2 -2
  194. package/src/view/ShadowEnv.d.ts +49 -2
  195. package/src/view/ShadowEnv.d.ts.map +1 -1
  196. package/src/view/ShadowEnv.js +223 -60
  197. package/src/view/ShadowEnv.js.map +2 -2
  198. package/src/view/ViewComponent.d.ts +78 -14
  199. package/src/view/ViewComponent.d.ts.map +1 -1
  200. package/src/view/ViewComponent.js +90 -14
  201. package/src/view/ViewComponent.js.map +2 -2
  202. package/src/view/cloneChangeTrail.js.map +2 -2
  203. package/src/worker/MessageRouter.d.ts +14 -0
  204. package/src/worker/MessageRouter.d.ts.map +1 -1
  205. package/src/worker/MessageRouter.js +75 -15
  206. package/src/worker/MessageRouter.js.map +2 -2
  207. package/src/worker/WorkerRuntime.d.ts +22 -1
  208. package/src/worker/WorkerRuntime.d.ts.map +1 -1
  209. package/src/worker/WorkerRuntime.js +60 -8
  210. package/src/worker/WorkerRuntime.js.map +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/worker/MessageRouter.ts"],
4
- "sourcesContent": ["import {off, on} from '@spearwolf/eventize';\nimport {\n AppliedChangeTrail,\n ChangeTrail,\n Configure,\n Destroy,\n Destroyed,\n ImportedModule,\n MessageToView,\n ShadowObjectsExport,\n} from '../constants.js';\nimport {importModule} from '../in-the-dark/importModule.js';\nimport {Kernel, type MessageToViewEvent} from '../in-the-dark/Kernel.js';\nimport type {AppliedChangeTrailEvent, ImportedModuleEvent, ShadowObjectsModule, SyncEvent} from '../types.js';\nimport {toUrlString} from '../utils/toUrlString.js';\n\ninterface ConfigurePayloadData {\n importModule?: string;\n}\n\nexport interface MessageRouterOptions {\n kernel?: Kernel;\n postMessage?: typeof self.postMessage;\n}\n\nexport class MessageRouter {\n #importedModules: Set<ShadowObjectsModule> = new Set();\n\n kernel: Kernel;\n\n postMessage: typeof self.postMessage;\n\n constructor(options?: MessageRouterOptions) {\n this.kernel = options?.kernel ?? new Kernel();\n\n this.postMessage = options?.postMessage ?? self.postMessage.bind(self);\n\n on(this.kernel, MessageToView, 'onMessageToView', this);\n }\n\n route(event: MessageEvent) {\n switch (event.data.type) {\n case Configure:\n this.#configure(event.data);\n break;\n\n case ChangeTrail:\n this.#onChangeTrail(event.data);\n break;\n\n case Destroy:\n this.#onDestroy(event.data);\n break;\n\n default:\n console.warn('[MessageRouter] unknown message', event.data.type ?? event.data);\n }\n }\n\n onMessageToView(event: MessageToViewEvent) {\n const {transferables: transfer, ...data} = event;\n this.postMessage({type: MessageToView, data}, {transfer});\n }\n\n async #configure(data: ConfigurePayloadData) {\n const url = data.importModule;\n try {\n if (!url) throw new Error('missing \"importModule\" url');\n const module = await import(/* @vite-ignore */ toUrlString(url));\n if (module[ShadowObjectsExport]) {\n await importModule(this.kernel, module[ShadowObjectsExport], this.#importedModules);\n this.postMessage({type: ImportedModule, url});\n } else {\n this.postMessage({\n type: ImportedModule,\n url,\n error: `module has no \"${ShadowObjectsExport}\" export`,\n } as ImportedModuleEvent);\n }\n } catch (error) {\n console.error('[MessageRouter] failed to import module', error);\n this.postMessage({type: ImportedModule, url, error: `${error}`} as ImportedModuleEvent);\n }\n }\n\n #onChangeTrail(data: SyncEvent) {\n // console.debug('[MessageRouter] parseChangeTrail', {data, kernel: this.kernel});\n\n try {\n this.kernel.run(data);\n } catch (error) {\n console.error('[MessageRouter] failed to apply change trail', error);\n this.postMessage({type: AppliedChangeTrail, serial: data.serial, error: `${error}`} as AppliedChangeTrailEvent);\n }\n\n if (data.serial) {\n this.postMessage({type: AppliedChangeTrail, serial: data.serial} as AppliedChangeTrailEvent);\n }\n }\n\n #onDestroy(data: any) {\n console.debug('[MessageRouter] on destroy', data);\n off(this.kernel, this);\n this.#importedModules.clear();\n this.postMessage({type: Destroyed});\n }\n}"],
5
- "mappings": "AAAA,SAAQ,KAAK,UAAS;AACtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAQ,oBAAmB;AAC3B,SAAQ,cAAsC;AAE9C,SAAQ,mBAAkB;AAWnB,MAAM,cAAc;AAAA,EACzB,mBAA6C,oBAAI,IAAI;AAAA,EAMrD,YAAY,SAAgC;AAC1C,SAAK,SAAS,SAAS,UAAU,IAAI,OAAO;AAE5C,SAAK,cAAc,SAAS,eAAe,KAAK,YAAY,KAAK,IAAI;AAErE,OAAG,KAAK,QAAQ,eAAe,mBAAmB,IAAI;AAAA,EACxD;AAAA,EAEA,MAAM,OAAqB;AACzB,YAAQ,MAAM,KAAK,MAAM;AAAA,MACvB,KAAK;AACH,aAAK,WAAW,MAAM,IAAI;AAC1B;AAAA,MAEF,KAAK;AACH,aAAK,eAAe,MAAM,IAAI;AAC9B;AAAA,MAEF,KAAK;AACH,aAAK,WAAW,MAAM,IAAI;AAC1B;AAAA,MAEF;AACE,gBAAQ,KAAK,mCAAmC,MAAM,KAAK,QAAQ,MAAM,IAAI;AAAA,IACjF;AAAA,EACF;AAAA,EAEA,gBAAgB,OAA2B;AACzC,UAAM,EAAC,eAAe,UAAU,GAAG,KAAI,IAAI;AAC3C,SAAK,YAAY,EAAC,MAAM,eAAe,KAAI,GAAG,EAAC,SAAQ,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAM,WAAW,MAA4B;AAC3C,UAAM,MAAM,KAAK;AACjB,QAAI;AACF,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4BAA4B;AACtD,YAAM,SAAS,MAAM;AAAA;AAAA,QAA0B,YAAY,GAAG;AAAA;AAC9D,UAAI,OAAO,mBAAmB,GAAG;AAC/B,cAAM,aAAa,KAAK,QAAQ,OAAO,mBAAmB,GAAG,KAAK,gBAAgB;AAClF,aAAK,YAAY,EAAC,MAAM,gBAAgB,IAAG,CAAC;AAAA,MAC9C,OAAO;AACL,aAAK,YAAY;AAAA,UACf,MAAM;AAAA,UACN;AAAA,UACA,OAAO,kBAAkB,mBAAmB;AAAA,QAC9C,CAAwB;AAAA,MAC1B;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,2CAA2C,KAAK;AAC9D,WAAK,YAAY,EAAC,MAAM,gBAAgB,KAAK,OAAO,GAAG,KAAK,GAAE,CAAwB;AAAA,IACxF;AAAA,EACF;AAAA,EAEA,eAAe,MAAiB;AAG9B,QAAI;AACF,WAAK,OAAO,IAAI,IAAI;AAAA,IACtB,SAAS,OAAO;AACd,cAAQ,MAAM,gDAAgD,KAAK;AACnE,WAAK,YAAY,EAAC,MAAM,oBAAoB,QAAQ,KAAK,QAAQ,OAAO,GAAG,KAAK,GAAE,CAA4B;AAAA,IAChH;AAEA,QAAI,KAAK,QAAQ;AACf,WAAK,YAAY,EAAC,MAAM,oBAAoB,QAAQ,KAAK,OAAM,CAA4B;AAAA,IAC7F;AAAA,EACF;AAAA,EAEA,WAAW,MAAW;AACpB,YAAQ,MAAM,8BAA8B,IAAI;AAChD,QAAI,KAAK,QAAQ,IAAI;AACrB,SAAK,iBAAiB,MAAM;AAC5B,SAAK,YAAY,EAAC,MAAM,UAAS,CAAC;AAAA,EACpC;AACF;",
4
+ "sourcesContent": ["import {off, on} from '@spearwolf/eventize';\nimport {ChangeTrailRefusedError} from '../ChangeTrailRefusedError.js';\nimport {\n AppliedChangeTrail,\n ChangeTrail,\n Configure,\n Destroy,\n Destroyed,\n ImportedModule,\n MessageToView,\n ShadowObjectsExport,\n} from '../constants.js';\nimport {importModule, missingShadowObjectsExportMessage} from '../in-the-dark/importModule.js';\nimport {Kernel, type MessageToViewEvent} from '../in-the-dark/Kernel.js';\nimport type {AppliedChangeTrailEvent, ImportedModuleEvent, ShadowObjectsModule, SyncEvent} from '../types.js';\nimport {ConsoleLogger} from '../utils/ConsoleLogger.js';\nimport {toUrlString} from '../utils/toUrlString.js';\n\ninterface ConfigurePayloadData {\n importModule?: string;\n}\n\n/**\n * The teardown request carries nothing but its own type: there is no field a sender could vary,\n * and the router reads none. Named all the same -- the three routes then read alike, and a\n * payload that says which message it is says more than one that says nothing at all.\n */\ninterface DestroyPayloadData {\n type: typeof Destroy;\n}\n\n/**\n * A payload this side can read is an object: every branch below takes a `type` off it and\n * then reads further fields. `null`, `undefined`, a number or a string come from someone who\n * does not speak this protocol, and reading through them takes the whole worker down over one\n * message. Deliberately a plain boolean rather than a type predicate: `event.data` is `any` on\n * both call sites, and narrowing it would only cost the branches below the payload types they\n * already have.\n */\nexport const isReadableMessageData = (data: unknown): boolean => typeof data === 'object' && data !== null;\n\n/**\n * Reduces a throw to the two fields that survive the wire. `RemoteWorkerEnv` builds an error\n * from them, and it decides between a confirmation and a refusal by whether `error` is there\n * at all -- so the wording must never come out empty, not even for an `Error` carrying no\n * message of its own.\n *\n * Reading a throw means running its code: `String()` goes through its `toString()`, and\n * `message` and `name` can be getters of the thrown value's own making. A value that throws\n * from there -- an object whose `toString()` fails, one with no prototype at all -- must not\n * take the answer with it: the caller in the view is waiting on a reply, and without one it\n * sits out its `configureTimeout` or `changeTrailTimeout` and learns nothing about why.\n */\nconst describeError = (error: unknown): {error: string; errorName?: string} => {\n try {\n return error instanceof Error\n ? {error: error.message || String(error), errorName: error.name}\n : {error: String(error) || 'unknown error'};\n } catch {\n // No name goes with it: whatever the value would have said about itself is exactly what\n // could not be read. The throw is already on the console -- both callers log it before\n // they ask for a description.\n return {error: 'an error that cannot be described'};\n }\n};\n\nexport interface MessageRouterOptions {\n kernel?: Kernel;\n postMessage?: typeof self.postMessage;\n}\n\nexport class MessageRouter {\n #importedModules: Set<ShadowObjectsModule> = new Set();\n\n /**\n * Built in the field initializer rather than on first read, the way the lazy getter\n * `WorkerRuntime.logger` has to be: a `MessageRouter` is only ever built from\n * `WorkerRuntime.onmessage`, and only past the branch that answers the `CONSOLE_LOGGER`\n * configuration message and returns -- so by the time this initializer runs, that configuration\n * has already been installed. The `Kernel` this router holds builds its own logger the same way,\n * in its own field initializer, on the same guarantee; which of the two is built first is not\n * something either one depends on.\n */\n readonly #logger = new ConsoleLogger('MessageRouter');\n\n /** The logger this router reports through. */\n get logger(): ConsoleLogger {\n return this.#logger;\n }\n\n #isDestroyed = false;\n\n /** Whether this router has been torn down. Once it is, every message that reaches it is discarded. */\n get isDestroyed(): boolean {\n return this.#isDestroyed;\n }\n\n kernel: Kernel;\n\n postMessage: typeof self.postMessage;\n\n constructor(options?: MessageRouterOptions) {\n this.kernel = options?.kernel ?? new Kernel();\n\n this.postMessage = options?.postMessage ?? self.postMessage.bind(self);\n\n on(this.kernel, MessageToView, 'onMessageToView', this);\n }\n\n route(event: MessageEvent) {\n const data = event.data;\n\n if (!isReadableMessageData(data)) {\n this.logger.debug('discarding a message it cannot read', data);\n return;\n }\n\n // After the teardown the kernel is empty and nothing of it reaches the view any more, so a\n // change trail applied here would build entities nobody ever hears about. A second destroy\n // meets the same barrier: the confirmation belongs to the destroy that was answered, and the\n // one waiter there is settled on it.\n if (this.#isDestroyed) {\n this.logger.debug('discarding a message that arrived after the teardown', data.type);\n return;\n }\n\n switch (data.type) {\n case Configure:\n this.#configure(data);\n break;\n\n case ChangeTrail:\n this.#onChangeTrail(data);\n break;\n\n case Destroy:\n this.#onDestroy(data);\n break;\n\n default:\n this.logger.warn('unknown message', data.type ?? data);\n }\n }\n\n onMessageToView(event: MessageToViewEvent) {\n const {transferables: transfer, ...data} = event;\n // WebIDL defaults `transfer` to `[]`, so a missing key and an empty list are the same call.\n this.postMessage({type: MessageToView, data}, {transfer: transfer ?? []});\n }\n\n async #configure(data: ConfigurePayloadData) {\n const url = data.importModule;\n try {\n if (!url) throw new Error('missing \"importModule\" url');\n const module = await import(/* @vite-ignore */ toUrlString(url));\n\n // the import outlived a teardown that happened while it was in flight: registering it now\n // would fill a kernel that is already down\n if (this.#isDestroyed) {\n this.logger.debug('discarding a module that arrived after the teardown', url);\n return;\n }\n\n if (module[ShadowObjectsExport]) {\n await importModule(this.kernel, module[ShadowObjectsExport], this.#importedModules);\n this.postMessage({type: ImportedModule, url});\n } else {\n this.postMessage({\n type: ImportedModule,\n url,\n error: missingShadowObjectsExportMessage,\n } as ImportedModuleEvent);\n }\n } catch (error) {\n // an error report is not gated on a debug switch, the same way `RemoteWorkerEnv` keeps its\n // own error reports ungated: a failure is worth printing regardless of what debug logging\n // is set to\n this.logger.error('failed to import module', error);\n this.postMessage({type: ImportedModule, url, ...describeError(error)} as ImportedModuleEvent);\n }\n }\n\n #onChangeTrail(data: SyncEvent) {\n // One change trail, one confirmation -- and only where a serial asked for one. A caller\n // waiting on that serial decides between rejection and resolution on the first message it\n // sees, so a second one behind it would make the outcome a matter of order.\n // A serial is either on the message or it is not; zero is a number like any other, and\n // the sender that chose it is waiting for its answer.\n try {\n this.kernel.run(data);\n } catch (error) {\n this.logger.error('failed to apply change trail', error);\n if (data.serial != null) {\n const refusal = error instanceof ChangeTrailRefusedError ? error : undefined;\n this.postMessage({\n type: AppliedChangeTrail,\n serial: data.serial,\n // what the entry threw, not the refusal wrapped around it: the number travels in a\n // field of its own, so the reason stays the reason\n ...describeError(refusal?.cause ?? error),\n ...(refusal ? {appliedCount: refusal.appliedCount} : {}),\n } as AppliedChangeTrailEvent);\n }\n return;\n }\n\n if (data.serial != null) {\n this.postMessage({type: AppliedChangeTrail, serial: data.serial} as AppliedChangeTrailEvent);\n }\n }\n\n #onDestroy(data: DestroyPayloadData) {\n this.logger.debug('on destroy', data);\n\n // `route()` is the barrier, so this runs once: every later message, a second destroy included,\n // is discarded before it gets here.\n this.#isDestroyed = true;\n\n // taken off before the kernel goes down: a message a teardown callback dispatches reaches\n // the view a microtask later, behind the confirmation this call is about to send. What an\n // `onDestroy` sends to the view during a worker teardown is therefore dropped, where a\n // local environment still delivers it.\n off(this.kernel, this);\n\n try {\n this.kernel.destroy();\n } catch (error) {\n // the confirmation is owed either way -- without it the view sits out its destroy\n // timeout before terminating the worker, and learns nothing it could act on\n this.logger.error('failed to tear the kernel down', error);\n }\n\n // releases the module objects this router imported; nothing can import into it again\n this.#importedModules.clear();\n\n this.postMessage({type: Destroyed});\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,28 @@
1
+ import { ConsoleLogger } from '../utils/ConsoleLogger.js';
1
2
  import { MessageRouter } from './MessageRouter.js';
2
3
  export declare class WorkerRuntime {
3
- router?: MessageRouter;
4
+ #private;
5
+ router?: MessageRouter | undefined;
6
+ /**
7
+ * Built on first use rather than in a field initializer: a `ConsoleLogger` reads its own
8
+ * `<namespace>.enable` key once, when it is built, and in a worker the config that key lives in
9
+ * arrives as a message. A logger built ahead of that message keeps the default for its own switch
10
+ * for the rest of the thread; the shared switches reach it either way.
11
+ *
12
+ * The window is narrow: the two guard branches of `onmessage` that discard a message it cannot
13
+ * read or a message that arrived after the teardown reach for this logger ahead of the
14
+ * `CONSOLE_LOGGER` branch below them. A `RemoteWorkerEnv` cannot trigger either guard before its
15
+ * configuration arrives -- it sends that message first -- but a foreign host driving this entry
16
+ * point on its own could send something unreadable ahead of it.
17
+ */
18
+ get logger(): ConsoleLogger;
19
+ /** Whether this runtime is listening on the global scope. */
20
+ get isStarted(): boolean;
21
+ /** Whether a destroy has ended this runtime. Final: neither a message nor a `start()` revives it. */
22
+ get isDestroyed(): boolean;
4
23
  onmessage: (event: MessageEvent) => void;
5
24
  start(): void;
25
+ /** Stops listening on the global scope. A later `start()` picks the work up again, unless a destroy has ended this runtime. */
26
+ stop(): void;
6
27
  }
7
28
  //# sourceMappingURL=WorkerRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkerRuntime.d.ts","sourceRoot":"","sources":["../../../src/worker/WorkerRuntime.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAEjD,qBAAa,aAAa;IACxB,MAAM,CAAC,EAAE,aAAa,CAAC;IAEvB,SAAS,GAAI,OAAO,YAAY,KAAG,IAAI,CAQrC;IAEF,KAAK;CAIN"}
1
+ {"version":3,"file":"WorkerRuntime.d.ts","sourceRoot":"","sources":["../../../src/worker/WorkerRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,aAAa,EAA0B,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAwB,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAExE,qBAAa,aAAa;;IACxB,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAInC;;;;;;;;;;;OAWG;IACH,IAAI,MAAM,IAAI,aAAa,CAE1B;IAMD,6DAA6D;IAC7D,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,qGAAqG;IACrG,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,SAAS,UAAW,YAAY,KAAG,IAAI,CAkCrC;IAEF,KAAK,IAAI,IAAI,CAYZ;IAED,+HAA+H;IAC/H,IAAI,IAAI,IAAI,CAKX;CACF"}
@@ -1,21 +1,73 @@
1
- import { Loaded } from "../constants.js";
2
- import { CONSOLE_LOGGER, CONSOLE_LOGGER_STORAGE } from "../utils/ConsoleLogger.js";
3
- import { MessageRouter } from "./MessageRouter.js";
1
+ import { Destroy, Loaded } from "../constants.js";
2
+ import { CONSOLE_LOGGER, ConsoleLogger, setConsoleLoggerStorage } from "../utils/ConsoleLogger.js";
3
+ import { isReadableMessageData, MessageRouter } from "./MessageRouter.js";
4
4
  class WorkerRuntime {
5
5
  constructor() {
6
+ this.#isStarted = false;
7
+ this.#isDestroyed = false;
6
8
  this.onmessage = (event) => {
7
- if (event.data.type === CONSOLE_LOGGER) {
8
- globalThis[CONSOLE_LOGGER_STORAGE] = event.data.config;
9
- } else {
10
- this.router ??= new MessageRouter();
11
- this.router.route(event);
9
+ const data = event.data;
10
+ if (!isReadableMessageData(data)) {
11
+ this.logger.debug("discarding a message it cannot read", data);
12
+ return;
13
+ }
14
+ if (this.#isDestroyed) {
15
+ this.logger.debug("discarding a message that arrived after the teardown", data.type);
16
+ return;
17
+ }
18
+ if (data.type === CONSOLE_LOGGER) {
19
+ setConsoleLoggerStorage(data.config);
20
+ this.logger.debug("console-logger config installed", data.config);
21
+ return;
22
+ }
23
+ this.router ??= new MessageRouter();
24
+ this.router.route(event);
25
+ if (data.type === Destroy) {
26
+ this.#isDestroyed = true;
27
+ this.stop();
28
+ this.router = void 0;
12
29
  }
13
30
  };
14
31
  }
32
+ #loggerInstance;
33
+ /**
34
+ * Built on first use rather than in a field initializer: a `ConsoleLogger` reads its own
35
+ * `<namespace>.enable` key once, when it is built, and in a worker the config that key lives in
36
+ * arrives as a message. A logger built ahead of that message keeps the default for its own switch
37
+ * for the rest of the thread; the shared switches reach it either way.
38
+ *
39
+ * The window is narrow: the two guard branches of `onmessage` that discard a message it cannot
40
+ * read or a message that arrived after the teardown reach for this logger ahead of the
41
+ * `CONSOLE_LOGGER` branch below them. A `RemoteWorkerEnv` cannot trigger either guard before its
42
+ * configuration arrives -- it sends that message first -- but a foreign host driving this entry
43
+ * point on its own could send something unreadable ahead of it.
44
+ */
45
+ get logger() {
46
+ return this.#loggerInstance ??= new ConsoleLogger("WorkerRuntime");
47
+ }
48
+ #isStarted;
49
+ #isDestroyed;
50
+ /** Whether this runtime is listening on the global scope. */
51
+ get isStarted() {
52
+ return this.#isStarted;
53
+ }
54
+ /** Whether a destroy has ended this runtime. Final: neither a message nor a `start()` revives it. */
55
+ get isDestroyed() {
56
+ return this.#isDestroyed;
57
+ }
15
58
  start() {
59
+ if (this.#isDestroyed) return;
60
+ if (this.#isStarted) return;
61
+ this.#isStarted = true;
16
62
  self.addEventListener("message", this.onmessage);
17
63
  self.postMessage({ type: Loaded });
18
64
  }
65
+ /** Stops listening on the global scope. A later `start()` picks the work up again, unless a destroy has ended this runtime. */
66
+ stop() {
67
+ if (!this.#isStarted) return;
68
+ this.#isStarted = false;
69
+ self.removeEventListener("message", this.onmessage);
70
+ }
19
71
  }
20
72
  export {
21
73
  WorkerRuntime
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/worker/WorkerRuntime.ts"],
4
- "sourcesContent": ["import {Loaded} from '../constants.js';\nimport {CONSOLE_LOGGER, CONSOLE_LOGGER_STORAGE} from '../utils/ConsoleLogger.js';\nimport {MessageRouter} from './MessageRouter.js';\n\nexport class WorkerRuntime {\n router?: MessageRouter;\n\n onmessage = (event: MessageEvent): void => {\n if (event.data.type === CONSOLE_LOGGER) {\n // @ts-ignore\n globalThis[CONSOLE_LOGGER_STORAGE] = event.data.config;\n } else {\n this.router ??= new MessageRouter();\n this.router.route(event);\n }\n };\n\n start() {\n self.addEventListener('message', this.onmessage);\n self.postMessage({type: Loaded}); // inform the main thread that we are ready\n }\n}"],
5
- "mappings": "AAAA,SAAQ,cAAa;AACrB,SAAQ,gBAAgB,8BAA6B;AACrD,SAAQ,qBAAoB;AAErB,MAAM,cAAc;AAAA,EAApB;AAGL,qBAAY,CAAC,UAA8B;AACzC,UAAI,MAAM,KAAK,SAAS,gBAAgB;AAEtC,mBAAW,sBAAsB,IAAI,MAAM,KAAK;AAAA,MAClD,OAAO;AACL,aAAK,WAAW,IAAI,cAAc;AAClC,aAAK,OAAO,MAAM,KAAK;AAAA,MACzB;AAAA,IACF;AAAA;AAAA,EAEA,QAAQ;AACN,SAAK,iBAAiB,WAAW,KAAK,SAAS;AAC/C,SAAK,YAAY,EAAC,MAAM,OAAM,CAAC;AAAA,EACjC;AACF;",
4
+ "sourcesContent": ["import {Destroy, Loaded} from '../constants.js';\nimport {CONSOLE_LOGGER, ConsoleLogger, setConsoleLoggerStorage} from '../utils/ConsoleLogger.js';\nimport {isReadableMessageData, MessageRouter} from './MessageRouter.js';\n\nexport class WorkerRuntime {\n router?: MessageRouter | undefined;\n\n #loggerInstance?: ConsoleLogger;\n\n /**\n * Built on first use rather than in a field initializer: a `ConsoleLogger` reads its own\n * `<namespace>.enable` key once, when it is built, and in a worker the config that key lives in\n * arrives as a message. A logger built ahead of that message keeps the default for its own switch\n * for the rest of the thread; the shared switches reach it either way.\n *\n * The window is narrow: the two guard branches of `onmessage` that discard a message it cannot\n * read or a message that arrived after the teardown reach for this logger ahead of the\n * `CONSOLE_LOGGER` branch below them. A `RemoteWorkerEnv` cannot trigger either guard before its\n * configuration arrives -- it sends that message first -- but a foreign host driving this entry\n * point on its own could send something unreadable ahead of it.\n */\n get logger(): ConsoleLogger {\n return (this.#loggerInstance ??= new ConsoleLogger('WorkerRuntime'));\n }\n\n #isStarted = false;\n\n #isDestroyed = false;\n\n /** Whether this runtime is listening on the global scope. */\n get isStarted(): boolean {\n return this.#isStarted;\n }\n\n /** Whether a destroy has ended this runtime. Final: neither a message nor a `start()` revives it. */\n get isDestroyed(): boolean {\n return this.#isDestroyed;\n }\n\n onmessage = (event: MessageEvent): void => {\n const data = event.data;\n\n // read before a router exists, so the check belongs here as well: a payload this side\n // cannot read would end the worker before anything of it is even built\n if (!isReadableMessageData(data)) {\n this.logger.debug('discarding a message it cannot read', data);\n return;\n }\n\n // the router that answered the destroy is released below, so without this the next message\n // would build a fresh one -- an untorn kernel behind the barrier the destroy just raised\n if (this.#isDestroyed) {\n this.logger.debug('discarding a message that arrived after the teardown', data.type);\n return;\n }\n\n if (data.type === CONSOLE_LOGGER) {\n setConsoleLoggerStorage(data.config);\n this.logger.debug('console-logger config installed', data.config);\n return;\n }\n\n this.router ??= new MessageRouter();\n this.router.route(event);\n\n if (data.type === Destroy) {\n // whoever put the listener on takes it off again: the router has confirmed the teardown\n // by now, and both it and its kernel would stay reachable from `self` for the rest of\n // the thread's life\n this.#isDestroyed = true;\n this.stop();\n this.router = undefined;\n }\n };\n\n start(): void {\n // a destroy is the end of this runtime: starting again would announce a second handshake for\n // an environment whose entities are gone\n if (this.#isDestroyed) return;\n\n // `addEventListener` de-dupes the listener, the announcement is not de-duped: a second\n // start would tell the view of a handshake it has already completed\n if (this.#isStarted) return;\n this.#isStarted = true;\n\n self.addEventListener('message', this.onmessage);\n self.postMessage({type: Loaded}); // inform the main thread that we are ready\n }\n\n /** Stops listening on the global scope. A later `start()` picks the work up again, unless a destroy has ended this runtime. */\n stop(): void {\n if (!this.#isStarted) return;\n this.#isStarted = false;\n\n self.removeEventListener('message', this.onmessage);\n }\n}\n"],
5
+ "mappings": "AAAA,SAAQ,SAAS,cAAa;AAC9B,SAAQ,gBAAgB,eAAe,+BAA8B;AACrE,SAAQ,uBAAuB,qBAAoB;AAE5C,MAAM,cAAc;AAAA,EAApB;AAqBL,sBAAa;AAEb,wBAAe;AAYf,qBAAY,CAAC,UAA8B;AACzC,YAAM,OAAO,MAAM;AAInB,UAAI,CAAC,sBAAsB,IAAI,GAAG;AAChC,aAAK,OAAO,MAAM,uCAAuC,IAAI;AAC7D;AAAA,MACF;AAIA,UAAI,KAAK,cAAc;AACrB,aAAK,OAAO,MAAM,wDAAwD,KAAK,IAAI;AACnF;AAAA,MACF;AAEA,UAAI,KAAK,SAAS,gBAAgB;AAChC,gCAAwB,KAAK,MAAM;AACnC,aAAK,OAAO,MAAM,mCAAmC,KAAK,MAAM;AAChE;AAAA,MACF;AAEA,WAAK,WAAW,IAAI,cAAc;AAClC,WAAK,OAAO,MAAM,KAAK;AAEvB,UAAI,KAAK,SAAS,SAAS;AAIzB,aAAK,eAAe;AACpB,aAAK,KAAK;AACV,aAAK,SAAS;AAAA,MAChB;AAAA,IACF;AAAA;AAAA,EAlEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,IAAI,SAAwB;AAC1B,WAAQ,KAAK,oBAAoB,IAAI,cAAc,eAAe;AAAA,EACpE;AAAA,EAEA;AAAA,EAEA;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EAsCA,QAAc;AAGZ,QAAI,KAAK,aAAc;AAIvB,QAAI,KAAK,WAAY;AACrB,SAAK,aAAa;AAElB,SAAK,iBAAiB,WAAW,KAAK,SAAS;AAC/C,SAAK,YAAY,EAAC,MAAM,OAAM,CAAC;AAAA,EACjC;AAAA;AAAA,EAGA,OAAa;AACX,QAAI,CAAC,KAAK,WAAY;AACtB,SAAK,aAAa;AAElB,SAAK,oBAAoB,WAAW,KAAK,SAAS;AAAA,EACpD;AACF;",
6
6
  "names": []
7
7
  }