svelte-effect-runtime 4.0.0 → 4.1.0

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 (150) hide show
  1. package/.dist/chunks/client-DbwVAMWm.js +530 -0
  2. package/.dist/chunks/client-DbwVAMWm.js.map +1 -0
  3. package/.dist/chunks/compiler-Dpyu4Owd.js +412 -0
  4. package/.dist/chunks/compiler-Dpyu4Owd.js.map +1 -0
  5. package/.dist/chunks/descriptors-q909VWyR.js +216 -0
  6. package/.dist/chunks/descriptors-q909VWyR.js.map +1 -0
  7. package/.dist/chunks/diagnostics-DLwwrBWb.js +359 -0
  8. package/.dist/chunks/diagnostics-DLwwrBWb.js.map +1 -0
  9. package/.dist/chunks/dispatcher-CTWINW5I.js +534 -0
  10. package/.dist/chunks/dispatcher-CTWINW5I.js.map +1 -0
  11. package/.dist/chunks/dispatcher-pZPzarul.js +23 -0
  12. package/.dist/chunks/dispatcher-pZPzarul.js.map +1 -0
  13. package/.dist/chunks/{errors-IJjsUwrE.js → errors-qhcbUH6o.js} +56 -44
  14. package/.dist/chunks/errors-qhcbUH6o.js.map +1 -0
  15. package/.dist/chunks/live-BW7xZKjb.js +146 -0
  16. package/.dist/chunks/live-BW7xZKjb.js.map +1 -0
  17. package/.dist/chunks/live-CHK0RrZu.js +10 -0
  18. package/.dist/chunks/live-CHK0RrZu.js.map +1 -0
  19. package/.dist/chunks/{remote-client-CVI4t66c.js → remote-client-mkQAfP1G.js} +29 -23
  20. package/.dist/chunks/remote-client-mkQAfP1G.js.map +1 -0
  21. package/.dist/chunks/{runtime-GBQz32DZ.js → runtime-CPosEhGl.js} +3 -27
  22. package/.dist/chunks/runtime-CPosEhGl.js.map +1 -0
  23. package/.dist/chunks/{server-D1LcDnZE.js → server-yQrNoiCR.js} +15 -84
  24. package/.dist/chunks/server-yQrNoiCR.js.map +1 -0
  25. package/.dist/chunks/source-scan-cSawCvsg.js +1059 -0
  26. package/.dist/chunks/source-scan-cSawCvsg.js.map +1 -0
  27. package/.dist/chunks/{transform-jNUr65K9.js → transform-D7TTlPpK.js} +245 -371
  28. package/.dist/chunks/transform-D7TTlPpK.js.map +1 -0
  29. package/.dist/compiler/markup-identifiers.d.ts +2 -0
  30. package/.dist/compiler/remote-client.d.ts +1 -19
  31. package/.dist/compiler/source-scan.d.ts +11 -108
  32. package/.dist/compiler/sveltekit-remote-bridge.d.ts +3 -0
  33. package/.dist/compiler.d.ts +6 -0
  34. package/.dist/compiler.js +1 -1
  35. package/.dist/detect.d.ts +0 -31
  36. package/.dist/detect.js +0 -39
  37. package/.dist/detect.js.map +1 -1
  38. package/.dist/diagnostics.d.ts +0 -16
  39. package/.dist/dispatcher/deps.d.ts +3 -14
  40. package/.dist/dispatcher/fibers.d.ts +5 -46
  41. package/.dist/dispatcher/index.d.ts +42 -135
  42. package/.dist/dispatcher/scope.d.ts +36 -0
  43. package/.dist/dispatcher/types.d.ts +0 -151
  44. package/.dist/dispatcher.d.ts +2 -1
  45. package/.dist/dispatcher.js +2 -2
  46. package/.dist/errors.d.ts +44 -42
  47. package/.dist/generated/dispatcher.d.ts +6 -51
  48. package/.dist/generators.d.ts +2 -12
  49. package/.dist/internal/descriptors.d.ts +0 -16
  50. package/.dist/internal/generators.js +14 -9
  51. package/.dist/internal/generators.js.map +1 -1
  52. package/.dist/internal/live.d.ts +9 -0
  53. package/.dist/internal/remote-client.js +2 -2
  54. package/.dist/internal/remote-server.js +2 -2
  55. package/.dist/internal/schema.d.ts +0 -54
  56. package/.dist/live.d.ts +9 -26
  57. package/.dist/markup/event-attributes.d.ts +0 -32
  58. package/.dist/markup/promise.d.ts +1 -23
  59. package/.dist/markup/promise.js +2 -18
  60. package/.dist/markup/promise.js.map +1 -1
  61. package/.dist/markup/run.d.ts +1 -10
  62. package/.dist/markup/run.js +2 -11
  63. package/.dist/markup/run.js.map +1 -1
  64. package/.dist/markup/transform/apply.d.ts +5 -4
  65. package/.dist/markup/transform/classify.d.ts +2 -11
  66. package/.dist/markup/transform/constants.d.ts +2 -1
  67. package/.dist/markup/transform/effect-bindings.d.ts +2 -26
  68. package/.dist/markup/transform/effect-callbacks.d.ts +0 -20
  69. package/.dist/markup/transform/emit.d.ts +2 -11
  70. package/.dist/markup/transform/expressions.d.ts +0 -35
  71. package/.dist/markup/transform/scan.d.ts +3 -22
  72. package/.dist/markup/transform/types.d.ts +15 -127
  73. package/.dist/markup/transform.js +1 -1
  74. package/.dist/markup/value.d.ts +1 -18
  75. package/.dist/markup/value.js +2 -19
  76. package/.dist/markup/value.js.map +1 -1
  77. package/.dist/mod.d.ts +3 -8
  78. package/.dist/mod.js +5 -5
  79. package/.dist/mod.js.map +1 -1
  80. package/.dist/remote/cause-codec.d.ts +3 -37
  81. package/.dist/remote/client/command.d.ts +3 -17
  82. package/.dist/remote/client/form-data.d.ts +0 -7
  83. package/.dist/remote/client/form-enhance.d.ts +0 -7
  84. package/.dist/remote/client/form-transport.d.ts +14 -20
  85. package/.dist/remote/client/form.d.ts +4 -24
  86. package/.dist/remote/client/index.d.ts +2 -1
  87. package/.dist/remote/client/prerender.d.ts +6 -0
  88. package/.dist/remote/client/query-result.d.ts +2 -14
  89. package/.dist/remote/client/query.d.ts +8 -48
  90. package/.dist/remote/client/responses.d.ts +3 -27
  91. package/.dist/remote/client/types.d.ts +16 -110
  92. package/.dist/remote/client/utils.d.ts +0 -8
  93. package/.dist/remote/client.d.ts +2 -2
  94. package/.dist/remote/client.js +2 -2
  95. package/.dist/remote/effect.d.ts +6 -0
  96. package/.dist/remote/failures.d.ts +4 -0
  97. package/.dist/remote/query-update.d.ts +2 -0
  98. package/.dist/remote/resource.d.ts +25 -0
  99. package/.dist/remote/server.d.ts +5 -50
  100. package/.dist/remote/server.js +2 -2
  101. package/.dist/remote/shared.d.ts +6 -145
  102. package/.dist/remote/shared.js +6 -127
  103. package/.dist/remote/shared.js.map +1 -1
  104. package/.dist/runtime/transform.js +26 -31
  105. package/.dist/runtime/transform.js.map +1 -1
  106. package/.dist/script-transform/ast.d.ts +0 -46
  107. package/.dist/script-transform/imports.d.ts +3 -39
  108. package/.dist/script-transform/index.d.ts +2 -0
  109. package/.dist/script-transform/lower.d.ts +0 -9
  110. package/.dist/script-transform/runes.d.ts +0 -10
  111. package/.dist/script-transform/runtime-block.d.ts +0 -17
  112. package/.dist/script-transform/source.d.ts +0 -24
  113. package/.dist/script-transform/types.d.ts +9 -126
  114. package/.dist/server/effects.d.ts +4 -53
  115. package/.dist/server/factories.d.ts +7 -7
  116. package/.dist/server/index.d.ts +1 -1
  117. package/.dist/server/invalid.d.ts +0 -7
  118. package/.dist/server/live-snapshot.d.ts +5 -0
  119. package/.dist/server/remote-handler-context.d.ts +5 -0
  120. package/.dist/server/runtime.d.ts +6 -24
  121. package/.dist/server/schema.d.ts +0 -14
  122. package/.dist/server/transport.d.ts +2 -0
  123. package/.dist/server/types.d.ts +49 -26
  124. package/.dist/server/wrappers.d.ts +3 -40
  125. package/.dist/server.d.ts +1 -1
  126. package/.dist/server.js +200 -215
  127. package/.dist/server.js.map +1 -1
  128. package/.dist/yieldable.d.ts +1 -35
  129. package/package.json +2 -2
  130. package/.dist/chunks/client-DcZUV4rR.js +0 -653
  131. package/.dist/chunks/client-DcZUV4rR.js.map +0 -1
  132. package/.dist/chunks/compiler-BBPNyXmQ.js +0 -460
  133. package/.dist/chunks/compiler-BBPNyXmQ.js.map +0 -1
  134. package/.dist/chunks/dispatcher-DOx8iC6r.js +0 -505
  135. package/.dist/chunks/dispatcher-DOx8iC6r.js.map +0 -1
  136. package/.dist/chunks/dispatcher-H-Ia0Os4.js +0 -47
  137. package/.dist/chunks/dispatcher-H-Ia0Os4.js.map +0 -1
  138. package/.dist/chunks/errors-IJjsUwrE.js.map +0 -1
  139. package/.dist/chunks/live-BXAKre_4.js +0 -104
  140. package/.dist/chunks/live-BXAKre_4.js.map +0 -1
  141. package/.dist/chunks/remote-client-CVI4t66c.js.map +0 -1
  142. package/.dist/chunks/runtime-GBQz32DZ.js.map +0 -1
  143. package/.dist/chunks/schema-D9pct6Y5.js +0 -89
  144. package/.dist/chunks/schema-D9pct6Y5.js.map +0 -1
  145. package/.dist/chunks/server-D1LcDnZE.js.map +0 -1
  146. package/.dist/chunks/source-scan-C4PsggID.js +0 -341
  147. package/.dist/chunks/source-scan-C4PsggID.js.map +0 -1
  148. package/.dist/chunks/transform-jNUr65K9.js.map +0 -1
  149. package/.dist/remote/client/effect.d.ts +0 -29
  150. package/.dist/remote/client/failures.d.ts +0 -42
