@async/framework 0.11.11 → 0.11.13

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/browser.ts CHANGED
@@ -2574,12 +2574,17 @@ const __serverModule = (() => {
2574
2574
  if (!element) {
2575
2575
  return {};
2576
2576
  }
2577
-
2578
- return {
2579
- value: "value" in element ? element.value : undefined,
2580
- checked: "checked" in element ? element.checked : undefined,
2581
- dataset: element.dataset ? { ...element.dataset } : {}
2582
- };
2577
+ const input = {};
2578
+ if ("value" in element) {
2579
+ input.value = element.value;
2580
+ }
2581
+ if ("checked" in element) {
2582
+ input.checked = element.checked;
2583
+ }
2584
+ if (element.dataset) {
2585
+ input.dataset = { ...element.dataset };
2586
+ }
2587
+ return input;
2583
2588
  }
2584
2589
 
2585
2590
  function createServerNamespace(run, root = {}, contextProvider = () => ({})) {
@@ -2766,38 +2771,76 @@ const __serverModule = (() => {
2766
2771
  return output;
2767
2772
  }
2768
2773
 
2769
- function assertJsonTransportable(value, stack = new Set()) {
2770
- if (typeof value === "bigint") {
2771
- throw new Error("Server proxy JSON transport does not support BigInt values.");
2774
+ function assertJsonTransportable(value, path = "$", stack = new Set()) {
2775
+ if (value === null) {
2776
+ return;
2777
+ }
2778
+
2779
+ const type = typeof value;
2780
+ if (type === "boolean" || type === "string") {
2781
+ return;
2772
2782
  }
2773
- if (value == null || typeof value !== "object") {
2783
+ if (type === "number") {
2784
+ if (!Number.isFinite(value)) {
2785
+ throw new Error(`Server proxy JSON transport does not support non-finite numbers at ${path}.`);
2786
+ }
2774
2787
  return;
2775
2788
  }
2789
+ if (type === "bigint") {
2790
+ throw new Error(`Server proxy JSON transport does not support BigInt values at ${path}.`);
2791
+ }
2792
+ if (type === "undefined") {
2793
+ throw new Error(`Server proxy JSON transport does not support undefined values at ${path}.`);
2794
+ }
2795
+ if (type === "function" || type === "symbol") {
2796
+ throw new Error(`Server proxy JSON transport does not support ${type} values at ${path}.`);
2797
+ }
2798
+ if (type !== "object") {
2799
+ throw new Error(`Server proxy JSON transport does not support ${type} values at ${path}.`);
2800
+ }
2801
+
2776
2802
  if (stack.has(value)) {
2777
- throw new Error("Server proxy JSON transport does not support circular values.");
2803
+ throw new Error(`Server proxy JSON transport does not support circular values at ${path}.`);
2778
2804
  }
2779
2805
  stack.add(value);
2780
2806
 
2781
2807
  const tag = Object.prototype.toString.call(value);
2782
2808
  if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
2783
- throw new Error("Server proxy JSON transport does not support File, Blob, or FormData values yet.");
2809
+ throw new Error(`Server proxy JSON transport does not support File, Blob, or FormData values yet at ${path}.`);
2784
2810
  }
2785
2811
  if (isUnsupportedJsonTransportObject(value, tag)) {
2786
- throw new Error("Server proxy JSON transport does not support URLSearchParams, Headers, Request, Response, ReadableStream, ArrayBuffer, or typed array values yet.");
2812
+ throw new Error(`Server proxy JSON transport does not support URLSearchParams, Headers, Request, Response, ReadableStream, ArrayBuffer, or typed array values yet at ${path}.`);
2787
2813
  }
2788
2814
  if (Array.isArray(value)) {
2789
- for (const item of value) {
2790
- assertJsonTransportable(item, stack);
2815
+ for (let index = 0; index < value.length; index += 1) {
2816
+ if (!Object.hasOwn(value, index)) {
2817
+ throw new Error(`Server proxy JSON transport does not support sparse arrays at ${path}[${index}].`);
2818
+ }
2819
+ assertJsonTransportable(value[index], `${path}[${index}]`, stack);
2791
2820
  }
2792
2821
  stack.delete(value);
2793
2822
  return;
2794
2823
  }
2795
- for (const item of Object.values(value)) {
2796
- assertJsonTransportable(item, stack);
2824
+
2825
+ if (!isPlainJsonObject(value)) {
2826
+ throw new Error(`Server proxy JSON transport only supports plain objects at ${path}.`);
2827
+ }
2828
+
2829
+ for (const [key, item] of Object.entries(value)) {
2830
+ assertJsonTransportable(item, propertyPath(path, key), stack);
2797
2831
  }
2798
2832
  stack.delete(value);
2799
2833
  }
2800
2834
 
2835
+ function isPlainJsonObject(value) {
2836
+ const prototype = Object.getPrototypeOf(value);
2837
+ return prototype === Object.prototype || prototype === null;
2838
+ }
2839
+
2840
+ function propertyPath(path, key) {
2841
+ return /^[A-Za-z_$][\w$]*$/.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
2842
+ }
2843
+
2801
2844
  function isUnsupportedJsonTransportObject(value, tag = Object.prototype.toString.call(value)) {
2802
2845
  return tag === "[object URLSearchParams]"
2803
2846
  || tag === "[object Headers]"
@@ -5816,101 +5859,25 @@ const __boundaryReceiverModule = (() => {
5816
5859
 
5817
5860
  const normalized = validatePatch(patch);
5818
5861
  const record = boundaryRecord(normalized.boundary);
5819
- if (normalized.seq <= record.lastSeq) {
5820
- const result = {
5821
- status: "ignored-stale",
5822
- boundary: normalized.boundary,
5823
- seq: normalized.seq,
5824
- lastSeq: record.lastSeq
5825
- };
5826
- record.ignored += 1;
5827
- record.lastStatus = result.status;
5828
- remember(result);
5829
- onIgnore?.(result, patch);
5830
- return result;
5831
- }
5832
-
5833
- if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) {
5834
- const result = {
5835
- status: "ignored-destroyed",
5836
- boundary: normalized.boundary,
5837
- seq: normalized.seq,
5838
- parentScope: normalized.parentScope
5839
- };
5840
- record.ignored += 1;
5841
- record.lastStatus = result.status;
5842
- remember(result);
5843
- onIgnore?.(result, patch);
5844
- return result;
5845
- }
5846
-
5847
- record.lastSeq = normalized.seq;
5848
-
5849
- if (Object.hasOwn(normalized, "error")) {
5850
- const error = toStableError(normalized.error);
5851
- const result = {
5852
- status: "errored",
5853
- boundary: normalized.boundary,
5854
- seq: normalized.seq,
5855
- error
5856
- };
5857
- record.errored += 1;
5858
- record.lastStatus = result.status;
5859
- remember(result);
5860
- onError?.(error, result, patch);
5861
- if (throwOnError) {
5862
- throw error;
5863
- }
5864
- return result;
5865
- }
5862
+ let releasePending;
5863
+ const previousPending = record.pending ?? Promise.resolve();
5864
+ const pending = new Promise((resolve) => {
5865
+ releasePending = resolve;
5866
+ });
5867
+ record.pending = pending;
5866
5868
 
5867
- if (normalized.signals) {
5868
- if (!signals || typeof signals.set !== "function") {
5869
- throw new Error("Boundary patch includes signals, but no signal registry is available.");
5870
- }
5871
- for (const [path, value] of Object.entries(normalized.signals)) {
5872
- signals.set(path, value);
5869
+ try {
5870
+ await previousPending;
5871
+ if (destroyed) {
5872
+ throw new Error("Boundary receiver has been destroyed.");
5873
5873
  }
5874
- }
5875
-
5876
- if (normalized.cache?.browser) {
5877
- if (!cache || typeof cache.restore !== "function") {
5878
- throw new Error("Boundary patch includes browser cache, but no cache registry is available.");
5874
+ return await applyBoundaryPatch(record, normalized, patch);
5875
+ } finally {
5876
+ releasePending();
5877
+ if (record.pending === pending) {
5878
+ record.pending = undefined;
5879
5879
  }
5880
- cache.restore(normalized.cache.browser);
5881
5880
  }
5882
-
5883
- if (normalized.html != null) {
5884
- loader.swap(normalized.boundary, normalized.html);
5885
- }
5886
-
5887
- await flushScheduler(scheduler, normalized.scope);
5888
-
5889
- if (normalized.redirect) {
5890
- await followRedirect(normalized.redirect, router, loader);
5891
- const result = {
5892
- status: "redirected",
5893
- boundary: normalized.boundary,
5894
- seq: normalized.seq,
5895
- redirect: normalized.redirect
5896
- };
5897
- record.applied += 1;
5898
- record.lastStatus = result.status;
5899
- remember(result);
5900
- onApply?.(result, patch);
5901
- return result;
5902
- }
5903
-
5904
- const result = {
5905
- status: "applied",
5906
- boundary: normalized.boundary,
5907
- seq: normalized.seq
5908
- };
5909
- record.applied += 1;
5910
- record.lastStatus = result.status;
5911
- remember(result);
5912
- onApply?.(result, patch);
5913
- return result;
5914
5881
  },
5915
5882
 
5916
5883
  inspect() {
@@ -5958,6 +5925,105 @@ const __boundaryReceiverModule = (() => {
5958
5925
 
5959
5926
  return receiver;
5960
5927
 
5928
+ async function applyBoundaryPatch(record, normalized, patch) {
5929
+ if (normalized.seq <= record.lastSeq) {
5930
+ const result = {
5931
+ status: "ignored-stale",
5932
+ boundary: normalized.boundary,
5933
+ seq: normalized.seq,
5934
+ lastSeq: record.lastSeq
5935
+ };
5936
+ record.ignored += 1;
5937
+ record.lastStatus = result.status;
5938
+ remember(result);
5939
+ onIgnore?.(result, patch);
5940
+ return result;
5941
+ }
5942
+
5943
+ if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) {
5944
+ const result = {
5945
+ status: "ignored-destroyed",
5946
+ boundary: normalized.boundary,
5947
+ seq: normalized.seq,
5948
+ parentScope: normalized.parentScope
5949
+ };
5950
+ record.ignored += 1;
5951
+ record.lastStatus = result.status;
5952
+ remember(result);
5953
+ onIgnore?.(result, patch);
5954
+ return result;
5955
+ }
5956
+
5957
+ if (Object.hasOwn(normalized, "error")) {
5958
+ const error = toStableError(normalized.error);
5959
+ const result = {
5960
+ status: "errored",
5961
+ boundary: normalized.boundary,
5962
+ seq: normalized.seq,
5963
+ error
5964
+ };
5965
+ record.lastSeq = normalized.seq;
5966
+ record.errored += 1;
5967
+ record.lastStatus = result.status;
5968
+ remember(result);
5969
+ onError?.(error, result, patch);
5970
+ if (throwOnError) {
5971
+ throw error;
5972
+ }
5973
+ return result;
5974
+ }
5975
+
5976
+ if (normalized.signals) {
5977
+ if (!signals || typeof signals.set !== "function") {
5978
+ throw new Error("Boundary patch includes signals, but no signal registry is available.");
5979
+ }
5980
+ for (const [path, value] of Object.entries(normalized.signals)) {
5981
+ signals.set(path, value);
5982
+ }
5983
+ }
5984
+
5985
+ if (normalized.cache?.browser) {
5986
+ if (!cache || typeof cache.restore !== "function") {
5987
+ throw new Error("Boundary patch includes browser cache, but no cache registry is available.");
5988
+ }
5989
+ cache.restore(normalized.cache.browser);
5990
+ }
5991
+
5992
+ if (normalized.html != null) {
5993
+ loader.swap(normalized.boundary, normalized.html);
5994
+ }
5995
+
5996
+ await flushScheduler(scheduler, normalized.scope);
5997
+
5998
+ if (normalized.redirect) {
5999
+ const result = {
6000
+ status: "redirected",
6001
+ boundary: normalized.boundary,
6002
+ seq: normalized.seq,
6003
+ redirect: normalized.redirect
6004
+ };
6005
+ await followRedirect(normalized.redirect, router, loader);
6006
+ record.applied += 1;
6007
+ record.lastSeq = normalized.seq;
6008
+ record.lastStatus = result.status;
6009
+ remember(result);
6010
+ onApply?.(result, patch);
6011
+ return result;
6012
+ }
6013
+
6014
+ const result = {
6015
+ status: "applied",
6016
+ boundary: normalized.boundary,
6017
+ seq: normalized.seq
6018
+ };
6019
+ record.applied += 1;
6020
+ record.lastSeq = normalized.seq;
6021
+ record.lastStatus = result.status;
6022
+ remember(result);
6023
+ onApply?.(result, patch);
6024
+ return result;
6025
+ }
6026
+
5961
6027
  function boundaryRecord(boundary) {
5962
6028
  if (!boundaries.has(boundary)) {
5963
6029
  boundaries.set(boundary, {
@@ -5965,7 +6031,8 @@ const __boundaryReceiverModule = (() => {
5965
6031
  applied: 0,
5966
6032
  ignored: 0,
5967
6033
  errored: 0,
5968
- lastStatus: undefined
6034
+ lastStatus: undefined,
6035
+ pending: undefined
5969
6036
  });
5970
6037
  }
5971
6038
  return boundaries.get(boundary);
package/browser.umd.js CHANGED
@@ -2584,12 +2584,17 @@
2584
2584
  if (!element) {
2585
2585
  return {};
2586
2586
  }
2587
-
2588
- return {
2589
- value: "value" in element ? element.value : undefined,
2590
- checked: "checked" in element ? element.checked : undefined,
2591
- dataset: element.dataset ? { ...element.dataset } : {}
2592
- };
2587
+ const input = {};
2588
+ if ("value" in element) {
2589
+ input.value = element.value;
2590
+ }
2591
+ if ("checked" in element) {
2592
+ input.checked = element.checked;
2593
+ }
2594
+ if (element.dataset) {
2595
+ input.dataset = { ...element.dataset };
2596
+ }
2597
+ return input;
2593
2598
  }
2594
2599
 
2595
2600
  function createServerNamespace(run, root = {}, contextProvider = () => ({})) {
@@ -2776,38 +2781,76 @@
2776
2781
  return output;
2777
2782
  }
2778
2783
 
2779
- function assertJsonTransportable(value, stack = new Set()) {
2780
- if (typeof value === "bigint") {
2781
- throw new Error("Server proxy JSON transport does not support BigInt values.");
2784
+ function assertJsonTransportable(value, path = "$", stack = new Set()) {
2785
+ if (value === null) {
2786
+ return;
2787
+ }
2788
+
2789
+ const type = typeof value;
2790
+ if (type === "boolean" || type === "string") {
2791
+ return;
2782
2792
  }
2783
- if (value == null || typeof value !== "object") {
2793
+ if (type === "number") {
2794
+ if (!Number.isFinite(value)) {
2795
+ throw new Error(`Server proxy JSON transport does not support non-finite numbers at ${path}.`);
2796
+ }
2784
2797
  return;
2785
2798
  }
2799
+ if (type === "bigint") {
2800
+ throw new Error(`Server proxy JSON transport does not support BigInt values at ${path}.`);
2801
+ }
2802
+ if (type === "undefined") {
2803
+ throw new Error(`Server proxy JSON transport does not support undefined values at ${path}.`);
2804
+ }
2805
+ if (type === "function" || type === "symbol") {
2806
+ throw new Error(`Server proxy JSON transport does not support ${type} values at ${path}.`);
2807
+ }
2808
+ if (type !== "object") {
2809
+ throw new Error(`Server proxy JSON transport does not support ${type} values at ${path}.`);
2810
+ }
2811
+
2786
2812
  if (stack.has(value)) {
2787
- throw new Error("Server proxy JSON transport does not support circular values.");
2813
+ throw new Error(`Server proxy JSON transport does not support circular values at ${path}.`);
2788
2814
  }
2789
2815
  stack.add(value);
2790
2816
 
2791
2817
  const tag = Object.prototype.toString.call(value);
2792
2818
  if (tag === "[object File]" || tag === "[object Blob]" || tag === "[object FormData]") {
2793
- throw new Error("Server proxy JSON transport does not support File, Blob, or FormData values yet.");
2819
+ throw new Error(`Server proxy JSON transport does not support File, Blob, or FormData values yet at ${path}.`);
2794
2820
  }
2795
2821
  if (isUnsupportedJsonTransportObject(value, tag)) {
2796
- throw new Error("Server proxy JSON transport does not support URLSearchParams, Headers, Request, Response, ReadableStream, ArrayBuffer, or typed array values yet.");
2822
+ throw new Error(`Server proxy JSON transport does not support URLSearchParams, Headers, Request, Response, ReadableStream, ArrayBuffer, or typed array values yet at ${path}.`);
2797
2823
  }
2798
2824
  if (Array.isArray(value)) {
2799
- for (const item of value) {
2800
- assertJsonTransportable(item, stack);
2825
+ for (let index = 0; index < value.length; index += 1) {
2826
+ if (!Object.hasOwn(value, index)) {
2827
+ throw new Error(`Server proxy JSON transport does not support sparse arrays at ${path}[${index}].`);
2828
+ }
2829
+ assertJsonTransportable(value[index], `${path}[${index}]`, stack);
2801
2830
  }
2802
2831
  stack.delete(value);
2803
2832
  return;
2804
2833
  }
2805
- for (const item of Object.values(value)) {
2806
- assertJsonTransportable(item, stack);
2834
+
2835
+ if (!isPlainJsonObject(value)) {
2836
+ throw new Error(`Server proxy JSON transport only supports plain objects at ${path}.`);
2837
+ }
2838
+
2839
+ for (const [key, item] of Object.entries(value)) {
2840
+ assertJsonTransportable(item, propertyPath(path, key), stack);
2807
2841
  }
2808
2842
  stack.delete(value);
2809
2843
  }
2810
2844
 
2845
+ function isPlainJsonObject(value) {
2846
+ const prototype = Object.getPrototypeOf(value);
2847
+ return prototype === Object.prototype || prototype === null;
2848
+ }
2849
+
2850
+ function propertyPath(path, key) {
2851
+ return /^[A-Za-z_$][\w$]*$/.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
2852
+ }
2853
+
2811
2854
  function isUnsupportedJsonTransportObject(value, tag = Object.prototype.toString.call(value)) {
2812
2855
  return tag === "[object URLSearchParams]"
2813
2856
  || tag === "[object Headers]"
@@ -5826,101 +5869,25 @@
5826
5869
 
5827
5870
  const normalized = validatePatch(patch);
5828
5871
  const record = boundaryRecord(normalized.boundary);
5829
- if (normalized.seq <= record.lastSeq) {
5830
- const result = {
5831
- status: "ignored-stale",
5832
- boundary: normalized.boundary,
5833
- seq: normalized.seq,
5834
- lastSeq: record.lastSeq
5835
- };
5836
- record.ignored += 1;
5837
- record.lastStatus = result.status;
5838
- remember(result);
5839
- onIgnore?.(result, patch);
5840
- return result;
5841
- }
5842
-
5843
- if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) {
5844
- const result = {
5845
- status: "ignored-destroyed",
5846
- boundary: normalized.boundary,
5847
- seq: normalized.seq,
5848
- parentScope: normalized.parentScope
5849
- };
5850
- record.ignored += 1;
5851
- record.lastStatus = result.status;
5852
- remember(result);
5853
- onIgnore?.(result, patch);
5854
- return result;
5855
- }
5856
-
5857
- record.lastSeq = normalized.seq;
5858
-
5859
- if (Object.hasOwn(normalized, "error")) {
5860
- const error = toStableError(normalized.error);
5861
- const result = {
5862
- status: "errored",
5863
- boundary: normalized.boundary,
5864
- seq: normalized.seq,
5865
- error
5866
- };
5867
- record.errored += 1;
5868
- record.lastStatus = result.status;
5869
- remember(result);
5870
- onError?.(error, result, patch);
5871
- if (throwOnError) {
5872
- throw error;
5873
- }
5874
- return result;
5875
- }
5872
+ let releasePending;
5873
+ const previousPending = record.pending ?? Promise.resolve();
5874
+ const pending = new Promise((resolve) => {
5875
+ releasePending = resolve;
5876
+ });
5877
+ record.pending = pending;
5876
5878
 
5877
- if (normalized.signals) {
5878
- if (!signals || typeof signals.set !== "function") {
5879
- throw new Error("Boundary patch includes signals, but no signal registry is available.");
5880
- }
5881
- for (const [path, value] of Object.entries(normalized.signals)) {
5882
- signals.set(path, value);
5879
+ try {
5880
+ await previousPending;
5881
+ if (destroyed) {
5882
+ throw new Error("Boundary receiver has been destroyed.");
5883
5883
  }
5884
- }
5885
-
5886
- if (normalized.cache?.browser) {
5887
- if (!cache || typeof cache.restore !== "function") {
5888
- throw new Error("Boundary patch includes browser cache, but no cache registry is available.");
5884
+ return await applyBoundaryPatch(record, normalized, patch);
5885
+ } finally {
5886
+ releasePending();
5887
+ if (record.pending === pending) {
5888
+ record.pending = undefined;
5889
5889
  }
5890
- cache.restore(normalized.cache.browser);
5891
5890
  }
5892
-
5893
- if (normalized.html != null) {
5894
- loader.swap(normalized.boundary, normalized.html);
5895
- }
5896
-
5897
- await flushScheduler(scheduler, normalized.scope);
5898
-
5899
- if (normalized.redirect) {
5900
- await followRedirect(normalized.redirect, router, loader);
5901
- const result = {
5902
- status: "redirected",
5903
- boundary: normalized.boundary,
5904
- seq: normalized.seq,
5905
- redirect: normalized.redirect
5906
- };
5907
- record.applied += 1;
5908
- record.lastStatus = result.status;
5909
- remember(result);
5910
- onApply?.(result, patch);
5911
- return result;
5912
- }
5913
-
5914
- const result = {
5915
- status: "applied",
5916
- boundary: normalized.boundary,
5917
- seq: normalized.seq
5918
- };
5919
- record.applied += 1;
5920
- record.lastStatus = result.status;
5921
- remember(result);
5922
- onApply?.(result, patch);
5923
- return result;
5924
5891
  },
5925
5892
 
5926
5893
  inspect() {
@@ -5968,6 +5935,105 @@
5968
5935
 
5969
5936
  return receiver;
5970
5937
 
5938
+ async function applyBoundaryPatch(record, normalized, patch) {
5939
+ if (normalized.seq <= record.lastSeq) {
5940
+ const result = {
5941
+ status: "ignored-stale",
5942
+ boundary: normalized.boundary,
5943
+ seq: normalized.seq,
5944
+ lastSeq: record.lastSeq
5945
+ };
5946
+ record.ignored += 1;
5947
+ record.lastStatus = result.status;
5948
+ remember(result);
5949
+ onIgnore?.(result, patch);
5950
+ return result;
5951
+ }
5952
+
5953
+ if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) {
5954
+ const result = {
5955
+ status: "ignored-destroyed",
5956
+ boundary: normalized.boundary,
5957
+ seq: normalized.seq,
5958
+ parentScope: normalized.parentScope
5959
+ };
5960
+ record.ignored += 1;
5961
+ record.lastStatus = result.status;
5962
+ remember(result);
5963
+ onIgnore?.(result, patch);
5964
+ return result;
5965
+ }
5966
+
5967
+ if (Object.hasOwn(normalized, "error")) {
5968
+ const error = toStableError(normalized.error);
5969
+ const result = {
5970
+ status: "errored",
5971
+ boundary: normalized.boundary,
5972
+ seq: normalized.seq,
5973
+ error
5974
+ };
5975
+ record.lastSeq = normalized.seq;
5976
+ record.errored += 1;
5977
+ record.lastStatus = result.status;
5978
+ remember(result);
5979
+ onError?.(error, result, patch);
5980
+ if (throwOnError) {
5981
+ throw error;
5982
+ }
5983
+ return result;
5984
+ }
5985
+
5986
+ if (normalized.signals) {
5987
+ if (!signals || typeof signals.set !== "function") {
5988
+ throw new Error("Boundary patch includes signals, but no signal registry is available.");
5989
+ }
5990
+ for (const [path, value] of Object.entries(normalized.signals)) {
5991
+ signals.set(path, value);
5992
+ }
5993
+ }
5994
+
5995
+ if (normalized.cache?.browser) {
5996
+ if (!cache || typeof cache.restore !== "function") {
5997
+ throw new Error("Boundary patch includes browser cache, but no cache registry is available.");
5998
+ }
5999
+ cache.restore(normalized.cache.browser);
6000
+ }
6001
+
6002
+ if (normalized.html != null) {
6003
+ loader.swap(normalized.boundary, normalized.html);
6004
+ }
6005
+
6006
+ await flushScheduler(scheduler, normalized.scope);
6007
+
6008
+ if (normalized.redirect) {
6009
+ const result = {
6010
+ status: "redirected",
6011
+ boundary: normalized.boundary,
6012
+ seq: normalized.seq,
6013
+ redirect: normalized.redirect
6014
+ };
6015
+ await followRedirect(normalized.redirect, router, loader);
6016
+ record.applied += 1;
6017
+ record.lastSeq = normalized.seq;
6018
+ record.lastStatus = result.status;
6019
+ remember(result);
6020
+ onApply?.(result, patch);
6021
+ return result;
6022
+ }
6023
+
6024
+ const result = {
6025
+ status: "applied",
6026
+ boundary: normalized.boundary,
6027
+ seq: normalized.seq
6028
+ };
6029
+ record.applied += 1;
6030
+ record.lastSeq = normalized.seq;
6031
+ record.lastStatus = result.status;
6032
+ remember(result);
6033
+ onApply?.(result, patch);
6034
+ return result;
6035
+ }
6036
+
5971
6037
  function boundaryRecord(boundary) {
5972
6038
  if (!boundaries.has(boundary)) {
5973
6039
  boundaries.set(boundary, {
@@ -5975,7 +6041,8 @@
5975
6041
  applied: 0,
5976
6042
  ignored: 0,
5977
6043
  errored: 0,
5978
- lastStatus: undefined
6044
+ lastStatus: undefined,
6045
+ pending: undefined
5979
6046
  });
5980
6047
  }
5981
6048
  return boundaries.get(boundary);