@weasel-js/forge 1.10.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  import { parseRoute, formatRoute, paramsToKnobs, knobPaths, sameKnob, knobsToParams, PLAYHEAD_PARAM, reservedParams } from '../chunk-DKWHGSBZ.js';
2
2
  import { DEFAULT_TITLE } from '../chunk-5DXUNLV2.js';
3
- import { TITLE_LIBRARIES, isIndexId, indexId, indexEntries, librariesFrom, LibrariesContext, schemaFromDescription, LibraryBadge, openChannel, IndexPage } from '../chunk-V4RI7GWD.js';
3
+ import { TITLE_LIBRARIES, isIndexId, indexId, indexEntries, librariesFrom, LibrariesContext, schemaFromDescription, LibraryBadge, openChannel, IndexPage } from '../chunk-BIAEGWGJ.js';
4
4
  import { isGallery } from '../chunk-WEQSLPKT.js';
5
- import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useTrialClock, TrialHost } from '../chunk-ENXU34PI.js';
6
- export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-ENXU34PI.js';
5
+ import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useTrialClock, TrialHost } from '../chunk-E2FHBDNQ.js';
6
+ export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-E2FHBDNQ.js';
7
7
  import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, PLAYHEAD_KEY, labOptions, isGlobalsPath } from '../chunk-DFKCLZKS.js';
8
- import { loadStories, indexRenderOf, useNearViewport, IN_VIEW_MARGIN } from '../chunk-4NM3RTYK.js';
8
+ import { loadStories, indexRenderOf, useNearViewport, IN_VIEW_MARGIN } from '../chunk-AP3DRQLI.js';
9
9
  import '../chunk-L5XM5VKB.js';
10
10
  import '../chunk-ZAWXMUGZ.js';
11
11
  import '../chunk-GB6PRJET.js';
@@ -18,9 +18,10 @@ import { createRoot } from 'react-dom/client';
18
18
  import { createEmitter } from '@weasel-js/registry';
19
19
  import { f, valueAtPath, isConfigBranch } from '@weasel-js/labkit/config';
20
20
  import { InfoIcon, ToggleBar, Checkbox, Dialog, TOKEN_CATEGORIES, Icon, DisclosureMark, Button as Button$1, Callout, Slider, Transport, SearchIcon } from '@weasel-js/ui';
21
- import { TOKEN_MANIFEST, THEME_SOURCES, isByAxis } from '@weasel-js/theme';
21
+ import { themeAxes, weaselTheme, TOKEN_MANIFEST, THEME_SOURCES, resolveTheme, isColorModePreference, isByAxis } from '@weasel-js/theme';
22
22
  import { scale, httpThemeApi } from '@weasel-js/theme/engine';
23
23
  import { useLatest, historyKey, createHistory, swapOp, isPlainObject } from '@weasel-js/core';
24
+ import { useResolvedColorMode } from '@weasel-js/theme/react';
24
25
 
