From 31882d1d2d948611d6826b5e9bf55a1d7fad6aa0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 28 Feb 2025 08:28:27 -0500 Subject: [PATCH] add `$effect.pending()` --- .../3-transform/client/visitors/CallExpression.js | 3 +++ .../3-transform/server/visitors/CallExpression.js | 4 ++++ packages/svelte/src/internal/client/index.js | 1 + .../svelte/src/internal/client/reactivity/forks.js | 13 +++++++++++++ packages/svelte/src/utils.js | 1 + 5 files changed, 22 insertions(+) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js index 7a3057451a..e7e20dc150 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js @@ -30,6 +30,9 @@ export function CallExpression(node, context) { .../** @type {Expression[]} */ (node.arguments.map((arg) => context.visit(arg))) ); + case '$effect.pending': + return b.call('$.get', b.id('$.pending')); + case '$inspect': case '$inspect().with': return transform_inspect_rune(node, context); diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js index 386c6b6ff3..727947be89 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js @@ -25,6 +25,10 @@ export function CallExpression(node, context) { return b.arrow([], b.block([])); } + if (rune === '$effect.pending') { + return b.false; + } + if (rune === '$state.snapshot') { return b.call( '$.snapshot', diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index a20e1f67dc..fea7ac1ada 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -115,6 +115,7 @@ export { user_effect, user_pre_effect } from './reactivity/effects.js'; +export { pending } from './reactivity/forks.js'; export { mutable_state, mutate, set, state, update, update_pre } from './reactivity/sources.js'; export { prop, diff --git a/packages/svelte/src/internal/client/reactivity/forks.js b/packages/svelte/src/internal/client/reactivity/forks.js index 19894db94f..1abefbfe34 100644 --- a/packages/svelte/src/internal/client/reactivity/forks.js +++ b/packages/svelte/src/internal/client/reactivity/forks.js @@ -1,6 +1,7 @@ /** @import { Effect, Source } from '#client' */ import { noop } from '../../shared/utils.js'; import { flushSync } from '../runtime.js'; +import { internal_set, source } from './sources.js'; /** @type {Set} */ const forks = new Set(); @@ -12,6 +13,12 @@ export function remove_active_fork() { active_fork = null; } +export let pending = source(false); + +function update_pending() { + internal_set(pending, forks.size > 0); +} + let uid = 1; export class Fork { @@ -97,6 +104,8 @@ export class Fork { } } } + + update_pending(); } /** @@ -134,6 +143,10 @@ export class Fork { static ensure() { if (active_fork === null) { + if (forks.size === 0) { + requestAnimationFrame(update_pending); + } + active_fork = new Fork(); forks.add(active_fork); // TODO figure out where we remove this } diff --git a/packages/svelte/src/utils.js b/packages/svelte/src/utils.js index d4d106d56d..bce4e091e2 100644 --- a/packages/svelte/src/utils.js +++ b/packages/svelte/src/utils.js @@ -441,6 +441,7 @@ const RUNES = /** @type {const} */ ([ '$effect.pre', '$effect.tracking', '$effect.root', + '$effect.pending', '$inspect', '$inspect().with', '$inspect.trace',