@jbrowse/core 5.0.0-beta.3 → 5.0.0-beta.4

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.
@@ -1,3 +1,8 @@
1
+ export interface SettleableView {
2
+ initialized: boolean;
3
+ error: unknown;
4
+ pendingLaunch?: unknown;
5
+ }
1
6
  /**
2
7
  * Wait until a view has either initialized — launch blob consumed and all — or
3
8
  * failed, and report which.
@@ -28,13 +33,33 @@
28
33
  *
29
34
  * No time bound, deliberately: `(initialized && launch consumed) || error` is a
30
35
  * terminal set, so a slow-but-healthy remote assembly is waited out rather than
31
- * guessed at.
36
+ * guessed at. `escape` is how a caller adds the one term that is not the view's
37
+ * own — a session-level render failure for an export, `superseded` for a view
38
+ * an `installInitAutorun` apply is waiting on — which is what keeps a caller
39
+ * from re-spelling the whole predicate around it.
40
+ *
41
+ * **Not for the view whose `apply` you are inside.** `applyInitOnce` clears the
42
+ * launch blob only after awaiting `apply`, so `pendingLaunch` is held for the
43
+ * whole of it and this can end only on `escape` or `error`, never on success.
44
+ * A wait on `self` stays hand-rolled; `reference/VIEW_INIT.md` has the shape.
32
45
  *
33
46
  * @returns true if the view initialized (and consumed any launch), false if it
34
47
  * settled on an error
35
48
  */
36
- export declare function whenViewSettled(view: {
37
- initialized: boolean;
38
- error: unknown;
39
- pendingLaunch?: unknown;
40
- }): Promise<boolean>;
49
+ export declare function whenViewSettled(view: SettleableView, escape?: () => boolean): Promise<boolean>;
50
+ /**
51
+ * The same wait over several views at once — a synteny view's genome rows. An
52
+ * SVG export of a split view keeps its own per-panel loop instead: the split
53
+ * view's `initialized` folds in `views.every(v => v.initialized)` but not each
54
+ * panel's own `pendingLaunch`, so that loop is waiting on a different question
55
+ * by the time it runs.
56
+ *
57
+ * One predicate over `every`, never `Promise.all` of the single form: `when`
58
+ * returns a cancellable promise, so racing N of them against an escape leaves
59
+ * N-1 live reactions behind on the path that escapes. This is one reaction with
60
+ * nothing to cancel.
61
+ *
62
+ * @returns true if every view initialized, false if any settled on an error or
63
+ * the escape fired
64
+ */
65
+ export declare function whenViewsSettled(views: SettleableView[], escape?: () => boolean): Promise<boolean>;
@@ -1,4 +1,6 @@
1
1
  import { when } from 'mobx';
2
+ const consumed = (view) => view.initialized && view.pendingLaunch === undefined;
3
+ const done = (view) => consumed(view) || !!view.error;
2
4
  /**
3
5
  * Wait until a view has either initialized — launch blob consumed and all — or
4
6
  * failed, and report which.
@@ -29,13 +31,39 @@ import { when } from 'mobx';
29
31
  *
30
32
  * No time bound, deliberately: `(initialized && launch consumed) || error` is a
31
33
  * terminal set, so a slow-but-healthy remote assembly is waited out rather than
32
- * guessed at.
34
+ * guessed at. `escape` is how a caller adds the one term that is not the view's
35
+ * own — a session-level render failure for an export, `superseded` for a view
36
+ * an `installInitAutorun` apply is waiting on — which is what keeps a caller
37
+ * from re-spelling the whole predicate around it.
38
+ *
39
+ * **Not for the view whose `apply` you are inside.** `applyInitOnce` clears the
40
+ * launch blob only after awaiting `apply`, so `pendingLaunch` is held for the
41
+ * whole of it and this can end only on `escape` or `error`, never on success.
42
+ * A wait on `self` stays hand-rolled; `reference/VIEW_INIT.md` has the shape.
33
43
  *
34
44
  * @returns true if the view initialized (and consumed any launch), false if it
35
45
  * settled on an error
36
46
  */
37
- export async function whenViewSettled(view) {
38
- const ready = () => view.initialized && view.pendingLaunch === undefined;
39
- await when(() => ready() || !!view.error);
40
- return ready();
47
+ export async function whenViewSettled(view, escape = () => false) {
48
+ await when(() => escape() || done(view));
49
+ return consumed(view);
50
+ }
51
+ /**
52
+ * The same wait over several views at once — a synteny view's genome rows. An
53
+ * SVG export of a split view keeps its own per-panel loop instead: the split
54
+ * view's `initialized` folds in `views.every(v => v.initialized)` but not each
55
+ * panel's own `pendingLaunch`, so that loop is waiting on a different question
56
+ * by the time it runs.
57
+ *
58
+ * One predicate over `every`, never `Promise.all` of the single form: `when`
59
+ * returns a cancellable promise, so racing N of them against an escape leaves
60
+ * N-1 live reactions behind on the path that escapes. This is one reaction with
61
+ * nothing to cancel.
62
+ *
63
+ * @returns true if every view initialized, false if any settled on an error or
64
+ * the escape fired
65
+ */
66
+ export async function whenViewsSettled(views, escape = () => false) {
67
+ await when(() => escape() || views.every(done));
68
+ return views.every(consumed);
41
69
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/core",
3
- "version": "5.0.0-beta.3",
3
+ "version": "5.0.0-beta.4",
4
4
  "type": "module",
5
5
  "description": "JBrowse 2 core libraries used by plugins",
6
6
  "keywords": [
@@ -275,8 +275,8 @@
275
275
  "pako-esm2": "^2.0.2",
276
276
  "rxjs": "^7.8.2",
277
277
  "source-map-js": "^1.2.1",
278
- "@jbrowse/add-track-core": "^5.0.0-beta.3",
279
- "@jbrowse/render-core": "^5.0.0-beta.3"
278
+ "@jbrowse/add-track-core": "^5.0.0-beta.4",
279
+ "@jbrowse/render-core": "^5.0.0-beta.4"
280
280
  },
281
281
  "peerDependencies": {
282
282
  "react": ">=19.0.0",