svelte-effect-runtime 2.3.1 → 2.4.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-LYwZZXy7.js → client-CtxuIuC8.js} +4 -5
- package/.dist/chunks/client-CtxuIuC8.js.map +1 -0
- package/.dist/chunks/{descriptors-CU2g4U_i.js → descriptors-OS4VfJuW.js} +1 -1
- package/.dist/chunks/{descriptors-CU2g4U_i.js.map → descriptors-OS4VfJuW.js.map} +1 -1
- package/.dist/chunks/{dispatcher-g0HYqHOK.js → dispatcher-8B6Ol80H.js} +1 -1
- package/.dist/chunks/{dispatcher-g0HYqHOK.js.map → dispatcher-8B6Ol80H.js.map} +1 -1
- package/.dist/chunks/{preprocess-33aQ41uE.js → preprocess-Cn4JH9OO.js} +36 -15
- package/.dist/chunks/preprocess-Cn4JH9OO.js.map +1 -0
- package/.dist/chunks/{transform-B4g76Ur4.js → transform-s9gKPYu5.js} +424 -29
- package/.dist/chunks/transform-s9gKPYu5.js.map +1 -0
- package/.dist/detect.js.map +1 -1
- package/.dist/dispatcher.js +1 -1
- package/.dist/internal/generators.js +1 -1
- package/.dist/internal/remote-client.js +1 -1
- package/.dist/markup/promise.js +1 -1
- package/.dist/markup/promise.js.map +1 -1
- package/.dist/markup/run.js +1 -1
- package/.dist/markup/run.js.map +1 -1
- package/.dist/markup/transform/constants.d.ts +3 -3
- package/.dist/markup/transform/effect-bindings.d.ts +41 -0
- package/.dist/markup/transform/effect-callbacks.d.ts +26 -0
- package/.dist/markup/transform/emit.d.ts +4 -1
- package/.dist/markup/transform.js +1 -1
- package/.dist/markup/value.js +1 -1
- package/.dist/markup/value.js.map +1 -1
- package/.dist/mod.js +1 -1
- package/.dist/mod.js.map +1 -1
- package/.dist/preprocess/imports.d.ts +2 -1
- package/.dist/preprocess.js +2 -2
- package/.dist/remote/client/types.d.ts +7 -7
- package/.dist/remote/client.js +1 -1
- package/.dist/remote/server.js.map +1 -1
- package/.dist/remote/shared.js.map +1 -1
- package/.dist/runtime/preprocess.js +2 -2
- package/.dist/runtime/preprocess.js.map +1 -1
- package/.dist/server/factories.d.ts +10 -1
- package/.dist/server/types.d.ts +10 -1
- package/.dist/server.js +1 -1
- package/.dist/server.js.map +1 -1
- package/.dist/vite.js +41 -6
- package/.dist/vite.js.map +1 -1
- package/package.json +6 -3
- package/.dist/chunks/client-LYwZZXy7.js.map +0 -1
- package/.dist/chunks/preprocess-33aQ41uE.js.map +0 -1
- package/.dist/chunks/transform-B4g76Ur4.js.map +0 -1
|
@@ -4,9 +4,9 @@ import MagicString from "magic-string";
|
|
|
4
4
|
import ts from "typescript";
|
|
5
5
|
//#region src/markup/transform/constants.ts
|
|
6
6
|
const HELPERS = {
|
|
7
|
-
value: "
|
|
8
|
-
promise: "
|
|
9
|
-
run: "
|
|
7
|
+
value: "__SER___markup_value",
|
|
8
|
+
promise: "__SER___markup_promise",
|
|
9
|
+
run: "__SER___markup_run"
|
|
10
10
|
};
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/markup/transform/apply.ts
|
|
@@ -24,11 +24,14 @@ function blank_script_blocks(content) {
|
|
|
24
24
|
}
|
|
25
25
|
function inject_helpers(magic, content, helpers = []) {
|
|
26
26
|
if (content.includes(HELPERS.value)) return;
|
|
27
|
+
const import_helpers = unique_import_helpers(helpers);
|
|
28
|
+
const local_helpers = helpers.filter((helper) => !is_import_helper(helper));
|
|
27
29
|
const helper_segments = [
|
|
28
30
|
`import { value as ${HELPERS.value} } from "svelte-effect-runtime/internal/generators";`,
|
|
29
31
|
`import { promise as ${HELPERS.promise} } from "svelte-effect-runtime/internal/generators";`,
|
|
30
32
|
`import { run as ${HELPERS.run} } from "svelte-effect-runtime/internal/generators";`,
|
|
31
|
-
...
|
|
33
|
+
...import_helpers,
|
|
34
|
+
...local_helpers
|
|
32
35
|
].map((helper) => typeof helper === "string" ? { text: helper } : helper);
|
|
33
36
|
const helper_block = helper_segments.map((segment) => segment.text).join("\n");
|
|
34
37
|
const script_tag = find_instance_script_tag(content);
|
|
@@ -105,6 +108,18 @@ function find_instance_script_tag(content) {
|
|
|
105
108
|
};
|
|
106
109
|
}
|
|
107
110
|
}
|
|
111
|
+
function unique_import_helpers(helpers) {
|
|
112
|
+
const seen = /* @__PURE__ */ new Set();
|
|
113
|
+
return helpers.filter((helper) => {
|
|
114
|
+
if (!is_import_helper(helper)) return false;
|
|
115
|
+
if (seen.has(helper.text)) return false;
|
|
116
|
+
seen.add(helper.text);
|
|
117
|
+
return true;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function is_import_helper(helper) {
|
|
121
|
+
return helper.text.trimStart().startsWith("import ");
|
|
122
|
+
}
|
|
108
123
|
//#endregion
|
|
109
124
|
//#region src/markup/transform/classify.ts
|
|
110
125
|
/**
|
|
@@ -254,6 +269,149 @@ function is_record(value) {
|
|
|
254
269
|
return typeof value === "object" && value !== null;
|
|
255
270
|
}
|
|
256
271
|
//#endregion
|
|
272
|
+
//#region src/markup/transform/effect-bindings.ts
|
|
273
|
+
const EFFECT_PACKAGE_MODULE = "effect";
|
|
274
|
+
const EFFECT_DIRECT_MODULE = "effect/Effect";
|
|
275
|
+
const GENERATED_EFFECT_NAME = "__SER___Effect";
|
|
276
|
+
/**
|
|
277
|
+
* Collects Effect import bindings that markup callback rewriting can trust.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```ts
|
|
281
|
+
* const bindings = collect_effect_callback_bindings(
|
|
282
|
+
* `<script>import { Effect as E } from "effect";<\/script>`,
|
|
283
|
+
* );
|
|
284
|
+
* ```
|
|
285
|
+
*
|
|
286
|
+
* @since 2.4.0
|
|
287
|
+
* @param content - Full Svelte component source before markup lowering.
|
|
288
|
+
* @returns Binding metadata used to identify Effect callback combinators.
|
|
289
|
+
*/
|
|
290
|
+
function collect_effect_callback_bindings(content) {
|
|
291
|
+
const state = make_effect_binding_state();
|
|
292
|
+
const scripts = collect_script_blocks(content);
|
|
293
|
+
for (const script of scripts) collect_source_file_bindings(ts.createSourceFile("component-script.ts", script, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS), state);
|
|
294
|
+
ensure_implicit_effect_binding(state);
|
|
295
|
+
const wrapper = choose_effect_wrapper(state);
|
|
296
|
+
return {
|
|
297
|
+
effect_object_names: new Set(state.effect_object_names),
|
|
298
|
+
effect_module_names: new Set(state.effect_module_names),
|
|
299
|
+
effect_package_names: new Set(state.effect_package_names),
|
|
300
|
+
direct_members: new Map(state.direct_members),
|
|
301
|
+
wrapper_expression: wrapper.expression,
|
|
302
|
+
wrapper_import: wrapper.import_text ? { text: wrapper.import_text } : void 0
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function make_effect_binding_state() {
|
|
306
|
+
return {
|
|
307
|
+
effect_object_names: [],
|
|
308
|
+
effect_module_names: [],
|
|
309
|
+
effect_package_names: [],
|
|
310
|
+
direct_members: /* @__PURE__ */ new Map(),
|
|
311
|
+
local_names: /* @__PURE__ */ new Set(),
|
|
312
|
+
implicit_effect_import: false
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function collect_script_blocks(content) {
|
|
316
|
+
return [...content.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/gi)].map((match) => match[1] ?? "");
|
|
317
|
+
}
|
|
318
|
+
function collect_source_file_bindings(source_file, state) {
|
|
319
|
+
for (const statement of source_file.statements) collect_statement_binding(statement, state);
|
|
320
|
+
}
|
|
321
|
+
function collect_statement_binding(statement, state) {
|
|
322
|
+
if (ts.isImportDeclaration(statement)) {
|
|
323
|
+
collect_import_binding(statement, state);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (ts.isImportEqualsDeclaration(statement)) {
|
|
327
|
+
state.local_names.add(statement.name.text);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (ts.isVariableStatement(statement)) {
|
|
331
|
+
for (const declaration of statement.declarationList.declarations) collect_binding_name(declaration.name, state.local_names);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement) || ts.isInterfaceDeclaration(statement) || ts.isTypeAliasDeclaration(statement) || ts.isEnumDeclaration(statement) || ts.isModuleDeclaration(statement)) {
|
|
335
|
+
if (statement.name) state.local_names.add(statement.name.text);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function collect_import_binding(statement, state) {
|
|
339
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier)) return;
|
|
340
|
+
const module_name = statement.moduleSpecifier.text;
|
|
341
|
+
const clause = statement.importClause;
|
|
342
|
+
if (!clause) return;
|
|
343
|
+
if (clause.name) state.local_names.add(clause.name.text);
|
|
344
|
+
const named_bindings = clause.namedBindings;
|
|
345
|
+
if (!named_bindings) return;
|
|
346
|
+
if (ts.isNamespaceImport(named_bindings)) {
|
|
347
|
+
collect_namespace_import_binding(module_name, named_bindings.name.text, state);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
for (const element of named_bindings.elements) collect_named_import_binding(module_name, element, state);
|
|
351
|
+
}
|
|
352
|
+
function collect_namespace_import_binding(module_name, local_name, state) {
|
|
353
|
+
state.local_names.add(local_name);
|
|
354
|
+
if (module_name === EFFECT_DIRECT_MODULE) {
|
|
355
|
+
add_ordered_name(state.effect_module_names, local_name);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if (module_name === EFFECT_PACKAGE_MODULE) add_ordered_name(state.effect_package_names, local_name);
|
|
359
|
+
}
|
|
360
|
+
function collect_named_import_binding(module_name, element, state) {
|
|
361
|
+
const imported_name = element.propertyName?.text ?? element.name.text;
|
|
362
|
+
const local_name = element.name.text;
|
|
363
|
+
state.local_names.add(local_name);
|
|
364
|
+
if (module_name === EFFECT_PACKAGE_MODULE && imported_name === "Effect") {
|
|
365
|
+
add_ordered_name(state.effect_object_names, local_name);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (module_name === EFFECT_DIRECT_MODULE) state.direct_members.set(local_name, imported_name);
|
|
369
|
+
}
|
|
370
|
+
function collect_binding_name(name, local_names) {
|
|
371
|
+
if (ts.isIdentifier(name)) {
|
|
372
|
+
local_names.add(name.text);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
for (const element of name.elements) {
|
|
376
|
+
if (ts.isOmittedExpression(element)) continue;
|
|
377
|
+
collect_binding_name(element.name, local_names);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function ensure_implicit_effect_binding(state) {
|
|
381
|
+
if (has_effect_binding(state) || state.local_names.has("Effect")) return;
|
|
382
|
+
add_ordered_name(state.effect_object_names, "Effect");
|
|
383
|
+
state.implicit_effect_import = true;
|
|
384
|
+
}
|
|
385
|
+
function has_effect_binding(state) {
|
|
386
|
+
return state.effect_object_names.length > 0 || state.effect_module_names.length > 0 || state.effect_package_names.length > 0 || state.direct_members.size > 0;
|
|
387
|
+
}
|
|
388
|
+
function choose_effect_wrapper(state) {
|
|
389
|
+
const effect_object = state.effect_object_names[0];
|
|
390
|
+
if (effect_object) return {
|
|
391
|
+
expression: effect_object,
|
|
392
|
+
import_text: state.implicit_effect_import ? `import { Effect } from "effect";` : void 0
|
|
393
|
+
};
|
|
394
|
+
const effect_module = state.effect_module_names[0];
|
|
395
|
+
if (effect_module) return { expression: effect_module };
|
|
396
|
+
const effect_package = state.effect_package_names[0];
|
|
397
|
+
if (effect_package) return { expression: `${effect_package}.Effect` };
|
|
398
|
+
const generated_name = make_generated_effect_name(state.local_names);
|
|
399
|
+
return {
|
|
400
|
+
expression: generated_name,
|
|
401
|
+
import_text: `import { Effect as ${generated_name} } from "effect";`
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function make_generated_effect_name(local_names) {
|
|
405
|
+
if (!local_names.has(GENERATED_EFFECT_NAME)) return GENERATED_EFFECT_NAME;
|
|
406
|
+
let index = 1;
|
|
407
|
+
while (local_names.has(`${GENERATED_EFFECT_NAME}_${index}`)) index += 1;
|
|
408
|
+
return `${GENERATED_EFFECT_NAME}_${index}`;
|
|
409
|
+
}
|
|
410
|
+
function add_ordered_name(names, name) {
|
|
411
|
+
if (names.includes(name)) return;
|
|
412
|
+
names.push(name);
|
|
413
|
+
}
|
|
414
|
+
//#endregion
|
|
257
415
|
//#region src/error.ts
|
|
258
416
|
/**
|
|
259
417
|
* Formats a runtime-owned error message with a stable screaming-case code.
|
|
@@ -483,7 +641,7 @@ function strip_arrow_function(expr) {
|
|
|
483
641
|
* @returns Whether the expression parses as an arrow or function expression.
|
|
484
642
|
*/
|
|
485
643
|
function is_callback_function_expression(expr) {
|
|
486
|
-
const wrapped = `const
|
|
644
|
+
const wrapped = `const __SER___callback = ${expr};`;
|
|
487
645
|
const stmt = ts.createSourceFile("callback.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
|
|
488
646
|
if (!ts.isVariableStatement(stmt)) return false;
|
|
489
647
|
const initializer = stmt.declarationList.declarations[0]?.initializer;
|
|
@@ -504,7 +662,7 @@ function is_callback_function_expression(expr) {
|
|
|
504
662
|
* yield* appears inside a nested non-generator callback.
|
|
505
663
|
*/
|
|
506
664
|
function analyze_event_body_yield_star(body) {
|
|
507
|
-
const wrapped = `function*
|
|
665
|
+
const wrapped = `function* __SER___event() { ${body}; }`;
|
|
508
666
|
const stmt = ts.createSourceFile("event.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS).statements[0];
|
|
509
667
|
if (!ts.isFunctionDeclaration(stmt) || !stmt.body) return {
|
|
510
668
|
has_top_level_yield_star: false,
|
|
@@ -525,7 +683,7 @@ function analyze_event_body_yield_star(body) {
|
|
|
525
683
|
* @returns Identifier names referenced by the expression.
|
|
526
684
|
*/
|
|
527
685
|
function collect_free_identifiers(expr_text) {
|
|
528
|
-
const wrapped = `function*
|
|
686
|
+
const wrapped = `function* __SER___w() { return (${expr_text}); }`;
|
|
529
687
|
let sf;
|
|
530
688
|
try {
|
|
531
689
|
sf = ts.createSourceFile("expr.ts", wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
@@ -581,18 +739,249 @@ function is_property_access_name(node) {
|
|
|
581
739
|
return ts.isPropertyAccessExpression(parent) && parent.name === node || ts.isPropertyAssignment(parent) && parent.name === node || ts.isBindingElement(parent) && parent.propertyName === node || ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent);
|
|
582
740
|
}
|
|
583
741
|
//#endregion
|
|
742
|
+
//#region src/markup/transform/effect-callbacks.ts
|
|
743
|
+
const MATCH_EFFECT_MEMBERS = new Map([["match", "matchEffect"], ["matchCause", "matchCauseEffect"]]);
|
|
744
|
+
const EFFECTFUL_CALLBACK_MEMBERS = new Set([
|
|
745
|
+
"andThen",
|
|
746
|
+
"catchAll",
|
|
747
|
+
"catchAllCause",
|
|
748
|
+
"catchCause",
|
|
749
|
+
"catchTag",
|
|
750
|
+
"flatMap",
|
|
751
|
+
"forEach",
|
|
752
|
+
"tap",
|
|
753
|
+
"tapError",
|
|
754
|
+
"tapErrorCause"
|
|
755
|
+
]);
|
|
756
|
+
const EFFECTFUL_HANDLER_MEMBERS = new Set([
|
|
757
|
+
"matchCauseEffect",
|
|
758
|
+
"matchEffect",
|
|
759
|
+
"tapBoth"
|
|
760
|
+
]);
|
|
761
|
+
/**
|
|
762
|
+
* Rewrites effectful callback shorthand inside event handler expressions.
|
|
763
|
+
*
|
|
764
|
+
* @example
|
|
765
|
+
* ```ts
|
|
766
|
+
* normalize_effect_callback_yields(
|
|
767
|
+
* `yield* action.pipe(Effect.flatMap((value) => yield* next(value)))`,
|
|
768
|
+
* collect_effect_callback_bindings(source),
|
|
769
|
+
* );
|
|
770
|
+
* ```
|
|
771
|
+
*
|
|
772
|
+
* @since 2.0.0
|
|
773
|
+
* @param expr_text - Markup expression text before it is wrapped in the
|
|
774
|
+
* generated Effect runner.
|
|
775
|
+
* @param bindings - Local Effect import bindings collected from the Svelte
|
|
776
|
+
* component's script blocks.
|
|
777
|
+
* @returns The expression with nested Effect callback `yield*` shorthand
|
|
778
|
+
* lowered into explicit Effect callbacks, plus any import needed by generated
|
|
779
|
+
* wrapper calls.
|
|
780
|
+
*/
|
|
781
|
+
function normalize_effect_callback_yields(expr_text, bindings) {
|
|
782
|
+
const source_text = `const __SER___expression = ${expr_text};`;
|
|
783
|
+
const source_file = ts.createSourceFile("event-expression.ts", source_text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
784
|
+
const statement = source_file.statements[0];
|
|
785
|
+
const magic = new MagicString(expr_text);
|
|
786
|
+
const context = {
|
|
787
|
+
source_file,
|
|
788
|
+
source_text,
|
|
789
|
+
magic,
|
|
790
|
+
offset: 27,
|
|
791
|
+
bindings,
|
|
792
|
+
changed: false,
|
|
793
|
+
uses_wrapper: false
|
|
794
|
+
};
|
|
795
|
+
if (!ts.isVariableStatement(statement)) return {
|
|
796
|
+
expr_text,
|
|
797
|
+
helpers: []
|
|
798
|
+
};
|
|
799
|
+
const expression = statement.declarationList.declarations[0]?.initializer;
|
|
800
|
+
if (!expression) return {
|
|
801
|
+
expr_text,
|
|
802
|
+
helpers: []
|
|
803
|
+
};
|
|
804
|
+
visit_expression(expression, context);
|
|
805
|
+
if (!context.changed) return {
|
|
806
|
+
expr_text,
|
|
807
|
+
helpers: []
|
|
808
|
+
};
|
|
809
|
+
const helpers = context.uses_wrapper && bindings.wrapper_import ? [bindings.wrapper_import] : [];
|
|
810
|
+
return {
|
|
811
|
+
expr_text: magic.toString(),
|
|
812
|
+
helpers
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
function visit_expression(node, context) {
|
|
816
|
+
if (is_non_generator_callback_with_top_level_yield(node)) return;
|
|
817
|
+
if (ts.isCallExpression(node)) {
|
|
818
|
+
rewrite_match_call(node, context);
|
|
819
|
+
rewrite_effectful_handler_call(node, context);
|
|
820
|
+
rewrite_effectful_callback_arguments(node, context);
|
|
821
|
+
}
|
|
822
|
+
node.forEachChild((child) => {
|
|
823
|
+
visit_expression(child, context);
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
function rewrite_match_call(call, context) {
|
|
827
|
+
const member = get_effect_member(call.expression, context);
|
|
828
|
+
const upgraded_name = member && MATCH_EFFECT_MEMBERS.get(member.name);
|
|
829
|
+
const options = get_last_object_argument(call);
|
|
830
|
+
if (!member || !upgraded_name || !options) return;
|
|
831
|
+
const handlers = get_handler_properties(options);
|
|
832
|
+
if (!handlers.some((handler) => handler.callback && is_non_generator_callback_with_top_level_yield(handler.callback))) return;
|
|
833
|
+
rewrite_effect_member_name(member, upgraded_name, context);
|
|
834
|
+
context.changed = true;
|
|
835
|
+
for (const handler of handlers) {
|
|
836
|
+
if (!handler.callback) continue;
|
|
837
|
+
if (is_non_generator_callback_with_top_level_yield(handler.callback)) rewrite_callback_to_effect_gen(handler.callback, context);
|
|
838
|
+
else rewrite_callback_to_effect_sync(handler.callback, context);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
function rewrite_effectful_handler_call(call, context) {
|
|
842
|
+
const member = get_effect_member(call.expression, context);
|
|
843
|
+
const options = get_last_object_argument(call);
|
|
844
|
+
if (!member || !EFFECTFUL_HANDLER_MEMBERS.has(member.name) || !options) return;
|
|
845
|
+
for (const handler of get_handler_properties(options)) if (handler.callback && is_non_generator_callback_with_top_level_yield(handler.callback)) rewrite_callback_to_effect_gen(handler.callback, context);
|
|
846
|
+
}
|
|
847
|
+
function rewrite_effectful_callback_arguments(call, context) {
|
|
848
|
+
const member = get_effect_member(call.expression, context);
|
|
849
|
+
if (!member || !EFFECTFUL_CALLBACK_MEMBERS.has(member.name)) return;
|
|
850
|
+
for (const argument of call.arguments) if (is_callback_expression(argument) && is_non_generator_callback_with_top_level_yield(argument)) rewrite_callback_to_effect_gen(argument, context);
|
|
851
|
+
}
|
|
852
|
+
function rewrite_callback_to_effect_gen(callback, context) {
|
|
853
|
+
if (is_async_function(callback)) return;
|
|
854
|
+
if (ts.isArrowFunction(callback)) {
|
|
855
|
+
rewrite_arrow_callback(callback, "gen", context);
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
rewrite_function_body(callback, "gen", context);
|
|
859
|
+
}
|
|
860
|
+
function rewrite_callback_to_effect_sync(callback, context) {
|
|
861
|
+
if (is_async_function(callback)) return;
|
|
862
|
+
if (ts.isArrowFunction(callback)) {
|
|
863
|
+
rewrite_arrow_callback(callback, "sync", context);
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
rewrite_function_body(callback, "sync", context);
|
|
867
|
+
}
|
|
868
|
+
function rewrite_arrow_callback(callback, wrapper, context) {
|
|
869
|
+
const start = to_expr_pos(callback.getStart(context.source_file), context);
|
|
870
|
+
const end = to_expr_pos(callback.end, context);
|
|
871
|
+
const params_text = context.source_text.slice(callback.getStart(context.source_file), callback.equalsGreaterThanToken.getStart(context.source_file)).trim();
|
|
872
|
+
const body_text = get_body_text(callback.body, context);
|
|
873
|
+
const replacement = `${params_text} => ${make_effect_body(callback.body, body_text, wrapper, context)}`;
|
|
874
|
+
context.magic.overwrite(start, end, replacement);
|
|
875
|
+
context.changed = true;
|
|
876
|
+
}
|
|
877
|
+
function rewrite_function_body(callback, wrapper, context) {
|
|
878
|
+
const body_start = to_expr_pos(callback.body.getStart(context.source_file), context);
|
|
879
|
+
const body_end = to_expr_pos(callback.body.end, context);
|
|
880
|
+
const body_text = get_body_text(callback.body, context);
|
|
881
|
+
const rewritten_body = make_effect_body(callback.body, body_text, wrapper, context);
|
|
882
|
+
context.magic.overwrite(body_start, body_end, `{ return ${rewritten_body}; }`);
|
|
883
|
+
context.changed = true;
|
|
884
|
+
}
|
|
885
|
+
function make_effect_body(body, body_text, wrapper, context) {
|
|
886
|
+
const wrapper_access = make_effect_access(wrapper, context);
|
|
887
|
+
if (wrapper === "gen") {
|
|
888
|
+
if (ts.isBlock(body)) return `${wrapper_access}(function* () ${body_text})`;
|
|
889
|
+
return `${wrapper_access}(function* () { return (${body_text}); })`;
|
|
890
|
+
}
|
|
891
|
+
if (ts.isBlock(body)) return `${wrapper_access}(() => ${body_text})`;
|
|
892
|
+
return `${wrapper_access}(() => (${body_text}))`;
|
|
893
|
+
}
|
|
894
|
+
function get_body_text(body, context) {
|
|
895
|
+
return context.source_text.slice(body.getStart(context.source_file), body.end).trim();
|
|
896
|
+
}
|
|
897
|
+
function get_handler_properties(object_literal) {
|
|
898
|
+
return object_literal.properties.flatMap((property) => {
|
|
899
|
+
if (!ts.isPropertyAssignment(property)) return [];
|
|
900
|
+
const name = get_property_name(property.name);
|
|
901
|
+
if (name !== "onFailure" && name !== "onSuccess") return [];
|
|
902
|
+
return [{ callback: is_callback_expression(property.initializer) ? property.initializer : void 0 }];
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
function get_last_object_argument(call) {
|
|
906
|
+
const last_argument = call.arguments[call.arguments.length - 1];
|
|
907
|
+
if (!last_argument || !ts.isObjectLiteralExpression(last_argument)) return;
|
|
908
|
+
return last_argument;
|
|
909
|
+
}
|
|
910
|
+
function get_effect_member(expression, context) {
|
|
911
|
+
if (ts.isIdentifier(expression)) {
|
|
912
|
+
const direct_member = context.bindings.direct_members.get(expression.text);
|
|
913
|
+
if (!direct_member) return;
|
|
914
|
+
return {
|
|
915
|
+
name: direct_member,
|
|
916
|
+
name_start: to_expr_pos(expression.getStart(context.source_file), context),
|
|
917
|
+
name_end: to_expr_pos(expression.end, context),
|
|
918
|
+
direct: true
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
if (!ts.isPropertyAccessExpression(expression)) return;
|
|
922
|
+
if (!is_effect_namespace_expression(expression.expression, context)) return;
|
|
923
|
+
return {
|
|
924
|
+
name: expression.name.text,
|
|
925
|
+
name_start: to_expr_pos(expression.name.getStart(context.source_file), context),
|
|
926
|
+
name_end: to_expr_pos(expression.name.end, context),
|
|
927
|
+
direct: false
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
function rewrite_effect_member_name(member, upgraded_name, context) {
|
|
931
|
+
if (member.direct) {
|
|
932
|
+
context.magic.overwrite(member.name_start, member.name_end, make_effect_access(upgraded_name, context));
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
context.magic.overwrite(member.name_start, member.name_end, upgraded_name);
|
|
936
|
+
}
|
|
937
|
+
function make_effect_access(member_name, context) {
|
|
938
|
+
context.uses_wrapper = true;
|
|
939
|
+
return `${context.bindings.wrapper_expression}.${member_name}`;
|
|
940
|
+
}
|
|
941
|
+
function is_effect_namespace_expression(expression, context) {
|
|
942
|
+
if (ts.isIdentifier(expression)) return context.bindings.effect_object_names.has(expression.text) || context.bindings.effect_module_names.has(expression.text);
|
|
943
|
+
if (!ts.isPropertyAccessExpression(expression)) return false;
|
|
944
|
+
if (expression.name.text !== "Effect") return false;
|
|
945
|
+
if (!ts.isIdentifier(expression.expression)) return false;
|
|
946
|
+
return context.bindings.effect_package_names.has(expression.expression.text);
|
|
947
|
+
}
|
|
948
|
+
function get_property_name(name) {
|
|
949
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) return name.text;
|
|
950
|
+
}
|
|
951
|
+
function is_callback_expression(node) {
|
|
952
|
+
return ts.isArrowFunction(node) || ts.isFunctionExpression(node);
|
|
953
|
+
}
|
|
954
|
+
function is_non_generator_callback_with_top_level_yield(node) {
|
|
955
|
+
if (!is_callback_expression(node)) return false;
|
|
956
|
+
if (ts.isFunctionExpression(node) && node.asteriskToken) return false;
|
|
957
|
+
return contains_top_level_yield_star(node.body);
|
|
958
|
+
}
|
|
959
|
+
function is_async_function(node) {
|
|
960
|
+
return node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) ?? false;
|
|
961
|
+
}
|
|
962
|
+
function to_expr_pos(pos, context) {
|
|
963
|
+
return pos - context.offset;
|
|
964
|
+
}
|
|
965
|
+
//#endregion
|
|
584
966
|
//#region src/markup/transform/emit.ts
|
|
585
967
|
/**
|
|
586
968
|
* Emits source edits for classified markup Effect expressions.
|
|
587
969
|
*
|
|
588
970
|
* @since 2.0.0
|
|
589
971
|
* @param classified - Candidates paired with their Svelte markup context.
|
|
972
|
+
* @param effect_context - Effect import bindings available to markup
|
|
973
|
+
* expression rewrites.
|
|
590
974
|
* @returns Replacements ready to apply to the original component source.
|
|
591
975
|
*/
|
|
592
|
-
function emit_replacements(classified) {
|
|
593
|
-
return classified.map(({ candidate, kind }) => emit_replacement(candidate, kind));
|
|
976
|
+
function emit_replacements(classified, effect_context) {
|
|
977
|
+
return classified.map(({ candidate, kind }) => emit_replacement(candidate, kind, effect_context));
|
|
594
978
|
}
|
|
595
|
-
function emit_replacement(candidate, kind) {
|
|
979
|
+
function emit_replacement(candidate, kind, effect_context) {
|
|
980
|
+
const normalized = normalize_effect_callback_yields(candidate.expr_text, effect_context);
|
|
981
|
+
const normalized_candidate = {
|
|
982
|
+
...candidate,
|
|
983
|
+
expr_text: normalized.expr_text
|
|
984
|
+
};
|
|
596
985
|
const id = make_cache_id(candidate);
|
|
597
986
|
const id_text = JSON.stringify(id);
|
|
598
987
|
const helper_name = make_helper_name(candidate);
|
|
@@ -600,29 +989,30 @@ function emit_replacement(candidate, kind) {
|
|
|
600
989
|
let helpers;
|
|
601
990
|
let relocation;
|
|
602
991
|
if (kind === "await") {
|
|
603
|
-
const effect = make_effect_helper(
|
|
992
|
+
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
604
993
|
replacement_text = emit_promise_expression(id_text, effect);
|
|
605
|
-
helpers = [effect.helper];
|
|
994
|
+
helpers = [...normalized.helpers, effect.helper];
|
|
606
995
|
} else if (kind === "render") {
|
|
607
|
-
const effect = make_effect_helper(
|
|
996
|
+
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
608
997
|
replacement_text = emit_render_expression(id_text, effect);
|
|
609
|
-
helpers = [effect.helper];
|
|
998
|
+
helpers = [...normalized.helpers, effect.helper];
|
|
610
999
|
} else if (kind === "each") {
|
|
611
|
-
const effect = make_effect_helper(
|
|
1000
|
+
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
612
1001
|
replacement_text = emit_each_expression(id_text, effect);
|
|
613
|
-
helpers = [effect.helper];
|
|
1002
|
+
helpers = [...normalized.helpers, effect.helper];
|
|
614
1003
|
} else if (kind === "event") {
|
|
615
|
-
|
|
616
|
-
|
|
1004
|
+
const event = make_event_handler(normalized_candidate);
|
|
1005
|
+
replacement_text = event.text;
|
|
1006
|
+
helpers = normalized.helpers;
|
|
617
1007
|
relocation = make_relocation(candidate, replacement_text, {
|
|
618
1008
|
originalStart: 0,
|
|
619
1009
|
originalEnd: candidate.expr_text.length,
|
|
620
|
-
generatedText:
|
|
1010
|
+
generatedText: event.expr_text
|
|
621
1011
|
});
|
|
622
1012
|
} else {
|
|
623
|
-
const effect = make_effect_helper(
|
|
1013
|
+
const effect = make_effect_helper(normalized_candidate, helper_name);
|
|
624
1014
|
replacement_text = emit_each_expression(id_text, effect);
|
|
625
|
-
helpers = [effect.helper];
|
|
1015
|
+
helpers = [...normalized.helpers, effect.helper];
|
|
626
1016
|
}
|
|
627
1017
|
return {
|
|
628
1018
|
start: candidate.start,
|
|
@@ -633,9 +1023,13 @@ function emit_replacement(candidate, kind) {
|
|
|
633
1023
|
};
|
|
634
1024
|
}
|
|
635
1025
|
function make_event_handler(candidate) {
|
|
636
|
-
|
|
637
|
-
if (
|
|
638
|
-
|
|
1026
|
+
const expr_text = candidate.expr_text;
|
|
1027
|
+
if (is_callback_function_expression(expr_text)) throw new YieldStarInEventCallbackError(candidate.filename, expr_text);
|
|
1028
|
+
if (analyze_event_body_yield_star(expr_text).has_nested_invalid_yield_star) throw new AsyncEffectInEventCallbackError(candidate.filename, expr_text);
|
|
1029
|
+
return {
|
|
1030
|
+
expr_text,
|
|
1031
|
+
text: `(event) => { ${HELPERS.run}(function* () { ${expr_text}; }); }`
|
|
1032
|
+
};
|
|
639
1033
|
}
|
|
640
1034
|
function emit_promise_expression(id_text, effect) {
|
|
641
1035
|
return `${HELPERS.promise}(${id_text}, ${effect.deps_text}, () => ${effect.call})`;
|
|
@@ -672,7 +1066,7 @@ function make_cache_id(candidate) {
|
|
|
672
1066
|
return `${candidate.filename}:${candidate.start}:${candidate.end}`;
|
|
673
1067
|
}
|
|
674
1068
|
function make_helper_name(candidate) {
|
|
675
|
-
return `
|
|
1069
|
+
return `__SER___markup_effect_${candidate.start}_${candidate.end}`;
|
|
676
1070
|
}
|
|
677
1071
|
function make_relocation(candidate, replacement_text, inner) {
|
|
678
1072
|
const generated_start = replacement_text.indexOf(inner.generatedText);
|
|
@@ -797,7 +1191,7 @@ function sanitize_markup(content, filename) {
|
|
|
797
1191
|
const declaration_yields = collect_declaration_yield_expressions(content, open, leading_ws, trimmed);
|
|
798
1192
|
if (declaration_yields.length > 0) {
|
|
799
1193
|
for (const declaration_yield of declaration_yields) {
|
|
800
|
-
const placeholder = `
|
|
1194
|
+
const placeholder = `__SER___markup_placeholder_${helper_index}`;
|
|
801
1195
|
helper_index += 1;
|
|
802
1196
|
candidates.push({
|
|
803
1197
|
placeholder,
|
|
@@ -846,7 +1240,7 @@ function sanitize_markup(content, filename) {
|
|
|
846
1240
|
continue;
|
|
847
1241
|
}
|
|
848
1242
|
/** Create a placeholder and replace the expression (preserving tag prefixes). */
|
|
849
|
-
const placeholder = `
|
|
1243
|
+
const placeholder = `__SER___markup_placeholder_${helper_index}`;
|
|
850
1244
|
helper_index += 1;
|
|
851
1245
|
candidates.push({
|
|
852
1246
|
placeholder,
|
|
@@ -1034,6 +1428,7 @@ function transform_markup_effect(content, filename) {
|
|
|
1034
1428
|
};
|
|
1035
1429
|
/** Find all brace expressions containing yield* and replace with placeholders. */
|
|
1036
1430
|
const work = sanitize_markup(content, filename);
|
|
1431
|
+
const effect_context = collect_effect_callback_bindings(content);
|
|
1037
1432
|
if (work.candidates.length === 0) return {
|
|
1038
1433
|
code: content,
|
|
1039
1434
|
has_yield: false
|
|
@@ -1041,7 +1436,7 @@ function transform_markup_effect(content, filename) {
|
|
|
1041
1436
|
const replacements = emit_replacements(classify_candidates(parse(blank_script_blocks(work.code), {
|
|
1042
1437
|
filename,
|
|
1043
1438
|
modern: true
|
|
1044
|
-
}), work.candidates));
|
|
1439
|
+
}), work.candidates), effect_context);
|
|
1045
1440
|
const helpers = replacements.flatMap((replacement) => replacement.helpers ?? []);
|
|
1046
1441
|
const magic = new MagicString(content);
|
|
1047
1442
|
replacements.sort((a, b) => b.start - a.start);
|
|
@@ -1057,4 +1452,4 @@ function transform_markup_effect(content, filename) {
|
|
|
1057
1452
|
//#endregion
|
|
1058
1453
|
export { find_yield_star_node as a, AsyncEffectInSyncRuneError as c, extract_binding_names as i, AwaitInEffectWorkError as l, collect_yield_star_nodes as n, is_yield_star_expression as o, contains_top_level_await as r, collect_free_identifiers as s, transform_markup_effect as t };
|
|
1059
1454
|
|
|
1060
|
-
//# sourceMappingURL=transform-
|
|
1455
|
+
//# sourceMappingURL=transform-s9gKPYu5.js.map
|