@genome-spy/core 0.68.0 → 0.69.1

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 (163) hide show
  1. package/dist/bundle/index.es.js +12119 -10681
  2. package/dist/bundle/index.js +119 -119
  3. package/dist/schema.json +6224 -6319
  4. package/dist/src/data/dataFlow.d.ts.map +1 -1
  5. package/dist/src/data/dataFlow.js +10 -0
  6. package/dist/src/data/flowNode.d.ts +25 -10
  7. package/dist/src/data/flowNode.d.ts.map +1 -1
  8. package/dist/src/data/flowNode.js +66 -13
  9. package/dist/src/data/flowTestUtils.d.ts +2 -2
  10. package/dist/src/data/flowTestUtils.d.ts.map +1 -1
  11. package/dist/src/data/flowTestUtils.js +5 -4
  12. package/dist/src/data/sources/dataSource.js +2 -2
  13. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  14. package/dist/src/data/sources/lazy/bigBedSource.js +11 -10
  15. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  16. package/dist/src/data/sources/lazy/bigWigSource.js +11 -10
  17. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +1 -1
  18. package/dist/src/data/sources/lazy/tabixSource.d.ts +0 -1
  19. package/dist/src/data/sources/lazy/tabixSource.d.ts.map +1 -1
  20. package/dist/src/data/sources/lazy/tabixSource.js +41 -11
  21. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  22. package/dist/src/data/sources/sequenceSource.js +5 -3
  23. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  24. package/dist/src/data/sources/urlSource.js +7 -3
  25. package/dist/src/data/transforms/filter.d.ts +4 -4
  26. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  27. package/dist/src/data/transforms/filter.js +13 -7
  28. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  29. package/dist/src/data/transforms/filterScoredLabels.js +11 -6
  30. package/dist/src/data/transforms/filterScoredLabels.test.d.ts +2 -0
  31. package/dist/src/data/transforms/filterScoredLabels.test.d.ts.map +1 -0
  32. package/dist/src/data/transforms/formula.d.ts +4 -4
  33. package/dist/src/data/transforms/formula.d.ts.map +1 -1
  34. package/dist/src/data/transforms/formula.js +12 -6
  35. package/dist/src/data/transforms/measureText.d.ts +2 -2
  36. package/dist/src/data/transforms/measureText.d.ts.map +1 -1
  37. package/dist/src/data/transforms/measureText.js +16 -12
  38. package/dist/src/data/transforms/transform.d.ts +2 -2
  39. package/dist/src/data/transforms/transform.d.ts.map +1 -1
  40. package/dist/src/data/transforms/transform.js +3 -3
  41. package/dist/src/encoder/accessor.d.ts +8 -4
  42. package/dist/src/encoder/accessor.d.ts.map +1 -1
  43. package/dist/src/encoder/accessor.js +10 -10
  44. package/dist/src/encoder/encoder.js +5 -5
  45. package/dist/src/genome/genome.d.ts +8 -0
  46. package/dist/src/genome/genome.d.ts.map +1 -1
  47. package/dist/src/genome/genome.js +16 -1
  48. package/dist/src/genomeSpy/inputBindingManager.js +1 -1
  49. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  50. package/dist/src/genomeSpy/interactionController.js +7 -1
  51. package/dist/src/genomeSpy.js +1 -1
  52. package/dist/src/gl/glslScaleGenerator.js +1 -1
  53. package/dist/src/marks/mark.d.ts.map +1 -1
  54. package/dist/src/marks/mark.js +22 -30
  55. package/dist/src/marks/point.d.ts.map +1 -1
  56. package/dist/src/marks/point.js +4 -6
  57. package/dist/src/paramRuntime/expressionCompiler.d.ts +7 -0
  58. package/dist/src/paramRuntime/expressionCompiler.d.ts.map +1 -0
  59. package/dist/src/paramRuntime/expressionCompiler.js +10 -0
  60. package/dist/src/paramRuntime/expressionRef.d.ts +20 -0
  61. package/dist/src/paramRuntime/expressionRef.d.ts.map +1 -0
  62. package/dist/src/paramRuntime/expressionRef.js +95 -0
  63. package/dist/src/paramRuntime/expressionRef.test.d.ts +2 -0
  64. package/dist/src/paramRuntime/expressionRef.test.d.ts.map +1 -0
  65. package/dist/src/paramRuntime/graphRuntime.d.ts +176 -0
  66. package/dist/src/paramRuntime/graphRuntime.d.ts.map +1 -0
  67. package/dist/src/paramRuntime/graphRuntime.js +628 -0
  68. package/dist/src/paramRuntime/graphRuntime.test.d.ts +2 -0
  69. package/dist/src/paramRuntime/graphRuntime.test.d.ts.map +1 -0
  70. package/dist/src/paramRuntime/index.d.ts +9 -0
  71. package/dist/src/paramRuntime/index.d.ts.map +1 -0
  72. package/dist/src/paramRuntime/index.js +8 -0
  73. package/dist/src/paramRuntime/lifecycleRegistry.d.ts +27 -0
  74. package/dist/src/paramRuntime/lifecycleRegistry.d.ts.map +1 -0
  75. package/dist/src/paramRuntime/lifecycleRegistry.js +54 -0
  76. package/dist/src/paramRuntime/paramRuntime.d.ts +165 -0
  77. package/dist/src/paramRuntime/paramRuntime.d.ts.map +1 -0
  78. package/dist/src/paramRuntime/paramRuntime.js +222 -0
  79. package/dist/src/paramRuntime/paramRuntime.test.d.ts +2 -0
  80. package/dist/src/paramRuntime/paramRuntime.test.d.ts.map +1 -0
  81. package/dist/src/paramRuntime/paramStore.d.ts +68 -0
  82. package/dist/src/paramRuntime/paramStore.d.ts.map +1 -0
  83. package/dist/src/paramRuntime/paramStore.js +148 -0
  84. package/dist/src/paramRuntime/paramStore.test.d.ts +2 -0
  85. package/dist/src/paramRuntime/paramStore.test.d.ts.map +1 -0
  86. package/dist/src/paramRuntime/paramUtils.d.ts +86 -0
  87. package/dist/src/paramRuntime/paramUtils.d.ts.map +1 -0
  88. package/dist/src/paramRuntime/paramUtils.js +272 -0
  89. package/dist/src/paramRuntime/selectionStore.d.ts +6 -0
  90. package/dist/src/paramRuntime/selectionStore.d.ts.map +1 -0
  91. package/dist/src/paramRuntime/selectionStore.js +13 -0
  92. package/dist/src/paramRuntime/types.d.ts +16 -0
  93. package/dist/src/paramRuntime/types.d.ts.map +1 -0
  94. package/dist/src/paramRuntime/types.js +25 -0
  95. package/dist/src/paramRuntime/viewParamRuntime.d.ts +164 -0
  96. package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -0
  97. package/dist/src/paramRuntime/viewParamRuntime.js +443 -0
  98. package/dist/src/scales/scaleInstanceManager.d.ts +6 -3
  99. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  100. package/dist/src/scales/scaleInstanceManager.js +17 -11
  101. package/dist/src/scales/scaleResolution.d.ts +1 -0
  102. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  103. package/dist/src/scales/scaleResolution.js +7 -1
  104. package/dist/src/selection/selection.js +1 -1
  105. package/dist/src/spec/coreSchemaRoot.d.ts +53 -0
  106. package/dist/src/spec/root.d.ts +1 -1
  107. package/dist/src/spec/view.d.ts +114 -33
  108. package/dist/src/tooltip/dataTooltipHandler.d.ts +1 -1
  109. package/dist/src/tooltip/dataTooltipHandler.js +23 -32
  110. package/dist/src/tooltip/dataTooltipHandler.test.d.ts +2 -0
  111. package/dist/src/tooltip/dataTooltipHandler.test.d.ts.map +1 -0
  112. package/dist/src/tooltip/flattenDatumRows.d.ts +13 -0
  113. package/dist/src/tooltip/flattenDatumRows.d.ts.map +1 -0
  114. package/dist/src/tooltip/flattenDatumRows.js +47 -0
  115. package/dist/src/tooltip/flattenDatumRows.test.d.ts +2 -0
  116. package/dist/src/tooltip/flattenDatumRows.test.d.ts.map +1 -0
  117. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts +1 -1
  118. package/dist/src/tooltip/refseqGeneTooltipHandler.js +7 -1
  119. package/dist/src/tooltip/tooltipContext.d.ts +13 -0
  120. package/dist/src/tooltip/tooltipContext.d.ts.map +1 -0
  121. package/dist/src/tooltip/tooltipContext.js +543 -0
  122. package/dist/src/tooltip/tooltipContext.test.d.ts +2 -0
  123. package/dist/src/tooltip/tooltipContext.test.d.ts.map +1 -0
  124. package/dist/src/tooltip/tooltipHandler.d.ts +40 -1
  125. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  126. package/dist/src/tooltip/tooltipHandler.ts +62 -1
  127. package/dist/src/types/encoder.d.ts +1 -1
  128. package/dist/src/utils/inputBinding.d.ts +10 -2
  129. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  130. package/dist/src/utils/inputBinding.js +12 -3
  131. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  132. package/dist/src/view/flowBuilder.js +12 -3
  133. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  134. package/dist/src/view/gridView/gridChild.js +8 -3
  135. package/dist/src/view/gridView/selectionRect.d.ts +6 -10
  136. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  137. package/dist/src/view/gridView/selectionRect.js +3 -20
  138. package/dist/src/view/layerView.d.ts.map +1 -1
  139. package/dist/src/view/layerView.js +4 -2
  140. package/dist/src/view/multiscale.d.ts +35 -0
  141. package/dist/src/view/multiscale.d.ts.map +1 -0
  142. package/dist/src/view/multiscale.js +233 -0
  143. package/dist/src/view/multiscale.test.d.ts +2 -0
  144. package/dist/src/view/multiscale.test.d.ts.map +1 -0
  145. package/dist/src/view/unitView.d.ts.map +1 -1
  146. package/dist/src/view/unitView.js +10 -4
  147. package/dist/src/view/view.d.ts +5 -4
  148. package/dist/src/view/view.d.ts.map +1 -1
  149. package/dist/src/view/view.js +223 -28
  150. package/dist/src/view/viewFactory.d.ts +0 -12
  151. package/dist/src/view/viewFactory.d.ts.map +1 -1
  152. package/dist/src/view/viewFactory.js +35 -24
  153. package/dist/src/view/viewParamRuntime.test.d.ts +2 -0
  154. package/dist/src/view/viewParamRuntime.test.d.ts.map +1 -0
  155. package/dist/src/view/viewSelectors.d.ts.map +1 -1
  156. package/dist/src/view/viewSelectors.js +8 -5
  157. package/package.json +3 -3
  158. package/dist/src/spec/sampleView.d.ts +0 -197
  159. package/dist/src/view/paramMediator.d.ts +0 -168
  160. package/dist/src/view/paramMediator.d.ts.map +0 -1
  161. package/dist/src/view/paramMediator.js +0 -545
  162. package/dist/src/view/paramMediator.test.d.ts +0 -2
  163. package/dist/src/view/paramMediator.test.d.ts.map +0 -1
