@jbrowse/core 5.0.0-beta.7 → 5.0.0-beta.9

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 (379) hide show
  1. package/README.md +427 -130
  2. package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.d.ts +3 -2
  3. package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +5 -3
  4. package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.d.ts +3 -5
  5. package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +8 -9
  6. package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.js +8 -13
  7. package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -1
  8. package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.js +3 -3
  9. package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.d.ts +8 -0
  10. package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.js +24 -0
  11. package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.d.ts +3 -2
  12. package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.js +5 -3
  13. package/esm/BaseFeatureWidget/BaseFeatureDetail/index.d.ts +1 -0
  14. package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +1 -4
  15. package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.d.ts +16 -0
  16. package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.js +53 -0
  17. package/esm/BaseFeatureWidget/BaseFeatureDetail/util.d.ts +0 -8
  18. package/esm/BaseFeatureWidget/BaseFeatureDetail/util.js +0 -16
  19. package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceContents.js +7 -34
  20. package/esm/BaseFeatureWidget/configSchema.d.ts +1 -1
  21. package/esm/BaseFeatureWidget/formatDetails.d.ts +13 -29
  22. package/esm/BaseFeatureWidget/formatDetails.js +46 -79
  23. package/esm/BaseFeatureWidget/index.d.ts +1 -0
  24. package/esm/BaseFeatureWidget/stateModelFactory.d.ts +35 -28
  25. package/esm/BaseFeatureWidget/stateModelFactory.js +94 -102
  26. package/esm/BaseFeatureWidget/types.d.ts +3 -0
  27. package/esm/BaseFeatureWidget/util.d.ts +0 -3
  28. package/esm/BaseFeatureWidget/util.js +0 -17
  29. package/esm/PluginLoader.d.ts +14 -9
  30. package/esm/PluginLoader.js +34 -26
  31. package/esm/PluginManager.d.ts +4 -4
  32. package/esm/PluginManager.js +1 -1
  33. package/esm/ReExports/coreModules.generated.d.ts +2 -0
  34. package/esm/ReExports/coreModules.generated.js +492 -0
  35. package/esm/ReExports/coreWorkerModules.generated.d.ts +2 -0
  36. package/esm/ReExports/coreWorkerModules.generated.js +453 -0
  37. package/esm/ReExports/frameworkModules.d.ts +2 -0
  38. package/esm/ReExports/frameworkModules.js +67 -0
  39. package/esm/ReExports/frameworkShared.d.ts +12 -0
  40. package/esm/ReExports/frameworkShared.js +16 -0
  41. package/esm/ReExports/frameworkWorkerModules.generated.d.ts +2 -0
  42. package/esm/ReExports/frameworkWorkerModules.generated.js +130 -0
  43. package/esm/ReExports/list.js +493 -79
  44. package/esm/ReExports/modules.d.ts +1 -1
  45. package/esm/ReExports/modules.js +10 -87
  46. package/esm/ReExports/registry.d.ts +1 -0
  47. package/esm/ReExports/registry.js +23 -5
  48. package/esm/ReExports/uiStub.d.ts +2 -1
  49. package/esm/ReExports/uiStub.js +24 -2
  50. package/esm/ReExports/workerModules.js +8 -12
  51. package/esm/TextSearch/TextSearchManager.d.ts +3 -12
  52. package/esm/TextSearch/TextSearchManager.js +22 -10
  53. package/esm/assemblyManager/assembly.d.ts +10 -14
  54. package/esm/assemblyManager/assembly.js +10 -14
  55. package/esm/assemblyManager/assemblyConfigSchema.d.ts +23 -81
  56. package/esm/assemblyManager/assemblyManager.d.ts +10 -16
  57. package/esm/assemblyManager/assemblyManager.js +7 -10
  58. package/esm/assemblyManager/loadRefNameMap.js +3 -3
  59. package/esm/configuration/configurationSchema.d.ts +75 -31
  60. package/esm/configuration/configurationSchema.js +74 -40
  61. package/esm/configuration/configurationSchemaUnion.d.ts +39 -0
  62. package/esm/configuration/configurationSchemaUnion.js +59 -0
  63. package/esm/configuration/configurationSlot.d.ts +37 -12
  64. package/esm/configuration/configurationSlot.js +83 -22
  65. package/esm/configuration/formatAboutConfigSchema.d.ts +7 -21
  66. package/esm/configuration/formatDetailsConfigSchema.d.ts +11 -37
  67. package/esm/configuration/formatDetailsConfigSchema.js +10 -13
  68. package/esm/configuration/getConf.d.ts +17 -9
  69. package/esm/configuration/getConf.js +52 -7
  70. package/esm/configuration/index.d.ts +11 -4
  71. package/esm/configuration/index.js +7 -4
  72. package/esm/configuration/mergeFormatCallbacks.d.ts +6 -7
  73. package/esm/configuration/mergeFormatCallbacks.js +13 -10
  74. package/esm/configuration/readConfObject.d.ts +2 -22
  75. package/esm/configuration/readConfObject.js +15 -49
  76. package/esm/configuration/requirements.d.ts +37 -0
  77. package/esm/configuration/requirements.js +88 -0
  78. package/esm/configuration/schemaRegistry.d.ts +21 -1
  79. package/esm/configuration/schemaRegistry.js +11 -0
  80. package/esm/configuration/schemaTypes.d.ts +3 -0
  81. package/esm/configuration/schemaTypes.js +10 -0
  82. package/esm/configuration/slotFacade.d.ts +35 -4
  83. package/esm/configuration/slotFacade.js +96 -9
  84. package/esm/configuration/snapshotPreprocess.d.ts +27 -0
  85. package/esm/configuration/snapshotPreprocess.js +102 -0
  86. package/esm/configuration/types.d.ts +161 -22
  87. package/esm/data_adapters/BaseAdapter/BaseAdapter.d.ts +2 -2
  88. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +11 -2
  89. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +12 -1
  90. package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +2 -3
  91. package/esm/data_adapters/BaseAdapter/featureDensity.js +2 -3
  92. package/esm/data_adapters/BaseAdapter/index.d.ts +22 -3
  93. package/esm/data_adapters/BaseAdapter/types.d.ts +3 -4
  94. package/esm/data_adapters/BaseAdapter/zoomRange.d.ts +10 -0
  95. package/esm/data_adapters/BaseAdapter/zoomRange.js +1 -0
  96. package/esm/data_adapters/CytobandAdapter/configSchema.d.ts +9 -11
  97. package/esm/data_adapters/getSequenceSubAdapter.d.ts +1 -3
  98. package/esm/data_adapters/getSequenceSubAdapter.js +1 -3
  99. package/esm/pluggableElementTypes/AdapterType.d.ts +7 -7
  100. package/esm/pluggableElementTypes/RpcMethodType.d.ts +1 -1
  101. package/esm/pluggableElementTypes/RpcMethodType.js +3 -8
  102. package/esm/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions.d.ts +1 -2
  103. package/esm/pluggableElementTypes/TextSearchAdapterType.d.ts +7 -7
  104. package/esm/pluggableElementTypes/index.d.ts +1 -1
  105. package/esm/pluggableElementTypes/index.js +1 -1
  106. package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +17 -7
  107. package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +45 -48
  108. package/esm/pluggableElementTypes/models/BaseDisplayModel.js +40 -36
  109. package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +10 -13
  110. package/esm/pluggableElementTypes/models/BaseTrackModel.js +6 -6
  111. package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +37 -17
  112. package/esm/pluggableElementTypes/models/BaseViewModel.js +25 -10
  113. package/esm/pluggableElementTypes/models/InternetAccountModel.d.ts +26 -16
  114. package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +1 -1
  115. package/esm/pluggableElementTypes/models/baseConnectionConfig.d.ts +22 -18
  116. package/esm/pluggableElementTypes/models/baseConnectionConfig.js +5 -5
  117. package/esm/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +26 -31
  118. package/esm/pluggableElementTypes/models/baseTrackConfig.d.ts +57 -141
  119. package/esm/pluggableElementTypes/models/baseTrackConfig.js +22 -26
  120. package/esm/pluggableElementTypes/models/components/SaveTrackData.js +2 -2
  121. package/esm/pluggableElementTypes/models/components/fetchTrackData.d.ts +3 -4
  122. package/esm/pluggableElementTypes/models/components/fetchTrackData.js +3 -3
  123. package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.d.ts +15 -7
  124. package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.js +38 -29
  125. package/esm/pluggableElementTypes/models/index.d.ts +1 -2
  126. package/esm/pluggableElementTypes/models/index.js +1 -2
  127. package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.d.ts +3 -3
  128. package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.js +4 -4
  129. package/esm/pluggableElementTypes/models/saveTrackFileTypes/types.d.ts +3 -3
  130. package/esm/rpc/BaseRpcDriver.d.ts +1 -2
  131. package/esm/rpc/BaseRpcDriver.js +23 -30
  132. package/esm/rpc/MainThreadRpcDriver.d.ts +2 -2
  133. package/esm/rpc/MainThreadRpcDriver.js +13 -8
  134. package/esm/rpc/RpcClient.d.ts +17 -6
  135. package/esm/rpc/RpcClient.js +42 -12
  136. package/esm/rpc/RpcManager.d.ts +8 -10
  137. package/esm/rpc/RpcManager.js +1 -1
  138. package/esm/rpc/RpcRegistry.d.ts +8 -2
  139. package/esm/rpc/RpcServer.d.ts +3 -1
  140. package/esm/rpc/RpcServer.js +19 -12
  141. package/esm/rpc/WebWorkerRpcDriver.d.ts +3 -3
  142. package/esm/rpc/WebWorkerRpcDriver.js +9 -47
  143. package/esm/rpc/byteBudget.d.ts +3 -5
  144. package/esm/rpc/byteBudget.js +4 -4
  145. package/esm/rpc/configSchema.d.ts +7 -21
  146. package/esm/rpc/coreRpcMethods.d.ts +1 -0
  147. package/esm/rpc/coreRpcMethods.js +1 -0
  148. package/esm/rpc/methods/CoreEncodeFeatures.d.ts +6 -5
  149. package/esm/rpc/methods/CoreEncodeFeatures.js +26 -31
  150. package/esm/rpc/methods/CoreGetEncodedFeature.d.ts +13 -0
  151. package/esm/rpc/methods/CoreGetEncodedFeature.js +31 -0
  152. package/esm/rpc/methods/CoreGetExportData.js +2 -2
  153. package/esm/rpc/methods/CoreGetFeatureDensity.js +2 -2
  154. package/esm/rpc/methods/CoreGetFeatures.js +2 -2
  155. package/esm/rpc/methods/CoreGetSequence.js +2 -2
  156. package/esm/rpc/methods/layerFeatures.d.ts +26 -0
  157. package/esm/rpc/methods/layerFeatures.js +40 -0
  158. package/esm/svg/SvgExport.js +3 -4
  159. package/esm/svg/SvgThemeProviders.d.ts +12 -0
  160. package/esm/svg/SvgThemeProviders.js +15 -0
  161. package/esm/svg/exportViewSvg.d.ts +32 -0
  162. package/esm/svg/exportViewSvg.js +13 -0
  163. package/esm/svg/normalizeSvgMarkup.d.ts +7 -0
  164. package/esm/svg/normalizeSvgMarkup.js +99 -0
  165. package/esm/svg/serializeSvg.d.ts +7 -0
  166. package/esm/svg/serializeSvg.js +11 -0
  167. package/esm/svg/svgReady.d.ts +8 -7
  168. package/esm/svg/svgReady.js +8 -7
  169. package/esm/svg/trackNames.d.ts +5 -5
  170. package/esm/svg/trackNames.js +6 -6
  171. package/esm/svg/wrapSvgExport.js +6 -74
  172. package/esm/ui/CascadingMenu.js +83 -86
  173. package/esm/ui/ErrorMessageStackTraceDialog.js +0 -5
  174. package/esm/ui/FileSelector/useInternetAccounts.d.ts +156 -96
  175. package/esm/ui/HoverMenu.d.ts +1 -2
  176. package/esm/ui/HoverMenu.js +6 -3
  177. package/esm/ui/JexlFilterDialog.d.ts +13 -10
  178. package/esm/ui/JexlFilterDialog.js +122 -49
  179. package/esm/ui/JexlFilterRowEditors.d.ts +15 -0
  180. package/esm/ui/JexlFilterRowEditors.js +90 -0
  181. package/esm/ui/LazyBaseTooltip.d.ts +4 -0
  182. package/esm/ui/LazyBaseTooltip.js +9 -0
  183. package/esm/ui/LoadingOverlay.js +3 -1
  184. package/esm/ui/MonospaceTextField.d.ts +2 -1
  185. package/esm/ui/MonospaceTextField.js +21 -19
  186. package/esm/ui/PaletteContext.d.ts +7 -9
  187. package/esm/ui/PaletteContext.js +24 -10
  188. package/esm/ui/RefNameAutocomplete/index.d.ts +1 -2
  189. package/esm/ui/RefNameAutocomplete/index.js +1 -1
  190. package/esm/ui/ScrollChrome.d.ts +6 -9
  191. package/esm/ui/ScrollChrome.js +5 -6
  192. package/esm/ui/ScrollEdgeShadow.d.ts +6 -9
  193. package/esm/ui/ScrollEdgeShadow.js +9 -24
  194. package/esm/ui/SettingsChangesTable.js +3 -3
  195. package/esm/ui/VerticalScrollbar.d.ts +13 -34
  196. package/esm/ui/VerticalScrollbar.js +29 -83
  197. package/esm/ui/ViewLoadingScreen.d.ts +2 -2
  198. package/esm/ui/ViewLoadingScreen.js +3 -3
  199. package/esm/ui/colorScale.d.ts +26 -1
  200. package/esm/ui/colorScale.js +28 -5
  201. package/esm/ui/colors.d.ts +49 -1
  202. package/esm/ui/colors.js +139 -4
  203. package/esm/ui/hoverBoxStyle.d.ts +14 -2
  204. package/esm/ui/hoverBoxStyle.js +17 -2
  205. package/esm/ui/index.d.ts +5 -3
  206. package/esm/ui/index.js +9 -7
  207. package/esm/ui/launchViewMenu.js +3 -3
  208. package/esm/ui/legendSpec.d.ts +2 -0
  209. package/esm/ui/legendSpec.js +3 -0
  210. package/esm/ui/palette.d.ts +0 -1
  211. package/esm/ui/palette.js +3 -27
  212. package/esm/ui/replaceViewAction.d.ts +1 -1
  213. package/esm/ui/replaceViewAction.js +1 -1
  214. package/esm/ui/theme.d.ts +1 -1
  215. package/esm/ui/theme.js +6 -40
  216. package/esm/ui/viewHeaderHeight.d.ts +1 -0
  217. package/esm/ui/viewHeaderHeight.js +1 -0
  218. package/esm/util/Base1DUtils.d.ts +1 -1
  219. package/esm/util/Base1DUtils.js +2 -2
  220. package/esm/util/SvgCanvas.d.ts +15 -13
  221. package/esm/util/SvgCanvas.js +72 -53
  222. package/esm/util/aborting.d.ts +39 -0
  223. package/esm/util/aborting.js +84 -0
  224. package/esm/util/adapterMetadata.d.ts +1 -1
  225. package/esm/util/adapterMetadata.js +6 -6
  226. package/esm/util/addAndShowTrack.d.ts +1 -4
  227. package/esm/util/addRelativeUris.d.ts +10 -2
  228. package/esm/util/addRelativeUris.js +22 -7
  229. package/esm/util/addTrackFromWidget.d.ts +2 -5
  230. package/esm/util/animationAllowed.d.ts +9 -0
  231. package/esm/util/animationAllowed.js +13 -0
  232. package/esm/util/applyRowResizeWheel.d.ts +10 -5
  233. package/esm/util/applyRowResizeWheel.js +10 -21
  234. package/esm/util/bandLayout.d.ts +4 -4
  235. package/esm/util/bandLayout.js +4 -4
  236. package/esm/util/bezierConnector.js +5 -4
  237. package/esm/util/bgzfWorkerPool.d.ts +20 -74
  238. package/esm/util/bgzfWorkerPool.js +20 -74
  239. package/esm/util/cachedSetup.d.ts +1 -1
  240. package/esm/util/cachedSetup.js +2 -2
  241. package/esm/util/categoricalField.d.ts +37 -0
  242. package/esm/util/categoricalField.js +52 -0
  243. package/esm/util/color/cssColorsLevel4.d.ts +1 -0
  244. package/esm/util/color/cssColorsLevel4.js +1 -0
  245. package/esm/util/color/index.d.ts +5 -3
  246. package/esm/util/color/index.js +7 -4
  247. package/esm/util/colorBits.d.ts +1 -2
  248. package/esm/util/colorBits.js +17 -39
  249. package/esm/util/colorRamp.d.ts +27 -1
  250. package/esm/util/colorRamp.js +56 -2
  251. package/esm/util/colorSchemes.d.ts +9 -0
  252. package/esm/util/colorSchemes.js +7 -0
  253. package/esm/util/{createStopTokenRotation.d.ts → createAbortRotation.d.ts} +11 -14
  254. package/esm/util/{createStopTokenRotation.js → createAbortRotation.js} +14 -26
  255. package/esm/util/cssColorParse.d.ts +15 -0
  256. package/esm/util/cssColorParse.js +53 -0
  257. package/esm/util/diagonalizeRegions.d.ts +2 -3
  258. package/esm/util/diagonalizeRegions.js +7 -12
  259. package/esm/util/expandLooseSearchIndex.d.ts +7 -0
  260. package/esm/util/expandLooseSearchIndex.js +25 -0
  261. package/esm/util/featureTransforms.d.ts +30 -3
  262. package/esm/util/featureTransforms.js +233 -36
  263. package/esm/util/fetchAndMaybeUnzip.js +5 -6
  264. package/esm/util/fetchContext.d.ts +5 -6
  265. package/esm/util/fetchContext.js +1 -1
  266. package/esm/util/fetchHub.d.ts +3 -1
  267. package/esm/util/fetchHub.js +2 -2
  268. package/esm/util/fetchSeq.d.ts +2 -3
  269. package/esm/util/fetchSeq.js +2 -2
  270. package/esm/util/fieldReader.d.ts +17 -0
  271. package/esm/util/fieldReader.js +62 -0
  272. package/esm/util/groupKeys.d.ts +75 -0
  273. package/esm/util/groupKeys.js +152 -0
  274. package/esm/util/highlights.d.ts +6 -4
  275. package/esm/util/highlights.js +12 -25
  276. package/esm/util/hooks.d.ts +1 -2
  277. package/esm/util/hooks.js +1 -2
  278. package/esm/util/index.d.ts +3 -3
  279. package/esm/util/index.js +4 -3
  280. package/esm/util/indexCandidates.js +1 -1
  281. package/esm/util/installFetch.d.ts +13 -10
  282. package/esm/util/installFetch.js +11 -10
  283. package/esm/util/installPrerequisiteFetch.d.ts +5 -3
  284. package/esm/util/installPrerequisiteFetch.js +3 -4
  285. package/esm/util/io/index.js +12 -12
  286. package/esm/util/isDataCurrent.d.ts +7 -5
  287. package/esm/util/isDataCurrent.js +9 -6
  288. package/esm/util/jexl.js +24 -21
  289. package/esm/util/jexlFilterRows.d.ts +89 -0
  290. package/esm/util/jexlFilterRows.js +252 -0
  291. package/esm/util/jexlFilters.d.ts +7 -5
  292. package/esm/util/jexlStrings.d.ts +3 -4
  293. package/esm/util/jexlStrings.js +2 -3
  294. package/esm/util/legendCandidates.d.ts +31 -27
  295. package/esm/util/legendCandidates.js +79 -53
  296. package/esm/util/localStorage.js +4 -4
  297. package/esm/util/markEncoding.d.ts +32 -16
  298. package/esm/util/markEncoding.js +177 -150
  299. package/esm/util/markEncodingTypes.d.ts +137 -66
  300. package/esm/util/mstUtils.d.ts +19 -22
  301. package/esm/util/mstUtils.js +19 -22
  302. package/esm/util/numericUtils.d.ts +7 -0
  303. package/esm/util/numericUtils.js +16 -0
  304. package/esm/util/numericValue.d.ts +14 -0
  305. package/esm/util/numericValue.js +34 -0
  306. package/esm/util/openFeatureWidget.js +1 -2
  307. package/esm/util/openViews.d.ts +1 -0
  308. package/esm/util/openViews.js +3 -3
  309. package/esm/util/parseLineByLine.d.ts +3 -4
  310. package/esm/util/parseLineByLine.js +7 -13
  311. package/esm/util/progress.d.ts +21 -21
  312. package/esm/util/progress.js +27 -26
  313. package/esm/util/renameRegions.d.ts +1 -2
  314. package/esm/util/renderToStaticMarkup.js +16 -16
  315. package/esm/util/rxjs.d.ts +7 -8
  316. package/esm/util/rxjs.js +12 -15
  317. package/esm/util/simpleFeature.d.ts +0 -1
  318. package/esm/util/svgColorProps.d.ts +11 -0
  319. package/esm/util/svgColorProps.js +28 -1
  320. package/esm/util/tabix.d.ts +3 -4
  321. package/esm/util/tabix.js +6 -7
  322. package/esm/util/thresholdScale.d.ts +54 -0
  323. package/esm/util/thresholdScale.js +112 -0
  324. package/esm/util/timeGate.d.ts +4 -5
  325. package/esm/util/timeGate.js +4 -5
  326. package/esm/util/trackConfigDelta.d.ts +22 -18
  327. package/esm/util/trackConfigDelta.js +40 -38
  328. package/esm/util/tracks.d.ts +27 -4
  329. package/esm/util/tracks.js +116 -43
  330. package/esm/util/translateTranscript.d.ts +44 -0
  331. package/esm/util/translateTranscript.js +102 -0
  332. package/esm/util/types/index.d.ts +19 -7
  333. package/esm/util/types/services.d.ts +1 -1
  334. package/esm/util/unknownSnapshotKeys.d.ts +15 -0
  335. package/esm/util/unknownSnapshotKeys.js +13 -0
  336. package/esm/util/useFeatureSequence.js +4 -4
  337. package/esm/util/useFetch.d.ts +3 -4
  338. package/esm/util/useFetch.js +5 -6
  339. package/esm/util/usePanelVirtualScroll.d.ts +7 -39
  340. package/esm/util/usePanelVirtualScroll.js +9 -40
  341. package/esm/util/useRowVirtualScroll.d.ts +6 -29
  342. package/esm/util/useRowVirtualScroll.js +8 -49
  343. package/esm/util/useVirtualScrollWheel.d.ts +20 -4
  344. package/esm/util/useVirtualScrollWheel.js +40 -84
  345. package/esm/util/viewHighlights.d.ts +3 -0
  346. package/esm/util/viewHighlights.js +5 -0
  347. package/esm/util/viewStatus.d.ts +24 -15
  348. package/esm/util/viewStatus.js +17 -0
  349. package/esm/util/withLaunchInput.d.ts +1 -1
  350. package/esm/util/withLaunchInput.js +0 -4
  351. package/package.json +26 -12
  352. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.d.ts +0 -80
  353. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.js +0 -583
  354. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +0 -141
  355. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.js +0 -1116
  356. package/esm/ReExports/BaseFeatureDetails.d.ts +0 -1
  357. package/esm/ReExports/BaseFeatureDetails.js +0 -10
  358. package/esm/ReExports/barrelOnlyNames.d.ts +0 -5
  359. package/esm/ReExports/barrelOnlyNames.js +0 -63
  360. package/esm/ReExports/index.d.ts +0 -1
  361. package/esm/ReExports/index.js +0 -1
  362. package/esm/ReExports/publicTracks.d.ts +0 -1
  363. package/esm/ReExports/publicTracks.js +0 -14
  364. package/esm/ReExports/publicUi.d.ts +0 -4
  365. package/esm/ReExports/publicUi.js +0 -33
  366. package/esm/ReExports/publicUtil.d.ts +0 -1
  367. package/esm/ReExports/publicUtil.js +0 -32
  368. package/esm/ReExports/sharedModules.d.ts +0 -96
  369. package/esm/ReExports/sharedModules.js +0 -66
  370. package/esm/ReExports/workerNamespaceNames.d.ts +0 -11
  371. package/esm/ReExports/workerNamespaceNames.js +0 -275
  372. package/esm/pluggableElementTypes/models/HighlightsMixin.d.ts +0 -51
  373. package/esm/pluggableElementTypes/models/HighlightsMixin.js +0 -78
  374. package/esm/ui/highlightChipReveal.d.ts +0 -32
  375. package/esm/ui/highlightChipReveal.js +0 -39
  376. package/esm/util/adapterConfigKey.d.ts +0 -12
  377. package/esm/util/adapterConfigKey.js +0 -14
  378. package/esm/util/stopToken.d.ts +0 -212
  379. package/esm/util/stopToken.js +0 -438
