@deepseek-ai/dsh-client-modules 0.1.6-alpha.1 → 0.1.7-alpha.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.
package/lib/client.js CHANGED
@@ -172,6 +172,274 @@ window.__ModuleLoader__.load({
172
172
  };
173
173
  }
174
174
  //#endregion
175
+ //#region lib/types/client/entry-lifecycle.js
176
+ /**
177
+ * Release a runtime before clearing its entry fiber so Loader refresh can import new code.
178
+ * Registry deletion prevents Loader from treating replacement as a user disable.
179
+ * @param entry - Entry retained for code replacement.
180
+ */
181
+ async function tearDownEntryFiber(entry) {
182
+ const fiber = entry.fiber;
183
+ if (fiber === void 0) return;
184
+ const runtime = fiber.runtime;
185
+ /* v8 ignore next -- Loader entries own plugin fibers; only the root context has a null runtime. */
186
+ if (runtime !== null) entry.ctx.registry.delete(runtime.callback);
187
+ while (fiber.inertia !== void 0) await fiber.inertia;
188
+ delete entry.fiber;
189
+ }
190
+ /**
191
+ * Remove styles after their plugin's effect cleanup has settled.
192
+ * @param id - Package whose factory owns the style tags.
193
+ */
194
+ function removeOwnedStyles(id) {
195
+ if (typeof document === "undefined") return;
196
+ for (const el of document.querySelectorAll("style[data-plugin]")) if (el.getAttribute("data-plugin") === id) el.remove();
197
+ }
198
+ //#endregion
199
+ //#region lib/types/client/entries.js
200
+ /** Numeric values mirror Cordis's const enum, which bundle loaders cannot import as a runtime object. */
201
+ const ACTIVE = 2;
202
+ const FAILED = 3;
203
+ /** Revisions and requests identify desired code; URLs only select its immutable delivery resource. */
204
+ function entryTargets(manifest) {
205
+ return JSON.stringify(manifest.modules.map((row) => [
206
+ row.id,
207
+ row.rev,
208
+ row.inject,
209
+ row.external
210
+ ]));
211
+ }
212
+ /** Manages only entries created from the Host manifest; other Loader contributors retain ownership. */
213
+ var ClientEntries = class {
214
+ modules;
215
+ index;
216
+ /** Stable observable consumed by page diagnostics through the renderer's injected hook. */
217
+ state = {
218
+ getSnapshot: () => this.snapshot,
219
+ subscribe: (listener) => {
220
+ this.listeners.add(listener);
221
+ return () => {
222
+ this.listeners.delete(listener);
223
+ };
224
+ }
225
+ };
226
+ snapshot = {
227
+ syncing: false,
228
+ failures: []
229
+ };
230
+ listeners = /* @__PURE__ */ new Set();
231
+ managed = /* @__PURE__ */ new Map();
232
+ revisions = /* @__PURE__ */ new Map();
233
+ loader;
234
+ queue = Promise.resolve();
235
+ desired;
236
+ generation = 0;
237
+ stopped = false;
238
+ /**
239
+ * Construct the page controller before Cordis boot.
240
+ * @param modules - Module arrival and materialization owner.
241
+ * @param index - Private descriptor replacement and unused-module cleanup.
242
+ */
243
+ constructor(modules, index) {
244
+ this.modules = modules;
245
+ this.index = index;
246
+ this.desired = modules.manifest;
247
+ }
248
+ /**
249
+ * Create the initial roster and retain its entry identities for subsequent reconciliation.
250
+ * @param loader - Page Loader, already configured with the module system.
251
+ * @param manifest - Initial roster audited by the boot caller.
252
+ * @returns after initial entries and their activation settle; boot owns its activation audit.
253
+ */
254
+ start(loader, manifest) {
255
+ if (this.loader !== void 0) throw new Error("client-modules: entries already started");
256
+ this.loader = loader;
257
+ this.desired = manifest;
258
+ loader.ctx.effect(() => () => {
259
+ this.stopped = true;
260
+ this.generation++;
261
+ return this.queue;
262
+ }, "client-modules: entry reconciliation");
263
+ return this.enqueue(async () => {
264
+ await Promise.all(this.desired.plugins.map(async ({ id }) => {
265
+ await this.create(loader, id);
266
+ }));
267
+ await loader.await();
268
+ for (const row of this.modules.manifest.modules) this.revisions.set(row.id, row.rev);
269
+ });
270
+ }
271
+ /**
272
+ * Validate and apply the latest full Host graph. Changed targets cancel obsolete mounts; identical targets share pending loads.
273
+ * @param graph - JSON-decoded graph received from the Host.
274
+ * @returns after the queued reconciliation; per-package failures remain available in {@link state}.
275
+ */
276
+ sync(graph) {
277
+ const manifest = parseBootManifest(graph);
278
+ if (entryTargets(manifest) !== entryTargets(this.desired)) this.generation++;
279
+ this.desired = manifest;
280
+ const generation = this.generation;
281
+ return this.enqueue(() => this.reconcile(generation));
282
+ }
283
+ /**
284
+ * Retry failed entries against the latest graph, including an unchanged revision.
285
+ * @returns after retry settlement, with remaining errors in {@link state}.
286
+ */
287
+ retry() {
288
+ const generation = ++this.generation;
289
+ return this.enqueue(() => this.reconcile(generation));
290
+ }
291
+ /**
292
+ * Replace one entry's code in the same queue as graph updates; duplicate revisions are ignored.
293
+ * Entries missing after a failed import are reconciled; bootstrap replacement fails before teardown.
294
+ * @param id - Package id from a rebuilt frame.
295
+ * @param rev - Opaque revision selecting the rebuilt artifact.
296
+ * @returns after queued work; replacement errors reject, while per-package reconciliation errors remain in {@link state}.
297
+ */
298
+ reload(id, rev) {
299
+ this.desired = {
300
+ ...this.desired,
301
+ modules: this.desired.modules.map((row) => row.id === id ? {
302
+ ...row,
303
+ rev
304
+ } : row)
305
+ };
306
+ return this.enqueue(async () => {
307
+ const desired = this.desired.modules.find((row) => row.id === id);
308
+ if (this.stopped || desired === void 0) return;
309
+ const entry = this.managed.get(id);
310
+ if (entry === void 0) {
311
+ this.modules.invalidate(id, desired.rev);
312
+ removeOwnedStyles(id);
313
+ await this.reconcile(this.generation);
314
+ return;
315
+ }
316
+ if (this.revisions.get(id) === rev) return;
317
+ this.publish({
318
+ syncing: true,
319
+ failures: this.snapshot.failures.filter((failure) => failure.id !== id)
320
+ });
321
+ await this.replace(entry, id, rev, this.generation);
322
+ this.publish({
323
+ syncing: false,
324
+ failures: this.snapshot.failures
325
+ });
326
+ }, id);
327
+ }
328
+ publish(snapshot) {
329
+ this.snapshot = snapshot;
330
+ for (const listener of [...this.listeners]) try {
331
+ listener();
332
+ } catch (error) {
333
+ console.error("client-modules: synchronization subscriber failed", error);
334
+ }
335
+ }
336
+ enqueue(task, subject = "graph") {
337
+ const run = this.queue.then(task);
338
+ this.queue = run.then(() => void 0, (error) => {
339
+ this.publish({
340
+ syncing: false,
341
+ failures: [...this.snapshot.failures.filter((failure) => failure.id !== subject), {
342
+ id: subject,
343
+ message: String(error)
344
+ }]
345
+ });
346
+ });
347
+ return run;
348
+ }
349
+ current(generation) {
350
+ return !this.stopped && generation === this.generation;
351
+ }
352
+ /** Keep ownership even when Loader rejects a module's plugin exports after inserting its entry. */
353
+ async create(loader, id) {
354
+ const options = { name: id };
355
+ const entryId = loader.ensureId(options);
356
+ try {
357
+ await loader.create(options);
358
+ } finally {
359
+ this.managed.set(id, loader.resolve(entryId));
360
+ }
361
+ }
362
+ async replace(entry, id, rev, generation) {
363
+ this.index.invalidateForReplacement(id, rev);
364
+ await this.modules.prefetch(id);
365
+ if (!this.current(generation)) return;
366
+ await tearDownEntryFiber(entry);
367
+ removeOwnedStyles(id);
368
+ if (!this.current(generation)) return;
369
+ await this.modules.import(id, "", {});
370
+ if (!this.current(generation)) return;
371
+ await entry.refresh();
372
+ await entry.fiber?.await();
373
+ if (entry.fiber === void 0) throw new Error(`client-modules: ${id} import failed (see console)`);
374
+ this.revisions.set(id, rev);
375
+ }
376
+ async reconcile(generation) {
377
+ if (!this.current(generation)) return;
378
+ const loader = this.loader;
379
+ if (loader === void 0) throw new Error("client-modules: entries have not started");
380
+ const manifest = this.desired;
381
+ this.publish({
382
+ syncing: true,
383
+ failures: []
384
+ });
385
+ const failures = [];
386
+ this.index.update(manifest, this.managed.keys());
387
+ const wanted = new Set(manifest.plugins.map((row) => row.id));
388
+ for (const [id, entry] of this.managed) {
389
+ if (wanted.has(id)) continue;
390
+ const fiber = entry.fiber;
391
+ loader.remove(entry.id);
392
+ this.managed.delete(id);
393
+ this.revisions.delete(id);
394
+ while (fiber?.inertia !== void 0) await fiber.inertia;
395
+ }
396
+ for (const row of manifest.modules) {
397
+ if (!this.current(generation)) break;
398
+ try {
399
+ const entry = this.managed.get(row.id);
400
+ if (entry === void 0) {
401
+ await this.modules.prefetch(row.id);
402
+ if (!this.current(generation)) break;
403
+ await this.modules.import(row.id, "", {});
404
+ if (!this.current(generation)) break;
405
+ await this.create(loader, row.id);
406
+ this.revisions.set(row.id, row.rev);
407
+ } else if (this.revisions.get(row.id) !== row.rev) await this.replace(entry, row.id, row.rev, generation);
408
+ else if (entry.fiber === void 0) await this.replace(entry, row.id, row.rev, generation);
409
+ else if (entry.fiber.state === FAILED) entry.fiber.update(entry.options.config);
410
+ } catch (error) {
411
+ failures.push({
412
+ id: row.id,
413
+ message: String(error)
414
+ });
415
+ }
416
+ }
417
+ await loader.await();
418
+ for (const [id, entry] of this.managed) {
419
+ if (failures.some((failure) => failure.id === id)) continue;
420
+ if (entry.fiber?.state === ACTIVE) continue;
421
+ try {
422
+ if (entry.fiber === void 0) throw new Error(`client-modules: ${id} import failed (see console)`);
423
+ await entry.fiber.await();
424
+ failures.push({
425
+ id,
426
+ message: `client-modules: ${id} is waiting for activation`
427
+ });
428
+ } catch (error) {
429
+ failures.push({
430
+ id,
431
+ message: String(error)
432
+ });
433
+ }
434
+ }
435
+ this.index.prune([...loader.entries()].map((entry) => entry.options.name));
436
+ if (this.current(generation)) this.publish({
437
+ syncing: false,
438
+ failures
439
+ });
440
+ }
441
+ };
442
+ //#endregion
175
443
  //#region lib/types/client/system.js
