@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/CHANGELOG.md +29 -0
- package/README.md +8 -0
- package/browser.js +176 -109
- package/browser.min.js +1 -1
- package/browser.ts +176 -109
- package/browser.umd.js +176 -109
- package/browser.umd.min.js +1 -1
- package/framework.ts +176 -109
- package/package.json +1 -1
- package/server.js +176 -109
package/browser.ts
CHANGED
|
@@ -2574,12 +2574,17 @@ const __serverModule = (() => {
|
|
|
2574
2574
|
if (!element) {
|
|
2575
2575
|
return {};
|
|
2576
2576
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
value
|
|
2580
|
-
|
|
2581
|
-
|
|
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 (
|
|
2771
|
-
|
|
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 (
|
|
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(
|
|
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(
|
|
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(
|
|
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 (
|
|
2790
|
-
|
|
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
|
-
|
|
2796
|
-
|
|
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
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
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
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
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
|
-
|
|
5877
|
-
if (
|
|
5878
|
-
|
|
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
|
-
|
|
2589
|
-
value
|
|
2590
|
-
|
|
2591
|
-
|
|
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 (
|
|
2781
|
-
|
|
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 (
|
|
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(
|
|
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(
|
|
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(
|
|
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 (
|
|
2800
|
-
|
|
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
|
-
|
|
2806
|
-
|
|
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
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
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
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
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
|
-
|
|
5887
|
-
if (
|
|
5888
|
-
|
|
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);
|