Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/failed-render-seed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect-atom-svelte": patch
---

A server render that fails while a serializable atom's result is still being prepared for the browser no longer reports an unhandled rejection ("registry is disposed"). The provider disposes of its registry when the failed render ends, and the pending result now stops there instead of reading from it.
15 changes: 14 additions & 1 deletion packages/effect-atom-svelte/src/Hooks.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
decodeSeed,
encodeSeed,
isWaiting,
noSeed,
revalidatesOnHydrate,
} from "./internal/hydration.ts";
import { onRenderEnd } from "./internal/renderEnd.ts";
Expand Down Expand Up @@ -1054,7 +1055,13 @@ const seedOnServer = (
): Promise<void> => {
// Mounted until the render ends, so the settled node is what the render reads.
const release = serverMount(registry, atom);
onRenderEnd(release);
// A render ends before its seeds settle only when it fails, as when a later reader throws during
// setup. The provider has disposed of the registry by then, so the seed reads nothing from it.
let ended = false;
onRenderEnd(() => {
ended = true;
release();
});
// hydratable hands every later reader of a key the first reader's value, but Svelte's dev build
// also runs each later reader's callback and throws hydratable_clobbering if what it encodes
// differs. Reading the atom again there would encode whatever it holds by then, so a later
Expand All @@ -1064,6 +1071,9 @@ const seedOnServer = (
const encoded = hydratable(key, () => {
claim.own = (async () => {
await undefined;
if (ended) {
return noSeed;
}
if (claim.first !== claim.own) {
return await claim.first;
}
Expand All @@ -1079,6 +1089,9 @@ const seedOnServer = (
await awaitResult(registry, atom, { suspendOnWaiting: settled });
}
}
if (ended) {
return noSeed;
}
return encodeSeed(key, encode, serverGet(registry, atom));
})();
return claim.own;
Expand Down
2 changes: 1 addition & 1 deletion packages/effect-atom-svelte/src/internal/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const revalidatesOnHydrate = (option: boolean | undefined): boolean =>
* What the server sends for a result it doesn't pass on, so the browser computes the atom itself.
* An encoded `AsyncResult` is an object, never `null`.
*/
const noSeed = null;
export const noSeed = null;

/**
* Encodes the server's result for the page, or returns the no-seed marker for a result that must
Expand Down
Loading