mirror of https://github.com/sveltejs/svelte
parent
05e60b1320
commit
caad89b888
@ -1,62 +1,67 @@
|
|||||||
/** @import { Encode, Transport } from '#shared' */
|
/** @import { HydratableContext } from '#server' */
|
||||||
/** @import { HydratableEntry } from '#server' */
|
|
||||||
import { async_mode_flag } from '../flags/index.js';
|
import { async_mode_flag } from '../flags/index.js';
|
||||||
import { get_render_context } from './render-context.js';
|
import { get_render_context } from './render-context.js';
|
||||||
import * as e from './errors.js';
|
import * as e from './errors.js';
|
||||||
import { DEV } from 'esm-env';
|
import { uneval } from 'devalue';
|
||||||
|
|
||||||
/** @type {WeakSet<HydratableEntry>} */
|
|
||||||
export const unresolved_hydratables = new WeakSet();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {() => T} fn
|
* @param {() => T} fn
|
||||||
* @param {Transport<T>} [transport]
|
|
||||||
* @returns {T}
|
* @returns {T}
|
||||||
*/
|
*/
|
||||||
export function hydratable(key, fn, transport) {
|
export function hydratable(key, fn) {
|
||||||
if (!async_mode_flag) {
|
if (!async_mode_flag) {
|
||||||
e.experimental_async_required('hydratable');
|
e.experimental_async_required('hydratable');
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = get_render_context();
|
const store = get_render_context();
|
||||||
|
|
||||||
const entry = create_entry(fn(), transport?.encode);
|
const entry = store.hydratable.lookup.get(key);
|
||||||
const existing_entry = store.hydratables.get(key);
|
if (entry !== undefined) {
|
||||||
if (DEV && existing_entry !== undefined) {
|
return /** @type {T} */ (entry.value);
|
||||||
(existing_entry.dev_competing_entries ??= []).push(entry);
|
|
||||||
return entry.value;
|
|
||||||
}
|
}
|
||||||
store.hydratables.set(key, entry);
|
|
||||||
return entry.value;
|
const result = fn();
|
||||||
|
store.hydratable.lookup.set(key, {
|
||||||
|
value: result,
|
||||||
|
root_index: encode(result, key, store.hydratable)
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @param {unknown} value
|
||||||
* @param {T} value
|
* @param {string} key
|
||||||
* @param {Encode<T> | undefined} encode
|
* @param {HydratableContext} hydratable_context
|
||||||
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
function create_entry(value, encode) {
|
function encode(value, key, hydratable_context) {
|
||||||
/** @type {Omit<HydratableEntry, 'value'> & { value: T }} */
|
const replacer = create_replacer(key, hydratable_context);
|
||||||
const entry = {
|
return hydratable_context.values.push(uneval(value, replacer)) - 1;
|
||||||
value,
|
}
|
||||||
encode
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DEV) {
|
/**
|
||||||
entry.stack = new Error().stack;
|
* @param {string} key
|
||||||
|
* @param {HydratableContext} hydratable_context
|
||||||
if (
|
* @returns {(value: unknown, uneval: (value: any) => string) => string | undefined}
|
||||||
typeof value === 'object' &&
|
*/
|
||||||
value !== null &&
|
function create_replacer(key, hydratable_context) {
|
||||||
'then' in value &&
|
/**
|
||||||
typeof value.then === 'function'
|
* @param {unknown} value
|
||||||
) {
|
* @param {(value: any) => string} inner_uneval
|
||||||
unresolved_hydratables.add(entry);
|
*/
|
||||||
value.then(() => unresolved_hydratables.delete(entry));
|
const replacer = (value, inner_uneval) => {
|
||||||
|
if (value instanceof Promise) {
|
||||||
|
hydratable_context.unresolved_promises.set(value, key);
|
||||||
|
value.finally(() => hydratable_context.unresolved_promises.delete(value));
|
||||||
|
// use the root-level uneval because we need a separate, top-level entry for each promise
|
||||||
|
const index =
|
||||||
|
hydratable_context.values.push(value.then((v) => `r(${uneval(v, replacer)})`)) - 1;
|
||||||
|
return `d(${index})`;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return entry;
|
return replacer;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in new issue