@async/framework 0.11.11 → 0.11.12
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 +14 -0
- package/browser.js +116 -92
- package/browser.min.js +1 -1
- package/browser.ts +116 -92
- package/browser.umd.js +116 -92
- package/browser.umd.min.js +1 -1
- package/framework.ts +116 -92
- package/package.json +1 -1
- package/server.js +116 -92
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.12 - 2026-06-18
|
|
4
|
+
|
|
5
|
+
- Deferred boundary receiver sequence commits until patch effects complete so
|
|
6
|
+
failed DOM swaps, scheduler flushes, redirects, or missing capabilities no
|
|
7
|
+
longer make the same streamed sequence stale.
|
|
8
|
+
- Serialized same-boundary patch application to keep concurrent patches from
|
|
9
|
+
committing out of order while preserving stale rejection after successful
|
|
10
|
+
commits.
|
|
11
|
+
- Added regression coverage for retryable DOM, scheduler, redirect, and
|
|
12
|
+
capability failures plus idempotent partial-effect replay.
|
|
13
|
+
- Bundle size from bundled TypeScript source: `browser.ts` 186,064 B raw /
|
|
14
|
+
35,039 B gzip -> `browser.min.js` 79,042 B raw / 23,445 B gzip
|
|
15
|
+
(-107,022 B raw, -11,594 B gzip).
|
|
16
|
+
|
|
3
17
|
## 0.11.11 - 2026-06-18
|
|
4
18
|
|
|
5
19
|
- Serialized rejected async-signal snapshot errors to stable `name`, `message`,
|
package/browser.js
CHANGED
|
@@ -5815,101 +5815,25 @@ const __boundaryReceiverModule = (() => {
|
|
|
5815
5815
|
|
|
5816
5816
|
const normalized = validatePatch(patch);
|
|
5817
5817
|
const record = boundaryRecord(normalized.boundary);
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
};
|
|
5825
|
-
record.ignored += 1;
|
|
5826
|
-
record.lastStatus = result.status;
|
|
5827
|
-
remember(result);
|
|
5828
|
-
onIgnore?.(result, patch);
|
|
5829
|
-
return result;
|
|
5830
|
-
}
|
|
5831
|
-
|
|
5832
|
-
if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) {
|
|
5833
|
-
const result = {
|
|
5834
|
-
status: "ignored-destroyed",
|
|
5835
|
-
boundary: normalized.boundary,
|
|
5836
|
-
seq: normalized.seq,
|
|
5837
|
-
parentScope: normalized.parentScope
|
|
5838
|
-
};
|
|
5839
|
-
record.ignored += 1;
|
|
5840
|
-
record.lastStatus = result.status;
|
|
5841
|
-
remember(result);
|
|
5842
|
-
onIgnore?.(result, patch);
|
|
5843
|
-
return result;
|
|
5844
|
-
}
|
|
5845
|
-
|
|
5846
|
-
record.lastSeq = normalized.seq;
|
|
5847
|
-
|
|
5848
|
-
if (Object.hasOwn(normalized, "error")) {
|
|
5849
|
-
const error = toStableError(normalized.error);
|
|
5850
|
-
const result = {
|
|
5851
|
-
status: "errored",
|
|
5852
|
-
boundary: normalized.boundary,
|
|
5853
|
-
seq: normalized.seq,
|
|
5854
|
-
error
|
|
5855
|
-
};
|
|
5856
|
-
record.errored += 1;
|
|
5857
|
-
record.lastStatus = result.status;
|
|
5858
|
-
remember(result);
|
|
5859
|
-
onError?.(error, result, patch);
|
|
5860
|
-
if (throwOnError) {
|
|
5861
|
-
throw error;
|
|
5862
|
-
}
|
|
5863
|
-
return result;
|
|
5864
|
-
}
|
|
5818
|
+
let releasePending;
|
|
5819
|
+
const previousPending = record.pending ?? Promise.resolve();
|
|
5820
|
+
const pending = new Promise((resolve) => {
|
|
5821
|
+
releasePending = resolve;
|
|
5822
|
+
});
|
|
5823
|
+
record.pending = pending;
|
|
5865
5824
|
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
for (const [path, value] of Object.entries(normalized.signals)) {
|
|
5871
|
-
signals.set(path, value);
|
|
5825
|
+
try {
|
|
5826
|
+
await previousPending;
|
|
5827
|
+
if (destroyed) {
|
|
5828
|
+
throw new Error("Boundary receiver has been destroyed.");
|
|
5872
5829
|
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
if (
|
|
5877
|
-
|
|
5830
|
+
return await applyBoundaryPatch(record, normalized, patch);
|
|
5831
|
+
} finally {
|
|
5832
|
+
releasePending();
|
|
5833
|
+
if (record.pending === pending) {
|
|
5834
|
+
record.pending = undefined;
|
|
5878
5835
|
}
|
|
5879
|
-
cache.restore(normalized.cache.browser);
|
|
5880
|
-
}
|
|
5881
|
-
|
|
5882
|
-
if (normalized.html != null) {
|
|
5883
|
-
loader.swap(normalized.boundary, normalized.html);
|
|
5884
|
-
}
|
|
5885
|
-
|
|
5886
|
-
await flushScheduler(scheduler, normalized.scope);
|
|
5887
|
-
|
|
5888
|
-
if (normalized.redirect) {
|
|
5889
|
-
await followRedirect(normalized.redirect, router, loader);
|
|
5890
|
-
const result = {
|
|
5891
|
-
status: "redirected",
|
|
5892
|
-
boundary: normalized.boundary,
|
|
5893
|
-
seq: normalized.seq,
|
|
5894
|
-
redirect: normalized.redirect
|
|
5895
|
-
};
|
|
5896
|
-
record.applied += 1;
|
|
5897
|
-
record.lastStatus = result.status;
|
|
5898
|
-
remember(result);
|
|
5899
|
-
onApply?.(result, patch);
|
|
5900
|
-
return result;
|
|
5901
5836
|
}
|
|
5902
|
-
|
|
5903
|
-
const result = {
|
|
5904
|
-
status: "applied",
|
|
5905
|
-
boundary: normalized.boundary,
|
|
5906
|
-
seq: normalized.seq
|
|
5907
|
-
};
|
|
5908
|
-
record.applied += 1;
|
|
5909
|
-
record.lastStatus = result.status;
|
|
5910
|
-
remember(result);
|
|
5911
|
-
onApply?.(result, patch);
|
|
5912
|
-
return result;
|
|
5913
5837
|
},
|
|
5914
5838
|
|
|
5915
5839
|
inspect() {
|
|
@@ -5957,6 +5881,105 @@ const __boundaryReceiverModule = (() => {
|
|
|
5957
5881
|
|
|
5958
5882
|
return receiver;
|
|
5959
5883
|
|
|
5884
|
+
async function applyBoundaryPatch(record, normalized, patch) {
|
|
5885
|
+
if (normalized.seq <= record.lastSeq) {
|
|
5886
|
+
const result = {
|
|
5887
|
+
status: "ignored-stale",
|
|
5888
|
+
boundary: normalized.boundary,
|
|
5889
|
+
seq: normalized.seq,
|
|
5890
|
+
lastSeq: record.lastSeq
|
|
5891
|
+
};
|
|
5892
|
+
record.ignored += 1;
|
|
5893
|
+
record.lastStatus = result.status;
|
|
5894
|
+
remember(result);
|
|
5895
|
+
onIgnore?.(result, patch);
|
|
5896
|
+
return result;
|
|
5897
|
+
}
|
|
5898
|
+
|
|
5899
|
+
if (normalized.parentScope !== undefined && isScopeDestroyed(normalized.parentScope)) {
|
|
5900
|
+
const result = {
|
|
5901
|
+
status: "ignored-destroyed",
|
|
5902
|
+
boundary: normalized.boundary,
|
|
5903
|
+
seq: normalized.seq,
|
|
5904
|
+
parentScope: normalized.parentScope
|
|
5905
|
+
};
|
|
5906
|
+
record.ignored += 1;
|
|
5907
|
+
record.lastStatus = result.status;
|
|
5908
|
+
remember(result);
|
|
5909
|
+
onIgnore?.(result, patch);
|
|
5910
|
+
return result;
|
|
5911
|
+
}
|
|
5912
|
+
|
|
5913
|
+
if (Object.hasOwn(normalized, "error")) {
|
|
5914
|
+
const error = toStableError(normalized.error);
|
|
5915
|
+
const result = {
|
|
5916
|
+
status: "errored",
|
|
5917
|
+
boundary: normalized.boundary,
|
|
5918
|
+
seq: normalized.seq,
|
|
5919
|
+
error
|
|
5920
|
+
};
|
|
5921
|
+
record.lastSeq = normalized.seq;
|
|
5922
|
+
record.errored += 1;
|
|
5923
|
+
record.lastStatus = result.status;
|
|
5924
|
+
remember(result);
|
|
5925
|
+
onError?.(error, result, patch);
|
|
5926
|
+
if (throwOnError) {
|
|
5927
|
+
throw error;
|
|
5928
|
+
}
|
|
5929
|
+
return result;
|
|
5930
|
+
}
|
|
5931
|
+
|
|
5932
|
+
if (normalized.signals) {
|
|
5933
|
+
if (!signals || typeof signals.set !== "function") {
|
|
5934
|
+
throw new Error("Boundary patch includes signals, but no signal registry is available.");
|
|
5935
|
+
}
|
|
5936
|
+
for (const [path, value] of Object.entries(normalized.signals)) {
|
|
5937
|
+
signals.set(path, value);
|
|
5938
|
+
}
|
|
5939
|
+
}
|
|
5940
|
+
|
|
5941
|
+
if (normalized.cache?.browser) {
|
|
5942
|
+
if (!cache || typeof cache.restore !== "function") {
|
|
5943
|
+
throw new Error("Boundary patch includes browser cache, but no cache registry is available.");
|
|
5944
|
+
}
|
|
5945
|
+
cache.restore(normalized.cache.browser);
|
|
5946
|
+
}
|
|
5947
|
+
|
|
5948
|
+
if (normalized.html != null) {
|
|
5949
|
+
loader.swap(normalized.boundary, normalized.html);
|
|
5950
|
+
}
|
|
5951
|
+
|
|
5952
|
+
await flushScheduler(scheduler, normalized.scope);
|
|
5953
|
+
|
|
5954
|
+
if (normalized.redirect) {
|
|
5955
|
+
const result = {
|
|
5956
|
+
status: "redirected",
|
|
5957
|
+
boundary: normalized.boundary,
|
|
5958
|
+
seq: normalized.seq,
|
|
5959
|
+
redirect: normalized.redirect
|
|
5960
|
+
};
|
|
5961
|
+
await followRedirect(normalized.redirect, router, loader);
|
|
5962
|
+
record.applied += 1;
|
|
5963
|
+
record.lastSeq = normalized.seq;
|
|
5964
|
+
record.lastStatus = result.status;
|
|
5965
|
+
remember(result);
|
|
5966
|
+
onApply?.(result, patch);
|
|
5967
|
+
return result;
|
|
5968
|
+
}
|
|
5969
|
+
|
|
5970
|
+
const result = {
|
|
5971
|
+
status: "applied",
|
|
5972
|
+
boundary: normalized.boundary,
|
|
5973
|
+
seq: normalized.seq
|
|
5974
|
+
};
|
|
5975
|
+
record.applied += 1;
|
|
5976
|
+
record.lastSeq = normalized.seq;
|
|
5977
|
+
record.lastStatus = result.status;
|
|
5978
|
+
remember(result);
|
|
5979
|
+
onApply?.(result, patch);
|
|
5980
|
+
return result;
|
|
5981
|
+
}
|
|
5982
|
+
|
|
5960
5983
|
function boundaryRecord(boundary) {
|
|
5961
5984
|
if (!boundaries.has(boundary)) {
|
|
5962
5985
|
boundaries.set(boundary, {
|
|
@@ -5964,7 +5987,8 @@ const __boundaryReceiverModule = (() => {
|
|
|
5964
5987
|
applied: 0,
|
|
5965
5988
|
ignored: 0,
|
|
5966
5989
|
errored: 0,
|
|
5967
|
-
lastStatus: undefined
|
|
5990
|
+
lastStatus: undefined,
|
|
5991
|
+
pending: undefined
|
|
5968
5992
|
});
|
|
5969
5993
|
}
|
|
5970
5994
|
return boundaries.get(boundary);
|