svelte-effect-runtime 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dist/chunks/{client-BeOE81fW.js → client-zavjI3Qd.js} +9 -9
- package/.dist/chunks/client-zavjI3Qd.js.map +1 -0
- package/.dist/chunks/{dispatcher-BSg2-ttN.js → dispatcher-g0HYqHOK.js} +3 -3
- package/.dist/chunks/{dispatcher-BSg2-ttN.js.map → dispatcher-g0HYqHOK.js.map} +1 -1
- package/.dist/chunks/{preprocess-BZyUYWY7.js → preprocess-BeZqJxso.js} +242 -128
- package/.dist/chunks/preprocess-BeZqJxso.js.map +1 -0
- package/.dist/chunks/{transform-BtlxgJrg.js → transform-BguSlVDO.js} +64 -17
- package/.dist/chunks/transform-BguSlVDO.js.map +1 -0
- package/.dist/dispatcher.js +1 -1
- package/.dist/error.d.ts +26 -14
- package/.dist/internal/generators.js +1 -1
- package/.dist/internal/remote-client.js +1 -1
- package/.dist/markup/promise.js +1 -1
- package/.dist/markup/run.js +1 -1
- package/.dist/markup/transform.js +1 -1
- package/.dist/markup/value.js +1 -1
- package/.dist/mod.d.ts +1 -1
- package/.dist/mod.js +2 -2
- package/.dist/mod.js.map +1 -1
- package/.dist/preprocess/imports.d.ts +1 -2
- package/.dist/preprocess/index.d.ts +1 -1
- package/.dist/preprocess/lower.d.ts +1 -1
- package/.dist/preprocess/runes.d.ts +24 -0
- package/.dist/preprocess/runtime-block.d.ts +5 -4
- package/.dist/preprocess/types.d.ts +15 -3
- package/.dist/preprocess.js +2 -2
- package/.dist/remote/client.js +1 -1
- package/.dist/remote/server.js +3 -3
- package/.dist/remote/server.js.map +1 -1
- package/.dist/runtime/preprocess.js +2 -2
- package/.dist/server.js +8 -8
- package/.dist/server.js.map +1 -1
- package/package.json +1 -1
- package/.dist/chunks/client-BeOE81fW.js.map +0 -1
- package/.dist/chunks/preprocess-BZyUYWY7.js.map +0 -1
- package/.dist/chunks/transform-BtlxgJrg.js.map +0 -1
|
@@ -1,7 +1,117 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { i as collect_free_identifiers, n as AsyncEffectInSyncRuneError, r as AwaitInEffectWorkError } from "./transform-BguSlVDO.js";
|
|
2
2
|
import { contains_top_level_yield_star } from "../detect.js";
|
|
3
3
|
import MagicString from "magic-string";
|
|
4
4
|
import ts from "typescript";
|
|
5
|
+
//#region src/preprocess/imports.ts
|
|
6
|
+
/**
|
|
7
|
+
* Builds the import statements injected by the script preprocessor.
|
|
8
|
+
*
|
|
9
|
+
* @since 2.0.0
|
|
10
|
+
* @param has_effect_import - Whether the user already imports `Effect`.
|
|
11
|
+
* @param has_dispatcher_import - Whether the user already imports
|
|
12
|
+
* `get_dispatcher`.
|
|
13
|
+
* @returns Newline-separated import statements to inject.
|
|
14
|
+
*/
|
|
15
|
+
function make_imports(has_effect_import, has_dispatcher_import) {
|
|
16
|
+
return [!has_effect_import && `import { Effect } from "effect";`, !has_dispatcher_import && `import { get_dispatcher } from "svelte-effect-runtime/internal/generators";`].filter(Boolean).join("\n");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Checks whether a source file imports a local binding from a module.
|
|
20
|
+
*
|
|
21
|
+
* @since 2.0.0
|
|
22
|
+
* @param source_file - Parsed TypeScript source file to inspect.
|
|
23
|
+
* @param module_name - Module specifier to match.
|
|
24
|
+
* @param local_name - Local binding name to look for.
|
|
25
|
+
* @returns Whether that binding is already locally available.
|
|
26
|
+
*/
|
|
27
|
+
function has_local_import_binding(source_file, module_name, local_name) {
|
|
28
|
+
return source_file.statements.some((stmt) => {
|
|
29
|
+
if (!ts.isImportDeclaration(stmt) || !ts.isStringLiteral(stmt.moduleSpecifier) || stmt.moduleSpecifier.text !== module_name) return false;
|
|
30
|
+
const clause = stmt.importClause;
|
|
31
|
+
if (!clause) return false;
|
|
32
|
+
if (clause.name?.text === local_name) return true;
|
|
33
|
+
const named_bindings = clause.namedBindings;
|
|
34
|
+
if (!named_bindings) return false;
|
|
35
|
+
if (ts.isNamespaceImport(named_bindings)) return named_bindings.name.text === local_name;
|
|
36
|
+
return named_bindings.elements.some((element) => element.name.text === local_name);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/preprocess/source.ts
|
|
41
|
+
/**
|
|
42
|
+
* Creates a source map from transformed script back to the original block.
|
|
43
|
+
*
|
|
44
|
+
* @since 2.0.0
|
|
45
|
+
* @param magic - MagicString instance holding the transformed source.
|
|
46
|
+
* @param filename - Source filename used for the source map entry.
|
|
47
|
+
* @returns A plain source map object.
|
|
48
|
+
*/
|
|
49
|
+
function create_source_map(magic, filename) {
|
|
50
|
+
return magic.generateMap({
|
|
51
|
+
hires: true,
|
|
52
|
+
includeContent: true,
|
|
53
|
+
source: filename
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Slices a substring matching a node's full source range.
|
|
58
|
+
*
|
|
59
|
+
* @since 2.0.0
|
|
60
|
+
* @param content - Original source text.
|
|
61
|
+
* @param node - AST node whose full range should be extracted.
|
|
62
|
+
* @returns Source text including leading trivia.
|
|
63
|
+
*/
|
|
64
|
+
function slice(content, node) {
|
|
65
|
+
return content.slice(node.getFullStart(), node.end);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Slices a substring matching a node's source range without leading trivia.
|
|
69
|
+
*
|
|
70
|
+
* @since 2.0.0
|
|
71
|
+
* @param content - Original source text.
|
|
72
|
+
* @param node - AST node whose non-trivia range should be extracted.
|
|
73
|
+
* @returns Source text excluding leading trivia.
|
|
74
|
+
*/
|
|
75
|
+
function slice_start(content, node) {
|
|
76
|
+
return content.slice(node.getStart(), node.end);
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/preprocess/runtime-block.ts
|
|
80
|
+
/**
|
|
81
|
+
* Builds the runtime blocks appended to lowered script effect code.
|
|
82
|
+
*
|
|
83
|
+
* @since 2.0.0
|
|
84
|
+
* @param blocks - Effect bodies and dependency reads to emit.
|
|
85
|
+
* @returns Full `$effect` blocks that fork generated `Effect.gen` programs.
|
|
86
|
+
*/
|
|
87
|
+
function make_runtime_block(blocks) {
|
|
88
|
+
const merged_block = merge_effect_blocks(blocks);
|
|
89
|
+
const dep_reads = merged_block.deps.length === 0 ? [] : [` void [${merged_block.deps.join(", ")}];`];
|
|
90
|
+
const body = merged_block.statements.map((statement) => ` ${statement}`).join("\n");
|
|
91
|
+
return [
|
|
92
|
+
"",
|
|
93
|
+
"$effect(() => {",
|
|
94
|
+
...dep_reads,
|
|
95
|
+
" const __SER__dispatcher = get_dispatcher();",
|
|
96
|
+
" const __SER__program = Effect.gen(function* () {",
|
|
97
|
+
body,
|
|
98
|
+
" });",
|
|
99
|
+
" const __SER__cancel = __SER__dispatcher.fork(__SER__program);",
|
|
100
|
+
" import.meta.hot?.dispose(__SER__cancel);",
|
|
101
|
+
" return __SER__cancel;",
|
|
102
|
+
"});",
|
|
103
|
+
""
|
|
104
|
+
].join("\n");
|
|
105
|
+
}
|
|
106
|
+
function merge_effect_blocks(blocks) {
|
|
107
|
+
const statements = blocks.flatMap((block) => block.statements);
|
|
108
|
+
const deps = blocks.flatMap((block) => block.deps);
|
|
109
|
+
return {
|
|
110
|
+
statements,
|
|
111
|
+
deps: [...new Set(deps)]
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
5
115
|
//#region src/preprocess/ast.ts
|
|
6
116
|
/**
|
|
7
117
|
* Checks whether a node is a `yield*` binary expression.
|
|
@@ -87,83 +197,79 @@ function extract_binding_names(name) {
|
|
|
87
197
|
return result;
|
|
88
198
|
}
|
|
89
199
|
//#endregion
|
|
90
|
-
//#region src/preprocess/
|
|
200
|
+
//#region src/preprocess/runes.ts
|
|
201
|
+
const ASYNC_EXPRESSION_RUNES = new Set([
|
|
202
|
+
"$derived",
|
|
203
|
+
"$inspect",
|
|
204
|
+
"$state",
|
|
205
|
+
"$state.raw"
|
|
206
|
+
]);
|
|
207
|
+
const CALLBACK_RUNES = new Set([
|
|
208
|
+
"$derived.by",
|
|
209
|
+
"$effect",
|
|
210
|
+
"$effect.pre",
|
|
211
|
+
"$effect.root"
|
|
212
|
+
]);
|
|
91
213
|
/**
|
|
92
|
-
*
|
|
214
|
+
* Validates that `yield*` only appears in rune positions the script-effect
|
|
215
|
+
* transform can lower without changing the rune's normal Svelte contract.
|
|
93
216
|
*
|
|
94
217
|
* @since 2.0.0
|
|
95
|
-
* @param
|
|
96
|
-
* @param
|
|
97
|
-
* @param
|
|
98
|
-
*
|
|
99
|
-
* @returns Newline-separated import statements to inject.
|
|
218
|
+
* @param node - AST node to scan.
|
|
219
|
+
* @param content - Original script source used for diagnostics.
|
|
220
|
+
* @param filename - Source filename used for diagnostics.
|
|
221
|
+
* @returns Nothing.
|
|
100
222
|
*/
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
!has_onmount_import && `import { onMount } from "svelte";`,
|
|
104
|
-
!has_effect_import && `import { Effect } from "effect";`,
|
|
105
|
-
!has_dispatcher_import && `import { get_dispatcher } from "svelte-effect-runtime/internal/generators";`
|
|
106
|
-
].filter(Boolean).join("\n");
|
|
223
|
+
function validate_rune_yield_usage(node, content, filename) {
|
|
224
|
+
visit_rune_yield_usage(node, content, filename);
|
|
107
225
|
}
|
|
108
226
|
/**
|
|
109
|
-
*
|
|
227
|
+
* Identifies `$state(...)` and `$state.raw(...)` initializer calls.
|
|
110
228
|
*
|
|
111
229
|
* @since 2.0.0
|
|
112
|
-
* @param
|
|
113
|
-
* @param
|
|
114
|
-
* @
|
|
115
|
-
* @returns Whether that binding is already locally available.
|
|
230
|
+
* @param expr - Expression to classify.
|
|
231
|
+
* @param content - Original script source used to preserve argument text.
|
|
232
|
+
* @returns State rune details when the expression is a state initializer.
|
|
116
233
|
*/
|
|
117
|
-
function
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
});
|
|
234
|
+
function get_state_rune_initializer(expr, content) {
|
|
235
|
+
if (!ts.isCallExpression(expr)) return;
|
|
236
|
+
const rune_name = get_rune_name(expr.expression);
|
|
237
|
+
if (rune_name !== "$state" && rune_name !== "$state.raw") return;
|
|
238
|
+
const first_arg = expr.arguments[0];
|
|
239
|
+
if (!first_arg) return;
|
|
240
|
+
return {
|
|
241
|
+
rune_name,
|
|
242
|
+
value_text: slice(content, first_arg).trim()
|
|
243
|
+
};
|
|
128
244
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
*
|
|
134
|
-
* @since 2.0.0
|
|
135
|
-
* @param magic - MagicString instance holding the transformed source.
|
|
136
|
-
* @param filename - Source filename used for the source map entry.
|
|
137
|
-
* @returns A plain source map object.
|
|
138
|
-
*/
|
|
139
|
-
function create_source_map(magic, filename) {
|
|
140
|
-
return magic.generateMap({
|
|
141
|
-
hires: true,
|
|
142
|
-
includeContent: true,
|
|
143
|
-
source: filename
|
|
245
|
+
function visit_rune_yield_usage(node, content, filename) {
|
|
246
|
+
if (ts.isCallExpression(node)) validate_call_expression(node, content, filename);
|
|
247
|
+
node.forEachChild((child) => {
|
|
248
|
+
visit_rune_yield_usage(child, content, filename);
|
|
144
249
|
});
|
|
145
250
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
function slice(content, node) {
|
|
155
|
-
return content.slice(node.getFullStart(), node.end);
|
|
251
|
+
function validate_call_expression(call, content, filename) {
|
|
252
|
+
const rune_name = get_rune_name(call.expression);
|
|
253
|
+
if (!rune_name) return;
|
|
254
|
+
if (!ASYNC_EXPRESSION_RUNES.has(rune_name) && contains_top_level_yield_star(call)) throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
|
|
255
|
+
if (!CALLBACK_RUNES.has(rune_name)) return;
|
|
256
|
+
const callback = call.arguments[0];
|
|
257
|
+
if (!callback || !callback_has_top_level_yield_star(callback)) return;
|
|
258
|
+
throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
|
|
156
259
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return
|
|
260
|
+
function callback_has_top_level_yield_star(node) {
|
|
261
|
+
if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node)) && node.body !== void 0) return contains_top_level_yield_star(node.body);
|
|
262
|
+
return contains_top_level_yield_star(node);
|
|
263
|
+
}
|
|
264
|
+
function get_rune_name(expr) {
|
|
265
|
+
if (ts.isIdentifier(expr) && is_rune_root(expr.text)) return expr.text;
|
|
266
|
+
if (!ts.isPropertyAccessExpression(expr)) return;
|
|
267
|
+
const root_name = get_rune_name(expr.expression);
|
|
268
|
+
if (!root_name) return;
|
|
269
|
+
return `${root_name}.${expr.name.text}`;
|
|
270
|
+
}
|
|
271
|
+
function is_rune_root(name) {
|
|
272
|
+
return name === "$bindable" || name === "$derived" || name === "$effect" || name === "$host" || name === "$inspect" || name === "$props" || name === "$state";
|
|
167
273
|
}
|
|
168
274
|
//#endregion
|
|
169
275
|
//#region src/preprocess/lower.ts
|
|
@@ -179,10 +285,11 @@ function slice_start(content, node) {
|
|
|
179
285
|
function lower_statement(stmt, content, context) {
|
|
180
286
|
if (ts.isExpressionStatement(stmt)) return lower_expression_statement(stmt, content, context);
|
|
181
287
|
if (ts.isVariableStatement(stmt)) return lower_variable_statement(stmt, content, context);
|
|
288
|
+
const text = slice(content, stmt);
|
|
182
289
|
return {
|
|
183
290
|
temps: [],
|
|
184
291
|
rewritten_text: "",
|
|
185
|
-
|
|
292
|
+
effect_blocks: [make_effect_block([text], collect_deps(text))],
|
|
186
293
|
range: {
|
|
187
294
|
start: stmt.getFullStart(),
|
|
188
295
|
end: stmt.end
|
|
@@ -192,7 +299,8 @@ function lower_statement(stmt, content, context) {
|
|
|
192
299
|
function lower_variable_statement(stmt, content, context) {
|
|
193
300
|
const temps = [];
|
|
194
301
|
const rewritten_decls = [];
|
|
195
|
-
const
|
|
302
|
+
const statements = [];
|
|
303
|
+
const deps = [];
|
|
196
304
|
const decl_list = stmt.declarationList;
|
|
197
305
|
const kind = (decl_list.flags & ts.NodeFlags.Let) !== 0 ? "let" : "const";
|
|
198
306
|
let has_bare_yield = false;
|
|
@@ -210,11 +318,23 @@ function lower_variable_statement(stmt, content, context) {
|
|
|
210
318
|
has_bare_yield = true;
|
|
211
319
|
rewritten_decls.push(`${original_name} = $derived(${temp_name})`);
|
|
212
320
|
const yield_text = extract_yield_star_full_text(decl.initializer, content);
|
|
213
|
-
|
|
321
|
+
statements.push(`${temp_name} = ${yield_text};`);
|
|
322
|
+
deps.push(...collect_deps(yield_text));
|
|
214
323
|
} else {
|
|
324
|
+
const state_rune = get_state_rune_initializer(decl.initializer, content);
|
|
325
|
+
if (state_rune) {
|
|
326
|
+
has_bare_yield = true;
|
|
327
|
+
rewritten_decls.push(`${original_name} = ${state_rune.rune_name}(undefined)`);
|
|
328
|
+
statements.push(`${original_name} = ${state_rune.value_text};`);
|
|
329
|
+
deps.push(...collect_deps(state_rune.value_text));
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
215
332
|
const lowered = lower_expression_yields(decl.initializer, content, original_name, context);
|
|
216
333
|
temps.push(...lowered.temps);
|
|
217
|
-
|
|
334
|
+
for (const block of lowered.effect_blocks) {
|
|
335
|
+
statements.push(...block.statements);
|
|
336
|
+
deps.push(...block.deps);
|
|
337
|
+
}
|
|
218
338
|
const rewritten_expr = rewrite_state_rune_as_derived(lowered.rewritten_expr);
|
|
219
339
|
rewritten_decls.push(`${original_name} = ${rewritten_expr}`);
|
|
220
340
|
}
|
|
@@ -225,14 +345,15 @@ function lower_variable_statement(stmt, content, context) {
|
|
|
225
345
|
temps.push({ name: temp_name });
|
|
226
346
|
temps.push(...names.map((name) => ({ name })));
|
|
227
347
|
const yield_text = extract_yield_star_full_text(decl.initializer, content);
|
|
228
|
-
|
|
229
|
-
|
|
348
|
+
statements.push(`${temp_name} = ${yield_text};`);
|
|
349
|
+
statements.push(`(${binding_text} = ${temp_name});`);
|
|
350
|
+
deps.push(...collect_deps(yield_text));
|
|
230
351
|
}
|
|
231
352
|
}
|
|
232
353
|
return {
|
|
233
354
|
temps,
|
|
234
355
|
rewritten_text: rewritten_decls.length === 0 ? "" : `${has_bare_yield ? "let" : kind} ${rewritten_decls.join(", ")};`,
|
|
235
|
-
|
|
356
|
+
effect_blocks: statements.length === 0 ? [] : [make_effect_block(statements, deps)],
|
|
236
357
|
range: {
|
|
237
358
|
start: stmt.getStart(),
|
|
238
359
|
end: stmt.end
|
|
@@ -244,35 +365,42 @@ function lower_expression_statement(stmt, content, context) {
|
|
|
244
365
|
if (!contains_top_level_yield_star(expr)) return {
|
|
245
366
|
temps: [],
|
|
246
367
|
rewritten_text: slice(content, stmt).trim(),
|
|
247
|
-
|
|
248
|
-
range: {
|
|
249
|
-
start: stmt.getStart(),
|
|
250
|
-
end: stmt.end
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
if (is_yield_star_expression(expr)) return {
|
|
254
|
-
temps: [],
|
|
255
|
-
rewritten_text: "",
|
|
256
|
-
effect_assignments: [slice(content, expr).trim() + ";"],
|
|
257
|
-
range: {
|
|
258
|
-
start: stmt.getFullStart(),
|
|
259
|
-
end: stmt.end
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
if (ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.EqualsToken) return {
|
|
263
|
-
temps: [],
|
|
264
|
-
rewritten_text: "",
|
|
265
|
-
effect_assignments: [`${slice(content, expr.left).trim()} = ${extract_yield_star_full_text(expr, content)};`],
|
|
368
|
+
effect_blocks: [],
|
|
266
369
|
range: {
|
|
267
370
|
start: stmt.getStart(),
|
|
268
371
|
end: stmt.end
|
|
269
372
|
}
|
|
270
373
|
};
|
|
374
|
+
if (is_yield_star_expression(expr)) {
|
|
375
|
+
const text = slice(content, expr).trim();
|
|
376
|
+
return {
|
|
377
|
+
temps: [],
|
|
378
|
+
rewritten_text: "",
|
|
379
|
+
effect_blocks: [make_effect_block([text + ";"], collect_deps(text))],
|
|
380
|
+
range: {
|
|
381
|
+
start: stmt.getFullStart(),
|
|
382
|
+
end: stmt.end
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if (ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
387
|
+
const target = slice(content, expr.left).trim();
|
|
388
|
+
const yield_text = extract_yield_star_full_text(expr, content);
|
|
389
|
+
return {
|
|
390
|
+
temps: [],
|
|
391
|
+
rewritten_text: "",
|
|
392
|
+
effect_blocks: [make_effect_block([`${target} = ${yield_text};`], collect_deps(yield_text))],
|
|
393
|
+
range: {
|
|
394
|
+
start: stmt.getStart(),
|
|
395
|
+
end: stmt.end
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
271
399
|
const lowered = lower_expression_yields(expr, content, "call", context);
|
|
272
400
|
return {
|
|
273
401
|
temps: lowered.temps,
|
|
274
402
|
rewritten_text: lowered.rewritten_expr + ";",
|
|
275
|
-
|
|
403
|
+
effect_blocks: lowered.effect_blocks,
|
|
276
404
|
range: {
|
|
277
405
|
start: stmt.getStart(),
|
|
278
406
|
end: stmt.end
|
|
@@ -282,12 +410,14 @@ function lower_expression_statement(stmt, content, context) {
|
|
|
282
410
|
function lower_expression_yields(expr, content, hint, context) {
|
|
283
411
|
const replacements = [];
|
|
284
412
|
const temps = [];
|
|
285
|
-
const
|
|
413
|
+
const statements = [];
|
|
414
|
+
const deps = [];
|
|
286
415
|
collect_yield_star_nodes(expr, (node) => {
|
|
287
416
|
const temp_name = context.next_temp_name(hint);
|
|
288
417
|
const yield_text = slice_start(content, node).trim();
|
|
289
418
|
temps.push({ name: temp_name });
|
|
290
|
-
|
|
419
|
+
statements.push(`${temp_name} = ${yield_text};`);
|
|
420
|
+
deps.push(...collect_deps(yield_text));
|
|
291
421
|
replacements.push({
|
|
292
422
|
start: node.getStart(),
|
|
293
423
|
end: node.end,
|
|
@@ -297,7 +427,7 @@ function lower_expression_yields(expr, content, hint, context) {
|
|
|
297
427
|
if (replacements.length === 0) return {
|
|
298
428
|
temps,
|
|
299
429
|
rewritten_expr: slice(content, expr).trim(),
|
|
300
|
-
|
|
430
|
+
effect_blocks: []
|
|
301
431
|
};
|
|
302
432
|
replacements.sort((a, b) => b.start - a.start);
|
|
303
433
|
let text = slice(content, expr);
|
|
@@ -306,7 +436,7 @@ function lower_expression_yields(expr, content, hint, context) {
|
|
|
306
436
|
return {
|
|
307
437
|
temps,
|
|
308
438
|
rewritten_expr: text.trim(),
|
|
309
|
-
|
|
439
|
+
effect_blocks: [make_effect_block(statements, deps)]
|
|
310
440
|
};
|
|
311
441
|
}
|
|
312
442
|
function rewrite_state_rune_as_derived(expression) {
|
|
@@ -321,37 +451,21 @@ function extract_yield_star_full_text(expr, content) {
|
|
|
321
451
|
});
|
|
322
452
|
return found ?? "undefined";
|
|
323
453
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
*/
|
|
333
|
-
function make_runtime_block(assignments) {
|
|
334
|
-
return [
|
|
335
|
-
"",
|
|
336
|
-
"const __SER__program = Effect.gen(function* () {",
|
|
337
|
-
assignments.map((assignment) => ` ${assignment}`).join("\n"),
|
|
338
|
-
"});",
|
|
339
|
-
"",
|
|
340
|
-
"onMount(() => {",
|
|
341
|
-
" const __SER__dispatcher = get_dispatcher();",
|
|
342
|
-
" const __SER__cancel = __SER__dispatcher.fork(__SER__program);",
|
|
343
|
-
" import.meta.hot?.dispose(__SER__cancel);",
|
|
344
|
-
" return __SER__cancel;",
|
|
345
|
-
"});",
|
|
346
|
-
""
|
|
347
|
-
].join("\n");
|
|
454
|
+
function make_effect_block(statements, deps) {
|
|
455
|
+
return {
|
|
456
|
+
statements,
|
|
457
|
+
deps: [...new Set(deps)]
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function collect_deps(expr_text) {
|
|
461
|
+
return collect_free_identifiers(expr_text).filter((identifier) => !identifier.startsWith("__SER__"));
|
|
348
462
|
}
|
|
349
463
|
//#endregion
|
|
350
464
|
//#region src/preprocess/index.ts
|
|
351
465
|
/**
|
|
352
466
|
* Transforms a `<script effect>` body by extracting top-level `yield*`
|
|
353
467
|
* expressions into `$state` temp bindings and wrapping the lowered
|
|
354
|
-
* assignments in
|
|
468
|
+
* assignments in a dependency-tracked `$effect` block.
|
|
355
469
|
*
|
|
356
470
|
* @example
|
|
357
471
|
* ```ts
|
|
@@ -370,7 +484,7 @@ function transform_script_effect(content, filename) {
|
|
|
370
484
|
let temp_counter = 0;
|
|
371
485
|
const source_file = ts.createSourceFile(filename, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
372
486
|
const magic = new MagicString(content);
|
|
373
|
-
const
|
|
487
|
+
const effect_blocks = [];
|
|
374
488
|
const block_refs = [];
|
|
375
489
|
let has_effect = false;
|
|
376
490
|
const context = { next_temp_name(hint) {
|
|
@@ -381,12 +495,12 @@ function transform_script_effect(content, filename) {
|
|
|
381
495
|
} };
|
|
382
496
|
/** Phase 1: detect imports already provided by the user. */
|
|
383
497
|
const has_effect_import = has_local_import_binding(source_file, "effect", "Effect");
|
|
384
|
-
const has_onmount_import = has_local_import_binding(source_file, "svelte", "onMount");
|
|
385
498
|
const has_dispatcher_import = has_local_import_binding(source_file, "svelte-effect-runtime/internal/generators", "get_dispatcher");
|
|
386
499
|
/** Phase 2: lower every top-level statement that contains `yield*`. */
|
|
387
500
|
for (const stmt of source_file.statements) {
|
|
388
|
-
|
|
501
|
+
validate_rune_yield_usage(stmt, content, filename);
|
|
389
502
|
if (!contains_top_level_yield_star(stmt)) continue;
|
|
503
|
+
if (contains_top_level_await(stmt)) throw new AwaitInEffectWorkError(filename, slice(content, stmt));
|
|
390
504
|
has_effect = true;
|
|
391
505
|
const lowered = lower_statement(stmt, content, context);
|
|
392
506
|
magic.overwrite(lowered.range.start, lowered.range.end, lowered.rewritten_text);
|
|
@@ -394,7 +508,7 @@ function transform_script_effect(content, filename) {
|
|
|
394
508
|
const prefix = lowered.temps.map((temp) => `let ${temp.name} = $state(undefined);`).join("\n");
|
|
395
509
|
magic.appendLeft(lowered.range.start, prefix + "\n");
|
|
396
510
|
}
|
|
397
|
-
|
|
511
|
+
effect_blocks.push(...lowered.effect_blocks);
|
|
398
512
|
}
|
|
399
513
|
if (!has_effect) {
|
|
400
514
|
block_refs.push({
|
|
@@ -407,12 +521,12 @@ function transform_script_effect(content, filename) {
|
|
|
407
521
|
};
|
|
408
522
|
}
|
|
409
523
|
/** Phase 3: inject runtime imports after the last user import. */
|
|
410
|
-
const imports = make_imports(has_effect_import,
|
|
524
|
+
const imports = make_imports(has_effect_import, has_dispatcher_import);
|
|
411
525
|
const last_import = [...source_file.statements].reverse().find(ts.isImportDeclaration);
|
|
412
526
|
if (last_import) magic.appendRight(last_import.end, "\n" + imports);
|
|
413
527
|
else magic.prepend(imports + "\n");
|
|
414
528
|
/** Phase 4: append the runtime program and lifecycle wiring. */
|
|
415
|
-
const runtime_block = make_runtime_block(
|
|
529
|
+
const runtime_block = make_runtime_block(effect_blocks);
|
|
416
530
|
magic.append("\n" + runtime_block);
|
|
417
531
|
block_refs.push({
|
|
418
532
|
id: filename,
|
|
@@ -427,4 +541,4 @@ function transform_script_effect(content, filename) {
|
|
|
427
541
|
//#endregion
|
|
428
542
|
export { transform_script_effect as t };
|
|
429
543
|
|
|
430
|
-
//# sourceMappingURL=preprocess-
|
|
544
|
+
//# sourceMappingURL=preprocess-BeZqJxso.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preprocess-BeZqJxso.js","names":[],"sources":["../../../modules/svelte-effect-runtime/src/preprocess/imports.ts","../../../modules/svelte-effect-runtime/src/preprocess/source.ts","../../../modules/svelte-effect-runtime/src/preprocess/runtime-block.ts","../../../modules/svelte-effect-runtime/src/preprocess/ast.ts","../../../modules/svelte-effect-runtime/src/preprocess/runes.ts","../../../modules/svelte-effect-runtime/src/preprocess/lower.ts","../../../modules/svelte-effect-runtime/src/preprocess/index.ts"],"sourcesContent":["import ts from \"typescript\";\n\n/**\n * Builds the import statements injected by the script preprocessor.\n *\n * @since 2.0.0\n * @param has_effect_import - Whether the user already imports `Effect`.\n * @param has_dispatcher_import - Whether the user already imports\n * `get_dispatcher`.\n * @returns Newline-separated import statements to inject.\n */\nexport function make_imports(\n has_effect_import: boolean,\n has_dispatcher_import: boolean,\n): string {\n return [\n !has_effect_import && `import { Effect } from \"effect\";`,\n !has_dispatcher_import &&\n `import { get_dispatcher } from \"svelte-effect-runtime/internal/generators\";`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\n/**\n * Checks whether a source file imports a local binding from a module.\n *\n * @since 2.0.0\n * @param source_file - Parsed TypeScript source file to inspect.\n * @param module_name - Module specifier to match.\n * @param local_name - Local binding name to look for.\n * @returns Whether that binding is already locally available.\n */\nexport function has_local_import_binding(\n source_file: ts.SourceFile,\n module_name: string,\n local_name: string,\n): boolean {\n return source_file.statements.some((stmt) => {\n if (\n !ts.isImportDeclaration(stmt) ||\n !ts.isStringLiteral(stmt.moduleSpecifier) ||\n stmt.moduleSpecifier.text !== module_name\n ) {\n return false;\n }\n\n const clause = stmt.importClause;\n\n if (!clause) {\n return false;\n }\n\n if (clause.name?.text === local_name) {\n return true;\n }\n\n const named_bindings = clause.namedBindings;\n\n if (!named_bindings) {\n return false;\n }\n\n if (ts.isNamespaceImport(named_bindings)) {\n return named_bindings.name.text === local_name;\n }\n\n return named_bindings.elements.some(\n (element) => element.name.text === local_name,\n );\n });\n}\n","import type MagicString from \"magic-string\";\nimport type ts from \"typescript\";\n\n/**\n * Creates a source map from transformed script back to the original block.\n *\n * @since 2.0.0\n * @param magic - MagicString instance holding the transformed source.\n * @param filename - Source filename used for the source map entry.\n * @returns A plain source map object.\n */\nexport function create_source_map(\n magic: MagicString,\n filename: string,\n): Record<string, unknown> {\n const map = magic.generateMap({\n hires: true,\n includeContent: true,\n source: filename,\n });\n\n return map as unknown as Record<string, unknown>;\n}\n\n/**\n * Slices a substring matching a node's full source range.\n *\n * @since 2.0.0\n * @param content - Original source text.\n * @param node - AST node whose full range should be extracted.\n * @returns Source text including leading trivia.\n */\nexport function slice(content: string, node: ts.Node): string {\n return content.slice(node.getFullStart(), node.end);\n}\n\n/**\n * Slices a substring matching a node's source range without leading trivia.\n *\n * @since 2.0.0\n * @param content - Original source text.\n * @param node - AST node whose non-trivia range should be extracted.\n * @returns Source text excluding leading trivia.\n */\nexport function slice_start(content: string, node: ts.Node): string {\n return content.slice(node.getStart(), node.end);\n}\n","import type { EffectBlock } from \"./types.ts\";\n\n/**\n * Builds the runtime blocks appended to lowered script effect code.\n *\n * @since 2.0.0\n * @param blocks - Effect bodies and dependency reads to emit.\n * @returns Full `$effect` blocks that fork generated `Effect.gen` programs.\n */\nexport function make_runtime_block(blocks: EffectBlock[]): string {\n const merged_block = merge_effect_blocks(blocks);\n const dep_reads = merged_block.deps.length === 0\n ? []\n : [` void [${merged_block.deps.join(\", \")}];`];\n\n const body = merged_block.statements\n .map((statement) => ` ${statement}`)\n .join(\"\\n\");\n\n return [\n \"\",\n \"$effect(() => {\",\n ...dep_reads,\n \" const __SER__dispatcher = get_dispatcher();\",\n \" const __SER__program = Effect.gen(function* () {\",\n body,\n \" });\",\n \" const __SER__cancel = __SER__dispatcher.fork(__SER__program);\",\n \" import.meta.hot?.dispose(__SER__cancel);\",\n \" return __SER__cancel;\",\n \"});\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction merge_effect_blocks(blocks: EffectBlock[]): EffectBlock {\n const statements = blocks.flatMap((block) => block.statements);\n const deps = blocks.flatMap((block) => block.deps);\n\n return {\n statements,\n deps: [...new Set(deps)],\n };\n}\n","import ts from \"typescript\";\n\n/**\n * Checks whether a node is a `yield*` binary expression.\n *\n * @since 2.0.0\n * @param node - TypeScript AST node to check.\n * @returns Whether the node represents `yield * operand`.\n */\nexport function is_yield_star_expression(node: ts.Node): boolean {\n return (\n ts.isBinaryExpression(node) &&\n node.operatorToken.kind === ts.SyntaxKind.AsteriskToken &&\n ts.isIdentifier(node.left) &&\n node.left.text === \"yield\"\n );\n}\n\n/**\n * Checks whether a node owns its own yield semantics.\n *\n * @since 2.0.0\n * @param node - TypeScript AST node to check.\n * @returns Whether traversal should stop at this function boundary.\n */\nexport function is_function_boundary_node(node: ts.Node): boolean {\n return (\n ts.isArrowFunction(node) ||\n ts.isFunctionDeclaration(node) ||\n ts.isFunctionExpression(node) ||\n ts.isMethodDeclaration(node) ||\n ts.isGetAccessorDeclaration(node) ||\n ts.isSetAccessorDeclaration(node)\n );\n}\n\n/**\n * Returns `true` if the node tree contains a top-level `await`.\n *\n * @since 2.0.0\n * @param node - Root node to search.\n * @returns Whether a top-level await expression was found.\n */\nexport function contains_top_level_await(node: ts.Node): boolean {\n if (ts.isAwaitExpression(node)) {\n return true;\n }\n\n return node.getChildren().some(\n (child) =>\n !is_function_boundary_node(child) && contains_top_level_await(child),\n );\n}\n\n/**\n * Collects top-level `yield*` nodes under an expression.\n *\n * @since 2.0.0\n * @param node - Root node to search.\n * @param on_found - Callback invoked for each matching yield node.\n * @returns Nothing.\n */\nexport function collect_yield_star_nodes(\n node: ts.Node,\n on_found: (node: ts.Node) => void,\n): void {\n if (is_function_boundary_node(node)) {\n return;\n }\n\n if (is_yield_star_expression(node)) {\n on_found(node);\n return;\n }\n\n node.forEachChild((child) => {\n collect_yield_star_nodes(child, on_found);\n });\n}\n\n/**\n * Finds the first top-level `yield*` expression below a node.\n *\n * @since 2.0.0\n * @param node - Root node to search.\n * @param on_found - Callback invoked with the first matching node.\n * @returns Nothing.\n */\nexport function find_yield_star_node(\n node: ts.Node,\n on_found: (node: ts.Node) => void,\n): void {\n if (is_function_boundary_node(node)) {\n return;\n }\n\n if (is_yield_star_expression(node)) {\n on_found(node);\n return;\n }\n\n node.forEachChild((child) => {\n find_yield_star_node(child, on_found);\n });\n}\n\n/**\n * Extracts identifier names from a TypeScript binding name.\n *\n * @since 2.0.0\n * @param name - Binding name node to flatten.\n * @returns Identifier names from identifiers and destructuring patterns.\n */\nexport function extract_binding_names(name: ts.BindingName): string[] {\n if (ts.isIdentifier(name)) {\n return [name.text];\n }\n\n const result: string[] = [];\n\n for (const element of name.elements) {\n if (ts.isOmittedExpression(element)) {\n continue;\n }\n\n result.push(...extract_binding_names(element.name));\n }\n\n return result;\n}\n","import { contains_top_level_yield_star } from \"$/detect.ts\";\nimport { AsyncEffectInSyncRuneError } from \"$/error.ts\";\nimport { slice } from \"./source.ts\";\n\nimport ts from \"typescript\";\n\nconst ASYNC_EXPRESSION_RUNES = new Set([\n \"$derived\",\n \"$inspect\",\n \"$state\",\n \"$state.raw\",\n]);\n\nconst CALLBACK_RUNES = new Set([\n \"$derived.by\",\n \"$effect\",\n \"$effect.pre\",\n \"$effect.root\",\n]);\n\n/**\n * Validates that `yield*` only appears in rune positions the script-effect\n * transform can lower without changing the rune's normal Svelte contract.\n *\n * @since 2.0.0\n * @param node - AST node to scan.\n * @param content - Original script source used for diagnostics.\n * @param filename - Source filename used for diagnostics.\n * @returns Nothing.\n */\nexport function validate_rune_yield_usage(\n node: ts.Node,\n content: string,\n filename: string,\n): void {\n visit_rune_yield_usage(node, content, filename);\n}\n\n/**\n * Identifies `$state(...)` and `$state.raw(...)` initializer calls.\n *\n * @since 2.0.0\n * @param expr - Expression to classify.\n * @param content - Original script source used to preserve argument text.\n * @returns State rune details when the expression is a state initializer.\n */\nexport function get_state_rune_initializer(\n expr: ts.Expression,\n content: string,\n): { rune_name: \"$state\" | \"$state.raw\"; value_text: string } | undefined {\n if (!ts.isCallExpression(expr)) {\n return undefined;\n }\n\n const rune_name = get_rune_name(expr.expression);\n\n if (rune_name !== \"$state\" && rune_name !== \"$state.raw\") {\n return undefined;\n }\n\n const first_arg = expr.arguments[0];\n\n if (!first_arg) {\n return undefined;\n }\n\n return {\n rune_name,\n value_text: slice(content, first_arg).trim(),\n };\n}\n\nfunction visit_rune_yield_usage(\n node: ts.Node,\n content: string,\n filename: string,\n): void {\n if (ts.isCallExpression(node)) {\n validate_call_expression(node, content, filename);\n }\n\n node.forEachChild((child) => {\n visit_rune_yield_usage(child, content, filename);\n });\n}\n\nfunction validate_call_expression(\n call: ts.CallExpression,\n content: string,\n filename: string,\n): void {\n const rune_name = get_rune_name(call.expression);\n\n if (!rune_name) {\n return;\n }\n\n if (\n !ASYNC_EXPRESSION_RUNES.has(rune_name) &&\n contains_top_level_yield_star(call)\n ) {\n throw new AsyncEffectInSyncRuneError(\n rune_name,\n slice(content, call),\n filename,\n );\n }\n\n if (!CALLBACK_RUNES.has(rune_name)) {\n return;\n }\n\n const callback = call.arguments[0];\n\n if (!callback || !callback_has_top_level_yield_star(callback)) {\n return;\n }\n\n throw new AsyncEffectInSyncRuneError(\n rune_name,\n slice(content, call),\n filename,\n );\n}\n\nfunction callback_has_top_level_yield_star(node: ts.Expression): boolean {\n if (\n (ts.isArrowFunction(node) ||\n ts.isFunctionExpression(node)) &&\n node.body !== undefined\n ) {\n return contains_top_level_yield_star(node.body);\n }\n\n return contains_top_level_yield_star(node);\n}\n\nfunction get_rune_name(expr: ts.Expression): string | undefined {\n if (ts.isIdentifier(expr) && is_rune_root(expr.text)) {\n return expr.text;\n }\n\n if (!ts.isPropertyAccessExpression(expr)) {\n return undefined;\n }\n\n const root_name = get_rune_name(expr.expression);\n\n if (!root_name) {\n return undefined;\n }\n\n return `${root_name}.${expr.name.text}`;\n}\n\nfunction is_rune_root(name: string): boolean {\n return (\n name === \"$bindable\" ||\n name === \"$derived\" ||\n name === \"$effect\" ||\n name === \"$host\" ||\n name === \"$inspect\" ||\n name === \"$props\" ||\n name === \"$state\"\n );\n}\n","import { collect_free_identifiers } from \"$/markup/transform/expressions.ts\";\nimport { contains_top_level_yield_star } from \"$/detect.ts\";\nimport {\n collect_yield_star_nodes,\n extract_binding_names,\n find_yield_star_node,\n is_yield_star_expression,\n} from \"./ast.ts\";\nimport { get_state_rune_initializer } from \"./runes.ts\";\nimport { slice, slice_start } from \"./source.ts\";\nimport type {\n EffectBlock,\n LoweredExpression,\n LoweredStatement,\n ScriptLoweringContext,\n TempBinding,\n} from \"./types.ts\";\n\nimport ts from \"typescript\";\n\n/**\n * Delegates a statement to the correct lowerer based on syntax kind.\n *\n * @since 2.0.0\n * @param stmt - Statement to lower.\n * @param content - Original source text.\n * @param context - Lowering services for this transform pass.\n * @returns Lowered statement descriptor.\n */\nexport function lower_statement(\n stmt: ts.Statement,\n content: string,\n context: ScriptLoweringContext,\n): LoweredStatement {\n if (ts.isExpressionStatement(stmt)) {\n return lower_expression_statement(stmt, content, context);\n }\n\n if (ts.isVariableStatement(stmt)) {\n return lower_variable_statement(stmt, content, context);\n }\n\n const text = slice(content, stmt);\n\n return {\n temps: [],\n rewritten_text: \"\",\n effect_blocks: [make_effect_block([text], collect_deps(text))],\n range: { start: stmt.getFullStart(), end: stmt.end },\n };\n}\n\nfunction lower_variable_statement(\n stmt: ts.VariableStatement,\n content: string,\n context: ScriptLoweringContext,\n): LoweredStatement {\n const temps: TempBinding[] = [];\n const rewritten_decls: string[] = [];\n const statements: string[] = [];\n const deps: string[] = [];\n\n const decl_list = stmt.declarationList;\n const kind = (decl_list.flags & ts.NodeFlags.Let) !== 0 ? \"let\" : \"const\";\n let has_bare_yield = false;\n\n for (const decl of decl_list.declarations) {\n if (!decl.initializer || !contains_top_level_yield_star(decl.initializer)) {\n rewritten_decls.push(slice(content, decl).trim());\n continue;\n }\n\n const binding_text = slice(content, decl.name).trim();\n\n if (ts.isIdentifier(decl.name)) {\n const original_name = binding_text;\n\n if (is_yield_star_expression(decl.initializer)) {\n const temp_name = context.next_temp_name(original_name);\n\n temps.push({ name: temp_name });\n has_bare_yield = true;\n rewritten_decls.push(`${original_name} = $derived(${temp_name})`);\n\n const yield_text = extract_yield_star_full_text(\n decl.initializer,\n content,\n );\n\n statements.push(`${temp_name} = ${yield_text};`);\n deps.push(...collect_deps(yield_text));\n } else {\n const state_rune = get_state_rune_initializer(\n decl.initializer,\n content,\n );\n\n if (state_rune) {\n has_bare_yield = true;\n rewritten_decls.push(\n `${original_name} = ${state_rune.rune_name}(undefined)`,\n );\n statements.push(`${original_name} = ${state_rune.value_text};`);\n deps.push(...collect_deps(state_rune.value_text));\n continue;\n }\n\n const lowered = lower_expression_yields(\n decl.initializer,\n content,\n original_name,\n context,\n );\n\n temps.push(...lowered.temps);\n for (const block of lowered.effect_blocks) {\n statements.push(...block.statements);\n deps.push(...block.deps);\n }\n\n const rewritten_expr = rewrite_state_rune_as_derived(\n lowered.rewritten_expr,\n );\n\n rewritten_decls.push(`${original_name} = ${rewritten_expr}`);\n }\n } else {\n has_bare_yield = true;\n\n const temp_name = context.next_temp_name(\"destructure\");\n const names = extract_binding_names(decl.name);\n\n temps.push({ name: temp_name });\n temps.push(...names.map((name) => ({ name })));\n\n const yield_text = extract_yield_star_full_text(\n decl.initializer,\n content,\n );\n\n statements.push(`${temp_name} = ${yield_text};`);\n statements.push(`(${binding_text} = ${temp_name});`);\n deps.push(...collect_deps(yield_text));\n }\n }\n\n const rewritten_text = rewritten_decls.length === 0\n ? \"\"\n : `${has_bare_yield ? \"let\" : kind} ${rewritten_decls.join(\", \")};`;\n\n return {\n temps,\n rewritten_text,\n effect_blocks: statements.length === 0\n ? []\n : [make_effect_block(statements, deps)],\n range: { start: stmt.getStart(), end: stmt.end },\n };\n}\n\nfunction lower_expression_statement(\n stmt: ts.ExpressionStatement,\n content: string,\n context: ScriptLoweringContext,\n): LoweredStatement {\n const expr = stmt.expression;\n\n if (!contains_top_level_yield_star(expr)) {\n return {\n temps: [],\n rewritten_text: slice(content, stmt).trim(),\n effect_blocks: [],\n range: { start: stmt.getStart(), end: stmt.end },\n };\n }\n\n if (is_yield_star_expression(expr)) {\n const text = slice(content, expr).trim();\n\n return {\n temps: [],\n rewritten_text: \"\",\n effect_blocks: [make_effect_block([text + \";\"], collect_deps(text))],\n range: { start: stmt.getFullStart(), end: stmt.end },\n };\n }\n\n if (\n ts.isBinaryExpression(expr) &&\n expr.operatorToken.kind === ts.SyntaxKind.EqualsToken\n ) {\n const target = slice(content, expr.left).trim();\n const yield_text = extract_yield_star_full_text(expr, content);\n\n return {\n temps: [],\n rewritten_text: \"\",\n effect_blocks: [\n make_effect_block(\n [`${target} = ${yield_text};`],\n collect_deps(yield_text),\n ),\n ],\n range: { start: stmt.getStart(), end: stmt.end },\n };\n }\n\n const lowered = lower_expression_yields(\n expr,\n content,\n \"call\",\n context,\n );\n\n return {\n temps: lowered.temps,\n rewritten_text: lowered.rewritten_expr + \";\",\n effect_blocks: lowered.effect_blocks,\n range: { start: stmt.getStart(), end: stmt.end },\n };\n}\n\nfunction lower_expression_yields(\n expr: ts.Expression,\n content: string,\n hint: string,\n context: ScriptLoweringContext,\n): LoweredExpression {\n const replacements: Array<{\n start: number;\n end: number;\n text: string;\n }> = [];\n\n const temps: TempBinding[] = [];\n const statements: string[] = [];\n const deps: string[] = [];\n\n collect_yield_star_nodes(expr, (node) => {\n const temp_name = context.next_temp_name(hint);\n const yield_text = slice_start(content, node).trim();\n\n temps.push({ name: temp_name });\n statements.push(`${temp_name} = ${yield_text};`);\n deps.push(...collect_deps(yield_text));\n replacements.push({\n start: node.getStart(),\n end: node.end,\n text: temp_name,\n });\n });\n\n if (replacements.length === 0) {\n return {\n temps,\n rewritten_expr: slice(content, expr).trim(),\n effect_blocks: [],\n };\n }\n\n replacements.sort((a, b) => b.start - a.start);\n\n let text = slice(content, expr);\n\n const offset_in_expr = expr.getFullStart();\n\n for (const replacement of replacements) {\n text = text.slice(0, replacement.start - offset_in_expr) +\n replacement.text +\n text.slice(replacement.end - offset_in_expr);\n }\n\n return {\n temps,\n rewritten_expr: text.trim(),\n effect_blocks: [make_effect_block(statements, deps)],\n };\n}\n\nfunction rewrite_state_rune_as_derived(expression: string): string {\n const state_call = expression.match(/^\\$state(?:\\.raw)?\\(([\\s\\S]*)\\)$/);\n\n if (!state_call) {\n return expression;\n }\n\n return `$derived(${state_call[1]})`;\n}\n\nfunction extract_yield_star_full_text(\n expr: ts.Expression,\n content: string,\n): string {\n let found: string | undefined;\n\n find_yield_star_node(expr, (node) => {\n found = slice_start(content, node).trim();\n });\n\n return found ?? \"undefined\";\n}\n\nfunction make_effect_block(\n statements: string[],\n deps: string[],\n): EffectBlock {\n return {\n statements,\n deps: [...new Set(deps)],\n };\n}\n\nfunction collect_deps(expr_text: string): string[] {\n return collect_free_identifiers(expr_text).filter(\n (identifier) => !identifier.startsWith(\"__SER__\"),\n );\n}\n","import { contains_top_level_yield_star } from \"$/detect.ts\";\nimport { has_local_import_binding, make_imports } from \"./imports.ts\";\nimport { create_source_map, slice } from \"./source.ts\";\nimport { AwaitInEffectWorkError } from \"$/error.ts\";\nimport { make_runtime_block } from \"./runtime-block.ts\";\nimport { contains_top_level_await } from \"./ast.ts\";\nimport { lower_statement } from \"./lower.ts\";\nimport { validate_rune_yield_usage } from \"./runes.ts\";\nimport type { BlockRef, EffectBlock, ScriptTransformResult } from \"./types.ts\";\n\nimport MagicString from \"magic-string\";\nimport ts from \"typescript\";\n\nexport type { BlockRef, ScriptTransformResult } from \"./types.ts\";\n\n/**\n * Transforms a `<script effect>` body by extracting top-level `yield*`\n * expressions into `$state` temp bindings and wrapping the lowered\n * assignments in a dependency-tracked `$effect` block.\n *\n * @example\n * ```ts\n * const result = transform_script_effect(\n * `let user = $state(yield* getUser(id));`,\n * \"App.svelte\",\n * );\n * ```\n *\n * @since 2.0.0\n * @param content - The raw `<script effect>` body content.\n * @param filename - The source filename, used in error messages.\n * @returns The transformed code and any block references.\n */\nexport function transform_script_effect(\n content: string,\n filename: string,\n): ScriptTransformResult {\n let temp_counter = 0;\n\n const source_file = ts.createSourceFile(\n filename,\n content,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n\n const magic = new MagicString(content);\n const effect_blocks: EffectBlock[] = [];\n const block_refs: BlockRef[] = [];\n\n let has_effect = false;\n\n const context = {\n next_temp_name(hint?: string) {\n const suffix = temp_counter === 0 ? \"\" : `_${temp_counter}`;\n const name = hint ? `__SER__${hint}${suffix}` : `__SER__${temp_counter}`;\n\n temp_counter += 1;\n\n return name;\n },\n };\n\n /** Phase 1: detect imports already provided by the user. */\n const has_effect_import = has_local_import_binding(\n source_file,\n \"effect\",\n \"Effect\",\n );\n\n const has_dispatcher_import = has_local_import_binding(\n source_file,\n \"svelte-effect-runtime/internal/generators\",\n \"get_dispatcher\",\n );\n\n /** Phase 2: lower every top-level statement that contains `yield*`. */\n for (const stmt of source_file.statements) {\n validate_rune_yield_usage(stmt, content, filename);\n\n const has_top_level_yield_star = contains_top_level_yield_star(stmt);\n\n if (!has_top_level_yield_star) {\n continue;\n }\n\n if (contains_top_level_await(stmt)) {\n const text = slice(content, stmt);\n throw new AwaitInEffectWorkError(filename, text);\n }\n\n has_effect = true;\n const lowered = lower_statement(stmt, content, context);\n\n magic.overwrite(\n lowered.range.start,\n lowered.range.end,\n lowered.rewritten_text,\n );\n\n if (lowered.temps.length > 0) {\n const prefix = lowered.temps\n .map((temp) => `let ${temp.name} = $state(undefined);`)\n .join(\"\\n\");\n\n magic.appendLeft(lowered.range.start, prefix + \"\\n\");\n }\n\n effect_blocks.push(...lowered.effect_blocks);\n }\n\n if (!has_effect) {\n block_refs.push({ id: filename, kind: \"script\" });\n\n return { code: content, blocks: block_refs };\n }\n\n /** Phase 3: inject runtime imports after the last user import. */\n const imports = make_imports(\n has_effect_import,\n has_dispatcher_import,\n );\n\n const last_import = [...source_file.statements]\n .reverse()\n .find(ts.isImportDeclaration);\n\n if (last_import) {\n magic.appendRight(last_import.end, \"\\n\" + imports);\n } else {\n magic.prepend(imports + \"\\n\");\n }\n\n /** Phase 4: append the runtime program and lifecycle wiring. */\n const runtime_block = make_runtime_block(effect_blocks);\n magic.append(\"\\n\" + runtime_block);\n\n block_refs.push({ id: filename, kind: \"script\" });\n\n return {\n code: magic.toString(),\n blocks: block_refs,\n map: create_source_map(magic, filename),\n };\n}\n"],"mappings":"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"}
|