@@ -1,3 +1,5 @@
1
+ import { isElectron, isNode } from './environment.js';
2
+ import { createTimeGate } from './timeGate.js';
1
3
  class AbortError extends Error {
2
4
  code;
3
5
  }
@@ -45,3 +47,85 @@ export function isAbortException(exception) {
45
47
  (exception instanceof AbortError && exception.code === 'ERR_ABORTED') ||
46
48
  /\b(aborted|aborterror)\b/i.test(exception.message)));
47
49
  }
50
+ /**
51
+ * Throw an AbortError if `signal` has aborted. A `signal.aborted` read, so it
52
+ * is cheap enough for the body of a loop; place it after any await and in any
53
+ * per-item callback a reader hands you.
54
+ */
55
+ export function checkAbortSignal(signal) {
56
+ if (signal?.aborted) {
57
+ throw makeAbortError();
58
+ }
59
+ }
60
+ /**
61
+ * Run an awaited stage under `signal`: checked before it starts, and again
62
+ * once it settles. The check after is the one that gets left out when the two
63
+ * are placed by hand — a stop landing during a long await otherwise goes
64
+ * unseen until the next stage.
65
+ */
66
+ export async function withAbortCheck(signal, fn) {
67
+ checkAbortSignal(signal);
68
+ const result = await fn();
69
+ checkAbortSignal(signal);
70
+ return result;
71
+ }
72
+ const YIELD_INTERVAL_MS = 50;
73
+ /**
74
+ * Give the event loop one turn. A worker learns of an abort through a posted
75
+ * message, and a message is a task: an `await` on an already-settled promise
76
+ * drains only microtasks and delivers nothing. A browser realm, Electron's
77
+ * included, gets a MessageChannel task, which unlike `setTimeout` is not
78
+ * clamped. Not `scheduler.yield`: Chromium runs its continuation ahead of a
79
+ * posted message, so a worker loop yielding that way never sees the abort.
80
+ * Plain Node and jsdom get the timer: a MessagePort turn there runs no due
81
+ * timer, and under jest the abort is one.
82
+ */
83
+ const yieldToEventLoop = (() => {
84
+ if ((isElectron || !isNode) && typeof MessageChannel !== 'undefined') {
85
+ const channel = new MessageChannel();
86
+ let resolvers = [];
87
+ channel.port1.onmessage = () => {
88
+ const pending = resolvers;
89
+ resolvers = [];
90
+ for (const resolve of pending) {
91
+ resolve();
92
+ }
93
+ };
94
+ return () => new Promise(resolve => {
95
+ resolvers.push(resolve);
96
+ channel.port2.postMessage(0);
97
+ });
98
+ }
99
+ return () => new Promise(resolve => {
100
+ setTimeout(resolve, 0);
101
+ });
102
+ })();
103
+ /**
104
+ * Cancellation for a loop that can run for seconds without awaiting — a
105
+ * whole-genome projection, a matrix fill. A `signal.aborted` read inside such a
106
+ * loop never changes, because the abort is a posted message; the loop has to
107
+ * give the event loop a turn now and then. A loop bounded by the byte gate or
108
+ * one region's features finishes before this would matter and only checks.
109
+ *
110
+ * const breakpoint = createAbortBreakpoint(signal)
111
+ * for (const row of rows) {
112
+ * if (breakpoint.due()) {
113
+ * await breakpoint.yield()
114
+ * }
115
+ * …
116
+ * }
117
+ *
118
+ * Two calls rather than one because an `await` on a non-promise still costs a
119
+ * microtask, about 60 ns against 2 ns for the `due()` read, and a loop over
120
+ * every read in a pileup notices the difference.
121
+ */
122
+ export function createAbortBreakpoint(signal) {
123
+ const gate = createTimeGate();
124
+ return {
125
+ due: () => gate(YIELD_INTERVAL_MS),
126
+ async yield() {
127
+ await yieldToEventLoop();
128
+ checkAbortSignal(signal);
129
+ },
130
+ };
131
+ }
@@ -11,7 +11,7 @@ import type { IStateTreeNode } from '@jbrowse/mobx-state-tree';
11
11
  *
