@tsrx/core 0.1.46 → 0.1.48
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 +1 -1
- package/src/index.js +3 -2
- package/src/parse/index.js +3 -2
- package/src/plugin.js +110 -26
- package/src/transform/imports.js +96 -0
- package/src/transform/jsx/ast-builders.js +131 -110
- package/src/transform/jsx/helpers.js +77 -81
- package/src/transform/jsx/index.js +342 -360
- package/src/transform/lazy.js +5 -5
- package/src/transform/segments.js +29 -28
- package/src/transform/style-ref.js +9 -13
- package/src/utils/ast.js +11 -0
- package/src/utils/builders.js +3 -3
- package/types/index.d.ts +95 -12
- package/types/jsx-platform.d.ts +88 -54
- package/types/parse.d.ts +64 -4
|
@@ -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,
|
|
@@ -62,6 +63,7 @@ import {
|
|
|
62
63
|
import { is_hoist_safe_jsx_node } from '../jsx-hoist.js';
|
|
63
64
|
import { lower_server_module_for_types } from './server-module.js';
|
|
64
65
|
import {
|
|
66
|
+
has_location,
|
|
65
67
|
is_function_or_class_node as is_function_or_class_boundary,
|
|
66
68
|
is_template_directive as is_jsx_control_flow_expression,
|
|
67
69
|
} from '../../utils/ast.js';
|
|
@@ -106,18 +108,6 @@ function report_jsx_fragment_in_tsrx_error(node, transform_context) {
|
|
|
106
108
|
);
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
/**
|
|
110
|
-
* Local alias for the shared `JsxTransformContext`. Kept as a typedef so the
|
|
111
|
-
* rest of this file's `@param {TransformContext}` annotations don't all have
|
|
112
|
-
* to spell out the import.
|
|
113
|
-
*
|
|
114
|
-
* @typedef {JsxTransformContext} TransformContext
|
|
115
|
-
*/
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @typedef {{ source_name: string, read: () => any }} LazyBinding
|
|
119
|
-
*/
|
|
120
|
-
|
|
121
111
|
/**
|
|
122
112
|
* @param {any} node
|
|
123
113
|
* @param {boolean} [inside_function]
|
|
@@ -392,7 +382,7 @@ function wrap_lowered_value_in_fragment(expression, source) {
|
|
|
392
382
|
expression?.type === 'JSXExpressionContainer'
|
|
393
383
|
? expression
|
|
394
384
|
: to_jsx_expression_container(expression, source);
|
|
395
|
-
return set_loc(b.jsx_fragment([child]), source
|
|
385
|
+
return set_loc(b.jsx_fragment([child]), has_location(source) ? source : undefined);
|
|
396
386
|
}
|
|
397
387
|
|
|
398
388
|
/**
|
|
@@ -568,7 +558,7 @@ export function createJsxTransform(platform) {
|
|
|
568
558
|
function transform(ast, source, filename, options) {
|
|
569
559
|
const suspense_source = options?.suspenseSource ?? platform.imports.suspense;
|
|
570
560
|
const collect = !!(options?.collect || options?.loose);
|
|
571
|
-
/** @type {
|
|
561
|
+
/** @type {AST.CSS.StyleSheet[]} */
|
|
572
562
|
const stylesheets = [];
|
|
573
563
|
/** @type {AST.Statement[]} */
|
|
574
564
|
const type_only_style_anchors = [];
|
|
@@ -587,6 +577,14 @@ export function createJsxTransform(platform) {
|
|
|
587
577
|
needs_dynamic_factory: false,
|
|
588
578
|
needs_for_of_iterable: false,
|
|
589
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,
|
|
590
588
|
stylesheets,
|
|
591
589
|
type_only_style_anchors,
|
|
592
590
|
module_scoped_hook_components:
|
|
@@ -881,13 +879,13 @@ function lower_dynamic_jsx_element(node, transform_context) {
|
|
|
881
879
|
|
|
882
880
|
const dynamic_expression = dynamic_name.expression;
|
|
883
881
|
if (!dynamic_expression) return;
|
|
884
|
-
const generated_expression =
|
|
882
|
+
const generated_expression = clone_ast_node(dynamic_expression);
|
|
885
883
|
if (node.closingElement?.name?.expression) {
|
|
886
884
|
// One generated expression stands in for both tags; record the closing
|
|
887
885
|
// tag's positions so editor features keep working on `</{expr}>`.
|
|
888
886
|
add_extra_source_mappings_from_matching_expression(
|
|
889
887
|
generated_expression,
|
|
890
|
-
|
|
888
|
+
clone_ast_node(node.closingElement.name.expression),
|
|
891
889
|
);
|
|
892
890
|
}
|
|
893
891
|
|
|
@@ -1298,11 +1296,7 @@ function build_render_statements(
|
|
|
1298
1296
|
render_nodes.push(
|
|
1299
1297
|
b.jsx_expression_container(
|
|
1300
1298
|
set_loc(
|
|
1301
|
-
b.conditional(
|
|
1302
|
-
clone_expression_node(child.test),
|
|
1303
|
-
b.literal(null),
|
|
1304
|
-
stmt.argument,
|
|
1305
|
-
),
|
|
1299
|
+
b.conditional(clone_ast_node(child.test), b.literal(null), stmt.argument),
|
|
1306
1300
|
child,
|
|
1307
1301
|
),
|
|
1308
1302
|
),
|
|
@@ -1385,7 +1379,7 @@ function build_render_statements(
|
|
|
1385
1379
|
if (return_arg === null) {
|
|
1386
1380
|
return_arg = set_loc(
|
|
1387
1381
|
b.jsx_fragment([]),
|
|
1388
|
-
source_authored_fragment
|
|
1382
|
+
has_location(source_authored_fragment) ? source_authored_fragment : undefined,
|
|
1389
1383
|
);
|
|
1390
1384
|
} else if (return_arg.type !== 'JSXFragment') {
|
|
1391
1385
|
return_arg = wrap_lowered_value_in_fragment(return_arg, source_authored_fragment);
|
|
@@ -1587,7 +1581,7 @@ function create_helper_component_element(helper_id, bindings, source_node, mappi
|
|
|
1587
1581
|
const { mapWrapper = true, mapBindingNames = true, mapBindingValues = true } = mapping;
|
|
1588
1582
|
const attributes = bindings.map((binding) =>
|
|
1589
1583
|
b.jsx_attribute(
|
|
1590
|
-
|
|
1584
|
+
identifier_to_jsx_identifier(
|
|
1591
1585
|
mapBindingNames ? clone_identifier(binding) : create_generated_identifier(binding.name),
|
|
1592
1586
|
),
|
|
1593
1587
|
to_jsx_expression_container(
|
|
@@ -1598,7 +1592,7 @@ function create_helper_component_element(helper_id, bindings, source_node, mappi
|
|
|
1598
1592
|
);
|
|
1599
1593
|
|
|
1600
1594
|
const opening_element = b.jsx_opening_element(
|
|
1601
|
-
|
|
1595
|
+
identifier_to_jsx_identifier(clone_identifier(helper_id)),
|
|
1602
1596
|
attributes,
|
|
1603
1597
|
true,
|
|
1604
1598
|
);
|
|
@@ -2356,7 +2350,7 @@ function create_style_expression_value(node, stylesheet, transform_context) {
|
|
|
2356
2350
|
* @param {TransformContext} transform_context
|
|
2357
2351
|
*/
|
|
2358
2352
|
function add_type_only_style_anchor(node, transform_context) {
|
|
2359
|
-
const style_anchor = b.jsx_element(
|
|
2353
|
+
const style_anchor = b.jsx_element(clone_ast_node(node, true), [], []);
|
|
2360
2354
|
disable_style_anchor_verification(style_anchor);
|
|
2361
2355
|
|
|
2362
2356
|
const anchor_id = create_generated_identifier(create_style_anchor_name(transform_context));
|
|
@@ -2476,7 +2470,7 @@ function annotate_tsrx_with_hash(node, hash, jsx_class_attr_name, preserve_style
|
|
|
2476
2470
|
const annotated = { ...node };
|
|
2477
2471
|
annotated.children = (node.children || []).map((/** @type {any} */ statement) =>
|
|
2478
2472
|
annotate_with_hash(
|
|
2479
|
-
|
|
2473
|
+
clone_ast_node(statement),
|
|
2480
2474
|
hash,
|
|
2481
2475
|
jsx_class_attr_name,
|
|
2482
2476
|
preserve_style_elements,
|
|
@@ -2841,7 +2835,11 @@ function node_contains_hook_bearing_tsrx(node, transform_context) {
|
|
|
2841
2835
|
}
|
|
2842
2836
|
|
|
2843
2837
|
if (is_native_tsrx_node(node)) {
|
|
2844
|
-
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
|
+
);
|
|
2845
2843
|
}
|
|
2846
2844
|
|
|
2847
2845
|
if (
|
|
@@ -3244,7 +3242,7 @@ function create_component_return_statement(
|
|
|
3244
3242
|
type_only = false,
|
|
3245
3243
|
) {
|
|
3246
3244
|
const cloned = render_nodes.map((node) =>
|
|
3247
|
-
map_render_node_locations ?
|
|
3245
|
+
map_render_node_locations ? clone_ast_node(node) : clone_ast_node(node, false),
|
|
3248
3246
|
);
|
|
3249
3247
|
|
|
3250
3248
|
return set_loc(
|
|
@@ -3402,7 +3400,7 @@ function prepend_render_nodes_to_return_statement(
|
|
|
3402
3400
|
* @returns {any}
|
|
3403
3401
|
*/
|
|
3404
3402
|
function combine_render_return_argument(render_nodes, return_argument, type_only = false) {
|
|
3405
|
-
const combined = render_nodes.map((node) =>
|
|
3403
|
+
const combined = render_nodes.map((node) => clone_ast_node(node, false));
|
|
3406
3404
|
|
|
3407
3405
|
if (return_argument != null && !is_null_literal(return_argument)) {
|
|
3408
3406
|
combined.push(return_argument_to_render_node(return_argument));
|
|
@@ -3447,7 +3445,7 @@ function is_null_literal(node) {
|
|
|
3447
3445
|
* @returns {{ source_decl: any, source_normalize_decl: any }}
|
|
3448
3446
|
*/
|
|
3449
3447
|
function build_array_normalization_decls(source_id, source_expr) {
|
|
3450
|
-
const source_decl = b.let(clone_identifier(source_id),
|
|
3448
|
+
const source_decl = b.let(clone_identifier(source_id), clone_ast_node(source_expr));
|
|
3451
3449
|
const is_array_call = b.call(b.member(b.id('Array'), 'isArray'), clone_identifier(source_id));
|
|
3452
3450
|
const from_call = b.call(b.member(b.id('Array'), 'from'), clone_identifier(source_id));
|
|
3453
3451
|
const normalized = b.conditional(is_array_call, clone_identifier(source_id), from_call);
|
|
@@ -3493,7 +3491,7 @@ function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
|
3493
3491
|
const use_iterable_helper = !!transform_context.platform.imports.forOfIterableHelper;
|
|
3494
3492
|
const { source_decl, source_normalize_decl } = use_iterable_helper
|
|
3495
3493
|
? {
|
|
3496
|
-
source_decl: b.let(clone_identifier(source_id),
|
|
3494
|
+
source_decl: b.let(clone_identifier(source_id), clone_ast_node(node.right)),
|
|
3497
3495
|
source_normalize_decl: null,
|
|
3498
3496
|
}
|
|
3499
3497
|
: build_array_normalization_decls(source_id, node.right);
|
|
@@ -3595,10 +3593,12 @@ function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
|
3595
3593
|
|
|
3596
3594
|
const body_key_expression = find_key_expression_in_body(original_loop_body);
|
|
3597
3595
|
const explicit_key_expression =
|
|
3598
|
-
body_key_expression ?? (node.key ?
|
|
3596
|
+
body_key_expression ?? (node.key ? clone_ast_node(node.key) : undefined);
|
|
3599
3597
|
const key_expression =
|
|
3600
3598
|
explicit_key_expression ??
|
|
3601
|
-
(loop_params.length >= 2
|
|
3599
|
+
(loop_params.length >= 2
|
|
3600
|
+
? clone_identifier(/** @type {AST.Identifier} */ (loop_params[1]))
|
|
3601
|
+
: undefined);
|
|
3602
3602
|
if (key_expression) {
|
|
3603
3603
|
callback_invocation_element.openingElement.attributes.push(
|
|
3604
3604
|
b.jsx_attribute(b.jsx_id('key'), to_jsx_expression_container(key_expression, key_expression)),
|
|
@@ -3808,9 +3808,9 @@ function to_jsx_element(
|
|
|
3808
3808
|
}
|
|
3809
3809
|
|
|
3810
3810
|
/**
|
|
3811
|
-
* @param {
|
|
3811
|
+
* @param {AST.Node[]} children
|
|
3812
3812
|
* @param {TransformContext} transform_context
|
|
3813
|
-
* @returns {
|
|
3813
|
+
* @returns {ESTreeJSX.JSXElement['children']}
|
|
3814
3814
|
*/
|
|
3815
3815
|
|
|
3816
3816
|
function create_element_children(children, transform_context) {
|
|
@@ -3822,9 +3822,7 @@ function create_element_children(children, transform_context) {
|
|
|
3822
3822
|
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3823
3823
|
transform_context.inside_element_child = true;
|
|
3824
3824
|
try {
|
|
3825
|
-
return wrap_edge_whitespace(
|
|
3826
|
-
children.map((/** @type {any} */ child) => to_jsx_child(child, transform_context)),
|
|
3827
|
-
);
|
|
3825
|
+
return wrap_edge_whitespace(children.map((child) => to_jsx_child(child, transform_context)));
|
|
3828
3826
|
} finally {
|
|
3829
3827
|
transform_context.inside_element_child = saved_inside_element_child;
|
|
3830
3828
|
}
|
|
@@ -3840,7 +3838,7 @@ function create_element_children(children, transform_context) {
|
|
|
3840
3838
|
}
|
|
3841
3839
|
|
|
3842
3840
|
/**
|
|
3843
|
-
* @param {
|
|
3841
|
+
* @param {AST.Node[]} children
|
|
3844
3842
|
* @returns {boolean}
|
|
3845
3843
|
*/
|
|
3846
3844
|
function children_contain_return_semantics(children) {
|
|
@@ -3848,35 +3846,35 @@ function children_contain_return_semantics(children) {
|
|
|
3848
3846
|
}
|
|
3849
3847
|
|
|
3850
3848
|
/**
|
|
3851
|
-
* @param {
|
|
3849
|
+
* @param {unknown} node
|
|
3852
3850
|
* @returns {boolean}
|
|
3853
3851
|
*/
|
|
3854
3852
|
function child_contains_return_semantics(node) {
|
|
3853
|
+
if (Array.isArray(node)) {
|
|
3854
|
+
return node.some(child_contains_return_semantics);
|
|
3855
|
+
}
|
|
3855
3856
|
if (!node || typeof node !== 'object') {
|
|
3856
3857
|
return false;
|
|
3857
3858
|
}
|
|
3859
|
+
const ast_node = /** @type {Record<string, unknown>} */ (node);
|
|
3858
3860
|
|
|
3859
|
-
if (
|
|
3861
|
+
if (ast_node.type === 'ReturnStatement') {
|
|
3860
3862
|
return true;
|
|
3861
3863
|
}
|
|
3862
3864
|
|
|
3863
3865
|
if (
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3866
|
+
ast_node.type === 'FunctionDeclaration' ||
|
|
3867
|
+
ast_node.type === 'FunctionExpression' ||
|
|
3868
|
+
ast_node.type === 'ArrowFunctionExpression'
|
|
3867
3869
|
) {
|
|
3868
3870
|
return false;
|
|
3869
3871
|
}
|
|
3870
3872
|
|
|
3871
|
-
|
|
3872
|
-
return node.some(child_contains_return_semantics);
|
|
3873
|
-
}
|
|
3874
|
-
|
|
3875
|
-
for (const key of Object.keys(node)) {
|
|
3873
|
+
for (const key of Object.keys(ast_node)) {
|
|
3876
3874
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3877
3875
|
continue;
|
|
3878
3876
|
}
|
|
3879
|
-
if (child_contains_return_semantics(
|
|
3877
|
+
if (child_contains_return_semantics(ast_node[key])) {
|
|
3880
3878
|
return true;
|
|
3881
3879
|
}
|
|
3882
3880
|
}
|
|
@@ -3885,11 +3883,11 @@ function child_contains_return_semantics(node) {
|
|
|
3885
3883
|
}
|
|
3886
3884
|
|
|
3887
3885
|
/**
|
|
3888
|
-
* @param {
|
|
3889
|
-
* @returns {
|
|
3886
|
+
* @param {AST.Node | null | undefined} node
|
|
3887
|
+
* @returns {node is AST.TSRXRenderChild}
|
|
3890
3888
|
*/
|
|
3891
3889
|
function is_inline_element_child(node) {
|
|
3892
|
-
return node && is_render_child_node(node);
|
|
3890
|
+
return !!node && is_render_child_node(node);
|
|
3893
3891
|
}
|
|
3894
3892
|
|
|
3895
3893
|
/**
|
|
@@ -4252,7 +4250,7 @@ function get_body_source_node(body_nodes) {
|
|
|
4252
4250
|
const first = body_nodes[0];
|
|
4253
4251
|
const last = body_nodes[body_nodes.length - 1];
|
|
4254
4252
|
|
|
4255
|
-
if (first
|
|
4253
|
+
if (has_location(first) && has_location(last)) {
|
|
4256
4254
|
return {
|
|
4257
4255
|
start: first.start,
|
|
4258
4256
|
end: last.end,
|
|
@@ -4307,8 +4305,8 @@ function get_raw_jsx_code_block_body_nodes(node) {
|
|
|
4307
4305
|
}
|
|
4308
4306
|
|
|
4309
4307
|
/**
|
|
4310
|
-
* @param {
|
|
4311
|
-
* @returns {
|
|
4308
|
+
* @param {AST.Node | null | undefined} node
|
|
4309
|
+
* @returns {node is AST.NativeTSRXNode}
|
|
4312
4310
|
*/
|
|
4313
4311
|
function is_native_tsrx_node(node) {
|
|
4314
4312
|
return (
|
|
@@ -4316,21 +4314,21 @@ function is_native_tsrx_node(node) {
|
|
|
4316
4314
|
((node?.type === 'JSXElement' ||
|
|
4317
4315
|
node?.type === 'JSXFragment' ||
|
|
4318
4316
|
node?.type === 'JSXStyleElement') &&
|
|
4319
|
-
node.metadata?.native_tsrx)
|
|
4317
|
+
!!node.metadata?.native_tsrx)
|
|
4320
4318
|
);
|
|
4321
4319
|
}
|
|
4322
4320
|
|
|
4323
4321
|
/**
|
|
4324
|
-
* @param {
|
|
4325
|
-
* @returns {
|
|
4322
|
+
* @param {AST.Node | null | undefined} node
|
|
4323
|
+
* @returns {node is AST.IfStatement | AST.JSXIfExpression}
|
|
4326
4324
|
*/
|
|
4327
4325
|
function is_if_control_node(node) {
|
|
4328
4326
|
return node?.type === 'IfStatement' || node?.type === 'JSXIfExpression';
|
|
4329
4327
|
}
|
|
4330
4328
|
|
|
4331
4329
|
/**
|
|
4332
|
-
* @param {
|
|
4333
|
-
* @returns {
|
|
4330
|
+
* @param {AST.Node | null | undefined} node
|
|
4331
|
+
* @returns {node is AST.TSRXRenderChild}
|
|
4334
4332
|
*/
|
|
4335
4333
|
function is_render_child_node(node) {
|
|
4336
4334
|
if (!node) return false;
|
|
@@ -4383,8 +4381,25 @@ function is_try_control_node(node) {
|
|
|
4383
4381
|
* are pulled out; whitespace runs containing a newline are layout indentation and
|
|
4384
4382
|
* are left for the host compiler to collapse.
|
|
4385
4383
|
*
|
|
4386
|
-
|
|
4387
|
-
|
|
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[]}
|
|
4388
4403
|
*/
|
|
4389
4404
|
export function wrap_edge_whitespace(nodes) {
|
|
4390
4405
|
const length = nodes.length;
|
|
@@ -4398,7 +4413,7 @@ export function wrap_edge_whitespace(nodes) {
|
|
|
4398
4413
|
return nodes;
|
|
4399
4414
|
}
|
|
4400
4415
|
|
|
4401
|
-
/** @type {
|
|
4416
|
+
/** @type {ESTreeJSX.JSXTransformChild[]} */
|
|
4402
4417
|
const out = [];
|
|
4403
4418
|
for (let i = 0; i < length; i++) {
|
|
4404
4419
|
const node = nodes[i];
|
|
@@ -4428,7 +4443,7 @@ export function wrap_edge_whitespace(nodes) {
|
|
|
4428
4443
|
if (value !== '') {
|
|
4429
4444
|
// keep the location as we need it for @ autocomplete
|
|
4430
4445
|
// and perhaps other things in the future
|
|
4431
|
-
out.push(b.jsx_text(value, value, node));
|
|
4446
|
+
out.push(b.jsx_text(value, value, has_location(node) ? node : undefined));
|
|
4432
4447
|
}
|
|
4433
4448
|
if (trailing) {
|
|
4434
4449
|
out.push(trailing);
|
|
@@ -4438,9 +4453,21 @@ export function wrap_edge_whitespace(nodes) {
|
|
|
4438
4453
|
}
|
|
4439
4454
|
|
|
4440
4455
|
/**
|
|
4441
|
-
* @
|
|
4456
|
+
* @overload
|
|
4457
|
+
* @param {AST.TSRXRenderChild} node
|
|
4442
4458
|
* @param {TransformContext} transform_context
|
|
4443
|
-
* @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}
|
|
4444
4471
|
*/
|
|
4445
4472
|
function to_jsx_child(node, transform_context) {
|
|
4446
4473
|
if (!node) return node;
|
|
@@ -4514,25 +4541,25 @@ function to_jsx_child(node, transform_context) {
|
|
|
4514
4541
|
* Children have already been parsed and transformed through the normal TSRX
|
|
4515
4542
|
* JSX element/text/control-flow visitors.
|
|
4516
4543
|
*
|
|
4517
|
-
* @param {
|
|
4544
|
+
* @param {AST.TSRXJSXElement | AST.TSRXJSXFragment} node
|
|
4518
4545
|
* @param {TransformContext} transform_context
|
|
4519
4546
|
* @param {boolean} [in_jsx_child]
|
|
4520
|
-
* @returns {
|
|
4547
|
+
* @returns {AST.Expression | ESTreeJSX.JSXExpressionContainer}
|
|
4521
4548
|
*/
|
|
4522
4549
|
function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = false) {
|
|
4523
4550
|
const children = (node.children || []).filter(
|
|
4524
|
-
(
|
|
4551
|
+
(child) =>
|
|
4525
4552
|
child && child.type !== 'EmptyStatement' && (child.type !== 'JSXText' || child.value !== ''),
|
|
4526
4553
|
);
|
|
4527
4554
|
|
|
4528
|
-
/** @type {
|
|
4529
|
-
let expression;
|
|
4555
|
+
/** @type {AST.Expression | null} */
|
|
4556
|
+
let expression = null;
|
|
4530
4557
|
if (children.length === 0) {
|
|
4531
4558
|
// An empty fragment is a real value: keep it as `<></>` in BOTH child and
|
|
4532
4559
|
// expression position. Lowering it to a bare `null` in expression position
|
|
4533
4560
|
// (e.g. `let b = <></>`) drops the author's fragment and changes its type;
|
|
4534
4561
|
// `<></>` is a valid value and keeps the to_ts/runtime view faithful.
|
|
4535
|
-
expression = set_loc(b.jsx_fragment([]), node
|
|
4562
|
+
expression = set_loc(b.jsx_fragment([]), has_location(node) ? node : undefined);
|
|
4536
4563
|
} else if (
|
|
4537
4564
|
children.length === 1 &&
|
|
4538
4565
|
(is_empty_jsx_fragment(children[0]) ||
|
|
@@ -4543,7 +4570,7 @@ function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = fal
|
|
|
4543
4570
|
// dropping the outer fragment the author wrote. Keep both levels. (`<><></></>`
|
|
4544
4571
|
// is kept regardless; a non-empty inner is only kept for an authored outer, so
|
|
4545
4572
|
// a generated wrapper still collapses.)
|
|
4546
|
-
expression = set_loc(b.jsx_fragment(children), node
|
|
4573
|
+
expression = set_loc(b.jsx_fragment(children), has_location(node) ? node : undefined);
|
|
4547
4574
|
} else {
|
|
4548
4575
|
expression = return_value_body_to_expression(children, node, transform_context);
|
|
4549
4576
|
}
|
|
@@ -4554,7 +4581,7 @@ function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = fal
|
|
|
4554
4581
|
transform_context.inside_element_child = true;
|
|
4555
4582
|
try {
|
|
4556
4583
|
const render_nodes = wrap_edge_whitespace(
|
|
4557
|
-
children.map((
|
|
4584
|
+
children.map((child) => to_jsx_child(child, transform_context)),
|
|
4558
4585
|
);
|
|
4559
4586
|
expression =
|
|
4560
4587
|
build_return_expression(render_nodes, in_jsx_child, transform_context.typeOnly) ||
|
|
@@ -4567,13 +4594,7 @@ function tsrx_node_to_jsx_expression(node, transform_context, in_jsx_child = fal
|
|
|
4567
4594
|
}
|
|
4568
4595
|
}
|
|
4569
4596
|
|
|
4570
|
-
if (
|
|
4571
|
-
in_jsx_child &&
|
|
4572
|
-
expression.type !== 'JSXElement' &&
|
|
4573
|
-
expression.type !== 'JSXFragment' &&
|
|
4574
|
-
expression.type !== 'JSXText' &&
|
|
4575
|
-
expression.type !== 'JSXExpressionContainer'
|
|
4576
|
-
) {
|
|
4597
|
+
if (in_jsx_child && expression.type !== 'JSXElement' && expression.type !== 'JSXFragment') {
|
|
4577
4598
|
return to_jsx_expression_container(expression, node);
|
|
4578
4599
|
}
|
|
4579
4600
|
|
|
@@ -4669,14 +4690,14 @@ function create_statement_iife(body_nodes, source_node, transform_context) {
|
|
|
4669
4690
|
}
|
|
4670
4691
|
|
|
4671
4692
|
/**
|
|
4672
|
-
* @param {
|
|
4673
|
-
* @param {
|
|
4693
|
+
* @param {AST.Expression} node
|
|
4694
|
+
* @param {AST.Node | null | undefined} source_node
|
|
4674
4695
|
* @param {TransformContext} [transform_context]
|
|
4675
|
-
* @returns {
|
|
4696
|
+
* @returns {AST.Expression}
|
|
4676
4697
|
*/
|
|
4677
4698
|
function set_generated_expression_loc(node, source_node, transform_context) {
|
|
4678
|
-
if (transform_context?.typeOnly || !source_node
|
|
4679
|
-
return setLocation(
|
|
4699
|
+
if (transform_context?.typeOnly || !has_location(source_node)) return node;
|
|
4700
|
+
return setLocation(node, source_node);
|
|
4680
4701
|
}
|
|
4681
4702
|
|
|
4682
4703
|
/**
|
|
@@ -5046,17 +5067,17 @@ function for_of_statement_to_jsx_child(node, transform_context) {
|
|
|
5046
5067
|
body_contains_top_level_hook_call(loop_body, transform_context, true);
|
|
5047
5068
|
const body_key_expression = find_key_expression_in_body(loop_body);
|
|
5048
5069
|
const explicit_key_expression =
|
|
5049
|
-
body_key_expression ?? (node.key ?
|
|
5070
|
+
body_key_expression ?? (node.key ? clone_ast_node(node.key) : undefined);
|
|
5050
5071
|
const key_expression =
|
|
5051
5072
|
has_hooks && explicit_key_expression == null && node.index
|
|
5052
|
-
?
|
|
5073
|
+
? clone_ast_node(node.index)
|
|
5053
5074
|
: explicit_key_expression;
|
|
5054
5075
|
const implicit_non_hook_key_expression =
|
|
5055
5076
|
!has_hooks && body_key_expression == null
|
|
5056
5077
|
? node.key
|
|
5057
|
-
?
|
|
5078
|
+
? clone_ast_node(node.key)
|
|
5058
5079
|
: node.index
|
|
5059
|
-
?
|
|
5080
|
+
? clone_ast_node(node.index)
|
|
5060
5081
|
: undefined
|
|
5061
5082
|
: undefined;
|
|
5062
5083
|
|
|
@@ -5132,7 +5153,7 @@ function for_of_statement_to_jsx_child(node, transform_context) {
|
|
|
5132
5153
|
b.conditional(
|
|
5133
5154
|
b.binary(
|
|
5134
5155
|
'===',
|
|
5135
|
-
b.member(
|
|
5156
|
+
b.member(clone_ast_node(node.right), create_generated_identifier('length')),
|
|
5136
5157
|
b.literal(0),
|
|
5137
5158
|
),
|
|
5138
5159
|
empty_fallback,
|
|
@@ -5173,7 +5194,7 @@ function apply_key_to_loop_body(body_nodes, key_expression) {
|
|
|
5173
5194
|
...attributes,
|
|
5174
5195
|
b.jsx_attribute(
|
|
5175
5196
|
b.jsx_id('key'),
|
|
5176
|
-
to_jsx_expression_container(
|
|
5197
|
+
to_jsx_expression_container(clone_ast_node(key_expression), key_expression),
|
|
5177
5198
|
),
|
|
5178
5199
|
],
|
|
5179
5200
|
},
|
|
@@ -5254,7 +5275,7 @@ function apply_key_to_jsx_element(element, key_expression) {
|
|
|
5254
5275
|
...attributes,
|
|
5255
5276
|
b.jsx_attribute(
|
|
5256
5277
|
b.jsx_id('key'),
|
|
5257
|
-
to_jsx_expression_container(
|
|
5278
|
+
to_jsx_expression_container(clone_ast_node(key_expression), key_expression),
|
|
5258
5279
|
),
|
|
5259
5280
|
],
|
|
5260
5281
|
},
|
|
@@ -5270,7 +5291,7 @@ function keyed_fragment_to_jsx_element(fragment, key_expression) {
|
|
|
5270
5291
|
const name = b.jsx_id('Fragment');
|
|
5271
5292
|
const key_attribute = b.jsx_attribute(
|
|
5272
5293
|
b.jsx_id('key'),
|
|
5273
|
-
to_jsx_expression_container(
|
|
5294
|
+
to_jsx_expression_container(clone_ast_node(key_expression), key_expression),
|
|
5274
5295
|
);
|
|
5275
5296
|
|
|
5276
5297
|
return b.jsx_element_fresh(
|
|
@@ -5476,9 +5497,9 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5476
5497
|
* Create a simple JSX element AST node.
|
|
5477
5498
|
*
|
|
5478
5499
|
* @param {string} tag_name
|
|
5479
|
-
* @param {
|
|
5480
|
-
* @param {
|
|
5481
|
-
* @returns {
|
|
5500
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} attributes
|
|
5501
|
+
* @param {ESTreeJSX.JSXElement['children']} children
|
|
5502
|
+
* @returns {ESTreeJSX.JSXElement}
|
|
5482
5503
|
*/
|
|
5483
5504
|
function create_jsx_element(tag_name, attributes, children) {
|
|
5484
5505
|
const self_closing = children.length === 0;
|
|
@@ -5496,12 +5517,12 @@ function create_jsx_element(tag_name, attributes, children) {
|
|
|
5496
5517
|
*
|
|
5497
5518
|
* @param {AST.Program} program
|
|
5498
5519
|
* @param {TransformContext} transform_context
|
|
5499
|
-
* @param {JsxPlatform} platform
|
|
5520
|
+
* @param {Pick<JsxPlatform, 'imports'>} platform
|
|
5500
5521
|
* @param {string} suspense_source - effective suspense import source after
|
|
5501
5522
|
* applying any per-call override from JsxTransformOptions.suspenseSource.
|
|
5502
5523
|
*/
|
|
5503
5524
|
function inject_try_imports(program, transform_context, platform, suspense_source) {
|
|
5504
|
-
/** @type {
|
|
5525
|
+
/** @type {AST.ImportDeclaration[]} */
|
|
5505
5526
|
const imports = [];
|
|
5506
5527
|
|
|
5507
5528
|
if (transform_context.needs_fragment && platform.imports.fragment) {
|
|
@@ -5543,7 +5564,7 @@ function inject_try_imports(program, transform_context, platform, suspense_sourc
|
|
|
5543
5564
|
? platform.imports.refProp
|
|
5544
5565
|
: null;
|
|
5545
5566
|
|
|
5546
|
-
/** @type {Map<string,
|
|
5567
|
+
/** @type {Map<string, AST.ImportSpecifier[]>} */
|
|
5547
5568
|
const ref_imports = new Map();
|
|
5548
5569
|
|
|
5549
5570
|
if (merge_refs_source !== null) {
|
|
@@ -5583,9 +5604,9 @@ function inject_try_imports(program, transform_context, platform, suspense_sourc
|
|
|
5583
5604
|
}
|
|
5584
5605
|
|
|
5585
5606
|
/**
|
|
5586
|
-
* @param {Map<string,
|
|
5607
|
+
* @param {Map<string, AST.ImportSpecifier[]>} imports
|
|
5587
5608
|
* @param {string} source
|
|
5588
|
-
* @param {
|
|
5609
|
+
* @param {AST.ImportSpecifier} specifier
|
|
5589
5610
|
*/
|
|
5590
5611
|
function add_ref_import_specifier(imports, source, specifier) {
|
|
5591
5612
|
const specifiers = imports.get(source);
|
|
@@ -5597,9 +5618,9 @@ function add_ref_import_specifier(imports, source, specifier) {
|
|
|
5597
5618
|
}
|
|
5598
5619
|
|
|
5599
5620
|
/**
|
|
5600
|
-
* @param {
|
|
5621
|
+
* @param {AST.IfStatement | AST.JSXIfExpression} node
|
|
5601
5622
|
* @param {TransformContext} transform_context
|
|
5602
|
-
* @returns {
|
|
5623
|
+
* @returns {AST.IfStatement}
|
|
5603
5624
|
*/
|
|
5604
5625
|
function create_render_if_statement(node, transform_context) {
|
|
5605
5626
|
const consequent_body =
|
|
@@ -5616,7 +5637,8 @@ function create_render_if_statement(node, transform_context) {
|
|
|
5616
5637
|
if (is_if_control_node(node.alternate)) {
|
|
5617
5638
|
alternate = create_render_if_statement(node.alternate, transform_context);
|
|
5618
5639
|
} else {
|
|
5619
|
-
const alternate_body =
|
|
5640
|
+
const alternate_body =
|
|
5641
|
+
node.alternate.type === 'BlockStatement' ? node.alternate.body : [node.alternate];
|
|
5620
5642
|
if (is_template_if_node(node)) {
|
|
5621
5643
|
validate_if_body_control_flow(alternate_body, transform_context);
|
|
5622
5644
|
}
|
|
@@ -5659,8 +5681,8 @@ function create_render_if_statement(node, transform_context) {
|
|
|
5659
5681
|
* `own_body` is the case's isolated consequent. JSX `@switch` cases do not
|
|
5660
5682
|
* fall through, so `break` is not part of the template switch model.
|
|
5661
5683
|
*
|
|
5662
|
-
* @param {
|
|
5663
|
-
* @returns {{ own_body:
|
|
5684
|
+
* @param {AST.Statement[]} consequent
|
|
5685
|
+
* @returns {{ own_body: AST.Statement[], has_terminator: boolean }}
|
|
5664
5686
|
*/
|
|
5665
5687
|
function summarize_switch_case_body(consequent) {
|
|
5666
5688
|
const own_body = [];
|
|
@@ -5690,10 +5712,10 @@ function summarize_switch_case_body(consequent) {
|
|
|
5690
5712
|
* see double/triple hits per source range.
|
|
5691
5713
|
*
|
|
5692
5714
|
* @param {{ component_element: ESTreeJSX.JSXElement }} helper
|
|
5693
|
-
* @returns {
|
|
5715
|
+
* @returns {ESTreeJSX.JSXElement}
|
|
5694
5716
|
*/
|
|
5695
5717
|
export function clone_switch_helper_invocation(helper) {
|
|
5696
|
-
return
|
|
5718
|
+
return clone_ast_node(helper.component_element, false);
|
|
5697
5719
|
}
|
|
5698
5720
|
|
|
5699
5721
|
/**
|
|
@@ -5710,31 +5732,29 @@ export function clone_switch_helper_invocation(helper) {
|
|
|
5710
5732
|
* React, Vue, and Solid) already pushed their declarations into
|
|
5711
5733
|
* `transform_context.helper_state.helpers`, so `setup_statements` is empty.
|
|
5712
5734
|
*
|
|
5713
|
-
* @param {
|
|
5735
|
+
* @param {AST.SwitchStatement} switch_node
|
|
5714
5736
|
* @param {TransformContext} transform_context
|
|
5715
5737
|
* @returns {{
|
|
5716
|
-
* case_info: Array<{ own_body:
|
|
5717
|
-
* case_helpers: Array<
|
|
5718
|
-
* setup_statements:
|
|
5738
|
+
* case_info: Array<{ own_body: AST.Statement[], has_terminator: boolean }>,
|
|
5739
|
+
* case_helpers: Array<JsxHelperComponent | null>,
|
|
5740
|
+
* setup_statements: AST.Statement[],
|
|
5719
5741
|
* }}
|
|
5720
5742
|
*/
|
|
5721
5743
|
export function plan_switch_lift(switch_node, transform_context) {
|
|
5722
|
-
const case_info = switch_node.cases.map((
|
|
5744
|
+
const case_info = switch_node.cases.map((c) => {
|
|
5723
5745
|
const consequent = flatten_switch_consequent(c.consequent || []);
|
|
5724
5746
|
return summarize_switch_case_body(consequent);
|
|
5725
5747
|
});
|
|
5726
5748
|
|
|
5727
5749
|
// A case body needs to be lifted iff it contains hooks. Cases are isolated,
|
|
5728
5750
|
// so downstream case bodies are never duplicated into earlier arms.
|
|
5729
|
-
const needs_helper = case_info.map(
|
|
5730
|
-
(
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
},
|
|
5737
|
-
);
|
|
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
|
+
});
|
|
5738
5758
|
|
|
5739
5759
|
// Pre-allocate helper ids in source order so the snapshot's
|
|
5740
5760
|
// `StatementBodyHook<N>` numbering reads top-to-bottom by case position
|
|
@@ -5746,7 +5766,7 @@ export function plan_switch_lift(switch_node, transform_context) {
|
|
|
5746
5766
|
: null,
|
|
5747
5767
|
);
|
|
5748
5768
|
|
|
5749
|
-
/** @type {Array<
|
|
5769
|
+
/** @type {Array<JsxHelperComponent | null>} */
|
|
5750
5770
|
const case_helpers = new Array(switch_node.cases.length).fill(null);
|
|
5751
5771
|
|
|
5752
5772
|
for (let i = switch_node.cases.length - 1; i >= 0; i--) {
|
|
@@ -5758,12 +5778,13 @@ export function plan_switch_lift(switch_node, transform_context) {
|
|
|
5758
5778
|
undefined,
|
|
5759
5779
|
switch_node.cases[i],
|
|
5760
5780
|
transform_context,
|
|
5761
|
-
/** @type {
|
|
5781
|
+
/** @type {AST.Identifier} */ (helper_ids[i]),
|
|
5762
5782
|
);
|
|
5763
5783
|
}
|
|
5764
5784
|
|
|
5765
5785
|
// Hoist all helpers' setup statements above the switch in source order so
|
|
5766
5786
|
// the switch body stays a pure dispatcher.
|
|
5787
|
+
/** @type {AST.Statement[]} */
|
|
5767
5788
|
const setup_statements = [];
|
|
5768
5789
|
for (const helper of case_helpers) {
|
|
5769
5790
|
if (helper) setup_statements.push(...helper.setup_statements);
|
|
@@ -5777,9 +5798,9 @@ export function plan_switch_lift(switch_node, transform_context) {
|
|
|
5777
5798
|
}
|
|
5778
5799
|
|
|
5779
5800
|
/**
|
|
5780
|
-
* @param {
|
|
5801
|
+
* @param {AST.SwitchStatement} switch_node
|
|
5781
5802
|
* @param {TransformContext} transform_context
|
|
5782
|
-
* @returns {{ setup_statements:
|
|
5803
|
+
* @returns {{ setup_statements: AST.Statement[], switch_statement: AST.SwitchStatement }}
|
|
5783
5804
|
*/
|
|
5784
5805
|
function build_switch_with_lift(switch_node, transform_context) {
|
|
5785
5806
|
const { case_info, case_helpers, setup_statements } = plan_switch_lift(
|
|
@@ -5787,92 +5808,95 @@ function build_switch_with_lift(switch_node, transform_context) {
|
|
|
5787
5808
|
transform_context,
|
|
5788
5809
|
);
|
|
5789
5810
|
|
|
5790
|
-
const new_cases = switch_node.cases.map(
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
}
|
|
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
|
+
}
|
|
5806
5826
|
|
|
5807
|
-
|
|
5827
|
+
const { own_body, has_terminator } = case_info[i];
|
|
5808
5828
|
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
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),
|
|
5813
5846
|
);
|
|
5847
|
+
has_terminal = true;
|
|
5848
|
+
break;
|
|
5814
5849
|
}
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
has_terminal = true;
|
|
5831
|
-
break;
|
|
5832
|
-
}
|
|
5833
|
-
if (child.type === 'ReturnStatement') {
|
|
5834
|
-
case_body.push(child);
|
|
5835
|
-
has_terminal = true;
|
|
5836
|
-
break;
|
|
5837
|
-
}
|
|
5838
|
-
if (is_render_child_node(child)) {
|
|
5839
|
-
render_nodes.push(to_jsx_child(child, transform_context));
|
|
5840
|
-
} else if (is_bare_render_expression(child)) {
|
|
5841
|
-
render_nodes.push(to_jsx_expression_container(child, child));
|
|
5842
|
-
} else {
|
|
5843
|
-
case_body.push(child);
|
|
5844
|
-
}
|
|
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);
|
|
5845
5865
|
}
|
|
5866
|
+
}
|
|
5846
5867
|
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
}
|
|
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());
|
|
5862
5882
|
}
|
|
5883
|
+
}
|
|
5863
5884
|
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
);
|
|
5885
|
+
return set_loc(b.switch_case(original_case.test, case_body), original_case);
|
|
5886
|
+
});
|
|
5867
5887
|
|
|
5868
5888
|
return {
|
|
5869
5889
|
setup_statements,
|
|
5870
|
-
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
|
+
),
|
|
5871
5895
|
};
|
|
5872
5896
|
}
|
|
5873
5897
|
|
|
5874
5898
|
/**
|
|
5875
|
-
* @returns {
|
|
5899
|
+
* @returns {AST.ReturnStatement}
|
|
5876
5900
|
*/
|
|
5877
5901
|
function create_null_return_statement() {
|
|
5878
5902
|
return b.return(b.literal(null));
|
|
@@ -5880,25 +5904,25 @@ function create_null_return_statement() {
|
|
|
5880
5904
|
|
|
5881
5905
|
/**
|
|
5882
5906
|
* @param {AST.Expression} expression
|
|
5883
|
-
* @param {
|
|
5907
|
+
* @param {AST.Node} [source_node]
|
|
5884
5908
|
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
5885
5909
|
*/
|
|
5886
5910
|
function to_jsx_expression_container(expression, source_node = expression) {
|
|
5887
5911
|
// NOTE: JSXExpressionContainer nodes are intentionally created without loc.
|
|
5888
5912
|
// They are synthetic wrappers whose source positions do not correspond to
|
|
5889
5913
|
// entries in the generated source map, so adding loc causes Volar mapping failures.
|
|
5890
|
-
return
|
|
5914
|
+
return {
|
|
5891
5915
|
type: 'JSXExpressionContainer',
|
|
5892
|
-
expression
|
|
5916
|
+
expression,
|
|
5893
5917
|
metadata: { path: [] },
|
|
5894
|
-
}
|
|
5918
|
+
};
|
|
5895
5919
|
}
|
|
5896
5920
|
|
|
5897
5921
|
/**
|
|
5898
|
-
* Dispatch point for element attribute transformation. Platforms can
|
|
5899
|
-
* the
|
|
5900
|
-
*
|
|
5901
|
-
*
|
|
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
|
|
5902
5926
|
* `multiRefStrategy` can compose an explicit `ref={...}` with compiler-
|
|
5903
5927
|
* synthesized refs created for host spreads.
|
|
5904
5928
|
*
|
|
@@ -5907,10 +5931,10 @@ function to_jsx_expression_container(expression, source_node = expression) {
|
|
|
5907
5931
|
* duplicate JSX props which the JSX runtime collapses to last-wins (and
|
|
5908
5932
|
* which TypeScript can't type cleanly).
|
|
5909
5933
|
*
|
|
5910
|
-
* @param {
|
|
5934
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} attrs
|
|
5911
5935
|
* @param {TransformContext} transform_context
|
|
5912
|
-
* @param {
|
|
5913
|
-
* @returns {
|
|
5936
|
+
* @param {AST.TSRXJSXElement} element
|
|
5937
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
5914
5938
|
*/
|
|
5915
5939
|
function transform_element_attributes_dispatch(attrs, transform_context, element) {
|
|
5916
5940
|
validate_at_most_one_ref_attribute(attrs, transform_context);
|
|
@@ -5920,9 +5944,7 @@ function transform_element_attributes_dispatch(attrs, transform_context, element
|
|
|
5920
5944
|
attrs = preprocess(attrs, transform_context, element);
|
|
5921
5945
|
}
|
|
5922
5946
|
const hook = transform_context.platform.hooks?.transformElementAttributes;
|
|
5923
|
-
const result = hook
|
|
5924
|
-
? hook(attrs, transform_context, element)
|
|
5925
|
-
: attrs.map((/** @type {any} */ a) => to_jsx_attribute(a, transform_context));
|
|
5947
|
+
const result = hook ? hook(attrs, transform_context, element) : attrs;
|
|
5926
5948
|
return merge_duplicate_refs(
|
|
5927
5949
|
normalize_host_ref_spreads(result, !is_component, transform_context),
|
|
5928
5950
|
transform_context,
|
|
@@ -5930,7 +5952,7 @@ function transform_element_attributes_dispatch(attrs, transform_context, element
|
|
|
5930
5952
|
}
|
|
5931
5953
|
|
|
5932
5954
|
/**
|
|
5933
|
-
* @param {
|
|
5955
|
+
* @param {AST.TSRXJSXElement | ESTreeJSX.JSXElement} element
|
|
5934
5956
|
* @returns {boolean}
|
|
5935
5957
|
*/
|
|
5936
5958
|
export function is_component_like_element(element) {
|
|
@@ -5944,7 +5966,7 @@ export function is_component_like_element(element) {
|
|
|
5944
5966
|
}
|
|
5945
5967
|
|
|
5946
5968
|
/**
|
|
5947
|
-
* @param {
|
|
5969
|
+
* @param {ESTreeJSX.TSRXJSXOpeningElement['name']} name
|
|
5948
5970
|
* @returns {boolean}
|
|
5949
5971
|
*/
|
|
5950
5972
|
function is_component_like_jsx_name(name) {
|
|
@@ -5955,10 +5977,10 @@ function is_component_like_jsx_name(name) {
|
|
|
5955
5977
|
}
|
|
5956
5978
|
|
|
5957
5979
|
/**
|
|
5958
|
-
* @param {
|
|
5980
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} attrs
|
|
5959
5981
|
* @param {boolean} is_host
|
|
5960
5982
|
* @param {TransformContext} transform_context
|
|
5961
|
-
* @returns {
|
|
5983
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
5962
5984
|
*/
|
|
5963
5985
|
function normalize_host_ref_spreads(attrs, is_host, transform_context) {
|
|
5964
5986
|
if (!is_host) return attrs;
|
|
@@ -5970,49 +5992,55 @@ function normalize_host_ref_spreads(attrs, is_host, transform_context) {
|
|
|
5970
5992
|
.map((attr) => attr.value.expression);
|
|
5971
5993
|
const needs_synthetic_spread_ref = needs_explicit_spread_ref || ref_exprs.length > 0;
|
|
5972
5994
|
|
|
5973
|
-
return attrs.flatMap(
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
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
|
+
}
|
|
5977
6004
|
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
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);
|
|
5987
6014
|
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
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));
|
|
6005
6032
|
|
|
6006
|
-
|
|
6007
|
-
|
|
6033
|
+
return [spread, ref_attr];
|
|
6034
|
+
}
|
|
6008
6035
|
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6036
|
+
return [
|
|
6037
|
+
{
|
|
6038
|
+
...attr,
|
|
6039
|
+
argument: normalized,
|
|
6040
|
+
},
|
|
6041
|
+
];
|
|
6042
|
+
},
|
|
6043
|
+
);
|
|
6016
6044
|
}
|
|
6017
6045
|
|
|
6018
6046
|
/**
|
|
@@ -6029,8 +6057,8 @@ function create_spread_props_name(transform_context) {
|
|
|
6029
6057
|
}
|
|
6030
6058
|
|
|
6031
6059
|
/**
|
|
6032
|
-
* @param {
|
|
6033
|
-
* @param {
|
|
6060
|
+
* @param {AST.Node} node
|
|
6061
|
+
* @param {AST.Statement} declaration
|
|
6034
6062
|
*/
|
|
6035
6063
|
export function add_jsx_setup_declaration(node, declaration) {
|
|
6036
6064
|
node.metadata ??= { path: [] };
|
|
@@ -6038,29 +6066,40 @@ export function add_jsx_setup_declaration(node, declaration) {
|
|
|
6038
6066
|
}
|
|
6039
6067
|
|
|
6040
6068
|
/**
|
|
6041
|
-
* @param {
|
|
6042
|
-
* @param {Set<
|
|
6043
|
-
* @returns {
|
|
6069
|
+
* @param {AST.Node} node
|
|
6070
|
+
* @param {Set<object>} [seen]
|
|
6071
|
+
* @returns {AST.Statement[]}
|
|
6044
6072
|
*/
|
|
6045
6073
|
export function extract_jsx_setup_declarations(node, seen = new Set()) {
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6074
|
+
/** @type {AST.Statement[]} */
|
|
6075
|
+
const declarations = [];
|
|
6076
|
+
collect_jsx_setup_declarations(node, seen, declarations);
|
|
6077
|
+
return declarations;
|
|
6078
|
+
}
|
|
6050
6079
|
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
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);
|
|
6055
6089
|
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
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;
|
|
6059
6095
|
}
|
|
6060
|
-
declarations.push(...extract_jsx_setup_declarations(node[key], seen));
|
|
6061
6096
|
}
|
|
6062
6097
|
|
|
6063
|
-
|
|
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
|
+
}
|
|
6064
6103
|
}
|
|
6065
6104
|
|
|
6066
6105
|
/**
|
|
@@ -6094,11 +6133,11 @@ function wrap_jsx_setup_declarations(expression, in_jsx_child) {
|
|
|
6094
6133
|
* This validator runs over the raw, pre-lowering attribute list so each
|
|
6095
6134
|
* shape is still distinguishable by `type`.
|
|
6096
6135
|
*
|
|
6097
|
-
* @param {
|
|
6136
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} raw_attrs
|
|
6098
6137
|
* @param {TransformContext} [transform_context]
|
|
6099
6138
|
*/
|
|
6100
6139
|
export function validate_at_most_one_ref_attribute(raw_attrs, transform_context) {
|
|
6101
|
-
/** @type {
|
|
6140
|
+
/** @type {ESTreeJSX.JSXIdentifier[]} */
|
|
6102
6141
|
const refs = [];
|
|
6103
6142
|
for (const attr of raw_attrs) {
|
|
6104
6143
|
if (!attr) continue;
|
|
@@ -6108,7 +6147,7 @@ export function validate_at_most_one_ref_attribute(raw_attrs, transform_context)
|
|
|
6108
6147
|
attr.name.type === 'JSXIdentifier' &&
|
|
6109
6148
|
attr.name.name === 'ref';
|
|
6110
6149
|
if (!is_ref_attr) continue;
|
|
6111
|
-
refs.push(attr.name);
|
|
6150
|
+
refs.push(/** @type {ESTreeJSX.JSXIdentifier} */ (attr.name));
|
|
6112
6151
|
}
|
|
6113
6152
|
if (refs.length < 2) {
|
|
6114
6153
|
return;
|
|
@@ -6146,9 +6185,9 @@ export function validate_at_most_one_ref_attribute(raw_attrs, transform_context)
|
|
|
6146
6185
|
* Single-ref elements are always left unchanged so trivial cases stay
|
|
6147
6186
|
* import-free and produce no helper call.
|
|
6148
6187
|
*
|
|
6149
|
-
* @param {
|
|
6188
|
+
* @param {ESTreeJSX.JSXAttributeNode[]} jsx_attrs
|
|
6150
6189
|
* @param {TransformContext} transform_context
|
|
6151
|
-
* @returns {
|
|
6190
|
+
* @returns {ESTreeJSX.JSXAttributeNode[]}
|
|
6152
6191
|
*/
|
|
6153
6192
|
export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
6154
6193
|
const strategy = transform_context.platform.jsx.multiRefStrategy;
|
|
@@ -6168,11 +6207,11 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
6168
6207
|
// instead of silently composing them into `__mergeRefs(...)`.
|
|
6169
6208
|
if (tsx_form_count >= 2) return jsx_attrs;
|
|
6170
6209
|
|
|
6171
|
-
/** @type {
|
|
6210
|
+
/** @type {AST.Expression[]} */
|
|
6172
6211
|
const ref_exprs = [];
|
|
6173
|
-
/** @type {
|
|
6212
|
+
/** @type {ESTreeJSX.JSXAttributeNode[]} */
|
|
6174
6213
|
const result = [];
|
|
6175
|
-
/** @type {
|
|
6214
|
+
/** @type {ESTreeJSX.JSXRefAttribute | null} */
|
|
6176
6215
|
let source_attr = null;
|
|
6177
6216
|
for (const attr of jsx_attrs) {
|
|
6178
6217
|
if (is_jsx_ref_attribute(attr)) {
|
|
@@ -6202,12 +6241,15 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
6202
6241
|
// merged attribute and its name. Without this the kept `ref` keyword in
|
|
6203
6242
|
// `ref={__mergeRefs(...)}` has no source mapping back to the user's `ref=`
|
|
6204
6243
|
// keyword.
|
|
6205
|
-
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);
|
|
6206
6248
|
const merged_attr = build_jsx_attribute(
|
|
6207
6249
|
merged_name,
|
|
6208
6250
|
b.jsx_expression_container(merged_value),
|
|
6209
6251
|
false,
|
|
6210
|
-
|
|
6252
|
+
source_attr_location,
|
|
6211
6253
|
);
|
|
6212
6254
|
result.push(merged_attr);
|
|
6213
6255
|
|
|
@@ -6215,8 +6257,8 @@ export function merge_duplicate_refs(jsx_attrs, transform_context) {
|
|
|
6215
6257
|
}
|
|
6216
6258
|
|
|
6217
6259
|
/**
|
|
6218
|
-
* @param {
|
|
6219
|
-
* @returns {
|
|
6260
|
+
* @param {ESTreeJSX.JSXAttributeNode} attr
|
|
6261
|
+
* @returns {attr is ESTreeJSX.JSXRefAttribute}
|
|
6220
6262
|
*/
|
|
6221
6263
|
function is_jsx_ref_attribute(attr) {
|
|
6222
6264
|
return (
|
|
@@ -6263,7 +6305,7 @@ const MATHML_REF_TAG_NAMES = new Set(
|
|
|
6263
6305
|
);
|
|
6264
6306
|
|
|
6265
6307
|
/**
|
|
6266
|
-
* @param {
|
|
6308
|
+
* @param {ESTreeJSX.JSXElement | ESTreeJSX.JSXOpeningElement} element
|
|
6267
6309
|
* @param {'html' | 'svg' | 'mathml'} [namespace]
|
|
6268
6310
|
* @returns {AST.TypeNode | null}
|
|
6269
6311
|
*/
|
|
@@ -6314,13 +6356,14 @@ function infer_ref_namespace(tag_name) {
|
|
|
6314
6356
|
}
|
|
6315
6357
|
|
|
6316
6358
|
/**
|
|
6317
|
-
* @param {
|
|
6359
|
+
* @param {ESTreeJSX.JSXElement | ESTreeJSX.JSXOpeningElement} element
|
|
6318
6360
|
* @returns {string | null}
|
|
6319
6361
|
*/
|
|
6320
6362
|
function get_element_ref_tag_name(element) {
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
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') {
|
|
6324
6367
|
return element.openingElement.name.name;
|
|
6325
6368
|
}
|
|
6326
6369
|
return null;
|
|
@@ -6341,70 +6384,9 @@ function create_tag_name_map_ref_type(map_name, tag_name) {
|
|
|
6341
6384
|
}
|
|
6342
6385
|
|
|
6343
6386
|
/**
|
|
6344
|
-
* @param {
|
|
6345
|
-
* @param {TransformContext} transform_context
|
|
6346
|
-
* @returns {ESTreeJSX.JSXAttribute | ESTreeJSX.JSXSpreadAttribute}
|
|
6347
|
-
*/
|
|
6348
|
-
export function to_jsx_attribute(attr, transform_context) {
|
|
6349
|
-
if (!attr) return attr;
|
|
6350
|
-
if (attr.type === 'JSXAttribute') {
|
|
6351
|
-
return attr;
|
|
6352
|
-
}
|
|
6353
|
-
if (attr.type === 'JSXSpreadAttribute') {
|
|
6354
|
-
return attr;
|
|
6355
|
-
}
|
|
6356
|
-
// Keep this legacy hook for targets that need React-style DOM attrs. The
|
|
6357
|
-
// current first-party targets preserve authored `class`.
|
|
6358
|
-
let attr_name = attr.name;
|
|
6359
|
-
if (
|
|
6360
|
-
transform_context.platform.jsx.rewriteClassAttr &&
|
|
6361
|
-
attr_name &&
|
|
6362
|
-
attr_name.type === 'Identifier' &&
|
|
6363
|
-
attr_name.name === 'class'
|
|
6364
|
-
) {
|
|
6365
|
-
attr_name = set_loc(b.id('className'), attr.name);
|
|
6366
|
-
attr_name.metadata.source_name = 'class';
|
|
6367
|
-
attr_name.metadata.source_length = 'class'.length;
|
|
6368
|
-
}
|
|
6369
|
-
|
|
6370
|
-
const name =
|
|
6371
|
-
attr_name && attr_name.type === 'Identifier' ? identifier_to_jsx_name(attr_name) : attr_name;
|
|
6372
|
-
|
|
6373
|
-
let value = attr.value;
|
|
6374
|
-
if (value) {
|
|
6375
|
-
if (value.type === 'Literal' && typeof value.value === 'string') {
|
|
6376
|
-
// Keep string literal as attribute string.
|
|
6377
|
-
} else if (value.type !== 'JSXExpressionContainer') {
|
|
6378
|
-
value = to_jsx_expression_container(value);
|
|
6379
|
-
}
|
|
6380
|
-
}
|
|
6381
|
-
|
|
6382
|
-
const jsx_attribute = build_jsx_attribute(name, value || null, attr.shorthand === true);
|
|
6383
|
-
|
|
6384
|
-
if (value_has_unmappable_jsx_loc(value)) {
|
|
6385
|
-
/** @type {any} */ (jsx_attribute.metadata).has_unmappable_value = true;
|
|
6386
|
-
return jsx_attribute;
|
|
6387
|
-
}
|
|
6388
|
-
|
|
6389
|
-
return set_loc(jsx_attribute, attr);
|
|
6390
|
-
}
|
|
6391
|
-
|
|
6392
|
-
/**
|
|
6393
|
-
* @param {any} value
|
|
6394
|
-
* @returns {boolean}
|
|
6395
|
-
*/
|
|
6396
|
-
function value_has_unmappable_jsx_loc(value) {
|
|
6397
|
-
return !!(
|
|
6398
|
-
value?.type === 'JSXExpressionContainer' &&
|
|
6399
|
-
(value.expression?.type === 'JSXElement' || value.expression?.type === 'JSXFragment') &&
|
|
6400
|
-
!value.expression.loc
|
|
6401
|
-
);
|
|
6402
|
-
}
|
|
6403
|
-
|
|
6404
|
-
/**
|
|
6405
|
-
* @param {any[]} render_nodes
|
|
6387
|
+
* @param {ESTreeJSX.JSXRenderChild[]} render_nodes
|
|
6406
6388
|
* @param {boolean} [in_jsx_child]
|
|
6407
|
-
* @returns {
|
|
6389
|
+
* @returns {AST.Expression | null}
|
|
6408
6390
|
*/
|
|
6409
6391
|
export function build_return_expression(render_nodes, in_jsx_child = false, type_only = false) {
|
|
6410
6392
|
if (render_nodes.length === 0) return null;
|
|
@@ -6412,10 +6394,10 @@ export function build_return_expression(render_nodes, in_jsx_child = false, type
|
|
|
6412
6394
|
const only = render_nodes[0];
|
|
6413
6395
|
if (only.type === 'JSXExpressionContainer') {
|
|
6414
6396
|
if (only.metadata?.tsrx_reactive_block === true) {
|
|
6415
|
-
return set_loc(b.jsx_fragment([only]), only
|
|
6397
|
+
return set_loc(b.jsx_fragment([only]), has_location(only) ? only : undefined);
|
|
6416
6398
|
}
|
|
6417
6399
|
if (only.expression?.type === 'JSXEmptyExpression') {
|
|
6418
|
-
return set_loc(b.jsx_fragment([]), only
|
|
6400
|
+
return set_loc(b.jsx_fragment([]), has_location(only) ? only : undefined);
|
|
6419
6401
|
}
|
|
6420
6402
|
return only.expression;
|
|
6421
6403
|
}
|
|
@@ -6428,7 +6410,7 @@ export function build_return_expression(render_nodes, in_jsx_child = false, type
|
|
|
6428
6410
|
if (!type_only && !in_jsx_child && (only.value ?? '').trim() === '') {
|
|
6429
6411
|
return null;
|
|
6430
6412
|
}
|
|
6431
|
-
return set_loc(b.jsx_fragment([only]), only
|
|
6413
|
+
return set_loc(b.jsx_fragment([only]), has_location(only) ? only : undefined);
|
|
6432
6414
|
}
|
|
6433
6415
|
return only;
|
|
6434
6416
|
}
|
|
@@ -6436,7 +6418,7 @@ export function build_return_expression(render_nodes, in_jsx_child = false, type
|
|
|
6436
6418
|
const last = render_nodes[render_nodes.length - 1];
|
|
6437
6419
|
return set_loc(
|
|
6438
6420
|
b.jsx_fragment(render_nodes),
|
|
6439
|
-
first
|
|
6421
|
+
has_location(first) && has_location(last)
|
|
6440
6422
|
? {
|
|
6441
6423
|
start: first.start,
|
|
6442
6424
|
end: last.end,
|