@spearwolf/shadow-objects 0.34.0 → 0.35.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 (174) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +11 -2
  3. package/bundle.js +4 -2
  4. package/package.json +9 -1
  5. package/src/WorkerTimeoutError.d.ts +4 -3
  6. package/src/WorkerTimeoutError.d.ts.map +1 -1
  7. package/src/WorkerTimeoutError.js.map +2 -2
  8. package/src/constants.d.ts +8 -4
  9. package/src/constants.d.ts.map +1 -1
  10. package/src/constants.js +6 -0
  11. package/src/constants.js.map +2 -2
  12. package/src/elements/ShaePropElement.d.ts +15 -6
  13. package/src/elements/ShaePropElement.d.ts.map +1 -1
  14. package/src/elements/ShaePropElement.js +31 -7
  15. package/src/elements/ShaePropElement.js.map +2 -2
  16. package/src/elements/ShaeWorkerElement.d.ts +10 -0
  17. package/src/elements/ShaeWorkerElement.d.ts.map +1 -1
  18. package/src/elements/ShaeWorkerElement.js +69 -2
  19. package/src/elements/ShaeWorkerElement.js.map +2 -2
  20. package/src/elements/constants.d.ts +3 -0
  21. package/src/elements/constants.d.ts.map +1 -1
  22. package/src/elements/constants.js +6 -0
  23. package/src/elements/constants.js.map +2 -2
  24. package/src/in-the-dark/Entity.d.ts +30 -0
  25. package/src/in-the-dark/Entity.d.ts.map +1 -1
  26. package/src/in-the-dark/Entity.js +38 -0
  27. package/src/in-the-dark/Entity.js.map +2 -2
  28. package/src/in-the-dark/Kernel.d.ts +24 -1
  29. package/src/in-the-dark/Kernel.d.ts.map +1 -1
  30. package/src/in-the-dark/Kernel.js +56 -1
  31. package/src/in-the-dark/Kernel.js.map +2 -2
  32. package/src/in-the-dark/Registry.d.ts +7 -1
  33. package/src/in-the-dark/Registry.d.ts.map +1 -1
  34. package/src/in-the-dark/Registry.js +29 -0
  35. package/src/in-the-dark/Registry.js.map +2 -2
  36. package/src/in-the-dark/ShadowObjectCreationScope.d.ts +8 -1
  37. package/src/in-the-dark/ShadowObjectCreationScope.d.ts.map +1 -1
  38. package/src/in-the-dark/ShadowObjectCreationScope.js +23 -16
  39. package/src/in-the-dark/ShadowObjectCreationScope.js.map +2 -2
  40. package/src/in-the-dark/SignalsPath.d.ts +2 -0
  41. package/src/in-the-dark/SignalsPath.d.ts.map +1 -1
  42. package/src/in-the-dark/SignalsPath.js +4 -0
  43. package/src/in-the-dark/SignalsPath.js.map +2 -2
  44. package/src/in-the-dark/displayName.d.ts +4 -0
  45. package/src/in-the-dark/displayName.d.ts.map +1 -0
  46. package/src/in-the-dark/displayName.js +5 -0
  47. package/src/in-the-dark/displayName.js.map +7 -0
  48. package/src/index.d.ts +2 -0
  49. package/src/index.d.ts.map +1 -1
  50. package/src/index.js +4 -0
  51. package/src/index.js.map +2 -2
  52. package/src/inspect/createKernelSnapshot.d.ts +17 -0
  53. package/src/inspect/createKernelSnapshot.d.ts.map +1 -0
  54. package/src/inspect/createKernelSnapshot.js +247 -0
  55. package/src/inspect/createKernelSnapshot.js.map +7 -0
  56. package/src/inspect/createViewSnapshot.d.ts +10 -0
  57. package/src/inspect/createViewSnapshot.d.ts.map +1 -0
  58. package/src/inspect/createViewSnapshot.js +143 -0
  59. package/src/inspect/createViewSnapshot.js.map +7 -0
  60. package/src/inspect/normalizeInspectRequest.d.ts +32 -0
  61. package/src/inspect/normalizeInspectRequest.d.ts.map +1 -0
  62. package/src/inspect/normalizeInspectRequest.js +55 -0
  63. package/src/inspect/normalizeInspectRequest.js.map +7 -0
  64. package/src/inspect/serializeValue.d.ts +13 -0
  65. package/src/inspect/serializeValue.d.ts.map +1 -0
  66. package/src/inspect/serializeValue.js +149 -0
  67. package/src/inspect/serializeValue.js.map +7 -0
  68. package/src/inspect/types.d.ts +260 -0
  69. package/src/inspect/types.d.ts.map +1 -0
  70. package/src/inspect/types.js +1 -0
  71. package/src/inspect/types.js.map +7 -0
  72. package/src/model-context/ModelContextLike.d.ts +59 -0
  73. package/src/model-context/ModelContextLike.d.ts.map +1 -0
  74. package/src/model-context/ModelContextLike.js +15 -0
  75. package/src/model-context/ModelContextLike.js.map +7 -0
  76. package/src/model-context/exposeShadowEnvsToModelContext.d.ts +48 -0
  77. package/src/model-context/exposeShadowEnvsToModelContext.d.ts.map +1 -0
  78. package/src/model-context/exposeShadowEnvsToModelContext.js +39 -0
  79. package/src/model-context/exposeShadowEnvsToModelContext.js.map +7 -0
  80. package/src/model-context/redactProps.d.ts +14 -0
  81. package/src/model-context/redactProps.d.ts.map +1 -0
  82. package/src/model-context/redactProps.js +22 -0
  83. package/src/model-context/redactProps.js.map +7 -0
  84. package/src/model-context/sharedExposure.d.ts +32 -0
  85. package/src/model-context/sharedExposure.d.ts.map +1 -0
  86. package/src/model-context/sharedExposure.js +108 -0
  87. package/src/model-context/sharedExposure.js.map +7 -0
  88. package/src/model-context/toolSupport.d.ts +72 -0
  89. package/src/model-context/toolSupport.d.ts.map +1 -0
  90. package/src/model-context/toolSupport.js +145 -0
  91. package/src/model-context/toolSupport.js.map +7 -0
  92. package/src/model-context/tools/findEntities.d.ts +15 -0
  93. package/src/model-context/tools/findEntities.d.ts.map +1 -0
  94. package/src/model-context/tools/findEntities.js +71 -0
  95. package/src/model-context/tools/findEntities.js.map +7 -0
  96. package/src/model-context/tools/getEntity.d.ts +16 -0
  97. package/src/model-context/tools/getEntity.d.ts.map +1 -0
  98. package/src/model-context/tools/getEntity.js +65 -0
  99. package/src/model-context/tools/getEntity.js.map +7 -0
  100. package/src/model-context/tools/getEntityTree.d.ts +4 -0
  101. package/src/model-context/tools/getEntityTree.d.ts.map +1 -0
  102. package/src/model-context/tools/getEntityTree.js +58 -0
  103. package/src/model-context/tools/getEntityTree.js.map +7 -0
  104. package/src/model-context/tools/getRegistry.d.ts +14 -0
  105. package/src/model-context/tools/getRegistry.d.ts.map +1 -0
  106. package/src/model-context/tools/getRegistry.js +39 -0
  107. package/src/model-context/tools/getRegistry.js.map +7 -0
  108. package/src/model-context/tools/index.d.ts +9 -0
  109. package/src/model-context/tools/index.d.ts.map +1 -0
  110. package/src/model-context/tools/index.js +16 -0
  111. package/src/model-context/tools/index.js.map +7 -0
  112. package/src/model-context/tools/listEnvs.d.ts +33 -0
  113. package/src/model-context/tools/listEnvs.d.ts.map +1 -0
  114. package/src/model-context/tools/listEnvs.js +37 -0
  115. package/src/model-context/tools/listEnvs.js.map +7 -0
  116. package/src/model-context.d.ts +13 -0
  117. package/src/model-context.d.ts.map +1 -0
  118. package/src/model-context.js +15 -0
  119. package/src/model-context.js.map +7 -0
  120. package/src/shadow-objects.d.ts +2 -0
  121. package/src/shadow-objects.d.ts.map +1 -1
  122. package/src/shadow-objects.js +4 -0
  123. package/src/shadow-objects.js.map +2 -2
  124. package/src/testing/TestEntity.d.ts +79 -0
  125. package/src/testing/TestEntity.d.ts.map +1 -0
  126. package/src/testing/TestEntity.js +135 -0
  127. package/src/testing/TestEntity.js.map +7 -0
  128. package/src/testing/createTestKernel.d.ts +11 -0
  129. package/src/testing/createTestKernel.d.ts.map +1 -0
  130. package/src/testing/createTestKernel.js +132 -0
  131. package/src/testing/createTestKernel.js.map +7 -0
  132. package/src/testing/mountShadowObject.d.ts +21 -0
  133. package/src/testing/mountShadowObject.d.ts.map +1 -0
  134. package/src/testing/mountShadowObject.js +72 -0
  135. package/src/testing/mountShadowObject.js.map +7 -0
  136. package/src/testing/recordKernelErrors.d.ts +21 -0
  137. package/src/testing/recordKernelErrors.d.ts.map +1 -0
  138. package/src/testing/recordKernelErrors.js +39 -0
  139. package/src/testing/recordKernelErrors.js.map +7 -0
  140. package/src/testing/settle.d.ts +15 -0
  141. package/src/testing/settle.d.ts.map +1 -0
  142. package/src/testing/settle.js +19 -0
  143. package/src/testing/settle.js.map +7 -0
  144. package/src/testing/types.d.ts +119 -0
  145. package/src/testing/types.d.ts.map +1 -0
  146. package/src/testing/types.js +1 -0
  147. package/src/testing/types.js.map +7 -0
  148. package/src/testing.d.ts +14 -0
  149. package/src/testing.d.ts.map +1 -0
  150. package/src/testing.js +11 -0
  151. package/src/testing.js.map +7 -0
  152. package/src/types.d.ts +150 -10
  153. package/src/types.d.ts.map +1 -1
  154. package/src/utils/attr-utils.d.ts +5 -0
  155. package/src/utils/attr-utils.d.ts.map +1 -1
  156. package/src/utils/attr-utils.js +2 -0
  157. package/src/utils/attr-utils.js.map +2 -2
  158. package/src/view/IShadowObjectEnvProxy.d.ts +9 -0
  159. package/src/view/IShadowObjectEnvProxy.d.ts.map +1 -1
  160. package/src/view/LocalShadowObjectEnv.d.ts +7 -0
  161. package/src/view/LocalShadowObjectEnv.d.ts.map +1 -1
  162. package/src/view/LocalShadowObjectEnv.js +15 -1
  163. package/src/view/LocalShadowObjectEnv.js.map +2 -2
  164. package/src/view/RemoteWorkerEnv.d.ts +22 -3
  165. package/src/view/RemoteWorkerEnv.d.ts.map +1 -1
  166. package/src/view/RemoteWorkerEnv.js +50 -1
  167. package/src/view/RemoteWorkerEnv.js.map +2 -2
  168. package/src/view/ShadowEnv.d.ts +30 -0
  169. package/src/view/ShadowEnv.d.ts.map +1 -1
  170. package/src/view/ShadowEnv.js +101 -0
  171. package/src/view/ShadowEnv.js.map +3 -3
  172. package/src/worker/MessageRouter.d.ts.map +1 -1
  173. package/src/worker/MessageRouter.js +23 -0
  174. package/src/worker/MessageRouter.js.map +2 -2
@@ -23,6 +23,11 @@ const inertEffect = () => {
23
23
  };
24
24
  const noSubscription = () => {
25
25
  };
26
+ function subscribeOn(entity, args) {
27
+ const [first] = args;
28
+ const isTarget = args.length > 1 && typeof first === "object" && first !== null && !Array.isArray(first);
29
+ return isTarget ? args : [entity, ...args];
30
+ }
26
31
  class ShadowObjectCreationScope {
27
32
  #entity;
28
33
  #logger;
@@ -123,6 +128,22 @@ class ShadowObjectCreationScope {
123
128
  contextFeeds: this.#unsubscribeContextFeeds.size
124
129
  };
125
130
  }