12
12
  * Keyed on the adapter config rather than memoized for the display's life, so
13
13
  * a track re-pointed in the config editor stops serving the old header's
14
- * descriptions. Cleared on failure so a later click retries. No stop token and
14
+ * descriptions. Cleared on failure so a later click retries. No signal and
15
15
  * no status: nothing to narrate, and nothing a cancel could save — the widget
16
16
  * opens on the result.
17
17
  */
@@ -1,4 +1,4 @@
1
- import { adapterConfigKey } from './adapterConfigKey.js';
1
+ import { isDataCurrent } from './isDataCurrent.js';
2
2
  import { getRpcSessionId } from './parentWalk.js';
3
3
  import { getRpcHost } from './sessionServices.js';
4
4
  /**
@@ -13,19 +13,19 @@ import { getRpcHost } from './sessionServices.js';
13
13
  *
14
14
  * Keyed on the adapter config rather than memoized for the display's life, so
15
15
  * a track re-pointed in the config editor stops serving the old header's
16
- * descriptions. Cleared on failure so a later click retries. No stop token and
16
+ * descriptions. Cleared on failure so a later click retries. No signal and
17
17
  * no status: nothing to narrate, and nothing a cancel could save — the widget
18
18
  * opens on the result.
19
19
  */
20
20
  export function createAdapterMetadataFetch(self) {
21
21
  let cached;
22
22
  return () => {
23
- const key = adapterConfigKey(self.adapterConfig);
24
- if (cached?.key !== key) {
23
+ const { adapterConfig } = self;
24
+ if (!cached || !isDataCurrent(cached.adapterConfig, adapterConfig)) {
25
25
  const promise = getRpcHost(self)
26
26
  // eslint-disable-next-line no-restricted-syntax -- nothing to narrate, nothing a cancel could save
27
27
  .rpcManager.call(getRpcSessionId(self), 'CoreGetMetadata', {
28
- adapterConfig: self.adapterConfig,
28
+ adapterConfig,
29
29
  })
30
30
  .catch((e) => {
31
31
  if (cached?.promise === promise) {
@@ -33,7 +33,7 @@ export function createAdapterMetadataFetch(self) {
33
33
  }
34
34
  throw e;
35
35
  });
36
- cached = { key, promise };
36
+ cached = { adapterConfig, promise };
37
37
  }
38
38
  return cached.promise;
39
39
  };
@@ -16,7 +16,4 @@ export declare function addAndShowTrack(session: SessionWithAddSessionTrack, con
16
16
  trackId: string;
17
17
  }, view?: {
18
18
  launchTrack: (trackId: string) => Promise<unknown>;
19
- }): (import("@jbrowse/mobx-state-tree").ModelInstanceTypeProps<Record<string, any>> & {
20
- setSubschema(slotName: string, data: Record<string, unknown>): any;
21
- setSlot(slotName: string, value: unknown): void;
22
- } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("../configuration/types.ts").AnyConfigurationSchemaType>) | undefined;
19
+ }): import("../configuration/types.ts").AnyConfigurationModel | undefined;
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Stamp `baseUri` next to every `uri` in a config so relative URIs resolve
3
- * against the location the config itself was loaded from. jbrowse-web runs this
2
+ * Stamp `baseUri` next to every `uri` in a config, and beside a MultiWiggle
3
+ * `bigWigs` array of bare URI strings, so relative URIs resolve against the
4
+ * location the config itself was loaded from. jbrowse-web runs this
4
5
  * when it fetches a config.json from a URL; anything that injects a fetched
5
6
  * config as an object (a hub, a track hub connection, a headless render) has to
6
7
  * run it too, or the config's relative data URIs resolve against the page.
@@ -9,6 +10,13 @@
9
10
  * schema and expandAssemblyConfigShorthand read `baseUri` back out.
10
11
  */
11
12
  export declare function addRelativeUris(config: Record<string, unknown> | null, base: URL): void;
13
+ /**
14
+ * A copy of `config` with every relative URI stamped against the page, which
15
+ * is what the page itself would resolve it against. An RPC worker started from
16
+ * a `blob:` URL has no such base, so a location it receives without one fails
17
+ * to parse there.
18
+ */
19
+ export declare function withPageBaseUri<T>(config: T): T;
12
20
  /**
13
21
  * Inverse of {@link addRelativeUris}: recursively delete every synthetic
14
22
  * `baseUri` key (mutates in place), e.g. before serializing a config snapshot
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Stamp `baseUri` next to every `uri` in a config so relative URIs resolve
3
- * against the location the config itself was loaded from. jbrowse-web runs this
2
+ * Stamp `baseUri` next to every `uri` in a config, and beside a MultiWiggle
3
+ * `bigWigs` array of bare URI strings, so relative URIs resolve against the
4
+ * location the config itself was loaded from. jbrowse-web runs this
4
5
  * when it fetches a config.json from a URL; anything that injects a fetched
5
6
  * config as an object (a hub, a track hub connection, a headless render) has to
6
7
  * run it too, or the config's relative data URIs resolve against the page.
@@ -11,16 +12,30 @@
11
12
  export function addRelativeUris(config, base) {
12
13
  if (typeof config === 'object' && config !== null) {
13
14
  for (const key of Object.keys(config)) {
14
- if (typeof config[key] === 'object' && config[key] !== null) {
15
- addRelativeUris(config[key], base);
15
+ const value = config[key];
16
+ if (typeof value === 'object' && value !== null) {
17
+ addRelativeUris(value, base);
16
18
  }
17
- else if (key === 'uri') {
18
- // fill only when absent, so a node carrying its own baseUri wins
19
- config.baseUri = config.baseUri ?? base.href;
19
+ if (key === 'uri' || (key === 'bigWigs' && Array.isArray(value))) {
20
+ config.baseUri ??= base.href;
20
21
  }
21
22
  }
22
23
  }
23
24
  }
25
+ /**
26
+ * A copy of `config` with every relative URI stamped against the page, which
27
+ * is what the page itself would resolve it against. An RPC worker started from
28
+ * a `blob:` URL has no such base, so a location it receives without one fails
29
+ * to parse there.
30
+ */
31
+ export function withPageBaseUri(config) {
32
+ if (typeof document === 'undefined' || config === undefined) {
33
+ return config;
34
+ }
35
+ const copy = structuredClone(config);
36
+ addRelativeUris(copy, new URL(document.baseURI));
37
+ return copy;
38
+ }
24
39
  /**
25
40
  * Inverse of {@link addRelativeUris}: recursively delete every synthetic
26
41
  * `baseUri` key (mutates in place), e.g. before serializing a config snapshot
@@ -82,13 +82,10 @@ export declare function addTrackFromWidget({ model, session, conf, }: {
82
82
  name?: string;
83
83
  assemblyNames?: (string | undefined)[];
84
84
  };
85
- }): (import("@jbrowse/mobx-state-tree").$EmptyObjectBrand & Partial<{
85
+ }): import("../configuration/types.ts").AnyConfigurationModel | (import("@jbrowse/mobx-state-tree").$EmptyObjectBrand & Partial<{
86
86
  [x: string]: any;
87
87
  }> & {
88
88
  trackId: string;
89
89
  name?: string;
90
90
  assemblyNames?: (string | undefined)[];
91
- }) | (import("@jbrowse/mobx-state-tree").ModelInstanceTypeProps<Record<string, any>> & {
92
- setSubschema(slotName: string, data: Record<string, unknown>): any;
93
- setSlot(slotName: string, value: unknown): void;
94
- } & IStateTreeNode<import("../configuration/types.ts").AnyConfigurationSchemaType>) | undefined;
91
+ }) | undefined;
@@ -15,3 +15,12 @@ import type { AnimationMode } from './types/index.ts';
15
15
  * honors it.
16
16
  */
