svelte-effect-runtime 1.6.2 → 2.0.0-beta.1

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.
Files changed (174) hide show
  1. package/.dist/chunks/client-BeOE81fW.js +577 -0
  2. package/.dist/chunks/client-BeOE81fW.js.map +1 -0
  3. package/.dist/chunks/descriptors-CU2g4U_i.js +36 -0
  4. package/.dist/chunks/descriptors-CU2g4U_i.js.map +1 -0
  5. package/.dist/chunks/dispatcher-BSg2-ttN.js +339 -0
  6. package/.dist/chunks/dispatcher-BSg2-ttN.js.map +1 -0
  7. package/.dist/chunks/preprocess-BZyUYWY7.js +430 -0
  8. package/.dist/chunks/preprocess-BZyUYWY7.js.map +1 -0
  9. package/.dist/chunks/transform-BtlxgJrg.js +836 -0
  10. package/.dist/chunks/transform-BtlxgJrg.js.map +1 -0
  11. package/.dist/detect.d.ts +34 -0
  12. package/.dist/detect.js +56 -0
  13. package/.dist/detect.js.map +1 -0
  14. package/.dist/dispatcher/deps.d.ts +14 -0
  15. package/.dist/dispatcher/fibers.d.ts +52 -0
  16. package/.dist/dispatcher/index.d.ts +138 -0
  17. package/.dist/dispatcher/types.d.ts +63 -0
  18. package/.dist/dispatcher.d.ts +2 -0
  19. package/.dist/dispatcher.js +2 -0
  20. package/.dist/error.d.ts +77 -0
  21. package/.dist/generators.d.ts +16 -0
  22. package/.dist/internal/descriptors.d.ts +17 -0
  23. package/.dist/internal/generators.d.ts +6 -0
  24. package/.dist/internal/generators.js +5 -0
  25. package/.dist/internal/remote-client.d.ts +6 -0
  26. package/.dist/internal/remote-client.js +2 -0
  27. package/.dist/internal/remote-server.d.ts +6 -0
  28. package/.dist/internal/remote-server.js +2 -0
  29. package/.dist/markup/promise.d.ts +15 -0
  30. package/.dist/markup/promise.js +26 -0
  31. package/.dist/markup/promise.js.map +1 -0
  32. package/.dist/markup/run.d.ts +12 -0
  33. package/.dist/markup/run.js +21 -0
  34. package/.dist/markup/run.js.map +1 -0
  35. package/.dist/markup/transform/apply.d.ts +6 -0
  36. package/.dist/markup/transform/classify.d.ts +15 -0
  37. package/.dist/markup/transform/constants.d.ts +5 -0
  38. package/.dist/markup/transform/emit.d.ts +12 -0
  39. package/.dist/markup/transform/expressions.d.ts +39 -0
  40. package/.dist/markup/transform/index.d.ts +19 -0
  41. package/.dist/markup/transform/scan.d.ts +8 -0
  42. package/.dist/markup/transform/types.d.ts +64 -0
  43. package/.dist/markup/transform.d.ts +1 -0
  44. package/.dist/markup/transform.js +2 -0
  45. package/.dist/markup/value.d.ts +20 -0
  46. package/.dist/markup/value.js +32 -0
  47. package/.dist/markup/value.js.map +1 -0
  48. package/.dist/mod.d.ts +186 -0
  49. package/.dist/mod.js +190 -0
  50. package/.dist/mod.js.map +1 -0
  51. package/.dist/preprocess/ast.d.ts +51 -0
  52. package/.dist/preprocess/imports.d.ts +22 -0
  53. package/.dist/preprocess/index.d.ts +21 -0
  54. package/.dist/preprocess/lower.d.ts +12 -0
  55. package/.dist/preprocess/runtime-block.d.ts +8 -0
  56. package/.dist/preprocess/source.d.ts +29 -0
  57. package/.dist/preprocess/types.d.ts +70 -0
  58. package/.dist/preprocess.d.ts +2 -0
  59. package/.dist/preprocess.js +3 -0
  60. package/.dist/remote/client/command.d.ts +17 -0
  61. package/.dist/remote/client/effect.d.ts +15 -0
  62. package/.dist/remote/client/failures.d.ts +57 -0
  63. package/.dist/remote/client/form-data.d.ts +8 -0
  64. package/.dist/remote/client/form-enhance.d.ts +9 -0
  65. package/.dist/remote/client/form-transport.d.ts +20 -0
  66. package/.dist/remote/client/form.d.ts +21 -0
  67. package/.dist/remote/client/index.d.ts +4 -0
  68. package/.dist/remote/client/query-result.d.ts +14 -0
  69. package/.dist/remote/client/query.d.ts +57 -0
  70. package/.dist/remote/client/responses.d.ts +28 -0
  71. package/.dist/remote/client/types.d.ts +83 -0
  72. package/.dist/remote/client/utils.d.ts +11 -0
  73. package/.dist/remote/client.d.ts +2 -0
  74. package/.dist/remote/client.js +2 -0
  75. package/.dist/remote/server.d.ts +66 -0
  76. package/.dist/remote/server.js +104 -0
  77. package/.dist/remote/server.js.map +1 -0
  78. package/.dist/remote/shared.d.ts +202 -0
  79. package/.dist/remote/shared.js +161 -0
  80. package/.dist/remote/shared.js.map +1 -0
  81. package/.dist/runtime/preprocess.d.ts +38 -0
  82. package/.dist/runtime/preprocess.js +54 -0
  83. package/.dist/runtime/preprocess.js.map +1 -0
  84. package/.dist/server/effects.d.ts +49 -0
  85. package/.dist/server/factories.d.ts +97 -0
  86. package/.dist/server/index.d.ts +3 -0
  87. package/.dist/server/invalid.d.ts +9 -0
  88. package/.dist/server/runtime.d.ts +66 -0
  89. package/.dist/server/schema.d.ts +42 -0
  90. package/.dist/server/types.d.ts +271 -0
  91. package/.dist/server/wrappers.d.ts +45 -0
  92. package/.dist/server.d.ts +2 -0
  93. package/.dist/server.js +527 -0
  94. package/.dist/server.js.map +1 -0
  95. package/.dist/vite.d.ts +42 -0
  96. package/.dist/vite.js +118 -0
  97. package/.dist/vite.js.map +1 -0
  98. package/README.md +2 -0
  99. package/package.json +66 -101
  100. package/dist/chunks/client-vV6UAwoP.js +0 -199
  101. package/dist/chunks/client-vV6UAwoP.js.map +0 -1
  102. package/dist/chunks/effect-Crj3S8Cg.js +0 -51
  103. package/dist/chunks/effect-Crj3S8Cg.js.map +0 -1
  104. package/dist/chunks/effect-compat-BhW0YPIs.js +0 -103
  105. package/dist/chunks/effect-compat-BhW0YPIs.js.map +0 -1
  106. package/dist/chunks/magic-string.es-BnGH-5YR.js +0 -1013
  107. package/dist/chunks/magic-string.es-BnGH-5YR.js.map +0 -1
  108. package/dist/chunks/markup-CkPUZIJt.js +0 -13390
  109. package/dist/chunks/markup-CkPUZIJt.js.map +0 -1
  110. package/dist/chunks/preprocess-BFePqOC6.js +0 -49
  111. package/dist/chunks/preprocess-BFePqOC6.js.map +0 -1
  112. package/dist/chunks/server-Dea1CJuY.js +0 -704
  113. package/dist/chunks/server-Dea1CJuY.js.map +0 -1
  114. package/dist/chunks/v3-D0c0MKPf.js +0 -1
  115. package/dist/chunks/v4-MMhHmzIG.js +0 -1
  116. package/dist/chunks/vite-BlUTKv2u.js +0 -152
  117. package/dist/chunks/vite-BlUTKv2u.js.map +0 -1
  118. package/dist/client.d.ts +0 -1
  119. package/dist/client.js +0 -2
  120. package/dist/effect.d.ts +0 -1
  121. package/dist/effect.js +0 -2
  122. package/dist/internal/app-server-shim.d.ts +0 -8
  123. package/dist/internal/effect-compat.d.ts +0 -21
  124. package/dist/internal/markup.d.ts +0 -11
  125. package/dist/internal/markup.js +0 -2
  126. package/dist/internal/remote-client.d.ts +0 -36
  127. package/dist/internal/remote-client.js +0 -527
  128. package/dist/internal/remote-client.js.map +0 -1
  129. package/dist/internal/remote-shared.d.ts +0 -186
  130. package/dist/internal/remote-shared.js +0 -122
  131. package/dist/internal/remote-shared.js.map +0 -1
  132. package/dist/internal/transform.d.ts +0 -18
  133. package/dist/internal/transform.js +0 -418
  134. package/dist/internal/transform.js.map +0 -1
  135. package/dist/language-server.d.ts +0 -9
  136. package/dist/language-server.js +0 -4
  137. package/dist/mod.d.ts +0 -22
  138. package/dist/mod.js +0 -3
  139. package/dist/preprocess.d.ts +0 -29
  140. package/dist/preprocess.js +0 -20
  141. package/dist/preprocess.js.map +0 -1
  142. package/dist/root-node.d.ts +0 -1
  143. package/dist/root-node.js +0 -63
  144. package/dist/root-node.js.map +0 -1
  145. package/dist/server.d.ts +0 -81
  146. package/dist/server.js +0 -85
  147. package/dist/server.js.map +0 -1
  148. package/dist/v3/client.d.ts +0 -117
  149. package/dist/v3/effect.d.ts +0 -17
  150. package/dist/v3/mod.d.ts +0 -27
  151. package/dist/v3/preprocess.d.ts +0 -28
  152. package/dist/v3/root-node.d.ts +0 -59
  153. package/dist/v3/server.d.ts +0 -297
  154. package/dist/v3/vite.d.ts +0 -46
  155. package/dist/v4/client.d.ts +0 -2
  156. package/dist/v4/effect.d.ts +0 -24
  157. package/dist/v4/effect.js +0 -19
  158. package/dist/v4/effect.js.map +0 -1
  159. package/dist/v4/mod.d.ts +0 -27
  160. package/dist/v4/mod.js +0 -3
  161. package/dist/v4/preprocess.d.ts +0 -34
  162. package/dist/v4/preprocess.js +0 -32
  163. package/dist/v4/preprocess.js.map +0 -1
  164. package/dist/v4/root-node.d.ts +0 -59
  165. package/dist/v4/root-node.js +0 -4
  166. package/dist/v4/server.d.ts +0 -340
  167. package/dist/v4/server.js +0 -71
  168. package/dist/v4/server.js.map +0 -1
  169. package/dist/v4/vite.d.ts +0 -34
  170. package/dist/v4/vite.js +0 -31
  171. package/dist/v4/vite.js.map +0 -1
  172. package/dist/vite.d.ts +0 -31
  173. package/dist/vite.js +0 -24
  174. package/dist/vite.js.map +0 -1