25
26
  function Finding({ finding }) {
26
27
  return /* @__PURE__ */ jsxs("li", { className: "fg-a11y__finding", children: [
@@ -553,15 +554,24 @@ function applyTokenEdits(definition, edits, selection) {
553
554
  }
554
555
  return { ok: true, definition: root };
555
556
  }
557
+ function useTrialSelection(axes, globals) {
558
+ const { mode } = globals;
559
+ const osMode = useResolvedColorMode(isColorModePreference(mode) ? mode : "auto");
560
+ return useMemo(() => {
561
+ const selection = selectionFor(axes, globals);
562
+ return axes.mode && osMode in axes.mode.values ? { mode: osMode, ...selection } : selection;
563
+ }, [axes, globals, osMode]);
564
+ }
556
565
 
557
566
  // src/shell/cssVars/useThemeSave.ts
558
567
  var THEME_NAME = "weasel";
559
568
  var TOKEN_PREFIX = "--wzl-";
569
+ var NO_AXES = {};
560
570
  function useThemeSave({ trialId, globals, themeApi, scales, overrides, history: history2 }) {
571
+ const definition = THEME_SOURCES[THEME_NAME];
572
+ const selection = useTrialSelection(definition?.axes ?? NO_AXES, globals);
561
573
  const tokens = useMemo(() => {
562
- const definition = THEME_SOURCES[THEME_NAME];
563
574
  if (!definition) return {};
564
- const selection = selectionFor(definition.axes ?? {}, globals);
565
575
  const generated = new Set(scales.flatMap((scale) => scale.tokens));
566
576
  return Object.fromEntries(
567
577
  Object.entries(overrides).flatMap(([name, value]) => {
@@ -570,7 +580,7 @@ function useThemeSave({ trialId, globals, themeApi, scales, overrides, history:
570
580
  return writtenOut(definition, token, selection) ? [[token, value]] : [];
571
581
  })
572
582
  );
573
- }, [globals, scales, overrides]);
583
+ }, [definition, selection, scales, overrides]);
574
584
  const [saving, setSaving] = useState(false);
575
585
  const [held, setHeld] = useState(null);
576
586
  const setNotice = (next) => setHeld(next && { ...next, trialId });
@@ -585,7 +595,6 @@ function useThemeSave({ trialId, globals, themeApi, scales, overrides, history:
585
595
  setNotice({ tone: "error", text: `${file} has changed since this page loaded. Reload to edit against it.` });
586
596
  return;
587
597
  }
588
- const selection = selectionFor(stored.definition.axes ?? {}, globals);
589
598
  const scaled = applyScaleEdits(stored.definition, Object.fromEntries(scales.map((s) => [s.name, s.edit])), selection);
590
599
  const next = scaled.ok ? applyTokenEdits(scaled.definition, tokens, selection) : scaled;
591
600
  if (!next.ok) {
@@ -627,6 +636,21 @@ function useThemeSave({ trialId, globals, themeApi, scales, overrides, history:
627
636
  save
628
637
  };
629
638
  }
639
+ var AXES = themeAxes(weaselTheme);
640
+ function useThemeTokens(globals, vars) {
641
+ const selection = useTrialSelection(AXES, globals);
642
+ const themed = useMemo(() => resolveTheme(weaselTheme, selection), [selection]);
643
+ return useMemo(() => {
644
+ const reported = new Map(vars.map((v) => [v.name, v.value]));
645
+ return TOKEN_MANIFEST.map((token) => ({
646
+ name: token.name,
647
+ type: token.type,
648
+ group: token.group,
649
+ value: reported.get(token.name) ?? themed[token.name] ?? token.defaultValue,
650
+ description: token.description
651
+ }));
652
+ }, [vars, themed]);
653
+ }
630
654
  var SWAP = "fg.vars.swap";
631
655
  var COALESCE_MS = 800;
632
656
  var LIMIT = 100;
@@ -743,22 +767,14 @@ function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
743
767
  const [edited, setEdited] = usePersistedState("fg-css-vars-scales", {}, { scope: "trial" });
744
768
  const [tab, setTab] = useState("theme");
745
769
  const [filter, setFilter] = useState("");
770
+ const themeTokens = useThemeTokens(globals, frame.vars);
746
771
  const tokens = useMemo(() => {
747
- if (tab === "story") {
748
- return frame.vars.map(({ name, value }) => {
749
- const known = MANIFEST.get(name);
750
- return { name, type: known?.type ?? inferTokenType(value), group: known?.group ?? groupOf(name), value };
751
- });
752
- }
753
- const reported = new Map(frame.vars.map((v) => [v.name, v.value]));
754
- return TOKEN_MANIFEST.map((token) => ({
755
- name: token.name,
756
- type: token.type,
757
- group: token.group,
758
- value: reported.get(token.name) ?? token.defaultValue,
759
- description: token.description
760
- }));
761
- }, [tab, frame.vars]);
772
+ if (tab === "theme") return themeTokens;
773
+ return frame.vars.map(({ name, value }) => {
774
+ const known = MANIFEST.get(name);
775
+ return { name, type: known?.type ?? inferTokenType(value), group: known?.group ?? groupOf(name), value };
776
+ });
777
+ }, [tab, frame.vars, themeTokens]);
762
778
  const query = filter.trim().toLowerCase();
763
779
  const shown = tokens.map((token) => {
764
780
  const override = overrides[token.name];
@@ -1036,10 +1052,10 @@ var whenIdle = (fn) => {
1036
1052
  return () => clearTimeout(handle);
1037
1053
  };
1038
1054
  function createFramePool(frameUrl, size = 2) {
1039
- const shelf = document.createElement("div");
1040
- shelf.className = "fg-frame-pool";
1041
- shelf.setAttribute("aria-hidden", "true");
1042
- document.body.append(shelf);
1055
+ const shelf2 = document.createElement("div");
1056
+ shelf2.className = "fg-frame-pool";
1057
+ shelf2.setAttribute("aria-hidden", "true");
1058
+ document.body.append(shelf2);
1043
1059
  const warm = [];
1044
1060
  const waits = /* @__PURE__ */ new Set();
1045
1061
  let cancelRefill = null;
@@ -1066,7 +1082,7 @@ function createFramePool(frameUrl, size = 2) {
1066
1082
  }, HELLO_TIMEOUT_MS);
1067
1083
  waits.add(stop);
1068
1084
  window.addEventListener("message", onMessage);
1069
- shelf.append(frame);
1085
+ shelf2.append(frame);
1070
1086
  };
1071
1087
  const refill = () => {
1072
1088
  if (disposed || cancelRefill) return;
@@ -1087,7 +1103,7 @@ function createFramePool(frameUrl, size = 2) {
1087
1103
  disposed = true;
1088
1104
  cancelRefill?.();
1089
1105
  for (const stop of [...waits]) stop();
1090
- shelf.remove();
1106
+ shelf2.remove();
1091
1107
  }
1092
1108
  };
1093
1109
  }
@@ -1097,7 +1113,7 @@ var FramePoolContext = createContext(null);
1097
1113
  function routedTrial(trials, focusedTrialId, route) {
1098
1114
  return trials.find((t) => t.id === focusedTrialId && t.instrumentName === route) ?? trials.find((t) => t.instrumentName === route);
1099
1115
  }
1100
- function PlayheadSync({ trialId, route, applied }) {
1116
+ function PlayheadSync({ trialId, route, appliedRef }) {
1101
1117
  const clock = useTrialClock(trialId);
1102
1118
  useEffect(() => {
1103
1119
  if (!clock) return;
@@ -1115,8 +1131,8 @@ function PlayheadSync({ trialId, route, applied }) {
1115
1131
  held = next;
1116
1132
  writePlayheadParam(next);
1117
1133
  };
1118
- if (applied.current !== route) {
1119
- applied.current = route;
1134
+ if (appliedRef.current !== route) {
1135
+ appliedRef.current = route;
1120
1136
  fromUrl();
1121
1137
  }
1122
1138
  toUrl();
@@ -1132,7 +1148,7 @@ function PlayheadSync({ trialId, route, applied }) {
1132
1148
  off();
1133
1149
  window.removeEventListener("hashchange", onHashChange);
1134
1150
  };
1135
- }, [clock, route, applied]);
1151
+ }, [clock, route, appliedRef]);
1136
1152
  return null;
1137
1153
  }
1138
1154
  function RoutePlayhead() {
@@ -1141,7 +1157,7 @@ function RoutePlayhead() {
1141
1157
  const applied = useRef(null);
1142
1158
  const trial = route === null ? void 0 : routedTrial(lab.trials, lab.focusedTrialId, route);
1143
1159
  if (!trial || route === null) return null;
1144
- return /* @__PURE__ */ jsx(PlayheadSync, { trialId: trial.id, route, applied }, `${trial.id} ${route}`);
1160
+ return /* @__PURE__ */ jsx(PlayheadSync, { trialId: trial.id, route, appliedRef: applied }, `${trial.id} ${route}`);
1145
1161
  }
1146
1162
  var RECORD = "fg-globals";
1147
1163
  function useLabGlobals(declarations) {
@@ -1481,13 +1497,13 @@ function StoryTree({ ctx, index }) {
1481
1497
  }, [index]);
1482
1498
  const enabled = (value) => views.some((item) => item.value === value && !item.disabled);
1483
1499
  const view = [chosen, "components", "gallery"].find(enabled) ?? chosen;
1484
- const kept = useMemo(() => index.filter((entry) => !hidden[table.of(entry)]), [index, hidden, table]);
1500
+ const kept2 = useMemo(() => index.filter((entry) => !hidden[table.of(entry)]), [index, hidden, table]);
1485
1501
  const [galleryEntries, rest] = useMemo(() => {
1486
1502
  const yes = [];
1487
1503
  const no = [];
1488
- for (const entry of kept) (isGallery(entry) ? yes : no).push(entry);
1504
+ for (const entry of kept2) (isGallery(entry) ? yes : no).push(entry);
1489
1505
  return [yes, no];
1490
- }, [kept]);
1506
+ }, [kept2]);
1491
1507
  const tree = useMemo(() => buildTree(rest), [rest]);
1492
1508
  const components = useMemo(() => buildComponents(rest, table), [rest, table]);
1493
1509
  const galleries = useMemo(() => buildComponents(galleryEntries, table), [galleryEntries, table]);
@@ -1495,7 +1511,7 @@ function StoryTree({ ctx, index }) {
1495
1511
  () => view === "tree" ? filterTree(tree, query) : componentNodes(filterComponents(view === "gallery" ? galleries : components, query)),
1496
1512
  [view, components, galleries, tree, query]
1497
1513
  );
1498
- const routable = useMemo(() => [...kept, ...indexEntries(kept)], [kept]);
1514
+ const routable = useMemo(() => [...kept2, ...indexEntries(kept2)], [kept2]);
1499
1515
  const routed = routable.find((entry) => entry.id === route);
1500
1516
  const routeAncestors = useMemo(() => ancestorsOf(routed), [routed]);
1501
1517
  const filtering = query.trim() !== "";
@@ -1786,6 +1802,54 @@ function createAnswerBook() {
1786
1802
 
1787
1803
  // src/shell/readyKey.ts
1788
1804
  var readyKey = (ready) => stableStringify({ schema: ready.schema, layout: ready.layout, viewport: ready.viewport });
1805
+ var kept = /* @__PURE__ */ new Map();
1806
+ var shelf = null;
1807
+ function shelfElement() {
1808
+ if (!shelf) {
1809
+ shelf = document.createElement("div");
1810
+ shelf.className = "fg-frame-pool";
1811
+ shelf.setAttribute("aria-hidden", "true");
1812
+ }
1813
+ if (!shelf.isConnected) document.body.append(shelf);
1814
+ return shelf;
1815
+ }
1816
+ function adopt({ key, slot, frame, link, onAdopt }) {
1817
+ const waiting = key === null ? void 0 : kept.get(key);
1818
+ if (key === null || !waiting || !slot.current) return;
1819
+ kept.delete(key);
1820
+ moveFrame(slot.current, waiting.frame);
1821
+ frame.current = waiting.frame;
1822
+ link.current = waiting.link;
1823
+ onAdopt(waiting.link);
1824
+ }
1825
+ function shelve(options) {
1826
+ const { key, frame, link, onDrop } = options.current;
1827
+ const element = frame.current;
1828
+ const current = link.current;
1829
+ if (key === null || !element?.isConnected || !current || !canMoveFrames()) return false;
1830
+ if (current.awaiting === null && current.sent === null) return false;
1831
+ const entry = { frame: element, link: current };
1832
+ moveFrame(shelfElement(), element);
1833
+ kept.set(key, entry);
1834
+ queueMicrotask(() => {
1835
+ if (kept.get(key) !== entry) return;
1836
+ kept.delete(key);
1837
+ onDrop();
1838
+ element.remove();
1839
+ });
1840
+ return true;
1841
+ }
1842
+ function useKeptFrame(options) {
1843
+ const handedOn = useRef(false);
1844
+ const latest = useLatest(options);
1845
+ useLayoutEffect(() => {
1846
+ adopt(latest.current);
1847
+ return () => {
1848
+ if (shelve(latest)) handedOn.current = true;
1849
+ };
1850
+ }, [latest]);
1851
+ return useCallback(() => handedOn.current, []);
1852
+ }
1789
1853
  var START_TIMEOUT_MS = 1e4;
1790
1854
  var requests = 0;
1791
1855
  function closeLink(link) {
@@ -1800,6 +1864,27 @@ function closeLink(link) {
1800
1864
  function mismatchMessage(mismatch) {
1801
1865
  return mismatch.reason === "version" ? `Frame speaks protocol ${String(mismatch.version)}; this workshop speaks ${PROTOCOL_VERSION}` : "Frame sent a message that is not a forge envelope";
1802
1866
  }
1867
+ function sendInputs(current, sent, next) {
1868
+ const before = current.inputs;
1869
+ const { state, globals } = next;
1870
+ const config = storyConfig(next.config, sent.config);
1871
+ if (config !== sent.config) {
1872
+ sent.config = config;
1873
+ current.channel.send({ type: "config", config });
1874
+ current.inputs += 1;
1875
+ }
1876
+ if (state !== sent.state) {
1877
+ sent.state = state;
1878
+ current.channel.send({ type: "state", state });
1879
+ current.inputs += 1;
1880
+ }
1881
+ if (globals !== sent.globals && stableStringify(globals) !== stableStringify(sent.globals)) {
1882
+ sent.globals = globals;
1883
+ current.channel.send({ type: "globals", globals });
1884
+ current.inputs += 1;
1885
+ }
1886
+ return current.inputs !== before;
1887
+ }
1803
1888
  function FrameView(props) {
1804
1889
  const { entry, frameUrl, answers, descriptionKey, ctx } = props;
1805
1890
  const labGlobals2 = useContext(StoryGlobalsContext);
@@ -1906,6 +1991,7 @@ function FrameView(props) {
1906
1991
  };
1907
1992
  const current = {
1908
1993
  channel,
1994
+ deliver: (msg) => receive(current, msg),
1909
1995
  timer,
1910
1996
  awaiting: null,
1911
1997
  sent: null,
@@ -1916,23 +2002,35 @@ function FrameView(props) {
1916
2002
  queued: []
1917
2003
  };
1918
2004
  link.current = current;
1919
- channel.on((msg) => receive(current, msg));
2005
+ channel.on((msg) => current.deliver(msg));
1920
2006
  target.postMessage({ type: PORT_HANDOFF, id: latestRef.current.entry.id }, location.origin, [
1921
2007
  port2
1922
2008
  ]);
1923
2009
  };
1924
2010
  const connectRef = useLatest(connect);
2011
+ const handedOn = useKeptFrame({
2012
+ key: trialId ? `${trialId} ${src}` : null,
2013
+ slot: slotRef,
2014
+ frame: iframeRef,
2015
+ link,
2016
+ onAdopt: (adopted) => {
2017
+ adopted.deliver = (msg) => receive(adopted, msg);
2018
+ setPending(!adopted.hasRendered);
2019
+ },
2020
+ onDrop: () => closeLink(link)
2021
+ });
1925
2022
  useEffect(() => {
1926
2023
  const slot = slotRef.current;
1927
2024
  if (!inView || !slot) return;
1928
- const claimed = latestRef.current.pool?.claim() ?? null;
1929
- const frame = claimed ?? document.createElement("iframe");
2025
+ const adopted = iframeRef.current;
2026
+ const claimed = adopted ? null : latestRef.current.pool?.claim() ?? null;
2027
+ const frame = adopted ?? claimed ?? document.createElement("iframe");
1930
2028
  frame.className = "fg-frame-view";
1931
2029
  frame.title = latestRef.current.title;
1932
2030
  frame.removeAttribute("tabindex");
1933
2031
  frame.toggleAttribute("data-pending", true);
1934
2032
  iframeRef.current = frame;
1935
- const unheard = claimed ? void 0 : setTimeout(() => setFault({ phase: null, message: `Frame did not start: ${src}` }), HELLO_TIMEOUT_MS);
2033
+ const unheard = adopted || claimed ? void 0 : setTimeout(() => setFault({ phase: null, message: `Frame did not start: ${src}` }), HELLO_TIMEOUT_MS);
1936
2034
  const onMessage = (event) => {
1937
2035
  if (event.source !== frame.contentWindow || event.origin !== location.origin) return;
1938
2036
  if (event.data?.type !== FRAME_HELLO) return;
@@ -1943,20 +2041,21 @@ function FrameView(props) {
1943
2041
  if (claimed) {
1944
2042
  moveFrame(slot, claimed);
1945
2043
  connectRef.current(claimed);
1946
- } else {
2044
+ } else if (!adopted) {
1947
2045
  frame.src = src;
1948
2046
  slot.append(frame);
1949
2047
  }
1950
2048
  return () => {
1951
2049
  window.removeEventListener("message", onMessage);
1952
2050
  clearTimeout(unheard);
2051
+ if (handedOn()) return;
1953
2052
  closeLink(link);
1954
2053
  frame.remove();
1955
2054
  iframeRef.current = null;
1956
2055
  setPending(true);
1957
2056
  setFault(null);
1958
2057
  };
1959
- }, [inView, src, connectRef, latestRef]);
2058
+ }, [inView, src, connectRef, latestRef, handedOn]);
1960
2059
  useEffect(() => {
1961
2060
  iframeRef.current?.toggleAttribute("data-pending", pending && !fault);
1962
2061
  }, [pending, fault, inView, src]);
@@ -1971,29 +2070,9 @@ function FrameView(props) {
1971
2070
  if (current.awaiting === descriptionKey) init(current);
1972
2071
  return;
1973
2072
  }
1974
- const sent = current.sent;
1975
- if (!sent) return;
1976
- let input = false;
1977
- const config = storyConfig(ctx.config, sent.config);
1978
- if (config !== sent.config) {
1979
- sent.config = config;
1980
- current.channel.send({ type: "config", config });
1981
- current.inputs += 1;
1982
- input = true;
1983
- }
1984
- if (ctx.state !== sent.state) {
1985
- sent.state = ctx.state;
1986
- current.channel.send({ type: "state", state: ctx.state });
1987
- current.inputs += 1;
1988
- input = true;
1989
- }
1990
- if (globals !== sent.globals && stableStringify(globals) !== stableStringify(sent.globals)) {
1991
- sent.globals = globals;
1992
- current.channel.send({ type: "globals", globals });
1993
- current.inputs += 1;
1994
- input = true;
2073
+ if (current.sent && sendInputs(current, current.sent, { config: ctx.config, state: ctx.state, globals })) {
2074
+ setFault((shown) => shown?.phase === "render" ? null : shown);
1995
2075
  }
1996
- if (input) setFault((shown) => shown?.phase === "render" ? null : shown);
1997
2076
  }, [ctx.config, ctx.state, globals, descriptionKey, init]);
1998
2077
  return /* @__PURE__ */ jsxs("div", { ref: hostRef, className: "fg-frame-host", children: [
1999
2078
  /* @__PURE__ */ jsx("div", { ref: slotRef, className: "fg-frame-slot" }),
@@ -2172,7 +2251,7 @@ function useStoryRegistry(index, options) {
2172
2251
  const answers = previous.books.get(entry.id) ?? createAnswerBook();
2173
2252
  books.set(entry.id, answers);
2174
2253
  const held = previous.built.get(entry.id);
2175
- const kept = held && held.entryKey === entryKey && held.ready === ready && held.loaded === had && held.fault === fault && held.frameUrl === frameUrl && held.globals === globals && held.setup === setup && held.inDocument === inDocument && held.generation === generation && held.revision === revision ? held : {
2254
+ const kept2 = held && held.entryKey === entryKey && held.ready === ready && held.loaded === had && held.fault === fault && held.frameUrl === frameUrl && held.globals === globals && held.setup === setup && held.inDocument === inDocument && held.generation === generation && held.revision === revision ? held : {
2176
2255
  entryKey,
2177
2256
  ready,
2178
2257
  loaded: had,
@@ -2185,8 +2264,8 @@ function useStoryRegistry(index, options) {
2185
2264
  revision,
2186
2265
  instrument: !inDocument ? storyInstrument({ entry, ready, answers, frameUrl, onReady, globals }) : had ? documentInstrument({ entry, loaded: had, setup, globals }) : pendingInstrument({ entry, globals, load: request, generation, ...fault ? { fault } : {} })
2187
2266
  };
2188
- built.set(entry.id, kept);
2189
- return kept.instrument;
2267
+ built.set(entry.id, kept2);
2268
+ return kept2.instrument;
2190
2269
  });
2191
2270
  const unchanged = list.length === previous.list.length && list.every((i, n) => i === previous.list[n]);
2192
2271
  return { built, books, list: unchanged ? previous.list : list };