ajsldkfjalsdfkjasd

elliott/hydratable
Elliott Johnson 1 day ago
parent 3f3ad1a2e6
commit 640fabd70c

@ -24,7 +24,7 @@ export function hydratable(key, fn) {
let entry = hydratable.lookup.get(key);
if (entry !== undefined) {
if (DEV && entry.dev) {
if (DEV) {
const comparison = compare(key, entry, encode(key, fn(), []));
comparison.catch(() => {});
hydratable.comparisons.push(comparison);
@ -52,11 +52,7 @@ function encode(key, value, values, unresolved) {
const entry = { value, index: -1 };
if (DEV) {
entry.dev = {
serialized: undefined,
serialize_work: [],
stack: get_stack('hydratable')?.stack
};
entry.stack = get_stack('hydratable')?.stack;
}
let needs_thunk = false;
@ -82,12 +78,11 @@ function encode(key, value, values, unresolved) {
// of a given hydratable are identical with a simple string comparison
const result = DEV ? `d("${index}")` : `d(${index})`;
if (DEV && entry.dev) {
const { dev } = entry;
dev.serialize_work.push(
if (DEV) {
(entry.serialize_work ??= []).push(
serialize_promise.then((s) => {
serialized = serialized.replace(result, s);
dev.serialized = serialized;
entry.serialized = serialized;
})
);
}
@ -96,6 +91,7 @@ function encode(key, value, values, unresolved) {
}
});
entry.serialized = serialized;
entry.index = values.push(needs_thunk ? `()=>(${serialized})` : serialized) - 1;
needs_thunk = false;
@ -111,19 +107,19 @@ async function compare(key, a, b) {
// note: these need to be loops (as opposed to Promise.all) because
// additional promises can get pushed to them while we're awaiting
// an earlier one
for (const p of a.dev?.serialize_work ?? []) {
for (const p of a?.serialize_work ?? []) {
await p;
}
for (const p of b.dev?.serialize_work ?? []) {
for (const p of b?.serialize_work ?? []) {
await p;
}
if (a.dev?.serialized !== b.dev?.serialized) {
if (a?.serialized !== b?.serialized) {
e.hydratable_clobbering(
key,
a.dev?.stack ?? '<missing stack trace>',
b.dev?.stack ?? '<missing stack trace>'
a?.stack ?? '<missing stack trace>',
b?.stack ?? '<missing stack trace>'
);
}
}

@ -580,7 +580,7 @@ export class Renderer {
for (const [_, key] of ctx.unresolved_promises) {
// this is a problem -- it means we've finished the render but we're still waiting on a promise to resolve so we can
// serialize it, so we're blocking the response on useless content.
w.unresolved_hydratable(key, ctx.lookup.get(key)?.dev?.stack ?? '<missing stack trace>');
w.unresolved_hydratable(key, ctx.lookup.get(key)?.stack ?? '<missing stack trace>');
}
for (const comparison of ctx.comparisons) {

@ -18,11 +18,12 @@ export interface SSRContext {
export interface HydratableLookupEntry {
value: unknown;
index: number;
dev?: {
serialize_work: Array<Promise<void>>;
serialized: string | undefined;
stack: string | undefined;
};
/** dev-only */
serialize_work?: Array<Promise<void>>;
/** dev-only */
serialized?: string;
/** dev-only */
stack?: string;
}
export interface HydratableContext {

@ -0,0 +1,24 @@
import { tick } from 'svelte';
import { ok, test } from '../../test';
export default test({
skip_no_async: true,
skip_mode: ['server'],
server_props: { environment: 'server' },
ssrHtml: '<p>The current environment is: server</p>',
props: { environment: 'browser' },
async test({ assert, target, variant }) {
// make sure hydration has a chance to finish
await tick();
const p = target.querySelector('p');
ok(p);
if (variant === 'hydrate') {
assert.htmlEqual(p.outerHTML, '<p>The current environment is: server</p>');
} else {
assert.htmlEqual(p.outerHTML, '<p>The current environment is: browser</p>');
}
}
});

@ -0,0 +1,13 @@
<script lang="ts">
import { hydratable } from "svelte";
let { environment } = $props();
const value = hydratable("environment", () => Promise.resolve({
nested: Promise.resolve({
environment
})
}))
</script>
<p>The current environment is: {await value.then(res => res.nested).then(res => res.environment)}</p>

@ -0,0 +1,6 @@
import { test } from '../../test';
export default test({
mode: ['async'],
error: 'hydratable_clobbering'
});

@ -0,0 +1,16 @@
<script lang="ts">
import { hydratable } from 'svelte';
hydratable('key', () => Promise.resolve({
nested: Promise.resolve({
one: Promise.resolve(1),
}),
two: Promise.resolve(2),
}));
hydratable('key', () => Promise.resolve({
nested: Promise.resolve({
one: Promise.resolve(2),
}),
two: Promise.resolve(2),
}));
</script>
Loading…
Cancel
Save