Open-Source Wikis

/

Svelte

/

Features

/

Boundary and async

sveltejs/svelte

Boundary and async

Active contributors: Rich Harris, Dominic Gannaway, Simon H

Purpose

Svelte 5 has first-class support for async work in templates: {#await ...} blocks (since Svelte 3), top-level await in components, the {@async} block, and <svelte:boundary> for declarative error and pending UI. This page covers how those features fit together.

<svelte:boundary>

Implementation: packages/svelte/src/internal/client/dom/blocks/boundary.js (~13 KB).

A boundary captures errors thrown by descendants and pending Promises from async children, and renders the failed / pending snippets when triggered. The runtime hooks into the reactivity engine:

  • An Effect that sees an error in its child sub-graph propagates up until it finds an enclosing BoundaryEffect.
  • An async child (an await block, an async derived) suspends the boundary until it settles.
  • The boundary's pending snippet is rendered until the async work completes.

Compiler emit: packages/svelte/src/compiler/phases/3-transform/client/visitors/SvelteBoundary.js and the matching server visitor.

{#await} blocks

Existing-syntax await blocks render different children based on a Promise's state (pending, fulfilled, rejected). At runtime:

  • Client: packages/svelte/src/internal/client/dom/blocks/await.js. Tracks the Promise and switches branches on settle.
  • Server: packages/svelte/src/internal/server/blocks/await.js. Streams the resolved branch when the Promise settles.

Async runes and {@async}

Async-aware reactivity is gated on async_mode_flag in packages/svelte/src/internal/flags/async.js. The compiler imports svelte/internal/flags/async whenever it sees:

  • await at module/instance scope in runes mode.
  • await inside an expression in markup.
  • An {@async} block.

When the flag is on:

  • Reactions can be marked ASYNC (packages/svelte/src/internal/client/constants.js).
  • The Batch scheduler (internal/client/reactivity/batch.js) supports suspend() / resume() to defer flushes until pending Promises settle.
  • recent_async_deriveds in internal/client/reactivity/deriveds.js keeps a list of deriveds that haven't yet resolved.

CI exercises both modes:

  • The Tests job runs everything with async_mode_flag available.
  • The TestNoAsync job runs runtime-runes with SVELTE_NO_ASYNC=true (.github/workflows/ci.yml), which forces async_mode_flag to false so the legacy fast paths are exercised.

Error handling

packages/svelte/src/internal/client/error-handling.js provides handle_error(...). When an effect throws synchronously or rejects asynchronously, handle_error walks up the effect tree until it finds a boundary or hits the root. If no boundary is found, the error is rethrown to the host environment.

Server-side async

On the server, render() (packages/svelte/src/internal/server/index.js) collects async children as Promises in the Renderer queue and awaits them in order before flushing the parent. This keeps streaming output deterministic.

Key source files

File Purpose
packages/svelte/src/internal/client/dom/blocks/boundary.js <svelte:boundary> runtime.
packages/svelte/src/internal/client/dom/blocks/await.js {#await} block runtime (client).
packages/svelte/src/internal/client/dom/blocks/async.js {@async} block runtime.
packages/svelte/src/internal/client/error-handling.js Boundary error propagation.
packages/svelte/src/internal/client/reactivity/async.js Async reaction support glue.
packages/svelte/src/internal/server/blocks/await.js Server-side async streaming.
packages/svelte/src/internal/flags/async.js async_mode_flag toggle.
packages/svelte/src/internal/client/constants.js ASYNC, STALE_REACTION flags.

Entry points for modification

To change boundary semantics, edit internal/client/dom/blocks/boundary.js and the matching error propagation in error-handling.js. To change async scheduling, edit internal/client/reactivity/batch.js (look for suspend / resume) and internal/client/reactivity/async.js. Always run both async-on and async-off CI configurations locally:

pnpm test runtime-runes                  # async on
SVELTE_NO_ASYNC=true pnpm test runtime-runes  # async off

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Boundary and async – Svelte wiki | Factory