@@ -0,0 +1,836 @@
1
+ import { contains_top_level_yield_star } from "../detect.js";
2
+ import { parse } from "svelte/compiler";
3
+ import MagicString from "magic-string";
4
+ import ts from "typescript";
5
+ //#region src/markup/transform/constants.ts
6
+ const HELPERS = {
7
+ value: "__ser_markup_value",
8
+ promise: "__ser_markup_promise",
9
+ run: "__ser_markup_run"
10
+ };
11
+ //#endregion
12
+ //#region src/markup/transform/apply.ts
13
+ function create_source_map(magic, filename) {
14
+ return magic.generateMap({
15
+ hires: true,
16
+ includeContent: true,
17
+ source: filename
18
+ });
19
+ }
20
+ function blank_script_blocks(content) {
21
+ return content.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi, (match) => {
22
+ return match.split("\n").map((l) => " ".repeat(l.length)).join("\n");
23
+ });
24
+ }
25
+ function inject_helpers(magic, content, helpers = []) {
26
+ if (content.includes(HELPERS.value)) return;
27
+ const helper_segments = [
28
+ `import { value as ${HELPERS.value} } from "svelte-effect-runtime/internal/generators";`,
29
+ `import { promise as ${HELPERS.promise} } from "svelte-effect-runtime/internal/generators";`,
30
+ `import { run as ${HELPERS.run} } from "svelte-effect-runtime/internal/generators";`,
31
+ ...helpers
32
+ ].map((helper) => typeof helper === "string" ? { text: helper } : helper);
33
+ const helper_block = helper_segments.map((segment) => segment.text).join("\n");
34
+ const script_tag = find_instance_script_tag(content);
35
+ if (script_tag) {
36
+ const text = `\n${helper_block}\n`;
37
+ magic.appendLeft(script_tag.end, text);
38
+ return {
39
+ start: script_tag.end,
40
+ text,
41
+ relocations: make_insertion_relocations(helper_segments, "\n")
42
+ };
43
+ } else {
44
+ const text = `<script>\n${helper_block}\n<\/script>\n\n`;
45
+ magic.prepend(text);
46
+ return {
47
+ start: 0,
48
+ text,
49
+ relocations: make_insertion_relocations(helper_segments, "<script>\n")
50
+ };
51
+ }
52
+ }
53
+ function create_relocations(replacements, helper_insertion) {
54
+ const edits = [helper_insertion && {
55
+ start: helper_insertion.start,
56
+ removedLength: 0,
57
+ insertedLength: helper_insertion.text.length
58
+ }, ...replacements.map((replacement) => ({
59
+ start: replacement.start,
60
+ removedLength: replacement.end - replacement.start,
61
+ insertedLength: replacement.text.length
62
+ }))].filter(Boolean);
63
+ const replacement_relocations = replacements.flatMap((replacement) => {
64
+ if (!replacement.relocation) return [];
65
+ const delta_before = edits.filter((edit) => edit.start < replacement.start).reduce((total, edit) => total + edit.insertedLength - edit.removedLength, 0);
66
+ const generated_start = replacement.start + delta_before;
67
+ return [{
68
+ originalStart: replacement.relocation.originalStart,
69
+ originalEnd: replacement.relocation.originalEnd,
70
+ generatedStart: generated_start + replacement.relocation.generatedStartInReplacement,
71
+ generatedEnd: generated_start + replacement.relocation.generatedEndInReplacement
72
+ }];
73
+ });
74
+ const helper_relocations = helper_insertion?.relocations?.map((relocation) => ({
75
+ originalStart: relocation.originalStart,
76
+ originalEnd: relocation.originalEnd,
77
+ generatedStart: helper_insertion.start + relocation.generatedStartInReplacement,
78
+ generatedEnd: helper_insertion.start + relocation.generatedEndInReplacement
79
+ })) ?? [];
80
+ return [...replacement_relocations, ...helper_relocations];
81
+ }
82
+ function make_insertion_relocations(segments, prefix) {
83
+ const relocations = [];
84
+ let offset = prefix.length;
85
+ for (const segment of segments) {
86
+ if (segment.relocation) relocations.push({
87
+ originalStart: segment.relocation.originalStart,
88
+ originalEnd: segment.relocation.originalEnd,
89
+ generatedStartInReplacement: offset + segment.relocation.generatedStartInReplacement,
90
+ generatedEndInReplacement: offset + segment.relocation.generatedEndInReplacement
91
+ });
92
+ offset += segment.text.length + 1;
93
+ }
94
+ return relocations;
95
+ }
96
+ function find_instance_script_tag(content) {
97
+ for (const match of content.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script\s*>/gi)) {
98
+ if (match.index === void 0) continue;
99
+ const attrs = match[1] ?? "";
100
+ if (/\bcontext\s*=\s*["']module["']/.test(attrs) || /\bmodule\b/.test(attrs)) continue;
101
+ const open_end = match[0].indexOf(">") + 1;
102
+ return {
103
+ start: match.index + open_end,
104
+ end: match.index + match[0].length - 9
105
+ };
106
+ }
107
+ }
108
+ //#endregion
109
+ //#region src/markup/transform/classify.ts
110
+ /**
111
+ * Matches sanitized placeholders back to their Svelte AST context.
112
+ *
113
+ * @since 2.0.0
114
+ * @param ast - Parsed Svelte AST for the sanitized component markup.
115
+ * @param candidates - Placeholder candidates produced by the scanner.
116
+ * @returns Candidates paired with the markup context that determines how they
117
+ * should be emitted.
118
+ */
119
+ function classify_candidates(ast, candidates) {
120
+ const by_placeholder = new Map(candidates.map((candidate) => [candidate.placeholder, candidate]));
121
+ const classified = [];
122
+ const matched = /* @__PURE__ */ new Set();
123
+ walk_ast(ast.fragment, by_placeholder, matched, classified);
124
+ return classified;
125
+ }
126
+ function walk_ast(fragment, candidates, matched, classified) {
127
+ for (const node of fragment.nodes) visit_ast_node(node, candidates, matched, classified);
128
+ }
129
+ function visit_ast_node(node, candidates, matched, classified) {
130
+ switch (node.type) {
131
+ case "ExpressionTag":
132
+ classify_expression(node.expression, "plain", candidates, matched, classified);
133
+ return;
134
+ case "IfBlock":
135
+ classify_expression(node.test, "plain", candidates, matched, classified);
136
+ walk_ast(node.consequent, candidates, matched, classified);
137
+ if (node.alternate) walk_ast(node.alternate, candidates, matched, classified);
138
+ return;
139
+ case "EachBlock":
140
+ classify_expression(node.expression, "each", candidates, matched, classified);
141
+ walk_ast(node.body, candidates, matched, classified);
142
+ if (node.fallback) walk_ast(node.fallback, candidates, matched, classified);
143
+ return;
144
+ case "AwaitBlock":
145
+ classify_expression(node.expression, "await", candidates, matched, classified);
146
+ if (node.pending) walk_ast(node.pending, candidates, matched, classified);
147
+ if (node.then) walk_ast(node.then, candidates, matched, classified);
148
+ if (node.catch) walk_ast(node.catch, candidates, matched, classified);
149
+ return;
150
+ case "RenderTag":
151
+ classify_expression(node.expression, "render", candidates, matched, classified);
152
+ return;
153
+ case "HtmlTag":
154
+ classify_expression(node.expression, "plain", candidates, matched, classified);
155
+ return;
156
+ case "DebugTag":
157
+ classify_debug_tag(node, candidates, matched, classified);
158
+ return;
159
+ case "ConstTag":
160
+ case "DeclarationTag":
161
+ classify_declaration_tag(node, candidates, matched, classified);
162
+ return;
163
+ case "KeyBlock":
164
+ classify_expression(node.expression, "plain", candidates, matched, classified);
165
+ walk_ast(node.fragment, candidates, matched, classified);
166
+ return;
167
+ case "RegularElement":
168
+ case "Component":
169
+ case "TitleElement":
170
+ case "SlotElement":
171
+ case "SvelteBody":
172
+ case "SvelteBoundary":
173
+ case "SvelteComponent":
174
+ case "SvelteDocument":
175
+ case "SvelteElement":
176
+ case "SvelteFragment":
177
+ case "SvelteHead":
178
+ case "SvelteSelf":
179
+ case "SvelteWindow":
180
+ visit_element_attributes(node, candidates, matched, classified);
181
+ walk_ast(node.fragment, candidates, matched, classified);
182
+ return;
183
+ default: return;
184
+ }
185
+ }
186
+ function classify_debug_tag(node, candidates, matched, classified) {
187
+ const idents = node.identifiers;
188
+ if (!idents || idents.length === 0) return;
189
+ for (const ident of idents) classify_expression(ident, "plain", candidates, matched, classified);
190
+ }
191
+ function classify_declaration_tag(node, candidates, matched, classified) {
192
+ for (const decl of node.declaration.declarations) {
193
+ if (!decl.init) continue;
194
+ classify_expression(decl.init, "plain", candidates, matched, classified);
195
+ }
196
+ }
197
+ function visit_element_attributes(node, candidates, matched, classified) {
198
+ for (const attr of node.attributes) {
199
+ if (attr.type === "Attribute" && attr.name && (attr.name.startsWith("on:") || /^on[a-z]/.test(attr.name))) {
200
+ visit_attribute_value(attr.value, "event", candidates, matched, classified);
201
+ continue;
202
+ }
203
+ if (attr.type === "OnDirective" && attr.expression) {
204
+ classify_expression(attr.expression, "event", candidates, matched, classified);
205
+ continue;
206
+ }
207
+ }
208
+ }
209
+ function visit_attribute_value(value, kind, candidates, matched, classified) {
210
+ if (value === true) return;
211
+ if (Array.isArray(value)) {
212
+ for (const part of value) if (part.type === "ExpressionTag") classify_expression(part.expression, kind, candidates, matched, classified);
213
+ return;
214
+ }
215
+ classify_expression(value.expression, kind, candidates, matched, classified);
216
+ }
217
+ function classify_expression(expression, kind, candidates, matched, classified) {
218
+ if (!expression) return;
219
+ const candidate = find_candidate(expression, candidates);
220
+ if (!candidate || matched.has(candidate.placeholder)) return;
221
+ matched.add(candidate.placeholder);
222
+ classified.push({
223
+ candidate,
224
+ kind
225
+ });
226
+ }
227
+ function find_candidate(expression, candidates) {
228
+ if (expression.type === "Identifier" && expression.name) return candidates.get(expression.name);
229
+ if (expression.type === "CallExpression" && expression.callee?.type === "Identifier" && expression.callee.name) return candidates.get(expression.callee.name);
230
+ }
231
+ //#endregion
232
+ //#region src/markup/transform/expressions.ts
233
+ /**
234
+ * Strips an event handler arrow function down to its executable body.
235
+ *
236
+ * @since 2.0.0
237
+ * @param expr - Event handler expression text from the original markup.
238
+ * @returns Handler parameters, body text, and body offsets inside `expr`.
239
+ */
240
+ function strip_arrow_function(expr) {
241
+ const arrow_idx = expr.indexOf("=>");
242
+ if (arrow_idx === -1) return {
243
+ params: "()",
244
+ body: expr,
245
+ body_start: 0,
246
+ body_end: expr.length
247
+ };
248
+ const params = expr.slice(0, arrow_idx).trim();
249
+ const raw_body = expr.slice(arrow_idx + 2);
250
+ const leading_ws = raw_body.length - raw_body.trimStart().length;
251
+ let body_start = arrow_idx + 2 + leading_ws;
252
+ let body_end = expr.length - (raw_body.length - raw_body.trimEnd().length);
253
+ let body = expr.slice(body_start, body_end);
254
+ if (body.startsWith("{") && body.endsWith("}")) {
255
+ body_start += 1;
256
+ body_end -= 1;
257
+ body = body.slice(1, -1);
258
+ }
259
+ const body_leading_ws = body.length - body.trimStart().length;
260
+ const body_trailing_ws = body.length - body.trimEnd().length;
261
+ body_start += body_leading_ws;
262
+ body_end -= body_trailing_ws;
263
+ body = body.trim();
264
+ if (body.endsWith(";")) {
265
+ body = body.slice(0, -1);
266
+ body_end -= 1;
267
+ }
268
+ return {
269
+ params,
270
+ body,
271
+ body_start,
272
+ body_end
273
+ };
274
+ }
275
+ /**
276
+ * Classifies `yield*` placement inside an event handler body.
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * analyze_event_body_yield_star("yield* save()");
281
+ * ```
282
+ *
283
+ * @since 2.0.0
284
+ * @param body - Event handler body text after the outer arrow has been
285
+ * stripped.
286
+ * @returns Whether the body has top-level yield* expressions and whether any
287
+ * yield* appears inside a nested non-generator callback.
288
+ */
289
+ function analyze_event_body_yield_star(body) {
290
+ const wrapped = `function* __ser_event() { ${body}; }`;
291
+ const stmt = ts.createSourceFile("event.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
292
+ if (!ts.isFunctionDeclaration(stmt) || !stmt.body) return {
293
+ has_top_level_yield_star: false,
294
+ has_nested_invalid_yield_star: /\byield\s*\*/.test(body)
295
+ };
296
+ const result = {
297
+ has_top_level_yield_star: false,
298
+ has_nested_invalid_yield_star: false
299
+ };
300
+ visit_event_body(stmt.body, "top_level", result);
301
+ return result;
302
+ }
303
+ /**
304
+ * Collects free identifiers that must be captured as reactive dependencies.
305
+ *
306
+ * @since 2.0.0
307
+ * @param expr_text - Markup expression text to inspect.
308
+ * @returns Identifier names referenced by the expression.
309
+ */
310
+ function collect_free_identifiers(expr_text) {
311
+ const wrapped = `function* __w() { return (${expr_text}); }`;
312
+ let sf;
313
+ try {
314
+ sf = ts.createSourceFile("expr.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
315
+ } catch {
316
+ return [];
317
+ }
318
+ const fn = sf.statements[0];
319
+ if (!ts.isFunctionDeclaration(fn) || !fn.body) return [];
320
+ const ids = [];
321
+ const seen = /* @__PURE__ */ new Set();
322
+ visit_ids(fn.body, seen, ids);
323
+ return ids;
324
+ }
325
+ function visit_ids(node, seen, ids) {
326
+ if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) return;
327
+ if (ts.isIdentifier(node)) {
328
+ if (node.text === "yield" || node.text === "undefined" || node.text === "null" || node.text === "true" || node.text === "false" || node.text === "this") return;
329
+ if (is_property_access_name(node)) return;
330
+ if (!seen.has(node.text)) {
331
+ seen.add(node.text);
332
+ ids.push(node.text);
333
+ }
334
+ return;
335
+ }
336
+ node.forEachChild((child) => visit_ids(child, seen, ids));
337
+ }
338
+ function visit_event_body(node, context, result) {
339
+ if (is_yield_star_expression(node)) {
340
+ if (context === "top_level") result.has_top_level_yield_star = true;
341
+ else if (context === "nested_invalid") result.has_nested_invalid_yield_star = true;
342
+ node.forEachChild((child) => visit_event_body(child, context, result));
343
+ return;
344
+ }
345
+ if (is_nested_function_boundary(node)) {
346
+ const next_context = is_generator_function_boundary(node) ? "nested_generator" : "nested_invalid";
347
+ node.forEachChild((child) => visit_event_body(child, next_context, result));
348
+ return;
349
+ }
350
+ node.forEachChild((child) => visit_event_body(child, context, result));
351
+ }
352
+ function is_nested_function_boundary(node) {
353
+ return ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node);
354
+ }
355
+ function is_generator_function_boundary(node) {
356
+ return (ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) && node.asteriskToken !== void 0;
357
+ }
358
+ function is_yield_star_expression(node) {
359
+ if (ts.isYieldExpression(node)) return node.asteriskToken !== void 0;
360
+ return ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AsteriskToken && ts.isIdentifier(node.left) && node.left.text === "yield";
361
+ }
362
+ function is_property_access_name(node) {
363
+ const parent = node.parent;
364
+ return ts.isPropertyAccessExpression(parent) && parent.name === node || ts.isPropertyAssignment(parent) && parent.name === node || ts.isBindingElement(parent) && parent.propertyName === node || ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent);
365
+ }
366
+ //#endregion
367
+ //#region src/markup/transform/emit.ts
368
+ /**
369
+ * Emits source edits for classified markup Effect expressions.
370
+ *
371
+ * @since 2.0.0
372
+ * @param classified - Candidates paired with their Svelte markup context.
373
+ * @returns Replacements ready to apply to the original component source.
374
+ */
375
+ function emit_replacements(classified) {
376
+ return classified.map(({ candidate, kind }) => emit_replacement(candidate, kind));
377
+ }
378
+ function emit_replacement(candidate, kind) {
379
+ const id = make_cache_id(candidate);
380
+ const id_text = JSON.stringify(id);
381
+ const helper_name = make_helper_name(candidate);
382
+ let replacement_text;
383
+ let helpers;
384
+ let relocation;
385
+ if (kind === "await") {
386
+ const effect = make_effect_helper(candidate, helper_name);
387
+ replacement_text = emit_promise_expression(id_text, effect);
388
+ helpers = [effect.helper];
389
+ } else if (kind === "render") {
390
+ const effect = make_effect_helper(candidate, helper_name);
391
+ replacement_text = emit_render_expression(id_text, effect);
392
+ helpers = [effect.helper];
393
+ } else if (kind === "each") {
394
+ const effect = make_effect_helper(candidate, helper_name);
395
+ replacement_text = emit_each_expression(id_text, effect);
396
+ helpers = [effect.helper];
397
+ } else if (kind === "event") {
398
+ const event = strip_arrow_function(candidate.expr_text);
399
+ replacement_text = `${event.params} => { void ${HELPERS.run}(function* () { ${event.body}; }); }`;
400
+ helpers = [];
401
+ relocation = make_relocation(candidate, replacement_text, {
402
+ originalStart: event.body_start,
403
+ originalEnd: event.body_end,
404
+ generatedText: event.body
405
+ });
406
+ } else {
407
+ const effect = make_effect_helper(candidate, helper_name);
408
+ replacement_text = emit_each_expression(id_text, effect);
409
+ helpers = [effect.helper];
410
+ }
411
+ return {
412
+ start: candidate.start,
413
+ end: candidate.end,
414
+ text: replacement_text,
415
+ helpers,
416
+ relocation
417
+ };
418
+ }
419
+ function emit_promise_expression(id_text, effect) {
420
+ return `${HELPERS.promise}(${id_text}, ${effect.deps_text}, () => ${effect.call})`;
421
+ }
422
+ function emit_render_expression(id_text, effect) {
423
+ return `(await ${emit_promise_expression(id_text, effect)})()`;
424
+ }
425
+ function emit_each_expression(id_text, effect) {
426
+ return `await ${emit_promise_expression(id_text, effect)}`;
427
+ }
428
+ function make_effect_helper(candidate, helper_name) {
429
+ const deps = collect_free_identifiers(candidate.expr_text);
430
+ const params_text = deps.join(", ");
431
+ const args_text = deps.join(", ");
432
+ const deps_text = deps.length === 0 ? "[]" : `[${args_text}]`;
433
+ const call = `${helper_name}(${args_text})`;
434
+ const text = `function* ${helper_name}(${params_text}) { return (${candidate.expr_text}); }`;
435
+ const generated_start = text.indexOf(candidate.expr_text);
436
+ return {
437
+ call,
438
+ deps_text,
439
+ helper: {
440
+ text,
441
+ relocation: {
442
+ originalStart: candidate.start,
443
+ originalEnd: candidate.end,
444
+ generatedStartInReplacement: generated_start,
445
+ generatedEndInReplacement: generated_start + candidate.expr_text.length
446
+ }
447
+ }
448
+ };
449
+ }
450
+ function make_cache_id(candidate) {
451
+ return `${candidate.filename}:${candidate.start}:${candidate.end}`;
452
+ }
453
+ function make_helper_name(candidate) {
454
+ return `__ser_markup_effect_${candidate.start}_${candidate.end}`;
455
+ }
456
+ function make_relocation(candidate, replacement_text, inner) {
457
+ const generated_start = replacement_text.indexOf(inner.generatedText);
458
+ if (generated_start === -1) return;
459
+ return {
460
+ originalStart: candidate.start + inner.originalStart,
461
+ originalEnd: candidate.start + inner.originalEnd,
462
+ generatedStartInReplacement: generated_start,
463
+ generatedEndInReplacement: generated_start + inner.generatedText.length
464
+ };
465
+ }
466
+ //#endregion
467
+ //#region src/error.ts
468
+ /**
469
+ * Base error class for all preprocessor errors emitted during script and
470
+ * markup transformation. Carries the source filename so error messages can
471
+ * reference the affected file.
472
+ *
473
+ * @since 2.0.0
474
+ */
475
+ var PreprocessError = class extends Error {
476
+ /**
477
+ * The source filename that triggered this error.
478
+ *
479
+ * @since 2.0.0
480
+ */
481
+ filename;
482
+ constructor(message, filename) {
483
+ super(message);
484
+ this.name = "PreprocessError";
485
+ this.filename = filename;
486
+ }
487
+ };
488
+ /**
489
+ * Thrown when `await` is used at the top level of a `<script effect>` block.
490
+ * Top-level `await` is not supported — users should use
491
+ * `yield* Effect.promise(...)` or `yield* Effect.tryPromise(...)` instead.
492
+ *
493
+ * @since 2.0.0
494
+ */
495
+ var TopLevelAwaitError = class extends PreprocessError {
496
+ /**
497
+ * The full text of the problematic statement containing the `await`.
498
+ *
499
+ * @since 2.0.0
500
+ */
501
+ statement_text;
502
+ constructor(filename, statement_text) {
503
+ super([
504
+ `${filename}: top-level await is not supported in <script effect>.`,
505
+ `Use yield* Effect.promise(...) or yield* Effect.tryPromise(...) instead.`,
506
+ "",
507
+ `Problematic statement:`,
508
+ statement_text
509
+ ].join("\n"), filename);
510
+ this.name = "TopLevelAwaitError";
511
+ this.statement_text = statement_text;
512
+ }
513
+ };
514
+ /**
515
+ * Thrown when an event handler contains `yield*` inside a nested callback that
516
+ * is not itself a generator function.
517
+ *
518
+ * @example
519
+ * ```ts
520
+ * throw new NestedYieldStarInEventHandlerError(
521
+ * "Component.svelte",
522
+ * "Effect.try(() => yield* save())",
523
+ * );
524
+ * ```
525
+ *
526
+ * @since 2.0.0
527
+ */
528
+ var NestedYieldStarInEventHandlerError = class extends PreprocessError {
529
+ /**
530
+ * The full text of the problematic event handler body.
531
+ *
532
+ * @since 2.0.0
533
+ */
534
+ expression_text;
535
+ constructor(filename, expression_text) {
536
+ super([
537
+ `${filename}: yield* cannot be used inside a nested non-generator callback in a markup event handler.`,
538
+ `Move the yield* to the event handler body. Effect.try and Effect.sync callbacks are plain synchronous JavaScript; do not call Effect-returning functions inside them.`,
539
+ "",
540
+ `Run the remote Effect directly:`,
541
+ ` onclick={() => yield* UpvotePost(id)}`,
542
+ "",
543
+ `Recover from remote failures by composing the Effect value:`,
544
+ ` onclick={() => yield* UpvotePost(id).pipe(Effect.catch(() => Effect.void))}`,
545
+ "",
546
+ `Problematic expression:`,
547
+ expression_text
548
+ ].join("\n"), filename);
549
+ this.name = "NestedYieldStarInEventHandlerError";
550
+ this.expression_text = expression_text;
551
+ }
552
+ };
553
+ //#endregion
554
+ //#region src/markup/transform/scan.ts
555
+ function sanitize_markup(content, filename) {
556
+ const candidates = [];
557
+ const magic = new MagicString(content);
558
+ let helper_index = 0;
559
+ let cursor = 0;
560
+ while (cursor < content.length) {
561
+ const open = content.indexOf("{", cursor);
562
+ if (open === -1) break;
563
+ /** Skip braces inside <script> and <style> blocks. */
564
+ if (is_inside_excluded_block(content, open)) {
565
+ cursor = open + 1;
566
+ continue;
567
+ }
568
+ /** Find the matching closing brace. */
569
+ const close = find_closing_brace(content, open + 1);
570
+ if (close === -1) {
571
+ cursor = open + 1;
572
+ continue;
573
+ }
574
+ const inner = content.slice(open + 1, close);
575
+ const trimmed = inner.trimStart();
576
+ const leading_ws = inner.length - trimmed.length;
577
+ const tag_info = get_tag_info(trimmed);
578
+ const declaration_initializers = collect_declaration_initializers(content, open, leading_ws, trimmed);
579
+ if (declaration_initializers.length > 0) {
580
+ for (const initializer of declaration_initializers) {
581
+ const placeholder = `__ser_markup_placeholder_${helper_index}`;
582
+ helper_index += 1;
583
+ candidates.push({
584
+ placeholder,
585
+ start: initializer.start,
586
+ end: initializer.end,
587
+ expr_text: initializer.expr_text,
588
+ filename,
589
+ key: "plain"
590
+ });
591
+ magic.overwrite(initializer.start, initializer.end, placeholder);
592
+ }
593
+ cursor = close + 1;
594
+ continue;
595
+ }
596
+ let expr_body = trimmed.slice(tag_info.prefix_length);
597
+ /** For @const, only use the RHS after `=` as the expression body. */
598
+ const equal_idx = tag_info.kind === "plain" && trimmed.startsWith("@const ") ? expr_body.indexOf("=") : -1;
599
+ if (!((is_event_expression(inner) ? analyze_event_yield(inner, filename) : void 0)?.has_top_level_yield_star ?? contains_yield_star_in_text(expr_body))) {
600
+ cursor = close + 1;
601
+ continue;
602
+ }
603
+ /** The expression starts after the tag prefix. For @const, after the `=`. */
604
+ let extra_prefix = 0;
605
+ if (equal_idx !== -1) {
606
+ const after_eq_raw = expr_body.slice(equal_idx + 1);
607
+ expr_body = after_eq_raw.trimStart();
608
+ extra_prefix = equal_idx + 1 + (after_eq_raw.length - expr_body.length);
609
+ }
610
+ const expr_start = open + 1 + leading_ws + tag_info.prefix_length + extra_prefix;
611
+ /** For each/await, the expression ends before ` as ` or ` then `/` catch `. */
612
+ let expr_end = close;
613
+ const key = tag_info.kind;
614
+ if (key === "each") {
615
+ const as_idx = expr_body.lastIndexOf(" as ");
616
+ if (as_idx !== -1) expr_end = expr_start + as_idx;
617
+ }
618
+ if (key === "await") {
619
+ const then_idx = expr_body.indexOf(" then ");
620
+ const catch_idx = expr_body.indexOf(" catch ");
621
+ const boundary = Math.min(then_idx === -1 ? Infinity : then_idx, catch_idx === -1 ? Infinity : catch_idx);
622
+ if (boundary !== Infinity) expr_end = expr_start + boundary;
623
+ }
624
+ const expr_text = content.slice(expr_start, expr_end).trim();
625
+ if (expr_text.length === 0) {
626
+ cursor = close + 1;
627
+ continue;
628
+ }
629
+ /** Create a placeholder and replace the expression (preserving tag prefixes). */
630
+ const placeholder = `__ser_markup_placeholder_${helper_index}`;
631
+ helper_index += 1;
632
+ candidates.push({
633
+ placeholder,
634
+ start: expr_start,
635
+ end: expr_end,
636
+ expr_text,
637
+ filename,
638
+ key
639
+ });
640
+ magic.overwrite(expr_start, expr_end, key === "render" ? `${placeholder}()` : placeholder);
641
+ cursor = close + 1;
642
+ }
643
+ return {
644
+ code: magic.toString(),
645
+ candidates
646
+ };
647
+ }
648
+ function is_inside_excluded_block(content, pos) {
649
+ const script = find_tag_end(content, "script", pos);
650
+ const style = find_tag_end(content, "style", pos);
651
+ return script !== void 0 && pos < script.end && pos > script.start || style !== void 0 && pos < style.end && pos > style.start;
652
+ }
653
+ function find_tag_end(content, tag, after_pos) {
654
+ const pattern = new RegExp(`<${tag}\\b[^>]*>([\\s\\S]*?)<\\/${tag}\\s*>`, "gi");
655
+ for (const match of content.matchAll(pattern)) {
656
+ if (match.index === void 0) continue;
657
+ const end_pos = match.index + match[0].length;
658
+ if (match.index <= after_pos && after_pos < end_pos) return {
659
+ start: match.index,
660
+ end: end_pos
661
+ };
662
+ }
663
+ }
664
+ /** Brace matching helpers for extracting complete markup expressions. */
665
+ function find_closing_brace(content, start) {
666
+ let depth = 0;
667
+ for (let i = start; i < content.length; i += 1) {
668
+ const ch = content[i];
669
+ if (ch === "{" && content[i - 1] !== "$") depth += 1;
670
+ else if (ch === "}") {
671
+ if (depth === 0) return i;
672
+ depth -= 1;
673
+ } else if (ch === "'" || ch === "\"" || ch === "`") {
674
+ i = skip_string(content, i, ch);
675
+ if (i === -1) return -1;
676
+ } else if (ch === "/" && content[i + 1] === "/") i = skip_line_comment(content, i);
677
+ else if (ch === "/" && content[i + 1] === "*") {
678
+ i = skip_block_comment(content, i);
679
+ if (i === -1) return -1;
680
+ }
681
+ }
682
+ return -1;
683
+ }
684
+ function skip_string(content, start, quote) {
685
+ for (let i = start + 1; i < content.length; i += 1) {
686
+ if (content[i] === "\\") {
687
+ i += 1;
688
+ continue;
689
+ }
690
+ if (content[i] === quote) return i;
691
+ }
692
+ return -1;
693
+ }
694
+ function skip_line_comment(content, start) {
695
+ for (let i = start + 2; i < content.length; i += 1) if (content[i] === "\n") return i;
696
+ return content.length;
697
+ }
698
+ function skip_block_comment(content, start) {
699
+ for (let i = start + 2; i < content.length; i += 1) if (content[i] === "*" && content[i + 1] === "/") return i + 1;
700
+ return -1;
701
+ }
702
+ function get_tag_info(trimmed) {
703
+ if (trimmed.startsWith("#each ")) return {
704
+ kind: "each",
705
+ prefix_length: 6
706
+ };
707
+ if (trimmed.startsWith("#await ")) return {
708
+ kind: "await",
709
+ prefix_length: 7
710
+ };
711
+ if (trimmed.startsWith("@render ")) return {
712
+ kind: "render",
713
+ prefix_length: 8
714
+ };
715
+ /** Strip prefix-only tags — the expression starts after the tag keyword. */
716
+ if (trimmed.startsWith("#if ")) return {
717
+ kind: "plain",
718
+ prefix_length: 4
719
+ };
720
+ if (trimmed.startsWith(":else if ")) return {
721
+ kind: "plain",
722
+ prefix_length: 9
723
+ };
724
+ if (trimmed.startsWith("#key ")) return {
725
+ kind: "plain",
726
+ prefix_length: 5
727
+ };
728
+ if (trimmed.startsWith("@const ")) return {
729
+ kind: "plain",
730
+ prefix_length: 7
731
+ };
732
+ if (trimmed.startsWith("@html ")) return {
733
+ kind: "plain",
734
+ prefix_length: 6
735
+ };
736
+ if (trimmed.startsWith("@debug ")) return {
737
+ kind: "plain",
738
+ prefix_length: 7
739
+ };
740
+ return {
741
+ kind: "plain",
742
+ prefix_length: 0
743
+ };
744
+ }
745
+ function collect_declaration_initializers(content, open, leading_ws, trimmed) {
746
+ if (!is_declaration_tag_text(trimmed)) return [];
747
+ const source_file = ts.createSourceFile("declaration-tag.ts", `${trimmed};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
748
+ const stmt = source_file.statements[0];
749
+ if (!stmt || !ts.isVariableStatement(stmt)) return [];
750
+ const tag_start = open + 1 + leading_ws;
751
+ return stmt.declarationList.declarations.filter((decl) => decl.initializer && contains_top_level_yield_star(decl.initializer)).map((decl) => {
752
+ const initializer = decl.initializer;
753
+ const start = tag_start + initializer.getStart(source_file);
754
+ const end = tag_start + initializer.end;
755
+ return {
756
+ start,
757
+ end,
758
+ expr_text: content.slice(start, end).trim()
759
+ };
760
+ });
761
+ }
762
+ function is_declaration_tag_text(trimmed) {
763
+ return /^(?:const|let)\s/.test(trimmed);
764
+ }
765
+ function is_event_expression(inner) {
766
+ const trimmed = inner.trimStart();
767
+ return /^(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/.test(trimmed);
768
+ }
769
+ function analyze_event_yield(inner, filename) {
770
+ const event = strip_arrow_function(inner);
771
+ const analysis = analyze_event_body_yield_star(event.body);
772
+ if (analysis.has_nested_invalid_yield_star) throw new NestedYieldStarInEventHandlerError(filename, event.body);
773
+ return { has_top_level_yield_star: analysis.has_top_level_yield_star };
774
+ }
775
+ function contains_yield_star_in_text(text) {
776
+ if (!/\byield\s*\*/.test(text)) return false;
777
+ try {
778
+ const stmt = ts.createSourceFile("expr.ts", `const x = ${text};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
779
+ if (!ts.isVariableStatement(stmt)) return false;
780
+ const decl = stmt.declarationList.declarations[0];
781
+ if (!decl?.initializer) return false;
782
+ return contains_top_level_yield_star(decl.initializer);
783
+ } catch {
784
+ return true;
785
+ }
786
+ }
787
+ /** Free identifier collection helpers for generated closures. */
788
+ //#endregion
789
+ //#region src/markup/transform/index.ts
790
+ /**
791
+ * Transforms Svelte markup containing `{yield* expr}` brace expressions
792
+ * into calls to the markup runtime helpers (`value`, `promise`, `run`).
793
+ *
794
+ * Strategy: first find all brace expressions containing `yield*` via
795
+ * character scanning, replace them with placeholder identifiers, then
796
+ * parse the sanitized markup with Svelte's AST to determine the correct
797
+ * context for each placeholder (plain expression, #each, #await, event
798
+ * handler, etc.).
799
+ *
800
+ * @since 2.0.0
801
+ * @param content - The raw `.svelte` file content.
802
+ * @param filename - The source filename, used in error messages.
803
+ * @returns The transformed markup and a flag indicating whether yield* was
804
+ * found.
805
+ */
806
+ function transform_markup_effect(content, filename) {
807
+ if (!/\byield\s*\*/.test(content)) return {
808
+ code: content,
809
+ has_yield: false
810
+ };
811
+ /** Find all brace expressions containing yield* and replace with placeholders. */
812
+ const work = sanitize_markup(content, filename);
813
+ if (work.candidates.length === 0) return {
814
+ code: content,
815
+ has_yield: false
816
+ };
817
+ const replacements = emit_replacements(classify_candidates(parse(blank_script_blocks(work.code), {
818
+ filename,
819
+ modern: true
820
+ }), work.candidates));
821
+ const helpers = replacements.flatMap((replacement) => replacement.helpers ?? []);
822
+ const magic = new MagicString(content);
823
+ replacements.sort((a, b) => b.start - a.start);
824
+ for (const r of replacements) magic.overwrite(r.start, r.end, r.text);
825
+ const relocations = create_relocations(replacements, inject_helpers(magic, content, helpers));
826
+ return {
827
+ code: magic.toString(),
828
+ has_yield: true,
829
+ map: create_source_map(magic, filename),
830
+ relocations
831
+ };
832
+ }
833
+ //#endregion
834
+ export { TopLevelAwaitError as n, transform_markup_effect as t };
835
+
836
+ //# sourceMappingURL=transform-BtlxgJrg.js.map