@genome-spy/core 0.65.0 → 0.67.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 (249) hide show
  1. package/dist/bundle/browser-BRemItdO.js +138 -0
  2. package/dist/bundle/{index-CD7FLu9x.js → index-BatuyGAI.js} +23 -21
  3. package/dist/bundle/{index-C0llXMqm.js → index-ByuE8dvu.js} +140 -88
  4. package/dist/bundle/index-Cq3QFUxX.js +1781 -0
  5. package/dist/bundle/index-D28m8tSW.js +1607 -0
  6. package/dist/bundle/index-DbJ0oeYM.js +631 -0
  7. package/dist/bundle/index.es.js +15821 -14601
  8. package/dist/bundle/index.js +214 -212
  9. package/dist/bundle/{inflate-DRgHi_KK.js → inflate-GtwLkvSP.js} +222 -224
  10. package/dist/bundle/unzip-NywezaRR.js +1492 -0
  11. package/dist/schema.json +13 -3
  12. package/dist/src/config/scaleDefaults.d.ts +8 -0
  13. package/dist/src/config/scaleDefaults.d.ts.map +1 -0
  14. package/dist/src/config/scaleDefaults.js +45 -0
  15. package/dist/src/data/flowHandle.d.ts +2 -0
  16. package/dist/src/data/flowHandle.d.ts.map +1 -1
  17. package/dist/src/data/flowHandle.js +1 -0
  18. package/dist/src/data/flowInit.d.ts +12 -4
  19. package/dist/src/data/flowInit.d.ts.map +1 -1
  20. package/dist/src/data/flowInit.js +115 -16
  21. package/dist/src/data/sources/lazy/axisTickSource.js +1 -1
  22. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +1 -1
  23. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  24. package/dist/src/data/sources/lazy/singleAxisLazySource.js +10 -3
  25. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  26. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +5 -1
  27. package/dist/src/data/transforms/filterScoredLabels.d.ts +1 -1
  28. package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -1
  29. package/dist/src/data/transforms/filterScoredLabels.js +1 -1
  30. package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts.map +1 -1
  31. package/dist/src/data/transforms/linearizeGenomicCoordinate.js +2 -1
  32. package/dist/src/encoder/encoder.d.ts +1 -1
  33. package/dist/src/encoder/encoder.d.ts.map +1 -1
  34. package/dist/src/encoder/encoder.js +1 -1
  35. package/dist/src/genome/scaleLocus.d.ts +39 -0
  36. package/dist/src/genome/scaleLocus.d.ts.map +1 -1
  37. package/dist/src/genome/scaleLocus.js +76 -0
  38. package/dist/src/genomeSpy/canvasExport.d.ts +19 -0
  39. package/dist/src/genomeSpy/canvasExport.d.ts.map +1 -0
  40. package/dist/src/genomeSpy/canvasExport.js +66 -0
  41. package/dist/src/genomeSpy/containerUi.d.ts +17 -0
  42. package/dist/src/genomeSpy/containerUi.d.ts.map +1 -0
  43. package/dist/src/genomeSpy/containerUi.js +78 -0
  44. package/dist/src/genomeSpy/eventListenerRegistry.d.ts +19 -0
  45. package/dist/src/genomeSpy/eventListenerRegistry.d.ts.map +1 -0
  46. package/dist/src/genomeSpy/eventListenerRegistry.js +38 -0
  47. package/dist/src/genomeSpy/inputBindingManager.d.ts +14 -0
  48. package/dist/src/genomeSpy/inputBindingManager.d.ts.map +1 -0
  49. package/dist/src/genomeSpy/inputBindingManager.js +63 -0
  50. package/dist/src/genomeSpy/interactionController.d.ts +40 -0
  51. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -0
  52. package/dist/src/genomeSpy/interactionController.js +371 -0
  53. package/dist/src/genomeSpy/keyboardListenerManager.d.ts +10 -0
  54. package/dist/src/genomeSpy/keyboardListenerManager.d.ts.map +1 -0
  55. package/dist/src/genomeSpy/keyboardListenerManager.js +31 -0
  56. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts +15 -0
  57. package/dist/src/genomeSpy/loadingIndicatorManager.d.ts.map +1 -0
  58. package/dist/src/genomeSpy/loadingIndicatorManager.js +92 -0
  59. package/dist/src/genomeSpy/renderCoordinator.d.ts +22 -0
  60. package/dist/src/genomeSpy/renderCoordinator.d.ts.map +1 -0
  61. package/dist/src/genomeSpy/renderCoordinator.js +118 -0
  62. package/dist/src/genomeSpy/viewContextFactory.d.ts +18 -0
  63. package/dist/src/genomeSpy/viewContextFactory.d.ts.map +1 -0
  64. package/dist/src/genomeSpy/viewContextFactory.js +79 -0
  65. package/dist/src/genomeSpy/viewDataInit.d.ts +22 -0
  66. package/dist/src/genomeSpy/viewDataInit.d.ts.map +1 -0
  67. package/dist/src/genomeSpy/viewDataInit.js +160 -0
  68. package/dist/src/genomeSpy/viewDataInit.test.d.ts +2 -0
  69. package/dist/src/genomeSpy/viewDataInit.test.d.ts.map +1 -0
  70. package/dist/src/genomeSpy/viewHierarchyConfig.d.ts +14 -0
  71. package/dist/src/genomeSpy/viewHierarchyConfig.d.ts.map +1 -0
  72. package/dist/src/genomeSpy/viewHierarchyConfig.js +24 -0
  73. package/dist/src/genomeSpy/viewHighlight.d.ts +5 -0
  74. package/dist/src/genomeSpy/viewHighlight.d.ts.map +1 -0
  75. package/dist/src/genomeSpy/viewHighlight.js +30 -0
  76. package/dist/src/genomeSpy.d.ts +17 -71
  77. package/dist/src/genomeSpy.d.ts.map +1 -1
  78. package/dist/src/genomeSpy.js +197 -741
  79. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  80. package/dist/src/gl/dataToVertices.js +16 -4
  81. package/dist/src/gl/glslScaleGenerator.d.ts +1 -1
  82. package/dist/src/gl/webGLHelper.d.ts +2 -2
  83. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  84. package/dist/src/gl/webGLHelper.js +4 -4
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/index.js +2 -12
  87. package/dist/src/marks/mark.d.ts.map +1 -1
  88. package/dist/src/marks/mark.js +4 -2
  89. package/dist/src/{view → scales}/axisResolution.d.ts +9 -16
  90. package/dist/src/scales/axisResolution.d.ts.map +1 -0
  91. package/dist/src/{view → scales}/axisResolution.js +29 -18
  92. package/dist/src/scales/axisResolution.test.d.ts.map +1 -0
  93. package/dist/src/scales/scaleDomainAggregator.d.ts +57 -0
  94. package/dist/src/scales/scaleDomainAggregator.d.ts.map +1 -0
  95. package/dist/src/scales/scaleDomainAggregator.js +167 -0
  96. package/dist/src/scales/scaleDomainAggregator.test.d.ts +2 -0
  97. package/dist/src/scales/scaleDomainAggregator.test.d.ts.map +1 -0
  98. package/dist/src/scales/scaleInstanceManager.d.ts +40 -0
  99. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -0
  100. package/dist/src/scales/scaleInstanceManager.js +317 -0
  101. package/dist/src/scales/scaleInstanceManager.test.d.ts +2 -0
  102. package/dist/src/scales/scaleInstanceManager.test.d.ts.map +1 -0
  103. package/dist/src/scales/scaleInteractionController.d.ts +73 -0
  104. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -0
  105. package/dist/src/scales/scaleInteractionController.js +336 -0
  106. package/dist/src/scales/scaleInteractionController.test.d.ts +2 -0
  107. package/dist/src/scales/scaleInteractionController.test.d.ts.map +1 -0
  108. package/dist/src/scales/scalePropsResolver.d.ts +23 -0
  109. package/dist/src/scales/scalePropsResolver.d.ts.map +1 -0
  110. package/dist/src/scales/scalePropsResolver.js +74 -0
  111. package/dist/src/{view → scales}/scaleResolution.d.ts +53 -35
  112. package/dist/src/scales/scaleResolution.d.ts.map +1 -0
  113. package/dist/src/scales/scaleResolution.js +732 -0
  114. package/dist/src/scales/scaleResolution.test.d.ts.map +1 -0
  115. package/dist/src/scales/scaleResolutionConstants.d.ts +6 -0
  116. package/dist/src/scales/scaleResolutionConstants.d.ts.map +1 -0
  117. package/dist/src/scales/scaleResolutionConstants.js +5 -0
  118. package/dist/src/scales/scaleRules.d.ts +16 -0
  119. package/dist/src/scales/scaleRules.d.ts.map +1 -0
  120. package/dist/src/scales/scaleRules.js +103 -0
  121. package/dist/src/scales/scaleRules.test.d.ts +2 -0
  122. package/dist/src/scales/scaleRules.test.d.ts.map +1 -0
  123. package/dist/src/spec/channel.d.ts +13 -18
  124. package/dist/src/spec/scale.d.ts +6 -0
  125. package/dist/src/types/embedApi.d.ts +5 -0
  126. package/dist/src/types/scaleResolutionApi.d.ts +1 -1
  127. package/dist/src/utils/domainArray.d.ts.map +1 -1
  128. package/dist/src/utils/domainArray.js +3 -0
  129. package/dist/src/utils/indexer.d.ts +3 -0
  130. package/dist/src/utils/indexer.d.ts.map +1 -1
  131. package/dist/src/utils/indexer.js +3 -0
  132. package/dist/src/view/concatView.d.ts +18 -0
  133. package/dist/src/view/concatView.d.ts.map +1 -1
  134. package/dist/src/view/concatView.js +73 -0
  135. package/dist/src/view/concatView.test.d.ts +2 -0
  136. package/dist/src/view/concatView.test.d.ts.map +1 -0
  137. package/dist/src/view/containerMutationHelper.d.ts +74 -0
  138. package/dist/src/view/containerMutationHelper.d.ts.map +1 -0
  139. package/dist/src/view/containerMutationHelper.js +118 -0
  140. package/dist/src/view/containerView.d.ts +0 -7
  141. package/dist/src/view/containerView.d.ts.map +1 -1
  142. package/dist/src/view/containerView.js +0 -10
  143. package/dist/src/view/facetView.d.ts.map +1 -1
  144. package/dist/src/view/facetView.js +0 -15
  145. package/dist/src/view/flowBuilder.d.ts +5 -3
  146. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  147. package/dist/src/view/flowBuilder.js +69 -6
  148. package/dist/src/view/gridView/gridChild.d.ts +11 -0
  149. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  150. package/dist/src/view/gridView/gridChild.js +32 -6
  151. package/dist/src/view/gridView/gridView.d.ts +39 -1
  152. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  153. package/dist/src/view/gridView/gridView.js +106 -48
  154. package/dist/src/view/gridView/gridView.test.d.ts +2 -0
  155. package/dist/src/view/gridView/gridView.test.d.ts.map +1 -0
  156. package/dist/src/view/gridView/scrollbar.d.ts +39 -8
  157. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  158. package/dist/src/view/gridView/scrollbar.js +184 -69
  159. package/dist/src/view/layerView.d.ts +14 -0
  160. package/dist/src/view/layerView.d.ts.map +1 -1
  161. package/dist/src/view/layerView.js +66 -0
  162. package/dist/src/view/layerView.test.d.ts +2 -0
  163. package/dist/src/view/layerView.test.d.ts.map +1 -0
  164. package/dist/src/view/testUtils.d.ts.map +1 -1
  165. package/dist/src/view/testUtils.js +7 -1
  166. package/dist/src/view/unitView.d.ts.map +1 -1
  167. package/dist/src/view/unitView.js +41 -36
  168. package/dist/src/view/view.d.ts +18 -6
  169. package/dist/src/view/view.d.ts.map +1 -1
  170. package/dist/src/view/view.js +30 -4
  171. package/package.json +2 -2
  172. package/dist/bundle/browser-txUcLy2H.js +0 -123
  173. package/dist/bundle/index-BQpbYrv4.js +0 -1712
  174. package/dist/bundle/index-BhtHKLUo.js +0 -73
  175. package/dist/bundle/index-CCe8rnZz.js +0 -716
  176. package/dist/bundle/index-DhcU-Gk-.js +0 -1487
  177. package/dist/src/data/collector.test.js +0 -138
  178. package/dist/src/data/dataFlow.test.js +0 -38
  179. package/dist/src/data/flow.test.js +0 -81
  180. package/dist/src/data/flowInit.test.js +0 -413
  181. package/dist/src/data/flowNode.test.js +0 -50
  182. package/dist/src/data/flowOptimizer.test.js +0 -209
  183. package/dist/src/data/formats/fasta.test.js +0 -27
  184. package/dist/src/data/sources/inlineSource.test.js +0 -63
  185. package/dist/src/data/sources/sequenceSource.test.js +0 -81
  186. package/dist/src/data/transforms/aggregate.test.js +0 -134
  187. package/dist/src/data/transforms/clone.test.js +0 -11
  188. package/dist/src/data/transforms/coverage.test.js +0 -238
  189. package/dist/src/data/transforms/filter.test.js +0 -20
  190. package/dist/src/data/transforms/flatten.test.js +0 -96
  191. package/dist/src/data/transforms/flattenDelimited.test.js +0 -90
  192. package/dist/src/data/transforms/flattenSequence.test.js +0 -34
  193. package/dist/src/data/transforms/formula.test.js +0 -25
  194. package/dist/src/data/transforms/identifier.test.js +0 -92
  195. package/dist/src/data/transforms/pileup.test.js +0 -70
  196. package/dist/src/data/transforms/project.test.js +0 -32
  197. package/dist/src/data/transforms/regexExtract.test.js +0 -70
  198. package/dist/src/data/transforms/regexFold.test.js +0 -201
  199. package/dist/src/data/transforms/sample.test.js +0 -38
  200. package/dist/src/data/transforms/stack.test.js +0 -91
  201. package/dist/src/encoder/accessor.test.js +0 -162
  202. package/dist/src/encoder/encoder.test.js +0 -105
  203. package/dist/src/genome/genome.test.js +0 -268
  204. package/dist/src/genome/genomes.test.js +0 -8
  205. package/dist/src/genome/scaleIndex.test.js +0 -78
  206. package/dist/src/genome/scaleLocus.test.js +0 -4
  207. package/dist/src/scale/scale.test.js +0 -326
  208. package/dist/src/scale/ticks.test.js +0 -46
  209. package/dist/src/selection/selection.test.js +0 -14
  210. package/dist/src/utils/addBaseUrl.test.js +0 -30
  211. package/dist/src/utils/binnedIndex.test.js +0 -201
  212. package/dist/src/utils/cloner.test.js +0 -35
  213. package/dist/src/utils/coalesce.test.js +0 -16
  214. package/dist/src/utils/concatIterables.test.js +0 -8
  215. package/dist/src/utils/domainArray.test.js +0 -130
  216. package/dist/src/utils/indexer.test.js +0 -49
  217. package/dist/src/utils/interactionEvent.test.js +0 -35
  218. package/dist/src/utils/iterateNestedMaps.test.js +0 -33
  219. package/dist/src/utils/kWayMerge.test.js +0 -30
  220. package/dist/src/utils/mergeObjects.test.js +0 -42
  221. package/dist/src/utils/numberExtractor.test.js +0 -6
  222. package/dist/src/utils/propertyCacher.test.js +0 -89
  223. package/dist/src/utils/propertyCoalescer.test.js +0 -25
  224. package/dist/src/utils/radixSort.test.js +0 -51
  225. package/dist/src/utils/reservationMap.test.js +0 -20
  226. package/dist/src/utils/ringBuffer.test.js +0 -39
  227. package/dist/src/utils/topK.test.js +0 -54
  228. package/dist/src/utils/trees.test.js +0 -135
  229. package/dist/src/utils/url.test.js +0 -28
  230. package/dist/src/utils/variableTools.test.js +0 -13
  231. package/dist/src/view/axisResolution.d.ts.map +0 -1
  232. package/dist/src/view/axisResolution.test.d.ts.map +0 -1
  233. package/dist/src/view/axisResolution.test.js +0 -206
  234. package/dist/src/view/flowBuilder.test.js +0 -125
  235. package/dist/src/view/gridView/selectionRect.test.js +0 -87
  236. package/dist/src/view/layout/flexLayout.test.js +0 -323
  237. package/dist/src/view/layout/grid.test.js +0 -71
  238. package/dist/src/view/layout/rectangle.test.js +0 -192
  239. package/dist/src/view/paramMediator.test.js +0 -282
  240. package/dist/src/view/scaleResolution.d.ts.map +0 -1
  241. package/dist/src/view/scaleResolution.js +0 -1059
  242. package/dist/src/view/scaleResolution.test.d.ts.map +0 -1
  243. package/dist/src/view/scaleResolution.test.js +0 -645
  244. package/dist/src/view/view.test.js +0 -245
  245. package/dist/src/view/viewDispose.test.js +0 -110
  246. package/dist/src/view/viewFactory.test.js +0 -25
  247. package/dist/src/view/viewUtils.test.js +0 -87
  248. /package/dist/src/{view → scales}/axisResolution.test.d.ts +0 -0
  249. /package/dist/src/{view → scales}/scaleResolution.test.d.ts +0 -0
