@tsrx/core 0.0.13 → 0.0.15
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/README.md +13 -8
- package/package.json +1 -1
- package/src/analyze/validation.js +47 -0
- package/src/index.js +11 -1
- package/src/plugin.js +319 -24
- package/src/transform/jsx/helpers.js +17 -0
- package/src/transform/jsx/index.js +540 -349
- package/src/transform/lazy.js +185 -13
- package/src/transform/segments.js +131 -20
- package/src/utils/ast.js +61 -0
- package/types/index.d.ts +17 -0
- package/types/parse.d.ts +2 -0
|
@@ -35,6 +35,8 @@ import {
|
|
|
35
35
|
} from '../lazy.js';
|
|
36
36
|
import { find_first_top_level_await_in_component_body } from '../await.js';
|
|
37
37
|
import { prepare_stylesheet_for_render, annotate_component_with_hash } from '../scoping.js';
|
|
38
|
+
import { validate_component_return_statement } from '../../analyze/validation.js';
|
|
39
|
+
import { get_component_from_path } from '../../utils/ast.js';
|
|
38
40
|
import {
|
|
39
41
|
is_interleaved_body as is_interleaved_body_core,
|
|
40
42
|
is_capturable_jsx_child,
|
|
@@ -48,7 +50,7 @@ import { is_hoist_safe_jsx_node } from '../jsx-hoist.js';
|
|
|
48
50
|
* local_statement_component_index: number,
|
|
49
51
|
* needs_error_boundary: boolean,
|
|
50
52
|
* needs_suspense: boolean,
|
|
51
|
-
* helper_state: { base_name: string, next_id: number, helpers:
|
|
53
|
+
* helper_state: { base_name: string, next_id: number, helpers: any[], statics: any[] } | null,
|
|
52
54
|
* available_bindings: Map<string, AST.Identifier>,
|
|
53
55
|
* lazy_next_id: number,
|
|
54
56
|
* current_css_hash: string | null,
|
|
@@ -112,8 +114,17 @@ export function createJsxTransform(platform) {
|
|
|
112
114
|
preallocate_lazy_ids(/** @type {any} */ (ast), transform_context);
|
|
113
115
|
|
|
114
116
|
walk(/** @type {any} */ (ast), transform_context, {
|
|
117
|
+
ReturnStatement(node, { next, path }) {
|
|
118
|
+
if (get_component_from_path(path)) {
|
|
119
|
+
validate_component_return_statement(node, filename);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return next();
|
|
123
|
+
},
|
|
124
|
+
|
|
115
125
|
Component(node, { next, state }) {
|
|
116
126
|
const as_any = /** @type {any} */ (node);
|
|
127
|
+
|
|
117
128
|
const await_expression = find_first_top_level_await_in_component_body(as_any.body || []);
|
|
118
129
|
|
|
119
130
|
if (await_expression) {
|
|
@@ -170,17 +181,12 @@ export function createJsxTransform(platform) {
|
|
|
170
181
|
state.current_css_hash = as_any.css ? as_any.css.hash : null;
|
|
171
182
|
|
|
172
183
|
// Pre-collect component body bindings (params + top-level statements)
|
|
173
|
-
// so
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
// Only collect up to the split point — bindings declared after a
|
|
177
|
-
// hook-safe split aren't in scope at the return statement and would
|
|
178
|
-
// cause ReferenceErrors if passed as helper props.
|
|
184
|
+
// so Element children processed during the bottom-up walk can see
|
|
185
|
+
// component-scope names. Hook-safe helpers filter this set down to
|
|
186
|
+
// the names their body actually references before generating props.
|
|
179
187
|
const body_bindings = collect_param_bindings(as_any.params || []);
|
|
180
188
|
const body = as_any.body || [];
|
|
181
|
-
|
|
182
|
-
const collect_end = split_index === -1 ? body.length : split_index;
|
|
183
|
-
for (let i = 0; i < collect_end; i += 1) {
|
|
189
|
+
for (let i = 0; i < body.length; i += 1) {
|
|
184
190
|
collect_statement_bindings(body[i], body_bindings);
|
|
185
191
|
}
|
|
186
192
|
state.available_bindings = body_bindings;
|
|
@@ -347,12 +353,7 @@ function component_to_function_declaration(component, transform_context, walk_he
|
|
|
347
353
|
transform_context.helper_state = helper_state;
|
|
348
354
|
transform_context.available_bindings = new Map(param_bindings);
|
|
349
355
|
|
|
350
|
-
const body_statements = build_component_statements(
|
|
351
|
-
body,
|
|
352
|
-
helper_state,
|
|
353
|
-
param_bindings,
|
|
354
|
-
transform_context,
|
|
355
|
-
);
|
|
356
|
+
const body_statements = build_component_statements(body, transform_context);
|
|
356
357
|
|
|
357
358
|
// Replace lazy param patterns with generated identifiers
|
|
358
359
|
const final_params = lazy_bindings.size > 0 ? replace_lazy_params(params) : params;
|
|
@@ -371,6 +372,7 @@ function component_to_function_declaration(component, transform_context, walk_he
|
|
|
371
372
|
const fn = /** @type {any} */ ({
|
|
372
373
|
type: 'FunctionDeclaration',
|
|
373
374
|
id: component.id,
|
|
375
|
+
typeParameters: component.typeParameters,
|
|
374
376
|
params: final_params,
|
|
375
377
|
body: final_body,
|
|
376
378
|
async: is_async_component,
|
|
@@ -401,107 +403,11 @@ function component_to_function_declaration(component, transform_context, walk_he
|
|
|
401
403
|
|
|
402
404
|
/**
|
|
403
405
|
* @param {any[]} body_nodes
|
|
404
|
-
* @param {{ base_name: string, next_id: number, helpers: AST.FunctionDeclaration[], statics: any[] }} helper_state
|
|
405
|
-
* @param {Map<string, AST.Identifier>} available_bindings
|
|
406
406
|
* @param {TransformContext} transform_context
|
|
407
407
|
* @returns {any[]}
|
|
408
408
|
*/
|
|
409
|
-
function build_component_statements(
|
|
410
|
-
body_nodes,
|
|
411
|
-
helper_state,
|
|
412
|
-
available_bindings,
|
|
413
|
-
transform_context,
|
|
414
|
-
) {
|
|
415
|
-
const split_index = find_hook_safe_split_index(body_nodes);
|
|
416
|
-
if (split_index === -1) {
|
|
417
|
-
return build_render_statements(body_nodes, false, transform_context);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const statements = [];
|
|
421
|
-
const render_nodes = [];
|
|
422
|
-
const bindings = new Map(available_bindings);
|
|
423
|
-
|
|
424
|
-
const pre_split_body = body_nodes.slice(0, split_index);
|
|
425
|
-
const interleaved = is_interleaved_body(pre_split_body);
|
|
426
|
-
let capture_index = 0;
|
|
427
|
-
|
|
428
|
-
for (let i = 0; i < split_index; i += 1) {
|
|
429
|
-
const child = body_nodes[i];
|
|
430
|
-
|
|
431
|
-
if (is_bare_return_statement(child)) {
|
|
432
|
-
statements.push(create_component_return_statement(render_nodes, child));
|
|
433
|
-
return statements;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (is_lone_return_if_statement(child)) {
|
|
437
|
-
statements.push(create_component_lone_return_if_statement(child, render_nodes));
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
if (is_jsx_child(child)) {
|
|
442
|
-
const jsx = to_jsx_child(child, transform_context);
|
|
443
|
-
if (interleaved && is_capturable_jsx_child(jsx)) {
|
|
444
|
-
const { declaration, reference } = captureJsxChild(jsx, capture_index++);
|
|
445
|
-
statements.push(declaration);
|
|
446
|
-
render_nodes.push(reference);
|
|
447
|
-
} else {
|
|
448
|
-
render_nodes.push(jsx);
|
|
449
|
-
}
|
|
450
|
-
} else {
|
|
451
|
-
statements.push(child);
|
|
452
|
-
collect_statement_bindings(child, bindings);
|
|
453
|
-
transform_context.available_bindings = bindings;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (!interleaved) {
|
|
458
|
-
hoist_static_render_nodes(render_nodes, transform_context);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
const split_node = body_nodes[split_index];
|
|
462
|
-
const consequent_body =
|
|
463
|
-
split_node.consequent.type === 'BlockStatement'
|
|
464
|
-
? split_node.consequent.body
|
|
465
|
-
: [split_node.consequent];
|
|
466
|
-
const short_branch_body = consequent_body.filter(
|
|
467
|
-
(/** @type {any} */ child) => !is_bare_return_statement(child),
|
|
468
|
-
);
|
|
469
|
-
const continuation_body = body_nodes.slice(split_index + 1);
|
|
470
|
-
const short_branch = create_helper_component_expression(
|
|
471
|
-
short_branch_body,
|
|
472
|
-
helper_state,
|
|
473
|
-
bindings,
|
|
474
|
-
split_node.consequent,
|
|
475
|
-
'Exit',
|
|
476
|
-
transform_context,
|
|
477
|
-
);
|
|
478
|
-
const continuation = create_helper_component_expression(
|
|
479
|
-
continuation_body,
|
|
480
|
-
helper_state,
|
|
481
|
-
bindings,
|
|
482
|
-
split_node,
|
|
483
|
-
'Continue',
|
|
484
|
-
transform_context,
|
|
485
|
-
);
|
|
486
|
-
|
|
487
|
-
render_nodes.push(
|
|
488
|
-
to_jsx_expression_container(
|
|
489
|
-
set_loc(
|
|
490
|
-
/** @type {any} */ ({
|
|
491
|
-
type: 'ConditionalExpression',
|
|
492
|
-
test: split_node.test,
|
|
493
|
-
consequent: short_branch,
|
|
494
|
-
alternate: continuation,
|
|
495
|
-
metadata: { path: [] },
|
|
496
|
-
}),
|
|
497
|
-
split_node,
|
|
498
|
-
),
|
|
499
|
-
split_node,
|
|
500
|
-
),
|
|
501
|
-
);
|
|
502
|
-
|
|
503
|
-
statements.push(create_component_return_statement(render_nodes, split_node));
|
|
504
|
-
return statements;
|
|
409
|
+
function build_component_statements(body_nodes, transform_context) {
|
|
410
|
+
return build_render_statements(body_nodes, false, transform_context);
|
|
505
411
|
}
|
|
506
412
|
|
|
507
413
|
/**
|
|
@@ -527,15 +433,40 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
527
433
|
const interleaved = is_interleaved_body(body_nodes);
|
|
528
434
|
let capture_index = 0;
|
|
529
435
|
|
|
530
|
-
for (
|
|
436
|
+
for (let i = 0; i < body_nodes.length; i += 1) {
|
|
437
|
+
const child = body_nodes[i];
|
|
438
|
+
|
|
531
439
|
if (is_bare_return_statement(child)) {
|
|
532
440
|
statements.push(create_component_return_statement(render_nodes, child));
|
|
533
|
-
|
|
534
|
-
|
|
441
|
+
render_nodes.length = 0;
|
|
442
|
+
continue;
|
|
535
443
|
}
|
|
536
444
|
|
|
537
|
-
if (
|
|
538
|
-
|
|
445
|
+
if (is_returning_if_statement(child)) {
|
|
446
|
+
const branch_has_hooks = body_contains_top_level_hook_call(get_if_consequent_body(child));
|
|
447
|
+
const continuation_has_hooks = body_contains_top_level_hook_call(body_nodes.slice(i + 1));
|
|
448
|
+
|
|
449
|
+
if (branch_has_hooks || continuation_has_hooks) {
|
|
450
|
+
statements.push(
|
|
451
|
+
...create_component_helper_split_returning_if_statements(
|
|
452
|
+
child,
|
|
453
|
+
body_nodes.slice(i + 1),
|
|
454
|
+
render_nodes,
|
|
455
|
+
transform_context,
|
|
456
|
+
),
|
|
457
|
+
);
|
|
458
|
+
transform_context.available_bindings = saved_bindings;
|
|
459
|
+
return statements;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (is_lone_return_if_statement(child)) {
|
|
463
|
+
statements.push(create_component_lone_return_if_statement(child, render_nodes));
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
statements.push(
|
|
468
|
+
create_component_returning_if_statement(child, render_nodes, transform_context),
|
|
469
|
+
);
|
|
539
470
|
continue;
|
|
540
471
|
}
|
|
541
472
|
|
|
@@ -586,24 +517,6 @@ function is_interleaved_body(body_nodes) {
|
|
|
586
517
|
return is_interleaved_body_core(filtered, is_jsx_child);
|
|
587
518
|
}
|
|
588
519
|
|
|
589
|
-
/**
|
|
590
|
-
* @param {any[]} body_nodes
|
|
591
|
-
* @returns {number}
|
|
592
|
-
*/
|
|
593
|
-
function find_hook_safe_split_index(body_nodes) {
|
|
594
|
-
for (let i = 0; i < body_nodes.length; i += 1) {
|
|
595
|
-
if (!is_lone_return_if_statement(body_nodes[i])) {
|
|
596
|
-
continue;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
if (body_contains_top_level_hook_call(body_nodes.slice(i + 1))) {
|
|
600
|
-
return i;
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
return -1;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
520
|
/**
|
|
608
521
|
* @param {any[]} body_nodes
|
|
609
522
|
* @returns {boolean}
|
|
@@ -698,96 +611,6 @@ function is_hook_callee(callee) {
|
|
|
698
611
|
return false;
|
|
699
612
|
}
|
|
700
613
|
|
|
701
|
-
/**
|
|
702
|
-
* @param {any[]} body_nodes
|
|
703
|
-
* @param {{ base_name: string, next_id: number, helpers: AST.FunctionDeclaration[], statics: any[] }} helper_state
|
|
704
|
-
* @param {Map<string, AST.Identifier>} available_bindings
|
|
705
|
-
* @param {any} source_node
|
|
706
|
-
* @param {string} suffix
|
|
707
|
-
* @param {TransformContext} transform_context
|
|
708
|
-
* @returns {any}
|
|
709
|
-
*/
|
|
710
|
-
function create_helper_component_expression(
|
|
711
|
-
body_nodes,
|
|
712
|
-
helper_state,
|
|
713
|
-
available_bindings,
|
|
714
|
-
source_node,
|
|
715
|
-
suffix,
|
|
716
|
-
transform_context,
|
|
717
|
-
) {
|
|
718
|
-
if (body_nodes.length === 0) {
|
|
719
|
-
return create_null_literal();
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
const helper_name = create_helper_name(helper_state, suffix);
|
|
723
|
-
const helper_id = set_loc(create_generated_identifier(helper_name), source_node);
|
|
724
|
-
const helper_bindings = Array.from(available_bindings.values());
|
|
725
|
-
const helper_fn = create_helper_function_declaration(
|
|
726
|
-
helper_id,
|
|
727
|
-
body_nodes,
|
|
728
|
-
helper_state,
|
|
729
|
-
available_bindings,
|
|
730
|
-
helper_bindings,
|
|
731
|
-
source_node,
|
|
732
|
-
transform_context,
|
|
733
|
-
);
|
|
734
|
-
|
|
735
|
-
helper_state.helpers.push(helper_fn);
|
|
736
|
-
|
|
737
|
-
return create_helper_component_element(helper_id, helper_bindings, source_node);
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
* @param {AST.Identifier} helper_id
|
|
742
|
-
* @param {any[]} body_nodes
|
|
743
|
-
* @param {{ base_name: string, next_id: number, helpers: AST.FunctionDeclaration[], statics: any[] }} helper_state
|
|
744
|
-
* @param {Map<string, AST.Identifier>} available_bindings
|
|
745
|
-
* @param {AST.Identifier[]} helper_bindings
|
|
746
|
-
* @param {any} source_node
|
|
747
|
-
* @param {TransformContext} transform_context
|
|
748
|
-
* @returns {AST.FunctionDeclaration}
|
|
749
|
-
*/
|
|
750
|
-
function create_helper_function_declaration(
|
|
751
|
-
helper_id,
|
|
752
|
-
body_nodes,
|
|
753
|
-
helper_state,
|
|
754
|
-
available_bindings,
|
|
755
|
-
helper_bindings,
|
|
756
|
-
source_node,
|
|
757
|
-
transform_context,
|
|
758
|
-
) {
|
|
759
|
-
const fn = /** @type {any} */ ({
|
|
760
|
-
type: 'FunctionDeclaration',
|
|
761
|
-
id: helper_id,
|
|
762
|
-
params: helper_bindings.length > 0 ? [create_helper_props_pattern(helper_bindings)] : [],
|
|
763
|
-
body: {
|
|
764
|
-
type: 'BlockStatement',
|
|
765
|
-
body: build_component_statements(
|
|
766
|
-
body_nodes,
|
|
767
|
-
helper_state,
|
|
768
|
-
new Map(available_bindings),
|
|
769
|
-
transform_context,
|
|
770
|
-
),
|
|
771
|
-
metadata: { path: [] },
|
|
772
|
-
},
|
|
773
|
-
async: false,
|
|
774
|
-
generator: false,
|
|
775
|
-
metadata: {
|
|
776
|
-
path: [],
|
|
777
|
-
is_component: true,
|
|
778
|
-
},
|
|
779
|
-
});
|
|
780
|
-
|
|
781
|
-
if (fn.id) {
|
|
782
|
-
fn.id.metadata = /** @type {AST.Identifier['metadata']} */ ({
|
|
783
|
-
...fn.id.metadata,
|
|
784
|
-
is_component: true,
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
return set_loc(fn, source_node);
|
|
789
|
-
}
|
|
790
|
-
|
|
791
614
|
/**
|
|
792
615
|
* @param {AST.Identifier[]} bindings
|
|
793
616
|
* @returns {AST.ObjectPattern}
|
|
@@ -867,7 +690,7 @@ function create_helper_component_element(helper_id, bindings, source_node, mappi
|
|
|
867
690
|
}
|
|
868
691
|
|
|
869
692
|
/**
|
|
870
|
-
* @param {{ base_name: string, next_id: number, helpers:
|
|
693
|
+
* @param {{ base_name: string, next_id: number, helpers: any[], statics: any[] }} helper_state
|
|
871
694
|
* @param {string} suffix
|
|
872
695
|
* @returns {string}
|
|
873
696
|
*/
|
|
@@ -878,7 +701,7 @@ function create_helper_name(helper_state, suffix) {
|
|
|
878
701
|
|
|
879
702
|
/**
|
|
880
703
|
* @param {string} base_name
|
|
881
|
-
* @returns {{ base_name: string, next_id: number, helpers:
|
|
704
|
+
* @returns {{ base_name: string, next_id: number, helpers: any[], statics: any[] }}
|
|
882
705
|
*/
|
|
883
706
|
function create_helper_state(base_name) {
|
|
884
707
|
return {
|
|
@@ -1116,12 +939,31 @@ function is_lone_return_if_statement(node) {
|
|
|
1116
939
|
return false;
|
|
1117
940
|
}
|
|
1118
941
|
|
|
1119
|
-
const consequent_body =
|
|
1120
|
-
node.consequent.type === 'BlockStatement' ? node.consequent.body : [node.consequent];
|
|
942
|
+
const consequent_body = get_if_consequent_body(node);
|
|
1121
943
|
|
|
1122
944
|
return consequent_body.length === 1 && is_bare_return_statement(consequent_body[0]);
|
|
1123
945
|
}
|
|
1124
946
|
|
|
947
|
+
/**
|
|
948
|
+
* @param {any} node
|
|
949
|
+
* @returns {boolean}
|
|
950
|
+
*/
|
|
951
|
+
function is_returning_if_statement(node) {
|
|
952
|
+
if (node?.type !== 'IfStatement' || node.alternate) {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
return get_if_consequent_body(node).some(is_bare_return_statement);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* @param {any} node
|
|
961
|
+
* @returns {any[]}
|
|
962
|
+
*/
|
|
963
|
+
function get_if_consequent_body(node) {
|
|
964
|
+
return node.consequent.type === 'BlockStatement' ? node.consequent.body : [node.consequent];
|
|
965
|
+
}
|
|
966
|
+
|
|
1125
967
|
/**
|
|
1126
968
|
* @param {any[]} render_nodes
|
|
1127
969
|
* @param {any} source_node
|
|
@@ -1133,22 +975,25 @@ function create_component_return_statement(
|
|
|
1133
975
|
source_node,
|
|
1134
976
|
map_render_node_locations = true,
|
|
1135
977
|
) {
|
|
1136
|
-
return
|
|
1137
|
-
type
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
978
|
+
return set_loc(
|
|
979
|
+
/** @type {any} */ ({
|
|
980
|
+
type: 'ReturnStatement',
|
|
981
|
+
argument: build_return_expression(
|
|
982
|
+
render_nodes.map((node) =>
|
|
983
|
+
map_render_node_locations
|
|
984
|
+
? clone_expression_node(node)
|
|
985
|
+
: clone_expression_node_without_locations(node),
|
|
986
|
+
),
|
|
987
|
+
) || {
|
|
988
|
+
type: 'Literal',
|
|
989
|
+
value: null,
|
|
990
|
+
raw: 'null',
|
|
991
|
+
metadata: { path: [] },
|
|
992
|
+
},
|
|
1148
993
|
metadata: { path: [] },
|
|
1149
|
-
},
|
|
1150
|
-
|
|
1151
|
-
|
|
994
|
+
}),
|
|
995
|
+
source_node,
|
|
996
|
+
);
|
|
1152
997
|
}
|
|
1153
998
|
|
|
1154
999
|
/**
|
|
@@ -1157,8 +1002,7 @@ function create_component_return_statement(
|
|
|
1157
1002
|
* @returns {any}
|
|
1158
1003
|
*/
|
|
1159
1004
|
function create_component_lone_return_if_statement(node, render_nodes) {
|
|
1160
|
-
const consequent_body =
|
|
1161
|
-
node.consequent.type === 'BlockStatement' ? node.consequent.body : [node.consequent];
|
|
1005
|
+
const consequent_body = get_if_consequent_body(node);
|
|
1162
1006
|
|
|
1163
1007
|
return set_loc(
|
|
1164
1008
|
/** @type {any} */ ({
|
|
@@ -1179,6 +1023,195 @@ function create_component_lone_return_if_statement(node, render_nodes) {
|
|
|
1179
1023
|
);
|
|
1180
1024
|
}
|
|
1181
1025
|
|
|
1026
|
+
/**
|
|
1027
|
+
* @param {any} node
|
|
1028
|
+
* @param {any[]} render_nodes
|
|
1029
|
+
* @param {TransformContext} transform_context
|
|
1030
|
+
* @returns {any}
|
|
1031
|
+
*/
|
|
1032
|
+
function create_component_returning_if_statement(node, render_nodes, transform_context) {
|
|
1033
|
+
const consequent_body = get_if_consequent_body(node);
|
|
1034
|
+
const branch_statements = build_render_statements(consequent_body, true, transform_context);
|
|
1035
|
+
prepend_render_nodes_to_return_statements(branch_statements, render_nodes);
|
|
1036
|
+
|
|
1037
|
+
return set_loc(
|
|
1038
|
+
/** @type {any} */ ({
|
|
1039
|
+
type: 'IfStatement',
|
|
1040
|
+
test: node.test,
|
|
1041
|
+
consequent: set_loc(
|
|
1042
|
+
/** @type {any} */ ({
|
|
1043
|
+
type: 'BlockStatement',
|
|
1044
|
+
body: branch_statements,
|
|
1045
|
+
metadata: { path: [] },
|
|
1046
|
+
}),
|
|
1047
|
+
node.consequent,
|
|
1048
|
+
),
|
|
1049
|
+
alternate: null,
|
|
1050
|
+
metadata: { path: [] },
|
|
1051
|
+
}),
|
|
1052
|
+
node,
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/**
|
|
1057
|
+
* @param {any} node
|
|
1058
|
+
* @param {any[]} continuation_body
|
|
1059
|
+
* @param {any[]} render_nodes
|
|
1060
|
+
* @param {TransformContext} transform_context
|
|
1061
|
+
* @returns {any[]}
|
|
1062
|
+
*/
|
|
1063
|
+
function create_component_helper_split_returning_if_statements(
|
|
1064
|
+
node,
|
|
1065
|
+
continuation_body,
|
|
1066
|
+
render_nodes,
|
|
1067
|
+
transform_context,
|
|
1068
|
+
) {
|
|
1069
|
+
const consequent_body = get_if_consequent_body(node);
|
|
1070
|
+
const return_index = consequent_body.findIndex(is_bare_return_statement);
|
|
1071
|
+
const branch_body =
|
|
1072
|
+
return_index === -1 ? consequent_body : consequent_body.slice(0, return_index);
|
|
1073
|
+
const branch_helper = create_hook_safe_helper(
|
|
1074
|
+
branch_body,
|
|
1075
|
+
undefined,
|
|
1076
|
+
node.consequent,
|
|
1077
|
+
transform_context,
|
|
1078
|
+
);
|
|
1079
|
+
const continuation_helper = create_hook_safe_helper(
|
|
1080
|
+
continuation_body,
|
|
1081
|
+
undefined,
|
|
1082
|
+
node,
|
|
1083
|
+
transform_context,
|
|
1084
|
+
);
|
|
1085
|
+
return [
|
|
1086
|
+
set_loc(
|
|
1087
|
+
/** @type {any} */ ({
|
|
1088
|
+
type: 'IfStatement',
|
|
1089
|
+
test: node.test,
|
|
1090
|
+
consequent: set_loc(
|
|
1091
|
+
/** @type {any} */ ({
|
|
1092
|
+
type: 'BlockStatement',
|
|
1093
|
+
body: [
|
|
1094
|
+
...branch_helper.setup_statements,
|
|
1095
|
+
{
|
|
1096
|
+
type: 'ReturnStatement',
|
|
1097
|
+
argument: combine_render_return_argument(
|
|
1098
|
+
render_nodes,
|
|
1099
|
+
branch_helper.component_element,
|
|
1100
|
+
),
|
|
1101
|
+
metadata: { path: [] },
|
|
1102
|
+
},
|
|
1103
|
+
],
|
|
1104
|
+
metadata: { path: [] },
|
|
1105
|
+
}),
|
|
1106
|
+
node.consequent,
|
|
1107
|
+
),
|
|
1108
|
+
alternate: null,
|
|
1109
|
+
metadata: { path: [] },
|
|
1110
|
+
}),
|
|
1111
|
+
node,
|
|
1112
|
+
),
|
|
1113
|
+
...continuation_helper.setup_statements,
|
|
1114
|
+
{
|
|
1115
|
+
type: 'ReturnStatement',
|
|
1116
|
+
argument: combine_render_return_argument(render_nodes, continuation_helper.component_element),
|
|
1117
|
+
metadata: { path: [] },
|
|
1118
|
+
},
|
|
1119
|
+
];
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* @param {any[]} statements
|
|
1124
|
+
* @param {any[]} render_nodes
|
|
1125
|
+
* @returns {void}
|
|
1126
|
+
*/
|
|
1127
|
+
function prepend_render_nodes_to_return_statements(statements, render_nodes) {
|
|
1128
|
+
if (render_nodes.length === 0) {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
for (const statement of statements) {
|
|
1133
|
+
prepend_render_nodes_to_return_statement(statement, render_nodes, false);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/**
|
|
1138
|
+
* @param {any} node
|
|
1139
|
+
* @param {any[]} render_nodes
|
|
1140
|
+
* @param {boolean} inside_nested_function
|
|
1141
|
+
* @returns {void}
|
|
1142
|
+
*/
|
|
1143
|
+
function prepend_render_nodes_to_return_statement(node, render_nodes, inside_nested_function) {
|
|
1144
|
+
if (!node || typeof node !== 'object') {
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
if (
|
|
1149
|
+
node.type === 'FunctionDeclaration' ||
|
|
1150
|
+
node.type === 'FunctionExpression' ||
|
|
1151
|
+
node.type === 'ArrowFunctionExpression'
|
|
1152
|
+
) {
|
|
1153
|
+
inside_nested_function = true;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (!inside_nested_function && node.type === 'ReturnStatement') {
|
|
1157
|
+
node.argument = combine_render_return_argument(render_nodes, node.argument);
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
if (Array.isArray(node)) {
|
|
1162
|
+
for (const child of node) {
|
|
1163
|
+
prepend_render_nodes_to_return_statement(child, render_nodes, inside_nested_function);
|
|
1164
|
+
}
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
for (const key of Object.keys(node)) {
|
|
1169
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
prepend_render_nodes_to_return_statement(node[key], render_nodes, inside_nested_function);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
/**
|
|
1177
|
+
* @param {any[]} render_nodes
|
|
1178
|
+
* @param {any} return_argument
|
|
1179
|
+
* @returns {any}
|
|
1180
|
+
*/
|
|
1181
|
+
function combine_render_return_argument(render_nodes, return_argument) {
|
|
1182
|
+
const combined = render_nodes.map((node) => clone_expression_node_without_locations(node));
|
|
1183
|
+
|
|
1184
|
+
if (!is_null_literal(return_argument)) {
|
|
1185
|
+
combined.push(return_argument_to_render_node(return_argument));
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
return build_return_expression(combined) || create_null_literal();
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* @param {any} argument
|
|
1193
|
+
* @returns {any}
|
|
1194
|
+
*/
|
|
1195
|
+
function return_argument_to_render_node(argument) {
|
|
1196
|
+
if (
|
|
1197
|
+
argument?.type === 'JSXElement' ||
|
|
1198
|
+
argument?.type === 'JSXFragment' ||
|
|
1199
|
+
argument?.type === 'JSXExpressionContainer'
|
|
1200
|
+
) {
|
|
1201
|
+
return argument;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
return to_jsx_expression_container(argument);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* @param {any} node
|
|
1209
|
+
* @returns {boolean}
|
|
1210
|
+
*/
|
|
1211
|
+
function is_null_literal(node) {
|
|
1212
|
+
return node?.type === 'Literal' && node.value == null;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1182
1215
|
/**
|
|
1183
1216
|
* @param {any} node
|
|
1184
1217
|
* @returns {any}
|
|
@@ -1392,83 +1425,10 @@ function statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
|
1392
1425
|
*/
|
|
1393
1426
|
function hook_safe_statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
1394
1427
|
const source_node = get_body_source_node(body_nodes);
|
|
1395
|
-
const
|
|
1396
|
-
create_local_statement_component_name(transform_context),
|
|
1397
|
-
);
|
|
1398
|
-
const helper_bindings = Array.from(transform_context.available_bindings.values());
|
|
1399
|
-
|
|
1400
|
-
// Save and isolate bindings for the helper body
|
|
1401
|
-
const saved_bindings = transform_context.available_bindings;
|
|
1402
|
-
transform_context.available_bindings = new Map(saved_bindings);
|
|
1403
|
-
|
|
1404
|
-
const helper_fn = /** @type {any} */ ({
|
|
1405
|
-
type: 'FunctionDeclaration',
|
|
1406
|
-
id: helper_id,
|
|
1407
|
-
params: helper_bindings.length > 0 ? [create_helper_props_pattern(helper_bindings)] : [],
|
|
1408
|
-
body: {
|
|
1409
|
-
type: 'BlockStatement',
|
|
1410
|
-
body: build_render_statements(body_nodes, true, transform_context),
|
|
1411
|
-
metadata: { path: [] },
|
|
1412
|
-
},
|
|
1413
|
-
async: false,
|
|
1414
|
-
generator: false,
|
|
1415
|
-
metadata: {
|
|
1416
|
-
path: [],
|
|
1417
|
-
is_component: true,
|
|
1418
|
-
is_method: false,
|
|
1419
|
-
},
|
|
1420
|
-
});
|
|
1421
|
-
|
|
1422
|
-
// Restore bindings
|
|
1423
|
-
transform_context.available_bindings = saved_bindings;
|
|
1424
|
-
|
|
1425
|
-
// Register helper for hoisting to module level
|
|
1426
|
-
if (transform_context.helper_state) {
|
|
1427
|
-
transform_context.helper_state.helpers.push(helper_fn);
|
|
1428
|
-
|
|
1429
|
-
return to_jsx_expression_container(
|
|
1430
|
-
/** @type {any} */ (
|
|
1431
|
-
create_helper_component_element(helper_id, helper_bindings, source_node, {
|
|
1432
|
-
mapWrapper: false,
|
|
1433
|
-
mapBindingNames: false,
|
|
1434
|
-
mapBindingValues: false,
|
|
1435
|
-
})
|
|
1436
|
-
),
|
|
1437
|
-
source_node,
|
|
1438
|
-
);
|
|
1439
|
-
}
|
|
1428
|
+
const helper = create_hook_safe_helper(body_nodes, undefined, source_node, transform_context);
|
|
1440
1429
|
|
|
1441
1430
|
return to_jsx_expression_container(
|
|
1442
|
-
|
|
1443
|
-
type: 'CallExpression',
|
|
1444
|
-
callee: {
|
|
1445
|
-
type: 'ArrowFunctionExpression',
|
|
1446
|
-
params: [],
|
|
1447
|
-
body: /** @type {any} */ ({
|
|
1448
|
-
type: 'BlockStatement',
|
|
1449
|
-
body: [
|
|
1450
|
-
helper_fn,
|
|
1451
|
-
{
|
|
1452
|
-
type: 'ReturnStatement',
|
|
1453
|
-
argument: create_helper_component_element(helper_id, helper_bindings, source_node, {
|
|
1454
|
-
mapWrapper: false,
|
|
1455
|
-
mapBindingNames: false,
|
|
1456
|
-
mapBindingValues: false,
|
|
1457
|
-
}),
|
|
1458
|
-
metadata: { path: [] },
|
|
1459
|
-
},
|
|
1460
|
-
],
|
|
1461
|
-
metadata: { path: [] },
|
|
1462
|
-
}),
|
|
1463
|
-
async: false,
|
|
1464
|
-
generator: false,
|
|
1465
|
-
expression: false,
|
|
1466
|
-
metadata: { path: [] },
|
|
1467
|
-
},
|
|
1468
|
-
arguments: [],
|
|
1469
|
-
optional: false,
|
|
1470
|
-
metadata: { path: [] },
|
|
1471
|
-
}),
|
|
1431
|
+
create_hook_safe_helper_iife(helper.setup_statements, helper.component_element),
|
|
1472
1432
|
source_node,
|
|
1473
1433
|
);
|
|
1474
1434
|
}
|
|
@@ -1497,19 +1457,77 @@ function create_local_statement_component_name(transform_context) {
|
|
|
1497
1457
|
*/
|
|
1498
1458
|
function hook_safe_render_statements(body_nodes, key_expression, transform_context) {
|
|
1499
1459
|
const source_node = get_body_source_node(body_nodes);
|
|
1460
|
+
const helper = create_hook_safe_helper(
|
|
1461
|
+
body_nodes,
|
|
1462
|
+
key_expression,
|
|
1463
|
+
source_node,
|
|
1464
|
+
transform_context,
|
|
1465
|
+
);
|
|
1466
|
+
const statements = [...helper.setup_statements];
|
|
1467
|
+
|
|
1468
|
+
statements.push({
|
|
1469
|
+
type: 'ReturnStatement',
|
|
1470
|
+
argument: helper.component_element,
|
|
1471
|
+
metadata: { path: [] },
|
|
1472
|
+
});
|
|
1473
|
+
|
|
1474
|
+
return statements;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
/**
|
|
1478
|
+
* @param {any[]} body_nodes
|
|
1479
|
+
* @param {Map<string, AST.Identifier>} available_bindings
|
|
1480
|
+
* @returns {AST.Identifier[]}
|
|
1481
|
+
*/
|
|
1482
|
+
function get_referenced_helper_bindings(body_nodes, available_bindings) {
|
|
1483
|
+
const helper_bindings = [];
|
|
1484
|
+
const local_bindings = new Map();
|
|
1485
|
+
|
|
1486
|
+
for (const node of body_nodes) {
|
|
1487
|
+
collect_statement_bindings(node, local_bindings);
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
for (const [name, binding] of available_bindings) {
|
|
1491
|
+
if (local_bindings.has(name)) continue;
|
|
1492
|
+
|
|
1493
|
+
if (references_scope_bindings(body_nodes, new Map([[name, binding]]))) {
|
|
1494
|
+
helper_bindings.push(binding);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
return helper_bindings;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
/**
|
|
1502
|
+
* @param {any[]} body_nodes
|
|
1503
|
+
* @param {any} key_expression
|
|
1504
|
+
* @param {any} source_node
|
|
1505
|
+
* @param {TransformContext} transform_context
|
|
1506
|
+
* @returns {{ setup_statements: any[], component_element: ESTreeJSX.JSXElement }}
|
|
1507
|
+
*/
|
|
1508
|
+
function create_hook_safe_helper(body_nodes, key_expression, source_node, transform_context) {
|
|
1500
1509
|
const helper_id = create_generated_identifier(
|
|
1501
1510
|
create_local_statement_component_name(transform_context),
|
|
1502
1511
|
);
|
|
1503
|
-
const helper_bindings =
|
|
1512
|
+
const helper_bindings = get_referenced_helper_bindings(
|
|
1513
|
+
body_nodes,
|
|
1514
|
+
transform_context.available_bindings,
|
|
1515
|
+
);
|
|
1516
|
+
const aliases = helper_bindings.map((binding) =>
|
|
1517
|
+
create_helper_type_alias_declaration(helper_id, binding),
|
|
1518
|
+
);
|
|
1519
|
+
const props_type =
|
|
1520
|
+
helper_bindings.length > 0 ? create_helper_props_type_literal(helper_bindings, aliases) : null;
|
|
1521
|
+
const params =
|
|
1522
|
+
props_type !== null ? [create_typed_helper_props_pattern(helper_bindings, props_type)] : [];
|
|
1504
1523
|
|
|
1505
|
-
// Save and isolate bindings for the helper body
|
|
1506
1524
|
const saved_bindings = transform_context.available_bindings;
|
|
1507
1525
|
transform_context.available_bindings = new Map(saved_bindings);
|
|
1508
1526
|
|
|
1509
1527
|
const helper_fn = /** @type {any} */ ({
|
|
1510
|
-
type: '
|
|
1511
|
-
id: helper_id,
|
|
1512
|
-
params
|
|
1528
|
+
type: 'FunctionExpression',
|
|
1529
|
+
id: clone_identifier(helper_id),
|
|
1530
|
+
params,
|
|
1513
1531
|
body: {
|
|
1514
1532
|
type: 'BlockStatement',
|
|
1515
1533
|
body: build_render_statements(body_nodes, true, transform_context),
|
|
@@ -1524,14 +1542,8 @@ function hook_safe_render_statements(body_nodes, key_expression, transform_conte
|
|
|
1524
1542
|
},
|
|
1525
1543
|
});
|
|
1526
1544
|
|
|
1527
|
-
// Restore bindings
|
|
1528
1545
|
transform_context.available_bindings = saved_bindings;
|
|
1529
1546
|
|
|
1530
|
-
// Register helper for hoisting to module level
|
|
1531
|
-
if (transform_context.helper_state) {
|
|
1532
|
-
transform_context.helper_state.helpers.push(helper_fn);
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
1547
|
const component_element = create_helper_component_element(
|
|
1536
1548
|
helper_id,
|
|
1537
1549
|
helper_bindings,
|
|
@@ -1554,26 +1566,205 @@ function hook_safe_render_statements(body_nodes, key_expression, transform_conte
|
|
|
1554
1566
|
);
|
|
1555
1567
|
}
|
|
1556
1568
|
|
|
1557
|
-
// When helper_state is null (no enclosing component context), inline the
|
|
1558
|
-
// helper via an IIFE so the function declaration isn't silently dropped.
|
|
1559
1569
|
if (!transform_context.helper_state) {
|
|
1560
|
-
return
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
];
|
|
1570
|
+
return {
|
|
1571
|
+
setup_statements: [
|
|
1572
|
+
...aliases.map((alias) => alias.declaration),
|
|
1573
|
+
create_helper_function_declaration_from_expression(helper_id, helper_fn),
|
|
1574
|
+
],
|
|
1575
|
+
component_element,
|
|
1576
|
+
};
|
|
1568
1577
|
}
|
|
1569
1578
|
|
|
1570
|
-
|
|
1571
|
-
{
|
|
1572
|
-
|
|
1573
|
-
|
|
1579
|
+
const cache_id = create_generated_identifier(
|
|
1580
|
+
`${transform_context.helper_state.base_name}__${helper_id.name}`,
|
|
1581
|
+
);
|
|
1582
|
+
transform_context.helper_state.helpers.push(create_helper_cache_declaration(cache_id));
|
|
1583
|
+
|
|
1584
|
+
return {
|
|
1585
|
+
setup_statements: [
|
|
1586
|
+
...aliases.map((alias) => alias.declaration),
|
|
1587
|
+
create_cached_helper_declaration(helper_id, cache_id, helper_fn),
|
|
1588
|
+
],
|
|
1589
|
+
component_element,
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
/**
|
|
1594
|
+
* @param {any[]} setup_statements
|
|
1595
|
+
* @param {ESTreeJSX.JSXElement} component_element
|
|
1596
|
+
* @returns {any}
|
|
1597
|
+
*/
|
|
1598
|
+
function create_hook_safe_helper_iife(setup_statements, component_element) {
|
|
1599
|
+
return /** @type {any} */ ({
|
|
1600
|
+
type: 'CallExpression',
|
|
1601
|
+
callee: {
|
|
1602
|
+
type: 'ArrowFunctionExpression',
|
|
1603
|
+
params: [],
|
|
1604
|
+
body: /** @type {any} */ ({
|
|
1605
|
+
type: 'BlockStatement',
|
|
1606
|
+
body: [
|
|
1607
|
+
...setup_statements,
|
|
1608
|
+
{
|
|
1609
|
+
type: 'ReturnStatement',
|
|
1610
|
+
argument: component_element,
|
|
1611
|
+
metadata: { path: [] },
|
|
1612
|
+
},
|
|
1613
|
+
],
|
|
1614
|
+
metadata: { path: [] },
|
|
1615
|
+
}),
|
|
1616
|
+
async: false,
|
|
1617
|
+
generator: false,
|
|
1618
|
+
expression: false,
|
|
1574
1619
|
metadata: { path: [] },
|
|
1575
1620
|
},
|
|
1576
|
-
|
|
1621
|
+
arguments: [],
|
|
1622
|
+
optional: false,
|
|
1623
|
+
metadata: { path: [] },
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
/**
|
|
1628
|
+
* @param {AST.Identifier} helper_id
|
|
1629
|
+
* @param {AST.Identifier} binding
|
|
1630
|
+
* @returns {{ id: AST.Identifier, declaration: any }}
|
|
1631
|
+
*/
|
|
1632
|
+
function create_helper_type_alias_declaration(helper_id, binding) {
|
|
1633
|
+
const alias_id = create_generated_identifier(`_tsrx_${helper_id.name}_${binding.name}`);
|
|
1634
|
+
|
|
1635
|
+
return {
|
|
1636
|
+
id: alias_id,
|
|
1637
|
+
declaration: /** @type {any} */ ({
|
|
1638
|
+
type: 'VariableDeclaration',
|
|
1639
|
+
kind: 'const',
|
|
1640
|
+
declarations: [
|
|
1641
|
+
{
|
|
1642
|
+
type: 'VariableDeclarator',
|
|
1643
|
+
id: clone_identifier(alias_id),
|
|
1644
|
+
init: create_generated_identifier(binding.name),
|
|
1645
|
+
metadata: { path: [] },
|
|
1646
|
+
},
|
|
1647
|
+
],
|
|
1648
|
+
metadata: { path: [] },
|
|
1649
|
+
}),
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
/**
|
|
1654
|
+
* @param {AST.Identifier[]} bindings
|
|
1655
|
+
* @param {{ id: AST.Identifier }[]} aliases
|
|
1656
|
+
* @returns {any}
|
|
1657
|
+
*/
|
|
1658
|
+
function create_helper_props_type_literal(bindings, aliases) {
|
|
1659
|
+
return /** @type {any} */ ({
|
|
1660
|
+
type: 'TSTypeLiteral',
|
|
1661
|
+
members: bindings.map(
|
|
1662
|
+
(binding, i) =>
|
|
1663
|
+
/** @type {any} */ ({
|
|
1664
|
+
type: 'TSPropertySignature',
|
|
1665
|
+
key: create_generated_identifier(binding.name),
|
|
1666
|
+
computed: false,
|
|
1667
|
+
optional: false,
|
|
1668
|
+
readonly: false,
|
|
1669
|
+
static: false,
|
|
1670
|
+
kind: 'init',
|
|
1671
|
+
typeAnnotation: {
|
|
1672
|
+
type: 'TSTypeAnnotation',
|
|
1673
|
+
typeAnnotation: {
|
|
1674
|
+
type: 'TSTypeQuery',
|
|
1675
|
+
exprName: clone_identifier(aliases[i].id),
|
|
1676
|
+
typeArguments: null,
|
|
1677
|
+
metadata: { path: [] },
|
|
1678
|
+
},
|
|
1679
|
+
metadata: { path: [] },
|
|
1680
|
+
},
|
|
1681
|
+
metadata: { path: [] },
|
|
1682
|
+
}),
|
|
1683
|
+
),
|
|
1684
|
+
metadata: { path: [] },
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
/**
|
|
1689
|
+
* @param {AST.Identifier[]} bindings
|
|
1690
|
+
* @param {any} props_type
|
|
1691
|
+
* @returns {AST.ObjectPattern}
|
|
1692
|
+
*/
|
|
1693
|
+
function create_typed_helper_props_pattern(bindings, props_type) {
|
|
1694
|
+
const pattern = create_helper_props_pattern(bindings);
|
|
1695
|
+
/** @type {any} */ (pattern).typeAnnotation = {
|
|
1696
|
+
type: 'TSTypeAnnotation',
|
|
1697
|
+
typeAnnotation: props_type,
|
|
1698
|
+
metadata: { path: [] },
|
|
1699
|
+
};
|
|
1700
|
+
return pattern;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
/**
|
|
1704
|
+
* @param {AST.Identifier} cache_id
|
|
1705
|
+
* @returns {any}
|
|
1706
|
+
*/
|
|
1707
|
+
function create_helper_cache_declaration(cache_id) {
|
|
1708
|
+
return /** @type {any} */ ({
|
|
1709
|
+
type: 'VariableDeclaration',
|
|
1710
|
+
kind: 'let',
|
|
1711
|
+
declarations: [
|
|
1712
|
+
{
|
|
1713
|
+
type: 'VariableDeclarator',
|
|
1714
|
+
id: clone_identifier(cache_id),
|
|
1715
|
+
init: null,
|
|
1716
|
+
metadata: { path: [] },
|
|
1717
|
+
},
|
|
1718
|
+
],
|
|
1719
|
+
metadata: { path: [] },
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
/**
|
|
1724
|
+
* @param {AST.Identifier} helper_id
|
|
1725
|
+
* @param {AST.Identifier} cache_id
|
|
1726
|
+
* @param {any} helper_fn
|
|
1727
|
+
* @returns {any}
|
|
1728
|
+
*/
|
|
1729
|
+
function create_cached_helper_declaration(helper_id, cache_id, helper_fn) {
|
|
1730
|
+
return /** @type {any} */ ({
|
|
1731
|
+
type: 'VariableDeclaration',
|
|
1732
|
+
kind: 'const',
|
|
1733
|
+
declarations: [
|
|
1734
|
+
{
|
|
1735
|
+
type: 'VariableDeclarator',
|
|
1736
|
+
id: clone_identifier(helper_id),
|
|
1737
|
+
init: {
|
|
1738
|
+
type: 'LogicalExpression',
|
|
1739
|
+
operator: '??',
|
|
1740
|
+
left: clone_identifier(cache_id),
|
|
1741
|
+
right: {
|
|
1742
|
+
type: 'AssignmentExpression',
|
|
1743
|
+
operator: '=',
|
|
1744
|
+
left: clone_identifier(cache_id),
|
|
1745
|
+
right: helper_fn,
|
|
1746
|
+
metadata: { path: [] },
|
|
1747
|
+
},
|
|
1748
|
+
metadata: { path: [] },
|
|
1749
|
+
},
|
|
1750
|
+
metadata: { path: [] },
|
|
1751
|
+
},
|
|
1752
|
+
],
|
|
1753
|
+
metadata: { path: [] },
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
/**
|
|
1758
|
+
* @param {AST.Identifier} helper_id
|
|
1759
|
+
* @param {any} helper_fn
|
|
1760
|
+
* @returns {AST.FunctionDeclaration}
|
|
1761
|
+
*/
|
|
1762
|
+
function create_helper_function_declaration_from_expression(helper_id, helper_fn) {
|
|
1763
|
+
return /** @type {any} */ ({
|
|
1764
|
+
...helper_fn,
|
|
1765
|
+
type: 'FunctionDeclaration',
|
|
1766
|
+
id: clone_identifier(helper_id),
|
|
1767
|
+
});
|
|
1577
1768
|
}
|
|
1578
1769
|
|
|
1579
1770
|
/**
|