@@ -1,28 +1,19 @@
1
- import { D as UnsupportedMarkupEffectPositionError, k as YieldStarInEventCallbackError, n as AsyncEffectInSyncRuneError, t as AsyncEffectInEventCallbackError } from "./errors-IJjsUwrE.js";
2
- import { t as scan_svelte_effect_source } from "./source-scan-C4PsggID.js";
1
+ import { A as UnsupportedMarkupEffectPositionError, M as YieldStarInEventCallbackError, n as AsyncEffectInSyncRuneError, t as AsyncEffectInEventCallbackError } from "./errors-qhcbUH6o.js";
2
+ import { t as scan_svelte_effect_source } from "./source-scan-cSawCvsg.js";
3
3
  import { contains_top_level_yield_star } from "../detect.js";
4
4
  import ts from "typescript";
5
5
  import { parse } from "svelte/compiler";
6
6
  import MagicString from "magic-string";
7
7
  //#region src/script-transform/imports.ts
8
- /**
9
- * Builds the import statements injected by the script transform.
10
- *
11
- * @since 2.0.0
12
- * @param has_effect_import - Whether the user already imports `Effect`.
13
- * @param has_dispatcher_import - Whether the user already imports
14
- * `get_dispatcher`.
15
- * @param has_untrack_import - Whether the user already imports `untrack`.
16
- * @param bindings - Local names reserved for generated runtime helpers.
17
- * @param options - Runtime helper imports required by this transformed script.
18
- * @returns Newline-separated import statements to inject.
19
- */
20
- function make_imports(has_effect_import, has_dispatcher_import, has_untrack_import, bindings = {
8
+ function make_imports(has_effect_import, has_dispatcher_import, has_untrack_import, has_on_destroy_import, bindings = {
21
9
  cancel: "__SER___cancel",
10
+ component_scope_ref: "ComponentScopeRef",
22
11
  dispatcher: "get_dispatcher",
23
12
  dispatcher_value: "__SER___dispatcher",
24
13
  effect: "Effect",
14
+ on_destroy: "onDestroy",
25
15
  program: "__SER___program",
16
+ scope: "__SER___scope",
26
17
  untrack: "untrack",
27
18
  yield_success: "YieldSuccess",
28
19
  yieldable: "ToEffect"
@@ -30,22 +21,27 @@ function make_imports(has_effect_import, has_dispatcher_import, has_untrack_impo
30
21
  const needs_dispatcher = options.needs_dispatcher ?? true;
31
22
  const needs_effect = options.needs_effect ?? true;
32
23
  const needs_untrack = options.needs_untrack ?? true;
24
+ const needs_on_destroy = options.needs_on_destroy ?? false;
33
25
  const needs_yield_success = options.needs_yield_success ?? false;
34
26
  const needs_yieldable = options.needs_yieldable ?? false;
35
- const generator_import = make_generator_import(bindings, needs_dispatcher && !has_dispatcher_import, needs_yieldable, needs_yield_success);
27
+ const needs_scope_ref = options.needs_scope_ref ?? true;
28
+ const generator_import = make_generator_import(bindings, needs_dispatcher && !has_dispatcher_import, needs_yieldable, needs_yield_success, needs_scope_ref);
36
29
  const untrack_import = bindings.untrack === "untrack" ? `import { untrack } from "svelte";` : `import { untrack as ${bindings.untrack} } from "svelte";`;
30
+ const on_destroy_import = bindings.on_destroy === "onDestroy" ? `import { onDestroy } from "svelte";` : `import { onDestroy as ${bindings.on_destroy} } from "svelte";`;
37
31
  const effect_import = has_effect_import ? false : bindings.effect === "Effect" ? `import { Effect } from "effect";` : `import { Effect as ${bindings.effect} } from "effect";`;
38
32
  return [
39
33
  generator_import,
40
34
  needs_untrack && !has_untrack_import && untrack_import,
35
+ needs_on_destroy && !has_on_destroy_import && on_destroy_import,
41
36
  needs_effect && effect_import
42
37
  ].filter(Boolean).join("\n");
43
38
  }
44
- function make_generator_import(bindings, needs_dispatcher, needs_yieldable, needs_yield_success) {
39
+ function make_generator_import(bindings, needs_dispatcher, needs_yieldable, needs_yield_success, needs_scope_ref) {
45
40
  const specifiers = [
46
41
  needs_dispatcher && make_named_import("get_dispatcher", bindings.dispatcher),
47
42
  needs_yieldable && make_named_import("ToEffect", bindings.yieldable),
48
- needs_yield_success && make_named_import("YieldSuccess", bindings.yield_success, true)
43
+ needs_yield_success && make_named_import("YieldSuccess", bindings.yield_success, true),
44
+ needs_scope_ref && make_named_import("ComponentScopeRef", bindings.component_scope_ref)
49
45
  ].filter((specifier) => specifier !== false);
50
46
  if (specifiers.length === 0) return false;
51
47
  return `import { ${specifiers.join(", ")} } from "svelte-effect-runtime/internal/generators";`;
@@ -54,15 +50,6 @@ function make_named_import(imported_name, local_name, type_only = false) {
54
50
  const prefix = type_only ? "type " : "";
55
51
  return imported_name === local_name ? `${prefix}${imported_name}` : `${prefix}${imported_name} as ${local_name}`;
56
52
  }
57
- /**
58
- * Checks whether a source file imports a local binding from a module.
59
- *
60
- * @since 2.0.0
61
- * @param source_file - Parsed TypeScript source file to inspect.
62
- * @param module_name - Module specifier to match.
63
- * @param local_name - Local binding name to look for.
64
- * @returns Whether that binding is already locally available.
65
- */
66
53
  function has_local_import_binding(source_file, module_name, local_name) {
67
54
  return source_file.statements.some((stmt) => {
68
55
  if (!ts.isImportDeclaration(stmt) || !ts.isStringLiteral(stmt.moduleSpecifier) || stmt.moduleSpecifier.text !== module_name) return false;
@@ -75,13 +62,6 @@ function has_local_import_binding(source_file, module_name, local_name) {
75
62
  return named_bindings.elements.some((element) => !element.isTypeOnly && element.name.text === local_name);
76
63
  });
77
64
  }
78
- /**
79
- * Collects every local binding declared at module top level.
80
- *
81
- * @since 2.4.2
82
- * @param source_file - Parsed TypeScript source file to inspect.
83
- * @returns Top-level names declared by imports, declarations, and variables.
84
- */
85
65
  function collect_top_level_binding_names(source_file) {
86
66
  return source_file.statements.flatMap(collect_statement_binding_names);
87
67
  }
@@ -108,11 +88,49 @@ function collect_binding_name_text(name) {
108
88
  });
109
89
  }
110
90
  //#endregion
91
+ //#region src/compiler/markup-identifiers.ts
92
+ const wrapper_name = "__SER___markup_identifiers";
93
+ const identifier_names_by_scan = /* @__PURE__ */ new WeakMap();
94
+ function collect_markup_identifier_names(source_scan) {
95
+ const cached_names = identifier_names_by_scan.get(source_scan);
96
+ if (cached_names) return cached_names;
97
+ const names = new Set(source_scan.markup_binding_names);
98
+ for (const expression of source_scan.markup_expressions) collect_source_file_identifier_names(ts.createSourceFile("markup-identifiers.ts", make_identifier_parse_source(expression.inner), ts.ScriptTarget.Latest, true, ts.ScriptKind.TS), names);
99
+ names.delete(wrapper_name);
100
+ identifier_names_by_scan.set(source_scan, names);
101
+ return names;
102
+ }
103
+ function make_identifier_parse_source(expression) {
104
+ const snippet = expression.match(/^(\s*)#snippet\s+([\s\S]*)$/);
105
+ if (snippet) return `function* ${wrapper_name}() { ${snippet[1]}function ${snippet[2]} {} }`;
106
+ return `function* ${wrapper_name}() { ${expression} }`;
107
+ }
108
+ function collect_source_file_identifier_names(source_file, names) {
109
+ const visit = (node) => {
110
+ if (ts.isIdentifier(node) && !is_non_runtime_property_name(node)) names.add(node.text);
111
+ ts.forEachChild(node, visit);
112
+ };
113
+ visit(source_file);
114
+ }
115
+ function is_non_runtime_property_name(identifier) {
116
+ const parent = identifier.parent;
117
+ return is_within_type_node(identifier) || ts.isPropertyAccessExpression(parent) && parent.name === identifier || ts.isPropertyAssignment(parent) && parent.name === identifier || ts.isPropertySignature(parent) && parent.name === identifier || ts.isMethodDeclaration(parent) && parent.name === identifier || ts.isMethodSignature(parent) && parent.name === identifier || ts.isGetAccessorDeclaration(parent) && parent.name === identifier || ts.isSetAccessorDeclaration(parent) && parent.name === identifier || ts.isPropertyDeclaration(parent) && parent.name === identifier || ts.isEnumMember(parent) && parent.name === identifier || ts.isBindingElement(parent) && parent.propertyName === identifier;
118
+ }
119
+ function is_within_type_node(identifier) {
120
+ let ancestor = identifier.parent;
121
+ while (ancestor) {
122
+ if (ts.isTypeNode(ancestor)) return true;
123
+ ancestor = ancestor.parent;
124
+ }
125
+ return false;
126
+ }
127
+ //#endregion
111
128
  //#region src/markup/transform/constants.ts
112
- const HELPERS = {
129
+ const default_helper_bindings = {
113
130
  codes: "Code",
114
131
  dispatcher: "Dispatcher",
115
- yieldable: "ToEffect"
132
+ yieldable: "ToEffect",
133
+ scope: "__SER___scope"
116
134
  };
117
135
  //#endregion
118
136
  //#region src/markup/transform/apply.ts
@@ -123,65 +141,98 @@ function create_source_map$1(magic, filename) {
123
141
  source: filename
124
142
  });
125
143
  }
126
- function blank_script_blocks(content) {
127
- return content.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi, (match) => {
128
- return match.split("\n").map((l) => " ".repeat(l.length)).join("\n");
129
- });
130
- }
131
- function inject_helpers(magic, content, helpers = [], bindings = HELPERS) {
144
+ function inject_helpers(magic, source_scan, helpers = [], bindings = default_helper_bindings, scope_wiring) {
132
145
  const import_helpers = unique_import_helpers(helpers);
133
146
  const local_helpers = helpers.filter((helper) => !is_import_helper(helper));
134
147
  const helper_segments = [
135
- make_import_helper(content, make_dispatcher_import(bindings)),
148
+ make_dispatcher_import(bindings, scope_wiring),
136
149
  ...import_helpers,
137
150
  ...local_helpers
138
151
  ].filter((helper) => helper !== void 0).map((helper) => typeof helper === "string" ? { text: helper } : helper);
139
152
  if (helper_segments.length === 0) return;
140
153
  const helper_block = helper_segments.map((segment) => segment.text).join("\n");
141
- const script_tag = find_instance_script_tag(content);
142
- if (script_tag) {
154
+ const scope_block = scope_wiring ? make_scope_wiring_block(bindings, scope_wiring) : void 0;
155
+ const instance_script = source_scan.instance_script;
156
+ if (instance_script) {
157
+ /**
158
+ * The scope holder must be declared before any user statement so its
159
+ * `onDestroy` runs during component initialisation, ahead of any
160
+ * top-level `await`.
161
+ */
162
+ const scope_text = scope_block ? `\n${scope_block}\n` : void 0;
163
+ if (scope_text) magic.appendLeft(instance_script.content_start, scope_text);
143
164
  const text = `\n${helper_block}\n`;
144
- magic.appendLeft(script_tag.end, text);
165
+ magic.appendLeft(instance_script.content_end, text);
145
166
  return {
146
- start: script_tag.end,
167
+ start: instance_script.content_end,
147
168
  text,
169
+ extra_insertions: scope_text ? [{
170
+ start: instance_script.content_start,
171
+ text: scope_text
172
+ }] : [],
148
173
  relocations: make_insertion_relocations(helper_segments, "\n")
149
174
  };
150
175
  } else {
151
- const text = `<script>\n${helper_block}\n<\/script>\n\n`;
176
+ const text = `<script>\n${[scope_block, helper_block].filter(Boolean).join("\n")}\n<\/script>\n\n`;
177
+ const helper_prefix = `<script>\n${scope_block ? scope_block + "\n" : ""}`;
152
178
  magic.prepend(text);
153
179
  return {
154
180
  start: 0,
155
181
  text,
156
- relocations: make_insertion_relocations(helper_segments, "<script>\n")
182
+ relocations: make_insertion_relocations(helper_segments, helper_prefix)
157
183
  };
158
184
  }
159
185
  }
160
- function make_markup_helper_bindings(content) {
161
- const script_tag = find_instance_script_tag(content);
162
- const name_allocator = make_name_allocator(script_tag ? collect_script_binding_names(content.slice(script_tag.start, script_tag.end)) : []);
186
+ function make_markup_helper_bindings(source_scan, target = "client") {
187
+ const script_binding_names = source_scan.scripts.flatMap((script) => collect_script_binding_names(script.text));
188
+ const markup_identifier_names = collect_markup_identifier_names(source_scan);
189
+ const name_allocator = make_name_allocator([...script_binding_names, ...markup_identifier_names]);
190
+ const bindings = {
191
+ codes: name_allocator.reserve(default_helper_bindings.codes),
192
+ dispatcher: name_allocator.reserve(default_helper_bindings.dispatcher),
193
+ yieldable: name_allocator.reserve(default_helper_bindings.yieldable),
194
+ scope: default_helper_bindings.scope
195
+ };
196
+ const is_server_target = target === "server";
163
197
  return {
164
- bindings: {
165
- codes: name_allocator.reserve(HELPERS.codes),
166
- dispatcher: name_allocator.reserve(HELPERS.dispatcher),
167
- yieldable: name_allocator.reserve(HELPERS.yieldable)
168
- },
169
- name_allocator
198
+ bindings,
199
+ name_allocator,
200
+ scope_wiring: script_binding_names.includes(default_helper_bindings.scope) ? void 0 : {
201
+ component_scope_ref: name_allocator.reserve("ComponentScopeRef"),
202
+ get_dispatcher: name_allocator.reserve("get_dispatcher"),
203
+ ...is_server_target ? {} : { on_destroy: name_allocator.reserve("onDestroy") }
204
+ }
170
205
  };
171
206
  }
172
207
  function create_relocations(replacements, helper_insertion) {
173
- const edits = [helper_insertion && {
174
- start: helper_insertion.start,
175
- removedLength: 0,
176
- insertedLength: helper_insertion.text.length
177
- }, ...replacements.map((replacement) => ({
178
- start: replacement.start,
179
- removedLength: replacement.end - replacement.start,
180
- insertedLength: replacement.text.length
181
- }))].filter(Boolean);
208
+ const ordered_replacements = [...replacements].sort((left, right) => left.start - right.start);
209
+ const replacement_deltas = /* @__PURE__ */ new Map();
210
+ let accumulated_delta = 0;
211
+ let replacement_delta_before_helper = 0;
212
+ let cursor = 0;
213
+ while (cursor < ordered_replacements.length) {
214
+ const start = ordered_replacements[cursor]?.start;
215
+ let group_end = cursor;
216
+ let group_delta = 0;
217
+ while (ordered_replacements[group_end]?.start === start) {
218
+ const replacement = ordered_replacements[group_end];
219
+ if (replacement) {
220
+ replacement_deltas.set(replacement, accumulated_delta);
221
+ group_delta += replacement.text.length - (replacement.end - replacement.start);
222
+ }
223
+ group_end += 1;
224
+ }
225
+ if (helper_insertion && start !== void 0 && start < helper_insertion.start) replacement_delta_before_helper += group_delta;
226
+ accumulated_delta += group_delta;
227
+ cursor = group_end;
228
+ }
229
+ const insertion_shift_before = (point) => {
230
+ if (!helper_insertion) return 0;
231
+ return (helper_insertion.start <= point ? helper_insertion.text.length : 0) + (helper_insertion.extra_insertions ?? []).filter((insertion) => insertion.start <= point).reduce((shift, insertion) => shift + insertion.text.length, 0);
232
+ };
182
233
  const replacement_relocations = replacements.flatMap((replacement) => {
183
234
  if (!replacement.relocation) return [];
184
- const delta_before = edits.filter((edit) => edit.start < replacement.start).reduce((total, edit) => total + edit.insertedLength - edit.removedLength, 0);
235
+ const delta_before = (replacement_deltas.get(replacement) ?? 0) + insertion_shift_before(replacement.start);
185
236
  const generated_start = replacement.start + delta_before;
186
237
  return [{
187
238
  originalStart: replacement.relocation.originalStart,
@@ -190,25 +241,36 @@ function create_relocations(replacements, helper_insertion) {
190
241
  generatedEnd: generated_start + replacement.relocation.generatedEndInReplacement
191
242
  }];
192
243
  });
244
+ const helper_generated_start = (helper_insertion?.start ?? 0) + replacement_delta_before_helper + (helper_insertion?.extra_insertions ?? []).filter((insertion) => helper_insertion && insertion.start <= helper_insertion.start).reduce((shift, insertion) => shift + insertion.text.length, 0);
193
245
  const helper_relocations = helper_insertion?.relocations?.map((relocation) => ({
194
246
  originalStart: relocation.originalStart,
195
247
  originalEnd: relocation.originalEnd,
196
- generatedStart: helper_insertion.start + relocation.generatedStartInReplacement,
197
- generatedEnd: helper_insertion.start + relocation.generatedEndInReplacement
248
+ generatedStart: helper_generated_start + relocation.generatedStartInReplacement,
249
+ generatedEnd: helper_generated_start + relocation.generatedEndInReplacement
198
250
  })) ?? [];
199
251
  return [...replacement_relocations, ...helper_relocations];
200
252
  }
201
- function make_import_helper(content, import_text) {
202
- if (content.includes(import_text)) return;
203
- return import_text;
204
- }
205
- function make_dispatcher_import(bindings) {
206
- return `import { ${make_import_specifier(HELPERS.dispatcher, bindings.dispatcher)}, ${make_import_specifier(HELPERS.codes, bindings.codes)}, ${make_import_specifier(HELPERS.yieldable, bindings.yieldable)} } from "svelte-effect-runtime/internal/generators";`;
253
+ function make_dispatcher_import(bindings, scope_wiring) {
254
+ return `import { ${[
255
+ make_import_specifier(default_helper_bindings.dispatcher, bindings.dispatcher),
256
+ make_import_specifier(default_helper_bindings.codes, bindings.codes),
257
+ make_import_specifier(default_helper_bindings.yieldable, bindings.yieldable),
258
+ ...scope_wiring ? [make_import_specifier("ComponentScopeRef", scope_wiring.component_scope_ref), make_import_specifier("get_dispatcher", scope_wiring.get_dispatcher)] : []
259
+ ].join(", ")} } from "svelte-effect-runtime/internal/generators";`;
207
260
  }
208
261
  function make_import_specifier(imported_name, local_name) {
209
262
  if (imported_name === local_name) return imported_name;
210
263
  return `${imported_name} as ${local_name}`;
211
264
  }
265
+ function make_scope_wiring_block(bindings, scope_wiring) {
266
+ const on_destroy_import = scope_wiring.on_destroy ? make_import_specifier("onDestroy", scope_wiring.on_destroy) : void 0;
267
+ const on_destroy_call = scope_wiring.on_destroy ? `${scope_wiring.on_destroy}(() => ${bindings.scope}.dispose());` : void 0;
268
+ return [
269
+ on_destroy_import ? `import { ${on_destroy_import} } from "svelte";` : void 0,
270
+ `const ${bindings.scope} = new ${scope_wiring.component_scope_ref}(${scope_wiring.get_dispatcher});`,
271
+ on_destroy_call
272
+ ].join("\n");
273
+ }
212
274
  function make_insertion_relocations(segments, prefix) {
213
275
  const relocations = [];
214
276
  let offset = prefix.length;
@@ -223,18 +285,6 @@ function make_insertion_relocations(segments, prefix) {
223
285
  }
224
286
  return relocations;
225
287
  }
226
- function find_instance_script_tag(content) {
227
- for (const match of content.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script\s*>/gi)) {
228
- if (match.index === void 0) continue;
229
- const attrs = match[1] ?? "";
230
- if (/\bcontext\s*=\s*["']module["']/.test(attrs) || /\bmodule\b/.test(attrs)) continue;
231
- const open_end = match[0].indexOf(">") + 1;
232
- return {
233
- start: match.index + open_end,
234
- end: match.index + match[0].length - 9
235
- };
236
- }
237
- }
238
288
  function unique_import_helpers(helpers) {
239
289
  const seen = /* @__PURE__ */ new Set();
240
290
  return helpers.filter((helper) => {
@@ -265,27 +315,12 @@ function make_name_allocator(initial_names) {
265
315
  }
266
316
  //#endregion
267
317
  //#region src/markup/transform/effect-bindings.ts
268
- const EFFECT_PACKAGE_MODULE = "effect";
269
- const EFFECT_DIRECT_MODULE = "effect/Effect";
270
- const GENERATED_EFFECT_NAME = "__SER___Effect";
271
- /**
272
- * Collects Effect import bindings that markup callback rewriting can trust.
273
- *
274
- * @example
275
- * ```ts
276
- * const bindings = collect_effect_callback_bindings(
277
- * `<script>import { Effect as E } from "effect";<\/script>`,
278
- * );
279
- * ```
280
- *
281
- * @since 2.4.0
282
- * @param content - Full Svelte component source before markup lowering.
283
- * @returns Binding metadata used to identify Effect callback combinators.
284
- */
285
- function collect_effect_callback_bindings(content) {
318
+ const effect_package_module = "effect";
319
+ const effect_direct_module = "effect/Effect";
320
+ const generated_effect_name = "__SER___Effect";
321
+ function collect_effect_callback_bindings(scripts) {
286
322
  const state = make_effect_binding_state();
287
- const scripts = collect_script_blocks(content);
288
- for (const script of scripts) collect_source_file_bindings(ts.createSourceFile("component-script.ts", script, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS), state);
323
+ for (const script of scripts) collect_source_file_bindings(ts.createSourceFile("component-script.ts", script.text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS), state);
289
324
  ensure_implicit_effect_binding(state);
290
325
  const wrapper = choose_effect_wrapper(state);
291
326
  return {
@@ -307,9 +342,6 @@ function make_effect_binding_state() {
307
342
  implicit_effect_import: false
308
343
  };
309
344
  }
310
- function collect_script_blocks(content) {
311
- return [...content.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/gi)].map((match) => match[1] ?? "");
312
- }
313
345
  function collect_source_file_bindings(source_file, state) {
314
346
  for (const statement of source_file.statements) collect_statement_binding(statement, state);
315
347
  }
@@ -346,21 +378,21 @@ function collect_import_binding(statement, state) {
346
378
  }
347
379
  function collect_namespace_import_binding(module_name, local_name, state) {
348
380
  state.local_names.add(local_name);
349
- if (module_name === EFFECT_DIRECT_MODULE) {
381
+ if (module_name === effect_direct_module) {
350
382
  add_ordered_name(state.effect_module_names, local_name);
351
383
  return;
352
384
  }
353
- if (module_name === EFFECT_PACKAGE_MODULE) add_ordered_name(state.effect_package_names, local_name);
385
+ if (module_name === effect_package_module) add_ordered_name(state.effect_package_names, local_name);
354
386
  }
355
387
  function collect_named_import_binding(module_name, element, state) {
356
388
  const imported_name = element.propertyName?.text ?? element.name.text;
357
389
  const local_name = element.name.text;
358
390
  state.local_names.add(local_name);
359
- if (module_name === EFFECT_PACKAGE_MODULE && imported_name === "Effect") {
391
+ if (module_name === effect_package_module && imported_name === "Effect") {
360
392
  add_ordered_name(state.effect_object_names, local_name);
361
393
  return;
362
394
  }
363
- if (module_name === EFFECT_DIRECT_MODULE) state.direct_members.set(local_name, imported_name);
395
+ if (module_name === effect_direct_module) state.direct_members.set(local_name, imported_name);
364
396
  }
365
397
  function collect_binding_name(name, local_names) {
366
398
  if (ts.isIdentifier(name)) {
@@ -382,10 +414,10 @@ function has_effect_binding(state) {
382
414
  }
383
415
  function choose_effect_wrapper(state) {
384
416
  const effect_object = state.effect_object_names[0];
385
- if (effect_object) return {
417
+ if (effect_object) return state.implicit_effect_import ? {
386
418
  expression: effect_object,
387
- import_text: state.implicit_effect_import ? `import { Effect } from "effect";` : void 0
388
- };
419
+ import_text: `import { Effect } from "effect";`
420
+ } : { expression: effect_object };
389
421
  const effect_module = state.effect_module_names[0];
390
422
  if (effect_module) return { expression: effect_module };
391
423
  const effect_package = state.effect_package_names[0];
@@ -397,10 +429,10 @@ function choose_effect_wrapper(state) {
397
429
  };
398
430
  }
399
431
  function make_generated_effect_name(local_names) {
400
- if (!local_names.has(GENERATED_EFFECT_NAME)) return GENERATED_EFFECT_NAME;
432
+ if (!local_names.has(generated_effect_name)) return generated_effect_name;
401
433
  let index = 1;
402
- while (local_names.has(`${GENERATED_EFFECT_NAME}_${index}`)) index += 1;
403
- return `${GENERATED_EFFECT_NAME}_${index}`;
434
+ while (local_names.has(`${generated_effect_name}_${index}`)) index += 1;
435
+ return `${generated_effect_name}_${index}`;
404
436
  }
405
437
  function add_ordered_name(names, name) {
406
438
  if (names.includes(name)) return;
@@ -408,58 +440,17 @@ function add_ordered_name(names, name) {
408
440
  }
409
441
  //#endregion
410
442
  //#region src/markup/event-attributes.ts
411
- /**
412
- * Checks whether a parsed Svelte attribute has the same event shape that
413
- * Svelte's compiler recognizes.
414
- *
415
- * @example
416
- * ```ts
417
- * is_svelte_event_attribute({
418
- * type: "Attribute",
419
- * name: "onclick",
420
- * value: { type: "ExpressionTag" },
421
- * });
422
- * ```
423
- *
424
- * @since 4.0.0
425
- * @param attribute - Parsed Svelte attribute with its name and complete value
426
- * shape.
427
- * @returns Whether Svelte treats the attribute as an event attribute.
428
- */
429
443
  function is_svelte_event_attribute(attribute) {
430
444
  if (attribute.type !== "Attribute" || !attribute.name?.startsWith("on")) return false;
431
445
  const value = attribute.value;
432
446
  return value !== true && !Array.isArray(value) || Array.isArray(value) && value.length === 1 && value[0]?.type === "ExpressionTag";
433
447
  }
434
- /**
435
- * Normalizes an event-like attribute name to Svelte's lowercase DOM event
436
- * spelling while keeping the legacy directive prefix intact.
437
- *
438
- * @example
439
- * ```ts
440
- * normalize_event_attribute_name("onChange");
441
- * ```
442
- *
443
- * @since 3.4.11
444
- * @param name - Event-like attribute name read from Svelte source or the
445
- * parsed AST.
446
- * @returns Lowercase event attribute spelling for DOM-facing Svelte nodes.
447
- */
448
448
  function normalize_event_attribute_name(name) {
449
449
  if (name.startsWith("on:")) return `on:${name.slice(3).toLowerCase()}`;
450
450
  return name.toLowerCase();
451
451
  }
452
452
  //#endregion
453
453
  //#region src/markup/transform/classify.ts
454
- /**
455
- * Matches sanitized placeholders back to their Svelte AST context.
456
- *
457
- * @since 2.0.0
458
- * @param ast - Parsed Svelte AST for the sanitized component markup.
459
- * @param candidates - Placeholder candidates produced by the scanner.
460
- * @returns Candidates paired with the markup context that determines how they
461
- * should be emitted.
462
- */
463
454
  function classify_candidates(ast, candidates) {
464
455
  const by_placeholder = new Map(candidates.map((candidate) => [candidate.placeholder, candidate]));
465
456
  const classified = [];
@@ -495,7 +486,7 @@ function visit_ast_node(node, candidates, matched, classified) {
495
486
  classify_expression(node.expression, "render", candidates, matched, classified);
496
487
  return;
497
488
  case "HtmlTag":
498
- classify_expression(node.expression, "plain", candidates, matched, classified);
489
+ classify_expression(node.expression, "html", candidates, matched, classified);
499
490
  return;
500
491
  case "DebugTag": return;
501
492
  case "ConstTag":
@@ -623,83 +614,7 @@ function is_record(value) {
623
614
  return typeof value === "object" && value !== null;
624
615
  }
625
616
  //#endregion
626
- //#region src/script-transform/ast.ts
627
- /**
628
- * Checks whether a node is a `yield*` binary expression.
629
- *
630
- * @since 2.0.0
631
- * @param node - TypeScript AST node to check.
632
- * @returns Whether the node represents `yield * operand`.
633
- */
634
- function is_yield_star_expression$1(node) {
635
- return ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AsteriskToken && ts.isIdentifier(node.left) && node.left.text === "yield";
636
- }
637
- /**
638
- * Checks whether a node owns its own yield semantics.
639
- *
640
- * @since 2.0.0
641
- * @param node - TypeScript AST node to check.
642
- * @returns Whether traversal should stop at this function boundary.
643
- */
644
- function is_function_boundary_node(node) {
645
- return ts.isArrowFunction(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node);
646
- }
647
- /**
648
- * Returns `true` if the node tree contains a top-level `await`.
649
- *
650
- * @since 2.0.0
651
- * @param node - Root node to search.
652
- * @returns Whether a top-level await expression was found.
653
- */
654
- function contains_top_level_await(node) {
655
- if (ts.isAwaitExpression(node)) return true;
656
- return node.getChildren().some((child) => !is_function_boundary_node(child) && contains_top_level_await(child));
657
- }
658
- /**
659
- * Collects top-level `yield*` nodes under an expression.
660
- *
661
- * @since 2.0.0
662
- * @param node - Root node to search.
663
- * @param on_found - Callback invoked for each matching yield node.
664
- * @returns Nothing.
665
- */
666
- function collect_yield_star_nodes(node, on_found) {
667
- if (is_function_boundary_node(node)) return;
668
- if (is_yield_star_expression$1(node)) {
669
- on_found(node);
670
- return;
671
- }
672
- node.forEachChild((child) => {
673
- collect_yield_star_nodes(child, on_found);
674
- });
675
- }
676
- /**
677
- * Finds the first top-level `yield*` expression below a node.
678
- *
679
- * @since 2.0.0
680
- * @param node - Root node to search.
681
- * @param on_found - Callback invoked with the first matching node.
682
- * @returns Nothing.
683
- */
684
- function find_yield_star_node(node, on_found) {
685
- if (is_function_boundary_node(node)) return;
686
- if (is_yield_star_expression$1(node)) {
687
- on_found(node);
688
- return;
689
- }
690
- node.forEachChild((child) => {
691
- find_yield_star_node(child, on_found);
692
- });
693
- }
694
- //#endregion
695
617
  //#region src/markup/transform/expressions.ts
696
- /**
697
- * Strips an event handler arrow function down to its executable body.
698
- *
699
- * @since 2.0.0
700
- * @param expr - Event handler expression text from the original markup.
701
- * @returns Handler parameters, body text, and body offsets inside `expr`.
702
- */
703
618
  function strip_arrow_function(expr) {
704
619
  const arrow_idx = expr.indexOf("=>");
705
620
  if (arrow_idx === -1) return {
@@ -735,13 +650,6 @@ function strip_arrow_function(expr) {
735
650
  body_end
736
651
  };
737
652
  }
738
- /**
739
- * Returns whether an expression is a callback function.
740
- *
741
- * @since 2.0.0
742
- * @param expr - Expression text from a markup attribute or expression tag.
743
- * @returns Whether the expression parses as an arrow or function expression.
744
- */
745
653
  function is_callback_function_expression(expr) {
746
654
  const wrapped = `const __SER___callback = ${expr};`;
747
655
  const stmt = ts.createSourceFile("callback.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
@@ -749,20 +657,6 @@ function is_callback_function_expression(expr) {
749
657
  const initializer = stmt.declarationList.declarations[0]?.initializer;
750
658
  return initializer !== void 0 && (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer));
751
659
  }
752
- /**
753
- * Classifies `yield*` placement inside an event handler body.
754
- *
755
- * @example
756
- * ```ts
757
- * analyze_event_body_yield_star("yield* save()");
758
- * ```
759
- *
760
- * @since 2.0.0
761
- * @param body - Event handler body text after the outer arrow has been
762
- * stripped.
763
- * @returns Whether the body has top-level yield* expressions and whether any
764
- * yield* appears inside a nested non-generator callback.
765
- */
766
660
  function analyze_event_body_yield_star(body) {
767
661
  const wrapped = `function* __SER___event() { ${body}; }`;
768
662
  const stmt = ts.createSourceFile("event.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
@@ -777,13 +671,6 @@ function analyze_event_body_yield_star(body) {
777
671
  visit_event_body(stmt.body, "top_level", result);
778
672
  return result;
779
673
  }
780
- /**
781
- * Collects free identifiers that must be captured as reactive dependencies.
782
- *
783
- * @since 2.0.0
784
- * @param expr_text - Markup expression text to inspect.
785
- * @returns Identifier names referenced by the expression.
786
- */
787
674
  function collect_free_identifiers(expr_text) {
788
675
  const wrapped = `function* __SER___w() { return (${expr_text}); }`;
789
676
  let sf;
@@ -836,7 +723,7 @@ function add_binding_names(name, locals) {
836
723
  }
837
724
  }
838
725
  function visit_event_body(node, context, result) {
839
- if (is_yield_star_expression(node)) {
726
+ if (is_yield_star_expression$1(node)) {
840
727
  if (context === "top_level") result.has_top_level_yield_star = true;
841
728
  else if (context === "nested_invalid") result.has_nested_invalid_yield_star = true;
842
729
  node.forEachChild((child) => visit_event_body(child, context, result));
@@ -855,7 +742,7 @@ function is_nested_function_boundary(node) {
855
742
  function is_generator_function_boundary(node) {
856
743
  return (ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) && node.asteriskToken !== void 0;
857
744
  }
858
- function is_yield_star_expression(node) {
745
+ function is_yield_star_expression$1(node) {
859
746
  if (ts.isYieldExpression(node)) return node.asteriskToken !== void 0;
860
747
  return ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AsteriskToken && ts.isIdentifier(node.left) && node.left.text === "yield";
861
748
  }
@@ -884,26 +771,6 @@ const effectful_handler_members = /* @__PURE__ */ new Set([
884
771
  "tapBoth"
885
772
  ]);
886
773
  const effectful_handler_property_names = /* @__PURE__ */ new Set(["onFailure", "onSuccess"]);
887
- /**
888
- * Rewrites effectful callback shorthand inside event handler expressions.
889
- *
890
- * @example
891
- * ```ts
892
- * normalize_effect_callback_yields(
893
- * `yield* action.pipe(Effect.flatMap((value) => yield* next(value)))`,
894
- * collect_effect_callback_bindings(source),
895
- * );
896
- * ```
897
- *
898
- * @since 2.0.0
899
- * @param expr_text - Markup expression text before it is wrapped in the
900
- * generated Effect runner.
901
- * @param bindings - Local Effect import bindings collected from the Svelte
902
- * component's script blocks.
903
- * @returns The expression with nested Effect callback `yield*` shorthand
904
- * lowered into explicit Effect callbacks, plus any import needed by generated
905
- * wrapper calls.
906
- */
907
774
  function normalize_effect_callback_yields(expr_text, bindings) {
908
775
  const source_text = `const __SER___expression = ${expr_text};`;
909
776
  const source_file = ts.createSourceFile("event-expression.ts", source_text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
@@ -1089,16 +956,39 @@ function to_expr_pos(pos, context) {
1089
956
  return pos - context.offset;
1090
957
  }
1091
958
  //#endregion
959
+ //#region src/script-transform/ast.ts
960
+ function is_yield_star_expression(node) {
961
+ return ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AsteriskToken && ts.isIdentifier(node.left) && node.left.text === "yield";
962
+ }
963
+ function is_function_boundary_node(node) {
964
+ return ts.isArrowFunction(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node);
965
+ }
966
+ function contains_top_level_await(node) {
967
+ if (ts.isAwaitExpression(node)) return true;
968
+ return node.getChildren().some((child) => !is_function_boundary_node(child) && contains_top_level_await(child));
969
+ }
970
+ function collect_yield_star_nodes(node, on_found) {
971
+ if (is_function_boundary_node(node)) return;
972
+ if (is_yield_star_expression(node)) {
973
+ on_found(node);
974
+ return;
975
+ }
976
+ node.forEachChild((child) => {
977
+ collect_yield_star_nodes(child, on_found);
978
+ });
979
+ }
980
+ function find_yield_star_node(node, on_found) {
981
+ if (is_function_boundary_node(node)) return;
982
+ if (is_yield_star_expression(node)) {
983
+ on_found(node);
984
+ return;
985
+ }
986
+ node.forEachChild((child) => {
987
+ find_yield_star_node(child, on_found);
988
+ });
989
+ }
990
+ //#endregion
1092
991
  //#region src/markup/transform/emit.ts
1093
- /**
1094
- * Emits source edits for classified markup Effect expressions.
1095
- *
1096
- * @since 2.0.0
1097
- * @param classified - Candidates paired with their Svelte markup context.
1098
- * @param effect_context - Effect import bindings available to markup
1099
- * expression rewrites.
1100
- * @returns Replacements ready to apply to the original component source.
1101
- */
1102
992
  function emit_replacements(classified, effect_context, helper_bindings, name_allocator, target) {
1103
993
  const expression_replacements = classified.map(({ candidate, kind }) => emit_replacement(candidate, kind, effect_context, helper_bindings, name_allocator, target));
1104
994
  return [...unique_attribute_name_replacements(classified).map((replacement) => ({
@@ -1151,6 +1041,11 @@ function emit_replacement(candidate, kind, effect_context, helper_bindings, name
1151
1041
  replacement_text = event.text;
1152
1042
  helpers = normalized.helpers;
1153
1043
  relocation = make_pending_relocation(candidate, replacement_text, event.expr_text, event.relocation);
1044
+ } else if (kind === "html") {
1045
+ const effect = make_inline_effect(normalized_candidate, helper_bindings);
1046
+ replacement_text = emit_await_expression(id_text, effect, helper_bindings);
1047
+ helpers = normalized.helpers;
1048
+ relocation = make_pending_relocation(candidate, replacement_text, effect.effect_text, effect.relocation);
1154
1049
  } else {
1155
1050
  const effect = make_effect_helper(normalized_candidate, helper_name, helper_bindings);
1156
1051
  replacement_text = emit_await_expression(id_text, effect, helper_bindings, server_fallback(is_server_target, "undefined"));
@@ -1161,7 +1056,7 @@ function emit_replacement(candidate, kind, effect_context, helper_bindings, name
1161
1056
  end: candidate.end,
1162
1057
  text: replacement_text,
1163
1058
  helpers,
1164
- relocation
1059
+ ...relocation ? { relocation } : {}
1165
1060
  };
1166
1061
  }
1167
1062
  function make_event_handler(candidate, helper_bindings) {
@@ -1172,7 +1067,7 @@ function make_event_handler(candidate, helper_bindings) {
1172
1067
  return {
1173
1068
  expr_text: wrapped_expr_text,
1174
1069
  relocation: make_yield_operand_relocation(expr_text, wrapped_expr_text, helper_bindings),
1175
- text: `(event) => { ${helper_bindings.dispatcher}.emit({ type: ${helper_bindings.codes}.Markup.Run, fn: function* () { ${wrapped_expr_text}; } }); }`
1070
+ text: `(event) => { ${helper_bindings.dispatcher}.with_scope(${helper_bindings.scope}.scope, () => ${helper_bindings.dispatcher}.emit({ type: ${helper_bindings.codes}.Markup.Run, fn: function* () { ${wrapped_expr_text}; } })); }`
1176
1071
  };
1177
1072
  }
1178
1073
  function emit_promise_expression(id_text, effect, helper_bindings, ssr_fallback, options) {
@@ -1184,7 +1079,7 @@ function emit_promise_expression(id_text, effect, helper_bindings, ssr_fallback,
1184
1079
  ssr_fallback !== void 0 && `ssr_fallback: ${ssr_fallback}`,
1185
1080
  options !== void 0 && `options: ${options}`
1186
1081
  ].filter((property) => property !== false);
1187
- return `${helper_bindings.dispatcher}.emit({ ${properties.join(", ")} })`;
1082
+ return `${helper_bindings.dispatcher}.with_scope(${helper_bindings.scope}.scope, () => ${helper_bindings.dispatcher}.emit({ ${properties.join(", ")} }))`;
1188
1083
  }
1189
1084
  function emit_render_expression(id_text, effect, candidate, helper_bindings, is_server_target) {
1190
1085
  const expression = emit_promise_expression(id_text, effect, helper_bindings, server_fallback(is_server_target, `() => undefined`));
@@ -1225,6 +1120,18 @@ function make_effect_helper(candidate, helper_name, helper_bindings) {
1225
1120
  }
1226
1121
  };
1227
1122
  }
1123
+ function make_inline_effect(candidate, helper_bindings) {
1124
+ const deps = collect_free_identifiers(candidate.expr_text);
1125
+ const deps_text = deps.length === 0 ? "[]" : `[${deps.join(", ")}]`;
1126
+ const effect_text = wrap_yield_stars(candidate.expr_text, helper_bindings);
1127
+ const relocation = make_yield_operand_relocation(candidate.expr_text, effect_text, helper_bindings);
1128
+ return {
1129
+ call: `(function* () { return (${effect_text}); })()`,
1130
+ deps_text,
1131
+ effect_text,
1132
+ relocation
1133
+ };
1134
+ }
1228
1135
  function wrap_yield_stars(text, helper_bindings) {
1229
1136
  const source_file = ts.createSourceFile("markup-yield.ts", text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
1230
1137
  const replacements = [];
@@ -1286,14 +1193,6 @@ function make_pending_relocation(candidate, replacement_text, expression_text, r
1286
1193
  }
1287
1194
  //#endregion
1288
1195
  //#region src/script-transform/source.ts
1289
- /**
1290
- * Creates a source map from transformed script back to the original block.
1291
- *
1292
- * @since 2.0.0
1293
- * @param magic - MagicString instance holding the transformed source.
1294
- * @param filename - Source filename used for the source map entry.
1295
- * @returns A plain source map object.
1296
- */
1297
1196
  function create_source_map(magic, filename) {
1298
1197
  return magic.generateMap({
1299
1198
  hires: true,
@@ -1301,53 +1200,27 @@ function create_source_map(magic, filename) {
1301
1200
  source: filename
1302
1201
  });
1303
1202
  }
1304
- /**
1305
- * Slices a substring matching a node's full source range.
1306
- *
1307
- * @since 2.0.0
1308
- * @param content - Original source text.
1309
- * @param node - AST node whose full range should be extracted.
1310
- * @returns Source text including leading trivia.
1311
- */
1312
1203
  function slice(content, node) {
1313
1204
  return content.slice(node.getFullStart(), node.end);
1314
1205
  }
1315
- /**
1316
- * Slices a substring matching a node's source range without leading trivia.
1317
- *
1318
- * @since 2.0.0
1319
- * @param content - Original source text.
1320
- * @param node - AST node whose non-trivia range should be extracted.
1321
- * @returns Source text excluding leading trivia.
1322
- */
1323
1206
  function slice_start(content, node) {
1324
1207
  return content.slice(node.getStart(), node.end);
1325
1208
  }
1326
1209
  //#endregion
1327
1210
  //#region src/script-transform/runes.ts
1328
- const ASYNC_EXPRESSION_RUNES = /* @__PURE__ */ new Set([
1211
+ const async_expression_runes = /* @__PURE__ */ new Set([
1329
1212
  "$derived",
1330
1213
  "$state",
1331
1214
  "$state.raw",
1332
1215
  "$state.snapshot",
1333
1216
  "$bindable"
1334
1217
  ]);
1335
- const CALLBACK_RUNES = /* @__PURE__ */ new Set([
1218
+ const callback_runes = /* @__PURE__ */ new Set([
1336
1219
  "$derived.by",
1337
1220
  "$effect",
1338
1221
  "$effect.pre",
1339
1222
  "$effect.root"
1340
1223
  ]);
1341
- /**
1342
- * Validates that `yield*` only appears in rune positions the script-effect
1343
- * transform can lower without changing the rune's normal Svelte contract.
1344
- *
1345
- * @since 2.0.0
1346
- * @param node - AST node to scan.
1347
- * @param content - Original script source used for diagnostics.
1348
- * @param filename - Source filename used for diagnostics.
1349
- * @returns Nothing.
1350
- */
1351
1224
  function validate_rune_yield_usage(node, content, filename) {
1352
1225
  visit_rune_yield_usage(node, content, filename);
1353
1226
  }
@@ -1360,8 +1233,8 @@ function visit_rune_yield_usage(node, content, filename) {
1360
1233
  function validate_call_expression(call, content, filename) {
1361
1234
  const rune_name = get_rune_name(call.expression);
1362
1235
  if (!rune_name) return;
1363
- if (!ASYNC_EXPRESSION_RUNES.has(rune_name) && contains_top_level_yield_star(call)) throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
1364
- if (!CALLBACK_RUNES.has(rune_name)) return;
1236
+ if (!async_expression_runes.has(rune_name) && contains_top_level_yield_star(call)) throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
1237
+ if (!callback_runes.has(rune_name)) return;
1365
1238
  const callback = call.arguments[0];
1366
1239
  if (!callback || !callback_has_top_level_yield_star(callback)) return;
1367
1240
  throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
@@ -1382,29 +1255,10 @@ function is_rune_root(name) {
1382
1255
  }
1383
1256
  //#endregion
1384
1257
  //#region src/markup/transform/scan.ts
1385
- /**
1386
- * Replaces markup `yield*` expressions with placeholders before Svelte parses
1387
- * the component.
1388
- *
1389
- * @example
1390
- * ```ts
1391
- * const sanitized = sanitize_markup(
1392
- * `<p>{yield* loadLabel()}</p>`,
1393
- * "Label.svelte",
1394
- * );
1395
- * ```
1396
- *
1397
- * @since 2.0.0
1398
- * @param content - Raw Svelte component source to scan for effectful markup
1399
- * expressions.
1400
- * @param filename - Source filename used when validation errors need to point
1401
- * back to the component being transformed.
1402
- * @returns Sanitized source plus placeholder candidates that should be lowered
1403
- * after Svelte classifies their markup positions.
1404
- */
1405
- function sanitize_markup(content, filename) {
1258
+ function sanitize_markup(source_scan) {
1259
+ const content = source_scan.source;
1260
+ const filename = source_scan.filename;
1406
1261
  const candidates = [];
1407
- const source_scan = scan_svelte_effect_source(content, filename);
1408
1262
  const magic = new MagicString(content);
1409
1263
  let helper_index = 0;
1410
1264
  for (const expression of source_scan.markup_expressions) {
@@ -1491,11 +1345,30 @@ function sanitize_markup(content, filename) {
1491
1345
  });
1492
1346
  magic.overwrite(expr_start, expr_end, key === "render" ? `${placeholder}()` : placeholder);
1493
1347
  }
1348
+ if (candidates.length === 0) return {
1349
+ parse_code: content,
1350
+ candidates
1351
+ };
1352
+ for (const region of source_scan.scripts) {
1353
+ const region_source = content.slice(region.start, region.end);
1354
+ magic.overwrite(region.start, region.end, blank_script_region(region_source, region.is_module, region.is_typescript));
1355
+ }
1356
+ for (const region of source_scan.styles) {
1357
+ const region_source = content.slice(region.start, region.end);
1358
+ magic.overwrite(region.start, region.end, blank_source_region(region_source));
1359
+ }
1494
1360
  return {
1495
- code: magic.toString(),
1361
+ parse_code: magic.toString(),
1496
1362
  candidates
1497
1363
  };
1498
1364
  }
1365
+ function blank_source_region(source) {
1366
+ return source.replace(/[^\r\n]/g, " ");
1367
+ }
1368
+ function blank_script_region(source, is_module, is_typescript) {
1369
+ const scaffold = `<script${is_module ? " module" : ""}${is_typescript ? " lang=ts" : ""}><\/script>`;
1370
+ return scaffold + blank_source_region(source.slice(scaffold.length));
1371
+ }
1499
1372
  function collect_expression_yield_expressions(content, expr_start, expr_text, filename) {
1500
1373
  const source_file = ts.createSourceFile("markup-expression.ts", `const __SER___expr = ${expr_text};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
1501
1374
  const stmt = source_file.statements[0];
@@ -1552,7 +1425,7 @@ function get_tag_info(trimmed) {
1552
1425
  prefix_length: 7
1553
1426
  };
1554
1427
  if (trimmed.startsWith("@html ")) return {
1555
- kind: "plain",
1428
+ kind: "html",
1556
1429
  prefix_length: 6
1557
1430
  };
1558
1431
  if (trimmed.startsWith("@debug ")) return {
@@ -1607,7 +1480,7 @@ function is_event_callback_expression(inner) {
1607
1480
  function analyze_event_yield(inner) {
1608
1481
  const event = strip_arrow_function(inner);
1609
1482
  const analysis = analyze_event_body_yield_star(event.body);
1610
- if (new RegExp(`${HELPERS.dispatcher}(?:_\\d+)?\\.emit\\(\\{\\s*type:\\s*${HELPERS.codes}(?:_\\d+)?\\.Markup\\.Run`).test(event.body)) return { has_top_level_yield_star: false };
1483
+ if (new RegExp(`${default_helper_bindings.dispatcher}(?:_\\d+)?\\.emit\\(\\{\\s*type:\\s*${default_helper_bindings.codes}(?:_\\d+)?\\.Markup\\.Run`).test(event.body)) return { has_top_level_yield_star: false };
1611
1484
  return { has_top_level_yield_star: analysis.has_top_level_yield_star || analysis.has_nested_invalid_yield_star || /\byield\s*\*/.test(event.body) };
1612
1485
  }
1613
1486
  function contains_yield_star_in_text(text) {
@@ -1655,16 +1528,17 @@ function transform_markup_effect(content, filename, options = {}) {
1655
1528
  code: content,
1656
1529
  has_yield: false
1657
1530
  };
1531
+ const source_scan = scan_svelte_effect_source(content, filename);
1658
1532
  /** Find all brace expressions containing yield* and replace with placeholders. */
1659
- const work = sanitize_markup(content, filename);
1660
- const effect_context = collect_effect_callback_bindings(content);
1661
- const helper_context = make_markup_helper_bindings(content);
1533
+ const work = sanitize_markup(source_scan);
1662
1534
  if (work.candidates.length === 0) return {
1663
1535
  code: content,
1664
1536
  has_yield: false
1665
1537
  };
1538
+ const effect_context = collect_effect_callback_bindings(source_scan.scripts);
1539
+ const helper_context = make_markup_helper_bindings(source_scan, options.target ?? "client");
1666
1540
  /** Match placeholders to their AST context and build replacements. */
1667
- const classified = classify_candidates(parse(blank_script_blocks(work.code), {
1541
+ const classified = classify_candidates(parse(work.parse_code, {
1668
1542
  filename,
1669
1543
  modern: true
1670
1544
  }), work.candidates);
@@ -1676,7 +1550,7 @@ function transform_markup_effect(content, filename, options = {}) {
1676
1550
  const magic = new MagicString(content);
1677
1551
  replacements.sort((a, b) => b.start - a.start);
1678
1552
  for (const r of replacements) magic.overwrite(r.start, r.end, r.text);
1679
- const relocations = create_relocations(replacements, inject_helpers(magic, content, helpers, helper_context.bindings));
1553
+ const relocations = create_relocations(replacements, inject_helpers(magic, source_scan, helpers, helper_context.bindings, helper_context.scope_wiring));
1680
1554
  return {
1681
1555
  code: magic.toString(),
1682
1556
  has_yield: true,
@@ -1685,6 +1559,6 @@ function transform_markup_effect(content, filename, options = {}) {
1685
1559
  };
1686
1560
  }
1687
1561
  //#endregion
1688
- export { slice_start as a, contains_top_level_await as c, collect_top_level_binding_names as d, has_local_import_binding as f, slice as i, find_yield_star_node as l, validate_rune_yield_usage as n, collect_free_identifiers as o, make_imports as p, create_source_map as r, collect_yield_star_nodes as s, transform_markup_effect as t, is_yield_star_expression$1 as u };
1562
+ export { slice_start as a, find_yield_star_node as c, collect_top_level_binding_names as d, has_local_import_binding as f, slice as i, is_yield_star_expression as l, validate_rune_yield_usage as n, collect_yield_star_nodes as o, make_imports as p, create_source_map as r, contains_top_level_await as s, transform_markup_effect as t, collect_free_identifiers as u };
1689
1563
 
1690
- //# sourceMappingURL=transform-jNUr65K9.js.map
1564
+ //# sourceMappingURL=transform-D7TTlPpK.js.map