17
17
  export declare function animationAllowed(mode: AnimationMode): boolean;
18
+ /** how long a layout morph takes from where it drew to where it now draws */
19
+ export declare const MORPH_DURATION_MS = 300;
20
+ export declare function easeInOutCubic(t: number): number;
21
+ /**
22
+ * The wall clock a morph is timed on. Falls back to the epoch clock rather than
23
+ * a constant where `performance` is missing: a clock that never advances
24
+ * leaves a frame loop at progress 0 forever.
25
+ */
26
+ export declare function morphClockMs(): number;
@@ -20,3 +20,16 @@ export function animationAllowed(mode) {
20
20
  return (hasFrameClock &&
21
21
  (mode === 'enabled' || (mode === 'system' && !prefersReduced)));
22
22
  }
23
+ /** how long a layout morph takes from where it drew to where it now draws */
24
+ export const MORPH_DURATION_MS = 300;
25
+ export function easeInOutCubic(t) {
26
+ return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
27
+ }
28
+ /**
29
+ * The wall clock a morph is timed on. Falls back to the epoch clock rather than
30
+ * a constant where `performance` is missing: a clock that never advances
31
+ * leaves a frame loop at progress 0 forever.
32
+ */
33
+ export function morphClockMs() {
34
+ return typeof performance === 'undefined' ? Date.now() : performance.now();
35
+ }
@@ -1,10 +1,15 @@
1
- interface RowResizeTarget {
1
+ import type { VirtualScrollModel } from './useVirtualScrollWheel.ts';
2
+ export interface RowResizeTarget extends VirtualScrollModel {
3
+ /** resolved, never the 0/fit sentinel — this is divided by */
2
4
  effectiveRowHeight: number;
3
- scrollTop: number;
4
5
  nrow: number;
5
- viewportHeight: number;
6
6
  setRowHeight: (n: number) => void;
7
- setScrollTop: (n: number) => void;
8
7
  }
8
+ /**
9
+ * shift+wheel over a row stack: resize the rows, pinning the row under the
10
+ * cursor. The floor is the fit height, so rows never shrink past filling the
11
+ * viewport. The cap stops a gesture but never moves rows on its own, so it
12
+ * rises to a current height already above it (a pinned `rowHeight` is
13
+ * unbounded).
14
+ */
9
15
  export declare function applyRowResizeWheel(e: WheelEvent, el: HTMLElement, model: RowResizeTarget): void;
10
- export {};
@@ -1,30 +1,19 @@
1
- // shift+wheel resizes the sample rows (a vertical-zoom gesture) rather than
2
- // scrolling, keeping the row under the cursor pinned in place as the height
3
- // changes. Shared by every row-stack display — both variant displays and MAF —
4
- // so the gesture stays identical wherever rows have a resolved height and a
5
- // scroll offset. setScrollTop clamps to the new scrollableHeight, so the raw
6
- // target is passed through unclamped.
7
1
  import { normalizeWheelDelta } from './wheelZoom.js';
8
2
  const MAX_ROW_HEIGHT = 20;
9
- // px of row-height change per pixel of normalized wheel scroll. A mouse notch
10
- // (~100px) nudges the height ~0.4px; a trackpad's small continuous deltas
11
- // accumulate smoothly instead of the old sign-based ±1-per-event, which flew
12
- // through the whole range on a trackpad's event flood.
3
+ // A mouse notch (~100px) nudges the height ~0.4px, and a trackpad's small
4
+ // deltas accumulate smoothly rather than flying through the range.
13
5
  const RESIZE_PX_PER_WHEEL_PX = 1 / 240;
6
+ /**
7
+ * shift+wheel over a row stack: resize the rows, pinning the row under the
8
+ * cursor. The floor is the fit height, so rows never shrink past filling the
9
+ * viewport. The cap stops a gesture but never moves rows on its own, so it
10
+ * rises to a current height already above it (a pinned `rowHeight` is
11
+ * unbounded).
12
+ */
14
13
  export function applyRowResizeWheel(e, el, model) {
15
14
  e.preventDefault();
16
- // scroll up (deltaY < 0) grows rows; proportional to the normalized delta so
17
- // the speed is consistent across mice/trackpads and finer than ±1/event.
18
15
  const delta = -normalizeWheelDelta(e.deltaY, e.deltaMode) * RESIZE_PX_PER_WHEEL_PX;
19
- // guard nrow=0 (no samples) so the auto-fit floor stays finite
20
- const minRowHeight = model.viewportHeight / Math.max(1, model.nrow);
21
- // The cap may stop the gesture going further; it may never move the rows on
22
- // its own. So both heights that can already sit above MAX_ROW_HEIGHT raise
23
- // it: the auto-fit floor (few samples), and the current height (a pinned
24
- // `rowHeight` — the config slot and the "Custom..." dialog are both
25
- // unbounded, and MAF's own docs example is 12 while a bases-mode row wants
26
- // more). Without the second, a 40px pinned row met `min(20, 40.4)` on the
27
- // first notch of a *grow* gesture and halved.
16
+ const minRowHeight = model.scrollViewportHeight / Math.max(1, model.nrow);
28
17
  const maxRowHeight = Math.max(MAX_ROW_HEIGHT, minRowHeight, model.effectiveRowHeight);
29
18
  const newRowHeight = Math.max(minRowHeight, Math.min(maxRowHeight, model.effectiveRowHeight + delta));
30
19
  const mouseY = e.clientY - el.getBoundingClientRect().top;
@@ -39,11 +39,11 @@ export interface BandStack<K extends string> {
39
39
  /**
40
40
  * #api core/util
41
41
  * Fold an ordered set of bands into tops and a bottom. The order is the
42
- * argument, so a display states its band order exactly once; reserve, paint
43
- * and pick all read the same fold, which is what keeps "the reserver and the
44
- * painter read one function" true by construction rather than by prose.
42
+ * argument, so a display states its band order exactly once. Reserve, paint
43
+ * and pick all call this function, so the reserved and painted positions
44
+ * cannot disagree.
45
45
  *
46
- * Only the fold is shared. What varies per display stays there: per-lane
46
+ * Only the fold is shared; the rest stays in each display. Per-lane
47
47
  * iteration runs this once per lane, sticky-vs-scrolling is a property of how
48
48
  * the result is projected to the screen, and a band drawn outside its
49
49
  * reservation (an overlay) carries its own draw rect beside the stack.
@@ -14,11 +14,11 @@ export function reservedPx(band) {
14
14
  /**
15
15
  * #api core/util
16
16
  * Fold an ordered set of bands into tops and a bottom. The order is the
17
- * argument, so a display states its band order exactly once; reserve, paint
18
- * and pick all read the same fold, which is what keeps "the reserver and the
19
- * painter read one function" true by construction rather than by prose.
17
+ * argument, so a display states its band order exactly once. Reserve, paint
18
+ * and pick all call this function, so the reserved and painted positions
19
+ * cannot disagree.
20
20
  *
21
- * Only the fold is shared. What varies per display stays there: per-lane
21
+ * Only the fold is shared; the rest stays in each display. Per-lane
22
22
  * iteration runs this once per lane, sticky-vs-scrolling is a property of how
23
23
  * the result is projected to the screen, and a band drawn outside its
24
24
  * reservation (an overlay) carries its own draw rect beside the stack.
@@ -29,10 +29,11 @@ const MAX_HANDLE_PX = 200;
29
29
  const MAX_BOW_PX = 30;
30
30
  // A discordant connection bows *down* instead of up, so the two classes read
31
31
  // apart at a glance. Both renderers follow this: BreakpointSplitView dips its
32
- // same-level discordant links, and the pileup overlay dips every curve it draws
33
- // (its normal-orientation pairs are plain lines, so a curve there is always
34
- // discordant). Keep it that way — a renderer that opts out makes "below the
35
- // reads" mean two different things in two views of the same data.
32
+ // same-level discordant links, and the pileup overlay dips every discordant
33
+ // curve it draws (a normal-orientation pair is a plain line, or bows up over its
34
+ // row where a hidden-segment one would lie on a chain's connecting line). Keep
35
+ // it that way — a renderer that opts out makes "below the reads" mean two
36
+ // different things in two views of the same data.
36
37
  //
37
38
  // Depth comes from the connection's own horizontal span
38
39
  // rather than reaching for some fixed row: with "view as pairs" / "link
@@ -1,78 +1,24 @@
1
1
  import type { BgzfWorkerPool } from '@gmod/bgzf-filehandle';
2
2
  /**
3
- * The BGZF inflate pool the indexed-format libraries decompress their chunks
4
- * on, instead of decompressing them on the thread that asked.
5
- *
6
- * BGZF decompression is 70-90% of a cold query (`@gmod/bam` ADR 0003) and BGZF
7
- * blocks are independently inflatable, so spreading them across workers is the
8
- * largest remaining lever in the read path. Measured 1.95x end to end on the
9
- * BAM side: a 22-view pan / zoom out / pan back over 1000x long-read data, real
10
- * HTTP, headless Chrome, 4 workers, with both arms returning the same 38,246
11
- * records.
12
- *
13
- * ## One pool per JS context, like the cache budgets
14
- *
15
- * Same scope and same reason as `decompressedBytesBudget` — see
16
- * {@link ./cacheBudgets.ts} — so one per RPC worker plus one on the main
17
- * thread. That is the scope with spare cores: a track's queries are sticky to a
18
- * single RPC worker, so without a pool every chunk of every query inflates on
19
- * that one thread while the rest of the machine idles. `getSharedWorkerPool()`
20
- * memoizes per context, so every adapter in a worker shares its four workers
21
- * rather than each opening its own.
22
- *
23
- * ## Call it, don't hoist it
24
- *
25
- * This is a function and not an exported constant on purpose: it spawns workers
26
- * the first time it is called, and a module-level call would spawn them on
27
- * import, in every context that pulls in anything from `util`, whether or not a
28
- * bgzip-backed track is ever opened. Call it where a file is constructed.
29
- *
30
- * ## The dynamic import is about bundle weight, and only that
31
- *
32
- * `@gmod/bgzf-filehandle` inlines its worker bundle as a base64 string, and
33
- * `getSharedWorkerPool` is what reaches it, so a **static** import pins that
34
- * blob into the initial bundle of every entry point that reaches this helper.
35
- * Measured with esbuild, splitting and minifying, on the import alone:
36
- *
37
- * ```
38
- * static entry 54.7kb (23.4kb gzipped) — the blob is in the initial bundle
39
- * dynamic entry 114b (141b gzipped) + 123.9kb in a split chunk
40
- * ```
41
- *
42
- * So ~23kb gzipped off every bundle that can reach a bgzip adapter, deferred to
43
- * a chunk that is only fetched once such a track is actually opened. Core's
44
- * `util/unzip.ts` and `fetchAndMaybeUnzip.ts` dodge it the same way. It costs
45
- * nothing to do, because the libraries want a promise anyway — their callers'
46
- * `configure()` is synchronous and the pool is only available asynchronously.
47
- *
48
- * **It is not about test speed**, though it has been described that way. That
49
- * claim was checked here and did not reproduce: three jbrowse-web variant
50
- * suites ran 13.887s static against 13.856s dynamic, warm cache, and a 29s
51
- * reading that started this off turned out to be a cold jest transform cache in
52
- * a fresh worktree. Don't reintroduce a static import on the grounds that the
53
- * jest argument was wrong — the bundle argument above is the real one, and it
54
- * stands on its own.
55
- *
56
- * The `catch` is deliberate, but for a plain reason rather than a specific
57
- * failure: a pool is an optimization, `@gmod/bam` and `@gmod/tabix` both await
58
- * this, and anything going wrong here has to degrade to inflating in process
59
- * rather than break every read. A documented CJS-interop throw under jest was
60
- * the original motivation; that no longer reproduces (core's own suite, the
61
- * BamAdapter suites and jbrowse-web's Alignments suite all pass with the catch
62
- * removed), so keep it for the invariant, not the anecdote.
63
- *
64
- * ## Safe to pass unconditionally
65
- *
66
- * Returns a promise, and the libraries await it at the point of use rather than
67
- * at construction — which is what lets a synchronous `configure()` hand the
68
- * pending pool straight over. It resolves to `undefined` wherever Workers
69
- * cannot be created (node, jest), and `@gmod/bam` and `@gmod/tabix` then take
70
- * their in-process path, so no caller needs an environment check and the test
71
- * suites are unaffected.
72
- *
73
- * Needs no cross-origin isolation: each worker's range is transferred to it as
74
- * an ArrayBuffer rather than shared, so this works on an ordinary page. That
75
- * was the point of dropping SharedArrayBuffer in `@gmod/bgzf-filehandle` 6.4.0
76
- * — measured, the shared transport was at parity at best.
3
+ * The BGZF inflate pool the indexed-format libraries decompress large chunks on,
4
+ * one per JS context like `decompressedBytesBudget`: one per RPC worker plus one
5
+ * on the main thread. BGZF decompression is 70-90% of a cold query (`@gmod/bam`
6
+ * ADR 0003), and its blocks inflate independently.
7
+ *
8
+ * Holding it costs nothing. `@gmod/bgzf-filehandle` 6.7 starts the workers only
9
+ * when a chunk of at least `POOL_MIN_DECOMPRESSED_BYTES` (0.4MB inflated)
10
+ * arrives, inflates in process while they boot, and inflates in process for good
11
+ * if one of them fails, so no read waits on a worker. What it is worth per
12
+ * format, and why GFF3 and GTF go without it: reference/BGZF_WORKER_POOL.md.
13
+ *
14
+ * A function over a dynamic import because the library inlines its worker bundle
15
+ * as a base64 string, and a static import pins it into every entry point that
16
+ * can reach this helper: measured with esbuild, 23.4kb gzipped against 141b. Test
17
+ * speed is not a reason either way; three jbrowse-web variant suites ran 13.887s
18
+ * static against 13.856s dynamic.
19
+ *
20
+ * Resolves to `undefined` wherever Workers cannot be created (node, jest), which
21
+ * keeps `@gmod/bam` and `@gmod/tabix` on their in-process path, and the `catch`
22
+ * keeps anything else going wrong here on it too.
77
23
  */
78
24
  export declare function sharedBgzfWorkerPool(): Promise<BgzfWorkerPool | undefined>;
@@ -1,78 +1,24 @@
1
1
  /**
2
- * The BGZF inflate pool the indexed-format libraries decompress their chunks
3
- * on, instead of decompressing them on the thread that asked.
4
- *
5
- * BGZF decompression is 70-90% of a cold query (`@gmod/bam` ADR 0003) and BGZF
6
- * blocks are independently inflatable, so spreading them across workers is the
7
- * largest remaining lever in the read path. Measured 1.95x end to end on the
8
- * BAM side: a 22-view pan / zoom out / pan back over 1000x long-read data, real
9
- * HTTP, headless Chrome, 4 workers, with both arms returning the same 38,246
10
- * records.
11
- *
12
- * ## One pool per JS context, like the cache budgets
13
- *
14
- * Same scope and same reason as `decompressedBytesBudget` — see
15
- * {@link ./cacheBudgets.ts} — so one per RPC worker plus one on the main
16
- * thread. That is the scope with spare cores: a track's queries are sticky to a
17
- * single RPC worker, so without a pool every chunk of every query inflates on
18
- * that one thread while the rest of the machine idles. `getSharedWorkerPool()`
19
- * memoizes per context, so every adapter in a worker shares its four workers
20
- * rather than each opening its own.
21
- *
22
- * ## Call it, don't hoist it
23
- *
24
- * This is a function and not an exported constant on purpose: it spawns workers
25
- * the first time it is called, and a module-level call would spawn them on
26
- * import, in every context that pulls in anything from `util`, whether or not a
27
- * bgzip-backed track is ever opened. Call it where a file is constructed.
28
- *
29
- * ## The dynamic import is about bundle weight, and only that
30
- *
31
- * `@gmod/bgzf-filehandle` inlines its worker bundle as a base64 string, and
32
- * `getSharedWorkerPool` is what reaches it, so a **static** import pins that
33
- * blob into the initial bundle of every entry point that reaches this helper.
34
- * Measured with esbuild, splitting and minifying, on the import alone:
35
- *
36
- * ```
37
- * static entry 54.7kb (23.4kb gzipped) — the blob is in the initial bundle
38
- * dynamic entry 114b (141b gzipped) + 123.9kb in a split chunk
39
- * ```
40
- *
41
- * So ~23kb gzipped off every bundle that can reach a bgzip adapter, deferred to
42
- * a chunk that is only fetched once such a track is actually opened. Core's
43
- * `util/unzip.ts` and `fetchAndMaybeUnzip.ts` dodge it the same way. It costs
44
- * nothing to do, because the libraries want a promise anyway — their callers'
45
- * `configure()` is synchronous and the pool is only available asynchronously.
46
- *
47
- * **It is not about test speed**, though it has been described that way. That
48
- * claim was checked here and did not reproduce: three jbrowse-web variant
49
- * suites ran 13.887s static against 13.856s dynamic, warm cache, and a 29s
50
- * reading that started this off turned out to be a cold jest transform cache in
51
- * a fresh worktree. Don't reintroduce a static import on the grounds that the
52
- * jest argument was wrong — the bundle argument above is the real one, and it
53
- * stands on its own.
54
- *
55
- * The `catch` is deliberate, but for a plain reason rather than a specific
56
- * failure: a pool is an optimization, `@gmod/bam` and `@gmod/tabix` both await
57
- * this, and anything going wrong here has to degrade to inflating in process
58
- * rather than break every read. A documented CJS-interop throw under jest was
59
- * the original motivation; that no longer reproduces (core's own suite, the
60
- * BamAdapter suites and jbrowse-web's Alignments suite all pass with the catch
61
- * removed), so keep it for the invariant, not the anecdote.
62
- *
63
- * ## Safe to pass unconditionally
64
- *
65
- * Returns a promise, and the libraries await it at the point of use rather than
66
- * at construction — which is what lets a synchronous `configure()` hand the
67
- * pending pool straight over. It resolves to `undefined` wherever Workers
68
- * cannot be created (node, jest), and `@gmod/bam` and `@gmod/tabix` then take
69
- * their in-process path, so no caller needs an environment check and the test
70
- * suites are unaffected.
71
- *
72
- * Needs no cross-origin isolation: each worker's range is transferred to it as
73
- * an ArrayBuffer rather than shared, so this works on an ordinary page. That
74
- * was the point of dropping SharedArrayBuffer in `@gmod/bgzf-filehandle` 6.4.0
75
- * — measured, the shared transport was at parity at best.
2
+ * The BGZF inflate pool the indexed-format libraries decompress large chunks on,
3
+ * one per JS context like `decompressedBytesBudget`: one per RPC worker plus one
4
+ * on the main thread. BGZF decompression is 70-90% of a cold query (`@gmod/bam`
5
+ * ADR 0003), and its blocks inflate independently.
6
+ *
7
+ * Holding it costs nothing. `@gmod/bgzf-filehandle` 6.7 starts the workers only
8
+ * when a chunk of at least `POOL_MIN_DECOMPRESSED_BYTES` (0.4MB inflated)
9
+ * arrives, inflates in process while they boot, and inflates in process for good
10
+ * if one of them fails, so no read waits on a worker. What it is worth per
11
+ * format, and why GFF3 and GTF go without it: reference/BGZF_WORKER_POOL.md.
12
+ *
13
+ * A function over a dynamic import because the library inlines its worker bundle
14
+ * as a base64 string, and a static import pins it into every entry point that
15
+ * can reach this helper: measured with esbuild, 23.4kb gzipped against 141b. Test
16
+ * speed is not a reason either way; three jbrowse-web variant suites ran 13.887s
17
+ * static against 13.856s dynamic.
18
+ *
19
+ * Resolves to `undefined` wherever Workers cannot be created (node, jest), which
20
+ * keeps `@gmod/bam` and `@gmod/tabix` on their in-process path, and the `catch`
21
+ * keeps anything else going wrong here on it too.
76
22
  */
77
23
  export function sharedBgzfWorkerPool() {
78
24
  return import('@gmod/bgzf-filehandle')
@@ -17,7 +17,7 @@ type OnProgress = (current: number, total?: number) => void;
17
17
  * moment that fetch was superseded — the display's latest-wins guard gates the
18
18
  * old callback off — so the fetch replacing it awaited a multi-GB parse behind
19
19
  * a blank loading overlay.
20
- * - **`stopToken` is withheld from the shared work.** Honoring one caller's
20
+ * - **`signal` is withheld from the shared work.** Honoring one caller's
21
21
  * cancel would abort a parse the caller replacing it is already waiting on,
22
22
  * and reject them both. A superseded fetch just stops listening. Cancellation
23
23
  * stays with the per-call work (indexed range queries), which no one else is
@@ -15,7 +15,7 @@ import { downloadStatus } from './progress.js';
15
15
  * moment that fetch was superseded — the display's latest-wins guard gates the
16
16
  * old callback off — so the fetch replacing it awaited a multi-GB parse behind
17
17
  * a blank loading overlay.
18
- * - **`stopToken` is withheld from the shared work.** Honoring one caller's
18
+ * - **`signal` is withheld from the shared work.** Honoring one caller's
19
19
  * cancel would abort a parse the caller replacing it is already waiting on,
20
20
  * and reject them both. A superseded fetch just stops listening. Cancellation
21
21
  * stays with the per-call work (indexed range queries), which no one else is
@@ -39,7 +39,7 @@ export function cachedSetup({ setup, label, }) {
39
39
  const run = (opts, onProgress) => {
40
40
  cached ??= setup({
41
41
  ...opts,
42
- stopToken: undefined,
42
+ signal: undefined,
43
43
  statusCallback: status => {
44
44
  for (const cb of waiting) {
45
45
  cb(status);