Component Script Effect Syntax
Relevant source files
The following files were used as context for generating this wiki page:
- skills/svelte-effect-runtime/references/syntax.md
- modules/svelte-effect-runtime/src/script-transform/index.ts
- modules/svelte-effect-runtime/src/compiler/source-scan.ts
- modules/svelte-effect-runtime/src/runtime/transform.ts
- modules/svelte-effect-runtime/src/diagnostics.ts
- skills/svelte-effect-runtime/SKILL.md
The Component Script Effect Syntax is a specialized extension of Svelte 5 component logic provided by the Svelte Effect Runtime (SER). It enables developers to use Effect programs directly within Svelte component scripts and markup using a direct yield* syntax. This is achieved through a compile-time transform that lowers effectful code into Svelte-compatible reactive declarations and runtime lifecycle management.
By using the <script effect> attribute, top-level executable code within the script block becomes "effectful," allowing for the direct consumption of asynchronous or generator-based effects without manually wrapping logic in onMount or Effect.runPromise callbacks.
Sources: skills/svelte-effect-runtime/references/syntax.md:1-10, modules/svelte-effect-runtime/src/script-transform/index.ts:33-40, skills/svelte-effect-runtime/SKILL.md:13-25
Script Effect Usage
To enable effectful execution in a component, the effect attribute must be added to the <script> tag. This signals the SER compiler to transform the content of that specific script block.
<script lang="ts" effect>
import { get_user } from "./user.remote";
let id = $state("ada");
// Top-level yield* is permitted here
const user = yield* get_user({ id });
</script>
Sources: skills/svelte-effect-runtime/references/syntax.md:5-13, modules/svelte-effect-runtime/src/compiler/source-scan.ts:68-80
Supported Script Forms
SER supports several patterns for integrating effects into component state and derivations:
| Pattern | Example |
|---|---|
| Reactive State | let user = $state(yield* getUser(id)); |
| Destructuring | const { title } = yield* get_post(id); |
| Derivations | let label = $derived((yield* format(user.name)).toUpperCase()); |
| Raw State | let raw = $state.raw(yield* load_raw(id)); |
| Assignments | count = yield* next_count(); |
Sources: skills/svelte-effect-runtime/references/syntax.md:20-28, modules/svelte-effect-runtime/src/script-transform/index.ts:33-40
Script Transformation Pipeline
The transformation of <script effect> blocks occurs in several phases, orchestrated by the transform_script_effect function. The process ensures that yield* expressions are lowered while preserving Svelte's reactivity model and managing the lifecycle of the resulting fibers.
The following flowchart illustrates the script transformation logic:
The diagram shows the sequence of scanning, lowering, and injecting code into the component script.
Sources: modules/svelte-effect-runtime/src/script-transform/index.ts:55-175
Key Transformation Components
- Source Scanning: The
scan_svelte_effect_sourcefunction identifies script regions, their attributes (likeeffect), and their content boundaries. - Statement Lowering: The
lower_statementfunction converts top-level statements containingyield*into SER runtime calls. - Runtime Binding: Names like
__SER___dispatcherand__SER___programare reserved to avoid conflicts with user-defined variables. - Import Injection: SER automatically injects necessary imports from
svelte,effect, andsvelte-effect-runtime/internal/generators.
Sources: modules/svelte-effect-runtime/src/script-transform/index.ts:79-115, modules/svelte-effect-runtime/src/compiler/source-scan.ts:145-175
Syntax Constraints and Diagnostics
SER enforces specific boundaries for where yield* can be used to ensure the generated code remains reactive and the Effect lifecycle can be managed effectively.
Prohibited Usage
The following patterns are considered invalid and will trigger compiler errors or warnings:
- Synchronous Rune Callbacks:
yield*cannot be used inside$effect(() => ...)or$derived.by(() => ...)because these are synchronous execution contexts in Svelte. - Class Members:
yield*is prohibited in class fields and methods as they are not top-level reactive work. - Event Callbacks: Writing
onclick={() => yield* save()}is invalid; theyield*must be at the attribute boundary:onclick={yield* save()}.
Sources: skills/svelte-effect-runtime/references/syntax.md:30-40, modules/svelte-effect-runtime/src/script-transform/index.ts:291-315, modules/svelte-effect-runtime/src/diagnostics.ts:133-145
Diagnostic Warnings
The find_svelte_effect_diagnostics function scans markup expressions to warn about improper usage:
| Diagnostic Case | Warning Message Detail |
|---|---|
| Hidden Event Yield | Detected yield* hidden inside an event callback. |
| Explicit Runner | Detected an explicit Effect runner inside Svelte markup (e.g. Effect.runPromise). |
| Bare Effect.gen | Detected Effect.gen used as a value instead of an Effect program. |
| Sync Markup Effect | Detected a markup expression that creates an Effect but is not written with yield*. |
Sources: modules/svelte-effect-runtime/src/diagnostics.ts:133-210
Runtime Lifecycle and Integration
When a script is transformed, the resulting code wires the effects into the component's lifecycle. Fibers created by effects in the script are automatically cancelled when the component unmounts.
This diagram represents how the SER Dispatcher manages the bridge between Svelte's lifecycle and Effect's fiber management.
Sources: modules/svelte-effect-runtime/src/script-transform/index.ts:160-170, skills/svelte-effect-runtime/SKILL.md:20-25
Summary
The Component Script Effect Syntax simplifies the integration of complex effectful logic into Svelte 5 components. By leveraging the <script effect> attribute and yield* syntax, developers can treat asynchronous operations as first-class reactive values. The system handles the underlying complexities of fiber management, lifecycle cancellation, and Svelte reactivity through a robust compile-time transform and diagnostic layer.
Sources: skills/svelte-effect-runtime/references/syntax.md:1-5, modules/svelte-effect-runtime/src/runtime/transform.ts:50-80