svelte-effect-runtime 3.4.11 → 4.0.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.
- package/.dist/chunks/client-BrZka6DW.js +530 -0
- package/.dist/chunks/client-BrZka6DW.js.map +1 -0
- package/.dist/chunks/compiler-COVzgLYo.js +412 -0
- package/.dist/chunks/compiler-COVzgLYo.js.map +1 -0
- package/.dist/chunks/descriptors-B4otDlm1.js +216 -0
- package/.dist/chunks/descriptors-B4otDlm1.js.map +1 -0
- package/.dist/chunks/diagnostics-BDrky-Di.js +359 -0
- package/.dist/chunks/diagnostics-BDrky-Di.js.map +1 -0
- package/.dist/chunks/dispatcher-BA0PLQhA.js +16 -0
- package/.dist/chunks/dispatcher-BA0PLQhA.js.map +1 -0
- package/.dist/chunks/{dispatcher-pHH4JcFR.js → dispatcher-_x0MQZBS.js} +84 -258
- package/.dist/chunks/dispatcher-_x0MQZBS.js.map +1 -0
- package/.dist/chunks/{errors-Dcf0MVbq.js → errors-CLsbGjIa.js} +57 -106
- package/.dist/chunks/errors-CLsbGjIa.js.map +1 -0
- package/.dist/chunks/live-BundLSoY.js +146 -0
- package/.dist/chunks/live-BundLSoY.js.map +1 -0
- package/.dist/chunks/live-CHK0RrZu.js +10 -0
- package/.dist/chunks/live-CHK0RrZu.js.map +1 -0
- package/.dist/chunks/{remote-client-Bj1pZXgq.js → remote-client-mkQAfP1G.js} +30 -24
- package/.dist/chunks/remote-client-mkQAfP1G.js.map +1 -0
- package/.dist/chunks/{runtime-ekkMQ-wL.js → runtime-HDTlEnzp.js} +3 -27
- package/.dist/chunks/runtime-HDTlEnzp.js.map +1 -0
- package/.dist/chunks/server-BNrA1I-u.js +144 -0
- package/.dist/chunks/server-BNrA1I-u.js.map +1 -0
- package/.dist/chunks/source-scan-9pZxnfct.js +1059 -0
- package/.dist/chunks/source-scan-9pZxnfct.js.map +1 -0
- package/.dist/chunks/{transform-CtQDGS9c.js → transform-BXyYUAez.js} +308 -484
- package/.dist/chunks/transform-BXyYUAez.js.map +1 -0
- package/.dist/compiler/markup-identifiers.d.ts +2 -0
- package/.dist/compiler/remote-client.d.ts +6 -0
- package/.dist/compiler/source-scan.d.ts +101 -0
- package/.dist/compiler/sveltekit-remote-bridge.d.ts +3 -0
- package/.dist/{vite.d.ts → compiler.d.ts} +7 -1
- package/.dist/{vite.js → compiler.js} +1 -1
- package/.dist/detect.d.ts +0 -31
- package/.dist/detect.js +0 -39
- package/.dist/detect.js.map +1 -1
- package/.dist/diagnostics.d.ts +0 -16
- package/.dist/dispatcher/deps.d.ts +3 -14
- package/.dist/dispatcher/fibers.d.ts +5 -46
- package/.dist/dispatcher/index.d.ts +1 -143
- package/.dist/dispatcher/types.d.ts +0 -151
- package/.dist/dispatcher.js +1 -1
- package/.dist/errors.d.ts +44 -86
- package/.dist/generated/dispatcher.d.ts +0 -50
- package/.dist/generators.d.ts +3 -12
- package/.dist/internal/descriptors.d.ts +0 -16
- package/.dist/internal/generators.js +25 -3
- package/.dist/internal/generators.js.map +1 -0
- package/.dist/internal/live.d.ts +9 -0
- package/.dist/internal/remote-client.js +2 -2
- package/.dist/internal/remote-server.js +2 -2
- package/.dist/internal/schema.d.ts +13 -0
- package/.dist/live.d.ts +106 -0
- package/.dist/markup/event-attributes.d.ts +5 -28
- package/.dist/markup/promise.d.ts +1 -23
- package/.dist/markup/promise.js +2 -18
- package/.dist/markup/promise.js.map +1 -1
- package/.dist/markup/run.d.ts +1 -10
- package/.dist/markup/run.js +2 -11
- package/.dist/markup/run.js.map +1 -1
- package/.dist/markup/transform/apply.d.ts +4 -4
- package/.dist/markup/transform/classify.d.ts +2 -11
- package/.dist/markup/transform/constants.d.ts +2 -1
- package/.dist/markup/transform/effect-bindings.d.ts +2 -26
- package/.dist/markup/transform/effect-callbacks.d.ts +0 -20
- package/.dist/markup/transform/emit.d.ts +2 -11
- package/.dist/markup/transform/expressions.d.ts +0 -35
- package/.dist/markup/transform/scan.d.ts +3 -22
- package/.dist/markup/transform/types.d.ts +2 -129
- package/.dist/markup/transform.js +1 -1
- package/.dist/markup/value.d.ts +1 -18
- package/.dist/markup/value.js +2 -19
- package/.dist/markup/value.js.map +1 -1
- package/.dist/mod.d.ts +6 -8
- package/.dist/mod.js +5 -4
- package/.dist/mod.js.map +1 -1
- package/.dist/remote/cause-codec.d.ts +19 -0
- package/.dist/remote/client/command.d.ts +3 -17
- package/.dist/remote/client/form-data.d.ts +0 -7
- package/.dist/remote/client/form-enhance.d.ts +0 -7
- package/.dist/remote/client/form-transport.d.ts +15 -18
- package/.dist/remote/client/form.d.ts +9 -20
- package/.dist/remote/client/index.d.ts +2 -1
- package/.dist/remote/client/prerender.d.ts +6 -0
- package/.dist/remote/client/query-result.d.ts +2 -14
- package/.dist/remote/client/query.d.ts +9 -59
- package/.dist/remote/client/responses.d.ts +3 -27
- package/.dist/remote/client/types.d.ts +26 -101
- package/.dist/remote/client/utils.d.ts +0 -8
- package/.dist/remote/client.d.ts +2 -2
- package/.dist/remote/client.js +2 -2
- package/.dist/remote/effect.d.ts +6 -0
- package/.dist/remote/failures.d.ts +4 -0
- package/.dist/remote/query-update.d.ts +2 -0
- package/.dist/remote/resource.d.ts +25 -0
- package/.dist/remote/server.d.ts +5 -60
- package/.dist/remote/server.js +2 -179
- package/.dist/remote/shared.d.ts +6 -145
- package/.dist/remote/shared.js +6 -127
- package/.dist/remote/shared.js.map +1 -1
- package/.dist/runtime/transform.js +83 -87
- package/.dist/runtime/transform.js.map +1 -1
- package/.dist/script-transform/ast.d.ts +0 -46
- package/.dist/script-transform/imports.d.ts +2 -38
- package/.dist/script-transform/lower.d.ts +0 -9
- package/.dist/script-transform/runes.d.ts +0 -10
- package/.dist/script-transform/runtime-block.d.ts +0 -17
- package/.dist/script-transform/source.d.ts +0 -24
- package/.dist/script-transform/types.d.ts +9 -126
- package/.dist/server/effects.d.ts +8 -57
- package/.dist/server/factories.d.ts +7 -7
- package/.dist/server/handler.d.ts +37 -0
- package/.dist/server/index.d.ts +4 -1
- package/.dist/server/invalid.d.ts +0 -7
- package/.dist/server/live-snapshot.d.ts +5 -0
- package/.dist/server/remote-handler-context.d.ts +5 -0
- package/.dist/server/runtime.d.ts +6 -24
- package/.dist/server/schema.d.ts +2 -40
- package/.dist/server/transport.d.ts +2 -0
- package/.dist/server/types.d.ts +88 -71
- package/.dist/server/wrappers.d.ts +4 -41
- package/.dist/server.d.ts +2 -2
- package/.dist/server.js +255 -279
- package/.dist/server.js.map +1 -1
- package/.dist/yieldable.d.ts +7 -0
- package/README.md +1 -1
- package/package.json +5 -5
- package/.dist/chunks/client-CsVu54pU.js +0 -627
- package/.dist/chunks/client-CsVu54pU.js.map +0 -1
- package/.dist/chunks/descriptors-cOe9uRJz.js +0 -36
- package/.dist/chunks/descriptors-cOe9uRJz.js.map +0 -1
- package/.dist/chunks/dispatcher-LtvFKYUp.js +0 -47
- package/.dist/chunks/dispatcher-LtvFKYUp.js.map +0 -1
- package/.dist/chunks/dispatcher-pHH4JcFR.js.map +0 -1
- package/.dist/chunks/errors-Dcf0MVbq.js.map +0 -1
- package/.dist/chunks/event-attributes-gHzP2ycp.js +0 -39
- package/.dist/chunks/event-attributes-gHzP2ycp.js.map +0 -1
- package/.dist/chunks/remote-client-Bj1pZXgq.js.map +0 -1
- package/.dist/chunks/runtime-ekkMQ-wL.js.map +0 -1
- package/.dist/chunks/transform-CtQDGS9c.js.map +0 -1
- package/.dist/chunks/vite-WGlbSnso.js +0 -486
- package/.dist/chunks/vite-WGlbSnso.js.map +0 -1
- package/.dist/remote/client/effect.d.ts +0 -29
- package/.dist/remote/client/failures.d.ts +0 -42
- package/.dist/remote/server.js.map +0 -1
- package/.dist/vite/remote-client.d.ts +0 -24
|
@@ -1,51 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { j as YieldStarInEventCallbackError, k as UnsupportedMarkupEffectPositionError, n as AsyncEffectInSyncRuneError, t as AsyncEffectInEventCallbackError } from "./errors-CLsbGjIa.js";
|
|
2
|
+
import { t as scan_svelte_effect_source } from "./source-scan-9pZxnfct.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
8
|
function make_imports(has_effect_import, has_dispatcher_import, has_untrack_import, bindings = {
|
|
21
9
|
cancel: "__SER___cancel",
|
|
22
10
|
dispatcher: "get_dispatcher",
|
|
23
11
|
dispatcher_value: "__SER___dispatcher",
|
|
24
12
|
effect: "Effect",
|
|
25
13
|
program: "__SER___program",
|
|
26
|
-
untrack: "untrack"
|
|
14
|
+
untrack: "untrack",
|
|
15
|
+
yield_success: "YieldSuccess",
|
|
16
|
+
yieldable: "ToEffect"
|
|
27
17
|
}, options = {}) {
|
|
28
18
|
const needs_dispatcher = options.needs_dispatcher ?? true;
|
|
29
19
|
const needs_effect = options.needs_effect ?? true;
|
|
30
20
|
const needs_untrack = options.needs_untrack ?? true;
|
|
31
|
-
const
|
|
21
|
+
const needs_yield_success = options.needs_yield_success ?? false;
|
|
22
|
+
const needs_yieldable = options.needs_yieldable ?? false;
|
|
23
|
+
const generator_import = make_generator_import(bindings, needs_dispatcher && !has_dispatcher_import, needs_yieldable, needs_yield_success);
|
|
32
24
|
const untrack_import = bindings.untrack === "untrack" ? `import { untrack } from "svelte";` : `import { untrack as ${bindings.untrack} } from "svelte";`;
|
|
33
25
|
const effect_import = has_effect_import ? false : bindings.effect === "Effect" ? `import { Effect } from "effect";` : `import { Effect as ${bindings.effect} } from "effect";`;
|
|
34
26
|
return [
|
|
35
|
-
|
|
27
|
+
generator_import,
|
|
36
28
|
needs_untrack && !has_untrack_import && untrack_import,
|
|
37
29
|
needs_effect && effect_import
|
|
38
30
|
].filter(Boolean).join("\n");
|
|
39
31
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
32
|
+
function make_generator_import(bindings, needs_dispatcher, needs_yieldable, needs_yield_success) {
|
|
33
|
+
const specifiers = [
|
|
34
|
+
needs_dispatcher && make_named_import("get_dispatcher", bindings.dispatcher),
|
|
35
|
+
needs_yieldable && make_named_import("ToEffect", bindings.yieldable),
|
|
36
|
+
needs_yield_success && make_named_import("YieldSuccess", bindings.yield_success, true)
|
|
37
|
+
].filter((specifier) => specifier !== false);
|
|
38
|
+
if (specifiers.length === 0) return false;
|
|
39
|
+
return `import { ${specifiers.join(", ")} } from "svelte-effect-runtime/internal/generators";`;
|
|
40
|
+
}
|
|
41
|
+
function make_named_import(imported_name, local_name, type_only = false) {
|
|
42
|
+
const prefix = type_only ? "type " : "";
|
|
43
|
+
return imported_name === local_name ? `${prefix}${imported_name}` : `${prefix}${imported_name} as ${local_name}`;
|
|
44
|
+
}
|
|
49
45
|
function has_local_import_binding(source_file, module_name, local_name) {
|
|
50
46
|
return source_file.statements.some((stmt) => {
|
|
51
47
|
if (!ts.isImportDeclaration(stmt) || !ts.isStringLiteral(stmt.moduleSpecifier) || stmt.moduleSpecifier.text !== module_name) return false;
|
|
@@ -58,13 +54,6 @@ function has_local_import_binding(source_file, module_name, local_name) {
|
|
|
58
54
|
return named_bindings.elements.some((element) => !element.isTypeOnly && element.name.text === local_name);
|
|
59
55
|
});
|
|
60
56
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Collects every local binding declared at module top level.
|
|
63
|
-
*
|
|
64
|
-
* @since 2.4.2
|
|
65
|
-
* @param source_file - Parsed TypeScript source file to inspect.
|
|
66
|
-
* @returns Top-level names declared by imports, declarations, and variables.
|
|
67
|
-
*/
|
|
68
57
|
function collect_top_level_binding_names(source_file) {
|
|
69
58
|
return source_file.statements.flatMap(collect_statement_binding_names);
|
|
70
59
|
}
|
|
@@ -91,10 +80,48 @@ function collect_binding_name_text(name) {
|
|
|
91
80
|
});
|
|
92
81
|
}
|
|
93
82
|
//#endregion
|
|
83
|
+
//#region src/compiler/markup-identifiers.ts
|
|
84
|
+
const wrapper_name = "__SER___markup_identifiers";
|
|
85
|
+
const identifier_names_by_scan = /* @__PURE__ */ new WeakMap();
|
|
86
|
+
function collect_markup_identifier_names(source_scan) {
|
|
87
|
+
const cached_names = identifier_names_by_scan.get(source_scan);
|
|
88
|
+
if (cached_names) return cached_names;
|
|
89
|
+
const names = new Set(source_scan.markup_binding_names);
|
|
90
|
+
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);
|
|
91
|
+
names.delete(wrapper_name);
|
|
92
|
+
identifier_names_by_scan.set(source_scan, names);
|
|
93
|
+
return names;
|
|
94
|
+
}
|
|
95
|
+
function make_identifier_parse_source(expression) {
|
|
96
|
+
const snippet = expression.match(/^(\s*)#snippet\s+([\s\S]*)$/);
|
|
97
|
+
if (snippet) return `function* ${wrapper_name}() { ${snippet[1]}function ${snippet[2]} {} }`;
|
|
98
|
+
return `function* ${wrapper_name}() { ${expression} }`;
|
|
99
|
+
}
|
|
100
|
+
function collect_source_file_identifier_names(source_file, names) {
|
|
101
|
+
const visit = (node) => {
|
|
102
|
+
if (ts.isIdentifier(node) && !is_non_runtime_property_name(node)) names.add(node.text);
|
|
103
|
+
ts.forEachChild(node, visit);
|
|
104
|
+
};
|
|
105
|
+
visit(source_file);
|
|
106
|
+
}
|
|
107
|
+
function is_non_runtime_property_name(identifier) {
|
|
108
|
+
const parent = identifier.parent;
|
|
109
|
+
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;
|
|
110
|
+
}
|
|
111
|
+
function is_within_type_node(identifier) {
|
|
112
|
+
let ancestor = identifier.parent;
|
|
113
|
+
while (ancestor) {
|
|
114
|
+
if (ts.isTypeNode(ancestor)) return true;
|
|
115
|
+
ancestor = ancestor.parent;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
94
120
|
//#region src/markup/transform/constants.ts
|
|
95
|
-
const
|
|
121
|
+
const default_helper_bindings = {
|
|
96
122
|
codes: "Code",
|
|
97
|
-
dispatcher: "Dispatcher"
|
|
123
|
+
dispatcher: "Dispatcher",
|
|
124
|
+
yieldable: "ToEffect"
|
|
98
125
|
};
|
|
99
126
|
//#endregion
|
|
100
127
|
//#region src/markup/transform/apply.ts
|
|
@@ -105,27 +132,22 @@ function create_source_map$1(magic, filename) {
|
|
|
105
132
|
source: filename
|
|
106
133
|
});
|
|
107
134
|
}
|
|
108
|
-
function
|
|
109
|
-
return content.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi, (match) => {
|
|
110
|
-
return match.split("\n").map((l) => " ".repeat(l.length)).join("\n");
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
function inject_helpers(magic, content, helpers = [], bindings = HELPERS) {
|
|
135
|
+
function inject_helpers(magic, source_scan, helpers = [], bindings = default_helper_bindings) {
|
|
114
136
|
const import_helpers = unique_import_helpers(helpers);
|
|
115
137
|
const local_helpers = helpers.filter((helper) => !is_import_helper(helper));
|
|
116
138
|
const helper_segments = [
|
|
117
|
-
|
|
139
|
+
make_dispatcher_import(bindings),
|
|
118
140
|
...import_helpers,
|
|
119
141
|
...local_helpers
|
|
120
142
|
].filter((helper) => helper !== void 0).map((helper) => typeof helper === "string" ? { text: helper } : helper);
|
|
121
143
|
if (helper_segments.length === 0) return;
|
|
122
144
|
const helper_block = helper_segments.map((segment) => segment.text).join("\n");
|
|
123
|
-
const
|
|
124
|
-
if (
|
|
145
|
+
const instance_script = source_scan.instance_script;
|
|
146
|
+
if (instance_script) {
|
|
125
147
|
const text = `\n${helper_block}\n`;
|
|
126
|
-
magic.appendLeft(
|
|
148
|
+
magic.appendLeft(instance_script.content_end, text);
|
|
127
149
|
return {
|
|
128
|
-
start:
|
|
150
|
+
start: instance_script.content_end,
|
|
129
151
|
text,
|
|
130
152
|
relocations: make_insertion_relocations(helper_segments, "\n")
|
|
131
153
|
};
|
|
@@ -139,30 +161,44 @@ function inject_helpers(magic, content, helpers = [], bindings = HELPERS) {
|
|
|
139
161
|
};
|
|
140
162
|
}
|
|
141
163
|
}
|
|
142
|
-
function make_markup_helper_bindings(
|
|
143
|
-
const
|
|
144
|
-
const
|
|
164
|
+
function make_markup_helper_bindings(source_scan) {
|
|
165
|
+
const script_binding_names = source_scan.scripts.flatMap((script) => collect_script_binding_names(script.text));
|
|
166
|
+
const markup_identifier_names = collect_markup_identifier_names(source_scan);
|
|
167
|
+
const name_allocator = make_name_allocator([...script_binding_names, ...markup_identifier_names]);
|
|
145
168
|
return {
|
|
146
169
|
bindings: {
|
|
147
|
-
codes: name_allocator.reserve(
|
|
148
|
-
dispatcher: name_allocator.reserve(
|
|
170
|
+
codes: name_allocator.reserve(default_helper_bindings.codes),
|
|
171
|
+
dispatcher: name_allocator.reserve(default_helper_bindings.dispatcher),
|
|
172
|
+
yieldable: name_allocator.reserve(default_helper_bindings.yieldable)
|
|
149
173
|
},
|
|
150
174
|
name_allocator
|
|
151
175
|
};
|
|
152
176
|
}
|
|
153
177
|
function create_relocations(replacements, helper_insertion) {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
const ordered_replacements = [...replacements].sort((left, right) => left.start - right.start);
|
|
179
|
+
const replacement_deltas = /* @__PURE__ */ new Map();
|
|
180
|
+
let accumulated_delta = 0;
|
|
181
|
+
let replacement_delta_before_helper = 0;
|
|
182
|
+
let cursor = 0;
|
|
183
|
+
while (cursor < ordered_replacements.length) {
|
|
184
|
+
const start = ordered_replacements[cursor]?.start;
|
|
185
|
+
let group_end = cursor;
|
|
186
|
+
let group_delta = 0;
|
|
187
|
+
while (ordered_replacements[group_end]?.start === start) {
|
|
188
|
+
const replacement = ordered_replacements[group_end];
|
|
189
|
+
if (replacement) {
|
|
190
|
+
replacement_deltas.set(replacement, accumulated_delta);
|
|
191
|
+
group_delta += replacement.text.length - (replacement.end - replacement.start);
|
|
192
|
+
}
|
|
193
|
+
group_end += 1;
|
|
194
|
+
}
|
|
195
|
+
if (helper_insertion && start !== void 0 && start < helper_insertion.start) replacement_delta_before_helper += group_delta;
|
|
196
|
+
accumulated_delta += group_delta;
|
|
197
|
+
cursor = group_end;
|
|
198
|
+
}
|
|
163
199
|
const replacement_relocations = replacements.flatMap((replacement) => {
|
|
164
200
|
if (!replacement.relocation) return [];
|
|
165
|
-
const delta_before =
|
|
201
|
+
const delta_before = (replacement_deltas.get(replacement) ?? 0) + (helper_insertion && helper_insertion.start <= replacement.start ? helper_insertion.text.length : 0);
|
|
166
202
|
const generated_start = replacement.start + delta_before;
|
|
167
203
|
return [{
|
|
168
204
|
originalStart: replacement.relocation.originalStart,
|
|
@@ -171,20 +207,17 @@ function create_relocations(replacements, helper_insertion) {
|
|
|
171
207
|
generatedEnd: generated_start + replacement.relocation.generatedEndInReplacement
|
|
172
208
|
}];
|
|
173
209
|
});
|
|
210
|
+
const helper_generated_start = (helper_insertion?.start ?? 0) + replacement_delta_before_helper;
|
|
174
211
|
const helper_relocations = helper_insertion?.relocations?.map((relocation) => ({
|
|
175
212
|
originalStart: relocation.originalStart,
|
|
176
213
|
originalEnd: relocation.originalEnd,
|
|
177
|
-
generatedStart:
|
|
178
|
-
generatedEnd:
|
|
214
|
+
generatedStart: helper_generated_start + relocation.generatedStartInReplacement,
|
|
215
|
+
generatedEnd: helper_generated_start + relocation.generatedEndInReplacement
|
|
179
216
|
})) ?? [];
|
|
180
217
|
return [...replacement_relocations, ...helper_relocations];
|
|
181
218
|
}
|
|
182
|
-
function make_import_helper(content, import_text) {
|
|
183
|
-
if (content.includes(import_text)) return;
|
|
184
|
-
return import_text;
|
|
185
|
-
}
|
|
186
219
|
function make_dispatcher_import(bindings) {
|
|
187
|
-
return `import { ${make_import_specifier(
|
|
220
|
+
return `import { ${make_import_specifier(default_helper_bindings.dispatcher, bindings.dispatcher)}, ${make_import_specifier(default_helper_bindings.codes, bindings.codes)}, ${make_import_specifier(default_helper_bindings.yieldable, bindings.yieldable)} } from "svelte-effect-runtime/internal/generators";`;
|
|
188
221
|
}
|
|
189
222
|
function make_import_specifier(imported_name, local_name) {
|
|
190
223
|
if (imported_name === local_name) return imported_name;
|
|
@@ -204,18 +237,6 @@ function make_insertion_relocations(segments, prefix) {
|
|
|
204
237
|
}
|
|
205
238
|
return relocations;
|
|
206
239
|
}
|
|
207
|
-
function find_instance_script_tag(content) {
|
|
208
|
-
for (const match of content.matchAll(/<script\b([^>]*)>([\s\S]*?)<\/script\s*>/gi)) {
|
|
209
|
-
if (match.index === void 0) continue;
|
|
210
|
-
const attrs = match[1] ?? "";
|
|
211
|
-
if (/\bcontext\s*=\s*["']module["']/.test(attrs) || /\bmodule\b/.test(attrs)) continue;
|
|
212
|
-
const open_end = match[0].indexOf(">") + 1;
|
|
213
|
-
return {
|
|
214
|
-
start: match.index + open_end,
|
|
215
|
-
end: match.index + match[0].length - 9
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
240
|
function unique_import_helpers(helpers) {
|
|
220
241
|
const seen = /* @__PURE__ */ new Set();
|
|
221
242
|
return helpers.filter((helper) => {
|
|
@@ -246,27 +267,12 @@ function make_name_allocator(initial_names) {
|
|
|
246
267
|
}
|
|
247
268
|
//#endregion
|
|
248
269
|
//#region src/markup/transform/effect-bindings.ts
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
* Collects Effect import bindings that markup callback rewriting can trust.
|
|
254
|
-
*
|
|
255
|
-
* @example
|
|
256
|
-
* ```ts
|
|
257
|
-
* const bindings = collect_effect_callback_bindings(
|
|
258
|
-
* `<script>import { Effect as E } from "effect";<\/script>`,
|
|
259
|
-
* );
|
|
260
|
-
* ```
|
|
261
|
-
*
|
|
262
|
-
* @since 2.4.0
|
|
263
|
-
* @param content - Full Svelte component source before markup lowering.
|
|
264
|
-
* @returns Binding metadata used to identify Effect callback combinators.
|
|
265
|
-
*/
|
|
266
|
-
function collect_effect_callback_bindings(content) {
|
|
270
|
+
const effect_package_module = "effect";
|
|
271
|
+
const effect_direct_module = "effect/Effect";
|
|
272
|
+
const generated_effect_name = "__SER___Effect";
|
|
273
|
+
function collect_effect_callback_bindings(scripts) {
|
|
267
274
|
const state = make_effect_binding_state();
|
|
268
|
-
const scripts
|
|
269
|
-
for (const script of scripts) collect_source_file_bindings(ts.createSourceFile("component-script.ts", script, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS), state);
|
|
275
|
+
for (const script of scripts) collect_source_file_bindings(ts.createSourceFile("component-script.ts", script.text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS), state);
|
|
270
276
|
ensure_implicit_effect_binding(state);
|
|
271
277
|
const wrapper = choose_effect_wrapper(state);
|
|
272
278
|
return {
|
|
@@ -288,9 +294,6 @@ function make_effect_binding_state() {
|
|
|
288
294
|
implicit_effect_import: false
|
|
289
295
|
};
|
|
290
296
|
}
|
|
291
|
-
function collect_script_blocks(content) {
|
|
292
|
-
return [...content.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/gi)].map((match) => match[1] ?? "");
|
|
293
|
-
}
|
|
294
297
|
function collect_source_file_bindings(source_file, state) {
|
|
295
298
|
for (const statement of source_file.statements) collect_statement_binding(statement, state);
|
|
296
299
|
}
|
|
@@ -327,21 +330,21 @@ function collect_import_binding(statement, state) {
|
|
|
327
330
|
}
|
|
328
331
|
function collect_namespace_import_binding(module_name, local_name, state) {
|
|
329
332
|
state.local_names.add(local_name);
|
|
330
|
-
if (module_name ===
|
|
333
|
+
if (module_name === effect_direct_module) {
|
|
331
334
|
add_ordered_name(state.effect_module_names, local_name);
|
|
332
335
|
return;
|
|
333
336
|
}
|
|
334
|
-
if (module_name ===
|
|
337
|
+
if (module_name === effect_package_module) add_ordered_name(state.effect_package_names, local_name);
|
|
335
338
|
}
|
|
336
339
|
function collect_named_import_binding(module_name, element, state) {
|
|
337
340
|
const imported_name = element.propertyName?.text ?? element.name.text;
|
|
338
341
|
const local_name = element.name.text;
|
|
339
342
|
state.local_names.add(local_name);
|
|
340
|
-
if (module_name ===
|
|
343
|
+
if (module_name === effect_package_module && imported_name === "Effect") {
|
|
341
344
|
add_ordered_name(state.effect_object_names, local_name);
|
|
342
345
|
return;
|
|
343
346
|
}
|
|
344
|
-
if (module_name ===
|
|
347
|
+
if (module_name === effect_direct_module) state.direct_members.set(local_name, imported_name);
|
|
345
348
|
}
|
|
346
349
|
function collect_binding_name(name, local_names) {
|
|
347
350
|
if (ts.isIdentifier(name)) {
|
|
@@ -363,10 +366,10 @@ function has_effect_binding(state) {
|
|
|
363
366
|
}
|
|
364
367
|
function choose_effect_wrapper(state) {
|
|
365
368
|
const effect_object = state.effect_object_names[0];
|
|
366
|
-
if (effect_object) return {
|
|
369
|
+
if (effect_object) return state.implicit_effect_import ? {
|
|
367
370
|
expression: effect_object,
|
|
368
|
-
import_text:
|
|
369
|
-
};
|
|
371
|
+
import_text: `import { Effect } from "effect";`
|
|
372
|
+
} : { expression: effect_object };
|
|
370
373
|
const effect_module = state.effect_module_names[0];
|
|
371
374
|
if (effect_module) return { expression: effect_module };
|
|
372
375
|
const effect_package = state.effect_package_names[0];
|
|
@@ -378,26 +381,28 @@ function choose_effect_wrapper(state) {
|
|
|
378
381
|
};
|
|
379
382
|
}
|
|
380
383
|
function make_generated_effect_name(local_names) {
|
|
381
|
-
if (!local_names.has(
|
|
384
|
+
if (!local_names.has(generated_effect_name)) return generated_effect_name;
|
|
382
385
|
let index = 1;
|
|
383
|
-
while (local_names.has(`${
|
|
384
|
-
return `${
|
|
386
|
+
while (local_names.has(`${generated_effect_name}_${index}`)) index += 1;
|
|
387
|
+
return `${generated_effect_name}_${index}`;
|
|
385
388
|
}
|
|
386
389
|
function add_ordered_name(names, name) {
|
|
387
390
|
if (names.includes(name)) return;
|
|
388
391
|
names.push(name);
|
|
389
392
|
}
|
|
390
393
|
//#endregion
|
|
394
|
+
//#region src/markup/event-attributes.ts
|
|
395
|
+
function is_svelte_event_attribute(attribute) {
|
|
396
|
+
if (attribute.type !== "Attribute" || !attribute.name?.startsWith("on")) return false;
|
|
397
|
+
const value = attribute.value;
|
|
398
|
+
return value !== true && !Array.isArray(value) || Array.isArray(value) && value.length === 1 && value[0]?.type === "ExpressionTag";
|
|
399
|
+
}
|
|
400
|
+
function normalize_event_attribute_name(name) {
|
|
401
|
+
if (name.startsWith("on:")) return `on:${name.slice(3).toLowerCase()}`;
|
|
402
|
+
return name.toLowerCase();
|
|
403
|
+
}
|
|
404
|
+
//#endregion
|
|
391
405
|
//#region src/markup/transform/classify.ts
|
|
392
|
-
/**
|
|
393
|
-
* Matches sanitized placeholders back to their Svelte AST context.
|
|
394
|
-
*
|
|
395
|
-
* @since 2.0.0
|
|
396
|
-
* @param ast - Parsed Svelte AST for the sanitized component markup.
|
|
397
|
-
* @param candidates - Placeholder candidates produced by the scanner.
|
|
398
|
-
* @returns Candidates paired with the markup context that determines how they
|
|
399
|
-
* should be emitted.
|
|
400
|
-
*/
|
|
401
406
|
function classify_candidates(ast, candidates) {
|
|
402
407
|
const by_placeholder = new Map(candidates.map((candidate) => [candidate.placeholder, candidate]));
|
|
403
408
|
const classified = [];
|
|
@@ -433,7 +438,7 @@ function visit_ast_node(node, candidates, matched, classified) {
|
|
|
433
438
|
classify_expression(node.expression, "render", candidates, matched, classified);
|
|
434
439
|
return;
|
|
435
440
|
case "HtmlTag":
|
|
436
|
-
classify_expression(node.expression, "
|
|
441
|
+
classify_expression(node.expression, "html", candidates, matched, classified);
|
|
437
442
|
return;
|
|
438
443
|
case "DebugTag": return;
|
|
439
444
|
case "ConstTag":
|
|
@@ -447,6 +452,11 @@ function visit_ast_node(node, candidates, matched, classified) {
|
|
|
447
452
|
case "SnippetBlock":
|
|
448
453
|
walk_ast(node.body, candidates, matched, classified);
|
|
449
454
|
return;
|
|
455
|
+
case "SvelteElement":
|
|
456
|
+
classify_expression(node.tag, "plain", candidates, matched, classified);
|
|
457
|
+
visit_element_attributes(node, candidates, matched, classified);
|
|
458
|
+
walk_ast(node.fragment, candidates, matched, classified);
|
|
459
|
+
return;
|
|
450
460
|
case "RegularElement":
|
|
451
461
|
case "Component":
|
|
452
462
|
case "TitleElement":
|
|
@@ -455,7 +465,6 @@ function visit_ast_node(node, candidates, matched, classified) {
|
|
|
455
465
|
case "SvelteBoundary":
|
|
456
466
|
case "SvelteComponent":
|
|
457
467
|
case "SvelteDocument":
|
|
458
|
-
case "SvelteElement":
|
|
459
468
|
case "SvelteFragment":
|
|
460
469
|
case "SvelteHead":
|
|
461
470
|
case "SvelteSelf":
|
|
@@ -471,7 +480,7 @@ function classify_declaration_tag(node, candidates, matched, classified) {
|
|
|
471
480
|
}
|
|
472
481
|
function visit_element_attributes(node, candidates, matched, classified) {
|
|
473
482
|
for (const attr of node.attributes) {
|
|
474
|
-
if (
|
|
483
|
+
if (is_svelte_event_attribute(attr)) {
|
|
475
484
|
const attribute_name_replacement = make_attribute_name_replacement(node, attr);
|
|
476
485
|
visit_attribute_value(attr.value, "event", candidates, matched, classified, attribute_name_replacement);
|
|
477
486
|
continue;
|
|
@@ -558,13 +567,6 @@ function is_record(value) {
|
|
|
558
567
|
}
|
|
559
568
|
//#endregion
|
|
560
569
|
//#region src/markup/transform/expressions.ts
|
|
561
|
-
/**
|
|
562
|
-
* Strips an event handler arrow function down to its executable body.
|
|
563
|
-
*
|
|
564
|
-
* @since 2.0.0
|
|
565
|
-
* @param expr - Event handler expression text from the original markup.
|
|
566
|
-
* @returns Handler parameters, body text, and body offsets inside `expr`.
|
|
567
|
-
*/
|
|
568
570
|
function strip_arrow_function(expr) {
|
|
569
571
|
const arrow_idx = expr.indexOf("=>");
|
|
570
572
|
if (arrow_idx === -1) return {
|
|
@@ -600,13 +602,6 @@ function strip_arrow_function(expr) {
|
|
|
600
602
|
body_end
|
|
601
603
|
};
|
|
602
604
|
}
|
|
603
|
-
/**
|
|
604
|
-
* Returns whether an expression is a callback function.
|
|
605
|
-
*
|
|
606
|
-
* @since 2.0.0
|
|
607
|
-
* @param expr - Expression text from a markup attribute or expression tag.
|
|
608
|
-
* @returns Whether the expression parses as an arrow or function expression.
|
|
609
|
-
*/
|
|
610
605
|
function is_callback_function_expression(expr) {
|
|
611
606
|
const wrapped = `const __SER___callback = ${expr};`;
|
|
612
607
|
const stmt = ts.createSourceFile("callback.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
|
|
@@ -614,20 +609,6 @@ function is_callback_function_expression(expr) {
|
|
|
614
609
|
const initializer = stmt.declarationList.declarations[0]?.initializer;
|
|
615
610
|
return initializer !== void 0 && (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer));
|
|
616
611
|
}
|
|
617
|
-
/**
|
|
618
|
-
* Classifies `yield*` placement inside an event handler body.
|
|
619
|
-
*
|
|
620
|
-
* @example
|
|
621
|
-
* ```ts
|
|
622
|
-
* analyze_event_body_yield_star("yield* save()");
|
|
623
|
-
* ```
|
|
624
|
-
*
|
|
625
|
-
* @since 2.0.0
|
|
626
|
-
* @param body - Event handler body text after the outer arrow has been
|
|
627
|
-
* stripped.
|
|
628
|
-
* @returns Whether the body has top-level yield* expressions and whether any
|
|
629
|
-
* yield* appears inside a nested non-generator callback.
|
|
630
|
-
*/
|
|
631
612
|
function analyze_event_body_yield_star(body) {
|
|
632
613
|
const wrapped = `function* __SER___event() { ${body}; }`;
|
|
633
614
|
const stmt = ts.createSourceFile("event.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
|
|
@@ -642,13 +623,6 @@ function analyze_event_body_yield_star(body) {
|
|
|
642
623
|
visit_event_body(stmt.body, "top_level", result);
|
|
643
624
|
return result;
|
|
644
625
|
}
|
|
645
|
-
/**
|
|
646
|
-
* Collects free identifiers that must be captured as reactive dependencies.
|
|
647
|
-
*
|
|
648
|
-
* @since 2.0.0
|
|
649
|
-
* @param expr_text - Markup expression text to inspect.
|
|
650
|
-
* @returns Identifier names referenced by the expression.
|
|
651
|
-
*/
|
|
652
626
|
function collect_free_identifiers(expr_text) {
|
|
653
627
|
const wrapped = `function* __SER___w() { return (${expr_text}); }`;
|
|
654
628
|
let sf;
|
|
@@ -749,26 +723,6 @@ const effectful_handler_members = /* @__PURE__ */ new Set([
|
|
|
749
723
|
"tapBoth"
|
|
750
724
|
]);
|
|
751
725
|
const effectful_handler_property_names = /* @__PURE__ */ new Set(["onFailure", "onSuccess"]);
|
|
752
|
-
/**
|
|
753
|
-
* Rewrites effectful callback shorthand inside event handler expressions.
|
|
754
|
-
*
|
|
755
|
-
* @example
|
|
756
|
-
* ```ts
|
|
757
|
-
* normalize_effect_callback_yields(
|
|
758
|
-
* `yield* action.pipe(Effect.flatMap((value) => yield* next(value)))`,
|
|
759
|
-
* collect_effect_callback_bindings(source),
|
|
760
|
-
* );
|
|
761
|
-
* ```
|
|
762
|
-
*
|
|
763
|
-
* @since 2.0.0
|
|
764
|
-
* @param expr_text - Markup expression text before it is wrapped in the
|
|
765
|
-
* generated Effect runner.
|
|
766
|
-
* @param bindings - Local Effect import bindings collected from the Svelte
|
|
767
|
-
* component's script blocks.
|
|
768
|
-
* @returns The expression with nested Effect callback `yield*` shorthand
|
|
769
|
-
* lowered into explicit Effect callbacks, plus any import needed by generated
|
|
770
|
-
* wrapper calls.
|
|
771
|
-
*/
|
|
772
726
|
function normalize_effect_callback_yields(expr_text, bindings) {
|
|
773
727
|
const source_text = `const __SER___expression = ${expr_text};`;
|
|
774
728
|
const source_file = ts.createSourceFile("event-expression.ts", source_text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
@@ -954,16 +908,39 @@ function to_expr_pos(pos, context) {
|
|
|
954
908
|
return pos - context.offset;
|
|
955
909
|
}
|
|
956
910
|
//#endregion
|
|
911
|
+
//#region src/script-transform/ast.ts
|
|
912
|
+
function is_yield_star_expression(node) {
|
|
913
|
+
return ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AsteriskToken && ts.isIdentifier(node.left) && node.left.text === "yield";
|
|
914
|
+
}
|
|
915
|
+
function is_function_boundary_node(node) {
|
|
916
|
+
return ts.isArrowFunction(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node);
|
|
917
|
+
}
|
|
918
|
+
function contains_top_level_await(node) {
|
|
919
|
+
if (ts.isAwaitExpression(node)) return true;
|
|
920
|
+
return node.getChildren().some((child) => !is_function_boundary_node(child) && contains_top_level_await(child));
|
|
921
|
+
}
|
|
922
|
+
function collect_yield_star_nodes(node, on_found) {
|
|
923
|
+
if (is_function_boundary_node(node)) return;
|
|
924
|
+
if (is_yield_star_expression(node)) {
|
|
925
|
+
on_found(node);
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
node.forEachChild((child) => {
|
|
929
|
+
collect_yield_star_nodes(child, on_found);
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
function find_yield_star_node(node, on_found) {
|
|
933
|
+
if (is_function_boundary_node(node)) return;
|
|
934
|
+
if (is_yield_star_expression(node)) {
|
|
935
|
+
on_found(node);
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
node.forEachChild((child) => {
|
|
939
|
+
find_yield_star_node(child, on_found);
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
//#endregion
|
|
957
943
|
//#region src/markup/transform/emit.ts
|
|
958
|
-
/**
|
|
959
|
-
* Emits source edits for classified markup Effect expressions.
|
|
960
|
-
*
|
|
961
|
-
* @since 2.0.0
|
|
962
|
-
* @param classified - Candidates paired with their Svelte markup context.
|
|
963
|
-
* @param effect_context - Effect import bindings available to markup
|
|
964
|
-
* expression rewrites.
|
|
965
|
-
* @returns Replacements ready to apply to the original component source.
|
|
966
|
-
*/
|
|
967
944
|
function emit_replacements(classified, effect_context, helper_bindings, name_allocator, target) {
|
|
968
945
|
const expression_replacements = classified.map(({ candidate, kind }) => emit_replacement(candidate, kind, effect_context, helper_bindings, name_allocator, target));
|
|
969
946
|
return [...unique_attribute_name_replacements(classified).map((replacement) => ({
|
|
@@ -996,32 +973,33 @@ function emit_replacement(candidate, kind, effect_context, helper_bindings, name
|
|
|
996
973
|
let helpers;
|
|
997
974
|
let relocation;
|
|
998
975
|
if (kind === "await") {
|
|
999
|
-
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
976
|
+
const effect = make_effect_helper(normalized_candidate, helper_name, helper_bindings);
|
|
1000
977
|
replacement_text = emit_promise_expression(id_text, effect, helper_bindings, "undefined", `{ ssr: "pending" }`);
|
|
1001
978
|
helpers = [...normalized.helpers, effect.helper];
|
|
1002
979
|
} else if (kind === "render") {
|
|
1003
|
-
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
980
|
+
const effect = make_effect_helper(normalized_candidate, helper_name, helper_bindings);
|
|
1004
981
|
replacement_text = emit_render_expression(id_text, effect, candidate, helper_bindings, is_server_target);
|
|
1005
982
|
helpers = [...normalized.helpers, effect.helper];
|
|
1006
983
|
} else if (kind === "render_argument") {
|
|
1007
|
-
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
984
|
+
const effect = make_effect_helper(normalized_candidate, helper_name, helper_bindings);
|
|
1008
985
|
replacement_text = emit_await_expression(id_text, effect, helper_bindings, server_fallback(is_server_target, "undefined"));
|
|
1009
986
|
helpers = [...normalized.helpers, effect.helper];
|
|
1010
987
|
} else if (kind === "each") {
|
|
1011
|
-
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
988
|
+
const effect = make_effect_helper(normalized_candidate, helper_name, helper_bindings);
|
|
1012
989
|
replacement_text = emit_await_expression(id_text, effect, helper_bindings, server_fallback(is_server_target, "[]"));
|
|
1013
990
|
helpers = [...normalized.helpers, effect.helper];
|
|
1014
991
|
} else if (kind === "event") {
|
|
1015
992
|
const event = make_event_handler(normalized_candidate, helper_bindings);
|
|
1016
993
|
replacement_text = event.text;
|
|
1017
994
|
helpers = normalized.helpers;
|
|
1018
|
-
relocation =
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
995
|
+
relocation = make_pending_relocation(candidate, replacement_text, event.expr_text, event.relocation);
|
|
996
|
+
} else if (kind === "html") {
|
|
997
|
+
const effect = make_inline_effect(normalized_candidate, helper_bindings);
|
|
998
|
+
replacement_text = emit_await_expression(id_text, effect, helper_bindings);
|
|
999
|
+
helpers = normalized.helpers;
|
|
1000
|
+
relocation = make_pending_relocation(candidate, replacement_text, effect.effect_text, effect.relocation);
|
|
1023
1001
|
} else {
|
|
1024
|
-
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
1002
|
+
const effect = make_effect_helper(normalized_candidate, helper_name, helper_bindings);
|
|
1025
1003
|
replacement_text = emit_await_expression(id_text, effect, helper_bindings, server_fallback(is_server_target, "undefined"));
|
|
1026
1004
|
helpers = [...normalized.helpers, effect.helper];
|
|
1027
1005
|
}
|
|
@@ -1030,16 +1008,18 @@ function emit_replacement(candidate, kind, effect_context, helper_bindings, name
|
|
|
1030
1008
|
end: candidate.end,
|
|
1031
1009
|
text: replacement_text,
|
|
1032
1010
|
helpers,
|
|
1033
|
-
relocation
|
|
1011
|
+
...relocation ? { relocation } : {}
|
|
1034
1012
|
};
|
|
1035
1013
|
}
|
|
1036
1014
|
function make_event_handler(candidate, helper_bindings) {
|
|
1037
1015
|
const expr_text = candidate.expr_text;
|
|
1038
1016
|
if (is_callback_function_expression(expr_text)) throw new YieldStarInEventCallbackError(candidate.filename, expr_text);
|
|
1039
1017
|
if (analyze_event_body_yield_star(expr_text).has_nested_invalid_yield_star) throw new AsyncEffectInEventCallbackError(candidate.filename, expr_text);
|
|
1018
|
+
const wrapped_expr_text = wrap_yield_stars(expr_text, helper_bindings);
|
|
1040
1019
|
return {
|
|
1041
|
-
expr_text,
|
|
1042
|
-
|
|
1020
|
+
expr_text: wrapped_expr_text,
|
|
1021
|
+
relocation: make_yield_operand_relocation(expr_text, wrapped_expr_text, helper_bindings),
|
|
1022
|
+
text: `(event) => { ${helper_bindings.dispatcher}.emit({ type: ${helper_bindings.codes}.Markup.Run, fn: function* () { ${wrapped_expr_text}; } }); }`
|
|
1043
1023
|
};
|
|
1044
1024
|
}
|
|
1045
1025
|
function emit_promise_expression(id_text, effect, helper_bindings, ssr_fallback, options) {
|
|
@@ -1064,53 +1044,107 @@ function emit_await_expression(id_text, effect, helper_bindings, ssr_fallback) {
|
|
|
1064
1044
|
function server_fallback(is_server_target, fallback) {
|
|
1065
1045
|
return is_server_target ? fallback : void 0;
|
|
1066
1046
|
}
|
|
1067
|
-
function make_effect_helper(candidate, helper_name) {
|
|
1047
|
+
function make_effect_helper(candidate, helper_name, helper_bindings) {
|
|
1068
1048
|
const deps = collect_free_identifiers(candidate.expr_text);
|
|
1069
1049
|
const args_text = deps.join(", ");
|
|
1070
1050
|
const deps_text = deps.length === 0 ? "[]" : `[${args_text}]`;
|
|
1071
1051
|
const call = `${helper_name}()`;
|
|
1072
|
-
const
|
|
1073
|
-
const
|
|
1052
|
+
const effect_text = wrap_yield_stars(candidate.expr_text, helper_bindings);
|
|
1053
|
+
const text = `function* ${helper_name}() { return (${effect_text}); }`;
|
|
1054
|
+
const generated_start = text.indexOf(effect_text);
|
|
1055
|
+
const relocation = make_yield_operand_relocation(candidate.expr_text, effect_text, helper_bindings) ?? {
|
|
1056
|
+
originalStart: 0,
|
|
1057
|
+
originalEnd: candidate.expr_text.length,
|
|
1058
|
+
generatedStart: 0,
|
|
1059
|
+
generatedEnd: effect_text.length
|
|
1060
|
+
};
|
|
1074
1061
|
return {
|
|
1075
1062
|
call,
|
|
1076
1063
|
deps_text,
|
|
1077
1064
|
helper: {
|
|
1078
1065
|
text,
|
|
1079
1066
|
relocation: {
|
|
1080
|
-
originalStart: candidate.start,
|
|
1081
|
-
originalEnd: candidate.
|
|
1082
|
-
generatedStartInReplacement: generated_start,
|
|
1083
|
-
generatedEndInReplacement: generated_start +
|
|
1067
|
+
originalStart: candidate.start + relocation.originalStart,
|
|
1068
|
+
originalEnd: candidate.start + relocation.originalEnd,
|
|
1069
|
+
generatedStartInReplacement: generated_start + relocation.generatedStart,
|
|
1070
|
+
generatedEndInReplacement: generated_start + relocation.generatedEnd
|
|
1084
1071
|
}
|
|
1085
1072
|
}
|
|
1086
1073
|
};
|
|
1087
1074
|
}
|
|
1075
|
+
function make_inline_effect(candidate, helper_bindings) {
|
|
1076
|
+
const deps = collect_free_identifiers(candidate.expr_text);
|
|
1077
|
+
const deps_text = deps.length === 0 ? "[]" : `[${deps.join(", ")}]`;
|
|
1078
|
+
const effect_text = wrap_yield_stars(candidate.expr_text, helper_bindings);
|
|
1079
|
+
const relocation = make_yield_operand_relocation(candidate.expr_text, effect_text, helper_bindings);
|
|
1080
|
+
return {
|
|
1081
|
+
call: `(function* () { return (${effect_text}); })()`,
|
|
1082
|
+
deps_text,
|
|
1083
|
+
effect_text,
|
|
1084
|
+
relocation
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
function wrap_yield_stars(text, helper_bindings) {
|
|
1088
|
+
const source_file = ts.createSourceFile("markup-yield.ts", text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
1089
|
+
const replacements = [];
|
|
1090
|
+
collect_yield_star_nodes(source_file, (node) => {
|
|
1091
|
+
const yield_text = text.slice(node.getStart(source_file), node.end).trim();
|
|
1092
|
+
replacements.push({
|
|
1093
|
+
start: node.getStart(source_file),
|
|
1094
|
+
end: node.end,
|
|
1095
|
+
text: `yield* ${helper_bindings.yieldable}(${strip_yield_star(yield_text)})`
|
|
1096
|
+
});
|
|
1097
|
+
});
|
|
1098
|
+
if (replacements.length === 0) return text;
|
|
1099
|
+
replacements.sort((a, b) => b.start - a.start);
|
|
1100
|
+
let output = text;
|
|
1101
|
+
for (const replacement of replacements) output = output.slice(0, replacement.start) + replacement.text + output.slice(replacement.end);
|
|
1102
|
+
return output;
|
|
1103
|
+
}
|
|
1104
|
+
function strip_yield_star(yield_text) {
|
|
1105
|
+
return yield_text.replace(/^yield\s*\*\s*/, "");
|
|
1106
|
+
}
|
|
1107
|
+
function make_yield_operand_relocation(original_text, generated_text, helper_bindings) {
|
|
1108
|
+
const source_file = ts.createSourceFile("markup-yield-relocation.ts", original_text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
1109
|
+
let yield_node;
|
|
1110
|
+
collect_yield_star_nodes(source_file, (node) => {
|
|
1111
|
+
yield_node ??= node;
|
|
1112
|
+
});
|
|
1113
|
+
if (!yield_node || !ts.isBinaryExpression(yield_node)) return;
|
|
1114
|
+
const operand = yield_node.right;
|
|
1115
|
+
const original_start = operand.getStart(source_file);
|
|
1116
|
+
const original_end = operand.end;
|
|
1117
|
+
const operand_text = original_text.slice(original_start, original_end).trim();
|
|
1118
|
+
const wrapper_text = `${helper_bindings.yieldable}(${operand_text})`;
|
|
1119
|
+
const wrapper_start = generated_text.indexOf(wrapper_text);
|
|
1120
|
+
if (wrapper_start === -1) return;
|
|
1121
|
+
const generated_start = wrapper_start + wrapper_text.indexOf(operand_text);
|
|
1122
|
+
return {
|
|
1123
|
+
originalStart: original_start,
|
|
1124
|
+
originalEnd: original_end,
|
|
1125
|
+
generatedStart: generated_start,
|
|
1126
|
+
generatedEnd: generated_start + operand_text.length
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1088
1129
|
function make_cache_id(candidate) {
|
|
1089
1130
|
return `${candidate.filename.replace(/[?#].*$/, "")}:${candidate.start}:${candidate.end}`;
|
|
1090
1131
|
}
|
|
1091
1132
|
function make_helper_name(candidate, name_allocator) {
|
|
1092
1133
|
return name_allocator.reserve(`__SER___markup_effect_${candidate.start}_${candidate.end}`);
|
|
1093
1134
|
}
|
|
1094
|
-
function
|
|
1095
|
-
|
|
1135
|
+
function make_pending_relocation(candidate, replacement_text, expression_text, relocation) {
|
|
1136
|
+
if (!relocation) return;
|
|
1137
|
+
const generated_start = replacement_text.indexOf(expression_text);
|
|
1096
1138
|
if (generated_start === -1) return;
|
|
1097
1139
|
return {
|
|
1098
|
-
originalStart: candidate.start +
|
|
1099
|
-
originalEnd: candidate.start +
|
|
1100
|
-
generatedStartInReplacement: generated_start,
|
|
1101
|
-
generatedEndInReplacement: generated_start +
|
|
1140
|
+
originalStart: candidate.start + relocation.originalStart,
|
|
1141
|
+
originalEnd: candidate.start + relocation.originalEnd,
|
|
1142
|
+
generatedStartInReplacement: generated_start + relocation.generatedStart,
|
|
1143
|
+
generatedEndInReplacement: generated_start + relocation.generatedEnd
|
|
1102
1144
|
};
|
|
1103
1145
|
}
|
|
1104
1146
|
//#endregion
|
|
1105
1147
|
//#region src/script-transform/source.ts
|
|
1106
|
-
/**
|
|
1107
|
-
* Creates a source map from transformed script back to the original block.
|
|
1108
|
-
*
|
|
1109
|
-
* @since 2.0.0
|
|
1110
|
-
* @param magic - MagicString instance holding the transformed source.
|
|
1111
|
-
* @param filename - Source filename used for the source map entry.
|
|
1112
|
-
* @returns A plain source map object.
|
|
1113
|
-
*/
|
|
1114
1148
|
function create_source_map(magic, filename) {
|
|
1115
1149
|
return magic.generateMap({
|
|
1116
1150
|
hires: true,
|
|
@@ -1118,53 +1152,27 @@ function create_source_map(magic, filename) {
|
|
|
1118
1152
|
source: filename
|
|
1119
1153
|
});
|
|
1120
1154
|
}
|
|
1121
|
-
/**
|
|
1122
|
-
* Slices a substring matching a node's full source range.
|
|
1123
|
-
*
|
|
1124
|
-
* @since 2.0.0
|
|
1125
|
-
* @param content - Original source text.
|
|
1126
|
-
* @param node - AST node whose full range should be extracted.
|
|
1127
|
-
* @returns Source text including leading trivia.
|
|
1128
|
-
*/
|
|
1129
1155
|
function slice(content, node) {
|
|
1130
1156
|
return content.slice(node.getFullStart(), node.end);
|
|
1131
1157
|
}
|
|
1132
|
-
/**
|
|
1133
|
-
* Slices a substring matching a node's source range without leading trivia.
|
|
1134
|
-
*
|
|
1135
|
-
* @since 2.0.0
|
|
1136
|
-
* @param content - Original source text.
|
|
1137
|
-
* @param node - AST node whose non-trivia range should be extracted.
|
|
1138
|
-
* @returns Source text excluding leading trivia.
|
|
1139
|
-
*/
|
|
1140
1158
|
function slice_start(content, node) {
|
|
1141
1159
|
return content.slice(node.getStart(), node.end);
|
|
1142
1160
|
}
|
|
1143
1161
|
//#endregion
|
|
1144
1162
|
//#region src/script-transform/runes.ts
|
|
1145
|
-
const
|
|
1163
|
+
const async_expression_runes = /* @__PURE__ */ new Set([
|
|
1146
1164
|
"$derived",
|
|
1147
1165
|
"$state",
|
|
1148
1166
|
"$state.raw",
|
|
1149
1167
|
"$state.snapshot",
|
|
1150
1168
|
"$bindable"
|
|
1151
1169
|
]);
|
|
1152
|
-
const
|
|
1170
|
+
const callback_runes = /* @__PURE__ */ new Set([
|
|
1153
1171
|
"$derived.by",
|
|
1154
1172
|
"$effect",
|
|
1155
1173
|
"$effect.pre",
|
|
1156
1174
|
"$effect.root"
|
|
1157
1175
|
]);
|
|
1158
|
-
/**
|
|
1159
|
-
* Validates that `yield*` only appears in rune positions the script-effect
|
|
1160
|
-
* transform can lower without changing the rune's normal Svelte contract.
|
|
1161
|
-
*
|
|
1162
|
-
* @since 2.0.0
|
|
1163
|
-
* @param node - AST node to scan.
|
|
1164
|
-
* @param content - Original script source used for diagnostics.
|
|
1165
|
-
* @param filename - Source filename used for diagnostics.
|
|
1166
|
-
* @returns Nothing.
|
|
1167
|
-
*/
|
|
1168
1176
|
function validate_rune_yield_usage(node, content, filename) {
|
|
1169
1177
|
visit_rune_yield_usage(node, content, filename);
|
|
1170
1178
|
}
|
|
@@ -1177,8 +1185,8 @@ function visit_rune_yield_usage(node, content, filename) {
|
|
|
1177
1185
|
function validate_call_expression(call, content, filename) {
|
|
1178
1186
|
const rune_name = get_rune_name(call.expression);
|
|
1179
1187
|
if (!rune_name) return;
|
|
1180
|
-
if (!
|
|
1181
|
-
if (!
|
|
1188
|
+
if (!async_expression_runes.has(rune_name) && contains_top_level_yield_star(call)) throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
|
|
1189
|
+
if (!callback_runes.has(rune_name)) return;
|
|
1182
1190
|
const callback = call.arguments[0];
|
|
1183
1191
|
if (!callback || !callback_has_top_level_yield_star(callback)) return;
|
|
1184
1192
|
throw new AsyncEffectInSyncRuneError(rune_name, slice(content, call), filename);
|
|
@@ -1198,118 +1206,17 @@ function is_rune_root(name) {
|
|
|
1198
1206
|
return name === "$bindable" || name === "$derived" || name === "$effect" || name === "$host" || name === "$inspect" || name === "$props" || name === "$state";
|
|
1199
1207
|
}
|
|
1200
1208
|
//#endregion
|
|
1201
|
-
//#region src/script-transform/ast.ts
|
|
1202
|
-
/**
|
|
1203
|
-
* Checks whether a node is a `yield*` binary expression.
|
|
1204
|
-
*
|
|
1205
|
-
* @since 2.0.0
|
|
1206
|
-
* @param node - TypeScript AST node to check.
|
|
1207
|
-
* @returns Whether the node represents `yield * operand`.
|
|
1208
|
-
*/
|
|
1209
|
-
function is_yield_star_expression(node) {
|
|
1210
|
-
return ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AsteriskToken && ts.isIdentifier(node.left) && node.left.text === "yield";
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* Checks whether a node owns its own yield semantics.
|
|
1214
|
-
*
|
|
1215
|
-
* @since 2.0.0
|
|
1216
|
-
* @param node - TypeScript AST node to check.
|
|
1217
|
-
* @returns Whether traversal should stop at this function boundary.
|
|
1218
|
-
*/
|
|
1219
|
-
function is_function_boundary_node(node) {
|
|
1220
|
-
return ts.isArrowFunction(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node);
|
|
1221
|
-
}
|
|
1222
|
-
/**
|
|
1223
|
-
* Returns `true` if the node tree contains a top-level `await`.
|
|
1224
|
-
*
|
|
1225
|
-
* @since 2.0.0
|
|
1226
|
-
* @param node - Root node to search.
|
|
1227
|
-
* @returns Whether a top-level await expression was found.
|
|
1228
|
-
*/
|
|
1229
|
-
function contains_top_level_await(node) {
|
|
1230
|
-
if (ts.isAwaitExpression(node)) return true;
|
|
1231
|
-
return node.getChildren().some((child) => !is_function_boundary_node(child) && contains_top_level_await(child));
|
|
1232
|
-
}
|
|
1233
|
-
/**
|
|
1234
|
-
* Collects top-level `yield*` nodes under an expression.
|
|
1235
|
-
*
|
|
1236
|
-
* @since 2.0.0
|
|
1237
|
-
* @param node - Root node to search.
|
|
1238
|
-
* @param on_found - Callback invoked for each matching yield node.
|
|
1239
|
-
* @returns Nothing.
|
|
1240
|
-
*/
|
|
1241
|
-
function collect_yield_star_nodes(node, on_found) {
|
|
1242
|
-
if (is_function_boundary_node(node)) return;
|
|
1243
|
-
if (is_yield_star_expression(node)) {
|
|
1244
|
-
on_found(node);
|
|
1245
|
-
return;
|
|
1246
|
-
}
|
|
1247
|
-
node.forEachChild((child) => {
|
|
1248
|
-
collect_yield_star_nodes(child, on_found);
|
|
1249
|
-
});
|
|
1250
|
-
}
|
|
1251
|
-
/**
|
|
1252
|
-
* Finds the first top-level `yield*` expression below a node.
|
|
1253
|
-
*
|
|
1254
|
-
* @since 2.0.0
|
|
1255
|
-
* @param node - Root node to search.
|
|
1256
|
-
* @param on_found - Callback invoked with the first matching node.
|
|
1257
|
-
* @returns Nothing.
|
|
1258
|
-
*/
|
|
1259
|
-
function find_yield_star_node(node, on_found) {
|
|
1260
|
-
if (is_function_boundary_node(node)) return;
|
|
1261
|
-
if (is_yield_star_expression(node)) {
|
|
1262
|
-
on_found(node);
|
|
1263
|
-
return;
|
|
1264
|
-
}
|
|
1265
|
-
node.forEachChild((child) => {
|
|
1266
|
-
find_yield_star_node(child, on_found);
|
|
1267
|
-
});
|
|
1268
|
-
}
|
|
1269
|
-
//#endregion
|
|
1270
1209
|
//#region src/markup/transform/scan.ts
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
*
|
|
1275
|
-
* @example
|
|
1276
|
-
* ```ts
|
|
1277
|
-
* const sanitized = sanitize_markup(
|
|
1278
|
-
* `<p>{yield* loadLabel()}</p>`,
|
|
1279
|
-
* "Label.svelte",
|
|
1280
|
-
* );
|
|
1281
|
-
* ```
|
|
1282
|
-
*
|
|
1283
|
-
* @since 2.0.0
|
|
1284
|
-
* @param content - Raw Svelte component source to scan for effectful markup
|
|
1285
|
-
* expressions.
|
|
1286
|
-
* @param filename - Source filename used when validation errors need to point
|
|
1287
|
-
* back to the component being transformed.
|
|
1288
|
-
* @returns Sanitized source plus placeholder candidates that should be lowered
|
|
1289
|
-
* after Svelte classifies their markup positions.
|
|
1290
|
-
*/
|
|
1291
|
-
function sanitize_markup(content, filename) {
|
|
1210
|
+
function sanitize_markup(source_scan) {
|
|
1211
|
+
const content = source_scan.source;
|
|
1212
|
+
const filename = source_scan.filename;
|
|
1292
1213
|
const candidates = [];
|
|
1293
|
-
const excluded_ranges = collect_excluded_ranges(content);
|
|
1294
1214
|
const magic = new MagicString(content);
|
|
1295
1215
|
let helper_index = 0;
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
/** Skip braces inside <script> and <style> blocks. */
|
|
1301
|
-
const excluded_range = find_excluded_range(excluded_ranges, open);
|
|
1302
|
-
if (excluded_range) {
|
|
1303
|
-
cursor = excluded_range.end;
|
|
1304
|
-
continue;
|
|
1305
|
-
}
|
|
1306
|
-
/** Find the matching closing brace. */
|
|
1307
|
-
const close = find_closing_brace(content, open + 1);
|
|
1308
|
-
if (close === -1) {
|
|
1309
|
-
cursor = open + 1;
|
|
1310
|
-
continue;
|
|
1311
|
-
}
|
|
1312
|
-
const inner = content.slice(open + 1, close);
|
|
1216
|
+
for (const expression of source_scan.markup_expressions) {
|
|
1217
|
+
const open = expression.open;
|
|
1218
|
+
const close = expression.close;
|
|
1219
|
+
const inner = expression.inner;
|
|
1313
1220
|
const trimmed = inner.trimStart();
|
|
1314
1221
|
const leading_ws = inner.length - trimmed.length;
|
|
1315
1222
|
const tag_info = get_tag_info(trimmed);
|
|
@@ -1328,16 +1235,12 @@ function sanitize_markup(content, filename) {
|
|
|
1328
1235
|
});
|
|
1329
1236
|
magic.overwrite(declaration_yield.start, declaration_yield.end, placeholder);
|
|
1330
1237
|
}
|
|
1331
|
-
cursor = close + 1;
|
|
1332
1238
|
continue;
|
|
1333
1239
|
}
|
|
1334
1240
|
let expr_body = trimmed.slice(tag_info.prefix_length);
|
|
1335
1241
|
/** For @const, only use the RHS after `=` as the expression body. */
|
|
1336
1242
|
const equal_idx = tag_info.kind === "plain" && trimmed.startsWith("@const ") ? expr_body.indexOf("=") : -1;
|
|
1337
|
-
if (!((is_event_callback_expression(inner) ? analyze_event_yield(inner) : void 0)?.has_top_level_yield_star ?? contains_yield_star_in_text(expr_body)))
|
|
1338
|
-
cursor = close + 1;
|
|
1339
|
-
continue;
|
|
1340
|
-
}
|
|
1243
|
+
if (!((is_event_callback_expression(inner) ? analyze_event_yield(inner) : void 0)?.has_top_level_yield_star ?? contains_yield_star_in_text(expr_body))) continue;
|
|
1341
1244
|
/** The expression starts after the tag prefix. For @const, after the `=`. */
|
|
1342
1245
|
let extra_prefix = 0;
|
|
1343
1246
|
if (equal_idx !== -1) {
|
|
@@ -1360,10 +1263,7 @@ function sanitize_markup(content, filename) {
|
|
|
1360
1263
|
if (boundary !== Infinity) expr_end = expr_start + boundary;
|
|
1361
1264
|
}
|
|
1362
1265
|
const expr_text = content.slice(expr_start, expr_end).trim();
|
|
1363
|
-
if (expr_text.length === 0)
|
|
1364
|
-
cursor = close + 1;
|
|
1365
|
-
continue;
|
|
1366
|
-
}
|
|
1266
|
+
if (expr_text.length === 0) continue;
|
|
1367
1267
|
validate_expression_yield_usage(expr_text, filename);
|
|
1368
1268
|
if (key === "render" && !/^\s*yield\s*\*/.test(expr_text)) {
|
|
1369
1269
|
const render_arg_yields = collect_expression_yield_expressions(content, expr_start, expr_text, filename);
|
|
@@ -1381,7 +1281,6 @@ function sanitize_markup(content, filename) {
|
|
|
1381
1281
|
});
|
|
1382
1282
|
magic.overwrite(render_arg_yield.start, render_arg_yield.end, placeholder);
|
|
1383
1283
|
}
|
|
1384
|
-
cursor = close + 1;
|
|
1385
1284
|
continue;
|
|
1386
1285
|
}
|
|
1387
1286
|
}
|
|
@@ -1397,13 +1296,31 @@ function sanitize_markup(content, filename) {
|
|
|
1397
1296
|
key
|
|
1398
1297
|
});
|
|
1399
1298
|
magic.overwrite(expr_start, expr_end, key === "render" ? `${placeholder}()` : placeholder);
|
|
1400
|
-
|
|
1299
|
+
}
|
|
1300
|
+
if (candidates.length === 0) return {
|
|
1301
|
+
parse_code: content,
|
|
1302
|
+
candidates
|
|
1303
|
+
};
|
|
1304
|
+
for (const region of source_scan.scripts) {
|
|
1305
|
+
const region_source = content.slice(region.start, region.end);
|
|
1306
|
+
magic.overwrite(region.start, region.end, blank_script_region(region_source, region.is_module, region.is_typescript));
|
|
1307
|
+
}
|
|
1308
|
+
for (const region of source_scan.styles) {
|
|
1309
|
+
const region_source = content.slice(region.start, region.end);
|
|
1310
|
+
magic.overwrite(region.start, region.end, blank_source_region(region_source));
|
|
1401
1311
|
}
|
|
1402
1312
|
return {
|
|
1403
|
-
|
|
1313
|
+
parse_code: magic.toString(),
|
|
1404
1314
|
candidates
|
|
1405
1315
|
};
|
|
1406
1316
|
}
|
|
1317
|
+
function blank_source_region(source) {
|
|
1318
|
+
return source.replace(/[^\r\n]/g, " ");
|
|
1319
|
+
}
|
|
1320
|
+
function blank_script_region(source, is_module, is_typescript) {
|
|
1321
|
+
const scaffold = `<script${is_module ? " module" : ""}${is_typescript ? " lang=ts" : ""}><\/script>`;
|
|
1322
|
+
return scaffold + blank_source_region(source.slice(scaffold.length));
|
|
1323
|
+
}
|
|
1407
1324
|
function collect_expression_yield_expressions(content, expr_start, expr_text, filename) {
|
|
1408
1325
|
const source_file = ts.createSourceFile("markup-expression.ts", `const __SER___expr = ${expr_text};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
1409
1326
|
const stmt = source_file.statements[0];
|
|
@@ -1425,108 +1342,6 @@ function collect_expression_yield_expressions(content, expr_start, expr_text, fi
|
|
|
1425
1342
|
});
|
|
1426
1343
|
return expressions;
|
|
1427
1344
|
}
|
|
1428
|
-
function collect_excluded_ranges(content) {
|
|
1429
|
-
const ranges = [
|
|
1430
|
-
...collect_tag_ranges(content, "script"),
|
|
1431
|
-
...collect_tag_ranges(content, "style"),
|
|
1432
|
-
...collect_html_comment_ranges(content)
|
|
1433
|
-
];
|
|
1434
|
-
ranges.sort((a, b) => a.start - b.start);
|
|
1435
|
-
return merge_ranges(ranges);
|
|
1436
|
-
}
|
|
1437
|
-
function collect_tag_ranges(content, tag) {
|
|
1438
|
-
const pattern = new RegExp(`<${tag}\\b[^>]*>([\\s\\S]*?)<\\/${tag}\\s*>`, "gi");
|
|
1439
|
-
return [...content.matchAll(pattern)].flatMap((match) => {
|
|
1440
|
-
if (match.index === void 0) return [];
|
|
1441
|
-
return [{
|
|
1442
|
-
start: match.index,
|
|
1443
|
-
end: match.index + match[0].length
|
|
1444
|
-
}];
|
|
1445
|
-
});
|
|
1446
|
-
}
|
|
1447
|
-
function collect_html_comment_ranges(content) {
|
|
1448
|
-
const ranges = [];
|
|
1449
|
-
let cursor = 0;
|
|
1450
|
-
while (cursor < content.length) {
|
|
1451
|
-
const start = content.indexOf("<!--", cursor);
|
|
1452
|
-
if (start === -1) break;
|
|
1453
|
-
const close = content.indexOf("-->", start + 4);
|
|
1454
|
-
const end = close === -1 ? content.length : close + 3;
|
|
1455
|
-
ranges.push({
|
|
1456
|
-
start,
|
|
1457
|
-
end
|
|
1458
|
-
});
|
|
1459
|
-
cursor = end;
|
|
1460
|
-
}
|
|
1461
|
-
return ranges;
|
|
1462
|
-
}
|
|
1463
|
-
function merge_ranges(ranges) {
|
|
1464
|
-
const merged = [];
|
|
1465
|
-
for (const range of ranges) {
|
|
1466
|
-
const previous = merged.at(-1);
|
|
1467
|
-
if (!previous || range.start > previous.end) {
|
|
1468
|
-
merged.push({ ...range });
|
|
1469
|
-
continue;
|
|
1470
|
-
}
|
|
1471
|
-
previous.end = Math.max(previous.end, range.end);
|
|
1472
|
-
}
|
|
1473
|
-
return merged;
|
|
1474
|
-
}
|
|
1475
|
-
function find_excluded_range(ranges, pos) {
|
|
1476
|
-
let low = 0;
|
|
1477
|
-
let high = ranges.length - 1;
|
|
1478
|
-
while (low <= high) {
|
|
1479
|
-
const mid = Math.floor((low + high) / 2);
|
|
1480
|
-
const range = ranges[mid];
|
|
1481
|
-
if (pos <= range.start) {
|
|
1482
|
-
high = mid - 1;
|
|
1483
|
-
continue;
|
|
1484
|
-
}
|
|
1485
|
-
if (pos >= range.end) {
|
|
1486
|
-
low = mid + 1;
|
|
1487
|
-
continue;
|
|
1488
|
-
}
|
|
1489
|
-
return range;
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
/** Brace matching helpers for extracting complete markup expressions. */
|
|
1493
|
-
function find_closing_brace(content, start) {
|
|
1494
|
-
let depth = 0;
|
|
1495
|
-
for (let i = start; i < content.length; i += 1) {
|
|
1496
|
-
const ch = content[i];
|
|
1497
|
-
if (ch === "{" && content[i - 1] !== "$") depth += 1;
|
|
1498
|
-
else if (ch === "}") {
|
|
1499
|
-
if (depth === 0) return i;
|
|
1500
|
-
depth -= 1;
|
|
1501
|
-
} else if (ch === "'" || ch === "\"" || ch === "`") {
|
|
1502
|
-
i = skip_string(content, i, ch);
|
|
1503
|
-
if (i === -1) return -1;
|
|
1504
|
-
} else if (ch === "/" && content[i + 1] === "/") i = skip_line_comment(content, i);
|
|
1505
|
-
else if (ch === "/" && content[i + 1] === "*") {
|
|
1506
|
-
i = skip_block_comment(content, i);
|
|
1507
|
-
if (i === -1) return -1;
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
return -1;
|
|
1511
|
-
}
|
|
1512
|
-
function skip_string(content, start, quote) {
|
|
1513
|
-
for (let i = start + 1; i < content.length; i += 1) {
|
|
1514
|
-
if (content[i] === "\\") {
|
|
1515
|
-
i += 1;
|
|
1516
|
-
continue;
|
|
1517
|
-
}
|
|
1518
|
-
if (content[i] === quote) return i;
|
|
1519
|
-
}
|
|
1520
|
-
return -1;
|
|
1521
|
-
}
|
|
1522
|
-
function skip_line_comment(content, start) {
|
|
1523
|
-
for (let i = start + 2; i < content.length; i += 1) if (content[i] === "\n") return i;
|
|
1524
|
-
return content.length;
|
|
1525
|
-
}
|
|
1526
|
-
function skip_block_comment(content, start) {
|
|
1527
|
-
for (let i = start + 2; i < content.length; i += 1) if (content[i] === "*" && content[i + 1] === "/") return i + 1;
|
|
1528
|
-
return -1;
|
|
1529
|
-
}
|
|
1530
1345
|
function get_tag_info(trimmed) {
|
|
1531
1346
|
if (trimmed.startsWith("#each ")) return {
|
|
1532
1347
|
kind: "each",
|
|
@@ -1541,6 +1356,10 @@ function get_tag_info(trimmed) {
|
|
|
1541
1356
|
prefix_length: 8
|
|
1542
1357
|
};
|
|
1543
1358
|
/** Strip prefix-only tags — the expression starts after the tag keyword. */
|
|
1359
|
+
if (trimmed.startsWith("@attach ")) return {
|
|
1360
|
+
kind: "plain",
|
|
1361
|
+
prefix_length: 8
|
|
1362
|
+
};
|
|
1544
1363
|
if (trimmed.startsWith("#if ")) return {
|
|
1545
1364
|
kind: "plain",
|
|
1546
1365
|
prefix_length: 4
|
|
@@ -1558,13 +1377,17 @@ function get_tag_info(trimmed) {
|
|
|
1558
1377
|
prefix_length: 7
|
|
1559
1378
|
};
|
|
1560
1379
|
if (trimmed.startsWith("@html ")) return {
|
|
1561
|
-
kind: "
|
|
1380
|
+
kind: "html",
|
|
1562
1381
|
prefix_length: 6
|
|
1563
1382
|
};
|
|
1564
1383
|
if (trimmed.startsWith("@debug ")) return {
|
|
1565
1384
|
kind: "plain",
|
|
1566
1385
|
prefix_length: 7
|
|
1567
1386
|
};
|
|
1387
|
+
if (trimmed.startsWith("...")) return {
|
|
1388
|
+
kind: "plain",
|
|
1389
|
+
prefix_length: 3
|
|
1390
|
+
};
|
|
1568
1391
|
return {
|
|
1569
1392
|
kind: "plain",
|
|
1570
1393
|
prefix_length: 0
|
|
@@ -1609,7 +1432,7 @@ function is_event_callback_expression(inner) {
|
|
|
1609
1432
|
function analyze_event_yield(inner) {
|
|
1610
1433
|
const event = strip_arrow_function(inner);
|
|
1611
1434
|
const analysis = analyze_event_body_yield_star(event.body);
|
|
1612
|
-
if (new RegExp(`${
|
|
1435
|
+
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 };
|
|
1613
1436
|
return { has_top_level_yield_star: analysis.has_top_level_yield_star || analysis.has_nested_invalid_yield_star || /\byield\s*\*/.test(event.body) };
|
|
1614
1437
|
}
|
|
1615
1438
|
function contains_yield_star_in_text(text) {
|
|
@@ -1657,16 +1480,17 @@ function transform_markup_effect(content, filename, options = {}) {
|
|
|
1657
1480
|
code: content,
|
|
1658
1481
|
has_yield: false
|
|
1659
1482
|
};
|
|
1483
|
+
const source_scan = scan_svelte_effect_source(content, filename);
|
|
1660
1484
|
/** Find all brace expressions containing yield* and replace with placeholders. */
|
|
1661
|
-
const work = sanitize_markup(
|
|
1662
|
-
const effect_context = collect_effect_callback_bindings(content);
|
|
1663
|
-
const helper_context = make_markup_helper_bindings(content);
|
|
1485
|
+
const work = sanitize_markup(source_scan);
|
|
1664
1486
|
if (work.candidates.length === 0) return {
|
|
1665
1487
|
code: content,
|
|
1666
1488
|
has_yield: false
|
|
1667
1489
|
};
|
|
1490
|
+
const effect_context = collect_effect_callback_bindings(source_scan.scripts);
|
|
1491
|
+
const helper_context = make_markup_helper_bindings(source_scan);
|
|
1668
1492
|
/** Match placeholders to their AST context and build replacements. */
|
|
1669
|
-
const classified = classify_candidates(parse(
|
|
1493
|
+
const classified = classify_candidates(parse(work.parse_code, {
|
|
1670
1494
|
filename,
|
|
1671
1495
|
modern: true
|
|
1672
1496
|
}), work.candidates);
|
|
@@ -1678,7 +1502,7 @@ function transform_markup_effect(content, filename, options = {}) {
|
|
|
1678
1502
|
const magic = new MagicString(content);
|
|
1679
1503
|
replacements.sort((a, b) => b.start - a.start);
|
|
1680
1504
|
for (const r of replacements) magic.overwrite(r.start, r.end, r.text);
|
|
1681
|
-
const relocations = create_relocations(replacements, inject_helpers(magic,
|
|
1505
|
+
const relocations = create_relocations(replacements, inject_helpers(magic, source_scan, helpers, helper_context.bindings));
|
|
1682
1506
|
return {
|
|
1683
1507
|
code: magic.toString(),
|
|
1684
1508
|
has_yield: true,
|
|
@@ -1687,6 +1511,6 @@ function transform_markup_effect(content, filename, options = {}) {
|
|
|
1687
1511
|
};
|
|
1688
1512
|
}
|
|
1689
1513
|
//#endregion
|
|
1690
|
-
export {
|
|
1514
|
+
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 };
|
|
1691
1515
|
|
|
1692
|
-
//# sourceMappingURL=transform-
|
|
1516
|
+
//# sourceMappingURL=transform-BXyYUAez.js.map
|