131
+ /**
132
+ * The names this scope handed readers and providers out for, by kind, plus the display name. Read
133
+ * off the private maps and nothing else: no reader is created, no late call is reported, and a
134
+ * scope past its teardown answers empty lists rather than a throw -- `tearDown()` clears the maps
135
+ * it reads.
136
+ */
137
+ describe() {
138
+ return {
139
+ displayName: this.#displayName,
140
+ usesProperties: Array.from(this.#propertyReaders.keys()),
141
+ usesContexts: Array.from(this.#contextReaders.keys()),
142
+ usesParentContexts: Array.from(this.#contextParentReaders.keys()),
143
+ providesContexts: Array.from(this.#contextProviders.keys()),
144
+ providesGlobalContexts: Array.from(this.#contextRootProviders.keys())
145
+ };
146
+ }
126
147
  constructor(entity, logger, displayName, shownDeprecations) {
127
148
  this.#entity = entity;
128
149
  this.#logger = logger;
@@ -536,26 +557,12 @@ class ShadowObjectCreationScope {
536
557
  }
537
558
  on(...args) {
538
559
  if (this.#refuseAfterTearDown("on")) return noSubscription;
539
- const [firstArg] = args;
540
- const unsubscribe = typeof firstArg === "string" || typeof firstArg === "symbol" || Array.isArray(firstArg) ? (
541
- // @ts-ignore
542
- on(this.#entity, ...args)
543
- ) : (
544
- // @ts-ignore
545
- on(...args)
546
- );
560
+ const unsubscribe = on(...subscribeOn(this.#entity, args));
547
561
  return this.#trackSubscription(unsubscribe);
548
562
  }
549
563
  once(...args) {
550
564
  if (this.#refuseAfterTearDown("once")) return noSubscription;
551
- const [firstArg] = args;
552
- const unsubscribe = typeof firstArg === "string" || typeof firstArg === "symbol" || Array.isArray(firstArg) ? (
553
- // @ts-ignore
554
- once(this.#entity, ...args)
555
- ) : (
556
- // @ts-ignore
557
- once(...args)
558
- );
565
+ const unsubscribe = once(...subscribeOn(this.#entity, args));
559
566
  return this.#trackSubscription(unsubscribe);
560
567
  }
561
568
  /**
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/in-the-dark/ShadowObjectCreationScope.ts"],
4
- "sourcesContent": ["import {emit, on, once, Priority} from '@spearwolf/eventize';\nimport {\n type CompareFunc,\n createEffect,\n createMemo,\n createSignal,\n destroySignal,\n isSignal,\n link,\n type Signal,\n type SignalReader,\n} from '@spearwolf/signalize';\nimport type {Maybe, ProvideContextOptions, ShadowObjectCreationAPI, ShadowObjectType, SignalValueOptions} from '../types.js';\nimport type {ConsoleLogger} from '../utils/ConsoleLogger.js';\nimport {runGuarded} from '../utils/runGuarded.js';\nimport {toMaybe} from '../utils/toMaybe.js';\nimport type {Entity} from './Entity.js';\nimport {onDestroy, onViewEvent} from './events.js';\n\n/**\n * What a creation-API call gets once the scope has closed: a real `Signal`, created and destroyed\n * on the spot. Reading it gives `undefined` and writing to it reaches nobody -- a destroyed signal\n * keeps its value but has neither effect nor link left on it. It belongs to whoever asked for it\n * and goes when they do, so a scope that is asked again and again after its end holds nothing.\n */\nconst inertSignal = (): Signal<any> => {\n const sig = createSignal<any>(undefined);\n destroySignal(sig);\n return sig;\n};\n\n/** The same for `createEffect()`: a real `Effect`, never run, already destroyed. */\nconst inertEffect = (): ReturnType<typeof createEffect> => {\n const effect = createEffect(() => {}, {autorun: false});\n effect.destroy();\n return effect;\n};\n\n/** The handle a late `on()` or `once()` gets: there is no subscription behind it. */\nconst noSubscription = (): void => {};\n\n/**\n * Everything a single shadow-object was given at construction time, and the end of all of it.\n *\n * The scope holds the signals, links and subscriptions the creation API hands out, and it hands the API\n * itself to the kernel through `createAPI()`. The instance stays with the kernel: a shadow-object only ever\n * sees the API object, never the scope behind it.\n *\n * One scope belongs to exactly one shadow-object, and it ends with it -- or, where the constructor throws,\n * without it: a scope that never reached `bindTo()` is torn down by the kernel on the spot, and everything the\n * constructor registered before the throw is released, although no shadow-object came out of it.\n *\n * Eight methods share their name with a module-level import: `on`, `once`, `emit`, `onDestroy`,\n * `onViewEvent`, `createSignal`, `createEffect` and `createMemo`. They are named that way deliberately,\n * because those names are part of the `ShadowObjectCreationAPI` contract a shadow-object destructures by\n * name. Seven of them call or reference their namesake inside their own body; `onDestroy` is the exception,\n * as its import is the entity event that `bindTo()` subscribes to. A bare name inside one of these eight\n * bodies is therefore always the import, and a call on the method of the same name always carries `this.`\n * -- `inertSignal`, `inertEffect` and `noSubscription` are bare names of a different kind, module-level\n * functions with no method of the same name to tell them apart from.\n */\nexport class ShadowObjectCreationScope {\n readonly #entity: Entity;\n readonly #logger: ConsoleLogger;\n readonly #displayName: string;\n\n // The kernel's list of member names whose deprecation report has already been made. Shared by\n // every scope of one kernel, which is what makes the report fall once per kernel and name.\n readonly #shownDeprecations: Set<string>;\n\n // The cleanup callbacks of the shadow-object itself, registered through `onDestroy()`.\n readonly #unsubscribePrimary = new Set<() => any>();\n\n // The cleanup callbacks the creation API registered on its own behalf. A `Set` iterating in\n // insertion order: which cleanup runs before which is observable behaviour.\n readonly #unsubscribeSecondary = new Set<() => any>();\n\n // The releases of the provider feeds, one per context name this shadow-object provides. The\n // entity hands each of them out when the provider is attached to it, and they fall after every\n // other cleanup callback, so a write the teardown still makes -- the `undefined` of a\n // `clearOnDestroy`, or one from an `onDestroy` callback -- reaches the entity-side signal instead\n // of stopping at the provider. Where the entity lives on, that is what makes the write count: the\n // entity hands it on to its own context signal one microtask later, and from there to its readers\n // and to the entities below it. The order matters in the other direction as well, because a\n // release also lets a provider that stays on the entity write its value once more, and that\n // hand-over may only happen once the write of the leaving provider is through.\n //\n // Where the entity is destroyed, the two kinds of target part ways. The signal behind\n // `provideContext()` takes the write and keeps it: the microtask that would hand it on falls\n // after the entity has cleared and destroyed its context signals, and the children that outlive\n // it were re-bound before the teardown even began. The signal behind `provideGlobalContext()`\n // stays a member of the kernel-wide chain of its name until the entity's own destruction runs at\n // `Priority.Min`, so the write does travel on to the inherited signals of other entities -- with\n // no observable difference, because the entity takes its signal out of that chain in the same run,\n // and what the chain resolves to without it is what those readers were going to see anyway: the\n // contribution of the next entity that holds the name, or nothing where there is none. The\n // ordering is kept for the paths on which it is observable.\n readonly #unsubscribeContextFeeds = new Set<() => any>();\n\n readonly #contextReaders = new Map<string | symbol, SignalReader<any>>();\n readonly #contextReaderCompares = new Map<string | symbol, CompareFunc<any> | undefined>();\n readonly #contextParentReaders = new Map<string | symbol, SignalReader<any>>();\n readonly #contextParentReaderCompares = new Map<string | symbol, CompareFunc<any> | undefined>();\n readonly #contextProviders = new Map<string | symbol, Signal<any>>();\n readonly #contextRootProviders = new Map<string | symbol, Signal<any>>();\n\n // The provider signals that already have their `clearOnDestroy` write registered in\n // `#unsubscribeSecondary`. Keyed by the signal itself rather than by name, because a\n // `provideContext(name)` and a `provideGlobalContext(name)` call can share one name while landing\n // in two different maps above -- a name-keyed set would conflate the two providers.\n readonly #clearOnDestroyRegistered = new Set<Signal<any>>();\n\n readonly #propertyReaders = new Map<string, SignalReader<any>>();\n readonly #propertyCompares = new Map<string, CompareFunc<any> | undefined>();\n\n #shadowObject: ShadowObjectType | undefined;\n #releaseScope: (() => void) | undefined;\n #forgetShadowObject: (() => void) | undefined;\n #unsubscribeFromEntityDestroy: (() => void) | undefined;\n\n #isTornDown = false;\n\n // Armed at the *end* of `tearDown()`, not at its start, and the difference is the whole point:\n // the teardown runs the shadow-object's own cleanup callbacks, and those are allowed the creation\n // API -- a goodbye to the view, a last write. What they register there is still swept up by the\n // steps behind them. What arrives after the teardown has returned is not, which is what this\n // closes.\n #isCreationApiClosed = false;\n\n // The member names whose late call has already been reported, at most as many as the API has\n // members. Lazy, because a scope that is used correctly never allocates it.\n #lateCallsReported: Set<string> | undefined;\n\n /**\n * The name the kernel gave this scope, taken from the constructor it belongs to rather than from\n * the shadow-object that came out of it. The two agree for most forms -- a class and a function\n * that returns nothing both leave their own name on the instance's `constructor` -- but not for a\n * function that returns an object literal: `new` hands that literal back, and it reports `Object`.\n * Reports about the shadow-object are keyed by this name, so the kernel reads it here instead of\n * asking the instance.\n */\n get displayName(): string {\n return this.#displayName;\n }\n\n /**\n * The four teardown handles, read without waiting on a garbage collector: a test can check that\n * `tearDown()` let go of them by comparing this before and after, rather than by proving the\n * absence of a reference through a `WeakRef`.\n *\n * @internal\n */\n get debugHandles(): {\n shadowObject: ShadowObjectType | undefined;\n releaseScope: (() => void) | undefined;\n forgetShadowObject: (() => void) | undefined;\n unsubscribeFromEntityDestroy: (() => void) | undefined;\n } {\n return {\n shadowObject: this.#shadowObject,\n releaseScope: this.#releaseScope,\n forgetShadowObject: this.#forgetShadowObject,\n unsubscribeFromEntityDestroy: this.#unsubscribeFromEntityDestroy,\n };\n }\n\n /**\n * How many cleanup callbacks the scope is holding, one count per set, read without waiting on a\n * garbage collector: a test can subscribe and unsubscribe n times and see that the scope let go\n * of each handle as it went, rather than inferring it from what a collector happened to do.\n *\n * @internal\n */\n get debugCleanupCounts(): {primary: number; secondary: number; contextFeeds: number} {\n return {\n primary: this.#unsubscribePrimary.size,\n secondary: this.#unsubscribeSecondary.size,\n contextFeeds: this.#unsubscribeContextFeeds.size,\n };\n }\n\n constructor(entity: Entity, logger: ConsoleLogger, displayName: string, shownDeprecations: Set<string>) {\n this.#entity = entity;\n this.#logger = logger;\n this.#displayName = displayName;\n this.#shownDeprecations = shownDeprecations;\n }\n\n /**\n * The object that goes into `new construct(\u2026)`.\n *\n * Every member is a bound function, because a shadow-object constructor is expected to destructure the\n * API in its parameter list \u2014 a member that took its receiver from the call site would lose it there.\n */\n createAPI(): ShadowObjectCreationAPI {\n return {\n entity: this.#entity,\n\n provideContext: this.provideContext.bind(this),\n provideGlobalContext: this.provideGlobalContext.bind(this),\n useContext: this.useContext.bind(this),\n useParentContext: this.useParentContext.bind(this),\n\n dispatchMessageToView: this.dispatchMessageToView.bind(this),\n\n useProperty: this.useProperty.bind(this),\n useProperties: this.useProperties.bind(this),\n\n createResource: this.createResource.bind(this),\n createEffect: this.createEffect.bind(this),\n createSignal: this.createSignal.bind(this),\n createMemo: this.createMemo.bind(this),\n\n on: this.on.bind(this),\n once: this.once.bind(this),\n emit: this.emit.bind(this),\n onViewEvent: this.onViewEvent.bind(this),\n onDestroy: this.onDestroy.bind(this),\n };\n }\n\n /**\n * Binds the scope to the shadow-object it made the API for and subscribes to the destruction of the entity.\n *\n * A shadow-object reaches its end on two independent paths: the entity is destroyed, or the shadow-object\n * leaves the constructor set of a still living entity (token or route change). Both run the same teardown,\n * and each path reaches it through a handle of its own.\n *\n * The kernel keeps two releases rather than one, because they belong to opposite ends of the teardown:\n * `releaseScope` runs at its start, `forgetShadowObject` at its end.\n *\n * One scope serves one shadow-object, once: the call is part of the contract, and both ways of breaking\n * it are refused below.\n */\n bindTo(shadowObject: ShadowObjectType, releaseScope: () => void, forgetShadowObject: () => void): void {\n // Refused rather than quietly returned, unlike `tearDown()`, where a second call is two teardown paths\n // legitimately meeting. A second binding is nothing of the sort -- it would mean one scope serving two\n // shadow-objects. It would replace the handles of the first: the release of the kernel's map entry and\n // the unsubscribe from the entity's `onDestroy`, leaving the first shadow-object standing in the kernel\n // and on the entity with nothing left to take it out.\n //\n // The teardown is asked about first, because it is the only one of the two checks that still applies to\n // a torn-down scope: `tearDown()` lets go of `#shadowObject` at its own end, so a scope that has already\n // torn down would otherwise sail straight past the second check below and rebind. Once a scope carries a\n // shadow-object, it is the second check that tells a live scope's first binding from its second -- the\n // two never overlap on a scope that is still live.\n if (this.#isTornDown) {\n throw new Error(`the creation scope of \"${this.#displayName}\" has torn down and cannot be bound`);\n }\n if (this.#shadowObject !== undefined) {\n throw new Error(`the creation scope of \"${this.#displayName}\" is already bound to a shadow-object`);\n }\n\n this.#shadowObject = shadowObject;\n this.#releaseScope = releaseScope;\n this.#forgetShadowObject = forgetShadowObject;\n\n this.#logger.info('create shadow-object', this.#displayName, {shadowObject, entity: this.#entity});\n\n this.#unsubscribeFromEntityDestroy = once(this.#entity, onDestroy, Priority.Low, () => {\n this.tearDown();\n });\n }\n\n /**\n * Runs once, whichever path reaches it first.\n *\n * Three lead here. Two belong to a shadow-object that lived: its entity is destroyed, or it leaves the\n * constructor set of an entity that stays. On the third, the kernel calls this directly on a scope that\n * `bindTo()` never saw, because the constructor threw -- there is no shadow-object then, and three of the\n * handles below are still unset (`#releaseScope` and `#unsubscribeFromEntityDestroy` at the start,\n * `#forgetShadowObject` at the end), which is why all three are called optionally.\n *\n * The provider feeds are released after everything else, so that a write made on the way out reaches the\n * entity-side signal rather than stopping at the provider, and so that the entity hands the context over to\n * a provider that stays only once that write is through.\n *\n * The flag makes the teardown a one-time act: a destroy callback reaching back into the kernel finds no\n * way to start it a second time. Releasing both handles right after ends the retention in both directions\n * -- the kernel's map points from the shadow-object to this scope, the subscription points from the entity\n * to the same scope.\n *\n * The kernel is told to forget the shadow-object at the very end, so a destroy callback that reaches back\n * into the kernel still finds its shadow-object listed among the ones the constructor created. Once that\n * call is through, the four handles above are let go of as well -- the shadow-object, both kernel releases\n * and the entity subscription -- so a scope past this point holds none of the four through these fields.\n *\n * Every step below runs behind its own guard, so a callback or signal teardown that throws does not stop\n * the ones after it: the remaining callbacks, the remaining signal releases, and the provider feed\n * hand-over all still happen. A caught error goes to the logger by displayName and the label of the step\n * that failed, and is not re-thrown -- neither `changeToken()` nor `destroyEntity()` deliver it to their\n * caller, nor does it stop the destroy notification the entity is still delivering to whatever comes after\n * this shadow-object in the same run.\n *\n * The creation API is closed as the very last step, after everything above has run. Until then it\n * is open, because the cleanup callbacks of the shadow-object run inside this method and are\n * entitled to it -- a last message to the view, a last write to a context. What such a callback\n * registers is still reached by the steps behind it. The two sets of cleanup callbacks are run\n * in rounds until neither has anything left, so a callback that another one registers is reached\n * whichever of the two it lands in. The context feed releases follow all of them. What arrives\n * once this method has returned is not, and is turned away by `#refuseAfterTearDown()`.\n */\n tearDown(): void {\n if (this.#isTornDown) return;\n this.#isTornDown = true;\n\n this.#runGuarded('scope release', () => this.#releaseScope?.());\n this.#runGuarded('entity destroy subscription', () => this.#unsubscribeFromEntityDestroy?.());\n\n // Without a shadow-object there is nothing to report here: none ever came to be, because the\n // constructor threw before it could.\n if (this.#shadowObject !== undefined) {\n this.#logger.info('destroy shadow-object', this.#displayName, {shadowObject: this.#shadowObject, entity: this.#entity});\n }\n\n // The two callback sets are run in rounds, and the rounds are what a cleanup that books into a\n // set which has already had its turn needs. A `for\u2026of` over a `Set` reaches what is added to it\n // while it runs, so a callback that registers another one of its own kind is caught by the pass\n // it stands in. Across the two sets there is no such reach: a creation-api cleanup that calls\n // `onDestroy()` books into the first set, which is through, and a callback pulled along that way\n // may take a subscription or create a signal, which books back into the second. Each of them gets\n // its turn here, and the teardown ends when neither set has anything left to run. A pass skips\n // what has already run, so a callback that hands itself in again is not called twice; one that\n // hands in a new callback every time does not terminate.\n const alreadyRun = new Set<() => any>();\n\n const runCleanups = (callbacks: Set<() => any>, step: string): boolean => {\n let ranAny = false;\n for (const callback of callbacks) {\n if (alreadyRun.has(callback)) continue;\n alreadyRun.add(callback);\n ranAny = true;\n this.#runGuarded(step, callback);\n }\n return ranAny;\n };\n\n let ranAnything = true;\n while (ranAnything) {\n const ranPrimary = runCleanups(this.#unsubscribePrimary, 'onDestroy callback');\n const ranSecondary = runCleanups(this.#unsubscribeSecondary, 'creation-api cleanup');\n ranAnything = ranPrimary || ranSecondary;\n }\n\n for (const callback of this.#unsubscribeContextFeeds) {\n this.#runGuarded('context feed release', callback);\n }\n\n for (const sig of this.#contextReaders.values()) {\n this.#runGuarded('context reader', () => destroySignal(sig));\n }\n\n for (const sig of this.#contextParentReaders.values()) {\n this.#runGuarded('parent context reader', () => destroySignal(sig));\n }\n\n for (const sig of this.#propertyReaders.values()) {\n this.#runGuarded('property reader', () => destroySignal(sig));\n }\n\n for (const sig of this.#contextProviders.values()) {\n this.#runGuarded('context provider', () => destroySignal(sig));\n }\n\n for (const sig of this.#contextRootProviders.values()) {\n this.#runGuarded('global context provider', () => destroySignal(sig));\n }\n\n this.#unsubscribePrimary.clear();\n this.#unsubscribeSecondary.clear();\n this.#unsubscribeContextFeeds.clear();\n this.#contextReaders.clear();\n this.#contextReaderCompares.clear();\n this.#contextParentReaders.clear();\n this.#contextParentReaderCompares.clear();\n this.#propertyReaders.clear();\n this.#propertyCompares.clear();\n this.#contextProviders.clear();\n this.#contextRootProviders.clear();\n this.#clearOnDestroyRegistered.clear();\n\n this.#runGuarded('forget shadow-object', () => this.#forgetShadowObject?.());\n\n // Let go of the shadow-object and both kernel handles: nothing reads them past this point --\n // the info line above already ran, `#releaseScope` and `#unsubscribeFromEntityDestroy` were\n // called at the start of this method, and `#forgetShadowObject` was just called above. A scope\n // past this point holds neither the shadow-object nor either kernel handle through these\n // fields. `#entity` is a separate, `readonly` field the scope carries for its whole life --\n // it stays set here, and the entity, with the kernel behind it, stays reachable through it\n // whether or not the scope has torn down.\n this.#shadowObject = undefined;\n this.#releaseScope = undefined;\n this.#forgetShadowObject = undefined;\n this.#unsubscribeFromEntityDestroy = undefined;\n\n this.#isCreationApiClosed = true;\n }\n\n /**\n * Isolates one teardown step from the ones around it: a step that throws is reported through the\n * logger -- ungated, so the report stays visible outside localhost -- and does not stop `tearDown()`\n * from reaching the steps that follow. The report goes out through the shared `runGuarded()`;\n * what this wrapper adds is the label of the step and the display name it belongs to.\n */\n #runGuarded(step: string, run: () => void): void {\n runGuarded(this.#logger, run, `shadow-object teardown failed (${step}):`, this.#displayName);\n }\n\n /**\n * Books an `on()` or `once()` subscription into the cleanup set and hands back a handle that takes\n * it out again. Unsubscribing releases the callback there and then rather than at the teardown, so\n * a shadow-object that subscribes and unsubscribes over the whole life of its entity holds one\n * handle at a time instead of one per call. The target makes no difference to that: a subscription\n * on the entity ends the same way one on any other object does.\n */\n #trackSubscription(unsubscribe: () => void): () => void {\n this.#unsubscribeSecondary.add(unsubscribe);\n\n return Object.assign(() => {\n this.#unsubscribeSecondary.delete(unsubscribe);\n unsubscribe();\n }, unsubscribe);\n }\n\n /**\n * The body the three cached readers share: one reader per name, created on the first call and fed\n * from the entity-side source, plus a warning when a later call brings a different {compare}\n * function than the one the reader was created with.\n *\n * `linkSource` is a thunk because the source may only be read when a reader is actually created.\n */\n #cachedReader<K extends string | symbol>(\n name: K,\n readers: Map<K, SignalReader<any>>,\n compares: Map<K, CompareFunc<any> | undefined>,\n linkSource: () => SignalReader<any>,\n opts: SignalValueOptions<any> | undefined,\n apiName: string,\n subject: string,\n ): SignalReader<any> {\n let reader = readers.get(name);\n\n if (reader === undefined) {\n reader = createSignal<any>(undefined, opts).get;\n readers.set(name, reader);\n compares.set(name, opts?.compare);\n // Destroying this link is what ends the feed: the entity-side signal must not go on writing\n // into a reader that the teardown has already destroyed.\n const ln = link(linkSource(), reader);\n this.#unsubscribeSecondary.add(ln.destroy.bind(ln));\n } else if (opts?.compare != null && compares.get(name) !== opts.compare) {\n // Through `error` for the same reason as the deprecation report below: the options of this\n // call are being dropped, and the caller has to hear that outside `localhost` too, where the\n // shared `enable` behind `isWarn` is off.\n this.#logger.error(\n `[shadow-objects] ${apiName}(\"${String(name)}\"): the cached signal already exists with a different (or no) {compare} function \u2014 the new options are ignored. Pass options only on the first call per ${subject}.`,\n );\n }\n\n return reader;\n }\n\n /**\n * Reports the deprecated call form in which a bare compare function stands where the options\n * object belongs, at most once per kernel and member name.\n *\n * Through `error` rather than `warn`: this names a mistake in the calling code, and its author\n * has to see it wherever the application runs. `logger.warn` is asked `isWarn` first, and the\n * shared `enable` behind that getter is off anywhere but `localhost` -- a deprecation notice\n * that goes silent everywhere the code actually ships is no notice at all. See the table of\n * call against getter under \"Console Logger\" in `docs/api-reference.md`.\n *\n * One line per kernel and member name: a shadow-object calling a deprecated member inside a\n * loop would otherwise fill the console.\n */\n #reportDeprecatedIsEqualOption(options: unknown, apiName: string): void {\n if (typeof options !== 'function' || this.#shownDeprecations.has(apiName)) return;\n this.#logger.error(\n `[shadow-objects] Deprecation Warning: The \"isEqual\" option of \"${apiName}()\" is now passed as {compare} argument. Please update your code accordingly.`,\n );\n this.#shownDeprecations.add(apiName);\n }\n\n /**\n * Answers whether the creation API still has anything to give, and reports it where it has not.\n *\n * Past the teardown the scope has released what it held and cleared what it tracked. A call\n * arriving now would fill those maps again with entries no second teardown ever reaches -- the\n * teardown runs once, and it has run. Such a call is therefore turned away rather than served.\n *\n * Turned away quietly: the callers that arrive late are the ones with nobody to catch a throw --\n * a timer, a continuation behind an `await`, a callback of some other object that outlived this\n * one. It is reported instead, through `error` for the same reason the deprecation report above\n * uses it: this names a mistake in the calling code, and its author has to see it wherever the\n * application runs. Once per member name and scope, because a stale timer comes back on its next\n * tick and a line per tick would bury the first one.\n */\n #refuseAfterTearDown(apiName: string): boolean {\n if (!this.#isCreationApiClosed) return false;\n\n if (!this.#lateCallsReported?.has(apiName)) {\n (this.#lateCallsReported ??= new Set()).add(apiName);\n this.#logger.error(\n `[shadow-objects] ${apiName}(): the creation scope of \"${this.#displayName}\" has torn down \u2014 the call does nothing. Something is still holding the creation API past the end of its shadow-object.`,\n );\n }\n\n return true;\n }\n\n useProperty<T = unknown>(name: string, options?: SignalValueOptions<T> | CompareFunc<T | undefined>): SignalReader<Maybe<T>> {\n if (this.#refuseAfterTearDown('useProperty')) return inertSignal().get;\n\n this.#reportDeprecatedIsEqualOption(options, 'useProperty');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#cachedReader(\n name,\n this.#propertyReaders,\n this.#propertyCompares,\n () => this.#entity.getPropertyReader(name),\n opts,\n 'useProperty',\n 'property',\n );\n }\n\n useProperties<T extends Record<string, unknown> = Record<string, unknown>>(\n props: {[K in keyof T]: string},\n ): {\n [K in keyof T]: SignalReader<Maybe<T[K]>>;\n } {\n const result = {} as {[K in keyof T]: SignalReader<Maybe<T[K]>>};\n for (const key in props) {\n if (Object.hasOwn(props, key)) {\n result[key] = this.useProperty<T[typeof key]>(props[key]);\n }\n }\n return result;\n }\n\n /**\n * The body the two context providers share: one provider signal per name, created on the first\n * call, attached to the entity-side context signal, and cleared on teardown unless the caller\n * opted out -- a clearing that finds the way to the entity side still open. A source signal handed\n * in instead of an initial value feeds the provider through a link of its own.\n *\n * The entity keeps every provider of a name together and answers the attachment with the release\n * that detaches this one again. Releasing it does more than cut the feed: the entity then lets a\n * provider that stays write its value once more, so the name ends up with a value that is actually\n * still being provided rather than with what this shadow-object left behind on its way out.\n *\n * `attachToEntity` is called inside the creation branch only, so the entity-side signal is\n * requested when a provider is actually created. The `clearOnDestroy` check sits outside that\n * branch: every call is allowed to ask for the clearing, not only the one that created the signal.\n * The request is booked once per provider, though -- a repeated ask does not queue a second write,\n * and once a provider has one on file, an opt-out on a later call does not take it back.\n */\n #provideContextSignal(\n name: string | symbol,\n providers: Map<string | symbol, Signal<any>>,\n attachToEntity: (provider: Signal<any>) => () => void,\n sourceOrInitialValue: unknown,\n opts: ProvideContextOptions<any> | undefined,\n ): Signal<any> {\n let ctxProvider = providers.get(name);\n\n if (ctxProvider == null) {\n const isSig = isSignal(sourceOrInitialValue);\n const initialValue = isSig ? undefined : toMaybe(sourceOrInitialValue);\n\n ctxProvider = createSignal(initialValue, opts?.compare ? {compare: opts.compare} : undefined);\n\n if (isSig) {\n const ln = link(sourceOrInitialValue as SignalReader<any>, ctxProvider);\n this.#unsubscribeSecondary.add(ln.destroy.bind(ln));\n }\n\n // The release runs after every `clearOnDestroy` callback below, so a write to `undefined`\n // still reaches the context signal on the entity side before the feed is cut.\n this.#unsubscribeContextFeeds.add(attachToEntity(ctxProvider));\n providers.set(name, ctxProvider);\n }\n\n if ((opts?.clearOnDestroy ?? true) && !this.#clearOnDestroyRegistered.has(ctxProvider)) {\n this.#clearOnDestroyRegistered.add(ctxProvider);\n this.#unsubscribeSecondary.add(() => {\n ctxProvider.set(undefined);\n });\n }\n\n return ctxProvider;\n }\n\n provideContext<T = unknown>(\n name: string | symbol,\n sourceOrInitialValue?: T | SignalReader<T> | SignalReader<T | undefined>,\n options?: ProvideContextOptions<T> | CompareFunc<T | undefined>,\n ) {\n if (this.#refuseAfterTearDown('provideContext')) return inertSignal();\n\n this.#reportDeprecatedIsEqualOption(options, 'provideContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#provideContextSignal(\n name,\n this.#contextProviders,\n (provider) => this.#entity.attachContextProvider(name, provider),\n sourceOrInitialValue,\n opts,\n );\n }\n\n provideGlobalContext<T = unknown>(\n name: string | symbol,\n sourceOrInitialValue?: T | SignalReader<T> | SignalReader<T | undefined>,\n options?: ProvideContextOptions<T> | CompareFunc<T | undefined>,\n ) {\n if (this.#refuseAfterTearDown('provideGlobalContext')) return inertSignal();\n\n this.#reportDeprecatedIsEqualOption(options, 'provideGlobalContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#provideContextSignal(\n name,\n this.#contextRootProviders,\n (provider) => this.#entity.attachGlobalContextProvider(name, provider),\n sourceOrInitialValue,\n opts,\n );\n }\n\n useContext<T = unknown>(name: string | symbol, options?: SignalValueOptions<T> | CompareFunc<T | undefined>) {\n if (this.#refuseAfterTearDown('useContext')) return inertSignal().get;\n\n this.#reportDeprecatedIsEqualOption(options, 'useContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#cachedReader(\n name,\n this.#contextReaders,\n this.#contextReaderCompares,\n () => this.#entity.useContext(name),\n opts,\n 'useContext',\n 'context',\n );\n }\n\n useParentContext<T = unknown>(name: string | symbol, options?: SignalValueOptions<T> | CompareFunc<T | undefined>) {\n if (this.#refuseAfterTearDown('useParentContext')) return inertSignal().get;\n\n this.#reportDeprecatedIsEqualOption(options, 'useParentContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#cachedReader(\n name,\n this.#contextParentReaders,\n this.#contextParentReaderCompares,\n () => this.#entity.useParentContext(name),\n opts,\n 'useParentContext',\n 'parent context',\n );\n }\n\n createSignal(...args: any[]): any {\n if (this.#refuseAfterTearDown('createSignal')) return inertSignal();\n\n // @ts-ignore\n const sig = createSignal(...args);\n this.#unsubscribeSecondary.add(() => {\n destroySignal(sig);\n });\n return sig;\n }\n\n createEffect(...args: any[]): ReturnType<typeof createEffect> {\n if (this.#refuseAfterTearDown('createEffect')) return inertEffect();\n\n // @ts-ignore\n const effect = createEffect(...args);\n this.#unsubscribeSecondary.add(effect.destroy);\n return effect;\n }\n\n createMemo<T = unknown>(...args: Parameters<typeof createMemo<T>>): SignalReader<T> {\n if (this.#refuseAfterTearDown('createMemo')) return inertSignal().get;\n\n const sig = createMemo<T>(...args);\n this.#unsubscribeSecondary.add(() => {\n destroySignal(sig);\n });\n return sig;\n }\n\n createResource<T = unknown>(factory: () => T | undefined, cleanup?: (resource: NonNullable<T>) => unknown): Signal<Maybe<T>> {\n if (this.#refuseAfterTearDown('createResource')) return inertSignal();\n\n const resourceSignal = createSignal<Maybe<T>>();\n\n const effect = createEffect(() => {\n const resource = toMaybe(factory());\n resourceSignal.set(resource);\n\n if (resource !== undefined && cleanup) {\n return () => {\n cleanup(resource);\n resourceSignal.set(undefined);\n };\n }\n\n return () => {\n resourceSignal.set(undefined);\n };\n });\n\n this.#unsubscribeSecondary.add(() => {\n // `effect.destroy()` runs the consumer's `cleanup`, which may throw. The two releases below\n // still have to run in that case -- a `finally` reaches them without swallowing the throw, so\n // `#runGuarded()` in `tearDown()` still sees and reports it.\n try {\n effect.destroy();\n } finally {\n resourceSignal.set(undefined);\n destroySignal(resourceSignal);\n }\n });\n\n return resourceSignal;\n }\n\n on(...args: any[]): ReturnType<typeof on> {\n if (this.#refuseAfterTearDown('on')) return noSubscription;\n\n const [firstArg] = args;\n const unsubscribe =\n typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)\n ? // @ts-ignore\n on(this.#entity, ...args)\n : // @ts-ignore\n on(...args);\n\n return this.#trackSubscription(unsubscribe);\n }\n\n once(...args: any[]): ReturnType<typeof once> {\n if (this.#refuseAfterTearDown('once')) return noSubscription;\n\n const [firstArg] = args;\n const unsubscribe =\n typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)\n ? // @ts-ignore\n once(this.#entity, ...args)\n : // @ts-ignore\n once(...args);\n\n return this.#trackSubscription(unsubscribe);\n }\n\n /**\n * The plain `emit()`, deliberately, where every notification the framework sends out of its own\n * accord runs on the guarded dispatch. This one is outbound and belongs to the Shadow Object: it\n * owns the listeners, a throw from one of them is its own bug, and letting it surface where it\n * happened is the fastest way to find it. A listener that needs a policy of its own carries a\n * `try`/`catch` in its own body, which is where that decision belongs.\n */\n emit(...args: any[]): void {\n if (this.#refuseAfterTearDown('emit')) return;\n\n const [firstArg] = args;\n if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {\n // @ts-ignore\n emit(this.#entity, ...args);\n } else {\n // @ts-ignore\n emit(...args);\n }\n }\n\n onViewEvent(callback: (type: string, data: unknown) => any): void {\n if (this.#refuseAfterTearDown('onViewEvent')) return;\n\n const unsub = on(this.#entity, onViewEvent, (type: string, data: unknown) => {\n callback(type, data);\n });\n this.#unsubscribeSecondary.add(unsub);\n }\n\n onDestroy(callback: () => any): void {\n if (this.#refuseAfterTearDown('onDestroy')) return;\n\n this.#unsubscribePrimary.add(callback);\n }\n\n dispatchMessageToView(type: string, data?: unknown, transferables?: Transferable[], traverseChildren = false): void {\n if (this.#refuseAfterTearDown('dispatchMessageToView')) return;\n\n this.#entity.dispatchMessageToView(type, data, transferables, traverseChildren);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {emit, on, once, Priority} from '@spearwolf/eventize';\nimport {\n type CompareFunc,\n createEffect,\n createMemo,\n createSignal,\n destroySignal,\n isSignal,\n link,\n type Signal,\n type SignalReader,\n} from '@spearwolf/signalize';\nimport type {\n Maybe,\n ProvideContextOptions,\n ShadowObjectCreationAPI,\n ShadowObjectScopeDescription,\n ShadowObjectType,\n SignalValueOptions,\n} from '../types.js';\nimport type {ConsoleLogger} from '../utils/ConsoleLogger.js';\nimport {runGuarded} from '../utils/runGuarded.js';\nimport {toMaybe} from '../utils/toMaybe.js';\nimport type {Entity} from './Entity.js';\nimport {onDestroy, onViewEvent} from './events.js';\n\n/**\n * What a creation-API call gets once the scope has closed: a real `Signal`, created and destroyed\n * on the spot. Reading it gives `undefined` and writing to it reaches nobody -- a destroyed signal\n * keeps its value but has neither effect nor link left on it. It belongs to whoever asked for it\n * and goes when they do, so a scope that is asked again and again after its end holds nothing.\n */\nconst inertSignal = (): Signal<any> => {\n const sig = createSignal<any>(undefined);\n destroySignal(sig);\n return sig;\n};\n\n/** The same for `createEffect()`: a real `Effect`, never run, already destroyed. */\nconst inertEffect = (): ReturnType<typeof createEffect> => {\n const effect = createEffect(() => {}, {autorun: false});\n effect.destroy();\n return effect;\n};\n\n/** The handle a late `on()` or `once()` gets: there is no subscription behind it. */\nconst noSubscription = (): void => {};\n\n/**\n * Where a subscription taken through the creation API goes: the arguments of eventize's `on()` /\n * `once()` with the entity put in front, or the arguments as they are when the first of them is a\n * target of its own.\n *\n * Eventize reads the *shape* of the arguments to tell its forms apart, and the creation API has to\n * read the same shape one argument earlier. The first argument means the entity when it is an event\n * name or a list of them, a priority, a listener function, or an object standing alone -- a\n * listener object with nothing after it, the form the Kernel itself uses to attach a Shadow Object.\n * An object followed by anything is the target: `on(other, 'ping', fn)`, `on(other, fn)` and\n * `on(other, listenerObject)`. The one form that is unreachable on the entity by design is a\n * listener object together with a context object, because `[object, object]` reads as a target and\n * its listener; a context is not needed for the entity, where the object itself is the receiver.\n */\nfunction subscribeOn(entity: Entity, args: unknown[]): unknown[] {\n const [first] = args;\n const isTarget = args.length > 1 && typeof first === 'object' && first !== null && !Array.isArray(first);\n return isTarget ? args : [entity, ...args];\n}\n\n/**\n * Everything a single shadow-object was given at construction time, and the end of all of it.\n *\n * The scope holds the signals, links and subscriptions the creation API hands out, and it hands the API\n * itself to the kernel through `createAPI()`. The instance stays with the kernel: a shadow-object only ever\n * sees the API object, never the scope behind it.\n *\n * One scope belongs to exactly one shadow-object, and it ends with it -- or, where the constructor throws,\n * without it: a scope that never reached `bindTo()` is torn down by the kernel on the spot, and everything the\n * constructor registered before the throw is released, although no shadow-object came out of it.\n *\n * Eight methods share their name with a module-level import: `on`, `once`, `emit`, `onDestroy`,\n * `onViewEvent`, `createSignal`, `createEffect` and `createMemo`. They are named that way deliberately,\n * because those names are part of the `ShadowObjectCreationAPI` contract a shadow-object destructures by\n * name. Seven of them call or reference their namesake inside their own body; `onDestroy` is the exception,\n * as its import is the entity event that `bindTo()` subscribes to. A bare name inside one of these eight\n * bodies is therefore always the import, and a call on the method of the same name always carries `this.`\n * -- `inertSignal`, `inertEffect` and `noSubscription` are bare names of a different kind, module-level\n * functions with no method of the same name to tell them apart from.\n */\nexport class ShadowObjectCreationScope {\n readonly #entity: Entity;\n readonly #logger: ConsoleLogger;\n readonly #displayName: string;\n\n // The kernel's list of member names whose deprecation report has already been made. Shared by\n // every scope of one kernel, which is what makes the report fall once per kernel and name.\n readonly #shownDeprecations: Set<string>;\n\n // The cleanup callbacks of the shadow-object itself, registered through `onDestroy()`.\n readonly #unsubscribePrimary = new Set<() => any>();\n\n // The cleanup callbacks the creation API registered on its own behalf. A `Set` iterating in\n // insertion order: which cleanup runs before which is observable behaviour.\n readonly #unsubscribeSecondary = new Set<() => any>();\n\n // The releases of the provider feeds, one per context name this shadow-object provides. The\n // entity hands each of them out when the provider is attached to it, and they fall after every\n // other cleanup callback, so a write the teardown still makes -- the `undefined` of a\n // `clearOnDestroy`, or one from an `onDestroy` callback -- reaches the entity-side signal instead\n // of stopping at the provider. Where the entity lives on, that is what makes the write count: the\n // entity hands it on to its own context signal one microtask later, and from there to its readers\n // and to the entities below it. The order matters in the other direction as well, because a\n // release also lets a provider that stays on the entity write its value once more, and that\n // hand-over may only happen once the write of the leaving provider is through.\n //\n // Where the entity is destroyed, the two kinds of target part ways. The signal behind\n // `provideContext()` takes the write and keeps it: the microtask that would hand it on falls\n // after the entity has cleared and destroyed its context signals, and the children that outlive\n // it were re-bound before the teardown even began. The signal behind `provideGlobalContext()`\n // stays a member of the kernel-wide chain of its name until the entity's own destruction runs at\n // `Priority.Min`, so the write does travel on to the inherited signals of other entities -- with\n // no observable difference, because the entity takes its signal out of that chain in the same run,\n // and what the chain resolves to without it is what those readers were going to see anyway: the\n // contribution of the next entity that holds the name, or nothing where there is none. The\n // ordering is kept for the paths on which it is observable.\n readonly #unsubscribeContextFeeds = new Set<() => any>();\n\n readonly #contextReaders = new Map<string | symbol, SignalReader<any>>();\n readonly #contextReaderCompares = new Map<string | symbol, CompareFunc<any> | undefined>();\n readonly #contextParentReaders = new Map<string | symbol, SignalReader<any>>();\n readonly #contextParentReaderCompares = new Map<string | symbol, CompareFunc<any> | undefined>();\n readonly #contextProviders = new Map<string | symbol, Signal<any>>();\n readonly #contextRootProviders = new Map<string | symbol, Signal<any>>();\n\n // The provider signals that already have their `clearOnDestroy` write registered in\n // `#unsubscribeSecondary`. Keyed by the signal itself rather than by name, because a\n // `provideContext(name)` and a `provideGlobalContext(name)` call can share one name while landing\n // in two different maps above -- a name-keyed set would conflate the two providers.\n readonly #clearOnDestroyRegistered = new Set<Signal<any>>();\n\n readonly #propertyReaders = new Map<string, SignalReader<any>>();\n readonly #propertyCompares = new Map<string, CompareFunc<any> | undefined>();\n\n #shadowObject: ShadowObjectType | undefined;\n #releaseScope: (() => void) | undefined;\n #forgetShadowObject: (() => void) | undefined;\n #unsubscribeFromEntityDestroy: (() => void) | undefined;\n\n #isTornDown = false;\n\n // Armed at the *end* of `tearDown()`, not at its start, and the difference is the whole point:\n // the teardown runs the shadow-object's own cleanup callbacks, and those are allowed the creation\n // API -- a goodbye to the view, a last write. What they register there is still swept up by the\n // steps behind them. What arrives after the teardown has returned is not, which is what this\n // closes.\n #isCreationApiClosed = false;\n\n // The member names whose late call has already been reported, at most as many as the API has\n // members. Lazy, because a scope that is used correctly never allocates it.\n #lateCallsReported: Set<string> | undefined;\n\n /**\n * The name the kernel gave this scope, taken from the constructor it belongs to rather than from\n * the shadow-object that came out of it. The two agree for most forms -- a class and a function\n * that returns nothing both leave their own name on the instance's `constructor` -- but not for a\n * function that returns an object literal: `new` hands that literal back, and it reports `Object`.\n * Reports about the shadow-object are keyed by this name, so the kernel reads it here instead of\n * asking the instance.\n */\n get displayName(): string {\n return this.#displayName;\n }\n\n /**\n * The four teardown handles, read without waiting on a garbage collector: a test can check that\n * `tearDown()` let go of them by comparing this before and after, rather than by proving the\n * absence of a reference through a `WeakRef`.\n *\n * @internal\n */\n get debugHandles(): {\n shadowObject: ShadowObjectType | undefined;\n releaseScope: (() => void) | undefined;\n forgetShadowObject: (() => void) | undefined;\n unsubscribeFromEntityDestroy: (() => void) | undefined;\n } {\n return {\n shadowObject: this.#shadowObject,\n releaseScope: this.#releaseScope,\n forgetShadowObject: this.#forgetShadowObject,\n unsubscribeFromEntityDestroy: this.#unsubscribeFromEntityDestroy,\n };\n }\n\n /**\n * How many cleanup callbacks the scope is holding, one count per set, read without waiting on a\n * garbage collector: a test can subscribe and unsubscribe n times and see that the scope let go\n * of each handle as it went, rather than inferring it from what a collector happened to do.\n *\n * @internal\n */\n get debugCleanupCounts(): {primary: number; secondary: number; contextFeeds: number} {\n return {\n primary: this.#unsubscribePrimary.size,\n secondary: this.#unsubscribeSecondary.size,\n contextFeeds: this.#unsubscribeContextFeeds.size,\n };\n }\n\n /**\n * The names this scope handed readers and providers out for, by kind, plus the display name. Read\n * off the private maps and nothing else: no reader is created, no late call is reported, and a\n * scope past its teardown answers empty lists rather than a throw -- `tearDown()` clears the maps\n * it reads.\n */\n describe(): ShadowObjectScopeDescription {\n return {\n displayName: this.#displayName,\n usesProperties: Array.from(this.#propertyReaders.keys()),\n usesContexts: Array.from(this.#contextReaders.keys()),\n usesParentContexts: Array.from(this.#contextParentReaders.keys()),\n providesContexts: Array.from(this.#contextProviders.keys()),\n providesGlobalContexts: Array.from(this.#contextRootProviders.keys()),\n };\n }\n\n constructor(entity: Entity, logger: ConsoleLogger, displayName: string, shownDeprecations: Set<string>) {\n this.#entity = entity;\n this.#logger = logger;\n this.#displayName = displayName;\n this.#shownDeprecations = shownDeprecations;\n }\n\n /**\n * The object that goes into `new construct(\u2026)`.\n *\n * Every member is a bound function, because a shadow-object constructor is expected to destructure the\n * API in its parameter list \u2014 a member that took its receiver from the call site would lose it there.\n */\n createAPI(): ShadowObjectCreationAPI {\n return {\n entity: this.#entity,\n\n provideContext: this.provideContext.bind(this),\n provideGlobalContext: this.provideGlobalContext.bind(this),\n useContext: this.useContext.bind(this),\n useParentContext: this.useParentContext.bind(this),\n\n dispatchMessageToView: this.dispatchMessageToView.bind(this),\n\n useProperty: this.useProperty.bind(this),\n useProperties: this.useProperties.bind(this),\n\n createResource: this.createResource.bind(this),\n createEffect: this.createEffect.bind(this),\n createSignal: this.createSignal.bind(this),\n createMemo: this.createMemo.bind(this),\n\n on: this.on.bind(this),\n once: this.once.bind(this),\n emit: this.emit.bind(this),\n onViewEvent: this.onViewEvent.bind(this),\n onDestroy: this.onDestroy.bind(this),\n };\n }\n\n /**\n * Binds the scope to the shadow-object it made the API for and subscribes to the destruction of the entity.\n *\n * A shadow-object reaches its end on two independent paths: the entity is destroyed, or the shadow-object\n * leaves the constructor set of a still living entity (token or route change). Both run the same teardown,\n * and each path reaches it through a handle of its own.\n *\n * The kernel keeps two releases rather than one, because they belong to opposite ends of the teardown:\n * `releaseScope` runs at its start, `forgetShadowObject` at its end.\n *\n * One scope serves one shadow-object, once: the call is part of the contract, and both ways of breaking\n * it are refused below.\n */\n bindTo(shadowObject: ShadowObjectType, releaseScope: () => void, forgetShadowObject: () => void): void {\n // Refused rather than quietly returned, unlike `tearDown()`, where a second call is two teardown paths\n // legitimately meeting. A second binding is nothing of the sort -- it would mean one scope serving two\n // shadow-objects. It would replace the handles of the first: the release of the kernel's map entry and\n // the unsubscribe from the entity's `onDestroy`, leaving the first shadow-object standing in the kernel\n // and on the entity with nothing left to take it out.\n //\n // The teardown is asked about first, because it is the only one of the two checks that still applies to\n // a torn-down scope: `tearDown()` lets go of `#shadowObject` at its own end, so a scope that has already\n // torn down would otherwise sail straight past the second check below and rebind. Once a scope carries a\n // shadow-object, it is the second check that tells a live scope's first binding from its second -- the\n // two never overlap on a scope that is still live.\n if (this.#isTornDown) {\n throw new Error(`the creation scope of \"${this.#displayName}\" has torn down and cannot be bound`);\n }\n if (this.#shadowObject !== undefined) {\n throw new Error(`the creation scope of \"${this.#displayName}\" is already bound to a shadow-object`);\n }\n\n this.#shadowObject = shadowObject;\n this.#releaseScope = releaseScope;\n this.#forgetShadowObject = forgetShadowObject;\n\n this.#logger.info('create shadow-object', this.#displayName, {shadowObject, entity: this.#entity});\n\n this.#unsubscribeFromEntityDestroy = once(this.#entity, onDestroy, Priority.Low, () => {\n this.tearDown();\n });\n }\n\n /**\n * Runs once, whichever path reaches it first.\n *\n * Three lead here. Two belong to a shadow-object that lived: its entity is destroyed, or it leaves the\n * constructor set of an entity that stays. On the third, the kernel calls this directly on a scope that\n * `bindTo()` never saw, because the constructor threw -- there is no shadow-object then, and three of the\n * handles below are still unset (`#releaseScope` and `#unsubscribeFromEntityDestroy` at the start,\n * `#forgetShadowObject` at the end), which is why all three are called optionally.\n *\n * The provider feeds are released after everything else, so that a write made on the way out reaches the\n * entity-side signal rather than stopping at the provider, and so that the entity hands the context over to\n * a provider that stays only once that write is through.\n *\n * The flag makes the teardown a one-time act: a destroy callback reaching back into the kernel finds no\n * way to start it a second time. Releasing both handles right after ends the retention in both directions\n * -- the kernel's map points from the shadow-object to this scope, the subscription points from the entity\n * to the same scope.\n *\n * The kernel is told to forget the shadow-object at the very end, so a destroy callback that reaches back\n * into the kernel still finds its shadow-object listed among the ones the constructor created. Once that\n * call is through, the four handles above are let go of as well -- the shadow-object, both kernel releases\n * and the entity subscription -- so a scope past this point holds none of the four through these fields.\n *\n * Every step below runs behind its own guard, so a callback or signal teardown that throws does not stop\n * the ones after it: the remaining callbacks, the remaining signal releases, and the provider feed\n * hand-over all still happen. A caught error goes to the logger by displayName and the label of the step\n * that failed, and is not re-thrown -- neither `changeToken()` nor `destroyEntity()` deliver it to their\n * caller, nor does it stop the destroy notification the entity is still delivering to whatever comes after\n * this shadow-object in the same run.\n *\n * The creation API is closed as the very last step, after everything above has run. Until then it\n * is open, because the cleanup callbacks of the shadow-object run inside this method and are\n * entitled to it -- a last message to the view, a last write to a context. What such a callback\n * registers is still reached by the steps behind it. The two sets of cleanup callbacks are run\n * in rounds until neither has anything left, so a callback that another one registers is reached\n * whichever of the two it lands in. The context feed releases follow all of them. What arrives\n * once this method has returned is not, and is turned away by `#refuseAfterTearDown()`.\n */\n tearDown(): void {\n if (this.#isTornDown) return;\n this.#isTornDown = true;\n\n this.#runGuarded('scope release', () => this.#releaseScope?.());\n this.#runGuarded('entity destroy subscription', () => this.#unsubscribeFromEntityDestroy?.());\n\n // Without a shadow-object there is nothing to report here: none ever came to be, because the\n // constructor threw before it could.\n if (this.#shadowObject !== undefined) {\n this.#logger.info('destroy shadow-object', this.#displayName, {shadowObject: this.#shadowObject, entity: this.#entity});\n }\n\n // The two callback sets are run in rounds, and the rounds are what a cleanup that books into a\n // set which has already had its turn needs. A `for\u2026of` over a `Set` reaches what is added to it\n // while it runs, so a callback that registers another one of its own kind is caught by the pass\n // it stands in. Across the two sets there is no such reach: a creation-api cleanup that calls\n // `onDestroy()` books into the first set, which is through, and a callback pulled along that way\n // may take a subscription or create a signal, which books back into the second. Each of them gets\n // its turn here, and the teardown ends when neither set has anything left to run. A pass skips\n // what has already run, so a callback that hands itself in again is not called twice; one that\n // hands in a new callback every time does not terminate.\n const alreadyRun = new Set<() => any>();\n\n const runCleanups = (callbacks: Set<() => any>, step: string): boolean => {\n let ranAny = false;\n for (const callback of callbacks) {\n if (alreadyRun.has(callback)) continue;\n alreadyRun.add(callback);\n ranAny = true;\n this.#runGuarded(step, callback);\n }\n return ranAny;\n };\n\n let ranAnything = true;\n while (ranAnything) {\n const ranPrimary = runCleanups(this.#unsubscribePrimary, 'onDestroy callback');\n const ranSecondary = runCleanups(this.#unsubscribeSecondary, 'creation-api cleanup');\n ranAnything = ranPrimary || ranSecondary;\n }\n\n for (const callback of this.#unsubscribeContextFeeds) {\n this.#runGuarded('context feed release', callback);\n }\n\n for (const sig of this.#contextReaders.values()) {\n this.#runGuarded('context reader', () => destroySignal(sig));\n }\n\n for (const sig of this.#contextParentReaders.values()) {\n this.#runGuarded('parent context reader', () => destroySignal(sig));\n }\n\n for (const sig of this.#propertyReaders.values()) {\n this.#runGuarded('property reader', () => destroySignal(sig));\n }\n\n for (const sig of this.#contextProviders.values()) {\n this.#runGuarded('context provider', () => destroySignal(sig));\n }\n\n for (const sig of this.#contextRootProviders.values()) {\n this.#runGuarded('global context provider', () => destroySignal(sig));\n }\n\n this.#unsubscribePrimary.clear();\n this.#unsubscribeSecondary.clear();\n this.#unsubscribeContextFeeds.clear();\n this.#contextReaders.clear();\n this.#contextReaderCompares.clear();\n this.#contextParentReaders.clear();\n this.#contextParentReaderCompares.clear();\n this.#propertyReaders.clear();\n this.#propertyCompares.clear();\n this.#contextProviders.clear();\n this.#contextRootProviders.clear();\n this.#clearOnDestroyRegistered.clear();\n\n this.#runGuarded('forget shadow-object', () => this.#forgetShadowObject?.());\n\n // Let go of the shadow-object and both kernel handles: nothing reads them past this point --\n // the info line above already ran, `#releaseScope` and `#unsubscribeFromEntityDestroy` were\n // called at the start of this method, and `#forgetShadowObject` was just called above. A scope\n // past this point holds neither the shadow-object nor either kernel handle through these\n // fields. `#entity` is a separate, `readonly` field the scope carries for its whole life --\n // it stays set here, and the entity, with the kernel behind it, stays reachable through it\n // whether or not the scope has torn down.\n this.#shadowObject = undefined;\n this.#releaseScope = undefined;\n this.#forgetShadowObject = undefined;\n this.#unsubscribeFromEntityDestroy = undefined;\n\n this.#isCreationApiClosed = true;\n }\n\n /**\n * Isolates one teardown step from the ones around it: a step that throws is reported through the\n * logger -- ungated, so the report stays visible outside localhost -- and does not stop `tearDown()`\n * from reaching the steps that follow. The report goes out through the shared `runGuarded()`;\n * what this wrapper adds is the label of the step and the display name it belongs to.\n */\n #runGuarded(step: string, run: () => void): void {\n runGuarded(this.#logger, run, `shadow-object teardown failed (${step}):`, this.#displayName);\n }\n\n /**\n * Books an `on()` or `once()` subscription into the cleanup set and hands back a handle that takes\n * it out again. Unsubscribing releases the callback there and then rather than at the teardown, so\n * a shadow-object that subscribes and unsubscribes over the whole life of its entity holds one\n * handle at a time instead of one per call. The target makes no difference to that: a subscription\n * on the entity ends the same way one on any other object does.\n */\n #trackSubscription(unsubscribe: () => void): () => void {\n this.#unsubscribeSecondary.add(unsubscribe);\n\n return Object.assign(() => {\n this.#unsubscribeSecondary.delete(unsubscribe);\n unsubscribe();\n }, unsubscribe);\n }\n\n /**\n * The body the three cached readers share: one reader per name, created on the first call and fed\n * from the entity-side source, plus a warning when a later call brings a different {compare}\n * function than the one the reader was created with.\n *\n * `linkSource` is a thunk because the source may only be read when a reader is actually created.\n */\n #cachedReader<K extends string | symbol>(\n name: K,\n readers: Map<K, SignalReader<any>>,\n compares: Map<K, CompareFunc<any> | undefined>,\n linkSource: () => SignalReader<any>,\n opts: SignalValueOptions<any> | undefined,\n apiName: string,\n subject: string,\n ): SignalReader<any> {\n let reader = readers.get(name);\n\n if (reader === undefined) {\n reader = createSignal<any>(undefined, opts).get;\n readers.set(name, reader);\n compares.set(name, opts?.compare);\n // Destroying this link is what ends the feed: the entity-side signal must not go on writing\n // into a reader that the teardown has already destroyed.\n const ln = link(linkSource(), reader);\n this.#unsubscribeSecondary.add(ln.destroy.bind(ln));\n } else if (opts?.compare != null && compares.get(name) !== opts.compare) {\n // Through `error` for the same reason as the deprecation report below: the options of this\n // call are being dropped, and the caller has to hear that outside `localhost` too, where the\n // shared `enable` behind `isWarn` is off.\n this.#logger.error(\n `[shadow-objects] ${apiName}(\"${String(name)}\"): the cached signal already exists with a different (or no) {compare} function \u2014 the new options are ignored. Pass options only on the first call per ${subject}.`,\n );\n }\n\n return reader;\n }\n\n /**\n * Reports the deprecated call form in which a bare compare function stands where the options\n * object belongs, at most once per kernel and member name.\n *\n * Through `error` rather than `warn`: this names a mistake in the calling code, and its author\n * has to see it wherever the application runs. `logger.warn` is asked `isWarn` first, and the\n * shared `enable` behind that getter is off anywhere but `localhost` -- a deprecation notice\n * that goes silent everywhere the code actually ships is no notice at all. See the table of\n * call against getter under \"Console Logger\" in `docs/api-reference.md`.\n *\n * One line per kernel and member name: a shadow-object calling a deprecated member inside a\n * loop would otherwise fill the console.\n */\n #reportDeprecatedIsEqualOption(options: unknown, apiName: string): void {\n if (typeof options !== 'function' || this.#shownDeprecations.has(apiName)) return;\n this.#logger.error(\n `[shadow-objects] Deprecation Warning: The \"isEqual\" option of \"${apiName}()\" is now passed as {compare} argument. Please update your code accordingly.`,\n );\n this.#shownDeprecations.add(apiName);\n }\n\n /**\n * Answers whether the creation API still has anything to give, and reports it where it has not.\n *\n * Past the teardown the scope has released what it held and cleared what it tracked. A call\n * arriving now would fill those maps again with entries no second teardown ever reaches -- the\n * teardown runs once, and it has run. Such a call is therefore turned away rather than served.\n *\n * Turned away quietly: the callers that arrive late are the ones with nobody to catch a throw --\n * a timer, a continuation behind an `await`, a callback of some other object that outlived this\n * one. It is reported instead, through `error` for the same reason the deprecation report above\n * uses it: this names a mistake in the calling code, and its author has to see it wherever the\n * application runs. Once per member name and scope, because a stale timer comes back on its next\n * tick and a line per tick would bury the first one.\n */\n #refuseAfterTearDown(apiName: string): boolean {\n if (!this.#isCreationApiClosed) return false;\n\n if (!this.#lateCallsReported?.has(apiName)) {\n (this.#lateCallsReported ??= new Set()).add(apiName);\n this.#logger.error(\n `[shadow-objects] ${apiName}(): the creation scope of \"${this.#displayName}\" has torn down \u2014 the call does nothing. Something is still holding the creation API past the end of its shadow-object.`,\n );\n }\n\n return true;\n }\n\n useProperty<T = unknown>(name: string, options?: SignalValueOptions<T> | CompareFunc<T | undefined>): SignalReader<Maybe<T>> {\n if (this.#refuseAfterTearDown('useProperty')) return inertSignal().get;\n\n this.#reportDeprecatedIsEqualOption(options, 'useProperty');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#cachedReader(\n name,\n this.#propertyReaders,\n this.#propertyCompares,\n () => this.#entity.getPropertyReader(name),\n opts,\n 'useProperty',\n 'property',\n );\n }\n\n useProperties<T extends Record<string, unknown> = Record<string, unknown>>(\n props: {[K in keyof T]: string},\n ): {\n [K in keyof T]: SignalReader<Maybe<T[K]>>;\n } {\n const result = {} as {[K in keyof T]: SignalReader<Maybe<T[K]>>};\n for (const key in props) {\n if (Object.hasOwn(props, key)) {\n result[key] = this.useProperty<T[typeof key]>(props[key]);\n }\n }\n return result;\n }\n\n /**\n * The body the two context providers share: one provider signal per name, created on the first\n * call, attached to the entity-side context signal, and cleared on teardown unless the caller\n * opted out -- a clearing that finds the way to the entity side still open. A source signal handed\n * in instead of an initial value feeds the provider through a link of its own.\n *\n * The entity keeps every provider of a name together and answers the attachment with the release\n * that detaches this one again. Releasing it does more than cut the feed: the entity then lets a\n * provider that stays write its value once more, so the name ends up with a value that is actually\n * still being provided rather than with what this shadow-object left behind on its way out.\n *\n * `attachToEntity` is called inside the creation branch only, so the entity-side signal is\n * requested when a provider is actually created. The `clearOnDestroy` check sits outside that\n * branch: every call is allowed to ask for the clearing, not only the one that created the signal.\n * The request is booked once per provider, though -- a repeated ask does not queue a second write,\n * and once a provider has one on file, an opt-out on a later call does not take it back.\n */\n #provideContextSignal(\n name: string | symbol,\n providers: Map<string | symbol, Signal<any>>,\n attachToEntity: (provider: Signal<any>) => () => void,\n sourceOrInitialValue: unknown,\n opts: ProvideContextOptions<any> | undefined,\n ): Signal<any> {\n let ctxProvider = providers.get(name);\n\n if (ctxProvider == null) {\n const isSig = isSignal(sourceOrInitialValue);\n const initialValue = isSig ? undefined : toMaybe(sourceOrInitialValue);\n\n ctxProvider = createSignal(initialValue, opts?.compare ? {compare: opts.compare} : undefined);\n\n if (isSig) {\n const ln = link(sourceOrInitialValue as SignalReader<any>, ctxProvider);\n this.#unsubscribeSecondary.add(ln.destroy.bind(ln));\n }\n\n // The release runs after every `clearOnDestroy` callback below, so a write to `undefined`\n // still reaches the context signal on the entity side before the feed is cut.\n this.#unsubscribeContextFeeds.add(attachToEntity(ctxProvider));\n providers.set(name, ctxProvider);\n }\n\n if ((opts?.clearOnDestroy ?? true) && !this.#clearOnDestroyRegistered.has(ctxProvider)) {\n this.#clearOnDestroyRegistered.add(ctxProvider);\n this.#unsubscribeSecondary.add(() => {\n ctxProvider.set(undefined);\n });\n }\n\n return ctxProvider;\n }\n\n provideContext<T = unknown>(\n name: string | symbol,\n sourceOrInitialValue?: T | SignalReader<T> | SignalReader<T | undefined>,\n options?: ProvideContextOptions<T> | CompareFunc<T | undefined>,\n ) {\n if (this.#refuseAfterTearDown('provideContext')) return inertSignal();\n\n this.#reportDeprecatedIsEqualOption(options, 'provideContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#provideContextSignal(\n name,\n this.#contextProviders,\n (provider) => this.#entity.attachContextProvider(name, provider),\n sourceOrInitialValue,\n opts,\n );\n }\n\n provideGlobalContext<T = unknown>(\n name: string | symbol,\n sourceOrInitialValue?: T | SignalReader<T> | SignalReader<T | undefined>,\n options?: ProvideContextOptions<T> | CompareFunc<T | undefined>,\n ) {\n if (this.#refuseAfterTearDown('provideGlobalContext')) return inertSignal();\n\n this.#reportDeprecatedIsEqualOption(options, 'provideGlobalContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#provideContextSignal(\n name,\n this.#contextRootProviders,\n (provider) => this.#entity.attachGlobalContextProvider(name, provider),\n sourceOrInitialValue,\n opts,\n );\n }\n\n useContext<T = unknown>(name: string | symbol, options?: SignalValueOptions<T> | CompareFunc<T | undefined>) {\n if (this.#refuseAfterTearDown('useContext')) return inertSignal().get;\n\n this.#reportDeprecatedIsEqualOption(options, 'useContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#cachedReader(\n name,\n this.#contextReaders,\n this.#contextReaderCompares,\n () => this.#entity.useContext(name),\n opts,\n 'useContext',\n 'context',\n );\n }\n\n useParentContext<T = unknown>(name: string | symbol, options?: SignalValueOptions<T> | CompareFunc<T | undefined>) {\n if (this.#refuseAfterTearDown('useParentContext')) return inertSignal().get;\n\n this.#reportDeprecatedIsEqualOption(options, 'useParentContext');\n\n const opts = typeof options === 'function' ? {compare: options} : options;\n\n return this.#cachedReader(\n name,\n this.#contextParentReaders,\n this.#contextParentReaderCompares,\n () => this.#entity.useParentContext(name),\n opts,\n 'useParentContext',\n 'parent context',\n );\n }\n\n createSignal(...args: any[]): any {\n if (this.#refuseAfterTearDown('createSignal')) return inertSignal();\n\n // @ts-ignore\n const sig = createSignal(...args);\n this.#unsubscribeSecondary.add(() => {\n destroySignal(sig);\n });\n return sig;\n }\n\n createEffect(...args: any[]): ReturnType<typeof createEffect> {\n if (this.#refuseAfterTearDown('createEffect')) return inertEffect();\n\n // @ts-ignore\n const effect = createEffect(...args);\n this.#unsubscribeSecondary.add(effect.destroy);\n return effect;\n }\n\n createMemo<T = unknown>(...args: Parameters<typeof createMemo<T>>): SignalReader<T> {\n if (this.#refuseAfterTearDown('createMemo')) return inertSignal().get;\n\n const sig = createMemo<T>(...args);\n this.#unsubscribeSecondary.add(() => {\n destroySignal(sig);\n });\n return sig;\n }\n\n createResource<T = unknown>(factory: () => T | undefined, cleanup?: (resource: NonNullable<T>) => unknown): Signal<Maybe<T>> {\n if (this.#refuseAfterTearDown('createResource')) return inertSignal();\n\n const resourceSignal = createSignal<Maybe<T>>();\n\n const effect = createEffect(() => {\n const resource = toMaybe(factory());\n resourceSignal.set(resource);\n\n if (resource !== undefined && cleanup) {\n return () => {\n cleanup(resource);\n resourceSignal.set(undefined);\n };\n }\n\n return () => {\n resourceSignal.set(undefined);\n };\n });\n\n this.#unsubscribeSecondary.add(() => {\n // `effect.destroy()` runs the consumer's `cleanup`, which may throw. The two releases below\n // still have to run in that case -- a `finally` reaches them without swallowing the throw, so\n // `#runGuarded()` in `tearDown()` still sees and reports it.\n try {\n effect.destroy();\n } finally {\n resourceSignal.set(undefined);\n destroySignal(resourceSignal);\n }\n });\n\n return resourceSignal;\n }\n\n on(...args: any[]): ReturnType<typeof on> {\n if (this.#refuseAfterTearDown('on')) return noSubscription;\n\n // @ts-ignore -- the standalone `on()` has no rest-parameter overload; `subscribeOn()` decided the target\n const unsubscribe = on(...subscribeOn(this.#entity, args));\n\n return this.#trackSubscription(unsubscribe);\n }\n\n once(...args: any[]): ReturnType<typeof once> {\n if (this.#refuseAfterTearDown('once')) return noSubscription;\n\n // @ts-ignore -- same as in `on()`\n const unsubscribe = once(...subscribeOn(this.#entity, args));\n\n return this.#trackSubscription(unsubscribe);\n }\n\n /**\n * The plain `emit()`, deliberately, where every notification the framework sends out of its own\n * accord runs on the guarded dispatch. This one is outbound and belongs to the Shadow Object: it\n * owns the listeners, a throw from one of them is its own bug, and letting it surface where it\n * happened is the fastest way to find it. A listener that needs a policy of its own carries a\n * `try`/`catch` in its own body, which is where that decision belongs.\n */\n emit(...args: any[]): void {\n if (this.#refuseAfterTearDown('emit')) return;\n\n const [firstArg] = args;\n if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {\n // @ts-ignore\n emit(this.#entity, ...args);\n } else {\n // @ts-ignore\n emit(...args);\n }\n }\n\n onViewEvent(callback: (type: string, data: unknown) => any): void {\n if (this.#refuseAfterTearDown('onViewEvent')) return;\n\n const unsub = on(this.#entity, onViewEvent, (type: string, data: unknown) => {\n callback(type, data);\n });\n this.#unsubscribeSecondary.add(unsub);\n }\n\n onDestroy(callback: () => any): void {\n if (this.#refuseAfterTearDown('onDestroy')) return;\n\n this.#unsubscribePrimary.add(callback);\n }\n\n dispatchMessageToView(type: string, data?: unknown, transferables?: Transferable[], traverseChildren = false): void {\n if (this.#refuseAfterTearDown('dispatchMessageToView')) return;\n\n this.#entity.dispatchMessageToView(type, data, transferables, traverseChildren);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -4,6 +4,8 @@ export declare class SignalsPath {
4
4
  static readonly Value = "value";
5
5
  accessor value: any;
6
6
  readonly value$: Signal<any>;
7
+ /** The members of the path in chain order -- the first one holding a value is the one `value` reads. A copy. */
8
+ get signals(): readonly SignalLike<any>[];
7
9
  constructor(signals?: SignalLike<any>[]);
8
10
  add(...signals: (Signal<any> | SignalLike<any>)[]): () => void;
9
11
  unshift(...signals: SignalLike<any>[]): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"SignalsPath.d.ts","sourceRoot":"","sources":["../../../src/in-the-dark/SignalsPath.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,MAAM,EACX,KAAK,UAAU,EAEhB,MAAM,sBAAsB,CAAC;AAK9B,qBAAa,WAAW;;IACtB,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAS;IAKP,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAa;IAEvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAE7B,YAAY,OAAO,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,EAetC;IAED,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,cAIhD;IAED,OAAO,CAAC,GAAG,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,cAIpC;IAED,MAAM,CAAC,GAAG,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,QAEnC;IAED,KAAK,SAGJ;IAED,OAAO,SAWN;CAkCF"}
1
+ {"version":3,"file":"SignalsPath.d.ts","sourceRoot":"","sources":["../../../src/in-the-dark/SignalsPath.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,MAAM,EACX,KAAK,UAAU,EAEhB,MAAM,sBAAsB,CAAC;AAK9B,qBAAa,WAAW;;IACtB,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAS;IAKP,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAa;IAEvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAE7B,gHAAgH;IAChH,IAAI,OAAO,IAAI,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,CAExC;IAED,YAAY,OAAO,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,EAetC;IAED,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,cAIhD;IAED,OAAO,CAAC,GAAG,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,cAIpC;IAED,MAAM,CAAC,GAAG,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,QAEnC;IAED,KAAK,SAGJ;IAED,OAAO,SAWN;CAkCF"}
@@ -72,6 +72,10 @@ class SignalsPath {
72
72
  this.add(...signals);
73
73
  }
74
74
  }
75
+ /** The members of the path in chain order -- the first one holding a value is the one `value` reads. A copy. */
76
+ get signals() {
77
+ return __privateGet(this, _signals).slice();
78
+ }
75
79
  add(...signals) {
76
80
  __privateGet(this, _signals).push(...signals);
77
81
  __privateMethod(this, _SignalsPath_instances, updateGetValueFromSignalsEffect_fn).call(this);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/in-the-dark/SignalsPath.ts"],
4
- "sourcesContent": ["import {emitSafe, off, retain, retainClear} from '@spearwolf/eventize';\nimport {\n createEffect,\n destroyObjectSignals,\n Effect,\n findObjectSignalByName,\n type Signal,\n type SignalLike,\n value,\n} from '@spearwolf/signalize';\nimport {signal} from '@spearwolf/signalize/decorators';\n\nconst VALUE = 'value';\n\nexport class SignalsPath {\n static readonly Value = VALUE;\n\n #signals: SignalLike<any>[] = [];\n #effect?: Effect | undefined;\n\n @signal({name: VALUE}) accessor value: any = undefined;\n\n readonly value$: Signal<any>;\n\n constructor(signals?: SignalLike<any>[]) {\n retain(this as SignalsPath, VALUE);\n\n // the @signal accessor above creates this signal during field initialization,\n // so the lookup by that name always resolves once the constructor body runs\n this.value$ = findObjectSignalByName(this, VALUE)!;\n // `emitSafe()`: this runs from a signal change callback, so a listener that throws would leave\n // through whichever write moved the path and reach code that has nothing to do with this value.\n // The retained value is written either way, because the event was delivered -- which matters\n // here, since `Value` is retained and a later subscriber reads exactly that.\n this.value$.onChange((val) => emitSafe(this as SignalsPath, VALUE, val));\n\n if (signals) {\n this.add(...signals);\n }\n }\n\n add(...signals: (Signal<any> | SignalLike<any>)[]) {\n this.#signals.push(...signals);\n this.#updateGetValueFromSignalsEffect();\n return this.#makeRemoveFunc(signals);\n }\n\n unshift(...signals: SignalLike<any>[]) {\n this.#signals.unshift(...signals);\n this.#updateGetValueFromSignalsEffect();\n return this.#makeRemoveFunc(signals);\n }\n\n remove(...signals: SignalLike<any>[]) {\n this.#makeRemoveFunc(signals)();\n }\n\n clear() {\n this.#signals.length = 0;\n this.#updateGetValueFromSignalsEffect();\n }\n\n dispose() {\n this.clear();\n\n this.#effect?.destroy();\n this.#effect = undefined;\n\n retainClear(this as SignalsPath, VALUE);\n off(this);\n\n this.value$.destroy();\n destroyObjectSignals(this);\n }\n\n #makeRemoveFunc(signals: SignalLike<any>[]) {\n return () => {\n for (const sig of signals) {\n const idx = this.#signals.indexOf(sig);\n if (idx !== -1) {\n this.#signals.splice(idx, 1);\n }\n }\n this.#updateGetValueFromSignalsEffect();\n };\n }\n\n #updateGetValueFromSignalsEffect() {\n this.#effect?.destroy();\n if (this.#signals.length === 0) {\n this.#effect = undefined;\n this.value = undefined;\n } else {\n this.#effect = createEffect(() => {\n let valueFromSignals: any;\n for (const sig of this.#signals) {\n const val = value(sig);\n if (val != null) {\n valueFromSignals = val;\n break;\n }\n }\n this.value = valueFromSignals;\n }, this.#signals);\n this.#effect.run();\n }\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAQ,UAAU,KAAK,QAAQ,mBAAkB;AACjD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,OACK;AACP,SAAQ,cAAa;AAErB,MAAM,QAAQ;AAQZ,cAAC,OAAO,EAAC,MAAM,MAAK,CAAC;AANhB,MAAM,YAAY;AAAA,EAUvB,YAAY,SAA6B;AAVpC;AAGL,iCAA8B,CAAC;AAC/B;AAEuB,uBAAS,QAAa,kBAAtB;AAEvB,SAAS,SAAT;AAGE,WAAO,MAAqB,KAAK;AAIjC,SAAK,SAAS,uBAAuB,MAAM,KAAK;AAKhD,SAAK,OAAO,SAAS,CAAC,QAAQ,SAAS,MAAqB,OAAO,GAAG,CAAC;AAEvE,QAAI,SAAS;AACX,WAAK,IAAI,GAAG,OAAO;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,OAAO,SAA4C;AACjD,uBAAK,UAAS,KAAK,GAAG,OAAO;AAC7B,0BAAK,4DAAL;AACA,WAAO,sBAAK,2CAAL,WAAqB;AAAA,EAC9B;AAAA,EAEA,WAAW,SAA4B;AACrC,uBAAK,UAAS,QAAQ,GAAG,OAAO;AAChC,0BAAK,4DAAL;AACA,WAAO,sBAAK,2CAAL,WAAqB;AAAA,EAC9B;AAAA,EAEA,UAAU,SAA4B;AACpC,0BAAK,2CAAL,WAAqB,SAAS;AAAA,EAChC;AAAA,EAEA,QAAQ;AACN,uBAAK,UAAS,SAAS;AACvB,0BAAK,4DAAL;AAAA,EACF;AAAA,EAEA,UAAU;AACR,SAAK,MAAM;AAEX,uBAAK,UAAS,QAAQ;AACtB,uBAAK,SAAU;AAEf,gBAAY,MAAqB,KAAK;AACtC,QAAI,IAAI;AAER,SAAK,OAAO,QAAQ;AACpB,yBAAqB,IAAI;AAAA,EAC3B;AAkCF;AA7FO;AAGL;AACA;AAEgC;AAN3B;AA6DL,oBAAe,SAAC,SAA4B;AAC1C,SAAO,MAAM;AACX,eAAW,OAAO,SAAS;AACzB,YAAM,MAAM,mBAAK,UAAS,QAAQ,GAAG;AACrC,UAAI,QAAQ,IAAI;AACd,2BAAK,UAAS,OAAO,KAAK,CAAC;AAAA,MAC7B;AAAA,IACF;AACA,0BAAK,4DAAL;AAAA,EACF;AACF;AAEA,qCAAgC,WAAG;AACjC,qBAAK,UAAS,QAAQ;AACtB,MAAI,mBAAK,UAAS,WAAW,GAAG;AAC9B,uBAAK,SAAU;AACf,SAAK,QAAQ;AAAA,EACf,OAAO;AACL,uBAAK,SAAU,aAAa,MAAM;AAChC,UAAI;AACJ,iBAAW,OAAO,mBAAK,WAAU;AAC/B,cAAM,MAAM,MAAM,GAAG;AACrB,YAAI,OAAO,MAAM;AACf,6BAAmB;AACnB;AAAA,QACF;AAAA,MACF;AACA,WAAK,QAAQ;AAAA,IACf,GAAG,mBAAK,SAAQ;AAChB,uBAAK,SAAQ,IAAI;AAAA,EACnB;AACF;AAtFuB,4BAAS,SAAhC,YANW,aAMqB;AAN3B,2BAAM;AAAA,YACK,QAAQ;",
4
+ "sourcesContent": ["import {emitSafe, off, retain, retainClear} from '@spearwolf/eventize';\nimport {\n createEffect,\n destroyObjectSignals,\n Effect,\n findObjectSignalByName,\n type Signal,\n type SignalLike,\n value,\n} from '@spearwolf/signalize';\nimport {signal} from '@spearwolf/signalize/decorators';\n\nconst VALUE = 'value';\n\nexport class SignalsPath {\n static readonly Value = VALUE;\n\n #signals: SignalLike<any>[] = [];\n #effect?: Effect | undefined;\n\n @signal({name: VALUE}) accessor value: any = undefined;\n\n readonly value$: Signal<any>;\n\n /** The members of the path in chain order -- the first one holding a value is the one `value` reads. A copy. */\n get signals(): readonly SignalLike<any>[] {\n return this.#signals.slice();\n }\n\n constructor(signals?: SignalLike<any>[]) {\n retain(this as SignalsPath, VALUE);\n\n // the @signal accessor above creates this signal during field initialization,\n // so the lookup by that name always resolves once the constructor body runs\n this.value$ = findObjectSignalByName(this, VALUE)!;\n // `emitSafe()`: this runs from a signal change callback, so a listener that throws would leave\n // through whichever write moved the path and reach code that has nothing to do with this value.\n // The retained value is written either way, because the event was delivered -- which matters\n // here, since `Value` is retained and a later subscriber reads exactly that.\n this.value$.onChange((val) => emitSafe(this as SignalsPath, VALUE, val));\n\n if (signals) {\n this.add(...signals);\n }\n }\n\n add(...signals: (Signal<any> | SignalLike<any>)[]) {\n this.#signals.push(...signals);\n this.#updateGetValueFromSignalsEffect();\n return this.#makeRemoveFunc(signals);\n }\n\n unshift(...signals: SignalLike<any>[]) {\n this.#signals.unshift(...signals);\n this.#updateGetValueFromSignalsEffect();\n return this.#makeRemoveFunc(signals);\n }\n\n remove(...signals: SignalLike<any>[]) {\n this.#makeRemoveFunc(signals)();\n }\n\n clear() {\n this.#signals.length = 0;\n this.#updateGetValueFromSignalsEffect();\n }\n\n dispose() {\n this.clear();\n\n this.#effect?.destroy();\n this.#effect = undefined;\n\n retainClear(this as SignalsPath, VALUE);\n off(this);\n\n this.value$.destroy();\n destroyObjectSignals(this);\n }\n\n #makeRemoveFunc(signals: SignalLike<any>[]) {\n return () => {\n for (const sig of signals) {\n const idx = this.#signals.indexOf(sig);\n if (idx !== -1) {\n this.#signals.splice(idx, 1);\n }\n }\n this.#updateGetValueFromSignalsEffect();\n };\n }\n\n #updateGetValueFromSignalsEffect() {\n this.#effect?.destroy();\n if (this.#signals.length === 0) {\n this.#effect = undefined;\n this.value = undefined;\n } else {\n this.#effect = createEffect(() => {\n let valueFromSignals: any;\n for (const sig of this.#signals) {\n const val = value(sig);\n if (val != null) {\n valueFromSignals = val;\n break;\n }\n }\n this.value = valueFromSignals;\n }, this.#signals);\n this.#effect.run();\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAQ,UAAU,KAAK,QAAQ,mBAAkB;AACjD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,OACK;AACP,SAAQ,cAAa;AAErB,MAAM,QAAQ;AAQZ,cAAC,OAAO,EAAC,MAAM,MAAK,CAAC;AANhB,MAAM,YAAY;AAAA,EAevB,YAAY,SAA6B;AAfpC;AAGL,iCAA8B,CAAC;AAC/B;AAEuB,uBAAS,QAAa,kBAAtB;AAEvB,SAAS,SAAT;AAQE,WAAO,MAAqB,KAAK;AAIjC,SAAK,SAAS,uBAAuB,MAAM,KAAK;AAKhD,SAAK,OAAO,SAAS,CAAC,QAAQ,SAAS,MAAqB,OAAO,GAAG,CAAC;AAEvE,QAAI,SAAS;AACX,WAAK,IAAI,GAAG,OAAO;AAAA,IACrB;AAAA,EACF;AAAA;AAAA,EAnBA,IAAI,UAAsC;AACxC,WAAO,mBAAK,UAAS,MAAM;AAAA,EAC7B;AAAA,EAmBA,OAAO,SAA4C;AACjD,uBAAK,UAAS,KAAK,GAAG,OAAO;AAC7B,0BAAK,4DAAL;AACA,WAAO,sBAAK,2CAAL,WAAqB;AAAA,EAC9B;AAAA,EAEA,WAAW,SAA4B;AACrC,uBAAK,UAAS,QAAQ,GAAG,OAAO;AAChC,0BAAK,4DAAL;AACA,WAAO,sBAAK,2CAAL,WAAqB;AAAA,EAC9B;AAAA,EAEA,UAAU,SAA4B;AACpC,0BAAK,2CAAL,WAAqB,SAAS;AAAA,EAChC;AAAA,EAEA,QAAQ;AACN,uBAAK,UAAS,SAAS;AACvB,0BAAK,4DAAL;AAAA,EACF;AAAA,EAEA,UAAU;AACR,SAAK,MAAM;AAEX,uBAAK,UAAS,QAAQ;AACtB,uBAAK,SAAU;AAEf,gBAAY,MAAqB,KAAK;AACtC,QAAI,IAAI;AAER,SAAK,OAAO,QAAQ;AACpB,yBAAqB,IAAI;AAAA,EAC3B;AAkCF;AAlGO;AAGL;AACA;AAEgC;AAN3B;AAkEL,oBAAe,SAAC,SAA4B;AAC1C,SAAO,MAAM;AACX,eAAW,OAAO,SAAS;AACzB,YAAM,MAAM,mBAAK,UAAS,QAAQ,GAAG;AACrC,UAAI,QAAQ,IAAI;AACd,2BAAK,UAAS,OAAO,KAAK,CAAC;AAAA,MAC7B;AAAA,IACF;AACA,0BAAK,4DAAL;AAAA,EACF;AACF;AAEA,qCAAgC,WAAG;AACjC,qBAAK,UAAS,QAAQ;AACtB,MAAI,mBAAK,UAAS,WAAW,GAAG;AAC9B,uBAAK,SAAU;AACf,SAAK,QAAQ;AAAA,EACf,OAAO;AACL,uBAAK,SAAU,aAAa,MAAM;AAChC,UAAI;AACJ,iBAAW,OAAO,mBAAK,WAAU;AAC/B,cAAM,MAAM,MAAM,GAAG;AACrB,YAAI,OAAO,MAAM;AACf,6BAAmB;AACnB;AAAA,QACF;AAAA,MACF;AACA,WAAK,QAAQ;AAAA,IACf,GAAG,mBAAK,SAAQ;AAChB,uBAAK,SAAQ,IAAI;AAAA,EACnB;AACF;AA3FuB,4BAAS,SAAhC,YANW,aAMqB;AAN3B,2BAAM;AAAA,YACK,QAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,4 @@
1
+ import type { ShadowObjectConstructor } from '../types.js';
2
+ /** The name the Kernel reports a Shadow Object under: the constructor's `displayName`, or its `name`. */
3
+ export declare const getDisplayName: (construct: ShadowObjectConstructor) => string;
4
+ //# sourceMappingURL=displayName.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayName.d.ts","sourceRoot":"","sources":["../../../src/in-the-dark/displayName.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,aAAa,CAAC;AAEzD,yGAAyG;AACzG,eAAO,MAAM,cAAc,cAAe,uBAAuB,KAAG,MAAiD,CAAC"}
@@ -0,0 +1,5 @@
1
+ const getDisplayName = (construct) => construct.displayName || construct.name;
2
+ export {
3
+ getDisplayName
4
+ };
5
+ //# sourceMappingURL=displayName.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/in-the-dark/displayName.ts"],
4
+ "sourcesContent": ["import type {ShadowObjectConstructor} from '../types.js';\n\n/** The name the Kernel reports a Shadow Object under: the constructor's `displayName`, or its `name`. */\nexport const getDisplayName = (construct: ShadowObjectConstructor): string => construct.displayName || construct.name;\n"],
5
+ "mappings": "AAGO,MAAM,iBAAiB,CAAC,cAA+C,UAAU,eAAe,UAAU;",
6
+ "names": []
7
+ }
package/src/index.d.ts CHANGED
@@ -8,6 +8,8 @@ export * from './elements/ShaeElement.js';
8
8
  export * from './elements/ShaeEntElement.js';
9
9
  export * from './elements/ShaePropElement.js';
10
10
  export * from './elements/ShaeWorkerElement.js';
11
+ export { createKernelSnapshot } from './inspect/createKernelSnapshot.js';
12
+ export type * from './inspect/types.js';
11
13
  export type * from './types.js';
12
14
  export * from './utils/FrameLoop.js';
13
15
  export * from './utils/toNamespace.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,mBAAmB,sBAAsB,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,mBAAmB,YAAY,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,iCAAiC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,mBAAmB,sBAAsB,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,OAAO,EAAC,oBAAoB,EAAC,MAAM,mCAAmC,CAAC;AACvE,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,YAAY,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,iCAAiC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
package/src/index.js CHANGED
@@ -7,6 +7,7 @@ export * from "./elements/ShaeElement.js";
7
7
  export * from "./elements/ShaeEntElement.js";
8
8
  export * from "./elements/ShaePropElement.js";
9
9
  export * from "./elements/ShaeWorkerElement.js";
10
+ import { createKernelSnapshot } from "./inspect/createKernelSnapshot.js";
10
11
  export * from "./utils/FrameLoop.js";
11
12
  export * from "./utils/toNamespace.js";
12
13
  export * from "./view/ComponentContext.js";
@@ -15,4 +16,7 @@ export * from "./view/RemoteWorkerEnv.js";
15
16
  export * from "./view/ShadowEnv.js";
16
17
  export * from "./view/ViewComponent.js";
17
18
  export * from "./WorkerTimeoutError.js";
19
+ export {
20
+ createKernelSnapshot
21
+ };
18
22
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["export * from './ChangeTrailRefusedError.js';\nexport * from './constants.js';\nexport * from './EntityUuidInUseError.js';\nexport * from './elements/constants.js';\nexport type * from './elements/events.js';\nexport * from './elements/requestEntAncestor.js';\nexport * from './elements/ShaeElement.js';\nexport * from './elements/ShaeEntElement.js';\nexport * from './elements/ShaePropElement.js';\nexport * from './elements/ShaeWorkerElement.js';\nexport type * from './types.js';\nexport * from './utils/FrameLoop.js';\nexport * from './utils/toNamespace.js';\nexport * from './view/ComponentContext.js';\nexport type * from './view/ComponentMemory.js';\nexport type * from './view/IShadowObjectEnvProxy.js';\nexport * from './view/LocalShadowObjectEnv.js';\nexport * from './view/RemoteWorkerEnv.js';\nexport * from './view/ShadowEnv.js';\nexport * from './view/ViewComponent.js';\nexport * from './WorkerTimeoutError.js';\n"],
5
- "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
4
+ "sourcesContent": ["export * from './ChangeTrailRefusedError.js';\nexport * from './constants.js';\nexport * from './EntityUuidInUseError.js';\nexport * from './elements/constants.js';\nexport type * from './elements/events.js';\nexport * from './elements/requestEntAncestor.js';\nexport * from './elements/ShaeElement.js';\nexport * from './elements/ShaeEntElement.js';\nexport * from './elements/ShaePropElement.js';\nexport * from './elements/ShaeWorkerElement.js';\nexport {createKernelSnapshot} from './inspect/createKernelSnapshot.js';\nexport type * from './inspect/types.js';\nexport type * from './types.js';\nexport * from './utils/FrameLoop.js';\nexport * from './utils/toNamespace.js';\nexport * from './view/ComponentContext.js';\nexport type * from './view/ComponentMemory.js';\nexport type * from './view/IShadowObjectEnvProxy.js';\nexport * from './view/LocalShadowObjectEnv.js';\nexport * from './view/RemoteWorkerEnv.js';\nexport * from './view/ShadowEnv.js';\nexport * from './view/ViewComponent.js';\nexport * from './WorkerTimeoutError.js';\n"],
5
+ "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAQ,4BAA2B;AAGnC,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,17 @@
1
+ import type { Kernel } from '../in-the-dark/Kernel.js';
2
+ import type { ContextName, InspectRequest, KernelSnapshot } from './types.js';
3
+ /** A string name as it is; a symbol as its description, marked as such. */
4
+ export declare const toContextName: (name: string | symbol) => ContextName;
5
+ /** The rule `Entity.truthyProps()` routes by. */
6
+ export declare const routesOnValue: (val: unknown) => boolean;
7
+ /**
8
+ * A plain-data picture of the Entity Tree behind a Kernel, cut by the limits of the request: every
9
+ * visited Entity with its properties, Shadow Objects and Entity Contexts, the global context chains,
10
+ * and the Registry. Synchronous, read-only, and quiet -- no signal read here subscribes anything.
11
+ *
12
+ * The walk follows the rules of `getEntityGraph()`: every Entity appears once, a child the Kernel no
13
+ * longer holds or the walk has already placed is named under `omittedChildren`. What this adds is
14
+ * the depth and node budget, and the `truncation` notes that say where a budget cut the walk.
15
+ */
16
+ export declare function createKernelSnapshot(kernel: Kernel, request?: InspectRequest): KernelSnapshot;
17
+ //# sourceMappingURL=createKernelSnapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createKernelSnapshot.d.ts","sourceRoot":"","sources":["../../../src/inspect/createKernelSnapshot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAUrD,OAAO,KAAK,EACV,WAAW,EAOX,cAAc,EACd,cAAc,EAKf,MAAM,YAAY,CAAC;AAEpB,2EAA2E;AAC3E,eAAO,MAAM,aAAa,SAAU,MAAM,GAAG,MAAM,KAAG,WACc,CAAC;AAErE,iDAAiD;AACjD,eAAO,MAAM,aAAa,QAAS,OAAO,KAAG,OAAqD,CAAC;AAOnG;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,cAAc,CAE7F"}