176
444
  /**
177
445
  * ClientModuleSystem — the implementation behind the {@link ClientModuleLoader}
@@ -199,6 +467,19 @@ window.__ModuleLoader__.load({
199
467
  if (!/[?&]rev=[^&#]*/.test(url)) throw new Error(`client-modules: bundle URL ${url} has no revision`);
200
468
  return url.replace(/([?&]rev=)[^&#]*/, `$1${encodeURIComponent(rev)}`);
201
469
  }
470
+ const CLIENT_CHUNK = /^client\.[A-Za-z0-9][A-Za-z0-9._-]*\.js$/;
471
+ /** Internal module-table key for one package-local chunk. */
472
+ function chunkId(ownerId, fileName) {
473
+ return `${ownerId}/${fileName}`;
474
+ }
475
+ /** Resolve a sibling chunk against the package's one-resource URL and current revision. */
476
+ function chunkUrl(row, fileName, rev) {
477
+ const url = atRevision(row.url, rev);
478
+ const resourceStart = url.indexOf("/??");
479
+ const revisionStart = url.indexOf("&rev=", resourceStart + 3);
480
+ if ((resourceStart < 0 || revisionStart < 0 ? void 0 : url.slice(resourceStart + 3, revisionStart)) !== `${row.id}/client.js`) throw new Error(`client-modules: cannot resolve chunk ${JSON.stringify(fileName)} from bundle URL ${url}`);
481
+ return `${url.slice(0, resourceStart)}/${row.id}/${fileName}?${url.slice(revisionStart + 1)}`;
482
+ }
202
483
  /**
203
484
  * Claim and inventory the <style> tags a factory injected during
204
485
  * materialization: preset-emitted tags arrive pre-tagged with data-plugin;
@@ -221,14 +502,17 @@ window.__ModuleLoader__.load({
221
502
  var ClientModuleSystem = class {
222
503
  version = "client";
223
504
  manifest;
505
+ entries;
224
506
  loadCache = /* @__PURE__ */ new Map();
225
507
  seed;
226
508
  factories = /* @__PURE__ */ new Map();
227
509
  bootstrapIds = /* @__PURE__ */ new Set();
228
510
  /** In-flight script transport per URL; every row in one batch shares it. */
229
511
  pendingArrival = /* @__PURE__ */ new Map();
512
+ /** Owner generation captured by in-flight chunk requests and advanced on invalidation. */
513
+ generations = /* @__PURE__ */ new Map();
230
514
  /** Single-resource combo URL selected by HMR after invalidating one row. */
231
- reloadUrls = /* @__PURE__ */ new Map();
515
+ reloadTargets = /* @__PURE__ */ new Map();
232
516
  /** Materialization re-entrancy guard: factory-form CJS cannot deliver partial exports, so a cycle is fatal. */
233
517
  materializing = /* @__PURE__ */ new Set();
234
518
  graphRows = /* @__PURE__ */ new Map();
@@ -239,12 +523,21 @@ window.__ModuleLoader__.load({
239
523
  */
240
524
  constructor(options) {
241
525
  this.manifest = options.manifest;
526
+ this.entries = new ClientEntries(this, {
527
+ update: (manifest, managed) => {
528
+ this.updateManifest(manifest, managed);
529
+ },
530
+ invalidateForReplacement: (id, rev) => {
531
+ if (this.bootstrapIds.has(id)) throw new Error(`client-modules: replacing bootstrap module ${id} requires a page reload`);
532
+ this.invalidate(id, rev);
533
+ },
534
+ prune: (roots) => {
535
+ this.prune(roots);
536
+ }
537
+ });
242
538
  this.seed = new Map(Object.entries(options.staticModules));
243
539
  this.loadBundle = options.loadBundle ?? defaultLoadBundle;
244
- for (const row of options.manifest.modules) {
245
- if (this.graphRows.has(row.id)) throw new Error(`client-modules: duplicate graph entry "${row.id}"`);
246
- this.graphRows.set(row.id, row);
247
- }
540
+ for (const row of options.manifest.modules) this.graphRows.set(row.id, row);
248
541
  const bootstrapId = stripClientSuffix(options.bootstrapModule.id);
249
542
  this.bootstrapIds.add(bootstrapId);
250
543
  this.loadCache.set(bootstrapId, {
@@ -264,16 +557,24 @@ window.__ModuleLoader__.load({
264
557
  }
265
558
  /** Register one bundle factory, rejecting a script that executes twice without invalidation. */
266
559
  register(registration) {
267
- const id = stripClientSuffix(registration.id);
268
- if (this.bootstrapIds.has(id) || this.factories.has(id)) throw new Error(`client-modules: duplicate factory registration for "${registration.id}" (bundle executed twice without invalidate?)`);
269
- this.factories.set(id, registration.factory);
560
+ const ownerId = stripClientSuffix(registration.id);
561
+ if (registration.chunk !== void 0 && !CLIENT_CHUNK.test(registration.chunk)) throw new Error(`client-modules: invalid package-local chunk ${JSON.stringify(registration.chunk)}`);
562
+ const id = registration.chunk === void 0 ? ownerId : chunkId(ownerId, registration.chunk);
563
+ if (this.bootstrapIds.has(id) || this.factories.has(id)) {
564
+ const registrationName = registration.chunk === void 0 ? registration.id : id;
565
+ throw new Error(`client-modules: duplicate factory registration for "${registrationName}" (bundle executed twice without invalidate?)`);
566
+ }
567
+ this.factories.set(id, {
568
+ factory: registration.factory,
569
+ rev: this.reloadTargets.get(ownerId)?.rev ?? this.graphRows.get(ownerId)?.rev
570
+ });
270
571
  }
271
572
  /** Load one graph row so its factory is registered (idempotent per in-flight arrival). */
272
573
  arrive(row) {
273
574
  const { id } = row;
274
575
  if (this.loadCache.has(id) || this.factories.has(id)) return Promise.resolve();
275
- const reloadUrl = this.reloadUrls.get(id);
276
- const url = reloadUrl ?? row.initialUrl;
576
+ const reload = this.reloadTargets.get(id);
577
+ const url = reload?.url ?? row.initialUrl;
277
578
  let transport = this.pendingArrival.get(url);
278
579
  if (transport === void 0) {
279
580
  transport = this.loadBundle(url).finally(() => {
@@ -283,7 +584,7 @@ window.__ModuleLoader__.load({
283
584
  }
284
585
  return transport.then(() => {
285
586
  if (!this.factories.has(id)) throw new Error(`client-modules: bundle ${url} loaded without registering "${id}" via __ModuleLoader__.load`);
286
- if (reloadUrl !== void 0 && this.reloadUrls.get(id) === reloadUrl) this.reloadUrls.delete(id);
587
+ if (reload !== void 0 && this.reloadTargets.get(id) === reload) this.reloadTargets.delete(id);
287
588
  });
288
589
  }
289
590
  /** Register each injected package and unresolved dynamic request before its consumer. */
@@ -306,7 +607,7 @@ window.__ModuleLoader__.load({
306
607
  await this.arrive(row);
307
608
  }
308
609
  /** Materialize a registered factory (synchronous; memoized in loadCache). */
309
- materialize(id) {
610
+ materialize(id, ownerId = id) {
310
611
  const existing = this.loadCache.get(id);
311
612
  if (existing !== void 0) return existing;
312
613
  const registered = this.factories.get(id);
@@ -318,24 +619,22 @@ window.__ModuleLoader__.load({
318
619
  const edges = /* @__PURE__ */ new Set();
319
620
  const record = {
320
621
  id,
321
- exports: registered(this.makeRequire(edges)),
322
- styles: claimStyles(id),
622
+ exports: registered.factory(this.makeRequire(ownerId, edges)),
623
+ styles: claimStyles(ownerId),
323
624
  edges
324
625
  };
325
626
  this.loadCache.set(id, record);
326
627
  return record;
628
+ } catch (error) {
629
+ removeOwnedStyles(ownerId);
630
+ throw error;
327
631
  } finally {
328
632
  this.materializing.delete(id);
329
633
  }
330
634
  }
331
- /**
332
- * The synchronous require answered to factories: seed → memoized record →
333
- * registered factory. Fetching is async and therefore unreachable
334
- * from here; an external dynamic package must have arrived before its
335
- * consumer materializes.
336
- */
337
- makeRequire(edges) {
338
- return (spec) => {
635
+ /** Build the synchronous module-table require and its asynchronous chunk operation. */
636
+ makeRequire(ownerId, edges) {
637
+ const require = (spec) => {
339
638
  edges.add(spec);
340
639
  if (this.seed.has(spec)) return this.seed.get(spec);
341
640
  const id = stripClientSuffix(spec);
@@ -344,6 +643,41 @@ window.__ModuleLoader__.load({
344
643
  if (this.factories.has(id)) return this.materialize(id).exports;
345
644
  throw new Error(`client-modules: require("${spec}") missed the module table — not a platform seed word, not a materialized module, and no registered package factory (a build-time externals drift, or a dynamic dependency that did not arrive)`);
346
645
  };
646
+ require.async = async (spec) => {
647
+ edges.add(spec);
648
+ if (!spec.startsWith("./")) return await this.import(spec);
649
+ const fileName = spec.slice(2);
650
+ if (!CLIENT_CHUNK.test(fileName)) throw new Error(`client-modules: invalid relative chunk request ${JSON.stringify(spec)}`);
651
+ return await this.importChunk(ownerId, fileName);
652
+ };
653
+ return require;
654
+ }
655
+ /** Load, register, and materialize one package-local dynamic chunk. */
656
+ async importChunk(ownerId, fileName) {
657
+ const id = chunkId(ownerId, fileName);
658
+ const existing = this.loadCache.get(id);
659
+ if (existing !== void 0) return existing.exports;
660
+ if (!this.factories.has(id)) {
661
+ const generation = this.generations.get(ownerId) ?? 0;
662
+ const row = this.graphRows.get(ownerId);
663
+ if (row === void 0) throw new Error(`client-modules: chunk owner "${ownerId}" is not a boot graph entry`);
664
+ const url = chunkUrl(row, fileName, this.factories.get(ownerId)?.rev ?? this.reloadTargets.get(ownerId)?.rev ?? row.rev);
665
+ let transport = this.pendingArrival.get(url);
666
+ if (transport === void 0) {
667
+ transport = this.loadBundle(url).finally(() => {
668
+ this.pendingArrival.delete(url);
669
+ });
670
+ this.pendingArrival.set(url, transport);
671
+ }
672
+ await transport;
673
+ if ((this.generations.get(ownerId) ?? 0) !== generation) {
674
+ this.factories.delete(id);
675
+ this.loadCache.delete(id);
676
+ return await this.importChunk(ownerId, fileName);
677
+ }
678
+ if (!this.factories.has(id)) throw new Error(`client-modules: bundle ${url} loaded without registering "${id}" via __ModuleLoader__.load`);
679
+ }
680
+ return this.materialize(id, ownerId).exports;
347
681
  }
348
682
  async import(specifier) {
349
683
  if (this.seed.has(specifier)) return this.seed.get(specifier);
@@ -362,14 +696,60 @@ window.__ModuleLoader__.load({
362
696
  if (row === void 0) throw new Error(`client-modules: prefetch("${id}") — not a graph entry`);
363
697
  await this.arriveGraphRow(row);
364
698
  }
699
+ /** Refresh descriptors and unowned factory revisions before any entry imports its dependencies. */
700
+ updateManifest(manifest, managed) {
701
+ for (const id of this.bootstrapIds) if (this.manifest.modules.some((row) => row.id === id) && !manifest.modules.some((row) => row.id === id)) throw new Error(`client-modules: removing bootstrap module ${id} requires a page reload`);
702
+ const owned = new Set(managed);
703
+ for (const row of manifest.modules) {
704
+ this.graphRows.set(row.id, {
705
+ ...row,
706
+ initialUrl: row.url
707
+ });
708
+ const cachedRevision = this.factories.get(row.id)?.rev ?? this.reloadTargets.get(row.id)?.rev;
709
+ if (!owned.has(row.id) && cachedRevision !== void 0 && cachedRevision !== row.rev) {
710
+ this.invalidate(row.id, row.rev);
711
+ removeOwnedStyles(row.id);
712
+ }
713
+ }
714
+ this.manifest = manifest;
715
+ }
716
+ /** Retain live Loader modules and their transitive requests before evicting unreferenced graph records. */
717
+ prune(roots) {
718
+ const retained = new Set(this.bootstrapIds);
719
+ const visit = (specifier) => {
720
+ const id = stripClientSuffix(specifier);
721
+ if (retained.has(id)) return;
722
+ retained.add(id);
723
+ const row = this.graphRows.get(id);
724
+ for (const request of [
725
+ ...row?.external ?? [],
726
+ ...row?.inject ?? [],
727
+ ...this.loadCache.get(id)?.edges ?? []
728
+ ]) visit(request);
729
+ };
730
+ for (const row of this.manifest.modules) visit(row.id);
731
+ for (const id of roots) visit(id);
732
+ for (const id of this.graphRows.keys()) {
733
+ if (retained.has(id)) continue;
734
+ this.graphRows.delete(id);
735
+ this.invalidate(id);
736
+ removeOwnedStyles(id);
737
+ }
738
+ }
365
739
  invalidate(id, rev) {
366
740
  const normalized = stripClientSuffix(id);
367
741
  if (this.bootstrapIds.has(normalized)) return;
742
+ this.generations.set(normalized, (this.generations.get(normalized) ?? 0) + 1);
368
743
  const row = this.graphRows.get(normalized);
369
- if (row !== void 0) this.reloadUrls.set(normalized, atRevision(row.url, rev ?? row.rev));
370
- else this.reloadUrls.delete(normalized);
371
- this.factories.delete(normalized);
372
- this.loadCache.delete(normalized);
744
+ if (row !== void 0) {
745
+ const revision = rev ?? row.rev;
746
+ this.reloadTargets.set(normalized, {
747
+ url: atRevision(row.url, revision),
748
+ rev: revision
749
+ });
750
+ } else this.reloadTargets.delete(normalized);
751
+ for (const key of this.factories.keys()) if (key === normalized || key.startsWith(`${normalized}/client.`)) this.factories.delete(key);
752
+ for (const key of this.loadCache.keys()) if (key === normalized || key.startsWith(`${normalized}/client.`)) this.loadCache.delete(key);
373
753
  }
374
754
  };
375
755
  //#endregion
@@ -410,6 +790,7 @@ window.__ModuleLoader__.load({
410
790
  exports.parseBootManifest = parseBootManifest;
411
791
  exports.parseDshClient = parseDshClient;
412
792
  exports.stripClientSuffix = stripClientSuffix;
793
+ exports.tearDownEntryFiber = tearDownEntryFiber;
413
794
  return module.exports;
414
795
  }
415
796
  });