@tsrx/core 0.1.4 → 0.1.6
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/package.json +23 -5
- package/src/diagnostics.js +1 -0
- package/src/index.js +7 -0
- package/src/plugin.js +31 -1
- package/src/runtime/index.js +110 -0
- package/src/source-map-utils.js +19 -2
- package/src/transform/jsx/ast-builders.js +120 -0
- package/src/transform/jsx/index.js +563 -1328
- package/src/transform/lazy.js +19 -60
- package/src/transform/scoping.js +9 -45
- package/src/transform/segments.js +164 -11
- package/src/utils/builders.js +51 -13
- package/types/jsx-platform.d.ts +10 -0
- package/types/runtime/index.d.ts +13 -0
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
get_for_of_iteration_params,
|
|
22
22
|
identifier_to_jsx_name,
|
|
23
23
|
is_bare_render_expression,
|
|
24
|
+
is_component_jsx_name,
|
|
24
25
|
is_dynamic_element_id,
|
|
25
26
|
is_jsx_child,
|
|
26
27
|
set_loc,
|
|
@@ -245,6 +246,8 @@ export function createJsxTransform(platform) {
|
|
|
245
246
|
needs_ref_prop: false,
|
|
246
247
|
needs_normalize_spread_props: false,
|
|
247
248
|
needs_fragment: false,
|
|
249
|
+
needs_for_of_iterable: false,
|
|
250
|
+
needs_iteration_value_type: false,
|
|
248
251
|
module_scoped_hook_components:
|
|
249
252
|
options?.moduleScopedHookComponents ?? !!platform.hooks?.moduleScopedHookComponents,
|
|
250
253
|
helper_state: null,
|
|
@@ -515,7 +518,7 @@ export function createJsxTransform(platform) {
|
|
|
515
518
|
const value = state.current_css_hash
|
|
516
519
|
? `${state.current_css_hash} ${class_name}`
|
|
517
520
|
: class_name;
|
|
518
|
-
return
|
|
521
|
+
return b.literal(value, undefined, node);
|
|
519
522
|
},
|
|
520
523
|
|
|
521
524
|
// Default .metadata on every function-like node so downstream consumers
|
|
@@ -666,11 +669,7 @@ export function component_to_function_declaration(component, transform_context,
|
|
|
666
669
|
// Wrap body_statements in a BlockStatement so that apply_lazy_transforms
|
|
667
670
|
// runs collect_block_shadowed_names and detects body-level declarations
|
|
668
671
|
// (e.g. `const name = ...`) that shadow lazy binding names.
|
|
669
|
-
const body_block =
|
|
670
|
-
type: 'BlockStatement',
|
|
671
|
-
body: body_statements,
|
|
672
|
-
metadata: { path: [] },
|
|
673
|
-
});
|
|
672
|
+
const body_block = b.block(body_statements);
|
|
674
673
|
const final_body =
|
|
675
674
|
lazy_bindings.size > 0 ? apply_lazy_transforms(body_block, lazy_bindings) : body_block;
|
|
676
675
|
|
|
@@ -678,48 +677,19 @@ export function component_to_function_declaration(component, transform_context,
|
|
|
678
677
|
let fn;
|
|
679
678
|
|
|
680
679
|
if (component.id) {
|
|
681
|
-
fn =
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
generator: false,
|
|
689
|
-
metadata: {
|
|
690
|
-
path: [],
|
|
691
|
-
is_component: true,
|
|
692
|
-
},
|
|
693
|
-
});
|
|
680
|
+
fn = b.function_declaration(
|
|
681
|
+
component.id,
|
|
682
|
+
final_params,
|
|
683
|
+
final_body,
|
|
684
|
+
is_async_component,
|
|
685
|
+
component.typeParameters,
|
|
686
|
+
);
|
|
694
687
|
} else if (component.metadata?.arrow) {
|
|
695
|
-
fn =
|
|
696
|
-
type: 'ArrowFunctionExpression',
|
|
697
|
-
typeParameters: component.typeParameters,
|
|
698
|
-
params: final_params,
|
|
699
|
-
body: final_body,
|
|
700
|
-
async: is_async_component,
|
|
701
|
-
generator: false,
|
|
702
|
-
expression: false,
|
|
703
|
-
metadata: {
|
|
704
|
-
path: [],
|
|
705
|
-
is_component: true,
|
|
706
|
-
},
|
|
707
|
-
});
|
|
688
|
+
fn = b.arrow(final_params, final_body, is_async_component, component.typeParameters);
|
|
708
689
|
} else {
|
|
709
|
-
fn =
|
|
710
|
-
type: 'FunctionExpression',
|
|
711
|
-
id: null,
|
|
712
|
-
typeParameters: component.typeParameters,
|
|
713
|
-
params: final_params,
|
|
714
|
-
body: final_body,
|
|
715
|
-
async: is_async_component,
|
|
716
|
-
generator: false,
|
|
717
|
-
metadata: {
|
|
718
|
-
path: [],
|
|
719
|
-
is_component: true,
|
|
720
|
-
},
|
|
721
|
-
});
|
|
690
|
+
fn = b.function(null, final_params, final_body, is_async_component, component.typeParameters);
|
|
722
691
|
}
|
|
692
|
+
/** @type {any} */ (fn.metadata).is_component = true;
|
|
723
693
|
|
|
724
694
|
// Restore context
|
|
725
695
|
transform_context.helper_state = saved_helper_state;
|
|
@@ -889,25 +859,16 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
889
859
|
if (stmt.type === 'ReturnStatement') {
|
|
890
860
|
if (stmt.argument) {
|
|
891
861
|
render_nodes.push(
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
type: 'Literal',
|
|
900
|
-
value: null,
|
|
901
|
-
raw: 'null',
|
|
902
|
-
metadata: { path: [] },
|
|
903
|
-
},
|
|
904
|
-
alternate: stmt.argument,
|
|
905
|
-
metadata: { path: [] },
|
|
906
|
-
}),
|
|
862
|
+
b.jsx_expression_container(
|
|
863
|
+
set_loc(
|
|
864
|
+
b.conditional(
|
|
865
|
+
clone_expression_node(child.test),
|
|
866
|
+
b.literal(null),
|
|
867
|
+
stmt.argument,
|
|
868
|
+
),
|
|
907
869
|
child,
|
|
908
870
|
),
|
|
909
|
-
|
|
910
|
-
}),
|
|
871
|
+
),
|
|
911
872
|
);
|
|
912
873
|
}
|
|
913
874
|
} else {
|
|
@@ -928,26 +889,6 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
928
889
|
continue;
|
|
929
890
|
}
|
|
930
891
|
|
|
931
|
-
if (
|
|
932
|
-
child.type === 'IfStatement' &&
|
|
933
|
-
!child.alternate &&
|
|
934
|
-
!is_returning_if_statement(child) &&
|
|
935
|
-
!transform_context.platform.hooks?.isTopLevelSetupCall &&
|
|
936
|
-
body_contains_top_level_hook_call([child], transform_context, true) &&
|
|
937
|
-
i + 1 < body_nodes.length
|
|
938
|
-
) {
|
|
939
|
-
statements.push(
|
|
940
|
-
...create_continuation_lift_if_statement(
|
|
941
|
-
child,
|
|
942
|
-
body_nodes.slice(i + 1),
|
|
943
|
-
render_nodes,
|
|
944
|
-
transform_context,
|
|
945
|
-
),
|
|
946
|
-
);
|
|
947
|
-
transform_context.available_bindings = saved_bindings;
|
|
948
|
-
return statements;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
892
|
if (
|
|
952
893
|
child.type === 'ForOfStatement' &&
|
|
953
894
|
!child.await &&
|
|
@@ -959,26 +900,9 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
959
900
|
true,
|
|
960
901
|
)
|
|
961
902
|
) {
|
|
962
|
-
const
|
|
963
|
-
const hoisted = build_hoisted_for_of_with_hooks(
|
|
964
|
-
child,
|
|
965
|
-
for_of_continuation,
|
|
966
|
-
transform_context,
|
|
967
|
-
);
|
|
903
|
+
const hoisted = build_hoisted_for_of_with_hooks(child, transform_context);
|
|
968
904
|
if (hoisted) {
|
|
969
905
|
statements.push(...hoisted.hoist_statements);
|
|
970
|
-
if (for_of_continuation.length > 0) {
|
|
971
|
-
// Tail was lifted into the helper; everything after the for-of
|
|
972
|
-
// now lives there. Combine prior render_nodes with the iteration
|
|
973
|
-
// JSX and return.
|
|
974
|
-
statements.push({
|
|
975
|
-
type: 'ReturnStatement',
|
|
976
|
-
argument: combine_render_return_argument(render_nodes, hoisted.jsx_child),
|
|
977
|
-
metadata: { path: [] },
|
|
978
|
-
});
|
|
979
|
-
transform_context.available_bindings = saved_bindings;
|
|
980
|
-
return statements;
|
|
981
|
-
}
|
|
982
906
|
if (interleaved && is_capturable_jsx_child(hoisted.jsx_child)) {
|
|
983
907
|
const { declaration, reference } = captureJsxChild(hoisted.jsx_child, capture_index++);
|
|
984
908
|
statements.push(declaration);
|
|
@@ -990,43 +914,6 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
990
914
|
}
|
|
991
915
|
}
|
|
992
916
|
|
|
993
|
-
if (
|
|
994
|
-
child.type === 'TryStatement' &&
|
|
995
|
-
!child.finalizer &&
|
|
996
|
-
!transform_context.platform.hooks?.isTopLevelSetupCall &&
|
|
997
|
-
try_statement_contains_hooks(child, transform_context) &&
|
|
998
|
-
i + 1 < body_nodes.length
|
|
999
|
-
) {
|
|
1000
|
-
statements.push(
|
|
1001
|
-
...create_continuation_lift_try_statement(
|
|
1002
|
-
child,
|
|
1003
|
-
body_nodes.slice(i + 1),
|
|
1004
|
-
render_nodes,
|
|
1005
|
-
transform_context,
|
|
1006
|
-
),
|
|
1007
|
-
);
|
|
1008
|
-
transform_context.available_bindings = saved_bindings;
|
|
1009
|
-
return statements;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
if (
|
|
1013
|
-
child.type === 'SwitchStatement' &&
|
|
1014
|
-
!transform_context.platform.hooks?.isTopLevelSetupCall &&
|
|
1015
|
-
body_contains_top_level_hook_call([child], transform_context, true) &&
|
|
1016
|
-
i + 1 < body_nodes.length
|
|
1017
|
-
) {
|
|
1018
|
-
statements.push(
|
|
1019
|
-
...create_continuation_lift_switch_statement(
|
|
1020
|
-
child,
|
|
1021
|
-
body_nodes.slice(i + 1),
|
|
1022
|
-
render_nodes,
|
|
1023
|
-
transform_context,
|
|
1024
|
-
),
|
|
1025
|
-
);
|
|
1026
|
-
transform_context.available_bindings = saved_bindings;
|
|
1027
|
-
return statements;
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
917
|
if (is_jsx_child(child)) {
|
|
1031
918
|
const jsx = to_jsx_child(child, transform_context);
|
|
1032
919
|
statements.push(...extract_jsx_setup_declarations(jsx));
|
|
@@ -1051,10 +938,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
1051
938
|
|
|
1052
939
|
const return_arg = build_return_expression(render_nodes);
|
|
1053
940
|
if (return_arg || (return_null_when_empty && !has_terminal_return)) {
|
|
1054
|
-
statements.push(
|
|
1055
|
-
type: 'ReturnStatement',
|
|
1056
|
-
argument: return_arg || { type: 'Literal', value: null, raw: 'null' },
|
|
1057
|
-
});
|
|
941
|
+
statements.push(b.return(return_arg || b.literal(null)));
|
|
1058
942
|
}
|
|
1059
943
|
|
|
1060
944
|
transform_context.available_bindings = saved_bindings;
|
|
@@ -1254,16 +1138,7 @@ function create_helper_props_property(binding) {
|
|
|
1254
1138
|
const key = create_generated_identifier(binding.name);
|
|
1255
1139
|
const value = create_generated_identifier(binding.name);
|
|
1256
1140
|
|
|
1257
|
-
return
|
|
1258
|
-
type: 'Property',
|
|
1259
|
-
key,
|
|
1260
|
-
value,
|
|
1261
|
-
kind: 'init',
|
|
1262
|
-
method: false,
|
|
1263
|
-
shorthand: true,
|
|
1264
|
-
computed: false,
|
|
1265
|
-
metadata: { path: [] },
|
|
1266
|
-
});
|
|
1141
|
+
return b.prop('init', key, value, false, true);
|
|
1267
1142
|
}
|
|
1268
1143
|
|
|
1269
1144
|
/**
|
|
@@ -1499,7 +1374,7 @@ function create_module_scoped_hook_component_id(helper_id, transform_context) {
|
|
|
1499
1374
|
* @param {any[]} params
|
|
1500
1375
|
* @returns {Map<string, AST.Identifier>}
|
|
1501
1376
|
*/
|
|
1502
|
-
function collect_param_bindings(params) {
|
|
1377
|
+
export function collect_param_bindings(params) {
|
|
1503
1378
|
const bindings = new Map();
|
|
1504
1379
|
for (const param of params) {
|
|
1505
1380
|
collect_pattern_bindings(param, bindings);
|
|
@@ -1512,7 +1387,7 @@ function collect_param_bindings(params) {
|
|
|
1512
1387
|
* @param {Map<string, AST.Identifier>} bindings
|
|
1513
1388
|
* @returns {void}
|
|
1514
1389
|
*/
|
|
1515
|
-
function collect_statement_bindings(statement, bindings) {
|
|
1390
|
+
export function collect_statement_bindings(statement, bindings) {
|
|
1516
1391
|
if (!statement) return;
|
|
1517
1392
|
|
|
1518
1393
|
if (statement.type === 'VariableDeclaration') {
|
|
@@ -1646,6 +1521,16 @@ function hoist_static_render_nodes(render_nodes, transform_context) {
|
|
|
1646
1521
|
const node = render_nodes[i];
|
|
1647
1522
|
if (node.type !== 'JSXElement') continue;
|
|
1648
1523
|
if (!is_hoist_safe_jsx_node(node)) continue;
|
|
1524
|
+
if (is_bare_component_invocation(node)) {
|
|
1525
|
+
// `<Helper />` with no attributes and no children is just an
|
|
1526
|
+
// invocation reference — most often a generated `StatementBodyHook`
|
|
1527
|
+
// chain element we emitted ourselves. Hoisting it would produce
|
|
1528
|
+
// `const App__staticN = <Helper />` aliases that bloat the output
|
|
1529
|
+
// without enabling React's element-identity fast path (the helper
|
|
1530
|
+
// isn't memoized, so the parent re-invokes it every render either
|
|
1531
|
+
// way). Inline the reference at the call site instead.
|
|
1532
|
+
continue;
|
|
1533
|
+
}
|
|
1649
1534
|
if (
|
|
1650
1535
|
transform_context.platform.hooks?.canHoistStaticNode &&
|
|
1651
1536
|
!transform_context.platform.hooks.canHoistStaticNode(node, transform_context)
|
|
@@ -1663,6 +1548,23 @@ function hoist_static_render_nodes(render_nodes, transform_context) {
|
|
|
1663
1548
|
}
|
|
1664
1549
|
}
|
|
1665
1550
|
|
|
1551
|
+
/**
|
|
1552
|
+
* `<Helper />` shape with no attributes and no children. The opening element
|
|
1553
|
+
* name must be component-shaped (see `is_component_jsx_name`) — lowercase
|
|
1554
|
+
* identifiers are host DOM tags, which *do* benefit from hoisting because
|
|
1555
|
+
* React diffs them against the previous render.
|
|
1556
|
+
*
|
|
1557
|
+
* @param {any} node
|
|
1558
|
+
* @returns {boolean}
|
|
1559
|
+
*/
|
|
1560
|
+
function is_bare_component_invocation(node) {
|
|
1561
|
+
if (!node || node.type !== 'JSXElement') return false;
|
|
1562
|
+
const opening = node.openingElement;
|
|
1563
|
+
if (!opening || opening.attributes.length > 0) return false;
|
|
1564
|
+
if (node.children.length > 0) return false;
|
|
1565
|
+
return is_component_jsx_name(opening.name);
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1666
1568
|
/**
|
|
1667
1569
|
* Static JSX that appears before multiple early-return guards is otherwise
|
|
1668
1570
|
* cloned into every generated return. Capture it once at its source position
|
|
@@ -1891,169 +1793,6 @@ function create_component_returning_if_statement(node, render_nodes, transform_c
|
|
|
1891
1793
|
return set_loc(b.if(node.test, set_loc(b.block(branch_statements), node.consequent), null), node);
|
|
1892
1794
|
}
|
|
1893
1795
|
|
|
1894
|
-
/* ---------------------------------------------------------------------- *
|
|
1895
|
-
* Continuation-lift primitives shared across if / switch / try / for-of *
|
|
1896
|
-
* ---------------------------------------------------------------------- */
|
|
1897
|
-
|
|
1898
|
-
/**
|
|
1899
|
-
* Build the helper component that owns the post-control-flow continuation.
|
|
1900
|
-
* Same shape as `create_hook_safe_helper`; named for intent at lift call sites.
|
|
1901
|
-
*
|
|
1902
|
-
* @param {any[]} continuation_body
|
|
1903
|
-
* @param {any} source_node
|
|
1904
|
-
* @param {TransformContext} transform_context
|
|
1905
|
-
* @returns {{ setup_statements: any[], component_element: ESTreeJSX.JSXElement }}
|
|
1906
|
-
*/
|
|
1907
|
-
function build_tail_helper(continuation_body, source_node, transform_context) {
|
|
1908
|
-
return create_hook_safe_helper(continuation_body, undefined, source_node, transform_context);
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
/**
|
|
1912
|
-
* Clone the tail helper's component element for embedding inside another
|
|
1913
|
-
* branch's body. Loses location info because the same element appears in
|
|
1914
|
-
* multiple positions and downstream tooling treats AST nodes as identity-keyed.
|
|
1915
|
-
*
|
|
1916
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
1917
|
-
* @returns {any}
|
|
1918
|
-
*/
|
|
1919
|
-
function clone_tail_invocation(tail_helper) {
|
|
1920
|
-
return clone_expression_node(tail_helper.component_element, false);
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
/**
|
|
1924
|
-
* Return `[...body, <TailHelper x={x} />]` so the branch's render output
|
|
1925
|
-
* includes the tail invocation and the post-hook locals flow forward.
|
|
1926
|
-
* Used by if / switch / try (unconditional append). For-of uses a different
|
|
1927
|
-
* shape — gating on `_tsrx_isLast_<n>` — so it constructs its own.
|
|
1928
|
-
*
|
|
1929
|
-
* @param {any[]} body
|
|
1930
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
1931
|
-
* @returns {any[]}
|
|
1932
|
-
*/
|
|
1933
|
-
function append_tail_invocation(body, tail_helper) {
|
|
1934
|
-
return [...body, clone_tail_invocation(tail_helper)];
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
/**
|
|
1938
|
-
* @param {AST.Identifier} tail_synthetic_id
|
|
1939
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
1940
|
-
* @returns {any}
|
|
1941
|
-
*/
|
|
1942
|
-
function create_loop_tail_expression(tail_synthetic_id, tail_helper) {
|
|
1943
|
-
return b.logical('&&', clone_identifier(tail_synthetic_id), clone_tail_invocation(tail_helper));
|
|
1944
|
-
}
|
|
1945
|
-
|
|
1946
|
-
/**
|
|
1947
|
-
* @param {AST.Identifier} tail_synthetic_id
|
|
1948
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
1949
|
-
* @returns {any}
|
|
1950
|
-
*/
|
|
1951
|
-
function create_loop_tail_conditional(tail_synthetic_id, tail_helper) {
|
|
1952
|
-
return b.conditional(
|
|
1953
|
-
clone_identifier(tail_synthetic_id),
|
|
1954
|
-
clone_tail_invocation(tail_helper),
|
|
1955
|
-
create_null_literal(),
|
|
1956
|
-
);
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
/**
|
|
1960
|
-
* @param {any[]} statements
|
|
1961
|
-
* @param {AST.Identifier} tail_synthetic_id
|
|
1962
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
1963
|
-
* @returns {void}
|
|
1964
|
-
*/
|
|
1965
|
-
function append_loop_tail_to_return_statements(statements, tail_synthetic_id, tail_helper) {
|
|
1966
|
-
for (const statement of statements) {
|
|
1967
|
-
append_loop_tail_to_return_statement(statement, tail_synthetic_id, tail_helper, false);
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
|
|
1971
|
-
/**
|
|
1972
|
-
* @param {any} node
|
|
1973
|
-
* @param {AST.Identifier} tail_synthetic_id
|
|
1974
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
1975
|
-
* @param {boolean} inside_nested_function
|
|
1976
|
-
* @returns {void}
|
|
1977
|
-
*/
|
|
1978
|
-
function append_loop_tail_to_return_statement(
|
|
1979
|
-
node,
|
|
1980
|
-
tail_synthetic_id,
|
|
1981
|
-
tail_helper,
|
|
1982
|
-
inside_nested_function,
|
|
1983
|
-
) {
|
|
1984
|
-
if (!node || typeof node !== 'object') {
|
|
1985
|
-
return;
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
if (
|
|
1989
|
-
node.type === 'FunctionDeclaration' ||
|
|
1990
|
-
node.type === 'FunctionExpression' ||
|
|
1991
|
-
node.type === 'ArrowFunctionExpression'
|
|
1992
|
-
) {
|
|
1993
|
-
inside_nested_function = true;
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
if (!inside_nested_function && node.type === 'ReturnStatement') {
|
|
1997
|
-
if (
|
|
1998
|
-
references_scope_bindings(
|
|
1999
|
-
node.argument,
|
|
2000
|
-
new Map([[tail_synthetic_id.name, tail_synthetic_id]]),
|
|
2001
|
-
)
|
|
2002
|
-
) {
|
|
2003
|
-
return;
|
|
2004
|
-
}
|
|
2005
|
-
node.argument = append_loop_tail_to_return_argument(
|
|
2006
|
-
node.argument,
|
|
2007
|
-
tail_synthetic_id,
|
|
2008
|
-
tail_helper,
|
|
2009
|
-
);
|
|
2010
|
-
return;
|
|
2011
|
-
}
|
|
2012
|
-
|
|
2013
|
-
if (Array.isArray(node)) {
|
|
2014
|
-
for (const child of node) {
|
|
2015
|
-
append_loop_tail_to_return_statement(
|
|
2016
|
-
child,
|
|
2017
|
-
tail_synthetic_id,
|
|
2018
|
-
tail_helper,
|
|
2019
|
-
inside_nested_function,
|
|
2020
|
-
);
|
|
2021
|
-
}
|
|
2022
|
-
return;
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
for (const key of Object.keys(node)) {
|
|
2026
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
2027
|
-
continue;
|
|
2028
|
-
}
|
|
2029
|
-
append_loop_tail_to_return_statement(
|
|
2030
|
-
node[key],
|
|
2031
|
-
tail_synthetic_id,
|
|
2032
|
-
tail_helper,
|
|
2033
|
-
inside_nested_function,
|
|
2034
|
-
);
|
|
2035
|
-
}
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
/**
|
|
2039
|
-
* @param {any} return_argument
|
|
2040
|
-
* @param {AST.Identifier} tail_synthetic_id
|
|
2041
|
-
* @param {{ component_element: ESTreeJSX.JSXElement }} tail_helper
|
|
2042
|
-
* @returns {any}
|
|
2043
|
-
*/
|
|
2044
|
-
function append_loop_tail_to_return_argument(return_argument, tail_synthetic_id, tail_helper) {
|
|
2045
|
-
if (return_argument == null || is_null_literal(return_argument)) {
|
|
2046
|
-
return create_loop_tail_conditional(tail_synthetic_id, tail_helper);
|
|
2047
|
-
}
|
|
2048
|
-
|
|
2049
|
-
return (
|
|
2050
|
-
build_return_expression([
|
|
2051
|
-
return_argument_to_render_node(return_argument),
|
|
2052
|
-
to_jsx_expression_container(create_loop_tail_expression(tail_synthetic_id, tail_helper)),
|
|
2053
|
-
]) || create_null_literal()
|
|
2054
|
-
);
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
1796
|
/**
|
|
2058
1797
|
* Build a `return <combined-render-fragment>;` statement, prepending any
|
|
2059
1798
|
* `render_nodes` collected before the control-flow construct so they don't
|
|
@@ -2133,256 +1872,6 @@ function create_component_helper_split_returning_if_statements(
|
|
|
2133
1872
|
];
|
|
2134
1873
|
}
|
|
2135
1874
|
|
|
2136
|
-
/**
|
|
2137
|
-
* Lift a non-returning `if` whose consequent contains hook calls plus the
|
|
2138
|
-
* statements that follow it into helper components.
|
|
2139
|
-
*
|
|
2140
|
-
* Without this, the consequent's hook would be wrapped into a child component
|
|
2141
|
-
* (StatementBodyHook) but any code after the `if` that reads bindings the hook
|
|
2142
|
-
* mutates would observe the pre-hook value, because React commits children
|
|
2143
|
-
* after their parent has finished rendering. The fix mirrors the early-return
|
|
2144
|
-
* splitter: emit a tail helper that owns the post-`if` statements, append a
|
|
2145
|
-
* call to it inside the branch helper so the post-hook bindings flow forward,
|
|
2146
|
-
* and render the tail helper directly when the `if` is false.
|
|
2147
|
-
*
|
|
2148
|
-
* @param {any} if_node
|
|
2149
|
-
* @param {any[]} continuation_body
|
|
2150
|
-
* @param {any[]} render_nodes
|
|
2151
|
-
* @param {TransformContext} transform_context
|
|
2152
|
-
* @returns {any[]}
|
|
2153
|
-
*/
|
|
2154
|
-
function create_continuation_lift_if_statement(
|
|
2155
|
-
if_node,
|
|
2156
|
-
continuation_body,
|
|
2157
|
-
render_nodes,
|
|
2158
|
-
transform_context,
|
|
2159
|
-
) {
|
|
2160
|
-
const consequent_body = get_if_consequent_body(if_node);
|
|
2161
|
-
const tail_helper = build_tail_helper(continuation_body, if_node, transform_context);
|
|
2162
|
-
const branch_helper = create_hook_safe_helper(
|
|
2163
|
-
append_tail_invocation(consequent_body, tail_helper),
|
|
2164
|
-
undefined,
|
|
2165
|
-
if_node.consequent,
|
|
2166
|
-
transform_context,
|
|
2167
|
-
);
|
|
2168
|
-
|
|
2169
|
-
const branch_block = set_loc(
|
|
2170
|
-
b.block([
|
|
2171
|
-
...branch_helper.setup_statements,
|
|
2172
|
-
combined_return_statement(render_nodes, branch_helper.component_element),
|
|
2173
|
-
]),
|
|
2174
|
-
if_node.consequent,
|
|
2175
|
-
);
|
|
2176
|
-
|
|
2177
|
-
return [
|
|
2178
|
-
...tail_helper.setup_statements,
|
|
2179
|
-
set_loc(b.if(if_node.test, branch_block, null), if_node),
|
|
2180
|
-
combined_return_statement(render_nodes, tail_helper.component_element),
|
|
2181
|
-
];
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2184
|
-
/**
|
|
2185
|
-
* Continuation lift for `try` / `try / pending / catch` statements. Same
|
|
2186
|
-
* shape as if/switch: build a tail helper from the post-`try` statements, and
|
|
2187
|
-
* append a clone of its invocation to the try body and the catch body so the
|
|
2188
|
-
* post-hook locals inside each branch flow forward into the tail. The pending
|
|
2189
|
-
* body is left untouched — when Suspense renders the pending fallback the
|
|
2190
|
-
* parent's render is unwound, so the tail wouldn't run in source semantics
|
|
2191
|
-
* either. Once augmented, the existing try transform builds the
|
|
2192
|
-
* Suspense / TsrxErrorBoundary wrapper as usual.
|
|
2193
|
-
*
|
|
2194
|
-
* @param {any} node - TryStatement
|
|
2195
|
-
* @param {any[]} continuation_body
|
|
2196
|
-
* @param {any[]} render_nodes
|
|
2197
|
-
* @param {TransformContext} transform_context
|
|
2198
|
-
* @returns {any[]}
|
|
2199
|
-
*/
|
|
2200
|
-
function create_continuation_lift_try_statement(
|
|
2201
|
-
node,
|
|
2202
|
-
continuation_body,
|
|
2203
|
-
render_nodes,
|
|
2204
|
-
transform_context,
|
|
2205
|
-
) {
|
|
2206
|
-
const tail_helper = build_tail_helper(continuation_body, node, transform_context);
|
|
2207
|
-
|
|
2208
|
-
const augmented_block = {
|
|
2209
|
-
...node.block,
|
|
2210
|
-
body: append_tail_invocation(node.block.body || [], tail_helper),
|
|
2211
|
-
};
|
|
2212
|
-
|
|
2213
|
-
let augmented_handler = node.handler;
|
|
2214
|
-
if (node.handler) {
|
|
2215
|
-
augmented_handler = {
|
|
2216
|
-
...node.handler,
|
|
2217
|
-
body: {
|
|
2218
|
-
...node.handler.body,
|
|
2219
|
-
body: append_tail_invocation(node.handler.body.body || [], tail_helper),
|
|
2220
|
-
},
|
|
2221
|
-
};
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
|
-
const augmented_try = {
|
|
2225
|
-
...node,
|
|
2226
|
-
block: augmented_block,
|
|
2227
|
-
handler: augmented_handler,
|
|
2228
|
-
};
|
|
2229
|
-
|
|
2230
|
-
const try_jsx_child = (
|
|
2231
|
-
transform_context.platform.hooks?.controlFlow?.tryStatement ?? try_statement_to_jsx_child
|
|
2232
|
-
)(augmented_try, transform_context);
|
|
2233
|
-
|
|
2234
|
-
return [...tail_helper.setup_statements, combined_return_statement(render_nodes, try_jsx_child)];
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
/**
|
|
2238
|
-
* @param {any} node - TryStatement
|
|
2239
|
-
* @param {TransformContext} transform_context
|
|
2240
|
-
* @returns {boolean}
|
|
2241
|
-
*/
|
|
2242
|
-
function try_statement_contains_hooks(node, transform_context) {
|
|
2243
|
-
if (body_contains_top_level_hook_call(node.block?.body || [], transform_context, true)) {
|
|
2244
|
-
return true;
|
|
2245
|
-
}
|
|
2246
|
-
if (
|
|
2247
|
-
node.handler &&
|
|
2248
|
-
body_contains_top_level_hook_call(node.handler.body?.body || [], transform_context, true)
|
|
2249
|
-
) {
|
|
2250
|
-
return true;
|
|
2251
|
-
}
|
|
2252
|
-
if (
|
|
2253
|
-
node.pending &&
|
|
2254
|
-
body_contains_top_level_hook_call(node.pending.body || [], transform_context, true)
|
|
2255
|
-
) {
|
|
2256
|
-
return true;
|
|
2257
|
-
}
|
|
2258
|
-
return false;
|
|
2259
|
-
}
|
|
2260
|
-
|
|
2261
|
-
/**
|
|
2262
|
-
* Continuation lift for `switch` statements. Same shape as the if-version:
|
|
2263
|
-
* each case body is wrapped in its own helper component that ends with a
|
|
2264
|
-
* call to a shared tail helper, so post-hook bindings inside any case flow
|
|
2265
|
-
* forward to the statements after the switch. The fall-through return at
|
|
2266
|
-
* the end renders the tail helper directly, covering the case where no
|
|
2267
|
-
* `case` (and no `default`) matched.
|
|
2268
|
-
*
|
|
2269
|
-
* Empty fall-through cases (`case 'a':` with no body, falling through to
|
|
2270
|
-
* the next case) are preserved as-is — they must not get their own helper
|
|
2271
|
-
* because that would convert fall-through into early-return.
|
|
2272
|
-
*
|
|
2273
|
-
* @param {any} switch_node
|
|
2274
|
-
* @param {any[]} continuation_body
|
|
2275
|
-
* @param {any[]} render_nodes
|
|
2276
|
-
* @param {TransformContext} transform_context
|
|
2277
|
-
* @returns {any[]}
|
|
2278
|
-
*/
|
|
2279
|
-
function create_continuation_lift_switch_statement(
|
|
2280
|
-
switch_node,
|
|
2281
|
-
continuation_body,
|
|
2282
|
-
render_nodes,
|
|
2283
|
-
transform_context,
|
|
2284
|
-
) {
|
|
2285
|
-
const tail_helper = build_tail_helper(continuation_body, switch_node, transform_context);
|
|
2286
|
-
|
|
2287
|
-
// Per-case info computed once: own body (statements before any
|
|
2288
|
-
// terminator) and whether the case has a `break` / `return`.
|
|
2289
|
-
const case_info = switch_node.cases.map((/** @type {any} */ c) => {
|
|
2290
|
-
const consequent = flatten_switch_consequent(c.consequent || []);
|
|
2291
|
-
const own_body = [];
|
|
2292
|
-
let own_has_terminator = false;
|
|
2293
|
-
for (const node of consequent) {
|
|
2294
|
-
if (node.type === 'BreakStatement' || node.type === 'ReturnStatement') {
|
|
2295
|
-
own_has_terminator = true;
|
|
2296
|
-
break;
|
|
2297
|
-
}
|
|
2298
|
-
own_body.push(node);
|
|
2299
|
-
}
|
|
2300
|
-
return { own_body, own_has_terminator };
|
|
2301
|
-
});
|
|
2302
|
-
|
|
2303
|
-
// Allocate helper ids in source order (forward pass) so the snapshot's
|
|
2304
|
-
// `StatementBodyHook<N>` numbering reads top-to-bottom by case position.
|
|
2305
|
-
/** @type {Array<AST.Identifier | null>} */
|
|
2306
|
-
const helper_ids = case_info.map(
|
|
2307
|
-
(/** @type {{ own_body: any[], own_has_terminator: boolean }} */ info) =>
|
|
2308
|
-
info.own_body.length === 0
|
|
2309
|
-
? null
|
|
2310
|
-
: create_generated_identifier(create_local_statement_component_name(transform_context)),
|
|
2311
|
-
);
|
|
2312
|
-
|
|
2313
|
-
// Build helpers in reverse order: each fall-through case's helper body
|
|
2314
|
-
// invokes the *next* case's helper, so the chain forwards post-mutation
|
|
2315
|
-
// locals through the switch. Reverse iteration ensures the next helper's
|
|
2316
|
-
// component_element is already constructed when we need to embed it.
|
|
2317
|
-
/** @type {Array<{ setup_statements: any[], component_element: any } | null>} */
|
|
2318
|
-
const case_helper_by_index = new Array(switch_node.cases.length).fill(null);
|
|
2319
|
-
for (let i = switch_node.cases.length - 1; i >= 0; i--) {
|
|
2320
|
-
const { own_body, own_has_terminator } = case_info[i];
|
|
2321
|
-
if (own_body.length === 0) continue;
|
|
2322
|
-
|
|
2323
|
-
// Determine the downstream helper this case invokes after its own body.
|
|
2324
|
-
// - With a terminator: invoke the tail helper directly (case exits switch).
|
|
2325
|
-
// - Otherwise (fall-through): invoke the next non-empty case's helper,
|
|
2326
|
-
// or the tail if nothing else follows.
|
|
2327
|
-
let downstream;
|
|
2328
|
-
if (own_has_terminator) {
|
|
2329
|
-
downstream = tail_helper;
|
|
2330
|
-
} else {
|
|
2331
|
-
let next_helper = null;
|
|
2332
|
-
for (let j = i + 1; j < switch_node.cases.length; j++) {
|
|
2333
|
-
if (case_helper_by_index[j]) {
|
|
2334
|
-
next_helper = case_helper_by_index[j];
|
|
2335
|
-
break;
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
downstream = next_helper ?? tail_helper;
|
|
2339
|
-
}
|
|
2340
|
-
|
|
2341
|
-
case_helper_by_index[i] = create_hook_safe_helper(
|
|
2342
|
-
append_tail_invocation(own_body, downstream),
|
|
2343
|
-
undefined,
|
|
2344
|
-
switch_node.cases[i],
|
|
2345
|
-
transform_context,
|
|
2346
|
-
/** @type {any} */ (helper_ids[i]),
|
|
2347
|
-
);
|
|
2348
|
-
}
|
|
2349
|
-
|
|
2350
|
-
const new_cases = switch_node.cases.map(
|
|
2351
|
-
(/** @type {any} */ original_case, /** @type {number} */ i) => {
|
|
2352
|
-
const helper = case_helper_by_index[i];
|
|
2353
|
-
if (helper) {
|
|
2354
|
-
return b.switch_case(original_case.test, [
|
|
2355
|
-
combined_return_statement(render_nodes, helper.component_element),
|
|
2356
|
-
]);
|
|
2357
|
-
}
|
|
2358
|
-
|
|
2359
|
-
const { own_body, own_has_terminator } = case_info[i];
|
|
2360
|
-
if (own_body.length === 0 && own_has_terminator) {
|
|
2361
|
-
// `case 'a': break;` — exits the switch, then runs the tail.
|
|
2362
|
-
return b.switch_case(original_case.test, [
|
|
2363
|
-
combined_return_statement(render_nodes, tail_helper.component_element),
|
|
2364
|
-
]);
|
|
2365
|
-
}
|
|
2366
|
-
// Genuine empty fall-through (`case 'a': case 'b': ...`).
|
|
2367
|
-
return b.switch_case(original_case.test, []);
|
|
2368
|
-
},
|
|
2369
|
-
);
|
|
2370
|
-
|
|
2371
|
-
// Hoist all case helpers' setup statements above the switch in source
|
|
2372
|
-
// order so the switch body is purely a dispatcher.
|
|
2373
|
-
const case_helper_setup_statements = [];
|
|
2374
|
-
for (const helper of case_helper_by_index) {
|
|
2375
|
-
if (helper) case_helper_setup_statements.push(...helper.setup_statements);
|
|
2376
|
-
}
|
|
2377
|
-
|
|
2378
|
-
return [
|
|
2379
|
-
...tail_helper.setup_statements,
|
|
2380
|
-
...case_helper_setup_statements,
|
|
2381
|
-
set_loc(b.switch(switch_node.discriminant, new_cases), switch_node),
|
|
2382
|
-
combined_return_statement(render_nodes, tail_helper.component_element),
|
|
2383
|
-
];
|
|
2384
|
-
}
|
|
2385
|
-
|
|
2386
1875
|
/**
|
|
2387
1876
|
* Hoist the helper for a hook-bearing for-of body out of the iteration
|
|
2388
1877
|
* callback so the helper is declared once per render rather than re-bound on
|
|
@@ -2395,65 +1884,35 @@ function create_continuation_lift_switch_statement(
|
|
|
2395
1884
|
* works while skipping the copy when the source is already an array. The
|
|
2396
1885
|
* iteration itself is emitted as `source.map((item, i) => ...)`.
|
|
2397
1886
|
*
|
|
2398
|
-
* If `continuation_body` is non-empty (the for-of has a tail) we also lift
|
|
2399
|
-
* the tail into a TailHelper and call it conditionally on the last iteration
|
|
2400
|
-
* via an `isLast={i === source.length - 1}` prop on the loop helper. The
|
|
2401
|
-
* loop helper's mutated locals (post-`useState`) flow into the TailHelper as
|
|
2402
|
-
* its props. When the source is empty, `.map` returns `[]` and the TailHelper
|
|
2403
|
-
* never renders — we add a sibling fallback so the source's tail still runs
|
|
2404
|
-
* with the original outer values in that case.
|
|
2405
|
-
*
|
|
2406
1887
|
* Bails out (returns null) when the loop pattern is destructured — deriving
|
|
2407
1888
|
* element types from a tuple/object pattern is more involved and deferred.
|
|
2408
1889
|
*
|
|
2409
1890
|
* @param {any} node - ForOfStatement
|
|
2410
|
-
* @param {any[]} continuation_body
|
|
2411
1891
|
* @param {TransformContext} transform_context
|
|
2412
1892
|
* @returns {{ hoist_statements: any[], jsx_child: any } | null}
|
|
2413
1893
|
*/
|
|
2414
|
-
function build_hoisted_for_of_with_hooks(node,
|
|
1894
|
+
function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
2415
1895
|
const loop_params = get_for_of_iteration_params(node.left, node.index);
|
|
2416
1896
|
for (const param of loop_params) {
|
|
2417
1897
|
if (param.type !== 'Identifier') return null;
|
|
2418
1898
|
}
|
|
2419
1899
|
|
|
2420
|
-
const has_tail = continuation_body.length > 0;
|
|
2421
1900
|
const original_loop_body = /** @type {any[]} */ (
|
|
2422
1901
|
rewrite_loop_continues_to_bare_returns(
|
|
2423
1902
|
node.body.type === 'BlockStatement' ? node.body.body : [node.body],
|
|
2424
1903
|
)
|
|
2425
1904
|
);
|
|
2426
1905
|
|
|
2427
|
-
// When there's a tail, build TailHelper first so its component_element can
|
|
2428
|
-
// be embedded inside the loop helper's body (gated on isLast). The
|
|
2429
|
-
// synthetic isLast prop uses the loop helper's index (which will be the
|
|
2430
|
-
// next one assigned, since `create_hook_safe_helper` for the tail just
|
|
2431
|
-
// consumed one) so it lines up with `StatementBodyHook<N>` in the output.
|
|
2432
|
-
let tail_helper = null;
|
|
2433
|
-
/** @type {AST.Identifier} */ let tail_synthetic_id;
|
|
2434
|
-
if (has_tail) {
|
|
2435
|
-
tail_helper = build_tail_helper(continuation_body, node, transform_context);
|
|
2436
|
-
tail_synthetic_id = create_generated_identifier(
|
|
2437
|
-
`_tsrx_isLast_${transform_context.local_statement_component_index + 1}`,
|
|
2438
|
-
);
|
|
2439
|
-
} else {
|
|
2440
|
-
tail_synthetic_id = /** @type {any} */ (null);
|
|
2441
|
-
}
|
|
2442
|
-
const loop_tail_expression = has_tail
|
|
2443
|
-
? create_loop_tail_expression(tail_synthetic_id, /** @type {any} */ (tail_helper))
|
|
2444
|
-
: null;
|
|
2445
|
-
const loop_body =
|
|
2446
|
-
has_tail && loop_tail_expression
|
|
2447
|
-
? [...original_loop_body, b.jsx_expression_container(loop_tail_expression)]
|
|
2448
|
-
: original_loop_body;
|
|
2449
|
-
|
|
2450
1906
|
const source_id = create_generated_identifier(
|
|
2451
1907
|
`_tsrx_iteration_items_${transform_context.local_statement_component_index + 1}`,
|
|
2452
1908
|
);
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
1909
|
+
const use_iterable_helper = !!transform_context.platform.imports.forOfIterableHelper;
|
|
1910
|
+
const { source_decl, source_normalize_decl } = use_iterable_helper
|
|
1911
|
+
? {
|
|
1912
|
+
source_decl: b.let(clone_identifier(source_id), clone_expression_node(node.right)),
|
|
1913
|
+
source_normalize_decl: null,
|
|
1914
|
+
}
|
|
1915
|
+
: build_array_normalization_decls(source_id, node.right);
|
|
2457
1916
|
|
|
2458
1917
|
const saved_bindings = transform_context.available_bindings;
|
|
2459
1918
|
transform_context.available_bindings = new Map(saved_bindings);
|
|
@@ -2468,7 +1927,7 @@ function build_hoisted_for_of_with_hooks(node, continuation_body, transform_cont
|
|
|
2468
1927
|
);
|
|
2469
1928
|
|
|
2470
1929
|
const all_helper_bindings = get_referenced_helper_bindings(
|
|
2471
|
-
|
|
1930
|
+
original_loop_body,
|
|
2472
1931
|
transform_context.available_bindings,
|
|
2473
1932
|
);
|
|
2474
1933
|
const outer_bindings = all_helper_bindings.filter((b) => !loop_scoped_names.has(b.name));
|
|
@@ -2488,69 +1947,42 @@ function build_hoisted_for_of_with_hooks(node, continuation_body, transform_cont
|
|
|
2488
1947
|
const loop_aliases = use_module_scoped_component
|
|
2489
1948
|
? []
|
|
2490
1949
|
: loop_bindings.map((binding) =>
|
|
2491
|
-
create_loop_scoped_type_alias_declaration(
|
|
1950
|
+
create_loop_scoped_type_alias_declaration(
|
|
1951
|
+
helper_id,
|
|
1952
|
+
binding,
|
|
1953
|
+
source_id,
|
|
1954
|
+
loop_params,
|
|
1955
|
+
transform_context,
|
|
1956
|
+
),
|
|
2492
1957
|
);
|
|
2493
1958
|
|
|
2494
|
-
// Synthetic `isLast` prop on the loop helper when there's a tail. It's
|
|
2495
|
-
// passed from the .map callback as `i === source.length - 1` so every
|
|
2496
|
-
// loop-helper return can append the tail helper on the last iteration.
|
|
2497
|
-
const tail_isLast_alias = has_tail
|
|
2498
|
-
? use_module_scoped_component
|
|
2499
|
-
? null
|
|
2500
|
-
: {
|
|
2501
|
-
id: create_generated_identifier(`_tsrx_${helper_id.name}_isLast`),
|
|
2502
|
-
declaration: b.ts_type_alias(
|
|
2503
|
-
create_generated_identifier(`_tsrx_${helper_id.name}_isLast`),
|
|
2504
|
-
b.ts_keyword_type('boolean'),
|
|
2505
|
-
),
|
|
2506
|
-
}
|
|
2507
|
-
: null;
|
|
2508
|
-
|
|
2509
1959
|
const ordered_bindings = [...outer_bindings, ...loop_bindings];
|
|
2510
1960
|
const ordered_aliases = [...outer_aliases, ...loop_aliases];
|
|
2511
1961
|
const ordered_use_typeof = [...outer_bindings.map(() => true), ...loop_bindings.map(() => false)];
|
|
2512
1962
|
|
|
2513
|
-
const signature_bindings = has_tail ? [...ordered_bindings, tail_synthetic_id] : ordered_bindings;
|
|
2514
|
-
const signature_aliases = has_tail
|
|
2515
|
-
? [...ordered_aliases, /** @type {any} */ (tail_isLast_alias)]
|
|
2516
|
-
: ordered_aliases;
|
|
2517
|
-
const signature_use_typeof = has_tail ? [...ordered_use_typeof, false] : ordered_use_typeof;
|
|
2518
|
-
|
|
2519
1963
|
const props_type =
|
|
2520
|
-
|
|
1964
|
+
ordered_bindings.length > 0 && !use_module_scoped_component
|
|
2521
1965
|
? create_helper_props_type_literal_with_typeof_flags(
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
1966
|
+
ordered_bindings,
|
|
1967
|
+
ordered_aliases,
|
|
1968
|
+
ordered_use_typeof,
|
|
2525
1969
|
)
|
|
2526
1970
|
: null;
|
|
2527
1971
|
const params =
|
|
2528
|
-
|
|
1972
|
+
ordered_bindings.length > 0
|
|
2529
1973
|
? [
|
|
2530
1974
|
props_type !== null
|
|
2531
|
-
? create_typed_helper_props_pattern(
|
|
2532
|
-
: create_helper_props_pattern(
|
|
1975
|
+
? create_typed_helper_props_pattern(ordered_bindings, props_type)
|
|
1976
|
+
: create_helper_props_pattern(ordered_bindings),
|
|
2533
1977
|
]
|
|
2534
1978
|
: [];
|
|
2535
1979
|
|
|
2536
1980
|
const fn_saved_bindings = transform_context.available_bindings;
|
|
2537
1981
|
transform_context.available_bindings = new Map(fn_saved_bindings);
|
|
2538
|
-
|
|
2539
|
-
transform_context.available_bindings.set(tail_synthetic_id.name, tail_synthetic_id);
|
|
2540
|
-
}
|
|
2541
|
-
const fn_body_statements = build_render_statements(loop_body, true, transform_context);
|
|
2542
|
-
if (has_tail) {
|
|
2543
|
-
append_loop_tail_to_return_statements(
|
|
2544
|
-
fn_body_statements,
|
|
2545
|
-
tail_synthetic_id,
|
|
2546
|
-
/** @type {any} */ (tail_helper),
|
|
2547
|
-
);
|
|
2548
|
-
}
|
|
1982
|
+
const fn_body_statements = build_render_statements(original_loop_body, true, transform_context);
|
|
2549
1983
|
transform_context.available_bindings = fn_saved_bindings;
|
|
2550
1984
|
|
|
2551
|
-
const helper_fn =
|
|
2552
|
-
b.function(clone_identifier(component_id), params, b.block(fn_body_statements))
|
|
2553
|
-
);
|
|
1985
|
+
const helper_fn = b.function(clone_identifier(component_id), params, b.block(fn_body_statements));
|
|
2554
1986
|
helper_fn.metadata = { path: [], is_component: true, is_method: false };
|
|
2555
1987
|
|
|
2556
1988
|
let helper_decl;
|
|
@@ -2582,18 +2014,6 @@ function build_hoisted_for_of_with_hooks(node, continuation_body, transform_cont
|
|
|
2582
2014
|
{ mapWrapper: false, mapBindingNames: false, mapBindingValues: false },
|
|
2583
2015
|
);
|
|
2584
2016
|
|
|
2585
|
-
// When there's a tail, the .map callback always needs an index to compute
|
|
2586
|
-
// `isLast`. If the user didn't write `index i`, synthesize one. The same
|
|
2587
|
-
// identifier is also used as the implicit key fallback below.
|
|
2588
|
-
let index_identifier;
|
|
2589
|
-
if (loop_params.length >= 2) {
|
|
2590
|
-
index_identifier = clone_identifier(loop_params[1]);
|
|
2591
|
-
} else if (has_tail) {
|
|
2592
|
-
index_identifier = create_generated_identifier('i');
|
|
2593
|
-
} else {
|
|
2594
|
-
index_identifier = null;
|
|
2595
|
-
}
|
|
2596
|
-
|
|
2597
2017
|
const body_key_expression = find_key_expression_in_body(original_loop_body);
|
|
2598
2018
|
const explicit_key_expression =
|
|
2599
2019
|
body_key_expression ?? (node.key ? clone_expression_node(node.key) : undefined);
|
|
@@ -2606,57 +2026,24 @@ function build_hoisted_for_of_with_hooks(node, continuation_body, transform_cont
|
|
|
2606
2026
|
);
|
|
2607
2027
|
}
|
|
2608
2028
|
|
|
2609
|
-
|
|
2610
|
-
const length_minus_one = b.binary(
|
|
2611
|
-
'-',
|
|
2612
|
-
b.member(clone_identifier(source_id), 'length'),
|
|
2613
|
-
b.literal(1),
|
|
2614
|
-
);
|
|
2615
|
-
callback_invocation_element.openingElement.attributes.push(
|
|
2616
|
-
b.jsx_attribute(
|
|
2617
|
-
b.jsx_id(tail_synthetic_id.name),
|
|
2618
|
-
to_jsx_expression_container(
|
|
2619
|
-
b.binary('===', clone_identifier(index_identifier), length_minus_one),
|
|
2620
|
-
),
|
|
2621
|
-
),
|
|
2622
|
-
);
|
|
2623
|
-
}
|
|
2624
|
-
|
|
2625
|
-
const callback_params =
|
|
2626
|
-
has_tail && loop_params.length < 2 && index_identifier
|
|
2627
|
-
? [
|
|
2628
|
-
...loop_params.map((/** @type {any} */ p) => clone_identifier(p)),
|
|
2629
|
-
clone_identifier(index_identifier),
|
|
2630
|
-
]
|
|
2631
|
-
: loop_params.map((/** @type {any} */ p) => clone_identifier(p));
|
|
2029
|
+
const callback_params = loop_params.map((/** @type {any} */ p) => clone_identifier(p));
|
|
2632
2030
|
|
|
2633
2031
|
const iter_callback = b.arrow(callback_params, callback_invocation_element);
|
|
2634
2032
|
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
? to_jsx_expression_container(
|
|
2642
|
-
b.conditional(
|
|
2643
|
-
b.binary('===', b.member(clone_identifier(source_id), 'length'), b.literal(0)),
|
|
2644
|
-
clone_tail_invocation(/** @type {any} */ (tail_helper)),
|
|
2645
|
-
map_call,
|
|
2646
|
-
),
|
|
2647
|
-
node,
|
|
2648
|
-
)
|
|
2649
|
-
: to_jsx_expression_container(map_call, node);
|
|
2650
|
-
|
|
2651
|
-
const hoist_statements = [source_decl, source_normalize_decl];
|
|
2652
|
-
if (has_tail) {
|
|
2653
|
-
// TailHelper's setup statements (its alias consts and cache decl).
|
|
2654
|
-
hoist_statements.push(.../** @type {any} */ (tail_helper).setup_statements);
|
|
2033
|
+
let map_call;
|
|
2034
|
+
if (use_iterable_helper) {
|
|
2035
|
+
transform_context.needs_for_of_iterable = true;
|
|
2036
|
+
map_call = b.call(b.id(MAP_ITERABLE_INTERNAL_NAME), clone_identifier(source_id), iter_callback);
|
|
2037
|
+
} else {
|
|
2038
|
+
map_call = b.call(b.member(clone_identifier(source_id), 'map'), iter_callback);
|
|
2655
2039
|
}
|
|
2040
|
+
|
|
2041
|
+
const jsx_child = to_jsx_expression_container(map_call, node);
|
|
2042
|
+
|
|
2043
|
+
const hoist_statements = source_normalize_decl
|
|
2044
|
+
? [source_decl, source_normalize_decl]
|
|
2045
|
+
: [source_decl];
|
|
2656
2046
|
for (const alias of ordered_aliases) hoist_statements.push(alias.declaration);
|
|
2657
|
-
if (has_tail && tail_isLast_alias) {
|
|
2658
|
-
hoist_statements.push(tail_isLast_alias.declaration);
|
|
2659
|
-
}
|
|
2660
2047
|
if (helper_decl) {
|
|
2661
2048
|
hoist_statements.push(helper_decl);
|
|
2662
2049
|
}
|
|
@@ -2669,28 +2056,49 @@ function build_hoisted_for_of_with_hooks(node, continuation_body, transform_cont
|
|
|
2669
2056
|
|
|
2670
2057
|
/**
|
|
2671
2058
|
* Build a TS `type` alias for a loop-scoped binding, deriving the type
|
|
2672
|
-
* from the iteration source. For the
|
|
2673
|
-
* `
|
|
2674
|
-
*
|
|
2675
|
-
*
|
|
2059
|
+
* from the iteration source. For the index param the type is always
|
|
2060
|
+
* `number`. For the value param the shape depends on whether the platform
|
|
2061
|
+
* uses the `map_iterable` runtime helper:
|
|
2062
|
+
*
|
|
2063
|
+
* - With the helper (React, Preact): `IterationValue<typeof source>` — any
|
|
2064
|
+
* `Iterable<T>` is accepted, so the element type is derived through the
|
|
2065
|
+
* runtime's exported helper type.
|
|
2066
|
+
* - Without the helper: `(typeof source)[number]` — arrays/tuples only,
|
|
2067
|
+
* matching the inline `.map()` lowering.
|
|
2676
2068
|
*
|
|
2677
2069
|
* @param {AST.Identifier} helper_id
|
|
2678
2070
|
* @param {AST.Identifier} binding
|
|
2679
2071
|
* @param {AST.Identifier} source_id
|
|
2680
2072
|
* @param {any[]} loop_params
|
|
2073
|
+
* @param {TransformContext} transform_context
|
|
2681
2074
|
* @returns {{ id: AST.Identifier, declaration: any }}
|
|
2682
2075
|
*/
|
|
2683
|
-
function create_loop_scoped_type_alias_declaration(
|
|
2076
|
+
function create_loop_scoped_type_alias_declaration(
|
|
2077
|
+
helper_id,
|
|
2078
|
+
binding,
|
|
2079
|
+
source_id,
|
|
2080
|
+
loop_params,
|
|
2081
|
+
transform_context,
|
|
2082
|
+
) {
|
|
2684
2083
|
const alias_id = create_generated_identifier(`_tsrx_${helper_id.name}_${binding.name}`);
|
|
2685
2084
|
const is_index = loop_params.length > 1 && binding.name === loop_params[1].name;
|
|
2085
|
+
const use_iterable_helper = !!transform_context.platform.imports.forOfIterableHelper;
|
|
2686
2086
|
const type_annotation = is_index
|
|
2687
2087
|
? b.ts_keyword_type('number')
|
|
2688
|
-
:
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2088
|
+
: use_iterable_helper
|
|
2089
|
+
? (() => {
|
|
2090
|
+
transform_context.needs_iteration_value_type = true;
|
|
2091
|
+
return b.ts_type_reference(
|
|
2092
|
+
b.id(ITERATION_VALUE_INTERNAL_NAME),
|
|
2093
|
+
b.ts_type_parameter_instantiation([b.ts_type_query(clone_identifier(source_id))]),
|
|
2094
|
+
);
|
|
2095
|
+
})()
|
|
2096
|
+
: /** @type {any} */ ({
|
|
2097
|
+
type: 'TSIndexedAccessType',
|
|
2098
|
+
objectType: b.ts_type_query(clone_identifier(source_id)),
|
|
2099
|
+
indexType: b.ts_keyword_type('number'),
|
|
2100
|
+
metadata: { path: [] },
|
|
2101
|
+
});
|
|
2694
2102
|
|
|
2695
2103
|
return {
|
|
2696
2104
|
id: alias_id,
|
|
@@ -2750,23 +2158,19 @@ function create_setup_once_helper_split_returning_if_statements(
|
|
|
2750
2158
|
return [
|
|
2751
2159
|
...branch_helper.setup_statements,
|
|
2752
2160
|
...continuation_helper.setup_statements,
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
argument: combine_render_return_argument(
|
|
2161
|
+
b.return(
|
|
2162
|
+
combine_render_return_argument(
|
|
2756
2163
|
render_nodes,
|
|
2757
2164
|
set_loc(
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
metadata: { path: [] },
|
|
2764
|
-
}),
|
|
2165
|
+
b.conditional(
|
|
2166
|
+
node.test,
|
|
2167
|
+
branch_helper.component_element,
|
|
2168
|
+
continuation_helper.component_element,
|
|
2169
|
+
),
|
|
2765
2170
|
node,
|
|
2766
2171
|
),
|
|
2767
2172
|
),
|
|
2768
|
-
|
|
2769
|
-
},
|
|
2173
|
+
),
|
|
2770
2174
|
];
|
|
2771
2175
|
}
|
|
2772
2176
|
|
|
@@ -3038,25 +2442,7 @@ function statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
|
3038
2442
|
}
|
|
3039
2443
|
|
|
3040
2444
|
return to_jsx_expression_container(
|
|
3041
|
-
|
|
3042
|
-
type: 'CallExpression',
|
|
3043
|
-
callee: {
|
|
3044
|
-
type: 'ArrowFunctionExpression',
|
|
3045
|
-
params: [],
|
|
3046
|
-
body: /** @type {any} */ ({
|
|
3047
|
-
type: 'BlockStatement',
|
|
3048
|
-
body: build_render_statements(body_nodes, true, transform_context),
|
|
3049
|
-
metadata: { path: [] },
|
|
3050
|
-
}),
|
|
3051
|
-
async: false,
|
|
3052
|
-
generator: false,
|
|
3053
|
-
expression: false,
|
|
3054
|
-
metadata: { path: [] },
|
|
3055
|
-
},
|
|
3056
|
-
arguments: [],
|
|
3057
|
-
optional: false,
|
|
3058
|
-
metadata: { path: [] },
|
|
3059
|
-
}),
|
|
2445
|
+
b.call(b.arrow([], b.block(build_render_statements(body_nodes, true, transform_context)))),
|
|
3060
2446
|
);
|
|
3061
2447
|
}
|
|
3062
2448
|
|
|
@@ -3107,11 +2493,7 @@ function hook_safe_render_statements(body_nodes, key_expression, transform_conte
|
|
|
3107
2493
|
);
|
|
3108
2494
|
const statements = [...helper.setup_statements];
|
|
3109
2495
|
|
|
3110
|
-
statements.push(
|
|
3111
|
-
type: 'ReturnStatement',
|
|
3112
|
-
argument: helper.component_element,
|
|
3113
|
-
metadata: { path: [] },
|
|
3114
|
-
});
|
|
2496
|
+
statements.push(b.return(helper.component_element));
|
|
3115
2497
|
|
|
3116
2498
|
return statements;
|
|
3117
2499
|
}
|
|
@@ -3365,7 +2747,7 @@ function validate_hook_outer_assignments_in_node(
|
|
|
3365
2747
|
);
|
|
3366
2748
|
if (outer_names.length > 0) {
|
|
3367
2749
|
report_hook_outer_assignment_error(
|
|
3368
|
-
node,
|
|
2750
|
+
node.left,
|
|
3369
2751
|
outer_names,
|
|
3370
2752
|
find_first_hook_call_name(node.right) || 'hook',
|
|
3371
2753
|
transform_context,
|
|
@@ -3389,7 +2771,7 @@ function validate_hook_outer_assignments_in_node(
|
|
|
3389
2771
|
);
|
|
3390
2772
|
if (outer_names.length > 0) {
|
|
3391
2773
|
report_hook_outer_assignment_error(
|
|
3392
|
-
node,
|
|
2774
|
+
node.left,
|
|
3393
2775
|
outer_names,
|
|
3394
2776
|
find_first_hook_call_name(node.right) || 'hook',
|
|
3395
2777
|
transform_context,
|
|
@@ -3557,7 +2939,12 @@ function validate_hook_callback_outer_mutations_in_node(
|
|
|
3557
2939
|
shadowed_names,
|
|
3558
2940
|
);
|
|
3559
2941
|
if (outer_names.length > 0) {
|
|
3560
|
-
report_hook_callback_outer_mutation_error(
|
|
2942
|
+
report_hook_callback_outer_mutation_error(
|
|
2943
|
+
node.left,
|
|
2944
|
+
outer_names,
|
|
2945
|
+
hook_name,
|
|
2946
|
+
transform_context,
|
|
2947
|
+
);
|
|
3561
2948
|
}
|
|
3562
2949
|
}
|
|
3563
2950
|
|
|
@@ -3568,7 +2955,12 @@ function validate_hook_callback_outer_mutations_in_node(
|
|
|
3568
2955
|
shadowed_names,
|
|
3569
2956
|
);
|
|
3570
2957
|
if (outer_names.length > 0) {
|
|
3571
|
-
report_hook_callback_outer_mutation_error(
|
|
2958
|
+
report_hook_callback_outer_mutation_error(
|
|
2959
|
+
node.argument,
|
|
2960
|
+
outer_names,
|
|
2961
|
+
hook_name,
|
|
2962
|
+
transform_context,
|
|
2963
|
+
);
|
|
3572
2964
|
}
|
|
3573
2965
|
}
|
|
3574
2966
|
|
|
@@ -3863,23 +3255,13 @@ function create_hook_safe_helper(
|
|
|
3863
3255
|
const saved_bindings = transform_context.available_bindings;
|
|
3864
3256
|
transform_context.available_bindings = new Map(saved_bindings);
|
|
3865
3257
|
|
|
3866
|
-
const helper_fn =
|
|
3867
|
-
|
|
3868
|
-
id: clone_identifier(component_id),
|
|
3258
|
+
const helper_fn = b.function(
|
|
3259
|
+
clone_identifier(component_id),
|
|
3869
3260
|
params,
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
},
|
|
3875
|
-
async: false,
|
|
3876
|
-
generator: false,
|
|
3877
|
-
metadata: {
|
|
3878
|
-
path: [],
|
|
3879
|
-
is_component: true,
|
|
3880
|
-
is_method: false,
|
|
3881
|
-
},
|
|
3882
|
-
});
|
|
3261
|
+
b.block(build_render_statements(body_nodes, true, transform_context)),
|
|
3262
|
+
);
|
|
3263
|
+
helper_fn.metadata.is_component = true;
|
|
3264
|
+
helper_fn.metadata.is_method = false;
|
|
3883
3265
|
|
|
3884
3266
|
transform_context.available_bindings = saved_bindings;
|
|
3885
3267
|
|
|
@@ -3945,7 +3327,7 @@ function create_hook_safe_helper(
|
|
|
3945
3327
|
|
|
3946
3328
|
/**
|
|
3947
3329
|
* @param {AST.Identifier} helper_id
|
|
3948
|
-
* @param {
|
|
3330
|
+
* @param {AST.FunctionExpression} helper_fn
|
|
3949
3331
|
* @param {any} source_node
|
|
3950
3332
|
* @param {TransformContext} transform_context
|
|
3951
3333
|
* @returns {any}
|
|
@@ -3958,7 +3340,7 @@ function create_helper_declaration(helper_id, helper_fn, source_node, transform_
|
|
|
3958
3340
|
|
|
3959
3341
|
/**
|
|
3960
3342
|
* @param {AST.Identifier} helper_id
|
|
3961
|
-
* @param {
|
|
3343
|
+
* @param {AST.FunctionExpression} helper_fn
|
|
3962
3344
|
* @param {any} source_node
|
|
3963
3345
|
* @param {TransformContext} transform_context
|
|
3964
3346
|
* @returns {any}
|
|
@@ -3987,32 +3369,7 @@ function create_helper_init_expression(helper_id, helper_fn, source_node, transf
|
|
|
3987
3369
|
* @returns {any}
|
|
3988
3370
|
*/
|
|
3989
3371
|
function create_hook_safe_helper_iife(setup_statements, component_element) {
|
|
3990
|
-
return
|
|
3991
|
-
type: 'CallExpression',
|
|
3992
|
-
callee: {
|
|
3993
|
-
type: 'ArrowFunctionExpression',
|
|
3994
|
-
params: [],
|
|
3995
|
-
body: /** @type {any} */ ({
|
|
3996
|
-
type: 'BlockStatement',
|
|
3997
|
-
body: [
|
|
3998
|
-
...setup_statements,
|
|
3999
|
-
{
|
|
4000
|
-
type: 'ReturnStatement',
|
|
4001
|
-
argument: component_element,
|
|
4002
|
-
metadata: { path: [] },
|
|
4003
|
-
},
|
|
4004
|
-
],
|
|
4005
|
-
metadata: { path: [] },
|
|
4006
|
-
}),
|
|
4007
|
-
async: false,
|
|
4008
|
-
generator: false,
|
|
4009
|
-
expression: false,
|
|
4010
|
-
metadata: { path: [] },
|
|
4011
|
-
},
|
|
4012
|
-
arguments: [],
|
|
4013
|
-
optional: false,
|
|
4014
|
-
metadata: { path: [] },
|
|
4015
|
-
});
|
|
3372
|
+
return b.call(b.arrow([], b.block([...setup_statements, b.return(component_element)])));
|
|
4016
3373
|
}
|
|
4017
3374
|
|
|
4018
3375
|
/**
|
|
@@ -4025,19 +3382,7 @@ function create_helper_type_alias_declaration(helper_id, binding) {
|
|
|
4025
3382
|
|
|
4026
3383
|
return {
|
|
4027
3384
|
id: alias_id,
|
|
4028
|
-
declaration:
|
|
4029
|
-
type: 'VariableDeclaration',
|
|
4030
|
-
kind: 'const',
|
|
4031
|
-
declarations: [
|
|
4032
|
-
{
|
|
4033
|
-
type: 'VariableDeclarator',
|
|
4034
|
-
id: clone_identifier(alias_id),
|
|
4035
|
-
init: create_generated_identifier(binding.name),
|
|
4036
|
-
metadata: { path: [] },
|
|
4037
|
-
},
|
|
4038
|
-
],
|
|
4039
|
-
metadata: { path: [] },
|
|
4040
|
-
}),
|
|
3385
|
+
declaration: b.const(clone_identifier(alias_id), create_generated_identifier(binding.name)),
|
|
4041
3386
|
};
|
|
4042
3387
|
}
|
|
4043
3388
|
|
|
@@ -4047,33 +3392,14 @@ function create_helper_type_alias_declaration(helper_id, binding) {
|
|
|
4047
3392
|
* @returns {any}
|
|
4048
3393
|
*/
|
|
4049
3394
|
function create_helper_props_type_literal(bindings, aliases) {
|
|
4050
|
-
return
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
key: create_generated_identifier(binding.name),
|
|
4057
|
-
computed: false,
|
|
4058
|
-
optional: false,
|
|
4059
|
-
readonly: false,
|
|
4060
|
-
static: false,
|
|
4061
|
-
kind: 'init',
|
|
4062
|
-
typeAnnotation: {
|
|
4063
|
-
type: 'TSTypeAnnotation',
|
|
4064
|
-
typeAnnotation: {
|
|
4065
|
-
type: 'TSTypeQuery',
|
|
4066
|
-
exprName: clone_identifier(aliases[i].id),
|
|
4067
|
-
typeArguments: null,
|
|
4068
|
-
metadata: { path: [] },
|
|
4069
|
-
},
|
|
4070
|
-
metadata: { path: [] },
|
|
4071
|
-
},
|
|
4072
|
-
metadata: { path: [] },
|
|
4073
|
-
}),
|
|
3395
|
+
return b.ts_type_literal(
|
|
3396
|
+
bindings.map((binding, i) =>
|
|
3397
|
+
b.ts_property_signature(
|
|
3398
|
+
create_generated_identifier(binding.name),
|
|
3399
|
+
b.ts_type_annotation(b.ts_type_query(clone_identifier(aliases[i].id))),
|
|
3400
|
+
),
|
|
4074
3401
|
),
|
|
4075
|
-
|
|
4076
|
-
});
|
|
3402
|
+
);
|
|
4077
3403
|
}
|
|
4078
3404
|
|
|
4079
3405
|
/**
|
|
@@ -4083,11 +3409,7 @@ function create_helper_props_type_literal(bindings, aliases) {
|
|
|
4083
3409
|
*/
|
|
4084
3410
|
function create_typed_helper_props_pattern(bindings, props_type) {
|
|
4085
3411
|
const pattern = create_helper_props_pattern(bindings);
|
|
4086
|
-
/** @type {any} */ (pattern).typeAnnotation =
|
|
4087
|
-
type: 'TSTypeAnnotation',
|
|
4088
|
-
typeAnnotation: props_type,
|
|
4089
|
-
metadata: { path: [] },
|
|
4090
|
-
};
|
|
3412
|
+
/** @type {any} */ (pattern).typeAnnotation = b.ts_type_annotation(props_type);
|
|
4091
3413
|
return pattern;
|
|
4092
3414
|
}
|
|
4093
3415
|
|
|
@@ -4096,19 +3418,7 @@ function create_typed_helper_props_pattern(bindings, props_type) {
|
|
|
4096
3418
|
* @returns {any}
|
|
4097
3419
|
*/
|
|
4098
3420
|
function create_helper_cache_declaration(cache_id) {
|
|
4099
|
-
return
|
|
4100
|
-
type: 'VariableDeclaration',
|
|
4101
|
-
kind: 'let',
|
|
4102
|
-
declarations: [
|
|
4103
|
-
{
|
|
4104
|
-
type: 'VariableDeclarator',
|
|
4105
|
-
id: clone_identifier(cache_id),
|
|
4106
|
-
init: null,
|
|
4107
|
-
metadata: { path: [] },
|
|
4108
|
-
},
|
|
4109
|
-
],
|
|
4110
|
-
metadata: { path: [] },
|
|
4111
|
-
});
|
|
3421
|
+
return b.let(clone_identifier(cache_id));
|
|
4112
3422
|
}
|
|
4113
3423
|
|
|
4114
3424
|
/**
|
|
@@ -4118,44 +3428,27 @@ function create_helper_cache_declaration(cache_id) {
|
|
|
4118
3428
|
* @returns {any}
|
|
4119
3429
|
*/
|
|
4120
3430
|
function create_cached_helper_declaration(helper_id, cache_id, helper_init) {
|
|
4121
|
-
return
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
type: 'LogicalExpression',
|
|
4130
|
-
operator: '??',
|
|
4131
|
-
left: clone_identifier(cache_id),
|
|
4132
|
-
right: {
|
|
4133
|
-
type: 'AssignmentExpression',
|
|
4134
|
-
operator: '=',
|
|
4135
|
-
left: clone_identifier(cache_id),
|
|
4136
|
-
right: helper_init,
|
|
4137
|
-
metadata: { path: [] },
|
|
4138
|
-
},
|
|
4139
|
-
metadata: { path: [] },
|
|
4140
|
-
},
|
|
4141
|
-
metadata: { path: [] },
|
|
4142
|
-
},
|
|
4143
|
-
],
|
|
4144
|
-
metadata: { path: [] },
|
|
4145
|
-
});
|
|
3431
|
+
return b.const(
|
|
3432
|
+
clone_identifier(helper_id),
|
|
3433
|
+
b.logical(
|
|
3434
|
+
'??',
|
|
3435
|
+
clone_identifier(cache_id),
|
|
3436
|
+
b.assignment('=', clone_identifier(cache_id), helper_init),
|
|
3437
|
+
),
|
|
3438
|
+
);
|
|
4146
3439
|
}
|
|
4147
3440
|
|
|
4148
3441
|
/**
|
|
4149
3442
|
* @param {AST.Identifier} helper_id
|
|
4150
|
-
* @param {
|
|
3443
|
+
* @param {AST.FunctionExpression} helper_fn
|
|
4151
3444
|
* @returns {AST.FunctionDeclaration}
|
|
4152
3445
|
*/
|
|
4153
3446
|
function create_helper_function_declaration_from_expression(helper_id, helper_fn) {
|
|
4154
|
-
return
|
|
3447
|
+
return {
|
|
4155
3448
|
...helper_fn,
|
|
4156
3449
|
type: 'FunctionDeclaration',
|
|
4157
3450
|
id: clone_identifier(helper_id),
|
|
4158
|
-
}
|
|
3451
|
+
};
|
|
4159
3452
|
}
|
|
4160
3453
|
|
|
4161
3454
|
/**
|
|
@@ -4540,25 +3833,7 @@ function if_statement_to_jsx_child(node, transform_context) {
|
|
|
4540
3833
|
}
|
|
4541
3834
|
|
|
4542
3835
|
return to_jsx_expression_container(
|
|
4543
|
-
|
|
4544
|
-
type: 'CallExpression',
|
|
4545
|
-
callee: {
|
|
4546
|
-
type: 'ArrowFunctionExpression',
|
|
4547
|
-
params: [],
|
|
4548
|
-
body: /** @type {any} */ ({
|
|
4549
|
-
type: 'BlockStatement',
|
|
4550
|
-
body: [render_if_statement, create_null_return_statement()],
|
|
4551
|
-
metadata: { path: [] },
|
|
4552
|
-
}),
|
|
4553
|
-
async: false,
|
|
4554
|
-
generator: false,
|
|
4555
|
-
expression: false,
|
|
4556
|
-
metadata: { path: [] },
|
|
4557
|
-
},
|
|
4558
|
-
arguments: [],
|
|
4559
|
-
optional: false,
|
|
4560
|
-
metadata: { path: [] },
|
|
4561
|
-
}),
|
|
3836
|
+
b.call(b.arrow([], b.block([render_if_statement, create_null_return_statement()]))),
|
|
4562
3837
|
);
|
|
4563
3838
|
}
|
|
4564
3839
|
|
|
@@ -4583,16 +3858,7 @@ function render_if_statement_to_conditional_expression(node) {
|
|
|
4583
3858
|
}
|
|
4584
3859
|
}
|
|
4585
3860
|
|
|
4586
|
-
return set_loc(
|
|
4587
|
-
/** @type {any} */ ({
|
|
4588
|
-
type: 'ConditionalExpression',
|
|
4589
|
-
test: node.test,
|
|
4590
|
-
consequent,
|
|
4591
|
-
alternate,
|
|
4592
|
-
metadata: { path: [] },
|
|
4593
|
-
}),
|
|
4594
|
-
node,
|
|
4595
|
-
);
|
|
3861
|
+
return set_loc(b.conditional(node.test, consequent, alternate), node);
|
|
4596
3862
|
}
|
|
4597
3863
|
|
|
4598
3864
|
/**
|
|
@@ -4660,17 +3926,10 @@ function find_key_expression_in_body(body_nodes) {
|
|
|
4660
3926
|
|
|
4661
3927
|
/**
|
|
4662
3928
|
* @param {any} source_node
|
|
4663
|
-
* @returns {any}
|
|
4664
|
-
*/
|
|
4665
|
-
function continue_to_bare_return(source_node) {
|
|
4666
|
-
return set_loc(
|
|
4667
|
-
/** @type {any} */ ({
|
|
4668
|
-
type: 'ReturnStatement',
|
|
4669
|
-
argument: null,
|
|
4670
|
-
metadata: { path: [] },
|
|
4671
|
-
}),
|
|
4672
|
-
source_node,
|
|
4673
|
-
);
|
|
3929
|
+
* @returns {any}
|
|
3930
|
+
*/
|
|
3931
|
+
function continue_to_bare_return(source_node) {
|
|
3932
|
+
return set_loc(b.return(null), source_node);
|
|
4674
3933
|
}
|
|
4675
3934
|
|
|
4676
3935
|
/**
|
|
@@ -4796,36 +4055,17 @@ function for_of_statement_to_jsx_child(node, transform_context) {
|
|
|
4796
4055
|
// Restore bindings
|
|
4797
4056
|
transform_context.available_bindings = saved_bindings;
|
|
4798
4057
|
|
|
4058
|
+
const iter_callback = b.arrow(loop_params, b.block(body_statements));
|
|
4059
|
+
|
|
4060
|
+
if (transform_context.platform.imports.forOfIterableHelper) {
|
|
4061
|
+
transform_context.needs_for_of_iterable = true;
|
|
4062
|
+
return to_jsx_expression_container(
|
|
4063
|
+
b.call(b.id(MAP_ITERABLE_INTERNAL_NAME), node.right, iter_callback),
|
|
4064
|
+
);
|
|
4065
|
+
}
|
|
4066
|
+
|
|
4799
4067
|
return to_jsx_expression_container(
|
|
4800
|
-
|
|
4801
|
-
type: 'CallExpression',
|
|
4802
|
-
callee: {
|
|
4803
|
-
type: 'MemberExpression',
|
|
4804
|
-
object: node.right,
|
|
4805
|
-
property: create_generated_identifier('map'),
|
|
4806
|
-
computed: false,
|
|
4807
|
-
optional: false,
|
|
4808
|
-
metadata: { path: [] },
|
|
4809
|
-
},
|
|
4810
|
-
arguments: [
|
|
4811
|
-
{
|
|
4812
|
-
type: 'ArrowFunctionExpression',
|
|
4813
|
-
params: loop_params,
|
|
4814
|
-
body: /** @type {any} */ ({
|
|
4815
|
-
type: 'BlockStatement',
|
|
4816
|
-
body: body_statements,
|
|
4817
|
-
metadata: { path: [] },
|
|
4818
|
-
}),
|
|
4819
|
-
async: false,
|
|
4820
|
-
generator: false,
|
|
4821
|
-
expression: false,
|
|
4822
|
-
metadata: { path: [] },
|
|
4823
|
-
},
|
|
4824
|
-
],
|
|
4825
|
-
async: false,
|
|
4826
|
-
optional: false,
|
|
4827
|
-
metadata: { path: [] },
|
|
4828
|
-
}),
|
|
4068
|
+
b.call(b.member(node.right, create_generated_identifier('map')), iter_callback),
|
|
4829
4069
|
);
|
|
4830
4070
|
}
|
|
4831
4071
|
|
|
@@ -4846,7 +4086,7 @@ function apply_key_to_loop_body(body_nodes, key_expression) {
|
|
|
4846
4086
|
if (!has_key) {
|
|
4847
4087
|
attributes.push({
|
|
4848
4088
|
type: 'Attribute',
|
|
4849
|
-
name:
|
|
4089
|
+
name: b.id('key'),
|
|
4850
4090
|
value: clone_expression_node(key_expression),
|
|
4851
4091
|
shorthand: false,
|
|
4852
4092
|
metadata: { path: [] },
|
|
@@ -4866,15 +4106,10 @@ function apply_key_to_loop_body(body_nodes, key_expression) {
|
|
|
4866
4106
|
|
|
4867
4107
|
if (!has_key) {
|
|
4868
4108
|
attributes.push(
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
clone_expression_node(key_expression),
|
|
4874
|
-
key_expression,
|
|
4875
|
-
),
|
|
4876
|
-
metadata: { path: [] },
|
|
4877
|
-
}),
|
|
4109
|
+
b.jsx_attribute(
|
|
4110
|
+
b.jsx_id('key'),
|
|
4111
|
+
to_jsx_expression_container(clone_expression_node(key_expression), key_expression),
|
|
4112
|
+
),
|
|
4878
4113
|
);
|
|
4879
4114
|
}
|
|
4880
4115
|
return;
|
|
@@ -4969,29 +4204,12 @@ function keyed_fragment_to_jsx_element(fragment, key_expression) {
|
|
|
4969
4204
|
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
4970
4205
|
*/
|
|
4971
4206
|
function switch_statement_to_jsx_child(node, transform_context) {
|
|
4207
|
+
const { setup_statements, switch_statement } = build_switch_with_lift(node, transform_context);
|
|
4208
|
+
|
|
4972
4209
|
return to_jsx_expression_container(
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
type: 'ArrowFunctionExpression',
|
|
4977
|
-
params: [],
|
|
4978
|
-
body: /** @type {any} */ ({
|
|
4979
|
-
type: 'BlockStatement',
|
|
4980
|
-
body: [
|
|
4981
|
-
create_render_switch_statement(node, transform_context),
|
|
4982
|
-
create_null_return_statement(),
|
|
4983
|
-
],
|
|
4984
|
-
metadata: { path: [] },
|
|
4985
|
-
}),
|
|
4986
|
-
async: false,
|
|
4987
|
-
generator: false,
|
|
4988
|
-
expression: false,
|
|
4989
|
-
metadata: { path: [] },
|
|
4990
|
-
},
|
|
4991
|
-
arguments: [],
|
|
4992
|
-
optional: false,
|
|
4993
|
-
metadata: { path: [] },
|
|
4994
|
-
}),
|
|
4210
|
+
b.call(
|
|
4211
|
+
b.arrow([], b.block([...setup_statements, switch_statement, create_null_return_statement()])),
|
|
4212
|
+
),
|
|
4995
4213
|
);
|
|
4996
4214
|
}
|
|
4997
4215
|
|
|
@@ -5131,19 +4349,10 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5131
4349
|
catch_scoped_names,
|
|
5132
4350
|
);
|
|
5133
4351
|
|
|
5134
|
-
const fallback_fn =
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
type: 'BlockStatement',
|
|
5139
|
-
body: build_render_statements(catch_body_nodes, true, transform_context),
|
|
5140
|
-
metadata: { path: [] },
|
|
5141
|
-
}),
|
|
5142
|
-
async: false,
|
|
5143
|
-
generator: false,
|
|
5144
|
-
expression: false,
|
|
5145
|
-
metadata: { path: [] },
|
|
5146
|
-
};
|
|
4352
|
+
const fallback_fn = b.arrow(
|
|
4353
|
+
catch_params,
|
|
4354
|
+
b.block(build_render_statements(catch_body_nodes, true, transform_context)),
|
|
4355
|
+
);
|
|
5147
4356
|
|
|
5148
4357
|
transform_context.available_bindings = saved_catch_bindings;
|
|
5149
4358
|
|
|
@@ -5156,40 +4365,10 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5156
4365
|
|
|
5157
4366
|
if (boundary_content && transform_context.inside_element_child) {
|
|
5158
4367
|
result = to_jsx_expression_container(
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
{
|
|
5164
|
-
type: 'ObjectExpression',
|
|
5165
|
-
properties: [
|
|
5166
|
-
{
|
|
5167
|
-
type: 'Property',
|
|
5168
|
-
key: { type: 'Identifier', name: 'fallback', metadata: { path: [] } },
|
|
5169
|
-
value: fallback_fn,
|
|
5170
|
-
kind: 'init',
|
|
5171
|
-
method: false,
|
|
5172
|
-
shorthand: false,
|
|
5173
|
-
computed: false,
|
|
5174
|
-
metadata: { path: [] },
|
|
5175
|
-
},
|
|
5176
|
-
{
|
|
5177
|
-
type: 'Property',
|
|
5178
|
-
key: { type: 'Identifier', name: 'content', metadata: { path: [] } },
|
|
5179
|
-
value: boundary_content,
|
|
5180
|
-
kind: 'init',
|
|
5181
|
-
method: false,
|
|
5182
|
-
shorthand: false,
|
|
5183
|
-
computed: false,
|
|
5184
|
-
metadata: { path: [] },
|
|
5185
|
-
},
|
|
5186
|
-
],
|
|
5187
|
-
metadata: { path: [] },
|
|
5188
|
-
},
|
|
5189
|
-
],
|
|
5190
|
-
optional: false,
|
|
5191
|
-
metadata: { path: [] },
|
|
5192
|
-
}),
|
|
4368
|
+
b.call(
|
|
4369
|
+
'TsrxErrorBoundary',
|
|
4370
|
+
b.object([b.init('fallback', fallback_fn), b.init('content', boundary_content)]),
|
|
4371
|
+
),
|
|
5193
4372
|
);
|
|
5194
4373
|
|
|
5195
4374
|
return result;
|
|
@@ -5198,21 +4377,12 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5198
4377
|
result = create_jsx_element(
|
|
5199
4378
|
'TsrxErrorBoundary',
|
|
5200
4379
|
[
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
metadata: { path: [] },
|
|
5206
|
-
},
|
|
4380
|
+
b.jsx_attribute(
|
|
4381
|
+
b.jsx_id('fallback'),
|
|
4382
|
+
to_jsx_expression_container(/** @type {any} */ (fallback_fn)),
|
|
4383
|
+
),
|
|
5207
4384
|
...(boundary_content
|
|
5208
|
-
? [
|
|
5209
|
-
{
|
|
5210
|
-
type: 'JSXAttribute',
|
|
5211
|
-
name: { type: 'JSXIdentifier', name: 'content', metadata: { path: [] } },
|
|
5212
|
-
value: to_jsx_expression_container(boundary_content),
|
|
5213
|
-
metadata: { path: [] },
|
|
5214
|
-
},
|
|
5215
|
-
]
|
|
4385
|
+
? [b.jsx_attribute(b.jsx_id('content'), to_jsx_expression_container(boundary_content))]
|
|
5216
4386
|
: []),
|
|
5217
4387
|
],
|
|
5218
4388
|
boundary_content ? [] : [result],
|
|
@@ -5261,73 +4431,29 @@ function inject_try_imports(program, transform_context, platform, suspense_sourc
|
|
|
5261
4431
|
const imports = [];
|
|
5262
4432
|
|
|
5263
4433
|
if (transform_context.needs_fragment && platform.imports.fragment) {
|
|
5264
|
-
|
|
5265
|
-
imports.push({
|
|
5266
|
-
type: 'ImportDeclaration',
|
|
5267
|
-
specifiers: [
|
|
5268
|
-
{
|
|
5269
|
-
type: 'ImportSpecifier',
|
|
5270
|
-
imported: { type: 'Identifier', name: 'Fragment', metadata: { path: [] } },
|
|
5271
|
-
local: { type: 'Identifier', name: 'Fragment', metadata: { path: [] } },
|
|
5272
|
-
metadata: { path: [] },
|
|
5273
|
-
},
|
|
5274
|
-
],
|
|
5275
|
-
source: {
|
|
5276
|
-
type: 'Literal',
|
|
5277
|
-
value: fragment_source,
|
|
5278
|
-
raw: `'${fragment_source}'`,
|
|
5279
|
-
},
|
|
5280
|
-
metadata: { path: [] },
|
|
5281
|
-
});
|
|
4434
|
+
imports.push(b.imports([['Fragment', 'Fragment']], platform.imports.fragment));
|
|
5282
4435
|
}
|
|
5283
4436
|
|
|
5284
4437
|
if (transform_context.needs_suspense) {
|
|
5285
|
-
imports.push(
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
raw: `'${suspense_source}'`,
|
|
5299
|
-
},
|
|
5300
|
-
metadata: { path: [] },
|
|
5301
|
-
});
|
|
4438
|
+
imports.push(b.imports([['Suspense', 'Suspense']], suspense_source));
|
|
4439
|
+
}
|
|
4440
|
+
|
|
4441
|
+
if (transform_context.needs_for_of_iterable && platform.imports.forOfIterableHelper) {
|
|
4442
|
+
const specifiers = [b.import_specifier('map_iterable', MAP_ITERABLE_INTERNAL_NAME)];
|
|
4443
|
+
// The loop-scoped type alias `IterationValue<typeof source>` only
|
|
4444
|
+
// appears in the output when at least one hook-bearing for-of body
|
|
4445
|
+
// was lowered with non-module-scoped helpers (editor tooling sets
|
|
4446
|
+
// this for typeOnly virtual modules).
|
|
4447
|
+
if (transform_context.needs_iteration_value_type) {
|
|
4448
|
+
specifiers.push(b.import_specifier('IterationValue', ITERATION_VALUE_INTERNAL_NAME, 'type'));
|
|
4449
|
+
}
|
|
4450
|
+
imports.push(b.import_declaration(specifiers, platform.imports.forOfIterableHelper));
|
|
5302
4451
|
}
|
|
5303
4452
|
|
|
5304
4453
|
if (transform_context.needs_error_boundary) {
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
specifiers: [
|
|
5309
|
-
{
|
|
5310
|
-
type: 'ImportSpecifier',
|
|
5311
|
-
imported: {
|
|
5312
|
-
type: 'Identifier',
|
|
5313
|
-
name: 'TsrxErrorBoundary',
|
|
5314
|
-
metadata: { path: [] },
|
|
5315
|
-
},
|
|
5316
|
-
local: {
|
|
5317
|
-
type: 'Identifier',
|
|
5318
|
-
name: 'TsrxErrorBoundary',
|
|
5319
|
-
metadata: { path: [] },
|
|
5320
|
-
},
|
|
5321
|
-
metadata: { path: [] },
|
|
5322
|
-
},
|
|
5323
|
-
],
|
|
5324
|
-
source: {
|
|
5325
|
-
type: 'Literal',
|
|
5326
|
-
value: error_boundary_source,
|
|
5327
|
-
raw: `'${error_boundary_source}'`,
|
|
5328
|
-
},
|
|
5329
|
-
metadata: { path: [] },
|
|
5330
|
-
});
|
|
4454
|
+
imports.push(
|
|
4455
|
+
b.imports([['TsrxErrorBoundary', 'TsrxErrorBoundary']], platform.imports.errorBoundary),
|
|
4456
|
+
);
|
|
5331
4457
|
}
|
|
5332
4458
|
|
|
5333
4459
|
const merge_refs_source =
|
|
@@ -5345,67 +4471,31 @@ function inject_try_imports(program, transform_context, platform, suspense_sourc
|
|
|
5345
4471
|
const ref_imports = new Map();
|
|
5346
4472
|
|
|
5347
4473
|
if (merge_refs_source !== null) {
|
|
5348
|
-
add_ref_import_specifier(
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
metadata: { path: [] },
|
|
5354
|
-
},
|
|
5355
|
-
local: {
|
|
5356
|
-
type: 'Identifier',
|
|
5357
|
-
name: MERGE_REFS_INTERNAL_NAME,
|
|
5358
|
-
metadata: { path: [] },
|
|
5359
|
-
},
|
|
5360
|
-
metadata: { path: [] },
|
|
5361
|
-
});
|
|
4474
|
+
add_ref_import_specifier(
|
|
4475
|
+
ref_imports,
|
|
4476
|
+
merge_refs_source,
|
|
4477
|
+
b.import_specifier('mergeRefs', MERGE_REFS_INTERNAL_NAME),
|
|
4478
|
+
);
|
|
5362
4479
|
}
|
|
5363
4480
|
|
|
5364
4481
|
if (ref_prop_source !== null) {
|
|
5365
|
-
add_ref_import_specifier(
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
metadata: { path: [] },
|
|
5371
|
-
},
|
|
5372
|
-
local: {
|
|
5373
|
-
type: 'Identifier',
|
|
5374
|
-
name: CREATE_REF_PROP_INTERNAL_NAME,
|
|
5375
|
-
metadata: { path: [] },
|
|
5376
|
-
},
|
|
5377
|
-
metadata: { path: [] },
|
|
5378
|
-
});
|
|
4482
|
+
add_ref_import_specifier(
|
|
4483
|
+
ref_imports,
|
|
4484
|
+
ref_prop_source,
|
|
4485
|
+
b.import_specifier('create_ref_prop', CREATE_REF_PROP_INTERNAL_NAME),
|
|
4486
|
+
);
|
|
5379
4487
|
}
|
|
5380
4488
|
|
|
5381
4489
|
if (normalize_spread_props_source !== null) {
|
|
5382
|
-
add_ref_import_specifier(
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
metadata: { path: [] },
|
|
5388
|
-
},
|
|
5389
|
-
local: {
|
|
5390
|
-
type: 'Identifier',
|
|
5391
|
-
name: NORMALIZE_SPREAD_PROPS_INTERNAL_NAME,
|
|
5392
|
-
metadata: { path: [] },
|
|
5393
|
-
},
|
|
5394
|
-
metadata: { path: [] },
|
|
5395
|
-
});
|
|
4490
|
+
add_ref_import_specifier(
|
|
4491
|
+
ref_imports,
|
|
4492
|
+
normalize_spread_props_source,
|
|
4493
|
+
b.import_specifier('normalize_spread_props', NORMALIZE_SPREAD_PROPS_INTERNAL_NAME),
|
|
4494
|
+
);
|
|
5396
4495
|
}
|
|
5397
4496
|
|
|
5398
4497
|
for (const [source, ref_specifiers] of ref_imports) {
|
|
5399
|
-
imports.push(
|
|
5400
|
-
type: 'ImportDeclaration',
|
|
5401
|
-
specifiers: ref_specifiers,
|
|
5402
|
-
source: {
|
|
5403
|
-
type: 'Literal',
|
|
5404
|
-
value: source,
|
|
5405
|
-
raw: `'${source}'`,
|
|
5406
|
-
},
|
|
5407
|
-
metadata: { path: [] },
|
|
5408
|
-
});
|
|
4498
|
+
imports.push(b.import_declaration(ref_specifiers, source));
|
|
5409
4499
|
}
|
|
5410
4500
|
|
|
5411
4501
|
if (imports.length > 0) {
|
|
@@ -5453,130 +4543,343 @@ function create_render_if_statement(node, transform_context) {
|
|
|
5453
4543
|
true,
|
|
5454
4544
|
);
|
|
5455
4545
|
alternate = set_loc(
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
body: alternate_has_hooks
|
|
4546
|
+
b.block(
|
|
4547
|
+
alternate_has_hooks
|
|
5459
4548
|
? hook_safe_render_statements(alternate_body, undefined, transform_context)
|
|
5460
4549
|
: build_render_statements(alternate_body, true, transform_context),
|
|
5461
|
-
|
|
5462
|
-
}),
|
|
4550
|
+
),
|
|
5463
4551
|
node.alternate,
|
|
5464
4552
|
);
|
|
5465
4553
|
}
|
|
5466
4554
|
}
|
|
5467
4555
|
|
|
5468
4556
|
return set_loc(
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
type: 'BlockStatement',
|
|
5475
|
-
body: consequent_has_hooks
|
|
4557
|
+
b.if(
|
|
4558
|
+
node.test,
|
|
4559
|
+
set_loc(
|
|
4560
|
+
b.block(
|
|
4561
|
+
consequent_has_hooks
|
|
5476
4562
|
? hook_safe_render_statements(consequent_body, undefined, transform_context)
|
|
5477
4563
|
: build_render_statements(consequent_body, true, transform_context),
|
|
5478
|
-
|
|
5479
|
-
}),
|
|
4564
|
+
),
|
|
5480
4565
|
node.consequent,
|
|
5481
4566
|
),
|
|
5482
4567
|
alternate,
|
|
5483
|
-
|
|
4568
|
+
),
|
|
5484
4569
|
node,
|
|
5485
4570
|
);
|
|
5486
4571
|
}
|
|
5487
4572
|
|
|
5488
4573
|
/**
|
|
5489
|
-
*
|
|
5490
|
-
*
|
|
5491
|
-
*
|
|
4574
|
+
* Per-source-case information used by the switch lift to decide whether each
|
|
4575
|
+
* case body needs to be hoisted into its own helper component or can stay
|
|
4576
|
+
* inline.
|
|
4577
|
+
*
|
|
4578
|
+
* `own_body` is everything in the case's `consequent` up to (and including for
|
|
4579
|
+
* `return <expr>`, excluding for `break` / bare `return;`) the first
|
|
4580
|
+
* terminator. `has_terminator` records whether such a terminator was seen.
|
|
4581
|
+
*
|
|
4582
|
+
* @param {any[]} consequent
|
|
4583
|
+
* @returns {{ own_body: any[], has_terminator: boolean }}
|
|
5492
4584
|
*/
|
|
5493
|
-
function
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
4585
|
+
function summarize_switch_case_body(consequent) {
|
|
4586
|
+
const own_body = [];
|
|
4587
|
+
let has_terminator = false;
|
|
4588
|
+
for (const child of consequent) {
|
|
4589
|
+
if (child.type === 'BreakStatement') {
|
|
4590
|
+
has_terminator = true;
|
|
4591
|
+
break;
|
|
4592
|
+
}
|
|
4593
|
+
if (child.type === 'ReturnStatement' && child.argument == null) {
|
|
4594
|
+
has_terminator = true;
|
|
4595
|
+
break;
|
|
4596
|
+
}
|
|
4597
|
+
own_body.push(child);
|
|
4598
|
+
if (child.type === 'ReturnStatement') {
|
|
4599
|
+
// `return <expr>;` — keep it in own_body so build_render_statements
|
|
4600
|
+
// can emit it as the terminal return for this case, then stop
|
|
4601
|
+
// collecting further nodes.
|
|
4602
|
+
has_terminator = true;
|
|
4603
|
+
break;
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
return { own_body, has_terminator };
|
|
5502
4607
|
}
|
|
5503
4608
|
|
|
5504
4609
|
/**
|
|
5505
|
-
*
|
|
5506
|
-
*
|
|
4610
|
+
* Clone a helper's `component_element` for embedding in another case arm or
|
|
4611
|
+
* inside another helper's body. Locations are stripped because the same
|
|
4612
|
+
* element appears in multiple positions; only the helper's *definition* (the
|
|
4613
|
+
* lifted function) keeps the source position so editor IntelliSense doesn't
|
|
4614
|
+
* see double/triple hits per source range.
|
|
4615
|
+
*
|
|
4616
|
+
* @param {{ component_element: ESTreeJSX.JSXElement }} helper
|
|
5507
4617
|
* @returns {any}
|
|
5508
4618
|
*/
|
|
5509
|
-
function
|
|
5510
|
-
|
|
4619
|
+
export function clone_switch_helper_invocation(helper) {
|
|
4620
|
+
return clone_expression_node(helper.component_element, false);
|
|
4621
|
+
}
|
|
5511
4622
|
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
4623
|
+
/**
|
|
4624
|
+
* Plan the switch lift: decide which case bodies to hoist into their own
|
|
4625
|
+
* helper components, build them in reverse so each helper can chain into the
|
|
4626
|
+
* next, and return everything callers need to construct a target-specific
|
|
4627
|
+
* switch shape (a JS `switch` for React/Preact/Vue or `<Switch>/<Match>` for
|
|
4628
|
+
* Solid). Centralizes the lift bookkeeping so both consumers see the same
|
|
4629
|
+
* hook-detection rules, duplication analysis, and helper-id numbering.
|
|
4630
|
+
*
|
|
4631
|
+
* Returned helpers — when non-null — are already constructed via
|
|
4632
|
+
* `create_hook_safe_helper`, which is the same path hook-bearing case bodies
|
|
4633
|
+
* have always used. Locally-scoped helpers have their declarations in
|
|
4634
|
+
* `setup_statements`; module-scoped helpers (the client transform default on
|
|
4635
|
+
* React, Vue, and Solid) already pushed their declarations into
|
|
4636
|
+
* `transform_context.helper_state.helpers`, so `setup_statements` is empty.
|
|
4637
|
+
*
|
|
4638
|
+
* @param {any} switch_node
|
|
4639
|
+
* @param {TransformContext} transform_context
|
|
4640
|
+
* @returns {{
|
|
4641
|
+
* case_info: Array<{ own_body: any[], has_terminator: boolean }>,
|
|
4642
|
+
* case_helpers: Array<{ setup_statements: any[], component_element: ESTreeJSX.JSXElement } | null>,
|
|
4643
|
+
* find_next_helper_after: (from_index: number) => { component_element: ESTreeJSX.JSXElement } | null,
|
|
4644
|
+
* setup_statements: any[],
|
|
4645
|
+
* }}
|
|
4646
|
+
*/
|
|
4647
|
+
export function plan_switch_lift(switch_node, transform_context) {
|
|
4648
|
+
const case_info = switch_node.cases.map((/** @type {any} */ c) => {
|
|
4649
|
+
const consequent = flatten_switch_consequent(c.consequent || []);
|
|
4650
|
+
return summarize_switch_case_body(consequent);
|
|
4651
|
+
});
|
|
5518
4652
|
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
})
|
|
5526
|
-
|
|
4653
|
+
// A case body needs to be lifted iff (a) it would render in more than one
|
|
4654
|
+
// arm after fall-through expansion, or (b) it contains hooks (which always
|
|
4655
|
+
// went through the lift pipeline before this change). Duplication happens
|
|
4656
|
+
// exactly when the previous case has no terminator — that's the only way
|
|
4657
|
+
// an earlier arm can reach this body via JS fall-through semantics.
|
|
4658
|
+
const needs_helper = case_info.map(
|
|
4659
|
+
(/** @type {{ own_body: any[], has_terminator: boolean }} */ info, /** @type {number} */ k) => {
|
|
4660
|
+
if (info.own_body.length === 0) return false;
|
|
4661
|
+
if (body_contains_top_level_hook_call(info.own_body, transform_context, true)) {
|
|
4662
|
+
return true;
|
|
4663
|
+
}
|
|
4664
|
+
if (k === 0) return false;
|
|
4665
|
+
return !case_info[k - 1].has_terminator;
|
|
4666
|
+
},
|
|
4667
|
+
);
|
|
5527
4668
|
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
4669
|
+
// Pre-allocate helper ids in source order so the snapshot's
|
|
4670
|
+
// `StatementBodyHook<N>` numbering reads top-to-bottom by case position
|
|
4671
|
+
// even though we build helpers in reverse below.
|
|
4672
|
+
/** @type {Array<AST.Identifier | null>} */
|
|
4673
|
+
const helper_ids = needs_helper.map((/** @type {boolean} */ needs) =>
|
|
4674
|
+
needs
|
|
4675
|
+
? create_generated_identifier(create_local_statement_component_name(transform_context))
|
|
4676
|
+
: null,
|
|
4677
|
+
);
|
|
5531
4678
|
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
if (render_nodes.length > 0 && !has_terminal) {
|
|
5535
|
-
case_body.push(create_component_return_statement(render_nodes, switch_case));
|
|
5536
|
-
} else if (!has_terminal) {
|
|
5537
|
-
case_body.push(child);
|
|
5538
|
-
}
|
|
5539
|
-
has_terminal = true;
|
|
5540
|
-
break;
|
|
5541
|
-
}
|
|
4679
|
+
/** @type {Array<{ setup_statements: any[], component_element: ESTreeJSX.JSXElement } | null>} */
|
|
4680
|
+
const case_helpers = new Array(switch_node.cases.length).fill(null);
|
|
5542
4681
|
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
4682
|
+
/**
|
|
4683
|
+
* Find the next downstream helper this arm chains into when it has no
|
|
4684
|
+
* terminator: scan forward past any empty cases until we hit either a
|
|
4685
|
+
* helper-bearing case or a case whose body has a terminator (which stops
|
|
4686
|
+
* the chain — JS would have `break`/`return`ed out at that point).
|
|
4687
|
+
*
|
|
4688
|
+
* @param {number} from_index
|
|
4689
|
+
* @returns {{ component_element: ESTreeJSX.JSXElement } | null}
|
|
4690
|
+
*/
|
|
4691
|
+
function find_next_helper_after(from_index) {
|
|
4692
|
+
for (let j = from_index + 1; j < switch_node.cases.length; j++) {
|
|
4693
|
+
if (case_helpers[j]) return case_helpers[j];
|
|
4694
|
+
if (case_info[j].has_terminator) return null;
|
|
5547
4695
|
}
|
|
4696
|
+
return null;
|
|
4697
|
+
}
|
|
5548
4698
|
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
4699
|
+
for (let i = switch_node.cases.length - 1; i >= 0; i--) {
|
|
4700
|
+
if (!needs_helper[i]) continue;
|
|
4701
|
+
const { own_body, has_terminator } = case_info[i];
|
|
4702
|
+
|
|
4703
|
+
let helper_body = own_body;
|
|
4704
|
+
if (!has_terminator) {
|
|
4705
|
+
const next_helper = find_next_helper_after(i);
|
|
4706
|
+
if (next_helper) {
|
|
4707
|
+
helper_body = [...own_body, clone_switch_helper_invocation(next_helper)];
|
|
4708
|
+
}
|
|
5555
4709
|
}
|
|
4710
|
+
|
|
4711
|
+
case_helpers[i] = create_hook_safe_helper(
|
|
4712
|
+
helper_body,
|
|
4713
|
+
undefined,
|
|
4714
|
+
switch_node.cases[i],
|
|
4715
|
+
transform_context,
|
|
4716
|
+
/** @type {any} */ (helper_ids[i]),
|
|
4717
|
+
);
|
|
5556
4718
|
}
|
|
5557
4719
|
|
|
5558
|
-
|
|
5559
|
-
|
|
4720
|
+
// Hoist all helpers' setup statements above the switch in source order so
|
|
4721
|
+
// the switch body stays a pure dispatcher.
|
|
4722
|
+
const setup_statements = [];
|
|
4723
|
+
for (const helper of case_helpers) {
|
|
4724
|
+
if (helper) setup_statements.push(...helper.setup_statements);
|
|
5560
4725
|
}
|
|
5561
4726
|
|
|
5562
|
-
return
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
}
|
|
4727
|
+
return {
|
|
4728
|
+
case_info,
|
|
4729
|
+
case_helpers,
|
|
4730
|
+
find_next_helper_after,
|
|
4731
|
+
setup_statements,
|
|
4732
|
+
};
|
|
5568
4733
|
}
|
|
5569
4734
|
|
|
5570
4735
|
/**
|
|
5571
|
-
*
|
|
4736
|
+
* Switch lift for fall-through deduplication. Reuses the same `create_hook_safe_helper`
|
|
4737
|
+
* pipeline as hook-bearing case bodies: every case whose body would otherwise
|
|
4738
|
+
* appear in 2+ arms (because the previous case had no `break` / `return`) is
|
|
4739
|
+
* hoisted into its own helper component, and each upstream arm references the
|
|
4740
|
+
* next helper at the end of its own body to materialize JS fall-through at
|
|
4741
|
+
* render time. Cases whose bodies live in exactly one arm stay inline so the
|
|
4742
|
+
* common (break-terminated) shape compiles to the same simple switch as before
|
|
4743
|
+
* the lift was introduced.
|
|
4744
|
+
*
|
|
4745
|
+
* The chain pattern:
|
|
4746
|
+
* helper_idle = () => <><Online/><Helper_active/></>
|
|
4747
|
+
* helper_active = () => <><Away/><Helper_offline/></>
|
|
4748
|
+
* helper_offline = () => <Offline/>
|
|
4749
|
+
*
|
|
4750
|
+
* case "idle": return <Helper_idle/>
|
|
4751
|
+
* case "active": return <Helper_active/>
|
|
4752
|
+
* case "offline": return <Helper_offline/>
|
|
4753
|
+
*
|
|
4754
|
+
* Each case body appears exactly once in the generated module — matching how
|
|
4755
|
+
* we already handle hook-bearing case bodies — which keeps the bundle from
|
|
4756
|
+
* growing quadratically in case count and means editor mappings are 1:1.
|
|
4757
|
+
*
|
|
4758
|
+
* @param {any} switch_node
|
|
4759
|
+
* @param {TransformContext} transform_context
|
|
4760
|
+
* @returns {{ setup_statements: any[], switch_statement: any }}
|
|
5572
4761
|
*/
|
|
5573
|
-
function
|
|
4762
|
+
function build_switch_with_lift(switch_node, transform_context) {
|
|
4763
|
+
const { case_info, case_helpers, find_next_helper_after, setup_statements } = plan_switch_lift(
|
|
4764
|
+
switch_node,
|
|
4765
|
+
transform_context,
|
|
4766
|
+
);
|
|
4767
|
+
|
|
4768
|
+
const new_cases = switch_node.cases.map(
|
|
4769
|
+
(/** @type {any} */ original_case, /** @type {number} */ i) => {
|
|
4770
|
+
const helper = case_helpers[i];
|
|
4771
|
+
if (helper) {
|
|
4772
|
+
return /** @type {any} */ ({
|
|
4773
|
+
type: 'SwitchCase',
|
|
4774
|
+
test: original_case.test,
|
|
4775
|
+
consequent: [
|
|
4776
|
+
create_component_return_statement([helper.component_element], original_case),
|
|
4777
|
+
],
|
|
4778
|
+
metadata: { path: [] },
|
|
4779
|
+
});
|
|
4780
|
+
}
|
|
4781
|
+
|
|
4782
|
+
const { own_body, has_terminator } = case_info[i];
|
|
4783
|
+
|
|
4784
|
+
if (own_body.length === 0 && !has_terminator) {
|
|
4785
|
+
// Alias-pattern empty case (`case 'a': case 'b': ...`) — keep
|
|
4786
|
+
// the arm body empty so JS falls through to the next case at
|
|
4787
|
+
// runtime, where the helper invocation actually lives.
|
|
4788
|
+
return /** @type {any} */ ({
|
|
4789
|
+
type: 'SwitchCase',
|
|
4790
|
+
test: original_case.test,
|
|
4791
|
+
consequent: [],
|
|
4792
|
+
metadata: { path: [] },
|
|
4793
|
+
});
|
|
4794
|
+
}
|
|
4795
|
+
|
|
4796
|
+
const case_body = [];
|
|
4797
|
+
const render_nodes = [];
|
|
4798
|
+
let has_terminal = false;
|
|
4799
|
+
|
|
4800
|
+
for (const child of own_body) {
|
|
4801
|
+
if (is_bare_return_statement(child)) {
|
|
4802
|
+
case_body.push(create_component_return_statement(render_nodes, child));
|
|
4803
|
+
has_terminal = true;
|
|
4804
|
+
break;
|
|
4805
|
+
}
|
|
4806
|
+
if (child.type === 'ReturnStatement') {
|
|
4807
|
+
case_body.push(child);
|
|
4808
|
+
has_terminal = true;
|
|
4809
|
+
break;
|
|
4810
|
+
}
|
|
4811
|
+
if (is_jsx_child(child)) {
|
|
4812
|
+
render_nodes.push(to_jsx_child(child, transform_context));
|
|
4813
|
+
} else if (is_bare_render_expression(child)) {
|
|
4814
|
+
render_nodes.push(to_jsx_expression_container(child, child));
|
|
4815
|
+
} else {
|
|
4816
|
+
case_body.push(child);
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4820
|
+
if (!has_terminal && !has_terminator) {
|
|
4821
|
+
const next_helper = find_next_helper_after(i);
|
|
4822
|
+
if (next_helper) {
|
|
4823
|
+
render_nodes.push(clone_switch_helper_invocation(next_helper));
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
|
|
4827
|
+
if (!has_terminal) {
|
|
4828
|
+
if (render_nodes.length > 0) {
|
|
4829
|
+
case_body.push(create_component_return_statement(render_nodes, original_case));
|
|
4830
|
+
} else if (has_terminator) {
|
|
4831
|
+
// Empty body with explicit `break;` / bare `return;` — keep
|
|
4832
|
+
// a `break` so JS doesn't fall through into the next case
|
|
4833
|
+
// (which may now hold the lifted helper invocation).
|
|
4834
|
+
case_body.push(
|
|
4835
|
+
/** @type {any} */ ({
|
|
4836
|
+
type: 'BreakStatement',
|
|
4837
|
+
label: null,
|
|
4838
|
+
metadata: { path: [] },
|
|
4839
|
+
}),
|
|
4840
|
+
);
|
|
4841
|
+
} else if (case_body.length > 0) {
|
|
4842
|
+
// Statements-only inline case without terminator. We've
|
|
4843
|
+
// already inlined the downstream chain via the helper
|
|
4844
|
+
// reference above, so emit a `break` to stop the runtime
|
|
4845
|
+
// from re-running downstream statements via JS fall-through.
|
|
4846
|
+
case_body.push(
|
|
4847
|
+
/** @type {any} */ ({
|
|
4848
|
+
type: 'BreakStatement',
|
|
4849
|
+
label: null,
|
|
4850
|
+
metadata: { path: [] },
|
|
4851
|
+
}),
|
|
4852
|
+
);
|
|
4853
|
+
}
|
|
4854
|
+
}
|
|
4855
|
+
|
|
4856
|
+
return /** @type {any} */ ({
|
|
4857
|
+
type: 'SwitchCase',
|
|
4858
|
+
test: original_case.test,
|
|
4859
|
+
consequent: case_body,
|
|
4860
|
+
metadata: { path: [] },
|
|
4861
|
+
});
|
|
4862
|
+
},
|
|
4863
|
+
);
|
|
4864
|
+
|
|
5574
4865
|
return {
|
|
5575
|
-
|
|
5576
|
-
|
|
4866
|
+
setup_statements,
|
|
4867
|
+
switch_statement: /** @type {any} */ ({
|
|
4868
|
+
type: 'SwitchStatement',
|
|
4869
|
+
discriminant: switch_node.discriminant,
|
|
4870
|
+
cases: new_cases,
|
|
4871
|
+
metadata: { path: [] },
|
|
4872
|
+
}),
|
|
5577
4873
|
};
|
|
5578
4874
|
}
|
|
5579
4875
|
|
|
4876
|
+
/**
|
|
4877
|
+
* @returns {any}
|
|
4878
|
+
*/
|
|
4879
|
+
function create_null_return_statement() {
|
|
4880
|
+
return b.return(b.literal(null));
|
|
4881
|
+
}
|
|
4882
|
+
|
|
5580
4883
|
/**
|
|
5581
4884
|
* @param {AST.Expression} expression
|
|
5582
4885
|
* @param {any} [source_node]
|
|
@@ -5675,10 +4978,7 @@ function normalize_named_ref_attributes(attrs, is_host, transform_context) {
|
|
|
5675
4978
|
return {
|
|
5676
4979
|
...attr,
|
|
5677
4980
|
metadata: { ...(attr.metadata || {}), from_ref_keyword: true },
|
|
5678
|
-
name:
|
|
5679
|
-
attr.name?.type === 'JSXIdentifier'
|
|
5680
|
-
? { ...attr.name, name: 'ref' }
|
|
5681
|
-
: { type: 'Identifier', name: 'ref', metadata: { path: [] } },
|
|
4981
|
+
name: attr.name?.type === 'JSXIdentifier' ? { ...attr.name, name: 'ref' } : b.id('ref'),
|
|
5682
4982
|
};
|
|
5683
4983
|
});
|
|
5684
4984
|
}
|
|
@@ -5819,6 +5119,7 @@ function wrap_jsx_setup_declarations(expression, in_jsx_child) {
|
|
|
5819
5119
|
[],
|
|
5820
5120
|
b.block([...declarations, b.return(return_expression)], expression),
|
|
5821
5121
|
false,
|
|
5122
|
+
undefined,
|
|
5822
5123
|
expression,
|
|
5823
5124
|
),
|
|
5824
5125
|
);
|
|
@@ -5970,22 +5271,8 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
5970
5271
|
|
|
5971
5272
|
const merged_value =
|
|
5972
5273
|
strategy === 'merge-refs'
|
|
5973
|
-
?
|
|
5974
|
-
|
|
5975
|
-
callee: {
|
|
5976
|
-
type: 'Identifier',
|
|
5977
|
-
name: MERGE_REFS_INTERNAL_NAME,
|
|
5978
|
-
metadata: { path: [] },
|
|
5979
|
-
},
|
|
5980
|
-
arguments: ref_exprs,
|
|
5981
|
-
optional: false,
|
|
5982
|
-
metadata: { path: [] },
|
|
5983
|
-
})
|
|
5984
|
-
: /** @type {any} */ ({
|
|
5985
|
-
type: 'ArrayExpression',
|
|
5986
|
-
elements: ref_exprs,
|
|
5987
|
-
metadata: { path: [] },
|
|
5988
|
-
});
|
|
5274
|
+
? b.call(b.id(MERGE_REFS_INTERNAL_NAME), ...ref_exprs)
|
|
5275
|
+
: b.array(ref_exprs);
|
|
5989
5276
|
|
|
5990
5277
|
if (strategy === 'merge-refs') {
|
|
5991
5278
|
transform_context.needs_merge_refs = true;
|
|
@@ -5999,11 +5286,7 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
5999
5286
|
const merged_name = build_jsx_id('ref', source_attr?.name);
|
|
6000
5287
|
const merged_attr = build_jsx_attribute(
|
|
6001
5288
|
merged_name,
|
|
6002
|
-
|
|
6003
|
-
type: 'JSXExpressionContainer',
|
|
6004
|
-
expression: merged_value,
|
|
6005
|
-
metadata: { path: [] },
|
|
6006
|
-
}),
|
|
5289
|
+
b.jsx_expression_container(merged_value),
|
|
6007
5290
|
false,
|
|
6008
5291
|
source_attr,
|
|
6009
5292
|
);
|
|
@@ -6038,6 +5321,8 @@ function is_jsx_ref_attribute(attr) {
|
|
|
6038
5321
|
export const MERGE_REFS_INTERNAL_NAME = '__mergeRefs';
|
|
6039
5322
|
export const CREATE_REF_PROP_INTERNAL_NAME = '__create_ref_prop';
|
|
6040
5323
|
export const NORMALIZE_SPREAD_PROPS_INTERNAL_NAME = '__normalize_spread_props';
|
|
5324
|
+
export const MAP_ITERABLE_INTERNAL_NAME = '__map_iterable';
|
|
5325
|
+
export const ITERATION_VALUE_INTERNAL_NAME = '__IterationValue';
|
|
6041
5326
|
|
|
6042
5327
|
/**
|
|
6043
5328
|
* @param {any} attr
|
|
@@ -6111,10 +5396,7 @@ export function to_jsx_attribute(attr, transform_context) {
|
|
|
6111
5396
|
attr_name.type === 'Identifier' &&
|
|
6112
5397
|
attr_name.name === 'class'
|
|
6113
5398
|
) {
|
|
6114
|
-
attr_name = set_loc(
|
|
6115
|
-
/** @type {any} */ ({ type: 'Identifier', name: 'className', metadata: { path: [] } }),
|
|
6116
|
-
attr.name,
|
|
6117
|
-
);
|
|
5399
|
+
attr_name = set_loc(b.id('className'), attr.name);
|
|
6118
5400
|
}
|
|
6119
5401
|
|
|
6120
5402
|
const name =
|
|
@@ -6177,16 +5459,7 @@ function create_ref_prop_call(node, transform_context) {
|
|
|
6177
5459
|
|
|
6178
5460
|
if (argument.type === 'Identifier' || argument.type === 'MemberExpression') {
|
|
6179
5461
|
args.push(
|
|
6180
|
-
b.arrow(
|
|
6181
|
-
[b.id('v')],
|
|
6182
|
-
/** @type {any} */ ({
|
|
6183
|
-
type: 'AssignmentExpression',
|
|
6184
|
-
operator: '=',
|
|
6185
|
-
left: clone_expression_node(argument, false),
|
|
6186
|
-
right: b.id('v'),
|
|
6187
|
-
metadata: { path: [] },
|
|
6188
|
-
}),
|
|
6189
|
-
),
|
|
5462
|
+
b.arrow([b.id('v')], b.assignment('=', clone_expression_node(argument, false), b.id('v'))),
|
|
6190
5463
|
);
|
|
6191
5464
|
}
|
|
6192
5465
|
|
|
@@ -6200,57 +5473,19 @@ function create_ref_prop_call(node, transform_context) {
|
|
|
6200
5473
|
*/
|
|
6201
5474
|
function dynamic_element_to_jsx_child(node, transform_context) {
|
|
6202
5475
|
const dynamic_id = set_loc(create_generated_identifier('DynamicElement'), node.id);
|
|
6203
|
-
const alias_declaration = set_loc(
|
|
6204
|
-
/** @type {any} */ ({
|
|
6205
|
-
type: 'VariableDeclaration',
|
|
6206
|
-
kind: 'const',
|
|
6207
|
-
declarations: [
|
|
6208
|
-
{
|
|
6209
|
-
type: 'VariableDeclarator',
|
|
6210
|
-
id: dynamic_id,
|
|
6211
|
-
init: clone_expression_node(node.id),
|
|
6212
|
-
metadata: { path: [] },
|
|
6213
|
-
},
|
|
6214
|
-
],
|
|
6215
|
-
metadata: { path: [] },
|
|
6216
|
-
}),
|
|
6217
|
-
node,
|
|
6218
|
-
);
|
|
5476
|
+
const alias_declaration = set_loc(b.const(dynamic_id, clone_expression_node(node.id)), node);
|
|
6219
5477
|
const jsx_element = create_dynamic_jsx_element(dynamic_id, node, transform_context);
|
|
6220
5478
|
|
|
6221
5479
|
return to_jsx_expression_container(
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
{
|
|
6232
|
-
type: 'ReturnStatement',
|
|
6233
|
-
argument: {
|
|
6234
|
-
type: 'ConditionalExpression',
|
|
6235
|
-
test: clone_identifier(dynamic_id),
|
|
6236
|
-
consequent: jsx_element,
|
|
6237
|
-
alternate: create_null_literal(),
|
|
6238
|
-
metadata: { path: [] },
|
|
6239
|
-
},
|
|
6240
|
-
metadata: { path: [] },
|
|
6241
|
-
},
|
|
6242
|
-
],
|
|
6243
|
-
metadata: { path: [] },
|
|
6244
|
-
}),
|
|
6245
|
-
async: false,
|
|
6246
|
-
generator: false,
|
|
6247
|
-
expression: false,
|
|
6248
|
-
metadata: { path: [] },
|
|
6249
|
-
},
|
|
6250
|
-
arguments: [],
|
|
6251
|
-
optional: false,
|
|
6252
|
-
metadata: { path: [] },
|
|
6253
|
-
}),
|
|
5480
|
+
b.call(
|
|
5481
|
+
b.arrow(
|
|
5482
|
+
[],
|
|
5483
|
+
b.block([
|
|
5484
|
+
alias_declaration,
|
|
5485
|
+
b.return(b.conditional(clone_identifier(dynamic_id), jsx_element, create_null_literal())),
|
|
5486
|
+
]),
|
|
5487
|
+
),
|
|
5488
|
+
),
|
|
6254
5489
|
node,
|
|
6255
5490
|
);
|
|
6256
5491
|
}
|