@@ -48,7 +48,10 @@ import coalesceProperties from "../utils/propertyCoalescer.js";
48
48
  import { isScalar } from "../utils/variableTools.js";
49
49
  import { InternMap } from "internmap";
50
50
  import ViewError from "../view/viewError.js";
51
- import { isExprRef, validateParameterName } from "../view/paramMediator.js";
51
+ import {
52
+ isExprRef,
53
+ validateParameterName,
54
+ } from "../paramRuntime/paramUtils.js";
52
55
  import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
53
56
  import {
54
57
  isIntervalSelection,
@@ -95,11 +98,6 @@ export default class Mark {
95
98
  */
96
99
  #callAfterShaderCompilation = [];
97
100
 
98
- /**
99
- * @type {{expr: import("../view/paramMediator.js").ExprRefFunction, listener: () => void}[]}
100
- */
101
- #exprListeners = [];
102
-
103
101
  /**
104
102
  * @param {import("../view/unitView.js").default} unitView
105
103
  */
@@ -304,13 +302,13 @@ export default class Mark {
304
302
  for (const key of props) {
305
303
  const prop = this.properties[key];
306
304
  if (prop && isExprRef(prop)) {
307
- const fn = this.unitView.paramMediator.createExpression(
308
- prop.expr
305
+ const fn = this.unitView.paramRuntime.watchExpression(
306
+ prop.expr,
307
+ () => {
308
+ this.updateGraphicsData();
309
+ this.unitView.context.animator.requestRender();
310
+ }
309
311
  );
310
- fn.addListener(() => {
311
- this.updateGraphicsData();
312
- this.unitView.context.animator.requestRender();
313
- });
314
312
  // @ts-ignore
315
313
  if (!channels.includes(key)) {
316
314
  Object.defineProperty(exprProps, key, {
@@ -487,8 +485,8 @@ export default class Mark {
487
485
 
488
486
  for (const predicate of paramPredicates) {
489
487
  const param = predicate.param;
490
- const paramMediator = this.unitView.paramMediator;
491
- const selection = paramMediator.findValue(param);
488
+ const paramRuntime = this.unitView.paramRuntime;
489
+ const selection = paramRuntime.findValue(param);
492
490
 
493
491
  // The selection is supposed to have an empty value at this point
494
492
  // so that we can figure out the type of the selection.
@@ -546,7 +544,7 @@ export default class Mark {
546
544
 
547
545
  this.selectionTextureOps.push(() => {
548
546
  // Texture is set in the prepareRender method
549
- const selection = paramMediator.getValue(param);
547
+ const selection = paramRuntime.getValue(param);
550
548
  const texture = selectionTextures.get(selection);
551
549
  if (!texture) {
552
550
  throw new Error(
@@ -569,11 +567,10 @@ export default class Mark {
569
567
  // Create the initial texture
570
568
  glHelper.createSelectionTexture(selection);
571
569
 
572
- const fn = paramMediator.createExpression(param);
573
- fn.addListener(() => {
570
+ paramRuntime.watchExpression(param, () => {
574
571
  const selection =
575
572
  /** @type {import("../types/selectionTypes.js").MultiPointSelection} */ (
576
- fn(null)
573
+ paramRuntime.getValue(param)
577
574
  );
578
575
  glHelper.createSelectionTexture(selection);
579
576
  this.getContext().animator.requestRender();
@@ -1044,15 +1041,14 @@ export default class Mark {
1044
1041
  };
1045
1042
 
1046
1043
  if (isExprRef(propValue)) {
1047
- const fn = this.unitView.paramMediator.createExpression(
1048
- propValue.expr
1049
- );
1050
-
1044
+ /** @type {import("../paramRuntime/types.js").ExprRefFunction} */
1045
+ let fn;
1051
1046
  const set = () => setter(adjuster(fn(null)));
1047
+ fn = this.unitView.paramRuntime.watchExpression(
1048
+ propValue.expr,
1049
+ set
1050
+ );
1052
1051
 
1053
- // Register a listener ...
1054
- fn.addListener(set);
1055
- this.#exprListeners.push({ expr: fn, listener: set });
1056
1052
  // ... and set the initial value
1057
1053
  set();
1058
1054
  } else {
@@ -1097,10 +1093,6 @@ export default class Mark {
1097
1093
  }
1098
1094
 
1099
1095
  dispose() {
1100
- for (const { expr, listener } of this.#exprListeners) {
1101
- expr.removeListener(listener);
1102
- }
1103
- this.#exprListeners.length = 0;
1104
1096
  this.deleteGraphicsData();
1105
1097
  }
1106
1098
 
@@ -1177,7 +1169,7 @@ export default class Mark {
1177
1169
  isPickingParticipant() {
1178
1170
  if (
1179
1171
  this.properties.tooltip === null &&
1180
- !this.unitView.paramMediator.hasPointSelections()
1172
+ !this.unitView.paramRuntime.hasPointSelections()
1181
1173
  ) {
1182
1174
  // Disabled
1183
1175
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAmBA;;GAEG;AACH;IAGI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAmD/C;IA0EO,iDAMC;IAkET,+BAkBC;;CAgDJ;iBAtRgB,WAAW"}
1
+ {"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAmBA;;GAEG;AACH;IAGI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAiD/C;IA0EO,iDAMC;IAkET,+BAkBC;;CAgDJ;iBApRgB,WAAW"}
@@ -10,7 +10,7 @@ import FRAGMENT_SHADER from "./point.fragment.glsl.js";
10
10
  import COMMON_SHADER from "./point.common.glsl.js";
11
11
 
12
12
  import Mark from "./mark.js";
13
- import { isExprRef } from "../view/paramMediator.js";
13
+ import { isExprRef } from "../paramRuntime/paramUtils.js";
14
14
  import { sampleIterable } from "../data/transforms/sample.js";
15
15
  import { fixFill, fixStroke } from "./markUtils.js";
16
16
 
@@ -58,11 +58,9 @@ export default class PointMark extends Mark {
58
58
  const szf = this.properties.semanticZoomFraction;
59
59
  if (szf != null) {
60
60
  if (isExprRef(szf)) {
61
- const fn = this.unitView.paramMediator.createExpression(
62
- szf.expr
63
- );
64
- fn.addListener(() =>
65
- this.getContext().animator.requestRender()
61
+ const fn = this.unitView.paramRuntime.watchExpression(
62
+ szf.expr,
63
+ () => this.getContext().animator.requestRender()
66
64
  );
67
65
  this.#semanticZoomFraction = fn;
68
66
  } else {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @param {string} expr
3
+ * @param {Record<string, any>} [globalObject]
4
+ * @returns {import("../utils/expression.js").ExpressionFunction}
5
+ */
6
+ export function compileExpression(expr: string, globalObject?: Record<string, any>): import("../utils/expression.js").ExpressionFunction;
7
+ //# sourceMappingURL=expressionCompiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressionCompiler.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/expressionCompiler.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wCAJW,MAAM,iBACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACjB,OAAO,wBAAwB,EAAE,kBAAkB,CAI/D"}
@@ -0,0 +1,10 @@
1
+ import createFunction from "../utils/expression.js";
2
+
3
+ /**
4
+ * @param {string} expr
5
+ * @param {Record<string, any>} [globalObject]
6
+ * @returns {import("../utils/expression.js").ExpressionFunction}
7
+ */
8
+ export function compileExpression(expr, globalObject = {}) {
9
+ return createFunction(expr, globalObject);
10
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @typedef {{
3
+ * expression: import("./types.js").ExprRefFunction,
4
+ * dependencies: import("./types.js").ParamRef<any>[]
5
+ * }} BoundExpression
6
+ */
7
+ /**
8
+ * Binds expression globals to parameter refs in a specific scope and equips the
9
+ * resulting expression function with listener lifecycle helpers.
10
+ *
11
+ * @param {string} expr
12
+ * @param {(name: string) => import("./types.js").ParamRef<any> | undefined} resolve
13
+ * @returns {BoundExpression}
14
+ */
15
+ export function bindExpression(expr: string, resolve: (name: string) => import("./types.js").ParamRef<any> | undefined): BoundExpression;
16
+ export type BoundExpression = {
17
+ expression: import("./types.js").ExprRefFunction;
18
+ dependencies: import("./types.js").ParamRef<any>[];
19
+ };
20
+ //# sourceMappingURL=expressionRef.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressionRef.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/expressionRef.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,qCAJW,MAAM,WACN,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,SAAS,GAC9D,eAAe,CA+E3B;8BA3FY;IACR,UAAU,EAAE,OAAO,YAAY,EAAE,eAAe,CAAC;IACjD,YAAY,EAAE,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAA;CACnD"}
@@ -0,0 +1,95 @@
1
+ import { compileExpression } from "./expressionCompiler.js";
2
+
3
+ /**
4
+ * @typedef {{
5
+ * expression: import("./types.js").ExprRefFunction,
6
+ * dependencies: import("./types.js").ParamRef<any>[]
7
+ * }} BoundExpression
8
+ */
9
+
10
+ /**
11
+ * Binds expression globals to parameter refs in a specific scope and equips the
12
+ * resulting expression function with listener lifecycle helpers.
13
+ *
14
+ * @param {string} expr
15
+ * @param {(name: string) => import("./types.js").ParamRef<any> | undefined} resolve
16
+ * @returns {BoundExpression}
17
+ */
18
+ export function bindExpression(expr, resolve) {
19
+ const globalObject = {};
20
+
21
+ /** @type {import("./types.js").ExprRefFunction} */
22
+ const expression = /** @type {any} */ (
23
+ compileExpression(expr, globalObject)
24
+ );
25
+
26
+ /** @type {Map<string, import("./types.js").ParamRef<any>>} */
27
+ const refsForParams = new Map();
28
+
29
+ for (const globalName of expression.globals) {
30
+ if (refsForParams.has(globalName)) {
31
+ continue;
32
+ }
33
+
34
+ const ref = resolve(globalName);
35
+ if (!ref) {
36
+ throw new Error(
37
+ 'Unknown variable "' + globalName + '" in expression: ' + expr
38
+ );
39
+ }
40
+
41
+ refsForParams.set(globalName, ref);
42
+
43
+ Object.defineProperty(globalObject, globalName, {
44
+ enumerable: true,
45
+ get() {
46
+ return ref.get();
47
+ },
48
+ });
49
+ }
50
+
51
+ /** @type {Set<() => void>} */
52
+ const activeSubscriptions = new Set();
53
+
54
+ expression.subscribe = (listener) => {
55
+ /** @type {(() => void)[]} */
56
+ const disposers = [];
57
+ for (const ref of refsForParams.values()) {
58
+ disposers.push(ref.subscribe(listener));
59
+ }
60
+
61
+ let active = true;
62
+ const unsubscribe = () => {
63
+ if (!active) {
64
+ return;
65
+ }
66
+ active = false;
67
+ activeSubscriptions.delete(unsubscribe);
68
+ disposers.forEach((dispose) => dispose());
69
+ };
70
+ activeSubscriptions.add(unsubscribe);
71
+
72
+ return unsubscribe;
73
+ };
74
+
75
+ expression.invalidate = () => {
76
+ for (const unsubscribe of activeSubscriptions) {
77
+ unsubscribe();
78
+ }
79
+ activeSubscriptions.clear();
80
+ };
81
+
82
+ // Include dependency identities to avoid collisions between structurally
83
+ // identical expressions in different scopes.
84
+ expression.identifier = () =>
85
+ expression.code +
86
+ "|" +
87
+ Array.from(refsForParams.values())
88
+ .map((ref) => ref.id)
89
+ .join(",");
90
+
91
+ return {
92
+ expression,
93
+ dependencies: Array.from(refsForParams.values()),
94
+ };
95
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=expressionRef.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressionRef.test.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/expressionRef.test.js"],"names":[],"mappings":""}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Low-level reactive DAG runtime for parameter propagation.
3
+ *
4
+ * `GraphRuntime` is the scheduling engine behind `ParamRuntime`. It owns:
5
+ * 1. Writable source nodes (`base` and `selection`).
6
+ * 2. Derived/computed nodes with explicit dependencies.
7
+ * 3. Side-effect nodes that run after computed stabilization.
8
+ * 4. Transaction-aware batching and deterministic topological flushing.
9
+ *
10
+ * Typical usage:
11
+ * 1. Create writable refs using `createWritable(...)`.
12
+ * 2. Build derived refs with `computed(...)` from existing refs.
13
+ * 3. Attach side effects with `effect(...)` when external work is needed.
14
+ * 4. Batch writes with `runInTransaction(...)` when multiple updates belong to
15
+ * one logical state transition.
16
+ * 5. Await `whenPropagated(...)` when callers need a "graph is settled" barrier.
17
+ *
18
+ * Notes:
19
+ * 1. This class is intended for runtime internals; most call sites should use
20
+ * `ParamRuntime` / `ViewParamRuntime`.
21
+ * 2. Equality is referential (`!==`), so object writes must use new identities
22
+ * to trigger propagation.
23
+ */
24
+ export default class GraphRuntime {
25
+ /**
26
+ * Creates a graph runtime.
27
+ *
28
+ * @param {object} [options]
29
+ * @param {import("./lifecycleRegistry.js").default} [options.lifecycleRegistry]
30
+ * Optional lifecycle owner registry. When provided, all created nodes
31
+ * are bound to owners and disposed automatically on owner disposal.
32
+ */
33
+ constructor(options?: {
34
+ lifecycleRegistry?: import("./lifecycleRegistry.js").default;
35
+ });
36
+ /**
37
+ * Registers a writable source node and returns a writable param ref.
38
+ *
39
+ * Write semantics:
40
+ * 1. A write triggers propagation only when `value !== currentValue`.
41
+ * 2. If `options.notify` is `false`, local listeners are not notified and
42
+ * downstream scheduling is skipped for writes to this ref.
43
+ * 3. Writing to a disposed ref throws.
44
+ *
45
+ * Lifecycle:
46
+ * 1. The node is owner-bound via `ownerId`.
47
+ * 2. Owner disposal marks the node disposed and clears listeners.
48
+ *
49
+ * @template T
50
+ * @param {string} ownerId
51
+ * @param {string} name
52
+ * @param {"base" | "selection"} kind
53
+ * @param {T} initialValue
54
+ * @param {{ notify?: boolean }} [options]
55
+ * @returns {import("./types.js").WritableParamRef<T>}
56
+ */
57
+ createWritable<T>(ownerId: string, name: string, kind: "base" | "selection", initialValue: T, options?: {
58
+ notify?: boolean;
59
+ }): import("./types.js").WritableParamRef<T>;
60
+ /**
61
+ * Registers a derived node whose value is computed from dependencies.
62
+ *
63
+ * Compute semantics:
64
+ * 1. Initial value is computed eagerly at registration time.
65
+ * 2. On dependency changes, recomputation is queued (deduplicated per flush).
66
+ * 3. Downstream listeners are notified only if computed value identity changes.
67
+ *
68
+ * Lifecycle:
69
+ * 1. Dependency subscriptions are created immediately.
70
+ * 2. Owner disposal unsubscribes dependencies and detaches the node.
71
+ *
72
+ * @template T
73
+ * @param {string} ownerId
74
+ * @param {string} name
75
+ * @param {import("./types.js").ParamRef<any>[]} deps
76
+ * @param {() => T} fn
77
+ * @returns {import("./types.js").ParamRef<T>}
78
+ */
79
+ computed<T>(ownerId: string, name: string, deps: import("./types.js").ParamRef<any>[], fn: () => T): import("./types.js").ParamRef<T>;
80
+ /**
81
+ * Registers an effect node that runs after computed propagation.
82
+ *
83
+ * Effect semantics:
84
+ * 1. Effect callbacks are queued on dependency changes.
85
+ * 2. Effects run after computed nodes for the same flush epoch.
86
+ * 3. Multiple dependency changes before a flush coalesce to one queued run.
87
+ *
88
+ * @param {string} ownerId
89
+ * @param {import("./types.js").ParamRef<any>[]} deps
90
+ * @param {() => void} fn
91
+ * @returns {() => void} explicit disposer for manual teardown
92
+ */
93
+ effect(ownerId: string, deps: import("./types.js").ParamRef<any>[], fn: () => void): () => void;
94
+ /**
95
+ * Runs `fn` as an atomic update transaction for this runtime graph.
96
+ *
97
+ * Transaction intent:
98
+ * 1. Batch multiple source writes so downstream computeds/effects observe
99
+ * the final state for the batch, not each intermediate write.
100
+ * 2. Defer scheduling/flush until the outermost transaction exits.
101
+ * 3. Preserve deterministic propagation order by running one flush pass
102
+ * after the transaction boundary.
103
+ *
104
+ * Semantics:
105
+ * 1. Nested transactions are supported via depth counting.
106
+ * 2. Only the outermost transaction exit triggers scheduling.
107
+ * 3. If `fn` throws, the error is rethrown after transaction depth is
108
+ * restored; pending propagation is still scheduled from `finally`.
109
+ * 4. The scheduled flush runs in a microtask (`queueMicrotask`) after the
110
+ * outermost transaction exits.
111
+ * 5. This method does not force immediate synchronous propagation. Use
112
+ * `flushNow()` when the caller explicitly requires immediate flushing.
113
+ *
114
+ * @template T
115
+ * @param {() => T} fn
116
+ * @returns {T}
117
+ */
118
+ runInTransaction<T>(fn: () => T): T;
119
+ /**
120
+ * Flushes currently queued computed/effect work immediately.
121
+ *
122
+ * Behavior:
123
+ * 1. No-op if called while a transaction is open.
124
+ * 2. No-op during re-entrant flush calls.
125
+ * 3. Runs computeds first, then effects, until the graph reaches a fixed
126
+ * point for the current queued work.
127
+ */
128
+ flushNow(): void;
129
+ /**
130
+ * Returns a promise that resolves when currently pending graph propagation
131
+ * has completed (computed queue and effect queue are settled).
132
+ *
133
+ * This is a synchronization barrier for reactive propagation only. It does
134
+ * not include animation/time-based convergence semantics.
135
+ *
136
+ * @param {{ signal?: AbortSignal, timeoutMs?: number }} [options]
137
+ * Optional cancellation/timeout controls for waiting callers.
138
+ * @returns {Promise<void>}
139
+ */
140
+ whenPropagated(options?: {
141
+ signal?: AbortSignal;
142
+ timeoutMs?: number;
143
+ }): Promise<void>;
144
+ #private;
145
+ }
146
+ export type SubscribeFn = (listener: () => void) => () => void;
147
+ export type RuntimeNodeBase = {
148
+ id: string;
149
+ rank: number;
150
+ disposed: boolean;
151
+ listeners: Set<() => void>;
152
+ subscribe: SubscribeFn;
153
+ };
154
+ export type WritableNode<T> = RuntimeNodeBase & {
155
+ value: T;
156
+ kind: "base" | "selection";
157
+ name: string;
158
+ };
159
+ export type ComputedNode<T> = RuntimeNodeBase & {
160
+ value: T;
161
+ kind: "derived";
162
+ name: string;
163
+ fn: () => T;
164
+ };
165
+ export type EffectNode = {
166
+ id: string;
167
+ rank: number;
168
+ disposed: boolean;
169
+ fn: () => void;
170
+ };
171
+ /**
172
+ * @param {import("./types.js").ParamRef<any>} ref
173
+ * @returns {RuntimeNodeBase}
174
+ */
175
+ export function getNode(ref: import("./types.js").ParamRef<any>): RuntimeNodeBase;
176
+ //# sourceMappingURL=graphRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphRuntime.d.ts","sourceRoot":"","sources":["../../../src/paramRuntime/graphRuntime.js"],"names":[],"mappings":"AAoIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IA6BI;;;;;;;OAOG;IACH,sBAJG;QAA2D,iBAAiB,GAApE,OAAO,wBAAwB,EAAE,OAAO;KAGlD,EAGA;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,eARa,CAAC,WACH,MAAM,QACN,MAAM,QACN,MAAM,GAAG,WAAW,gBACpB,CAAC,YACD;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAClB,OAAO,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAwDpD;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,SAPa,CAAC,WACH,MAAM,QACN,MAAM,QACN,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MACpC,MAAM,CAAC,GACL,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAuD5C;IAED;;;;;;;;;;;;OAYG;IACH,gBALW,MAAM,QACN,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MACpC,MAAM,IAAI,GACR,MAAM,IAAI,CAwCtB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,iBAJa,CAAC,MACH,MAAM,CAAC,GACL,CAAC,CAYb;IAED;;;;;;;;OAQG;IACH,iBA8CC;IAED;;;;;;;;;;OAUG;IACH,yBAJW;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAE1C,OAAO,CAAC,IAAI,CAAC,CAgDzB;;CA2EJ;0BA3mBY,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI;8BAEpC;IACR,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3B,SAAS,EAAE,WAAW,CAAA;CACvB;yBAIS,CAAC,IACD,eAAe,GAAG;IAC1B,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAA;CACb;yBAIS,CAAC,IACD,eAAe,GAAG;IAC1B,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC,CAAA;CACZ;yBAIS;IACR,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,EAAE,EAAE,MAAM,IAAI,CAAA;CACf;AAgEJ;;;GAGG;AACH,6BAHW,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAChC,eAAe,CAa3B"}