@@ -1,138 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
-
3
- import Collector from "./collector.js";
4
- import { UNIQUE_ID_KEY } from "./transforms/identifier.js";
5
-
6
- const data = [1, 5, 2, 4, 3].map((x) => ({ x }));
7
-
8
- test("Collector collects data", () => {
9
- const collector = new Collector();
10
-
11
- for (const d of data) {
12
- collector.handle(d);
13
- }
14
- collector.complete();
15
-
16
- expect(collector.getData()).toEqual(data);
17
- });
18
-
19
- test("Collector collects and sorts data", () => {
20
- const collector = new Collector({
21
- type: "collect",
22
- sort: { field: ["x"] },
23
- });
24
-
25
- for (const d of data) {
26
- collector.handle(d);
27
- }
28
- collector.complete();
29
-
30
- expect([...collector.getData()]).toEqual(
31
- [1, 2, 3, 4, 5].map((x) => ({ x }))
32
- );
33
- });
34
-
35
- test("Collector collects, groups, and sorts data", () => {
36
- const collector = new Collector({
37
- type: "collect",
38
- sort: { field: ["x"] },
39
- groupby: ["a", "b"],
40
- });
41
-
42
- const data = [
43
- { a: 1, b: 1, x: 1 },
44
- { a: 1, b: 2, x: 2 },
45
- { a: 1, b: 2, x: 3 },
46
- { a: 2, b: 1, x: 4 },
47
- { a: 2, b: 1, x: 5 },
48
- { a: 2, b: 2, x: 6 },
49
- ];
50
-
51
- for (const d of data) {
52
- collector.handle(d);
53
- }
54
- collector.complete();
55
-
56
- const cd = [...collector.getData()];
57
-
58
- expect(cd.map((d) => ({ x: d.x }))).toEqual(
59
- [1, 2, 3, 4, 5, 6].map((x) => ({ x }))
60
- );
61
-
62
- /** @param {any[]} group*/
63
- const getGroupX = (group) =>
64
- collector.facetBatches.get(group).map((d) => d.x);
65
-
66
- expect(getGroupX([1, 1])).toEqual([1]);
67
- expect(getGroupX([1, 2])).toEqual([2, 3]);
68
- expect(getGroupX([2, 1])).toEqual([4, 5]);
69
- expect(getGroupX([2, 2])).toEqual([6]);
70
-
71
- expect(new Set(collector.facetBatches.keys())).toEqual(
72
- new Set([
73
- [1, 1],
74
- [1, 2],
75
- [2, 1],
76
- [2, 2],
77
- ])
78
- );
79
- });
80
-
81
- test("Collector throws on incomplete flow", () => {
82
- const collector = new Collector();
83
-
84
- expect(() => collector.getData()).toThrow();
85
- });
86
-
87
- describe("Indexing unique ids", () => {
88
- test("Collector builds a working index when ids are available", () => {
89
- const collector = new Collector({
90
- type: "collect",
91
- groupby: ["a"],
92
- });
93
-
94
- const data = [
95
- { a: 1, x: 1, [UNIQUE_ID_KEY]: 8 },
96
- { a: 1, x: 2, [UNIQUE_ID_KEY]: 2 },
97
- { a: 1, x: 3, [UNIQUE_ID_KEY]: 4 },
98
- { a: 1, x: 4, [UNIQUE_ID_KEY]: 6 },
99
- { a: 2, x: 5, [UNIQUE_ID_KEY]: 9 },
100
- { a: 2, x: 6, [UNIQUE_ID_KEY]: 7 },
101
- { a: 2, x: 7, [UNIQUE_ID_KEY]: 3 },
102
- { a: 2, x: 8, [UNIQUE_ID_KEY]: 1 },
103
- ];
104
-
105
- for (const d of data) {
106
- collector.handle(d);
107
- }
108
- collector.complete();
109
-
110
- expect(collector.findDatumByUniqueId(8)).toEqual(data[0]);
111
- expect(collector.findDatumByUniqueId(2)).toEqual(data[1]);
112
- expect(collector.findDatumByUniqueId(4)).toEqual(data[2]);
113
- expect(collector.findDatumByUniqueId(6)).toEqual(data[3]);
114
- expect(collector.findDatumByUniqueId(9)).toEqual(data[4]);
115
- expect(collector.findDatumByUniqueId(7)).toEqual(data[5]);
116
- expect(collector.findDatumByUniqueId(3)).toEqual(data[6]);
117
- expect(collector.findDatumByUniqueId(1)).toEqual(data[7]);
118
- });
119
-
120
- test("Collector returns undefined when ids are not available", () => {
121
- const collector = new Collector({
122
- type: "collect",
123
- groupby: ["a"],
124
- });
125
-
126
- const data = [
127
- { a: 1, x: 1 },
128
- { a: 2, x: 5 },
129
- ];
130
-
131
- for (const d of data) {
132
- collector.handle(d);
133
- }
134
- collector.complete();
135
-
136
- expect(collector.findDatumByUniqueId(0)).toBeUndefined();
137
- });
138
- });
@@ -1,38 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import DataFlow from "./dataFlow.js";
3
- import DataSource from "./sources/dataSource.js";
4
- import Collector from "./collector.js";
5
-
6
- describe("DataFlow", () => {
7
- test("removes sources and collectors and clears observers", () => {
8
- const flow = new DataFlow();
9
-
10
- const sourceA = new DataSource(/** @type {any} */ ({}));
11
- const sourceB = new DataSource(/** @type {any} */ ({}));
12
-
13
- flow.addDataSource(sourceA);
14
- flow.addDataSource(sourceB);
15
-
16
- const collector = new Collector();
17
- flow.addCollector(collector);
18
-
19
- let called = false;
20
- collector.observe(() => {
21
- called = true;
22
- });
23
-
24
- expect(flow.dataSources).toContain(sourceA);
25
- expect(flow.collectors).toContain(collector);
26
- expect(collector.observers.size).toBe(1);
27
-
28
- flow.removeDataSource(sourceA);
29
- flow.removeCollector(collector);
30
-
31
- expect(flow.dataSources).not.toContain(sourceA);
32
- expect(flow.collectors).not.toContain(collector);
33
-
34
- expect(collector.observers.size).toBe(0);
35
- expect(called).toBe(false);
36
- expect(flow.dataSources).toContain(sourceB);
37
- });
38
- });
@@ -1,81 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import FilterTransform from "./transforms/filter.js";
3
- import FormulaTransform from "./transforms/formula.js";
4
- import Collector from "./collector.js";
5
- import {
6
- SynchronousSequenceSource,
7
- makeParamMediatorProvider,
8
- } from "./flowTestUtils.js";
9
-
10
- describe("Test flow graphs", () => {
11
- test("Trivial graph: sequence to collector", () => {
12
- const source = new SynchronousSequenceSource(5);
13
- const collector = new Collector();
14
- source.addChild(collector);
15
-
16
- source.dispatch();
17
-
18
- expect(collector.getData()).toEqual(
19
- [0, 1, 2, 3, 4].map((d) => ({
20
- data: d,
21
- }))
22
- );
23
- });
24
-
25
- test("Trivial branching: sequence to two collectors", () => {
26
- const source = new SynchronousSequenceSource(5);
27
- const collector1 = new Collector();
28
- source.addChild(collector1);
29
- const collector2 = new Collector();
30
- source.addChild(collector2);
31
-
32
- source.dispatch();
33
-
34
- expect(collector1.getData()).toEqual(
35
- [0, 1, 2, 3, 4].map((d) => ({
36
- data: d,
37
- }))
38
- );
39
-
40
- expect(collector2.getData()).toEqual(
41
- [0, 1, 2, 3, 4].map((d) => ({
42
- data: d,
43
- }))
44
- );
45
- });
46
-
47
- test.skip("Implement stub for ParamMediator");
48
-
49
- test("Longer chain of nodes", () => {
50
- const source = new SynchronousSequenceSource(10);
51
- const filter = new FilterTransform(
52
- {
53
- type: "filter",
54
- expr: "datum.data < 5",
55
- },
56
- makeParamMediatorProvider()
57
- );
58
- const formula = new FormulaTransform(
59
- {
60
- type: "formula",
61
- expr: "datum.data * 2",
62
- as: "data",
63
- },
64
- makeParamMediatorProvider()
65
- );
66
- const collector = new Collector();
67
-
68
- source.addChild(filter);
69
- filter.addChild(formula);
70
- formula.addChild(collector);
71
-
72
- source.visit((node) => node.initialize());
73
- source.dispatch();
74
-
75
- expect(collector.getData()).toEqual(
76
- [0, 2, 4, 6, 8].map((d) => ({
77
- data: d,
78
- }))
79
- );
80
- });
81
- });
@@ -1,413 +0,0 @@
1
- import { describe, expect, test, vi } from "vitest";
2
-
3
- import { createTestViewContext } from "../view/testUtils.js";
4
- import { buildDataFlow } from "../view/flowBuilder.js";
5
- import { optimizeDataFlow } from "./flowOptimizer.js";
6
- import {
7
- collectNearestViewSubtreeDataSources,
8
- collectViewSubtreeDataSources,
9
- initializeViewSubtree,
10
- loadViewSubtreeData,
11
- syncFlowHandles,
12
- } from "./flowInit.js";
13
-
14
- describe("flowInit", () => {
15
- test("syncs handles to canonical data sources after merge", async () => {
16
- const context = createTestViewContext();
17
- context.getNamedDataFromProvider = () => [];
18
- context.addBroadcastListener = () => undefined;
19
- context.removeBroadcastListener = () => undefined;
20
-
21
- /** @type {import("../spec/view.js").HConcatSpec} */
22
- const spec = {
23
- hconcat: [
24
- {
25
- data: { name: "shared" },
26
- mark: "point",
27
- encoding: {
28
- x: { field: "x", type: "quantitative" },
29
- },
30
- },
31
- {
32
- data: { name: "shared" },
33
- mark: "point",
34
- encoding: {
35
- x: { field: "x", type: "quantitative" },
36
- },
37
- },
38
- ],
39
- };
40
-
41
- const root = await context.createOrImportView(spec, null, null, "root");
42
-
43
- const flow = buildDataFlow(root, context.dataFlow);
44
- const canonicalBySource = optimizeDataFlow(flow);
45
- syncFlowHandles(root, canonicalBySource);
46
-
47
- const concatRoot =
48
- /** @type {import("../view/concatView.js").default} */ (root);
49
- const left = concatRoot.children[0];
50
- const right = concatRoot.children[1];
51
-
52
- expect(left.flowHandle.dataSource).toBeDefined();
53
- expect(right.flowHandle.dataSource).toBeDefined();
54
- expect(left.flowHandle.dataSource).toBe(right.flowHandle.dataSource);
55
-
56
- const sharedSources = flow.dataSources.filter(
57
- (/** @type {import("./sources/dataSource.js").default} */ source) =>
58
- source.identifier === "shared"
59
- );
60
- expect(sharedSources).toEqual([left.flowHandle.dataSource]);
61
- });
62
-
63
- test("initializeViewSubtree wires collector updates for subtree loads", async () => {
64
- const context = createTestViewContext();
65
- context.getNamedDataFromProvider = () => [];
66
- context.addBroadcastListener = () => undefined;
67
- context.removeBroadcastListener = () => undefined;
68
-
69
- /** @type {import("../spec/view.js").UnitSpec} */
70
- const spec = {
71
- data: { values: [{ x: 1 }, { x: 2 }] },
72
- mark: "point",
73
- encoding: {
74
- x: { field: "x", type: "quantitative" },
75
- },
76
- };
77
-
78
- const root = await context.createOrImportView(spec, null, null, "root");
79
- const { dataSources } = initializeViewSubtree(root, context.dataFlow);
80
-
81
- // This guards subtree-only initialization: dynamic view rebuilds should still
82
- // trigger mark updates when their local collectors complete.
83
- const unitView = /** @type {import("../view/unitView.js").default} */ (
84
- root
85
- );
86
- const initializeSpy = vi.spyOn(unitView.mark, "initializeData");
87
-
88
- await Promise.all(
89
- Array.from(dataSources).map((dataSource) => dataSource.load())
90
- );
91
-
92
- expect(initializeSpy).toHaveBeenCalledTimes(1);
93
- initializeSpy.mockRestore();
94
- });
95
-
96
- test("disposeSubtree removes observers before rebuilding subtree", async () => {
97
- const context = createTestViewContext();
98
- context.getNamedDataFromProvider = () => [{ x: 1 }];
99
- context.addBroadcastListener = () => undefined;
100
- context.removeBroadcastListener = () => undefined;
101
-
102
- /** @type {import("../spec/view.js").UnitSpec} */
103
- const spec = {
104
- data: { name: "shared" },
105
- mark: "point",
106
- encoding: {
107
- x: { field: "x", type: "quantitative" },
108
- },
109
- };
110
-
111
- const firstRoot = await context.createOrImportView(
112
- spec,
113
- null,
114
- null,
115
- "first"
116
- );
117
- const { dataSources: firstSources } = initializeViewSubtree(
118
- firstRoot,
119
- context.dataFlow
120
- );
121
-
122
- const firstUnit = /** @type {import("../view/unitView.js").default} */ (
123
- firstRoot
124
- );
125
- const firstCollector = firstUnit.flowHandle.collector;
126
- const firstInitializeSpy = vi.spyOn(firstUnit.mark, "initializeData");
127
-
128
- await Promise.all(
129
- Array.from(firstSources).map((dataSource) => dataSource.load())
130
- );
131
-
132
- expect(firstInitializeSpy).toHaveBeenCalledTimes(1);
133
- firstInitializeSpy.mockRestore();
134
-
135
- firstRoot.disposeSubtree();
136
-
137
- // This prevents stale observers from firing after a subtree is rebuilt.
138
- expect(firstCollector.observers.size).toBe(0);
139
-
140
- const secondRoot = await context.createOrImportView(
141
- spec,
142
- null,
143
- null,
144
- "second"
145
- );
146
- const { dataSources: secondSources } = initializeViewSubtree(
147
- secondRoot,
148
- context.dataFlow
149
- );
150
-
151
- const secondUnit =
152
- /** @type {import("../view/unitView.js").default} */ (secondRoot);
153
- const secondInitializeSpy = vi.spyOn(secondUnit.mark, "initializeData");
154
-
155
- await Promise.all(
156
- Array.from(secondSources).map((dataSource) => dataSource.load())
157
- );
158
-
159
- expect(secondInitializeSpy).toHaveBeenCalledTimes(1);
160
- secondInitializeSpy.mockRestore();
161
- });
162
-
163
- test("disposeSubtree prunes named source branches", async () => {
164
- const context = createTestViewContext();
165
- context.getNamedDataFromProvider = () => [{ x: 1 }];
166
- context.addBroadcastListener = () => undefined;
167
- context.removeBroadcastListener = () => undefined;
168
-
169
- /** @type {import("../spec/view.js").UnitSpec} */
170
- const spec = {
171
- data: { name: "shared" },
172
- mark: "point",
173
- encoding: {
174
- x: { field: "x", type: "quantitative" },
175
- },
176
- };
177
-
178
- const root = await context.createOrImportView(spec, null, null, "root");
179
- initializeViewSubtree(root, context.dataFlow);
180
-
181
- const unitView = /** @type {import("../view/unitView.js").default} */ (
182
- root
183
- );
184
- const dataSource = unitView.flowHandle.dataSource;
185
-
186
- // This guards against stale flow branches when a subtree is disposed.
187
- expect(context.dataFlow.dataSources).toContain(dataSource);
188
- expect(dataSource.children.length).toBeGreaterThan(0);
189
-
190
- root.disposeSubtree();
191
-
192
- expect(dataSource.children.length).toBe(0);
193
- expect(context.dataFlow.dataSources).not.toContain(dataSource);
194
- });
195
-
196
- test("collectNearestViewSubtreeDataSources stops at nested sources", async () => {
197
- const context = createTestViewContext();
198
- context.addBroadcastListener = () => undefined;
199
- context.removeBroadcastListener = () => undefined;
200
-
201
- /** @type {import("../spec/view.js").LayerSpec} */
202
- const spec = {
203
- data: { values: [{ x: 0 }] },
204
- layer: [
205
- {
206
- data: { values: [{ x: 1 }] },
207
- mark: "point",
208
- encoding: {
209
- x: { field: "x", type: "quantitative" },
210
- },
211
- },
212
- {
213
- mark: "point",
214
- encoding: {
215
- x: { field: "x", type: "quantitative" },
216
- },
217
- },
218
- ],
219
- };
220
-
221
- const root = await context.createOrImportView(spec, null, null, "root");
222
- initializeViewSubtree(root, context.dataFlow);
223
-
224
- // Nearest-source semantics: a top-level source hides deeper sources.
225
- const sources = collectNearestViewSubtreeDataSources(root);
226
- expect(sources.size).toBe(1);
227
-
228
- const [rootSource] = Array.from(sources);
229
- const layerRoot =
230
- /** @type {import("../view/layerView.js").default} */ (root);
231
- const childWithSource = layerRoot.children[0];
232
-
233
- expect(rootSource).toBe(layerRoot.flowHandle.dataSource);
234
- expect(childWithSource.flowHandle.dataSource).not.toBe(rootSource);
235
- });
236
-
237
- test("loadViewSubtreeData only loads nearest sources", async () => {
238
- const context = createTestViewContext();
239
- context.addBroadcastListener = () => undefined;
240
- context.removeBroadcastListener = () => undefined;
241
-
242
- /** @type {import("../spec/view.js").LayerSpec} */
243
- const spec = {
244
- data: { values: [{ x: 0 }] },
245
- layer: [
246
- {
247
- data: { values: [{ x: 1 }] },
248
- mark: "point",
249
- encoding: {
250
- x: { field: "x", type: "quantitative" },
251
- },
252
- },
253
- ],
254
- };
255
-
256
- const root = await context.createOrImportView(spec, null, null, "root");
257
- initializeViewSubtree(root, context.dataFlow);
258
-
259
- const layerRoot =
260
- /** @type {import("../view/layerView.js").default} */ (root);
261
- const rootSource = layerRoot.flowHandle.dataSource;
262
- const childSource = layerRoot.children[0].flowHandle.dataSource;
263
-
264
- const rootLoadSpy = vi.spyOn(rootSource, "load");
265
- const childLoadSpy = vi.spyOn(childSource, "load");
266
-
267
- // Data-ready should ignore nested sources.
268
- await loadViewSubtreeData(root);
269
-
270
- expect(rootLoadSpy).toHaveBeenCalledTimes(1);
271
- expect(childLoadSpy).toHaveBeenCalledTimes(0);
272
-
273
- rootLoadSpy.mockRestore();
274
- childLoadSpy.mockRestore();
275
- });
276
-
277
- test("collectViewSubtreeDataSources includes nested sources", async () => {
278
- const context = createTestViewContext();
279
- context.addBroadcastListener = () => undefined;
280
- context.removeBroadcastListener = () => undefined;
281
-
282
- /** @type {import("../spec/view.js").LayerSpec} */
283
- const spec = {
284
- data: { values: [{ x: 0 }] },
285
- layer: [
286
- {
287
- data: { values: [{ x: 1 }] },
288
- mark: "point",
289
- encoding: {
290
- x: { field: "x", type: "quantitative" },
291
- },
292
- },
293
- ],
294
- };
295
-
296
- const root = await context.createOrImportView(spec, null, null, "root");
297
- initializeViewSubtree(root, context.dataFlow);
298
-
299
- // Initialization needs the full set of sources, including nested ones.
300
- const sources = collectViewSubtreeDataSources(root);
301
- expect(sources.size).toBe(2);
302
- });
303
-
304
- test("collectNearestViewSubtreeDataSources returns child sources when root has none", async () => {
305
- const context = createTestViewContext();
306
- context.addBroadcastListener = () => undefined;
307
- context.removeBroadcastListener = () => undefined;
308
-
309
- /** @type {import("../spec/view.js").HConcatSpec} */
310
- const spec = {
311
- hconcat: [
312
- {
313
- data: { values: [{ x: 1 }] },
314
- mark: "point",
315
- encoding: {
316
- x: { field: "x", type: "quantitative" },
317
- },
318
- },
319
- {
320
- data: { values: [{ x: 2 }] },
321
- mark: "point",
322
- encoding: {
323
- x: { field: "x", type: "quantitative" },
324
- },
325
- },
326
- ],
327
- };
328
-
329
- const root = await context.createOrImportView(spec, null, null, "root");
330
- initializeViewSubtree(root, context.dataFlow);
331
-
332
- // Without a root source, the nearest sources include the child sources.
333
- // Layout decorations may add additional sources.
334
- const sources = collectNearestViewSubtreeDataSources(root);
335
- const concatRoot =
336
- /** @type {import("../view/concatView.js").default} */ (root);
337
- expect(sources.has(concatRoot.children[0].flowHandle.dataSource)).toBe(
338
- true
339
- );
340
- expect(sources.has(concatRoot.children[1].flowHandle.dataSource)).toBe(
341
- true
342
- );
343
- });
344
-
345
- test("loadViewSubtreeData emits subtree data ready broadcast", async () => {
346
- const context = createTestViewContext();
347
- context.addBroadcastListener = () => undefined;
348
- context.removeBroadcastListener = () => undefined;
349
-
350
- /** @type {import("../spec/view.js").UnitSpec} */
351
- const spec = {
352
- data: { values: [{ x: 1 }] },
353
- mark: "point",
354
- encoding: {
355
- x: { field: "x", type: "quantitative" },
356
- },
357
- };
358
-
359
- const root = await context.createOrImportView(spec, null, null, "root");
360
- initializeViewSubtree(root, context.dataFlow);
361
-
362
- let calls = 0;
363
- root._addBroadcastHandler("subtreeDataReady", (message) => {
364
- calls += 1;
365
- expect(message.payload.subtreeRoot).toBe(root);
366
- });
367
-
368
- await loadViewSubtreeData(root);
369
-
370
- expect(calls).toBe(1);
371
- });
372
-
373
- test("loadViewSubtreeData deduplicates concurrent loads", async () => {
374
- const context = createTestViewContext();
375
- context.getNamedDataFromProvider = () => [{ x: 1 }];
376
- context.addBroadcastListener = () => undefined;
377
- context.removeBroadcastListener = () => undefined;
378
-
379
- /** @type {import("../spec/view.js").HConcatSpec} */
380
- const spec = {
381
- data: { name: "shared" },
382
- hconcat: [
383
- {
384
- mark: "point",
385
- encoding: {
386
- x: { field: "x", type: "quantitative" },
387
- },
388
- },
389
- {
390
- mark: "point",
391
- encoding: {
392
- x: { field: "x", type: "quantitative" },
393
- },
394
- },
395
- ],
396
- };
397
-
398
- const root = await context.createOrImportView(spec, null, null, "root");
399
- initializeViewSubtree(root, context.dataFlow);
400
-
401
- const dataSource = root.flowHandle.dataSource;
402
- const loadSpy = vi.spyOn(dataSource, "load");
403
-
404
- // Prevent duplicate fetches when concurrent subtrees share a source.
405
- await Promise.all([
406
- loadViewSubtreeData(root, new Set([dataSource])),
407
- loadViewSubtreeData(root, new Set([dataSource])),
408
- ]);
409
-
410
- expect(loadSpy).toHaveBeenCalledTimes(1);
411
- loadSpy.mockRestore();
412
- });
413
- });