mirror of https://github.com/sveltejs/svelte
parent
591aeb0cbc
commit
7144f11b5b
@ -1,37 +1,24 @@
|
|||||||
/** @import { Effect, TemplateNode, Value } from '#client' */
|
/** @import { TemplateNode, Value } from '#client' */
|
||||||
import { DESTROYED } from '#client/constants';
|
import { flatten } from '../../reactivity/async.js';
|
||||||
import { async_derived } from '../../reactivity/deriveds.js';
|
import { get } from '../../runtime.js';
|
||||||
import { active_effect, get } from '../../runtime.js';
|
import { get_pending_boundary } from './boundary.js';
|
||||||
import { capture, get_pending_boundary } from './boundary.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {TemplateNode} node
|
* @param {TemplateNode} node
|
||||||
* @param {Array<() => Promise<any>>} expressions
|
* @param {Array<() => Promise<any>>} expressions
|
||||||
* @param {(anchor: TemplateNode, ...deriveds: Value[]) => void} fn
|
* @param {(anchor: TemplateNode, ...deriveds: Value[]) => void} fn
|
||||||
*/
|
*/
|
||||||
export async function async(node, expressions, fn) {
|
export function async(node, expressions, fn) {
|
||||||
// TODO handle hydration
|
|
||||||
|
|
||||||
var parent = /** @type {Effect} */ (active_effect);
|
|
||||||
|
|
||||||
var restore = capture();
|
|
||||||
var boundary = get_pending_boundary();
|
var boundary = get_pending_boundary();
|
||||||
|
|
||||||
|
// TODO why is this necessary? doesn't it happen inside `async_derived` inside `flatten`?
|
||||||
boundary.update_pending_count(1);
|
boundary.update_pending_count(1);
|
||||||
|
|
||||||
try {
|
flatten([], expressions, (values) => {
|
||||||
const deriveds = await Promise.all(expressions.map((fn) => async_derived(fn)));
|
// get values eagerly to avoid creating blocks if they reject
|
||||||
|
for (const d of values) get(d);
|
||||||
// get deriveds eagerly to avoid creating blocks if they reject
|
|
||||||
for (const d of deriveds) get(d);
|
|
||||||
|
|
||||||
if ((parent.f & DESTROYED) !== 0) return;
|
|
||||||
|
|
||||||
restore();
|
fn(node, ...values);
|
||||||
fn(node, ...deriveds);
|
|
||||||
} catch (error) {
|
|
||||||
boundary.error(error);
|
|
||||||
} finally {
|
|
||||||
boundary.update_pending_count(-1);
|
boundary.update_pending_count(-1);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/** @import { Effect, Value } from '#client' */
|
||||||
|
|
||||||
|
import { DESTROYED } from '#client/constants';
|
||||||
|
import { is_runes } from '../context.js';
|
||||||
|
import { capture, get_pending_boundary } from '../dom/blocks/boundary.js';
|
||||||
|
import { invoke_error_boundary } from '../error-handling.js';
|
||||||
|
import { active_effect } from '../runtime.js';
|
||||||
|
import { current_batch } from './batch.js';
|
||||||
|
import { async_derived, derived, derived_safe_equal } from './deriveds.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Array<() => any>} sync
|
||||||
|
* @param {Array<() => Promise<any>>} async
|
||||||
|
* @param {(values: Value[]) => any} fn
|
||||||
|
*/
|
||||||
|
export function flatten(sync, async, fn) {
|
||||||
|
const d = is_runes() ? derived : derived_safe_equal;
|
||||||
|
|
||||||
|
if (async.length > 0) {
|
||||||
|
var batch = current_batch;
|
||||||
|
var parent = /** @type {Effect} */ (active_effect);
|
||||||
|
|
||||||
|
var restore = capture();
|
||||||
|
|
||||||
|
var boundary = get_pending_boundary();
|
||||||
|
|
||||||
|
Promise.all(async.map((expression) => async_derived(expression)))
|
||||||
|
.then((result) => {
|
||||||
|
if ((parent.f & DESTROYED) !== 0) return;
|
||||||
|
|
||||||
|
batch?.restore();
|
||||||
|
|
||||||
|
restore();
|
||||||
|
|
||||||
|
try {
|
||||||
|
fn([...sync.map(d), ...result]);
|
||||||
|
} catch (error) {
|
||||||
|
invoke_error_boundary(error, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
batch?.flush();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
boundary.error(error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fn(sync.map(d));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue