@tsrx/core 0.1.45 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/package.json +1 -1
- package/src/analyze/index.js +177 -0
- package/src/analyze/validation.js +19 -0
- package/src/index.js +12 -2
- package/src/parse/index.js +3 -2
- package/src/plugin.js +3 -104
- package/src/transform/jsx/ast-builders.js +131 -110
- package/src/transform/jsx/helpers.js +76 -81
- package/src/transform/jsx/index.js +346 -390
- package/src/transform/lazy.js +5 -5
- package/src/transform/segments.js +29 -28
- package/src/transform/style-ref.js +10 -27
- package/src/utils/ast.js +101 -1
- package/src/utils/builders.js +3 -3
- package/types/index.d.ts +118 -11
- package/types/jsx-platform.d.ts +88 -54
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import * as AST from 'estree' */
|
|
2
2
|
/** @import * as ESTreeJSX from 'estree-jsx' */
|
|
3
|
-
/** @import { JsxPlatform, JsxTransformContext, JsxTransformOptions, JsxTransformResult } from '@tsrx/core/types' */
|
|
3
|
+
/** @import { JsxHelperComponent, JsxPlatform, JsxTransformContext as TransformContext, JsxTransformOptions, JsxTransformResult } from '@tsrx/core/types' */
|
|
4
4
|
|
|
5
5
|
import { walk } from 'zimmerframe';
|
|
6
6
|
import { print } from 'esrap';
|
|
@@ -20,13 +20,14 @@ import {
|
|
|
20
20
|
} from './helpers.js';
|
|
21
21
|
import {
|
|
22
22
|
add_extra_source_mappings_from_matching_expression,
|
|
23
|
-
|
|
23
|
+
clone_ast_node,
|
|
24
24
|
clone_identifier,
|
|
25
25
|
clone_jsx_name,
|
|
26
26
|
create_generated_identifier,
|
|
27
27
|
create_null_literal,
|
|
28
28
|
flatten_switch_consequent,
|
|
29
29
|
get_for_of_iteration_params,
|
|
30
|
+
identifier_to_jsx_identifier,
|
|
30
31
|
identifier_to_jsx_name,
|
|
31
32
|
is_bare_render_expression,
|
|
32
33
|
is_component_jsx_name,
|
|
@@ -61,6 +62,11 @@ import {
|
|
|
61
62
|
} from '../jsx-interleave.js';
|
|
62
63
|
import { is_hoist_safe_jsx_node } from '../jsx-hoist.js';
|
|
63
64
|
import { lower_server_module_for_types } from './server-module.js';
|
|
65
|
+
import {
|
|
66
|
+
has_location,
|
|
67
|
+
is_function_or_class_node as is_function_or_class_boundary,
|
|
68
|
+
is_template_directive as is_jsx_control_flow_expression,
|
|
69
|
+
} from '../../utils/ast.js';
|
|
64
70
|
|
|
65
71
|
const TEMPLATE_FRAGMENT_ERROR =
|
|
66
72
|
'JSX fragment syntax is not needed in TSRX templates. TSRX renders in immediate mode, so everything is already a fragment. Use `<>...</>` only in expression position.';
|
|
@@ -102,32 +108,6 @@ function report_jsx_fragment_in_tsrx_error(node, transform_context) {
|
|
|
102
108
|
);
|
|
103
109
|
}
|
|
104
110
|
|
|
105
|
-
/**
|
|
106
|
-
* Local alias for the shared `JsxTransformContext`. Kept as a typedef so the
|
|
107
|
-
* rest of this file's `@param {TransformContext}` annotations don't all have
|
|
108
|
-
* to spell out the import.
|
|
109
|
-
*
|
|
110
|
-
* @typedef {JsxTransformContext} TransformContext
|
|
111
|
-
*/
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @typedef {{ source_name: string, read: () => any }} LazyBinding
|
|
115
|
-
*/
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @param {any} node
|
|
119
|
-
* @returns {boolean}
|
|
120
|
-
*/
|
|
121
|
-
function is_function_or_class_boundary(node) {
|
|
122
|
-
return (
|
|
123
|
-
node?.type === 'FunctionDeclaration' ||
|
|
124
|
-
node?.type === 'FunctionExpression' ||
|
|
125
|
-
node?.type === 'ArrowFunctionExpression' ||
|
|
126
|
-
node?.type === 'ClassDeclaration' ||
|
|
127
|
-
node?.type === 'ClassExpression'
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
111
|
/**
|
|
132
112
|
* @param {any} node
|
|
133
113
|
* @param {boolean} [inside_function]
|
|
@@ -264,22 +244,6 @@ function expand_child_code_blocks(node, seen = new Set()) {
|
|
|
264
244
|
return out;
|
|
265
245
|
}
|
|
266
246
|
|
|
267
|
-
/**
|
|
268
|
-
* A `@`-prefixed JSX control-flow expression (`@if`/`@for`/`@switch`/`@try`).
|
|
269
|
-
* These are the only control-flow nodes that can appear in expression position;
|
|
270
|
-
* the plain statement forms (`IfStatement`, `SwitchStatement`, …) never do.
|
|
271
|
-
* @param {any} node
|
|
272
|
-
* @returns {boolean}
|
|
273
|
-
*/
|
|
274
|
-
function is_jsx_control_flow_expression(node) {
|
|
275
|
-
return (
|
|
276
|
-
node?.type === 'JSXIfExpression' ||
|
|
277
|
-
node?.type === 'JSXForExpression' ||
|
|
278
|
-
node?.type === 'JSXSwitchExpression' ||
|
|
279
|
-
node?.type === 'JSXTryExpression'
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
247
|
/**
|
|
284
248
|
* Wrap a render-output node in a native TSRX fragment so it flows through the
|
|
285
249
|
* same single-child render path as a `<> … </>` output. This is a compiler
|
|
@@ -418,7 +382,7 @@ function wrap_lowered_value_in_fragment(expression, source) {
|
|
|
418
382
|
expression?.type === 'JSXExpressionContainer'
|
|
419
383
|
? expression
|
|
420
384
|
: to_jsx_expression_container(expression, source);
|
|
421
|
-
return set_loc(b.jsx_fragment([child]), source
|
|
385
|
+
return set_loc(b.jsx_fragment([child]), has_location(source) ? source : undefined);
|
|
422
386
|
}
|
|
423
387
|
|
|
424
388
|
/**
|
|
@@ -594,7 +558,7 @@ export function createJsxTransform(platform) {
|
|
|
594
558
|
function transform(ast, source, filename, options) {
|
|
595
559
|
const suspense_source = options?.suspenseSource ?? platform.imports.suspense;
|
|
596
560
|
const collect = !!(options?.collect || options?.loose);
|
|
597
|
-
/** @type {
|
|
561
|
+
/** @type {AST.CSS.StyleSheet[]} */
|
|
598
562
|
const stylesheets = [];
|
|
599
563
|
/** @type {AST.Statement[]} */
|
|
600
564
|
const type_only_style_anchors = [];
|
|
@@ -613,6 +577,14 @@ export function createJsxTransform(platform) {
|
|
|
613
577
|
needs_dynamic_factory: false,
|
|
614
578
|
needs_for_of_iterable: false,
|
|
615
579
|
needs_iteration_value_type: false,
|
|
580
|
+
needs_show: false,
|
|
581
|
+
needs_for: false,
|
|
582
|
+
needs_switch: false,
|
|
583
|
+
needs_match: false,
|
|
584
|
+
needs_errored: false,
|
|
585
|
+
needs_loading: false,
|
|
586
|
+
needs_define_vapor_component: false,
|
|
587
|
+
needs_vapor_for: false,
|
|
616
588
|
stylesheets,
|
|
617
589
|
type_only_style_anchors,
|
|
618
590
|
module_scoped_hook_components:
|
|
@@ -907,13 +879,13 @@ function lower_dynamic_jsx_element(node, transform_context) {
|
|
|
907
879
|
|
|
908
880
|
const dynamic_expression = dynamic_name.expression;
|
|
909
881
|
if (!dynamic_expression) return;
|
|
910
|
-
const generated_expression =
|
|
882
|
+
const generated_expression = clone_ast_node(dynamic_expression);
|
|
911
883
|
if (node.closingElement?.name?.expression) {
|
|
912
884
|
// One generated expression stands in for both tags; record the closing
|
|
913
885
|
// tag's positions so editor features keep working on `</{expr}>`.
|
|
914
886
|
add_extra_source_mappings_from_matching_expression(
|
|
915
887
|
generated_expression,
|
|
916
|
-
|
|
888
|
+
clone_ast_node(node.closingElement.name.expression),
|
|
917
889
|
);
|
|
918
890
|
}
|
|
919
891
|
|
|
@@ -1324,11 +1296,7 @@ function build_render_statements(
|
|
|
1324
1296
|
render_nodes.push(
|
|
1325
1297
|
b.jsx_expression_container(
|
|
1326
1298
|
set_loc(
|
|
1327
|
-
b.conditional(
|
|
1328
|
-
clone_expression_node(child.test),
|
|
1329
|
-
b.literal(null),
|
|
1330
|
-
stmt.argument,
|
|
1331
|
-
),
|
|
1299
|
+
b.conditional(clone_ast_node(child.test), b.literal(null), stmt.argument),
|
|
1332
1300
|
child,
|
|
1333
1301
|
),
|
|
1334
1302
|
),
|
|
@@ -1411,7 +1379,7 @@ function build_render_statements(
|
|
|
1411
1379
|
if (return_arg === null) {
|
|
1412
1380
|
return_arg = set_loc(
|
|
1413
1381
|
b.jsx_fragment([]),
|
|
1414
|
-
source_authored_fragment
|
|
1382
|
+
has_location(source_authored_fragment) ? source_authored_fragment : undefined,
|
|
1415
1383
|
);
|
|
1416
1384
|
} else if (return_arg.type !== 'JSXFragment') {
|
|
1417
1385
|
return_arg = wrap_lowered_value_in_fragment(return_arg, source_authored_fragment);
|
|
@@ -1613,7 +1581,7 @@ function create_helper_component_element(helper_id, bindings, source_node, mappi
|
|
|
1613
1581
|
const { mapWrapper = true, mapBindingNames = true, mapBindingValues = true } = mapping;
|
|
1614
1582
|
const attributes = bindings.map((binding) =>
|
|
1615
1583
|
b.jsx_attribute(
|
|
1616
|
-
|
|
1584
|
+
identifier_to_jsx_identifier(
|
|
1617
1585
|
mapBindingNames ? clone_identifier(binding) : create_generated_identifier(binding.name),
|
|
1618
1586
|
),
|
|
1619
1587
|
to_jsx_expression_container(
|
|
@@ -1624,7 +1592,7 @@ function create_helper_component_element(helper_id, bindings, source_node, mappi
|
|
|
1624
1592
|
);
|
|
1625
1593
|
|
|
1626
1594
|
const opening_element = b.jsx_opening_element(
|
|
1627
|
-
|
|
1595
|
+
identifier_to_jsx_identifier(clone_identifier(helper_id)),
|
|
1628
1596
|
attributes,
|
|
1629
1597
|
true,
|
|
1630
1598
|
);
|
|
@@ -2382,7 +2350,7 @@ function create_style_expression_value(node, stylesheet, transform_context) {
|
|
|
2382
2350
|
* @param {TransformContext} transform_context
|
|
2383
2351
|
*/
|
|
2384
2352
|
function add_type_only_style_anchor(node, transform_context) {
|
|
2385
|
-
const style_anchor = b.jsx_element(
|
|
2353
|
+
const style_anchor = b.jsx_element(clone_ast_node(node, true), [], []);
|
|
2386
2354
|
disable_style_anchor_verification(style_anchor);
|
|
2387
2355
|
|
|
2388
2356
|
const anchor_id = create_generated_identifier(create_style_anchor_name(transform_context));
|
|
@@ -2502,7 +2470,7 @@ function annotate_tsrx_with_hash(node, hash, jsx_class_attr_name, preserve_style
|
|
|
2502
2470
|
const annotated = { ...node };
|
|
2503
2471
|
annotated.children = (node.children || []).map((/** @type {any} */ statement) =>
|
|
2504
2472
|
annotate_with_hash(
|
|
2505
|
-
|
|
2473
|
+
clone_ast_node(statement),
|
|
2506
2474
|
hash,
|
|
2507
2475
|
jsx_class_attr_name,
|
|
2508
2476
|
preserve_style_elements,
|
|
@@ -2867,7 +2835,11 @@ function node_contains_hook_bearing_tsrx(node, transform_context) {
|
|
|
2867
2835
|
}
|
|
2868
2836
|
|
|
2869
2837
|
if (is_native_tsrx_node(node)) {
|
|
2870
|
-
return body_contains_top_level_hook_call(
|
|
2838
|
+
return body_contains_top_level_hook_call(
|
|
2839
|
+
'children' in node ? node.children : [],
|
|
2840
|
+
transform_context,
|
|
2841
|
+
true,
|
|
2842
|
+
);
|
|
2871
2843
|
}
|
|
2872
2844
|
|
|
2873
2845
|
if (
|
|
@@ -3270,7 +3242,7 @@ function create_component_return_statement(
|
|
|
3270
3242
|
type_only = false,
|
|
3271
3243
|
) {
|
|
3272
3244
|
const cloned = render_nodes.map((node) =>
|
|
3273
|
-
map_render_node_locations ?
|
|
3245
|
+
map_render_node_locations ? clone_ast_node(node) : clone_ast_node(node, false),
|
|
3274
3246
|
);
|
|
3275
3247
|
|
|
3276
3248
|
return set_loc(
|
|
@@ -3428,7 +3400,7 @@ function prepend_render_nodes_to_return_statement(
|
|
|
3428
3400
|
* @returns {any}
|
|
3429
3401
|
*/
|
|
3430
3402
|
function combine_render_return_argument(render_nodes, return_argument, type_only = false) {
|
|
3431
|
-
const combined = render_nodes.map((node) =>
|
|
3403
|
+
const combined = render_nodes.map((node) => clone_ast_node(node, false));
|
|
3432
3404
|
|
|
3433
3405
|
if (return_argument != null && !is_null_literal(return_argument)) {
|
|
3434
3406
|
combined.push(return_argument_to_render_node(return_argument));
|
|
@@ -3473,7 +3445,7 @@ function is_null_literal(node) {
|
|
|
3473
3445
|
* @returns {{ source_decl: any, source_normalize_decl: any }}
|
|
3474
3446
|
*/
|
|
3475
3447
|
function build_array_normalization_decls(source_id, source_expr) {
|
|
3476
|
-
const source_decl = b.let(clone_identifier(source_id),
|
|
3448
|
+
const source_decl = b.let(clone_identifier(source_id), clone_ast_node(source_expr));
|
|
3477
3449
|
const is_array_call = b.call(b.member(b.id('Array'), 'isArray'), clone_identifier(source_id));
|
|
3478
3450
|
const from_call = b.call(b.member(b.id('Array'), 'from'), clone_identifier(source_id));
|
|
3479
3451
|
const normalized = b.conditional(is_array_call, clone_identifier(source_id), from_call);
|
|
@@ -3519,7 +3491,7 @@ function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
|
3519
3491
|
const use_iterable_helper = !!transform_context.platform.imports.forOfIterableHelper;
|
|
3520
3492
|
const { source_decl, source_normalize_decl } = use_iterable_helper
|
|
3521
3493
|
? {
|
|
3522
|
-
source_decl: b.let(clone_identifier(source_id),
|
|
3494
|
+
source_decl: b.let(clone_identifier(source_id), clone_ast_node(node.right)),
|
|
3523
3495
|
source_normalize_decl: null,
|
|
3524
3496
|
}
|
|
3525
3497
|
: build_array_normalization_decls(source_id, node.right);
|
|
@@ -3621,10 +3593,12 @@ function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
|
3621
3593
|
|
|
3622
3594
|
const body_key_expression = find_key_expression_in_body(original_loop_body);
|
|
3623
3595
|
const explicit_key_expression =
|
|
3624
|
-
body_key_expression ?? (node.key ?
|
|
3596
|
+
body_key_expression ?? (node.key ? clone_ast_node(node.key) : undefined);
|
|
3625
3597
|
const key_expression =
|
|
3626
3598
|
explicit_key_expression ??
|
|
3627
|
-
(loop_params.length >= 2
|
|
3599
|
+
(loop_params.length >= 2
|
|
3600
|
+
? clone_identifier(/** @type {AST.Identifier} */ (loop_params[1]))
|
|
3601
|
+
: undefined);
|
|
3628
3602
|
if (key_expression) {
|
|
3629
3603
|
callback_invocation_element.openingElement.attributes.push(
|
|
3630
3604
|
b.jsx_attribute(b.jsx_id('key'), to_jsx_expression_container(key_expression, key_expression)),
|
|
@@ -3834,9 +3808,9 @@ function to_jsx_element(
|
|
|
3834
3808
|
}
|
|
3835
3809
|
|
|
3836
3810
|
/**
|
|
3837
|
-
* @param {
|
|
3811
|
+
* @param {AST.Node[]} children
|
|
3838
3812
|
* @param {TransformContext} transform_context
|
|
3839
|
-
* @returns {
|
|
3813
|
+
* @returns {ESTreeJSX.JSXElement['children']}
|
|
3840
3814
|
*/
|
|
3841
3815
|
|
|
3842
3816
|
function create_element_children(children, transform_context) {
|
|
@@ -3848,9 +3822,7 @@ function create_element_children(children, transform_context) {
|
|
|
3848
3822
|
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3849
3823
|
transform_context.inside_element_child = true;
|
|
3850
3824
|
try {
|
|
3851
|
-
return wrap_edge_whitespace(
|
|
3852
|
-
children.map((/** @type {any} */ child) => to_jsx_child(child, transform_context)),
|
|
3853
|
-
);
|
|
3825
|
+
return wrap_edge_whitespace(children.map((child) => to_jsx_child(child, transform_context)));
|
|
3854
3826
|
} finally {
|
|
3855
3827
|
transform_context.inside_element_child = saved_inside_element_child;
|
|
3856
3828
|
}
|
|
@@ -3866,7 +3838,7 @@ function create_element_children(children, transform_context) {
|
|
|
3866
3838
|
}
|
|
3867
3839
|
|
|
3868
3840
|
/**
|
|
3869
|
-
* @param {
|
|
3841
|
+
* @param {AST.Node[]} children
|
|
3870
3842
|
* @returns {boolean}
|
|
3871
3843
|
*/
|
|
3872
3844
|
function children_contain_return_semantics(children) {
|
|
@@ -3874,35 +3846,35 @@ function children_contain_return_semantics(children) {
|
|
|
3874
3846
|
}
|
|
3875
3847
|
|
|
3876
3848
|
/**
|
|
3877
|
-
* @param {
|
|
3849
|
+
* @param {unknown} node
|
|
3878
3850
|
* @returns {boolean}
|
|
3879
3851
|
*/
|
|
3880
3852
|
function child_contains_return_semantics(node) {
|
|
3853
|
+
if (Array.isArray(node)) {
|
|
3854
|
+
return node.some(child_contains_return_semantics);
|
|
3855
|
+
}
|
|
3881
3856
|
if (!node || typeof node !== 'object') {
|
|
3882
3857
|
return false;
|
|
3883
3858
|
}
|
|
3859
|
+
const ast_node = /** @type {Record<string, unknown>} */ (node);
|
|
3884
3860
|
|
|
3885
|
-
if (
|
|
3861
|
+
if (ast_node.type === 'ReturnStatement') {
|
|
3886
3862
|
return true;
|
|
3887
3863
|
}
|
|
3888
3864
|
|
|
3889
3865
|
if (
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3866
|
+
ast_node.type === 'FunctionDeclaration' ||
|
|
3867
|
+
ast_node.type === 'FunctionExpression' ||
|
|
3868
|
+
ast_node.type === 'ArrowFunctionExpression'
|
|
3893
3869
|
) {
|
|
3894
3870
|
return false;
|
|
3895
3871
|
}
|
|
3896
3872
|
|
|
3897
|
-
|
|
3898
|
-
return node.some(child_contains_return_semantics);
|
|
3899
|
-
}
|
|
3900
|
-
|
|
3901
|
-
for (const key of Object.keys(node)) {
|
|
3873
|
+
for (const key of Object.keys(ast_node)) {
|
|
3902
3874
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3903
3875
|
continue;
|
|
3904
3876
|
}
|
|
3905
|
-
if (child_contains_return_semantics(
|
|
3877
|
+
if (child_contains_return_semantics(ast_node[key])) {
|
|
3906
3878
|
return true;
|
|
3907
3879
|
}
|
|
3908
3880
|
}
|
|
@@ -3911,11 +3883,11 @@ function child_contains_return_semantics(node) {
|
|
|
3911
3883
|
}
|
|
3912
3884
|
|
|
3913
3885
|
/**
|
|
3914
|
-
* @param {
|
|
3915
|
-
* @returns {
|
|
3886
|
+
* @param {AST.Node | null | undefined} node
|
|
3887
|
+
* @returns {node is AST.TSRXRenderChild}
|
|
3916
3888
|
*/
|
|
3917
3889
|
function is_inline_element_child(node) {
|
|
3918
|
-
return node && is_render_child_node(node);
|
|
3890
|
+
return !!node && is_render_child_node(node);
|
|
3919
3891
|
}
|
|
3920
3892
|
|
|
3921
3893
|
/**
|
|
@@ -4278,7 +4250,7 @@ function get_body_source_node(body_nodes) {
|
|
|
4278
4250
|
const first = body_nodes[0];
|
|
4279
4251
|
const last = body_nodes[body_nodes.length - 1];
|
|
4280
4252
|
|
|
4281
|
-
if (first
|
|
4253
|
+
if (has_location(first) && has_location(last)) {
|
|
4282
4254
|
return {
|
|
4283
4255
|
start: first.start,
|
|
4284
4256
|
end: last.end,
|
|
@@ -4333,8 +4305,8 @@ function get_raw_jsx_code_block_body_nodes(node) {
|
|
|
4333
4305
|
}
|
|
4334
4306
|
|
|
4335
4307
|
/**
|
|
4336
|
-
* @param {
|
|
4337
|
-
* @returns {
|
|
4308
|
+
* @param {AST.Node | null | undefined} node
|
|
4309
|
+
* @returns {node is AST.NativeTSRXNode}
|
|
4338
4310
|
*/
|
|
4339
4311
|
function is_native_tsrx_node(node) {
|
|
4340
4312
|
return (
|
|
@@ -4342,21 +4314,21 @@ function is_native_tsrx_node(node) {
|
|
|
4342
4314
|
((node?.type === 'JSXElement' ||
|
|
4343
4315
|
node?.type === 'JSXFragment' ||
|
|
4344
4316
|
node?.type === 'JSXStyleElement') &&
|
|
4345
|
-
node.metadata?.native_tsrx)
|
|
4317
|
+
!!node.metadata?.native_tsrx)
|
|
4346
4318
|
);
|
|
4347
4319
|
}
|
|
4348
4320
|
|
|
4349
4321
|
/**
|
|
4350
|
-
* @param {
|
|
4351
|
-
* @returns {
|
|
4322
|
+
* @param {AST.Node | null | undefined} node
|
|
4323
|
+
* @returns {node is AST.IfStatement | AST.JSXIfExpression}
|
|
4352
4324
|
*/
|
|
4353
4325
|
function is_if_control_node(node) {
|
|
4354
4326
|
return node?.type === 'IfStatement' || node?.type === 'JSXIfExpression';
|
|
4355
4327
|
}
|
|
4356
4328
|
|
|
4357
4329
|
/**
|
|
4358
|
-
* @param {
|
|
4359
|
-
* @returns {
|
|
4330
|
+
* @param {AST.Node | null | undefined} node
|
|
4331
|
+
* @returns {node is AST.TSRXRenderChild}
|
|
4360
4332
|
*/
|
|
4361
4333
|
function is_render_child_node(node) {
|
|
4362
4334
|
if (!node) return false;
|
|
@@ -4409,8 +4381,25 @@ function is_try_control_node(node) {
|
|
|
4409
4381
|
* are pulled out; whitespace runs containing a newline are layout indentation and
|
|
4410
4382
|
* are left for the host compiler to collapse.
|
|
4411
4383
|
*
|
|
4412
|
-
|
|
4413
|
-
|
|
4384
|
+
*/
|
|
4385
|
+
/**
|
|
4386
|
+
* @overload
|
|
4387
|
+
* @param {ESTreeJSX.JSXRenderChild[]} nodes
|
|
4388
|
+
* @returns {ESTreeJSX.JSXRenderChild[]}
|
|
4389
|
+
*/
|
|
4390
|
+
/**
|
|
4391
|
+
* @overload
|
|
4392
|
+
* @param {ESTreeJSX.JSXElement['children']} nodes
|
|
4393
|
+
* @returns {ESTreeJSX.JSXElement['children']}
|
|
4394
|
+
*/
|
|
4395
|
+
/**
|
|
4396
|
+
* @overload
|
|
4397
|
+
* @param {ESTreeJSX.JSXTransformChild[]} nodes
|
|
4398
|
+
* @returns {ESTreeJSX.JSXTransformChild[]}
|
|
4399
|
+
*/
|
|
4400
|
+
/**
|
|
4401
|
+
* @param {ESTreeJSX.JSXTransformChild[]} nodes
|
|
4402
|
+
* @returns {ESTreeJSX.JSXTransformChild[]}
|
|
4414
4403
|
*/
|
|
4415
4404
|
export function wrap_edge_whitespace(nodes) {
|
|
4416
4405
|
const length = nodes.length;
|
|
@@ -4424,7 +4413,7 @@ export function wrap_edge_whitespace(nodes) {
|
|
|
4424
4413
|
return nodes;
|
|
4425
4414
|
}
|
|
4426
4415
|
|
|
4427
|
-
/** @type {
|
|
4416
|
+
/** @type {ESTreeJSX.JSXTransformChild[]} */
|
|
4428
4417
|
const out = [];
|
|
4429
4418
|
for (let i = 0; i < length; i++) {
|
|
4430
4419
|
const node = nodes[i];
|
|
@@ -4454,7 +4443,7 @@ export function wrap_edge_whitespace(nodes) {
|
|
|
4454
4443
|
if (value !== '') {
|
|
4455
4444
|
// keep the location as we need it for @ autocomplete
|
|
4456
4445
|
// and perhaps other things in the future
|
|
4457
|
-
out.push(b.jsx_text(value, value, node));
|
|
4446
|
+
out.push(b.jsx_text(value, value, has_location(node) ? node : undefined));
|
|
4458
4447
|
}
|
|
4459
4448
|
if (trailing) {
|
|
4460
4449
|
out.push(trailing);
|
|
@@ -4464,9 +4453,21 @@ export function wrap_edge_whitespace(nodes) {
|
|
|
4464
4453
|
}
|
|
4465
4454
|
|
|
4466
4455
|
/**
|
|
4467
|
-
* @
|
|
4456
|
+
* @overload
|
|
4457
|
+
* @param {AST.TSRXRenderChild} node
|
|
4468
4458
|
* @param {TransformContext} transform_context
|
|
4469
|
-
* @returns {
|
|
4459
|
+
* @returns {ESTreeJSX.JSXRenderChild}
|
|
4460
|
+
*/
|
|
4461
|
+
/**
|
|
4462
|
+
* @overload
|
|
4463
|
+
* @param {AST.Node} node
|
|
4464
|
+
* @param {TransformContext} transform_context
|
|
4465
|
+
* @returns {AST.Node}
|
|
4466
|
+
*/
|
|
4467
|
+
/**
|
|
4468
|
+
* @param {AST.Node} node
|
|
4469
|
+
* @param {TransformContext} transform_context
|
|
4470
|
+
* @returns {AST.Node}
|
|
4470
4471
|
*/
|
|
4471
4472
|
function to_jsx_child(node, transform_context) {
|
|
4472
4473
|
if (!node) return node;
|
|
@@ -4540,25 +4541,25 @@ function to_jsx_child(node, transform_context) {
|
|
|
4540
4541
|
* Children have already been parsed and transformed through the normal TSRX
|
|
4541
4542
|
* JSX element/text/control-flow visitors.
|
|
4542
4543
|
*
|
|
4543
|
-
* @param {
|
|
4544
|
+
* @param {AST.TSRXJSXElement | AST.TSRXJSXFragment} node
|
|
4544
4545
|
* @param {TransformContext} transform_context
|
|
4545
4546
|
* @param {boolean} [in_jsx_child]
|
|
4546
|
-
* @returns {
|
|
4547
|
+
* @returns {AST.Expression | ESTreeJSX.JSXExpressionContainer}
|
|
4547
4548
|
*/
|
|
4548
4549
|
function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = false) {
|
|
4549
4550
|
const children = (node.children || []).filter(
|
|
4550
|
-
(
|
|
4551
|
+
(child) =>
|
|
4551
4552
|
child && child.type !== 'EmptyStatement' && (child.type !== 'JSXText' || child.value !== ''),
|
|
4552
4553
|
);
|
|
4553
4554
|
|
|
4554
|
-
/** @type {
|
|
4555
|
-
let expression;
|
|
4555
|
+
/** @type {AST.Expression | null} */
|
|
4556
|
+
let expression = null;
|
|
4556
4557
|
if (children.length === 0) {
|
|
4557
4558
|
// An empty fragment is a real value: keep it as `<></>` in BOTH child and
|
|
4558
4559
|
// expression position. Lowering it to a bare `null` in expression position
|
|
4559
4560
|
// (e.g. `let b = <></>`) drops the author's fragment and changes its type;
|
|
4560
4561
|
// `<></>` is a valid value and keeps the to_ts/runtime view faithful.
|
|
4561
|
-
expression = set_loc(b.jsx_fragment([]), node
|
|
4562
|
+
expression = set_loc(b.jsx_fragment([]), has_location(node) ? node : undefined);
|
|
4562
4563
|
} else if (
|
|
4563
4564
|
children.length === 1 &&
|
|
4564
4565
|
(is_empty_jsx_fragment(children[0]) ||
|
|
@@ -4569,7 +4570,7 @@ function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = fal
|
|
|
4569
4570
|
// dropping the outer fragment the author wrote. Keep both levels. (`<><></></>`
|
|
4570
4571
|
// is kept regardless; a non-empty inner is only kept for an authored outer, so
|
|
4571
4572
|
// a generated wrapper still collapses.)
|
|
4572
|
-
expression = set_loc(b.jsx_fragment(children), node
|
|
4573
|
+
expression = set_loc(b.jsx_fragment(children), has_location(node) ? node : undefined);
|
|
4573
4574
|
} else {
|
|
4574
4575
|
expression = return_value_body_to_expression(children, node, transform_context);
|
|
4575
4576
|
}
|
|
@@ -4580,7 +4581,7 @@ function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = fal
|
|
|
4580
4581
|
transform_context.inside_element_child = true;
|
|
4581
4582
|
try {
|
|
4582
4583
|
const render_nodes = wrap_edge_whitespace(
|
|
4583
|
-
children.map((
|
|
4584
|
+
children.map((child) => to_jsx_child(child, transform_context)),
|
|
4584
4585
|
);
|
|
4585
4586
|
expression =
|
|
4586
4587
|
build_return_expression(render_nodes, in_jsx_child, transform_context.typeOnly) ||
|
|
@@ -4593,13 +4594,7 @@ function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = fal
|
|
|
4593
4594
|
}
|
|
4594
4595
|
}
|
|
4595
4596
|
|
|
4596
|
-
if (
|
|
4597
|
-
in_jsx_child &&
|
|
4598
|
-
expression.type !== 'JSXElement' &&
|
|
4599
|
-
expression.type !== 'JSXFragment' &&
|
|
4600
|
-
expression.type !== 'JSXText' &&
|
|
4601
|
-
expression.type !== 'JSXExpressionContainer'
|
|
4602
|
-
) {
|
|
4597
|
+
if (in_jsx_child && expression.type !== 'JSXElement' && expression.type !== 'JSXFragment') {
|
|
4603
4598
|
return to_jsx_expression_container(expression, node);
|
|
4604
4599
|
}
|
|
4605
4600
|
|
|
@@ -4695,14 +4690,14 @@ function create_statement_iife(body_nodes, source_node, transform_context) {
|
|
|
4695
4690
|
}
|
|
4696
4691
|
|
|
4697
4692
|
/**
|
|
4698
|
-
* @param {
|
|
4699
|
-
* @param {
|
|
4693
|
+
* @param {AST.Expression} node
|
|
4694
|
+
* @param {AST.Node | null | undefined} source_node
|
|
4700
4695
|
* @param {TransformContext} [transform_context]
|
|
4701
|
-
* @returns {
|
|
4696
|
+
* @returns {AST.Expression}
|
|
4702
4697
|
*/
|
|
4703
4698
|
function set_generated_expression_loc(node, source_node, transform_context) {
|
|
4704
|
-
if (transform_context?.typeOnly || !source_node
|
|
4705
|
-
return setLocation(
|
|
4699
|
+
if (transform_context?.typeOnly || !has_location(source_node)) return node;
|
|
4700
|
+
return setLocation(node, source_node);
|
|
4706
4701
|
}
|
|
4707
4702
|
|
|
4708
4703
|
/**
|
|
@@ -5072,17 +5067,17 @@ function for_of_statement_to_jsx_child(node, transform_context) {
|
|
|
5072
5067
|
body_contains_top_level_hook_call(loop_body, transform_context, true);
|
|
5073
5068
|
const body_key_expression = find_key_expression_in_body(loop_body);
|
|
5074
5069
|
const explicit_key_expression =
|
|
5075
|
-
body_key_expression ?? (node.key ?
|
|
5070
|
+
body_key_expression ?? (node.key ? clone_ast_node(node.key) : undefined);
|
|
5076
5071
|
const key_expression =
|
|
5077
5072
|
has_hooks && explicit_key_expression == null && node.index
|
|
5078
|
-
?
|
|
5073
|
+
? clone_ast_node(node.index)
|
|
5079
5074
|
: explicit_key_expression;
|
|
5080
5075
|
const implicit_non_hook_key_expression =
|
|
5081
5076
|
!has_hooks && body_key_expression == null
|
|
5082
5077
|
? node.key
|
|
5083
|
-
?
|
|
5078
|
+
? clone_ast_node(node.key)
|
|
5084
5079
|
: node.index
|
|
5085
|
-
?
|
|
5080
|
+
? clone_ast_node(node.index)
|
|
5086
5081
|
: undefined
|
|
5087
5082
|
: undefined;
|
|
5088
5083
|
|
|
@@ -5158,7 +5153,7 @@ function for_of_statement_to_jsx_child(node, transform_context) {
|
|
|
5158
5153
|
b.conditional(
|
|
5159
5154
|
b.binary(
|
|
5160
5155
|
'===',
|
|
5161
|
-
b.member(
|
|
5156
|
+
b.member(clone_ast_node(node.right), create_generated_identifier('length')),
|
|
5162
5157
|
b.literal(0),
|
|
5163
5158
|
),
|
|
5164
5159
|
empty_fallback,
|
|
@@ -5199,7 +5194,7 @@ function apply_key_to_loop_body(body_nodes, key_expression) {
|
|
|
5199
5194
|
...attributes,
|
|
5200
5195
|
b.jsx_attribute(
|
|
5201
5196
|
b.jsx_id('key'),
|
|
5202
|
-
to_jsx_expression_container(
|
|
5197
|
+
to_jsx_expression_container(clone_ast_node(key_expression), key_expression),
|
|
5203
5198
|
),
|
|
5204
5199
|
],
|
|
5205
5200
|
},
|
|
@@ -5280,7 +5275,7 @@ function apply_key_to_jsx_element(element, key_expression) {
|
|
|
5280
5275
|
...attributes,
|
|
5281
5276
|
b.jsx_attribute(
|
|
5282
5277
|
b.jsx_id('key'),
|
|
5283
|
-
to_jsx_expression_container(
|
|
5278
|
+
to_jsx_expression_container(clone_ast_node(key_expression), key_expression),
|
|
5284
5279
|
),
|
|
5285
5280
|
],
|
|
5286
5281
|
},
|
|
@@ -5296,7 +5291,7 @@ function keyed_fragment_to_jsx_element(fragment, key_expression) {
|
|
|
5296
5291
|
const name = b.jsx_id('Fragment');
|
|
5297
5292
|
const key_attribute = b.jsx_attribute(
|
|
5298
5293
|
b.jsx_id('key'),
|
|
5299
|
-
to_jsx_expression_container(
|
|
5294
|
+
to_jsx_expression_container(clone_ast_node(key_expression), key_expression),
|
|
5300
5295
|
);
|
|
5301
5296
|
|
|
5302
5297
|
return b.jsx_element_fresh(
|
|
@@ -5502,9 +5497,9 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5502
5497
|
* Create a simple JSX element AST node.
|
|
5503
5498
|
*
|
|
5504
5499
|
* @param {string} tag_name
|
|
5505
|
-
* @param {
|
|
5506
|
-
* @param {
|
|
5507
|
-
* @returns {
|
|
5500
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} attributes
|
|
5501
|
+
* @param {ESTreeJSX.JSXElement['children']} children
|
|
5502
|
+
* @returns {ESTreeJSX.JSXElement}
|
|
5508
5503
|
*/
|
|
5509
5504
|
function create_jsx_element(tag_name, attributes, children) {
|
|
5510
5505
|
const self_closing = children.length === 0;
|
|
@@ -5522,12 +5517,12 @@ function create_jsx_element(tag_name, attributes, children) {
|
|
|
5522
5517
|
*
|
|
5523
5518
|
* @param {AST.Program} program
|
|
5524
5519
|
* @param {TransformContext} transform_context
|
|
5525
|
-
* @param {JsxPlatform} platform
|
|
5520
|
+
* @param {Pick<JsxPlatform, 'imports'>} platform
|
|
5526
5521
|
* @param {string} suspense_source - effective suspense import source after
|
|
5527
5522
|
* applying any per-call override from JsxTransformOptions.suspenseSource.
|
|
5528
5523
|
*/
|
|
5529
5524
|
function inject_try_imports(program, transform_context, platform, suspense_source) {
|
|
5530
|
-
/** @type {
|
|
5525
|
+
/** @type {AST.ImportDeclaration[]} */
|
|
5531
5526
|
const imports = [];
|
|
5532
5527
|
|
|
5533
5528
|
if (transform_context.needs_fragment && platform.imports.fragment) {
|
|
@@ -5569,7 +5564,7 @@ function inject_try_imports(program, transform_context, platform, suspense_sourc
|
|
|
5569
5564
|
? platform.imports.refProp
|
|
5570
5565
|
: null;
|
|
5571
5566
|
|
|
5572
|
-
/** @type {Map<string,
|
|
5567
|
+
/** @type {Map<string, AST.ImportSpecifier[]>} */
|
|
5573
5568
|
const ref_imports = new Map();
|
|
5574
5569
|
|
|
5575
5570
|
if (merge_refs_source !== null) {
|
|
@@ -5609,9 +5604,9 @@ function inject_try_imports(program, transform_context, platform, suspense_sourc
|
|
|
5609
5604
|
}
|
|
5610
5605
|
|
|
5611
5606
|
/**
|
|
5612
|
-
* @param {Map<string,
|
|
5607
|
+
* @param {Map<string, AST.ImportSpecifier[]>} imports
|
|
5613
5608
|
* @param {string} source
|
|
5614
|
-
* @param {
|
|
5609
|
+
* @param {AST.ImportSpecifier} specifier
|
|
5615
5610
|
*/
|
|
5616
5611
|
function add_ref_import_specifier(imports, source, specifier) {
|
|
5617
5612
|
const specifiers = imports.get(source);
|
|
@@ -5623,9 +5618,9 @@ function add_ref_import_specifier(imports, source, specifier) {
|
|
|
5623
5618
|
}
|
|
5624
5619
|
|
|
5625
5620
|
/**
|
|
5626
|
-
* @param {
|
|
5621
|
+
* @param {AST.IfStatement | AST.JSXIfExpression} node
|
|
5627
5622
|
* @param {TransformContext} transform_context
|
|
5628
|
-
* @returns {
|
|
5623
|
+
* @returns {AST.IfStatement}
|
|
5629
5624
|
*/
|
|
5630
5625
|
function create_render_if_statement(node, transform_context) {
|
|
5631
5626
|
const consequent_body =
|
|
@@ -5642,7 +5637,8 @@ function create_render_if_statement(node, transform_context) {
|
|
|
5642
5637
|
if (is_if_control_node(node.alternate)) {
|
|
5643
5638
|
alternate = create_render_if_statement(node.alternate, transform_context);
|
|
5644
5639
|
} else {
|
|
5645
|
-
const alternate_body =
|
|
5640
|
+
const alternate_body =
|
|
5641
|
+
node.alternate.type === 'BlockStatement' ? node.alternate.body : [node.alternate];
|
|
5646
5642
|
if (is_template_if_node(node)) {
|
|
5647
5643
|
validate_if_body_control_flow(alternate_body, transform_context);
|
|
5648
5644
|
}
|
|
@@ -5685,8 +5681,8 @@ function create_render_if_statement(node, transform_context) {
|
|
|
5685
5681
|
* `own_body` is the case's isolated consequent. JSX `@switch` cases do not
|
|
5686
5682
|
* fall through, so `break` is not part of the template switch model.
|
|
5687
5683
|
*
|
|
5688
|
-
* @param {
|
|
5689
|
-
* @returns {{ own_body:
|
|
5684
|
+
* @param {AST.Statement[]} consequent
|
|
5685
|
+
* @returns {{ own_body: AST.Statement[], has_terminator: boolean }}
|
|
5690
5686
|
*/
|
|
5691
5687
|
function summarize_switch_case_body(consequent) {
|
|
5692
5688
|
const own_body = [];
|
|
@@ -5716,10 +5712,10 @@ function summarize_switch_case_body(consequent) {
|
|
|
5716
5712
|
* see double/triple hits per source range.
|
|
5717
5713
|
*
|
|
5718
5714
|
* @param {{ component_element: ESTreeJSX.JSXElement }} helper
|
|
5719
|
-
* @returns {
|
|
5715
|
+
* @returns {ESTreeJSX.JSXElement}
|
|
5720
5716
|
*/
|
|
5721
5717
|
export function clone_switch_helper_invocation(helper) {
|
|
5722
|
-
return
|
|
5718
|
+
return clone_ast_node(helper.component_element, false);
|
|
5723
5719
|
}
|
|
5724
5720
|
|
|
5725
5721
|
/**
|
|
@@ -5736,31 +5732,29 @@ export function clone_switch_helper_invocation(helper) {
|
|
|
5736
5732
|
* React, Vue, and Solid) already pushed their declarations into
|
|
5737
5733
|
* `transform_context.helper_state.helpers`, so `setup_statements` is empty.
|
|
5738
5734
|
*
|
|
5739
|
-
* @param {
|
|
5735
|
+
* @param {AST.SwitchStatement} switch_node
|
|
5740
5736
|
* @param {TransformContext} transform_context
|
|
5741
5737
|
* @returns {{
|
|
5742
|
-
* case_info: Array<{ own_body:
|
|
5743
|
-
* case_helpers: Array<
|
|
5744
|
-
* setup_statements:
|
|
5738
|
+
* case_info: Array<{ own_body: AST.Statement[], has_terminator: boolean }>,
|
|
5739
|
+
* case_helpers: Array<JsxHelperComponent | null>,
|
|
5740
|
+
* setup_statements: AST.Statement[],
|
|
5745
5741
|
* }}
|
|
5746
5742
|
*/
|
|
5747
5743
|
export function plan_switch_lift(switch_node, transform_context) {
|
|
5748
|
-
const case_info = switch_node.cases.map((
|
|
5744
|
+
const case_info = switch_node.cases.map((c) => {
|
|
5749
5745
|
const consequent = flatten_switch_consequent(c.consequent || []);
|
|
5750
5746
|
return summarize_switch_case_body(consequent);
|
|
5751
5747
|
});
|
|
5752
5748
|
|
|
5753
5749
|
// A case body needs to be lifted iff it contains hooks. Cases are isolated,
|
|
5754
5750
|
// so downstream case bodies are never duplicated into earlier arms.
|
|
5755
|
-
const needs_helper = case_info.map(
|
|
5756
|
-
(
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
},
|
|
5763
|
-
);
|
|
5751
|
+
const needs_helper = case_info.map((info) => {
|
|
5752
|
+
if (info.own_body.length === 0) return false;
|
|
5753
|
+
return (
|
|
5754
|
+
should_extract_hook_helpers(transform_context) &&
|
|
5755
|
+
body_contains_top_level_hook_call(info.own_body, transform_context, true)
|
|
5756
|
+
);
|
|
5757
|
+
});
|
|
5764
5758
|
|
|
5765
5759
|
// Pre-allocate helper ids in source order so the snapshot's
|
|
5766
5760
|
// `StatementBodyHook<N>` numbering reads top-to-bottom by case position
|
|
@@ -5772,7 +5766,7 @@ export function plan_switch_lift(switch_node, transform_context) {
|
|
|
5772
5766
|
: null,
|
|
5773
5767
|
);
|
|
5774
5768
|
|
|
5775
|
-
/** @type {Array<
|
|
5769
|
+
/** @type {Array<JsxHelperComponent | null>} */
|
|
5776
5770
|
const case_helpers = new Array(switch_node.cases.length).fill(null);
|
|
5777
5771
|
|
|
5778
5772
|
for (let i = switch_node.cases.length - 1; i >= 0; i--) {
|
|
@@ -5784,12 +5778,13 @@ export function plan_switch_lift(switch_node, transform_context) {
|
|
|
5784
5778
|
undefined,
|
|
5785
5779
|
switch_node.cases[i],
|
|
5786
5780
|
transform_context,
|
|
5787
|
-
/** @type {
|
|
5781
|
+
/** @type {AST.Identifier} */ (helper_ids[i]),
|
|
5788
5782
|
);
|
|
5789
5783
|
}
|
|
5790
5784
|
|
|
5791
5785
|
// Hoist all helpers' setup statements above the switch in source order so
|
|
5792
5786
|
// the switch body stays a pure dispatcher.
|
|
5787
|
+
/** @type {AST.Statement[]} */
|
|
5793
5788
|
const setup_statements = [];
|
|
5794
5789
|
for (const helper of case_helpers) {
|
|
5795
5790
|
if (helper) setup_statements.push(...helper.setup_statements);
|
|
@@ -5803,9 +5798,9 @@ export function plan_switch_lift(switch_node, transform_context) {
|
|
|
5803
5798
|
}
|
|
5804
5799
|
|
|
5805
5800
|
/**
|
|
5806
|
-
* @param {
|
|
5801
|
+
* @param {AST.SwitchStatement} switch_node
|
|
5807
5802
|
* @param {TransformContext} transform_context
|
|
5808
|
-
* @returns {{ setup_statements:
|
|
5803
|
+
* @returns {{ setup_statements: AST.Statement[], switch_statement: AST.SwitchStatement }}
|
|
5809
5804
|
*/
|
|
5810
5805
|
function build_switch_with_lift(switch_node, transform_context) {
|
|
5811
5806
|
const { case_info, case_helpers, setup_statements } = plan_switch_lift(
|
|
@@ -5813,92 +5808,95 @@ function build_switch_with_lift(switch_node, transform_context) {
|
|
|
5813
5808
|
transform_context,
|
|
5814
5809
|
);
|
|
5815
5810
|
|
|
5816
|
-
const new_cases = switch_node.cases.map(
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
}
|
|
5811
|
+
const new_cases = switch_node.cases.map((original_case, /** @type {number} */ i) => {
|
|
5812
|
+
const helper = case_helpers[i];
|
|
5813
|
+
if (helper) {
|
|
5814
|
+
return set_loc(
|
|
5815
|
+
b.switch_case(original_case.test, [
|
|
5816
|
+
create_component_return_statement(
|
|
5817
|
+
[helper.component_element],
|
|
5818
|
+
original_case,
|
|
5819
|
+
true,
|
|
5820
|
+
transform_context.typeOnly,
|
|
5821
|
+
),
|
|
5822
|
+
]),
|
|
5823
|
+
original_case,
|
|
5824
|
+
);
|
|
5825
|
+
}
|
|
5832
5826
|
|
|
5833
|
-
|
|
5827
|
+
const { own_body, has_terminator } = case_info[i];
|
|
5834
5828
|
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5829
|
+
if (own_body.length === 0 && !has_terminator) {
|
|
5830
|
+
return set_loc(
|
|
5831
|
+
b.switch_case(original_case.test, [create_null_return_statement()]),
|
|
5832
|
+
original_case,
|
|
5833
|
+
);
|
|
5834
|
+
}
|
|
5835
|
+
|
|
5836
|
+
/** @type {AST.Statement[]} */
|
|
5837
|
+
const case_body = [];
|
|
5838
|
+
/** @type {ESTreeJSX.JSXElement['children']} */
|
|
5839
|
+
const render_nodes = [];
|
|
5840
|
+
let has_terminal = false;
|
|
5841
|
+
|
|
5842
|
+
for (const child of own_body) {
|
|
5843
|
+
if (is_loop_skip_return_statement(child)) {
|
|
5844
|
+
case_body.push(
|
|
5845
|
+
create_component_return_statement(render_nodes, child, true, transform_context.typeOnly),
|
|
5839
5846
|
);
|
|
5847
|
+
has_terminal = true;
|
|
5848
|
+
break;
|
|
5840
5849
|
}
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
has_terminal = true;
|
|
5857
|
-
break;
|
|
5858
|
-
}
|
|
5859
|
-
if (child.type === 'ReturnStatement') {
|
|
5860
|
-
case_body.push(child);
|
|
5861
|
-
has_terminal = true;
|
|
5862
|
-
break;
|
|
5863
|
-
}
|
|
5864
|
-
if (is_render_child_node(child)) {
|
|
5865
|
-
render_nodes.push(to_jsx_child(child, transform_context));
|
|
5866
|
-
} else if (is_bare_render_expression(child)) {
|
|
5867
|
-
render_nodes.push(to_jsx_expression_container(child, child));
|
|
5868
|
-
} else {
|
|
5869
|
-
case_body.push(child);
|
|
5870
|
-
}
|
|
5850
|
+
if (child.type === 'ReturnStatement') {
|
|
5851
|
+
case_body.push(child);
|
|
5852
|
+
has_terminal = true;
|
|
5853
|
+
break;
|
|
5854
|
+
}
|
|
5855
|
+
if (is_render_child_node(child)) {
|
|
5856
|
+
render_nodes.push(
|
|
5857
|
+
/** @type {ESTreeJSX.JSXElement['children'][number]} */ (
|
|
5858
|
+
to_jsx_child(child, transform_context)
|
|
5859
|
+
),
|
|
5860
|
+
);
|
|
5861
|
+
} else if (is_bare_render_expression(child)) {
|
|
5862
|
+
render_nodes.push(to_jsx_expression_container(child, child));
|
|
5863
|
+
} else {
|
|
5864
|
+
case_body.push(child);
|
|
5871
5865
|
}
|
|
5866
|
+
}
|
|
5872
5867
|
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
}
|
|
5868
|
+
if (!has_terminal) {
|
|
5869
|
+
if (render_nodes.length > 0) {
|
|
5870
|
+
case_body.push(
|
|
5871
|
+
create_component_return_statement(
|
|
5872
|
+
render_nodes,
|
|
5873
|
+
original_case,
|
|
5874
|
+
true,
|
|
5875
|
+
transform_context.typeOnly,
|
|
5876
|
+
),
|
|
5877
|
+
);
|
|
5878
|
+
} else if (case_body.length > 0) {
|
|
5879
|
+
case_body.push(create_null_return_statement());
|
|
5880
|
+
} else if (has_terminator) {
|
|
5881
|
+
case_body.push(create_null_return_statement());
|
|
5888
5882
|
}
|
|
5883
|
+
}
|
|
5889
5884
|
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
);
|
|
5885
|
+
return set_loc(b.switch_case(original_case.test, case_body), original_case);
|
|
5886
|
+
});
|
|
5893
5887
|
|
|
5894
5888
|
return {
|
|
5895
5889
|
setup_statements,
|
|
5896
|
-
switch_statement: b.switch(
|
|
5890
|
+
switch_statement: b.switch(
|
|
5891
|
+
switch_node.discriminant,
|
|
5892
|
+
new_cases,
|
|
5893
|
+
has_location(switch_node) ? switch_node : undefined,
|
|
5894
|
+
),
|
|
5897
5895
|
};
|
|
5898
5896
|
}
|
|
5899
5897
|
|
|
5900
5898
|
/**
|
|
5901
|
-
* @returns {
|
|
5899
|
+
* @returns {AST.ReturnStatement}
|
|
5902
5900
|
*/
|
|
5903
5901
|
function create_null_return_statement() {
|
|
5904
5902
|
return b.return(b.literal(null));
|
|
@@ -5906,25 +5904,25 @@ function create_null_return_statement() {
|
|
|
5906
5904
|
|
|
5907
5905
|
/**
|
|
5908
5906
|
* @param {AST.Expression} expression
|
|
5909
|
-
* @param {
|
|
5907
|
+
* @param {AST.Node} [source_node]
|
|
5910
5908
|
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
5911
5909
|
*/
|
|
5912
5910
|
function to_jsx_expression_container(expression, source_node = expression) {
|
|
5913
5911
|
// NOTE: JSXExpressionContainer nodes are intentionally created without loc.
|
|
5914
5912
|
// They are synthetic wrappers whose source positions do not correspond to
|
|
5915
5913
|
// entries in the generated source map, so adding loc causes Volar mapping failures.
|
|
5916
|
-
return
|
|
5914
|
+
return {
|
|
5917
5915
|
type: 'JSXExpressionContainer',
|
|
5918
|
-
expression
|
|
5916
|
+
expression,
|
|
5919
5917
|
metadata: { path: [] },
|
|
5920
|
-
}
|
|
5918
|
+
};
|
|
5921
5919
|
}
|
|
5922
5920
|
|
|
5923
5921
|
/**
|
|
5924
|
-
* Dispatch point for element attribute transformation. Platforms can
|
|
5925
|
-
* the
|
|
5926
|
-
*
|
|
5927
|
-
*
|
|
5922
|
+
* Dispatch point for element attribute transformation. Platforms can transform
|
|
5923
|
+
* the parser-native JSX attributes via `hooks.transformElementAttributes`.
|
|
5924
|
+
* Whether or not the hook is used, the result is run through
|
|
5925
|
+
* `merge_duplicate_refs` so platforms with a
|
|
5928
5926
|
* `multiRefStrategy` can compose an explicit `ref={...}` with compiler-
|
|
5929
5927
|
* synthesized refs created for host spreads.
|
|
5930
5928
|
*
|
|
@@ -5933,10 +5931,10 @@ function to_jsx_expression_container(expression, source_node = expression) {
|
|
|
5933
5931
|
* duplicate JSX props which the JSX runtime collapses to last-wins (and
|
|
5934
5932
|
* which TypeScript can't type cleanly).
|
|
5935
5933
|
*
|
|
5936
|
-
* @param {
|
|
5934
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} attrs
|
|
5937
5935
|
* @param {TransformContext} transform_context
|
|
5938
|
-
* @param {
|
|
5939
|
-
* @returns {
|
|
5936
|
+
* @param {AST.TSRXJSXElement} element
|
|
5937
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
5940
5938
|
*/
|
|
5941
5939
|
function transform_element_attributes_dispatch(attrs, transform_context, element) {
|
|
5942
5940
|
validate_at_most_one_ref_attribute(attrs, transform_context);
|
|
@@ -5946,9 +5944,7 @@ function transform_element_attributes_dispatch(attrs, transform_context, element
|
|
|
5946
5944
|
attrs = preprocess(attrs, transform_context, element);
|
|
5947
5945
|
}
|
|
5948
5946
|
const hook = transform_context.platform.hooks?.transformElementAttributes;
|
|
5949
|
-
const result = hook
|
|
5950
|
-
? hook(attrs, transform_context, element)
|
|
5951
|
-
: attrs.map((/** @type {any} */ a) => to_jsx_attribute(a, transform_context));
|
|
5947
|
+
const result = hook ? hook(attrs, transform_context, element) : attrs;
|
|
5952
5948
|
return merge_duplicate_refs(
|
|
5953
5949
|
normalize_host_ref_spreads(result, !is_component, transform_context),
|
|
5954
5950
|
transform_context,
|
|
@@ -5956,7 +5952,7 @@ function transform_element_attributes_dispatch(attrs, transform_context, element
|
|
|
5956
5952
|
}
|
|
5957
5953
|
|
|
5958
5954
|
/**
|
|
5959
|
-
* @param {
|
|
5955
|
+
* @param {AST.TSRXJSXElement | ESTreeJSX.JSXElement} element
|
|
5960
5956
|
* @returns {boolean}
|
|
5961
5957
|
*/
|
|
5962
5958
|
export function is_component_like_element(element) {
|
|
@@ -5970,7 +5966,7 @@ export function is_component_like_element(element) {
|
|
|
5970
5966
|
}
|
|
5971
5967
|
|
|
5972
5968
|
/**
|
|
5973
|
-
* @param {
|
|
5969
|
+
* @param {ESTreeJSX.TSRXJSXOpeningElement['name']} name
|
|
5974
5970
|
* @returns {boolean}
|
|
5975
5971
|
*/
|
|
5976
5972
|
function is_component_like_jsx_name(name) {
|
|
@@ -5981,10 +5977,10 @@ function is_component_like_jsx_name(name) {
|
|
|
5981
5977
|
}
|
|
5982
5978
|
|
|
5983
5979
|
/**
|
|
5984
|
-
* @param {
|
|
5980
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} attrs
|
|
5985
5981
|
* @param {boolean} is_host
|
|
5986
5982
|
* @param {TransformContext} transform_context
|
|
5987
|
-
* @returns {
|
|
5983
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
5988
5984
|
*/
|
|
5989
5985
|
function normalize_host_ref_spreads(attrs, is_host, transform_context) {
|
|
5990
5986
|
if (!is_host) return attrs;
|
|
@@ -5996,49 +5992,55 @@ function normalize_host_ref_spreads(attrs, is_host, transform_context) {
|
|
|
5996
5992
|
.map((attr) => attr.value.expression);
|
|
5997
5993
|
const needs_synthetic_spread_ref = needs_explicit_spread_ref || ref_exprs.length > 0;
|
|
5998
5994
|
|
|
5999
|
-
return attrs.flatMap(
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
5995
|
+
return attrs.flatMap(
|
|
5996
|
+
/**
|
|
5997
|
+
* @param {ESTreeJSX.JSXAttributeNode} attr
|
|
5998
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
5999
|
+
*/
|
|
6000
|
+
(attr) => {
|
|
6001
|
+
if (attr.type !== 'JSXSpreadAttribute') {
|
|
6002
|
+
return [attr];
|
|
6003
|
+
}
|
|
6003
6004
|
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6005
|
+
const normalize_helper = needs_synthetic_spread_ref
|
|
6006
|
+
? NORMALIZE_SPREAD_PROPS_FOR_REF_ATTR_INTERNAL_NAME
|
|
6007
|
+
: NORMALIZE_SPREAD_PROPS_INTERNAL_NAME;
|
|
6008
|
+
if (needs_synthetic_spread_ref) {
|
|
6009
|
+
transform_context.needs_normalize_spread_props_for_ref_attr = true;
|
|
6010
|
+
} else {
|
|
6011
|
+
transform_context.needs_normalize_spread_props = true;
|
|
6012
|
+
}
|
|
6013
|
+
const normalized = b.call(normalize_helper, attr.argument);
|
|
6013
6014
|
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6015
|
+
if (needs_synthetic_spread_ref) {
|
|
6016
|
+
const normalized_id = create_generated_identifier(
|
|
6017
|
+
create_spread_props_name(transform_context),
|
|
6018
|
+
);
|
|
6019
|
+
const spread = {
|
|
6020
|
+
...attr,
|
|
6021
|
+
argument: clone_identifier(normalized_id),
|
|
6022
|
+
};
|
|
6023
|
+
const ref_attr = b.jsx_attribute(
|
|
6024
|
+
b.jsx_id('ref'),
|
|
6025
|
+
to_jsx_expression_container(b.member(clone_identifier(normalized_id), 'ref'), attr),
|
|
6026
|
+
false,
|
|
6027
|
+
has_location(attr) ? attr : undefined,
|
|
6028
|
+
);
|
|
6029
|
+
ref_attr.metadata = { ...(ref_attr.metadata || {}) };
|
|
6030
|
+
ref_attr.metadata.synthetic_ref = true;
|
|
6031
|
+
add_jsx_setup_declaration(spread, b.let(clone_identifier(normalized_id), normalized));
|
|
6031
6032
|
|
|
6032
|
-
|
|
6033
|
-
|
|
6033
|
+
return [spread, ref_attr];
|
|
6034
|
+
}
|
|
6034
6035
|
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6036
|
+
return [
|
|
6037
|
+
{
|
|
6038
|
+
...attr,
|
|
6039
|
+
argument: normalized,
|
|
6040
|
+
},
|
|
6041
|
+
];
|
|
6042
|
+
},
|
|
6043
|
+
);
|
|
6042
6044
|
}
|
|
6043
6045
|
|
|
6044
6046
|
/**
|
|
@@ -6055,8 +6057,8 @@ function create_spread_props_name(transform_context) {
|
|
|
6055
6057
|
}
|
|
6056
6058
|
|
|
6057
6059
|
/**
|
|
6058
|
-
* @param {
|
|
6059
|
-
* @param {
|
|
6060
|
+
* @param {AST.Node} node
|
|
6061
|
+
* @param {AST.Statement} declaration
|
|
6060
6062
|
*/
|
|
6061
6063
|
export function add_jsx_setup_declaration(node, declaration) {
|
|
6062
6064
|
node.metadata ??= { path: [] };
|
|
@@ -6064,29 +6066,40 @@ export function add_jsx_setup_declaration(node, declaration) {
|
|
|
6064
6066
|
}
|
|
6065
6067
|
|
|
6066
6068
|
/**
|
|
6067
|
-
* @param {
|
|
6068
|
-
* @param {Set<
|
|
6069
|
-
* @returns {
|
|
6069
|
+
* @param {AST.Node} node
|
|
6070
|
+
* @param {Set<object>} [seen]
|
|
6071
|
+
* @returns {AST.Statement[]}
|
|
6070
6072
|
*/
|
|
6071
6073
|
export function extract_jsx_setup_declarations(node, seen = new Set()) {
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6074
|
+
/** @type {AST.Statement[]} */
|
|
6075
|
+
const declarations = [];
|
|
6076
|
+
collect_jsx_setup_declarations(node, seen, declarations);
|
|
6077
|
+
return declarations;
|
|
6078
|
+
}
|
|
6076
6079
|
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6080
|
+
/**
|
|
6081
|
+
* @param {unknown} value
|
|
6082
|
+
* @param {Set<object>} seen
|
|
6083
|
+
* @param {AST.Statement[]} declarations
|
|
6084
|
+
* @returns {void}
|
|
6085
|
+
*/
|
|
6086
|
+
function collect_jsx_setup_declarations(value, seen, declarations) {
|
|
6087
|
+
if (value == null || typeof value !== 'object' || seen.has(value)) return;
|
|
6088
|
+
seen.add(value);
|
|
6081
6089
|
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6090
|
+
if ('type' in value && typeof value.type === 'string') {
|
|
6091
|
+
const node = /** @type {AST.Node} */ (value);
|
|
6092
|
+
if (node.metadata?.generated_setup_declarations) {
|
|
6093
|
+
declarations.push(...node.metadata.generated_setup_declarations);
|
|
6094
|
+
delete node.metadata.generated_setup_declarations;
|
|
6085
6095
|
}
|
|
6086
|
-
declarations.push(...extract_jsx_setup_declarations(node[key], seen));
|
|
6087
6096
|
}
|
|
6088
6097
|
|
|
6089
|
-
|
|
6098
|
+
const record = /** @type {Record<string, unknown>} */ (value);
|
|
6099
|
+
for (const key of Object.keys(record)) {
|
|
6100
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') continue;
|
|
6101
|
+
collect_jsx_setup_declarations(record[key], seen, declarations);
|
|
6102
|
+
}
|
|
6090
6103
|
}
|
|
6091
6104
|
|
|
6092
6105
|
/**
|
|
@@ -6120,11 +6133,11 @@ function wrap_jsx_setup_declarations(expression, in_jsx_child) {
|
|
|
6120
6133
|
* This validator runs over the raw, pre-lowering attribute list so each
|
|
6121
6134
|
* shape is still distinguishable by `type`.
|
|
6122
6135
|
*
|
|
6123
|
-
* @param {
|
|
6136
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} raw_attrs
|
|
6124
6137
|
* @param {TransformContext} [transform_context]
|
|
6125
6138
|
*/
|
|
6126
6139
|
export function validate_at_most_one_ref_attribute(raw_attrs, transform_context) {
|
|
6127
|
-
/** @type {
|
|
6140
|
+
/** @type {ESTreeJSX.JSXIdentifier[]} */
|
|
6128
6141
|
const refs = [];
|
|
6129
6142
|
for (const attr of raw_attrs) {
|
|
6130
6143
|
if (!attr) continue;
|
|
@@ -6134,7 +6147,7 @@ export function validate_at_most_one_ref_attribute(raw_attrs, transform_context)
|
|
|
6134
6147
|
attr.name.type === 'JSXIdentifier' &&
|
|
6135
6148
|
attr.name.name === 'ref';
|
|
6136
6149
|
if (!is_ref_attr) continue;
|
|
6137
|
-
refs.push(attr.name);
|
|
6150
|
+
refs.push(/** @type {ESTreeJSX.JSXIdentifier} */ (attr.name));
|
|
6138
6151
|
}
|
|
6139
6152
|
if (refs.length < 2) {
|
|
6140
6153
|
return;
|
|
@@ -6172,9 +6185,9 @@ export function validate_at_most_one_ref_attribute(raw_attrs, transform_context)
|
|
|
6172
6185
|
* Single-ref elements are always left unchanged so trivial cases stay
|
|
6173
6186
|
* import-free and produce no helper call.
|
|
6174
6187
|
*
|
|
6175
|
-
* @param {
|
|
6188
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} jsx_attrs
|
|
6176
6189
|
* @param {TransformContext} transform_context
|
|
6177
|
-
* @returns {
|
|
6190
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
6178
6191
|
*/
|
|
6179
6192
|
export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
6180
6193
|
const strategy = transform_context.platform.jsx.multiRefStrategy;
|
|
@@ -6194,11 +6207,11 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
6194
6207
|
// instead of silently composing them into `__mergeRefs(...)`.
|
|
6195
6208
|
if (tsx_form_count >= 2) return jsx_attrs;
|
|
6196
6209
|
|
|
6197
|
-
/** @type {
|
|
6210
|
+
/** @type {AST.Expression[]} */
|
|
6198
6211
|
const ref_exprs = [];
|
|
6199
|
-
/** @type {
|
|
6212
|
+
/** @type {ESTreeJSX.JSXAttributeNode[]} */
|
|
6200
6213
|
const result = [];
|
|
6201
|
-
/** @type {
|
|
6214
|
+
/** @type {ESTreeJSX.JSXRefAttribute | null} */
|
|
6202
6215
|
let source_attr = null;
|
|
6203
6216
|
for (const attr of jsx_attrs) {
|
|
6204
6217
|
if (is_jsx_ref_attribute(attr)) {
|
|
@@ -6228,12 +6241,15 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
6228
6241
|
// merged attribute and its name. Without this the kept `ref` keyword in
|
|
6229
6242
|
// `ref={__mergeRefs(...)}` has no source mapping back to the user's `ref=`
|
|
6230
6243
|
// keyword.
|
|
6231
|
-
const
|
|
6244
|
+
const source_name = source_attr?.name;
|
|
6245
|
+
const source_name_location = has_location(source_name) ? source_name : undefined;
|
|
6246
|
+
const source_attr_location = has_location(source_attr) ? source_attr : undefined;
|
|
6247
|
+
const merged_name = build_jsx_id('ref', source_name_location);
|
|
6232
6248
|
const merged_attr = build_jsx_attribute(
|
|
6233
6249
|
merged_name,
|
|
6234
6250
|
b.jsx_expression_container(merged_value),
|
|
6235
6251
|
false,
|
|
6236
|
-
|
|
6252
|
+
source_attr_location,
|
|
6237
6253
|
);
|
|
6238
6254
|
result.push(merged_attr);
|
|
6239
6255
|
|
|
@@ -6241,8 +6257,8 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
6241
6257
|
}
|
|
6242
6258
|
|
|
6243
6259
|
/**
|
|
6244
|
-
* @param {
|
|
6245
|
-
* @returns {
|
|
6260
|
+
* @param {ESTreeJSX.JSXAttributeNode} attr
|
|
6261
|
+
* @returns {attr is ESTreeJSX.JSXRefAttribute}
|
|
6246
6262
|
*/
|
|
6247
6263
|
function is_jsx_ref_attribute(attr) {
|
|
6248
6264
|
return (
|
|
@@ -6289,7 +6305,7 @@ const MATHML_REF_TAG_NAMES = new Set(
|
|
|
6289
6305
|
);
|
|
6290
6306
|
|
|
6291
6307
|
/**
|
|
6292
|
-
* @param {
|
|
6308
|
+
* @param {ESTreeJSX.JSXElement | ESTreeJSX.JSXOpeningElement} element
|
|
6293
6309
|
* @param {'html' | 'svg' | 'mathml'} [namespace]
|
|
6294
6310
|
* @returns {AST.TypeNode | null}
|
|
6295
6311
|
*/
|
|
@@ -6340,13 +6356,14 @@ function infer_ref_namespace(tag_name) {
|
|
|
6340
6356
|
}
|
|
6341
6357
|
|
|
6342
6358
|
/**
|
|
6343
|
-
* @param {
|
|
6359
|
+
* @param {ESTreeJSX.JSXElement | ESTreeJSX.JSXOpeningElement} element
|
|
6344
6360
|
* @returns {string | null}
|
|
6345
6361
|
*/
|
|
6346
6362
|
function get_element_ref_tag_name(element) {
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6363
|
+
if ('name' in element && element.name.type === 'JSXIdentifier') {
|
|
6364
|
+
return element.name.name;
|
|
6365
|
+
}
|
|
6366
|
+
if ('openingElement' in element && element.openingElement.name.type === 'JSXIdentifier') {
|
|
6350
6367
|
return element.openingElement.name.name;
|
|
6351
6368
|
}
|
|
6352
6369
|
return null;
|
|
@@ -6367,70 +6384,9 @@ function create_tag_name_map_ref_type(map_name, tag_name) {
|
|
|
6367
6384
|
}
|
|
6368
6385
|
|
|
6369
6386
|
/**
|
|
6370
|
-
* @param {
|
|
6371
|
-
* @param {TransformContext} transform_context
|
|
6372
|
-
* @returns {ESTreeJSX.JSXAttribute | ESTreeJSX.JSXSpreadAttribute}
|
|
6373
|
-
*/
|
|
6374
|
-
export function to_jsx_attribute(attr, transform_context) {
|
|
6375
|
-
if (!attr) return attr;
|
|
6376
|
-
if (attr.type === 'JSXAttribute') {
|
|
6377
|
-
return attr;
|
|
6378
|
-
}
|
|
6379
|
-
if (attr.type === 'JSXSpreadAttribute') {
|
|
6380
|
-
return attr;
|
|
6381
|
-
}
|
|
6382
|
-
// Keep this legacy hook for targets that need React-style DOM attrs. The
|
|
6383
|
-
// current first-party targets preserve authored `class`.
|
|
6384
|
-
let attr_name = attr.name;
|
|
6385
|
-
if (
|
|
6386
|
-
transform_context.platform.jsx.rewriteClassAttr &&
|
|
6387
|
-
attr_name &&
|
|
6388
|
-
attr_name.type === 'Identifier' &&
|
|
6389
|
-
attr_name.name === 'class'
|
|
6390
|
-
) {
|
|
6391
|
-
attr_name = set_loc(b.id('className'), attr.name);
|
|
6392
|
-
attr_name.metadata.source_name = 'class';
|
|
6393
|
-
attr_name.metadata.source_length = 'class'.length;
|
|
6394
|
-
}
|
|
6395
|
-
|
|
6396
|
-
const name =
|
|
6397
|
-
attr_name && attr_name.type === 'Identifier' ? identifier_to_jsx_name(attr_name) : attr_name;
|
|
6398
|
-
|
|
6399
|
-
let value = attr.value;
|
|
6400
|
-
if (value) {
|
|
6401
|
-
if (value.type === 'Literal' && typeof value.value === 'string') {
|
|
6402
|
-
// Keep string literal as attribute string.
|
|
6403
|
-
} else if (value.type !== 'JSXExpressionContainer') {
|
|
6404
|
-
value = to_jsx_expression_container(value);
|
|
6405
|
-
}
|
|
6406
|
-
}
|
|
6407
|
-
|
|
6408
|
-
const jsx_attribute = build_jsx_attribute(name, value || null, attr.shorthand === true);
|
|
6409
|
-
|
|
6410
|
-
if (value_has_unmappable_jsx_loc(value)) {
|
|
6411
|
-
/** @type {any} */ (jsx_attribute.metadata).has_unmappable_value = true;
|
|
6412
|
-
return jsx_attribute;
|
|
6413
|
-
}
|
|
6414
|
-
|
|
6415
|
-
return set_loc(jsx_attribute, attr);
|
|
6416
|
-
}
|
|
6417
|
-
|
|
6418
|
-
/**
|
|
6419
|
-
* @param {any} value
|
|
6420
|
-
* @returns {boolean}
|
|
6421
|
-
*/
|
|
6422
|
-
function value_has_unmappable_jsx_loc(value) {
|
|
6423
|
-
return !!(
|
|
6424
|
-
value?.type === 'JSXExpressionContainer' &&
|
|
6425
|
-
(value.expression?.type === 'JSXElement' || value.expression?.type === 'JSXFragment') &&
|
|
6426
|
-
!value.expression.loc
|
|
6427
|
-
);
|
|
6428
|
-
}
|
|
6429
|
-
|
|
6430
|
-
/**
|
|
6431
|
-
* @param {any[]} render_nodes
|
|
6387
|
+
* @param {ESTreeJSX.JSXRenderChild[]} render_nodes
|
|
6432
6388
|
* @param {boolean} [in_jsx_child]
|
|
6433
|
-
* @returns {
|
|
6389
|
+
* @returns {AST.Expression | null}
|
|
6434
6390
|
*/
|
|
6435
6391
|
export function build_return_expression(render_nodes, in_jsx_child = false, type_only = false) {
|
|
6436
6392
|
if (render_nodes.length === 0) return null;
|
|
@@ -6438,10 +6394,10 @@ export function build_return_expression(render_nodes, in_jsx_child = false, type
|
|
|
6438
6394
|
const only = render_nodes[0];
|
|
6439
6395
|
if (only.type === 'JSXExpressionContainer') {
|
|
6440
6396
|
if (only.metadata?.tsrx_reactive_block === true) {
|
|
6441
|
-
return set_loc(b.jsx_fragment([only]), only
|
|
6397
|
+
return set_loc(b.jsx_fragment([only]), has_location(only) ? only : undefined);
|
|
6442
6398
|
}
|
|
6443
6399
|
if (only.expression?.type === 'JSXEmptyExpression') {
|
|
6444
|
-
return set_loc(b.jsx_fragment([]), only
|
|
6400
|
+
return set_loc(b.jsx_fragment([]), has_location(only) ? only : undefined);
|
|
6445
6401
|
}
|
|
6446
6402
|
return only.expression;
|
|
6447
6403
|
}
|
|
@@ -6454,7 +6410,7 @@ export function build_return_expression(render_nodes, in_jsx_child = false, type
|
|
|
6454
6410
|
if (!type_only && !in_jsx_child && (only.value ?? '').trim() === '') {
|
|
6455
6411
|
return null;
|
|
6456
6412
|
}
|
|
6457
|
-
return set_loc(b.jsx_fragment([only]), only
|
|
6413
|
+
return set_loc(b.jsx_fragment([only]), has_location(only) ? only : undefined);
|
|
6458
6414
|
}
|
|
6459
6415
|
return only;
|
|
6460
6416
|
}
|
|
@@ -6462,7 +6418,7 @@ export function build_return_expression(render_nodes, in_jsx_child = false, type
|
|
|
6462
6418
|
const last = render_nodes[render_nodes.length - 1];
|
|
6463
6419
|
return set_loc(
|
|
6464
6420
|
b.jsx_fragment(render_nodes),
|
|
6465
|
-
first
|
|
6421
|
+
has_location(first) && has_location(last)
|
|
6466
6422
|
? {
|
|
6467
6423
|
start: first.start,
|
|
6468
6424
|
end: last.end,
|