@tsrx/core 0.1.22 → 0.1.25
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/analyze/prune.js +12 -23
- package/src/analyze/validation.js +1 -1
- package/src/diagnostics.js +1 -0
- package/src/index.js +0 -2
- package/src/plugin.js +267 -126
- package/src/runtime/html.js +1 -1
- package/src/runtime/language-helpers.js +39 -0
- package/src/transform/jsx/ast-builders.js +2 -62
- package/src/transform/jsx/index.js +596 -1138
- package/src/transform/scoping.js +1 -1
- package/src/transform/segments.js +13 -43
- package/types/index.d.ts +2 -7
- package/types/jsx-platform.d.ts +11 -8
- package/types/runtime/html.d.ts +1 -0
- package/types/runtime/language-helpers.d.ts +4 -0
|
@@ -7,6 +7,7 @@ import { print } from 'esrap';
|
|
|
7
7
|
import { error } from '../../errors.js';
|
|
8
8
|
import { analyze_css } from '../../analyze/css-analyze.js';
|
|
9
9
|
import { prune_css } from '../../analyze/prune.js';
|
|
10
|
+
import { create_scopes, ScopeRoot } from '../../scope.js';
|
|
10
11
|
import {
|
|
11
12
|
in_jsx_child_context,
|
|
12
13
|
set_node_path_metadata,
|
|
@@ -25,7 +26,6 @@ import {
|
|
|
25
26
|
is_bare_render_expression,
|
|
26
27
|
is_component_jsx_name,
|
|
27
28
|
is_jsx_child,
|
|
28
|
-
jsx_name_to_expression,
|
|
29
29
|
set_loc,
|
|
30
30
|
to_text_expression,
|
|
31
31
|
} from './ast-builders.js';
|
|
@@ -49,7 +49,6 @@ import {
|
|
|
49
49
|
create_style_ref_setup_statements,
|
|
50
50
|
get_style_element_stylesheet,
|
|
51
51
|
} from '../style-ref.js';
|
|
52
|
-
import { is_function_or_component_node } from '../../utils/ast.js';
|
|
53
52
|
import {
|
|
54
53
|
is_interleaved_body as is_interleaved_body_core,
|
|
55
54
|
is_capturable_jsx_child,
|
|
@@ -57,14 +56,10 @@ import {
|
|
|
57
56
|
} from '../jsx-interleave.js';
|
|
58
57
|
import { is_hoist_safe_jsx_node } from '../jsx-hoist.js';
|
|
59
58
|
|
|
60
|
-
const HOOK_OUTER_ASSIGNMENT_ERROR =
|
|
61
|
-
'Hook calls inside conditional or repeated TSRX scopes must keep their results local to the generated hook component.';
|
|
62
|
-
const HOOK_CALLBACK_OUTER_MUTATION_ERROR =
|
|
63
|
-
'Hook callbacks inside conditional or repeated TSRX scopes must not mutate bindings declared outside the generated hook component.';
|
|
64
59
|
const TEMPLATE_FRAGMENT_ERROR =
|
|
65
60
|
'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.';
|
|
66
61
|
const TSRX_FOR_RETURN_ERROR =
|
|
67
|
-
'Return statements are not allowed inside TSRX template for...of loops. Filter the iterable before rendering or use an @
|
|
62
|
+
'Return statements are not allowed inside TSRX template for...of loops. Filter the iterable before rendering or use an @empty fallback for empty lists.';
|
|
68
63
|
const TSRX_FOR_BREAK_ERROR =
|
|
69
64
|
'Break statements are not allowed inside TSRX template for...of loops.';
|
|
70
65
|
const TSRX_FOR_CONTINUE_ERROR =
|
|
@@ -89,44 +84,6 @@ function report_jsx_fragment_in_tsrx_error(node, transform_context) {
|
|
|
89
84
|
);
|
|
90
85
|
}
|
|
91
86
|
|
|
92
|
-
/**
|
|
93
|
-
* @param {AST.Node} node
|
|
94
|
-
* @param {string[]} names
|
|
95
|
-
* @param {string} hook_name
|
|
96
|
-
* @param {TransformContext} transform_context
|
|
97
|
-
* @returns {void}
|
|
98
|
-
*/
|
|
99
|
-
function report_hook_outer_assignment_error(node, names, hook_name, transform_context) {
|
|
100
|
-
const target =
|
|
101
|
-
names.length === 1 ? `\`${names[0]}\`` : names.map((name) => `\`${name}\``).join(', ');
|
|
102
|
-
error(
|
|
103
|
-
`${HOOK_OUTER_ASSIGNMENT_ERROR} The ${hook_name} result is assigned to ${target}, which is declared outside that generated component. Declare the hook result inside the TSRX branch, or move the hook into an explicit child component and pass values with props.`,
|
|
104
|
-
transform_context.filename,
|
|
105
|
-
node,
|
|
106
|
-
transform_context.errors,
|
|
107
|
-
transform_context.comments,
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @param {AST.Node} node
|
|
113
|
-
* @param {string[]} names
|
|
114
|
-
* @param {string} hook_name
|
|
115
|
-
* @param {TransformContext} transform_context
|
|
116
|
-
* @returns {void}
|
|
117
|
-
*/
|
|
118
|
-
function report_hook_callback_outer_mutation_error(node, names, hook_name, transform_context) {
|
|
119
|
-
const target =
|
|
120
|
-
names.length === 1 ? `\`${names[0]}\`` : names.map((name) => `\`${name}\``).join(', ');
|
|
121
|
-
error(
|
|
122
|
-
`${HOOK_CALLBACK_OUTER_MUTATION_ERROR} The ${hook_name} callback mutates ${target}. Read outer values through props or dependencies, and move mutable state into an explicit child component when it needs to change over time.`,
|
|
123
|
-
transform_context.filename,
|
|
124
|
-
node,
|
|
125
|
-
transform_context.errors,
|
|
126
|
-
transform_context.comments,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
87
|
/**
|
|
131
88
|
* Local alias for the shared `JsxTransformContext`. Kept as a typedef so the
|
|
132
89
|
* rest of this file's `@param {TransformContext}` annotations don't all have
|
|
@@ -223,6 +180,86 @@ function expand_child_code_blocks(node, seen = new Set()) {
|
|
|
223
180
|
}
|
|
224
181
|
}
|
|
225
182
|
|
|
183
|
+
/**
|
|
184
|
+
* A `@`-prefixed JSX control-flow expression (`@if`/`@for`/`@switch`/`@try`).
|
|
185
|
+
* These are the only control-flow nodes that can appear in expression position;
|
|
186
|
+
* the plain statement forms (`IfStatement`, `SwitchStatement`, …) never do.
|
|
187
|
+
* @param {any} node
|
|
188
|
+
* @returns {boolean}
|
|
189
|
+
*/
|
|
190
|
+
function is_jsx_control_flow_expression(node) {
|
|
191
|
+
return (
|
|
192
|
+
node?.type === 'JSXIfExpression' ||
|
|
193
|
+
node?.type === 'JSXForExpression' ||
|
|
194
|
+
node?.type === 'JSXSwitchExpression' ||
|
|
195
|
+
node?.type === 'JSXTryExpression'
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Wrap a render-output node in a native TSRX fragment so it flows through the
|
|
201
|
+
* same single-child render path as a `<> … </>` output.
|
|
202
|
+
* @param {any} node
|
|
203
|
+
* @returns {any}
|
|
204
|
+
*/
|
|
205
|
+
function wrap_in_native_tsrx_fragment(node) {
|
|
206
|
+
const fragment = b.jsx_fragment([node]);
|
|
207
|
+
fragment.metadata = { ...(fragment.metadata || {}), native_tsrx: true };
|
|
208
|
+
return fragment;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Wrap a bare JSX control-flow directive that sits directly in an expression
|
|
213
|
+
* position — an expression-bodied arrow (`() => @switch (…) { … }`), a
|
|
214
|
+
* `return @switch (…) { … }`, an unused expression statement,
|
|
215
|
+
* assignment to a variable
|
|
216
|
+
* (`const x = @switch (…) { … }`, `x = @switch (…) { … }`), or a call/`new`
|
|
217
|
+
* argument (`render(@if (…) { … })`) — in a native TSRX fragment.
|
|
218
|
+
* @param {any} node
|
|
219
|
+
* @param {Set<any>} [seen]
|
|
220
|
+
* @returns {void}
|
|
221
|
+
*/
|
|
222
|
+
function wrap_control_flow_expression_values(node, seen = new Set()) {
|
|
223
|
+
if (!node || typeof node !== 'object' || seen.has(node)) return;
|
|
224
|
+
seen.add(node);
|
|
225
|
+
|
|
226
|
+
if (Array.isArray(node)) {
|
|
227
|
+
for (const item of node) wrap_control_flow_expression_values(item, seen);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (
|
|
232
|
+
node.type === 'ArrowFunctionExpression' &&
|
|
233
|
+
node.body?.type !== 'BlockStatement' &&
|
|
234
|
+
is_jsx_control_flow_expression(node.body)
|
|
235
|
+
) {
|
|
236
|
+
node.body = wrap_in_native_tsrx_fragment(node.body);
|
|
237
|
+
} else if (node.type === 'ReturnStatement' && is_jsx_control_flow_expression(node.argument)) {
|
|
238
|
+
node.argument = wrap_in_native_tsrx_fragment(node.argument);
|
|
239
|
+
} else if (
|
|
240
|
+
node.type === 'ExpressionStatement' &&
|
|
241
|
+
is_jsx_control_flow_expression(node.expression)
|
|
242
|
+
) {
|
|
243
|
+
node.expression = wrap_in_native_tsrx_fragment(node.expression);
|
|
244
|
+
} else if (node.type === 'VariableDeclarator' && is_jsx_control_flow_expression(node.init)) {
|
|
245
|
+
node.init = wrap_in_native_tsrx_fragment(node.init);
|
|
246
|
+
} else if (node.type === 'AssignmentExpression' && is_jsx_control_flow_expression(node.right)) {
|
|
247
|
+
node.right = wrap_in_native_tsrx_fragment(node.right);
|
|
248
|
+
} else if (
|
|
249
|
+
(node.type === 'CallExpression' || node.type === 'NewExpression') &&
|
|
250
|
+
Array.isArray(node.arguments)
|
|
251
|
+
) {
|
|
252
|
+
node.arguments = node.arguments.map((/** @type {any} */ arg) =>
|
|
253
|
+
is_jsx_control_flow_expression(arg) ? wrap_in_native_tsrx_fragment(arg) : arg,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
for (const key of Object.keys(node)) {
|
|
258
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') continue;
|
|
259
|
+
wrap_control_flow_expression_values(node[key], seen);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
226
263
|
/**
|
|
227
264
|
* Build a `transform()` function for a specific JSX platform (React, Preact,
|
|
228
265
|
* Solid). Given a `JsxPlatform` descriptor, returns a transform that lowers
|
|
@@ -273,6 +310,7 @@ export function createJsxTransform(platform) {
|
|
|
273
310
|
hook_helpers_enabled: false,
|
|
274
311
|
available_bindings: new Map(),
|
|
275
312
|
lazy_next_id: 0,
|
|
313
|
+
runtime_dynamic_scopes: null,
|
|
276
314
|
filename: filename ?? null,
|
|
277
315
|
source,
|
|
278
316
|
collect,
|
|
@@ -285,6 +323,11 @@ export function createJsxTransform(platform) {
|
|
|
285
323
|
};
|
|
286
324
|
|
|
287
325
|
expand_child_code_blocks(/** @type {any} */ (ast));
|
|
326
|
+
wrap_control_flow_expression_values(/** @type {any} */ (ast));
|
|
327
|
+
transform_context.runtime_dynamic_scopes = create_runtime_dynamic_scopes(
|
|
328
|
+
/** @type {any} */ (ast),
|
|
329
|
+
transform_context,
|
|
330
|
+
);
|
|
288
331
|
|
|
289
332
|
if (!transform_context.typeOnly) {
|
|
290
333
|
preallocate_lazy_ids(/** @type {any} */ (ast), transform_context);
|
|
@@ -321,10 +364,6 @@ export function createJsxTransform(platform) {
|
|
|
321
364
|
},
|
|
322
365
|
|
|
323
366
|
JSXElement(node, { next, path, state }) {
|
|
324
|
-
if (!node.metadata?.native_tsrx && is_dynamic_jsx_element(node)) {
|
|
325
|
-
return dynamic_element_to_jsx(node, state, in_jsx_child_context(path));
|
|
326
|
-
}
|
|
327
|
-
|
|
328
367
|
if (!node.metadata?.native_tsrx) {
|
|
329
368
|
return next() ?? node;
|
|
330
369
|
}
|
|
@@ -464,16 +503,26 @@ export function createJsxTransform(platform) {
|
|
|
464
503
|
*
|
|
465
504
|
* @param {any} component
|
|
466
505
|
* @param {any} css
|
|
506
|
+
* @param {TransformContext} transform_context
|
|
467
507
|
* @param {boolean} [export_top_scoped_classes]
|
|
468
508
|
* @returns {void}
|
|
469
509
|
*/
|
|
470
|
-
function apply_css_definition_metadata(
|
|
510
|
+
function apply_css_definition_metadata(
|
|
511
|
+
component,
|
|
512
|
+
css,
|
|
513
|
+
transform_context,
|
|
514
|
+
export_top_scoped_classes = false,
|
|
515
|
+
) {
|
|
471
516
|
analyze_css(css);
|
|
472
517
|
|
|
473
518
|
const metadata = component.metadata || (component.metadata = { path: [] });
|
|
474
519
|
const style_classes = metadata.styleClasses || (metadata.styleClasses = new Map());
|
|
475
520
|
const top_scoped_classes = metadata.topScopedClasses || new Map();
|
|
476
|
-
const elements = collect_css_prunable_elements(
|
|
521
|
+
const elements = collect_css_prunable_elements(
|
|
522
|
+
component.body || component.children || [],
|
|
523
|
+
[],
|
|
524
|
+
transform_context,
|
|
525
|
+
);
|
|
477
526
|
|
|
478
527
|
const prune = () => {
|
|
479
528
|
for (const element of elements) {
|
|
@@ -498,16 +547,17 @@ function apply_css_definition_metadata(component, css, export_top_scoped_classes
|
|
|
498
547
|
/**
|
|
499
548
|
* @param {any} value
|
|
500
549
|
* @param {any[]} [elements]
|
|
550
|
+
* @param {TransformContext | null} [transform_context]
|
|
501
551
|
* @returns {any[]}
|
|
502
552
|
*/
|
|
503
|
-
function collect_css_prunable_elements(value, elements = []) {
|
|
553
|
+
function collect_css_prunable_elements(value, elements = [], transform_context = null) {
|
|
504
554
|
if (!value || typeof value !== 'object') {
|
|
505
555
|
return elements;
|
|
506
556
|
}
|
|
507
557
|
|
|
508
558
|
if (Array.isArray(value)) {
|
|
509
559
|
for (const child of value) {
|
|
510
|
-
collect_css_prunable_elements(child, elements);
|
|
560
|
+
collect_css_prunable_elements(child, elements, transform_context);
|
|
511
561
|
}
|
|
512
562
|
return elements;
|
|
513
563
|
}
|
|
@@ -521,6 +571,7 @@ function collect_css_prunable_elements(value, elements = []) {
|
|
|
521
571
|
}
|
|
522
572
|
|
|
523
573
|
if (value.type === 'JSXElement' && value.metadata?.native_tsrx) {
|
|
574
|
+
mark_runtime_dynamic_element(value, transform_context);
|
|
524
575
|
if (!is_style_element(value)) {
|
|
525
576
|
elements.push(value);
|
|
526
577
|
}
|
|
@@ -530,12 +581,247 @@ function collect_css_prunable_elements(value, elements = []) {
|
|
|
530
581
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata' || key === 'css') {
|
|
531
582
|
continue;
|
|
532
583
|
}
|
|
533
|
-
collect_css_prunable_elements(value[key], elements);
|
|
584
|
+
collect_css_prunable_elements(value[key], elements, transform_context);
|
|
534
585
|
}
|
|
535
586
|
|
|
536
587
|
return elements;
|
|
537
588
|
}
|
|
538
589
|
|
|
590
|
+
/**
|
|
591
|
+
* @param {AST.Program} ast
|
|
592
|
+
* @param {TransformContext} transform_context
|
|
593
|
+
* @returns {Map<any, any> | null}
|
|
594
|
+
*/
|
|
595
|
+
function create_runtime_dynamic_scopes(ast, transform_context) {
|
|
596
|
+
const dynamic_source = transform_context.platform.imports.dynamic;
|
|
597
|
+
if (!dynamic_source) {
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
if (!has_runtime_dynamic_import(ast, dynamic_source)) {
|
|
601
|
+
return null;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const { scopes } = create_scopes(ast, new ScopeRoot(), null, {
|
|
605
|
+
collect: true,
|
|
606
|
+
errors: [],
|
|
607
|
+
filename: transform_context.filename ?? '',
|
|
608
|
+
comments: transform_context.comments,
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
return scopes;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* @param {any} node
|
|
616
|
+
* @param {TransformContext | null} transform_context
|
|
617
|
+
* @returns {void}
|
|
618
|
+
*/
|
|
619
|
+
function mark_runtime_dynamic_element(node, transform_context) {
|
|
620
|
+
const dynamic_source = transform_context?.platform.imports.dynamic;
|
|
621
|
+
const scopes = transform_context?.runtime_dynamic_scopes;
|
|
622
|
+
if (
|
|
623
|
+
!dynamic_source ||
|
|
624
|
+
!scopes ||
|
|
625
|
+
node.metadata?.runtime_dynamic_element === true ||
|
|
626
|
+
!has_jsx_attribute(node, 'is') ||
|
|
627
|
+
!is_runtime_dynamic_jsx_name(node.openingElement?.name, scopes.get(node), dynamic_source)
|
|
628
|
+
) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
node.metadata.runtime_dynamic_element = true;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* @param {AST.Program} ast
|
|
637
|
+
* @param {string} dynamic_source
|
|
638
|
+
* @returns {boolean}
|
|
639
|
+
*/
|
|
640
|
+
function has_runtime_dynamic_import(ast, dynamic_source) {
|
|
641
|
+
return ast.body.some(
|
|
642
|
+
(/** @type {any} */ node) =>
|
|
643
|
+
node.type === 'ImportDeclaration' &&
|
|
644
|
+
node.importKind !== 'type' &&
|
|
645
|
+
node.source?.type === 'Literal' &&
|
|
646
|
+
node.source.value === dynamic_source &&
|
|
647
|
+
node.specifiers.some(
|
|
648
|
+
(/** @type {any} */ specifier) =>
|
|
649
|
+
is_runtime_dynamic_import_specifier(specifier, 'component') ||
|
|
650
|
+
is_runtime_dynamic_import_specifier(specifier, 'namespace'),
|
|
651
|
+
),
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* @param {any} node
|
|
657
|
+
* @param {string} name
|
|
658
|
+
* @returns {boolean}
|
|
659
|
+
*/
|
|
660
|
+
function has_jsx_attribute(node, name) {
|
|
661
|
+
return (node.openingElement?.attributes ?? []).some(
|
|
662
|
+
(/** @type {any} */ attr) =>
|
|
663
|
+
attr.type === 'JSXAttribute' &&
|
|
664
|
+
attr.name?.type === 'JSXIdentifier' &&
|
|
665
|
+
attr.name.name === name,
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* @param {any} name
|
|
671
|
+
* @param {any} scope
|
|
672
|
+
* @param {string} dynamic_source
|
|
673
|
+
* @returns {boolean}
|
|
674
|
+
*/
|
|
675
|
+
function is_runtime_dynamic_jsx_name(name, scope, dynamic_source) {
|
|
676
|
+
if (!scope || !name) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (name.type === 'JSXIdentifier') {
|
|
681
|
+
return is_runtime_dynamic_binding(scope.get(name.name), dynamic_source, 'component', new Set());
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (
|
|
685
|
+
name.type === 'JSXMemberExpression' &&
|
|
686
|
+
name.object?.type === 'JSXIdentifier' &&
|
|
687
|
+
name.property?.type === 'JSXIdentifier' &&
|
|
688
|
+
name.property.name === 'Dynamic'
|
|
689
|
+
) {
|
|
690
|
+
return is_runtime_dynamic_binding(
|
|
691
|
+
scope.get(name.object.name),
|
|
692
|
+
dynamic_source,
|
|
693
|
+
'namespace',
|
|
694
|
+
new Set(),
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* @param {any} binding
|
|
703
|
+
* @param {string} dynamic_source
|
|
704
|
+
* @param {'component' | 'namespace'} kind
|
|
705
|
+
* @param {Set<any>} seen
|
|
706
|
+
* @returns {boolean}
|
|
707
|
+
*/
|
|
708
|
+
function is_runtime_dynamic_binding(binding, dynamic_source, kind, seen) {
|
|
709
|
+
if (!binding || seen.has(binding)) {
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
seen.add(binding);
|
|
713
|
+
|
|
714
|
+
if (is_runtime_dynamic_import_binding(binding, dynamic_source, kind)) {
|
|
715
|
+
return true;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (binding.reassigned) {
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const initial = unwrap_reference_expression(binding.initial);
|
|
723
|
+
if (!initial) {
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (initial.type === 'Identifier') {
|
|
728
|
+
return is_runtime_dynamic_binding(binding.scope.get(initial.name), dynamic_source, kind, seen);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (
|
|
732
|
+
kind === 'component' &&
|
|
733
|
+
initial.type === 'MemberExpression' &&
|
|
734
|
+
!initial.computed &&
|
|
735
|
+
initial.object?.type === 'Identifier' &&
|
|
736
|
+
initial.property?.type === 'Identifier' &&
|
|
737
|
+
initial.property.name === 'Dynamic'
|
|
738
|
+
) {
|
|
739
|
+
return is_runtime_dynamic_binding(
|
|
740
|
+
binding.scope.get(initial.object.name),
|
|
741
|
+
dynamic_source,
|
|
742
|
+
'namespace',
|
|
743
|
+
new Set(),
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* @param {any} binding
|
|
752
|
+
* @param {string} dynamic_source
|
|
753
|
+
* @param {'component' | 'namespace'} kind
|
|
754
|
+
* @returns {boolean}
|
|
755
|
+
*/
|
|
756
|
+
function is_runtime_dynamic_import_binding(binding, dynamic_source, kind) {
|
|
757
|
+
const declaration = binding?.initial;
|
|
758
|
+
if (
|
|
759
|
+
binding?.declaration_kind !== 'import' ||
|
|
760
|
+
declaration?.type !== 'ImportDeclaration' ||
|
|
761
|
+
declaration.importKind === 'type' ||
|
|
762
|
+
declaration.source?.type !== 'Literal' ||
|
|
763
|
+
declaration.source.value !== dynamic_source
|
|
764
|
+
) {
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return declaration.specifiers.some(
|
|
769
|
+
(/** @type {any} */ specifier) =>
|
|
770
|
+
specifier.local?.name === binding.node?.name &&
|
|
771
|
+
is_runtime_dynamic_import_specifier(specifier, kind),
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* @param {any} specifier
|
|
777
|
+
* @param {'component' | 'namespace'} kind
|
|
778
|
+
* @returns {boolean}
|
|
779
|
+
*/
|
|
780
|
+
function is_runtime_dynamic_import_specifier(specifier, kind) {
|
|
781
|
+
if (kind === 'namespace') {
|
|
782
|
+
return specifier.type === 'ImportNamespaceSpecifier';
|
|
783
|
+
}
|
|
784
|
+
return (
|
|
785
|
+
specifier.type === 'ImportSpecifier' &&
|
|
786
|
+
specifier.importKind !== 'type' &&
|
|
787
|
+
get_imported_name(specifier) === 'Dynamic'
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* @param {any} specifier
|
|
793
|
+
* @returns {string | null}
|
|
794
|
+
*/
|
|
795
|
+
function get_imported_name(specifier) {
|
|
796
|
+
const imported = specifier.imported;
|
|
797
|
+
if (imported?.type === 'Identifier') {
|
|
798
|
+
return imported.name;
|
|
799
|
+
}
|
|
800
|
+
if (imported?.type === 'Literal') {
|
|
801
|
+
return String(imported.value);
|
|
802
|
+
}
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* @param {any} expression
|
|
808
|
+
* @returns {any}
|
|
809
|
+
*/
|
|
810
|
+
function unwrap_reference_expression(expression) {
|
|
811
|
+
let node = expression;
|
|
812
|
+
while (
|
|
813
|
+
node &&
|
|
814
|
+
(node.type === 'TSAsExpression' ||
|
|
815
|
+
node.type === 'TSTypeAssertion' ||
|
|
816
|
+
node.type === 'TSNonNullExpression' ||
|
|
817
|
+
node.type === 'ParenthesizedExpression' ||
|
|
818
|
+
node.type === 'ChainExpression')
|
|
819
|
+
) {
|
|
820
|
+
node = node.expression;
|
|
821
|
+
}
|
|
822
|
+
return node;
|
|
823
|
+
}
|
|
824
|
+
|
|
539
825
|
/**
|
|
540
826
|
* @param {any[]} body_nodes
|
|
541
827
|
* @param {TransformContext} transform_context
|
|
@@ -598,7 +884,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
598
884
|
(node) =>
|
|
599
885
|
!is_loop_skip_return_statement(node) &&
|
|
600
886
|
!is_loop_skip_if_statement(node) &&
|
|
601
|
-
!
|
|
887
|
+
!is_render_child_node(node),
|
|
602
888
|
);
|
|
603
889
|
|
|
604
890
|
if (!continuation_has_setup_statements) {
|
|
@@ -640,7 +926,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
640
926
|
}
|
|
641
927
|
|
|
642
928
|
if (
|
|
643
|
-
|
|
929
|
+
is_template_for_of_node(child) &&
|
|
644
930
|
!child.await &&
|
|
645
931
|
should_extract_hook_helpers(transform_context) &&
|
|
646
932
|
!transform_context.platform.hooks?.isTopLevelSetupCall &&
|
|
@@ -668,7 +954,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
668
954
|
}
|
|
669
955
|
}
|
|
670
956
|
|
|
671
|
-
if (
|
|
957
|
+
if (is_render_child_node(child)) {
|
|
672
958
|
const jsx = to_jsx_child(child, transform_context);
|
|
673
959
|
statements.push(...extract_jsx_setup_declarations(jsx));
|
|
674
960
|
if (interleaved && is_capturable_jsx_child(jsx)) {
|
|
@@ -705,189 +991,49 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
705
991
|
* @returns {boolean}
|
|
706
992
|
*/
|
|
707
993
|
function is_interleaved_body(body_nodes) {
|
|
708
|
-
return is_interleaved_body_core(body_nodes,
|
|
994
|
+
return is_interleaved_body_core(body_nodes, is_render_child_node);
|
|
709
995
|
}
|
|
710
996
|
|
|
711
997
|
/**
|
|
712
|
-
* @param {any}
|
|
998
|
+
* @param {any[]} body_nodes
|
|
713
999
|
* @param {TransformContext} transform_context
|
|
1000
|
+
* @param {boolean} include_platform_setup
|
|
714
1001
|
* @returns {boolean}
|
|
715
1002
|
*/
|
|
716
|
-
function
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
1003
|
+
function body_contains_top_level_hook_call(
|
|
1004
|
+
body_nodes,
|
|
1005
|
+
transform_context,
|
|
1006
|
+
include_platform_setup = false,
|
|
1007
|
+
) {
|
|
1008
|
+
return body_nodes.some((node) =>
|
|
1009
|
+
statement_contains_top_level_hook_call(node, transform_context, include_platform_setup),
|
|
721
1010
|
);
|
|
722
1011
|
}
|
|
723
1012
|
|
|
724
1013
|
/**
|
|
725
1014
|
* @param {any} node
|
|
726
1015
|
* @param {TransformContext} transform_context
|
|
727
|
-
* @
|
|
728
|
-
|
|
729
|
-
function create_hook_split_block(node, transform_context) {
|
|
730
|
-
if (
|
|
731
|
-
transform_context.platform.hooks?.componentBodyHookHelpers !== true ||
|
|
732
|
-
!should_extract_hook_helpers(transform_context) ||
|
|
733
|
-
node.body?.type !== 'BlockStatement'
|
|
734
|
-
) {
|
|
735
|
-
return null;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
const body = node.body.body || [];
|
|
739
|
-
const split_index = find_hook_split_index(body, transform_context);
|
|
740
|
-
if (split_index === -1) {
|
|
741
|
-
return null;
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
const split_statement = body[split_index];
|
|
745
|
-
const continuation_body = body.slice(split_index + 1);
|
|
746
|
-
const helper = create_hook_safe_helper(
|
|
747
|
-
expand_native_tsrx_return_statement_list(continuation_body, transform_context),
|
|
748
|
-
undefined,
|
|
749
|
-
get_body_source_node(continuation_body) || split_statement,
|
|
750
|
-
transform_context,
|
|
751
|
-
);
|
|
752
|
-
|
|
753
|
-
const block = b.block(
|
|
754
|
-
[
|
|
755
|
-
...body.slice(0, split_index + 1),
|
|
756
|
-
...helper.setup_statements,
|
|
757
|
-
set_loc(b.return(helper.component_element), split_statement),
|
|
758
|
-
],
|
|
759
|
-
node.body,
|
|
760
|
-
);
|
|
761
|
-
block.metadata = {
|
|
762
|
-
...(block.metadata || {}),
|
|
763
|
-
hook_split_block: true,
|
|
764
|
-
};
|
|
765
|
-
return block;
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
/**
|
|
769
|
-
* @param {any[]} body_nodes
|
|
770
|
-
* @param {TransformContext} transform_context
|
|
771
|
-
* @returns {number}
|
|
1016
|
+
* @param {boolean} include_platform_setup
|
|
1017
|
+
* @returns {boolean}
|
|
772
1018
|
*/
|
|
773
|
-
function
|
|
774
|
-
|
|
775
|
-
if (!is_component_body_conditional_return_statement(body_nodes[i])) {
|
|
776
|
-
continue;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
if (body_contains_top_level_hook_call(body_nodes.slice(i + 1), transform_context, true)) {
|
|
780
|
-
return i;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
return -1;
|
|
1019
|
+
function statement_contains_top_level_hook_call(node, transform_context, include_platform_setup) {
|
|
1020
|
+
return node_contains_top_level_hook_call(node, false, transform_context, include_platform_setup);
|
|
785
1021
|
}
|
|
786
1022
|
|
|
787
1023
|
/**
|
|
788
1024
|
* @param {any} node
|
|
1025
|
+
* @param {boolean} inside_nested_function
|
|
1026
|
+
* @param {TransformContext} transform_context
|
|
1027
|
+
* @param {boolean} include_platform_setup
|
|
789
1028
|
* @returns {boolean}
|
|
790
1029
|
*/
|
|
791
|
-
function
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
statement_contains_component_body_return(node.alternate)
|
|
799
|
-
);
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/**
|
|
803
|
-
* @param {any} node
|
|
804
|
-
* @returns {boolean}
|
|
805
|
-
*/
|
|
806
|
-
function statement_contains_component_body_return(node) {
|
|
807
|
-
if (!node || typeof node !== 'object') {
|
|
808
|
-
return false;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
if (node.type === 'ReturnStatement') {
|
|
812
|
-
return true;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
if (is_function_or_class_boundary(node)) {
|
|
816
|
-
return false;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
if (Array.isArray(node)) {
|
|
820
|
-
return node.some(statement_contains_component_body_return);
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
if (node.type === 'BlockStatement') {
|
|
824
|
-
return (node.body || []).some(statement_contains_component_body_return);
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
if (is_if_control_node(node)) {
|
|
828
|
-
return (
|
|
829
|
-
statement_contains_component_body_return(node.consequent) ||
|
|
830
|
-
statement_contains_component_body_return(node.alternate)
|
|
831
|
-
);
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
if (is_switch_control_node(node)) {
|
|
835
|
-
return (node.cases || []).some((/** @type {any} */ switch_case) =>
|
|
836
|
-
statement_contains_component_body_return(switch_case.consequent || []),
|
|
837
|
-
);
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
if (is_try_control_node(node)) {
|
|
841
|
-
return (
|
|
842
|
-
statement_contains_component_body_return(node.block) ||
|
|
843
|
-
statement_contains_component_body_return(node.handler?.body) ||
|
|
844
|
-
statement_contains_component_body_return(node.finalizer)
|
|
845
|
-
);
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
return false;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
/**
|
|
852
|
-
* @param {any[]} body_nodes
|
|
853
|
-
* @param {TransformContext} transform_context
|
|
854
|
-
* @param {boolean} include_platform_setup
|
|
855
|
-
* @returns {boolean}
|
|
856
|
-
*/
|
|
857
|
-
function body_contains_top_level_hook_call(
|
|
858
|
-
body_nodes,
|
|
859
|
-
transform_context,
|
|
860
|
-
include_platform_setup = false,
|
|
861
|
-
) {
|
|
862
|
-
return body_nodes.some((node) =>
|
|
863
|
-
statement_contains_top_level_hook_call(node, transform_context, include_platform_setup),
|
|
864
|
-
);
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
/**
|
|
868
|
-
* @param {any} node
|
|
869
|
-
* @param {TransformContext} transform_context
|
|
870
|
-
* @param {boolean} include_platform_setup
|
|
871
|
-
* @returns {boolean}
|
|
872
|
-
*/
|
|
873
|
-
function statement_contains_top_level_hook_call(node, transform_context, include_platform_setup) {
|
|
874
|
-
return node_contains_top_level_hook_call(node, false, transform_context, include_platform_setup);
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
* @param {any} node
|
|
879
|
-
* @param {boolean} inside_nested_function
|
|
880
|
-
* @param {TransformContext} transform_context
|
|
881
|
-
* @param {boolean} include_platform_setup
|
|
882
|
-
* @returns {boolean}
|
|
883
|
-
*/
|
|
884
|
-
function node_contains_top_level_hook_call(
|
|
885
|
-
node,
|
|
886
|
-
inside_nested_function,
|
|
887
|
-
transform_context,
|
|
888
|
-
include_platform_setup,
|
|
889
|
-
) {
|
|
890
|
-
if (!node || typeof node !== 'object') {
|
|
1030
|
+
function node_contains_top_level_hook_call(
|
|
1031
|
+
node,
|
|
1032
|
+
inside_nested_function,
|
|
1033
|
+
transform_context,
|
|
1034
|
+
include_platform_setup,
|
|
1035
|
+
) {
|
|
1036
|
+
if (!node || typeof node !== 'object') {
|
|
891
1037
|
return false;
|
|
892
1038
|
}
|
|
893
1039
|
|
|
@@ -1092,7 +1238,7 @@ function create_generated_helper_metadata(helper_state) {
|
|
|
1092
1238
|
* @returns {any}
|
|
1093
1239
|
*/
|
|
1094
1240
|
function strip_function_transform_metadata(metadata) {
|
|
1095
|
-
const { native_tsrx,
|
|
1241
|
+
const { native_tsrx, ...next_metadata } = metadata || {};
|
|
1096
1242
|
return next_metadata;
|
|
1097
1243
|
}
|
|
1098
1244
|
|
|
@@ -1102,19 +1248,11 @@ function strip_function_transform_metadata(metadata) {
|
|
|
1102
1248
|
* @returns {any}
|
|
1103
1249
|
*/
|
|
1104
1250
|
function transform_block_statement(node, { next, visit, state, path }) {
|
|
1105
|
-
if (node.metadata?.
|
|
1251
|
+
if (node.metadata?.native_return_block) {
|
|
1106
1252
|
return next() ?? node;
|
|
1107
1253
|
}
|
|
1108
1254
|
|
|
1109
|
-
|
|
1110
|
-
if (parent?.metadata?.hook_split && parent.body === node) {
|
|
1111
|
-
const block = create_hook_split_block(parent, state);
|
|
1112
|
-
if (block) {
|
|
1113
|
-
return visit(block, state);
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
if (get_active_native_tsrx_function(path)) {
|
|
1255
|
+
if (get_active_native_tsrx_function(path)?.metadata?.native_tsrx_body) {
|
|
1118
1256
|
const block = create_native_tsrx_statement_list_block(node, state);
|
|
1119
1257
|
if (block) {
|
|
1120
1258
|
return visit(block, state);
|
|
@@ -1130,7 +1268,22 @@ function transform_block_statement(node, { next, visit, state, path }) {
|
|
|
1130
1268
|
* @returns {any}
|
|
1131
1269
|
*/
|
|
1132
1270
|
function transform_return_statement(node, { next, visit, state, path }) {
|
|
1133
|
-
|
|
1271
|
+
const active_native_tsrx_function = get_active_native_tsrx_function(path);
|
|
1272
|
+
if (active_native_tsrx_function && is_native_tsrx_node(node.argument)) {
|
|
1273
|
+
if (!active_native_tsrx_function.metadata?.native_tsrx_body) {
|
|
1274
|
+
const statements = mark_native_pretransformed_jsx(
|
|
1275
|
+
create_native_tsrx_render_statements(node.argument, state),
|
|
1276
|
+
);
|
|
1277
|
+
if (statements.length === 1) {
|
|
1278
|
+
return visit(statements[0], state);
|
|
1279
|
+
}
|
|
1280
|
+
const block = b.block(statements, node.argument);
|
|
1281
|
+
block.metadata = {
|
|
1282
|
+
...(block.metadata || {}),
|
|
1283
|
+
native_return_block: true,
|
|
1284
|
+
};
|
|
1285
|
+
return visit(block, state);
|
|
1286
|
+
}
|
|
1134
1287
|
return visit(create_native_tsrx_render_block(node.argument, state), state);
|
|
1135
1288
|
}
|
|
1136
1289
|
|
|
@@ -1190,10 +1343,17 @@ function transform_function(node, context) {
|
|
|
1190
1343
|
// render output. The parser already marks the render JSX as native_tsrx, so
|
|
1191
1344
|
// from here it flows through the existing native-component machinery exactly
|
|
1192
1345
|
// like the older fenced `{ return <> … </> }` shape.
|
|
1346
|
+
const has_jsx_code_block_body = node.body?.type === 'JSXCodeBlock';
|
|
1193
1347
|
lower_jsx_code_block_function_body(node);
|
|
1194
1348
|
|
|
1195
|
-
if (
|
|
1196
|
-
|
|
1349
|
+
if (
|
|
1350
|
+
has_jsx_code_block_body ||
|
|
1351
|
+
node.metadata?.native_tsrx_function ||
|
|
1352
|
+
function_has_native_tsrx_return(node)
|
|
1353
|
+
) {
|
|
1354
|
+
return transform_native_tsrx_function(node, context, {
|
|
1355
|
+
nativeBody: has_jsx_code_block_body || !!node.metadata?.native_tsrx_function,
|
|
1356
|
+
});
|
|
1197
1357
|
}
|
|
1198
1358
|
|
|
1199
1359
|
return transform_function_with_hook_helpers(node, context);
|
|
@@ -1230,9 +1390,10 @@ function lower_jsx_code_block_function_body(node) {
|
|
|
1230
1390
|
/**
|
|
1231
1391
|
* @param {any} node
|
|
1232
1392
|
* @param {{ next: () => any, state: TransformContext }} context
|
|
1393
|
+
* @param {{ nativeBody?: boolean }} [options]
|
|
1233
1394
|
* @returns {any}
|
|
1234
1395
|
*/
|
|
1235
|
-
function transform_native_tsrx_function(node, { next, state }) {
|
|
1396
|
+
function transform_native_tsrx_function(node, { next, state }, { nativeBody = false } = {}) {
|
|
1236
1397
|
const helper_state =
|
|
1237
1398
|
state.helper_state || create_helper_state(get_function_helper_base_name(node));
|
|
1238
1399
|
const saved_helper_state = state.helper_state;
|
|
@@ -1244,7 +1405,7 @@ function transform_native_tsrx_function(node, { next, state }) {
|
|
|
1244
1405
|
node.metadata = {
|
|
1245
1406
|
...(node.metadata || {}),
|
|
1246
1407
|
native_tsrx: true,
|
|
1247
|
-
...(
|
|
1408
|
+
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1248
1409
|
};
|
|
1249
1410
|
state.available_bindings = merge_binding_maps(
|
|
1250
1411
|
saved_bindings,
|
|
@@ -1270,6 +1431,7 @@ function transform_native_tsrx_function(node, { next, state }) {
|
|
|
1270
1431
|
inner.metadata = {
|
|
1271
1432
|
...strip_function_transform_metadata(inner.metadata),
|
|
1272
1433
|
native_tsrx_function: true,
|
|
1434
|
+
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1273
1435
|
...(!saved_helper_state ? create_generated_helper_metadata(helper_state) || {} : {}),
|
|
1274
1436
|
};
|
|
1275
1437
|
|
|
@@ -1395,13 +1557,12 @@ function find_native_await_in_statement(statement) {
|
|
|
1395
1557
|
* @returns {any}
|
|
1396
1558
|
*/
|
|
1397
1559
|
function transform_function_with_hook_helpers(node, { next, state }) {
|
|
1560
|
+
if (!state.platform.hooks?.moduleScopedHookComponents) {
|
|
1561
|
+
return next() ?? node;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1398
1564
|
const has_hook_bearing_tsrx = function_contains_hook_bearing_tsrx(node, state);
|
|
1399
|
-
|
|
1400
|
-
if (
|
|
1401
|
-
state.helper_state ||
|
|
1402
|
-
!is_uppercase_function_like(node) ||
|
|
1403
|
-
(!has_hook_bearing_tsrx && !has_hook_split)
|
|
1404
|
-
) {
|
|
1565
|
+
if (state.helper_state || !is_uppercase_function_like(node) || !has_hook_bearing_tsrx) {
|
|
1405
1566
|
return next() ?? node;
|
|
1406
1567
|
}
|
|
1407
1568
|
|
|
@@ -1412,12 +1573,6 @@ function transform_function_with_hook_helpers(node, { next, state }) {
|
|
|
1412
1573
|
|
|
1413
1574
|
state.helper_state = helper_state;
|
|
1414
1575
|
state.hook_helpers_enabled = true;
|
|
1415
|
-
if (has_hook_split) {
|
|
1416
|
-
node.metadata = {
|
|
1417
|
-
...(node.metadata || {}),
|
|
1418
|
-
hook_split: true,
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
1576
|
state.available_bindings = collect_function_scope_bindings(node);
|
|
1422
1577
|
|
|
1423
1578
|
const inner = /** @type {any} */ (next() ?? node);
|
|
@@ -1681,7 +1836,7 @@ function prepare_tsrx_fragment_styles(node, transform_context) {
|
|
|
1681
1836
|
if (!css) return null;
|
|
1682
1837
|
|
|
1683
1838
|
const style_refs = collect_style_ref_attributes(node);
|
|
1684
|
-
apply_css_definition_metadata(node, css, style_refs.length > 0);
|
|
1839
|
+
apply_css_definition_metadata(node, css, transform_context, style_refs.length > 0);
|
|
1685
1840
|
transform_context.stylesheets.push(css);
|
|
1686
1841
|
const fragment = annotate_tsrx_with_hash(
|
|
1687
1842
|
node,
|
|
@@ -2271,7 +2426,10 @@ function should_use_module_scoped_hook_components(transform_context) {
|
|
|
2271
2426
|
* @returns {boolean}
|
|
2272
2427
|
*/
|
|
2273
2428
|
function should_extract_hook_helpers(transform_context) {
|
|
2274
|
-
return !!
|
|
2429
|
+
return !!(
|
|
2430
|
+
transform_context.hook_helpers_enabled &&
|
|
2431
|
+
transform_context.platform.hooks?.moduleScopedHookComponents
|
|
2432
|
+
);
|
|
2275
2433
|
}
|
|
2276
2434
|
|
|
2277
2435
|
/**
|
|
@@ -2833,11 +2991,6 @@ function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
|
2833
2991
|
for (const param of loop_params) {
|
|
2834
2992
|
collect_pattern_bindings(param, transform_context.available_bindings);
|
|
2835
2993
|
}
|
|
2836
|
-
validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
2837
|
-
original_loop_body,
|
|
2838
|
-
transform_context,
|
|
2839
|
-
loop_scoped_names,
|
|
2840
|
-
);
|
|
2841
2994
|
|
|
2842
2995
|
const all_helper_bindings = get_referenced_helper_bindings(
|
|
2843
2996
|
original_loop_body,
|
|
@@ -3056,7 +3209,7 @@ function to_jsx_element(
|
|
|
3056
3209
|
raw_children = node.children || [],
|
|
3057
3210
|
in_jsx_child = false,
|
|
3058
3211
|
) {
|
|
3059
|
-
if (node.type === 'JSXElement' && !node.metadata?.native_tsrx
|
|
3212
|
+
if (node.type === 'JSXElement' && !node.metadata?.native_tsrx) {
|
|
3060
3213
|
return node;
|
|
3061
3214
|
}
|
|
3062
3215
|
|
|
@@ -3066,10 +3219,6 @@ function to_jsx_element(
|
|
|
3066
3219
|
report_jsx_fragment_in_tsrx_error(node, transform_context);
|
|
3067
3220
|
return set_loc(b.jsx_fragment(), node);
|
|
3068
3221
|
}
|
|
3069
|
-
if (is_dynamic_jsx_element(node)) {
|
|
3070
|
-
return dynamic_element_to_jsx(node, transform_context, in_jsx_child);
|
|
3071
|
-
}
|
|
3072
|
-
|
|
3073
3222
|
const name = clone_jsx_name(source_name);
|
|
3074
3223
|
const attributes = transform_element_attributes_dispatch(
|
|
3075
3224
|
source_opening.attributes || [],
|
|
@@ -3146,829 +3295,160 @@ function create_element_children(children, transform_context) {
|
|
|
3146
3295
|
}
|
|
3147
3296
|
}
|
|
3148
3297
|
|
|
3149
|
-
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3150
|
-
transform_context.inside_element_child = true;
|
|
3151
|
-
try {
|
|
3152
|
-
return [statement_body_to_jsx_child(children, transform_context)];
|
|
3153
|
-
} finally {
|
|
3154
|
-
transform_context.inside_element_child = saved_inside_element_child;
|
|
3155
|
-
}
|
|
3156
|
-
}
|
|
3157
|
-
|
|
3158
|
-
/**
|
|
3159
|
-
* @param {any[]} children
|
|
3160
|
-
* @returns {boolean}
|
|
3161
|
-
*/
|
|
3162
|
-
function children_contain_return_semantics(children) {
|
|
3163
|
-
return children.some(child_contains_return_semantics);
|
|
3164
|
-
}
|
|
3165
|
-
|
|
3166
|
-
/**
|
|
3167
|
-
* @param {any} node
|
|
3168
|
-
* @returns {boolean}
|
|
3169
|
-
*/
|
|
3170
|
-
function child_contains_return_semantics(node) {
|
|
3171
|
-
if (!node || typeof node !== 'object') {
|
|
3172
|
-
return false;
|
|
3173
|
-
}
|
|
3174
|
-
|
|
3175
|
-
if (node.type === 'ReturnStatement') {
|
|
3176
|
-
return true;
|
|
3177
|
-
}
|
|
3178
|
-
|
|
3179
|
-
if (
|
|
3180
|
-
node.type === 'FunctionDeclaration' ||
|
|
3181
|
-
node.type === 'FunctionExpression' ||
|
|
3182
|
-
node.type === 'ArrowFunctionExpression'
|
|
3183
|
-
) {
|
|
3184
|
-
return false;
|
|
3185
|
-
}
|
|
3186
|
-
|
|
3187
|
-
if (Array.isArray(node)) {
|
|
3188
|
-
return node.some(child_contains_return_semantics);
|
|
3189
|
-
}
|
|
3190
|
-
|
|
3191
|
-
for (const key of Object.keys(node)) {
|
|
3192
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3193
|
-
continue;
|
|
3194
|
-
}
|
|
3195
|
-
if (child_contains_return_semantics(node[key])) {
|
|
3196
|
-
return true;
|
|
3197
|
-
}
|
|
3198
|
-
}
|
|
3199
|
-
|
|
3200
|
-
return false;
|
|
3201
|
-
}
|
|
3202
|
-
|
|
3203
|
-
/**
|
|
3204
|
-
* @param {any} node
|
|
3205
|
-
* @returns {boolean}
|
|
3206
|
-
*/
|
|
3207
|
-
function is_inline_element_child(node) {
|
|
3208
|
-
return node && is_jsx_child(node);
|
|
3209
|
-
}
|
|
3210
|
-
|
|
3211
|
-
/**
|
|
3212
|
-
* @param {any[]} body_nodes
|
|
3213
|
-
* @param {TransformContext} transform_context
|
|
3214
|
-
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3215
|
-
*/
|
|
3216
|
-
function statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3217
|
-
if (
|
|
3218
|
-
should_extract_hook_helpers(transform_context) &&
|
|
3219
|
-
body_contains_top_level_hook_call(body_nodes, transform_context, true)
|
|
3220
|
-
) {
|
|
3221
|
-
return hook_safe_statement_body_to_jsx_child(body_nodes, transform_context);
|
|
3222
|
-
}
|
|
3223
|
-
|
|
3224
|
-
return to_jsx_expression_container(
|
|
3225
|
-
b.call(b.arrow([], b.block(build_render_statements(body_nodes, true, transform_context)))),
|
|
3226
|
-
);
|
|
3227
|
-
}
|
|
3228
|
-
|
|
3229
|
-
/**
|
|
3230
|
-
* @param {any[]} body_nodes
|
|
3231
|
-
* @param {TransformContext} transform_context
|
|
3232
|
-
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3233
|
-
*/
|
|
3234
|
-
function hook_safe_statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3235
|
-
const source_node = get_body_source_node(body_nodes);
|
|
3236
|
-
const helper = create_hook_safe_helper(body_nodes, undefined, source_node, transform_context);
|
|
3237
|
-
|
|
3238
|
-
return to_jsx_expression_container(
|
|
3239
|
-
create_hook_safe_helper_iife(helper.setup_statements, helper.component_element),
|
|
3240
|
-
source_node,
|
|
3241
|
-
);
|
|
3242
|
-
}
|
|
3243
|
-
|
|
3244
|
-
/**
|
|
3245
|
-
* @param {TransformContext} transform_context
|
|
3246
|
-
* @returns {string}
|
|
3247
|
-
*/
|
|
3248
|
-
function create_local_statement_component_name(transform_context) {
|
|
3249
|
-
transform_context.local_statement_component_index += 1;
|
|
3250
|
-
return `StatementBodyHook${transform_context.local_statement_component_index}`;
|
|
3251
|
-
}
|
|
3252
|
-
|
|
3253
|
-
/**
|
|
3254
|
-
* Wraps a list of body nodes into a component and returns
|
|
3255
|
-
* statements that return `<ComponentName prop1={prop1} ... />`.
|
|
3256
|
-
* Targets can either emit the helper component at module scope or cache the
|
|
3257
|
-
* component identity in module state while initializing it from the parent.
|
|
3258
|
-
* Used when a control flow branch contains hook calls that must be moved
|
|
3259
|
-
* into their own component boundary to satisfy the Rules of Hooks.
|
|
3260
|
-
*
|
|
3261
|
-
* @param {any[]} body_nodes
|
|
3262
|
-
* @param {any} key_expression - Optional key expression to add to the component element (for for-of loops)
|
|
3263
|
-
* @param {TransformContext} transform_context
|
|
3264
|
-
* @returns {any[]}
|
|
3265
|
-
*/
|
|
3266
|
-
function hook_safe_render_statements(body_nodes, key_expression, transform_context) {
|
|
3267
|
-
const source_node = get_body_source_node(body_nodes);
|
|
3268
|
-
const helper = create_hook_safe_helper(
|
|
3269
|
-
body_nodes,
|
|
3270
|
-
key_expression,
|
|
3271
|
-
source_node,
|
|
3272
|
-
transform_context,
|
|
3273
|
-
);
|
|
3274
|
-
const statements = [...helper.setup_statements];
|
|
3275
|
-
|
|
3276
|
-
statements.push(b.return(helper.component_element));
|
|
3277
|
-
|
|
3278
|
-
return statements;
|
|
3279
|
-
}
|
|
3280
|
-
|
|
3281
|
-
/**
|
|
3282
|
-
* @param {any[]} body_nodes
|
|
3283
|
-
* @param {Map<string, AST.Identifier>} available_bindings
|
|
3284
|
-
* @returns {AST.Identifier[]}
|
|
3285
|
-
*/
|
|
3286
|
-
function get_referenced_helper_bindings(body_nodes, available_bindings) {
|
|
3287
|
-
const helper_bindings = [];
|
|
3288
|
-
const local_bindings = new Map();
|
|
3289
|
-
|
|
3290
|
-
for (const node of body_nodes) {
|
|
3291
|
-
collect_statement_bindings(node, local_bindings);
|
|
3292
|
-
}
|
|
3293
|
-
|
|
3294
|
-
for (const [name, binding] of available_bindings) {
|
|
3295
|
-
if (local_bindings.has(name)) continue;
|
|
3296
|
-
|
|
3297
|
-
if (references_scope_bindings(body_nodes, new Map([[name, binding]]))) {
|
|
3298
|
-
helper_bindings.push(binding);
|
|
3299
|
-
}
|
|
3300
|
-
}
|
|
3301
|
-
|
|
3302
|
-
return helper_bindings;
|
|
3303
|
-
}
|
|
3304
|
-
|
|
3305
|
-
/**
|
|
3306
|
-
* @param {any[]} body_nodes
|
|
3307
|
-
* @param {TransformContext} transform_context
|
|
3308
|
-
* @param {Set<string>} [local_binding_names]
|
|
3309
|
-
* @returns {void}
|
|
3310
|
-
*/
|
|
3311
|
-
function validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
3312
|
-
body_nodes,
|
|
3313
|
-
transform_context,
|
|
3314
|
-
local_binding_names,
|
|
3315
|
-
) {
|
|
3316
|
-
if (!is_react_like_hook_platform(transform_context)) {
|
|
3317
|
-
return;
|
|
3318
|
-
}
|
|
3319
|
-
if (!body_contains_top_level_hook_call(body_nodes, transform_context, true)) {
|
|
3320
|
-
return;
|
|
3321
|
-
}
|
|
3322
|
-
if (!transform_context.available_bindings || transform_context.available_bindings.size === 0) {
|
|
3323
|
-
return;
|
|
3324
|
-
}
|
|
3325
|
-
|
|
3326
|
-
const shadowed_names = collect_block_binding_names(body_nodes);
|
|
3327
|
-
for (const name of local_binding_names || []) {
|
|
3328
|
-
shadowed_names.add(name);
|
|
3329
|
-
}
|
|
3330
|
-
validate_hook_outer_assignments_in_node(body_nodes, shadowed_names, transform_context, new Set());
|
|
3331
|
-
}
|
|
3332
|
-
|
|
3333
|
-
/**
|
|
3334
|
-
* @param {TransformContext} transform_context
|
|
3335
|
-
* @returns {boolean}
|
|
3336
|
-
*/
|
|
3337
|
-
function is_react_like_hook_platform(transform_context) {
|
|
3338
|
-
return (
|
|
3339
|
-
transform_context.platform.name === 'React' || transform_context.platform.name === 'Preact'
|
|
3340
|
-
);
|
|
3341
|
-
}
|
|
3342
|
-
|
|
3343
|
-
/**
|
|
3344
|
-
* @param {any[]} statements
|
|
3345
|
-
* @returns {Set<string>}
|
|
3346
|
-
*/
|
|
3347
|
-
function collect_block_binding_names(statements) {
|
|
3348
|
-
const names = new Set();
|
|
3349
|
-
for (const statement of statements || []) {
|
|
3350
|
-
collect_block_binding_names_from_statement(statement, names);
|
|
3351
|
-
}
|
|
3352
|
-
return names;
|
|
3353
|
-
}
|
|
3354
|
-
|
|
3355
|
-
/**
|
|
3356
|
-
* @param {any} statement
|
|
3357
|
-
* @param {Set<string>} names
|
|
3358
|
-
* @returns {void}
|
|
3359
|
-
*/
|
|
3360
|
-
function collect_block_binding_names_from_statement(statement, names) {
|
|
3361
|
-
if (!statement || typeof statement !== 'object') {
|
|
3362
|
-
return;
|
|
3363
|
-
}
|
|
3364
|
-
|
|
3365
|
-
if (statement.type === 'VariableDeclaration') {
|
|
3366
|
-
for (const declaration of statement.declarations || []) {
|
|
3367
|
-
collect_pattern_names(declaration.id, names);
|
|
3368
|
-
}
|
|
3369
|
-
return;
|
|
3370
|
-
}
|
|
3371
|
-
|
|
3372
|
-
if (
|
|
3373
|
-
(statement.type === 'FunctionDeclaration' || statement.type === 'ClassDeclaration') &&
|
|
3374
|
-
statement.id?.type === 'Identifier'
|
|
3375
|
-
) {
|
|
3376
|
-
names.add(statement.id.name);
|
|
3377
|
-
return;
|
|
3378
|
-
}
|
|
3379
|
-
|
|
3380
|
-
if (
|
|
3381
|
-
statement.type === 'ForOfStatement' ||
|
|
3382
|
-
statement.type === 'ForInStatement' ||
|
|
3383
|
-
(statement.type === 'JSXForExpression' &&
|
|
3384
|
-
(statement.statementType === 'ForOfStatement' ||
|
|
3385
|
-
statement.statementType === 'ForInStatement'))
|
|
3386
|
-
) {
|
|
3387
|
-
if (statement.left?.type === 'VariableDeclaration' && statement.left.kind === 'var') {
|
|
3388
|
-
for (const declaration of statement.left.declarations || []) {
|
|
3389
|
-
collect_pattern_names(declaration.id, names);
|
|
3390
|
-
}
|
|
3391
|
-
}
|
|
3392
|
-
return;
|
|
3393
|
-
}
|
|
3394
|
-
|
|
3395
|
-
if (
|
|
3396
|
-
statement.type === 'ForStatement' &&
|
|
3397
|
-
statement.init?.type === 'VariableDeclaration' &&
|
|
3398
|
-
statement.init.kind === 'var'
|
|
3399
|
-
) {
|
|
3400
|
-
for (const declaration of statement.init.declarations || []) {
|
|
3401
|
-
collect_pattern_names(declaration.id, names);
|
|
3402
|
-
}
|
|
3403
|
-
}
|
|
3404
|
-
}
|
|
3405
|
-
|
|
3406
|
-
/**
|
|
3407
|
-
* @param {any} pattern
|
|
3408
|
-
* @param {Set<string>} names
|
|
3409
|
-
* @returns {void}
|
|
3410
|
-
*/
|
|
3411
|
-
function collect_pattern_names(pattern, names) {
|
|
3412
|
-
if (!pattern || typeof pattern !== 'object') {
|
|
3413
|
-
return;
|
|
3414
|
-
}
|
|
3415
|
-
|
|
3416
|
-
if (pattern.type === 'Identifier') {
|
|
3417
|
-
names.add(pattern.name);
|
|
3418
|
-
return;
|
|
3419
|
-
}
|
|
3420
|
-
|
|
3421
|
-
if (pattern.type === 'RestElement') {
|
|
3422
|
-
collect_pattern_names(pattern.argument, names);
|
|
3423
|
-
return;
|
|
3424
|
-
}
|
|
3425
|
-
|
|
3426
|
-
if (pattern.type === 'AssignmentPattern') {
|
|
3427
|
-
collect_pattern_names(pattern.left, names);
|
|
3428
|
-
return;
|
|
3429
|
-
}
|
|
3430
|
-
|
|
3431
|
-
if (pattern.type === 'ArrayPattern') {
|
|
3432
|
-
for (const element of pattern.elements || []) {
|
|
3433
|
-
collect_pattern_names(element, names);
|
|
3434
|
-
}
|
|
3435
|
-
return;
|
|
3436
|
-
}
|
|
3437
|
-
|
|
3438
|
-
if (pattern.type === 'ObjectPattern') {
|
|
3439
|
-
for (const property of pattern.properties || []) {
|
|
3440
|
-
if (property.type === 'RestElement') {
|
|
3441
|
-
collect_pattern_names(property.argument, names);
|
|
3442
|
-
} else {
|
|
3443
|
-
collect_pattern_names(property.value, names);
|
|
3444
|
-
}
|
|
3445
|
-
}
|
|
3446
|
-
}
|
|
3447
|
-
}
|
|
3448
|
-
|
|
3449
|
-
/**
|
|
3450
|
-
* @param {any} node
|
|
3451
|
-
* @param {Set<string>} shadowed_names
|
|
3452
|
-
* @param {TransformContext} transform_context
|
|
3453
|
-
* @param {Set<string>} hook_result_names
|
|
3454
|
-
* @returns {void}
|
|
3455
|
-
*/
|
|
3456
|
-
function validate_hook_outer_assignments_in_node(
|
|
3457
|
-
node,
|
|
3458
|
-
shadowed_names,
|
|
3459
|
-
transform_context,
|
|
3460
|
-
hook_result_names,
|
|
3461
|
-
) {
|
|
3462
|
-
if (!node || typeof node !== 'object') {
|
|
3463
|
-
return;
|
|
3464
|
-
}
|
|
3465
|
-
|
|
3466
|
-
if (Array.isArray(node)) {
|
|
3467
|
-
for (const child of node) {
|
|
3468
|
-
validate_hook_outer_assignments_in_node(
|
|
3469
|
-
child,
|
|
3470
|
-
shadowed_names,
|
|
3471
|
-
transform_context,
|
|
3472
|
-
hook_result_names,
|
|
3473
|
-
);
|
|
3474
|
-
}
|
|
3475
|
-
return;
|
|
3476
|
-
}
|
|
3477
|
-
|
|
3478
|
-
if (is_function_or_component_node(node)) {
|
|
3479
|
-
return;
|
|
3480
|
-
}
|
|
3481
|
-
|
|
3482
|
-
if (node.type === 'CallExpression' && is_hook_callee(node.callee)) {
|
|
3483
|
-
validate_hook_callback_outer_mutations(node, shadowed_names, transform_context);
|
|
3484
|
-
}
|
|
3485
|
-
|
|
3486
|
-
if (node.type === 'BlockStatement') {
|
|
3487
|
-
const next_shadowed = new Set(shadowed_names);
|
|
3488
|
-
const next_hook_result_names = new Set(hook_result_names);
|
|
3489
|
-
for (const name of collect_block_binding_names(node.body || [])) {
|
|
3490
|
-
next_shadowed.add(name);
|
|
3491
|
-
}
|
|
3492
|
-
for (const child of node.body || []) {
|
|
3493
|
-
validate_hook_outer_assignments_in_node(
|
|
3494
|
-
child,
|
|
3495
|
-
next_shadowed,
|
|
3496
|
-
transform_context,
|
|
3497
|
-
next_hook_result_names,
|
|
3498
|
-
);
|
|
3499
|
-
}
|
|
3500
|
-
return;
|
|
3501
|
-
}
|
|
3502
|
-
|
|
3503
|
-
if (node.type === 'VariableDeclaration') {
|
|
3504
|
-
for (const declaration of node.declarations || []) {
|
|
3505
|
-
if (
|
|
3506
|
-
declaration.init &&
|
|
3507
|
-
expression_contains_hook_derived_value(
|
|
3508
|
-
declaration.init,
|
|
3509
|
-
transform_context,
|
|
3510
|
-
hook_result_names,
|
|
3511
|
-
)
|
|
3512
|
-
) {
|
|
3513
|
-
collect_pattern_names(declaration.id, hook_result_names);
|
|
3514
|
-
}
|
|
3515
|
-
validate_hook_outer_assignments_in_node(
|
|
3516
|
-
declaration.init,
|
|
3517
|
-
shadowed_names,
|
|
3518
|
-
transform_context,
|
|
3519
|
-
hook_result_names,
|
|
3520
|
-
);
|
|
3521
|
-
}
|
|
3522
|
-
return;
|
|
3523
|
-
}
|
|
3524
|
-
|
|
3525
|
-
if (
|
|
3526
|
-
node.type === 'AssignmentExpression' &&
|
|
3527
|
-
expression_contains_hook_derived_value(node.right, transform_context, hook_result_names)
|
|
3528
|
-
) {
|
|
3529
|
-
const outer_names = get_referenced_outer_binding_names(
|
|
3530
|
-
node.left,
|
|
3531
|
-
transform_context.available_bindings,
|
|
3532
|
-
shadowed_names,
|
|
3533
|
-
);
|
|
3534
|
-
if (outer_names.length > 0) {
|
|
3535
|
-
report_hook_outer_assignment_error(
|
|
3536
|
-
node.left,
|
|
3537
|
-
outer_names,
|
|
3538
|
-
find_first_hook_call_name(node.right) || 'hook',
|
|
3539
|
-
transform_context,
|
|
3540
|
-
);
|
|
3541
|
-
}
|
|
3542
|
-
for (const name of get_referenced_local_binding_names(node.left, shadowed_names)) {
|
|
3543
|
-
hook_result_names.add(name);
|
|
3544
|
-
}
|
|
3545
|
-
}
|
|
3546
|
-
|
|
3547
|
-
if (is_for_of_control_node(node)) {
|
|
3548
|
-
if (
|
|
3549
|
-
node.left &&
|
|
3550
|
-
node.left.type !== 'VariableDeclaration' &&
|
|
3551
|
-
expression_contains_hook_derived_value(node.right, transform_context, hook_result_names)
|
|
3552
|
-
) {
|
|
3553
|
-
const outer_names = get_referenced_outer_binding_names(
|
|
3554
|
-
node.left,
|
|
3555
|
-
transform_context.available_bindings,
|
|
3556
|
-
shadowed_names,
|
|
3557
|
-
);
|
|
3558
|
-
if (outer_names.length > 0) {
|
|
3559
|
-
report_hook_outer_assignment_error(
|
|
3560
|
-
node.left,
|
|
3561
|
-
outer_names,
|
|
3562
|
-
find_first_hook_call_name(node.right) || 'hook',
|
|
3563
|
-
transform_context,
|
|
3564
|
-
);
|
|
3565
|
-
}
|
|
3566
|
-
for (const name of get_referenced_local_binding_names(node.left, shadowed_names)) {
|
|
3567
|
-
hook_result_names.add(name);
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
|
|
3571
|
-
validate_hook_outer_assignments_in_node(
|
|
3572
|
-
node.right,
|
|
3573
|
-
shadowed_names,
|
|
3574
|
-
transform_context,
|
|
3575
|
-
hook_result_names,
|
|
3576
|
-
);
|
|
3577
|
-
|
|
3578
|
-
// Loop-declared bindings (`for (const x of …)`, `for (let x of …)`) live
|
|
3579
|
-
// only in the body. They are deliberately NOT in the enclosing block's
|
|
3580
|
-
// shadowed set (see collect_block_binding_names_from_statement), so add
|
|
3581
|
-
// them just for the body recursion to keep references to the loop var
|
|
3582
|
-
// from being flagged as outer-binding mutations.
|
|
3583
|
-
const body_shadowed = new Set(shadowed_names);
|
|
3584
|
-
if (node.left && node.left.type === 'VariableDeclaration') {
|
|
3585
|
-
for (const declaration of node.left.declarations || []) {
|
|
3586
|
-
collect_pattern_names(declaration.id, body_shadowed);
|
|
3587
|
-
}
|
|
3588
|
-
}
|
|
3589
|
-
validate_hook_outer_assignments_in_node(
|
|
3590
|
-
node.body,
|
|
3591
|
-
body_shadowed,
|
|
3592
|
-
transform_context,
|
|
3593
|
-
hook_result_names,
|
|
3594
|
-
);
|
|
3595
|
-
return;
|
|
3596
|
-
}
|
|
3597
|
-
|
|
3598
|
-
for (const key of Object.keys(node)) {
|
|
3599
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3600
|
-
continue;
|
|
3601
|
-
}
|
|
3602
|
-
validate_hook_outer_assignments_in_node(
|
|
3603
|
-
node[key],
|
|
3604
|
-
shadowed_names,
|
|
3605
|
-
transform_context,
|
|
3606
|
-
hook_result_names,
|
|
3607
|
-
);
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
|
|
3611
|
-
/**
|
|
3612
|
-
* @param {any} call_node
|
|
3613
|
-
* @param {Set<string>} shadowed_names
|
|
3614
|
-
* @param {TransformContext} transform_context
|
|
3615
|
-
* @returns {void}
|
|
3616
|
-
*/
|
|
3617
|
-
function validate_hook_callback_outer_mutations(call_node, shadowed_names, transform_context) {
|
|
3618
|
-
const hook_name = get_hook_callee_name(call_node.callee);
|
|
3619
|
-
for (const argument of call_node.arguments || []) {
|
|
3620
|
-
if (!is_function_or_component_node(argument)) {
|
|
3621
|
-
continue;
|
|
3622
|
-
}
|
|
3623
|
-
const callback_shadowed_names = create_function_like_shadowed_names(argument, shadowed_names);
|
|
3624
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
3625
|
-
argument.body,
|
|
3626
|
-
callback_shadowed_names,
|
|
3627
|
-
transform_context,
|
|
3628
|
-
hook_name,
|
|
3629
|
-
);
|
|
3630
|
-
}
|
|
3631
|
-
}
|
|
3632
|
-
|
|
3633
|
-
/**
|
|
3634
|
-
* @param {any} node
|
|
3635
|
-
* @param {Set<string>} shadowed_names
|
|
3636
|
-
* @returns {Set<string>}
|
|
3637
|
-
*/
|
|
3638
|
-
function create_function_like_shadowed_names(node, shadowed_names) {
|
|
3639
|
-
const next_shadowed_names = new Set(shadowed_names);
|
|
3640
|
-
for (const param of node.params || []) {
|
|
3641
|
-
collect_pattern_names(param, next_shadowed_names);
|
|
3642
|
-
}
|
|
3643
|
-
if (node.body?.type === 'BlockStatement') {
|
|
3644
|
-
for (const name of collect_block_binding_names(node.body.body || [])) {
|
|
3645
|
-
next_shadowed_names.add(name);
|
|
3646
|
-
}
|
|
3647
|
-
}
|
|
3648
|
-
return next_shadowed_names;
|
|
3649
|
-
}
|
|
3650
|
-
|
|
3651
|
-
/**
|
|
3652
|
-
* @param {any} node
|
|
3653
|
-
* @param {Set<string>} shadowed_names
|
|
3654
|
-
* @param {TransformContext} transform_context
|
|
3655
|
-
* @param {string} hook_name
|
|
3656
|
-
* @returns {void}
|
|
3657
|
-
*/
|
|
3658
|
-
function validate_hook_callback_outer_mutations_in_node(
|
|
3659
|
-
node,
|
|
3660
|
-
shadowed_names,
|
|
3661
|
-
transform_context,
|
|
3662
|
-
hook_name,
|
|
3663
|
-
) {
|
|
3664
|
-
if (!node || typeof node !== 'object') {
|
|
3665
|
-
return;
|
|
3666
|
-
}
|
|
3667
|
-
|
|
3668
|
-
if (Array.isArray(node)) {
|
|
3669
|
-
for (const child of node) {
|
|
3670
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
3671
|
-
child,
|
|
3672
|
-
shadowed_names,
|
|
3673
|
-
transform_context,
|
|
3674
|
-
hook_name,
|
|
3675
|
-
);
|
|
3676
|
-
}
|
|
3677
|
-
return;
|
|
3678
|
-
}
|
|
3679
|
-
|
|
3680
|
-
if (is_function_or_component_node(node)) {
|
|
3681
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
3682
|
-
node.body,
|
|
3683
|
-
create_function_like_shadowed_names(node, shadowed_names),
|
|
3684
|
-
transform_context,
|
|
3685
|
-
hook_name,
|
|
3686
|
-
);
|
|
3687
|
-
return;
|
|
3688
|
-
}
|
|
3689
|
-
|
|
3690
|
-
if (node.type === 'BlockStatement') {
|
|
3691
|
-
const next_shadowed_names = new Set(shadowed_names);
|
|
3692
|
-
for (const name of collect_block_binding_names(node.body || [])) {
|
|
3693
|
-
next_shadowed_names.add(name);
|
|
3694
|
-
}
|
|
3695
|
-
for (const child of node.body || []) {
|
|
3696
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
3697
|
-
child,
|
|
3698
|
-
next_shadowed_names,
|
|
3699
|
-
transform_context,
|
|
3700
|
-
hook_name,
|
|
3701
|
-
);
|
|
3702
|
-
}
|
|
3703
|
-
return;
|
|
3704
|
-
}
|
|
3705
|
-
|
|
3706
|
-
if (node.type === 'AssignmentExpression') {
|
|
3707
|
-
const outer_names = get_referenced_outer_binding_names(
|
|
3708
|
-
node.left,
|
|
3709
|
-
transform_context.available_bindings,
|
|
3710
|
-
shadowed_names,
|
|
3711
|
-
);
|
|
3712
|
-
if (outer_names.length > 0) {
|
|
3713
|
-
report_hook_callback_outer_mutation_error(
|
|
3714
|
-
node.left,
|
|
3715
|
-
outer_names,
|
|
3716
|
-
hook_name,
|
|
3717
|
-
transform_context,
|
|
3718
|
-
);
|
|
3719
|
-
}
|
|
3720
|
-
}
|
|
3721
|
-
|
|
3722
|
-
if (node.type === 'UpdateExpression') {
|
|
3723
|
-
const outer_names = get_referenced_outer_binding_names(
|
|
3724
|
-
node.argument,
|
|
3725
|
-
transform_context.available_bindings,
|
|
3726
|
-
shadowed_names,
|
|
3727
|
-
);
|
|
3728
|
-
if (outer_names.length > 0) {
|
|
3729
|
-
report_hook_callback_outer_mutation_error(
|
|
3730
|
-
node.argument,
|
|
3731
|
-
outer_names,
|
|
3732
|
-
hook_name,
|
|
3733
|
-
transform_context,
|
|
3734
|
-
);
|
|
3735
|
-
}
|
|
3736
|
-
}
|
|
3737
|
-
|
|
3738
|
-
for (const key of Object.keys(node)) {
|
|
3739
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3740
|
-
continue;
|
|
3741
|
-
}
|
|
3742
|
-
if (key === 'left' && node.type === 'AssignmentExpression') {
|
|
3743
|
-
continue;
|
|
3744
|
-
}
|
|
3745
|
-
if (key === 'argument' && node.type === 'UpdateExpression') {
|
|
3746
|
-
continue;
|
|
3747
|
-
}
|
|
3748
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
3749
|
-
node[key],
|
|
3750
|
-
shadowed_names,
|
|
3751
|
-
transform_context,
|
|
3752
|
-
hook_name,
|
|
3753
|
-
);
|
|
3754
|
-
}
|
|
3755
|
-
}
|
|
3756
|
-
|
|
3757
|
-
/**
|
|
3758
|
-
* @param {any} node
|
|
3759
|
-
* @param {TransformContext} transform_context
|
|
3760
|
-
* @param {Set<string>} hook_result_names
|
|
3761
|
-
* @returns {boolean}
|
|
3762
|
-
*/
|
|
3763
|
-
function expression_contains_hook_derived_value(node, transform_context, hook_result_names) {
|
|
3764
|
-
return (
|
|
3765
|
-
node_contains_top_level_hook_call(node, false, transform_context, true) ||
|
|
3766
|
-
references_name_in_set(node, hook_result_names)
|
|
3767
|
-
);
|
|
3768
|
-
}
|
|
3769
|
-
|
|
3770
|
-
/**
|
|
3771
|
-
* @param {any} node
|
|
3772
|
-
* @param {Set<string>} names
|
|
3773
|
-
* @returns {boolean}
|
|
3774
|
-
*/
|
|
3775
|
-
function references_name_in_set(node, names) {
|
|
3776
|
-
if (!node || typeof node !== 'object' || names.size === 0) {
|
|
3777
|
-
return false;
|
|
3778
|
-
}
|
|
3779
|
-
|
|
3780
|
-
if (node.type === 'Identifier') {
|
|
3781
|
-
return names.has(node.name);
|
|
3782
|
-
}
|
|
3783
|
-
|
|
3784
|
-
if (
|
|
3785
|
-
node.type === 'FunctionDeclaration' ||
|
|
3786
|
-
node.type === 'FunctionExpression' ||
|
|
3787
|
-
node.type === 'ArrowFunctionExpression'
|
|
3788
|
-
) {
|
|
3789
|
-
return false;
|
|
3790
|
-
}
|
|
3791
|
-
|
|
3792
|
-
if (Array.isArray(node)) {
|
|
3793
|
-
return node.some((child) => references_name_in_set(child, names));
|
|
3794
|
-
}
|
|
3795
|
-
|
|
3796
|
-
for (const key of Object.keys(node)) {
|
|
3797
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3798
|
-
continue;
|
|
3799
|
-
}
|
|
3800
|
-
if (key === 'property' && node.type === 'MemberExpression' && !node.computed) {
|
|
3801
|
-
continue;
|
|
3802
|
-
}
|
|
3803
|
-
if (key === 'key' && node.type === 'Property' && !node.computed && !node.shorthand) {
|
|
3804
|
-
continue;
|
|
3805
|
-
}
|
|
3806
|
-
if (references_name_in_set(node[key], names)) {
|
|
3807
|
-
return true;
|
|
3808
|
-
}
|
|
3809
|
-
}
|
|
3810
|
-
|
|
3811
|
-
return false;
|
|
3812
|
-
}
|
|
3813
|
-
|
|
3814
|
-
/**
|
|
3815
|
-
* @param {any} node
|
|
3816
|
-
* @param {Set<string>} shadowed_names
|
|
3817
|
-
* @returns {string[]}
|
|
3818
|
-
*/
|
|
3819
|
-
function get_referenced_local_binding_names(node, shadowed_names) {
|
|
3820
|
-
const names = new Set();
|
|
3821
|
-
collect_referenced_local_binding_names(node, shadowed_names, names);
|
|
3822
|
-
return [...names];
|
|
3823
|
-
}
|
|
3824
|
-
|
|
3825
|
-
/**
|
|
3826
|
-
* @param {any} node
|
|
3827
|
-
* @param {Set<string>} shadowed_names
|
|
3828
|
-
* @param {Set<string>} names
|
|
3829
|
-
* @returns {void}
|
|
3830
|
-
*/
|
|
3831
|
-
function collect_referenced_local_binding_names(node, shadowed_names, names) {
|
|
3832
|
-
if (!node || typeof node !== 'object') {
|
|
3833
|
-
return;
|
|
3834
|
-
}
|
|
3835
|
-
|
|
3836
|
-
if (node.type === 'Identifier') {
|
|
3837
|
-
if (shadowed_names.has(node.name)) {
|
|
3838
|
-
names.add(node.name);
|
|
3839
|
-
}
|
|
3840
|
-
return;
|
|
3841
|
-
}
|
|
3842
|
-
|
|
3843
|
-
if (Array.isArray(node)) {
|
|
3844
|
-
for (const child of node) {
|
|
3845
|
-
collect_referenced_local_binding_names(child, shadowed_names, names);
|
|
3846
|
-
}
|
|
3847
|
-
return;
|
|
3848
|
-
}
|
|
3849
|
-
|
|
3850
|
-
for (const key of Object.keys(node)) {
|
|
3851
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3852
|
-
continue;
|
|
3853
|
-
}
|
|
3854
|
-
if (key === 'property' && node.type === 'MemberExpression' && !node.computed) {
|
|
3855
|
-
continue;
|
|
3856
|
-
}
|
|
3857
|
-
if (key === 'key' && node.type === 'Property' && !node.computed && !node.shorthand) {
|
|
3858
|
-
continue;
|
|
3859
|
-
}
|
|
3860
|
-
collect_referenced_local_binding_names(node[key], shadowed_names, names);
|
|
3298
|
+
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3299
|
+
transform_context.inside_element_child = true;
|
|
3300
|
+
try {
|
|
3301
|
+
return [statement_body_to_jsx_child(children, transform_context)];
|
|
3302
|
+
} finally {
|
|
3303
|
+
transform_context.inside_element_child = saved_inside_element_child;
|
|
3861
3304
|
}
|
|
3862
3305
|
}
|
|
3863
3306
|
|
|
3864
3307
|
/**
|
|
3865
|
-
* @param {any}
|
|
3866
|
-
* @
|
|
3867
|
-
* @param {Set<string>} shadowed_names
|
|
3868
|
-
* @returns {string[]}
|
|
3308
|
+
* @param {any[]} children
|
|
3309
|
+
* @returns {boolean}
|
|
3869
3310
|
*/
|
|
3870
|
-
function
|
|
3871
|
-
|
|
3872
|
-
collect_referenced_outer_binding_names(node, available_bindings, shadowed_names, names);
|
|
3873
|
-
return [...names];
|
|
3311
|
+
function children_contain_return_semantics(children) {
|
|
3312
|
+
return children.some(child_contains_return_semantics);
|
|
3874
3313
|
}
|
|
3875
3314
|
|
|
3876
3315
|
/**
|
|
3877
3316
|
* @param {any} node
|
|
3878
|
-
* @
|
|
3879
|
-
* @param {Set<string>} shadowed_names
|
|
3880
|
-
* @param {Set<string>} names
|
|
3881
|
-
* @returns {void}
|
|
3317
|
+
* @returns {boolean}
|
|
3882
3318
|
*/
|
|
3883
|
-
function
|
|
3319
|
+
function child_contains_return_semantics(node) {
|
|
3884
3320
|
if (!node || typeof node !== 'object') {
|
|
3885
|
-
return;
|
|
3321
|
+
return false;
|
|
3886
3322
|
}
|
|
3887
3323
|
|
|
3888
|
-
if (node.type === '
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3324
|
+
if (node.type === 'ReturnStatement') {
|
|
3325
|
+
return true;
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
if (
|
|
3329
|
+
node.type === 'FunctionDeclaration' ||
|
|
3330
|
+
node.type === 'FunctionExpression' ||
|
|
3331
|
+
node.type === 'ArrowFunctionExpression'
|
|
3332
|
+
) {
|
|
3333
|
+
return false;
|
|
3893
3334
|
}
|
|
3894
3335
|
|
|
3895
3336
|
if (Array.isArray(node)) {
|
|
3896
|
-
|
|
3897
|
-
collect_referenced_outer_binding_names(child, available_bindings, shadowed_names, names);
|
|
3898
|
-
}
|
|
3899
|
-
return;
|
|
3337
|
+
return node.some(child_contains_return_semantics);
|
|
3900
3338
|
}
|
|
3901
3339
|
|
|
3902
3340
|
for (const key of Object.keys(node)) {
|
|
3903
3341
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3904
3342
|
continue;
|
|
3905
3343
|
}
|
|
3906
|
-
if (key
|
|
3907
|
-
|
|
3908
|
-
}
|
|
3909
|
-
if (key === 'key' && node.type === 'Property' && !node.computed && !node.shorthand) {
|
|
3910
|
-
continue;
|
|
3344
|
+
if (child_contains_return_semantics(node[key])) {
|
|
3345
|
+
return true;
|
|
3911
3346
|
}
|
|
3912
|
-
collect_referenced_outer_binding_names(node[key], available_bindings, shadowed_names, names);
|
|
3913
3347
|
}
|
|
3348
|
+
|
|
3349
|
+
return false;
|
|
3914
3350
|
}
|
|
3915
3351
|
|
|
3916
3352
|
/**
|
|
3917
3353
|
* @param {any} node
|
|
3918
|
-
* @returns {
|
|
3354
|
+
* @returns {boolean}
|
|
3919
3355
|
*/
|
|
3920
|
-
function
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
}
|
|
3924
|
-
|
|
3925
|
-
if (node.type === 'CallExpression' && is_hook_callee(node.callee)) {
|
|
3926
|
-
return get_hook_callee_name(node.callee);
|
|
3927
|
-
}
|
|
3356
|
+
function is_inline_element_child(node) {
|
|
3357
|
+
return node && is_render_child_node(node);
|
|
3358
|
+
}
|
|
3928
3359
|
|
|
3360
|
+
/**
|
|
3361
|
+
* @param {any[]} body_nodes
|
|
3362
|
+
* @param {TransformContext} transform_context
|
|
3363
|
+
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3364
|
+
*/
|
|
3365
|
+
function statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3929
3366
|
if (
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
node.type === 'ArrowFunctionExpression'
|
|
3367
|
+
should_extract_hook_helpers(transform_context) &&
|
|
3368
|
+
body_contains_top_level_hook_call(body_nodes, transform_context, true)
|
|
3933
3369
|
) {
|
|
3934
|
-
return
|
|
3370
|
+
return hook_safe_statement_body_to_jsx_child(body_nodes, transform_context);
|
|
3935
3371
|
}
|
|
3936
3372
|
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
}
|
|
3942
|
-
return null;
|
|
3943
|
-
}
|
|
3373
|
+
return to_jsx_expression_container(
|
|
3374
|
+
b.call(b.arrow([], b.block(build_render_statements(body_nodes, true, transform_context)))),
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3944
3377
|
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3378
|
+
/**
|
|
3379
|
+
* @param {any[]} body_nodes
|
|
3380
|
+
* @param {TransformContext} transform_context
|
|
3381
|
+
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3382
|
+
*/
|
|
3383
|
+
function hook_safe_statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3384
|
+
const source_node = get_body_source_node(body_nodes);
|
|
3385
|
+
const helper = create_hook_safe_helper(body_nodes, undefined, source_node, transform_context);
|
|
3952
3386
|
|
|
3953
|
-
return
|
|
3387
|
+
return to_jsx_expression_container(
|
|
3388
|
+
create_hook_safe_helper_iife(helper.setup_statements, helper.component_element),
|
|
3389
|
+
source_node,
|
|
3390
|
+
);
|
|
3954
3391
|
}
|
|
3955
3392
|
|
|
3956
3393
|
/**
|
|
3957
|
-
* @param {
|
|
3394
|
+
* @param {TransformContext} transform_context
|
|
3958
3395
|
* @returns {string}
|
|
3959
3396
|
*/
|
|
3960
|
-
function
|
|
3961
|
-
|
|
3962
|
-
|
|
3397
|
+
function create_local_statement_component_name(transform_context) {
|
|
3398
|
+
transform_context.local_statement_component_index += 1;
|
|
3399
|
+
return `StatementBodyHook${transform_context.local_statement_component_index}`;
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
/**
|
|
3403
|
+
* Wraps a list of body nodes into a component and returns
|
|
3404
|
+
* statements that return `<ComponentName prop1={prop1} ... />`.
|
|
3405
|
+
* Targets can either emit the helper component at module scope or cache the
|
|
3406
|
+
* component identity in module state while initializing it from the parent.
|
|
3407
|
+
* Used when a control flow branch contains hook calls that must be moved
|
|
3408
|
+
* into their own component boundary to satisfy the Rules of Hooks.
|
|
3409
|
+
*
|
|
3410
|
+
* @param {any[]} body_nodes
|
|
3411
|
+
* @param {any} key_expression - Optional key expression to add to the component element (for for-of loops)
|
|
3412
|
+
* @param {TransformContext} transform_context
|
|
3413
|
+
* @returns {any[]}
|
|
3414
|
+
*/
|
|
3415
|
+
function hook_safe_render_statements(body_nodes, key_expression, transform_context) {
|
|
3416
|
+
const source_node = get_body_source_node(body_nodes);
|
|
3417
|
+
const helper = create_hook_safe_helper(
|
|
3418
|
+
body_nodes,
|
|
3419
|
+
key_expression,
|
|
3420
|
+
source_node,
|
|
3421
|
+
transform_context,
|
|
3422
|
+
);
|
|
3423
|
+
const statements = [...helper.setup_statements];
|
|
3424
|
+
|
|
3425
|
+
statements.push(b.return(helper.component_element));
|
|
3426
|
+
|
|
3427
|
+
return statements;
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
/**
|
|
3431
|
+
* @param {any[]} body_nodes
|
|
3432
|
+
* @param {Map<string, AST.Identifier>} available_bindings
|
|
3433
|
+
* @returns {AST.Identifier[]}
|
|
3434
|
+
*/
|
|
3435
|
+
function get_referenced_helper_bindings(body_nodes, available_bindings) {
|
|
3436
|
+
const helper_bindings = [];
|
|
3437
|
+
const local_bindings = new Map();
|
|
3438
|
+
|
|
3439
|
+
for (const node of body_nodes) {
|
|
3440
|
+
collect_statement_bindings(node, local_bindings);
|
|
3963
3441
|
}
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3442
|
+
|
|
3443
|
+
for (const [name, binding] of available_bindings) {
|
|
3444
|
+
if (local_bindings.has(name)) continue;
|
|
3445
|
+
|
|
3446
|
+
if (references_scope_bindings(body_nodes, new Map([[name, binding]]))) {
|
|
3447
|
+
helper_bindings.push(binding);
|
|
3448
|
+
}
|
|
3970
3449
|
}
|
|
3971
|
-
|
|
3450
|
+
|
|
3451
|
+
return helper_bindings;
|
|
3972
3452
|
}
|
|
3973
3453
|
|
|
3974
3454
|
/**
|
|
@@ -3989,11 +3469,6 @@ export function create_hook_safe_helper(
|
|
|
3989
3469
|
preallocated_helper_id,
|
|
3990
3470
|
options = {},
|
|
3991
3471
|
) {
|
|
3992
|
-
validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
3993
|
-
body_nodes,
|
|
3994
|
-
transform_context,
|
|
3995
|
-
);
|
|
3996
|
-
|
|
3997
3472
|
const helper_id =
|
|
3998
3473
|
preallocated_helper_id ??
|
|
3999
3474
|
create_generated_identifier(create_local_statement_component_name(transform_context));
|
|
@@ -4314,31 +3789,38 @@ function is_native_tsrx_node(node) {
|
|
|
4314
3789
|
* @param {any} node
|
|
4315
3790
|
* @returns {boolean}
|
|
4316
3791
|
*/
|
|
4317
|
-
function
|
|
4318
|
-
return
|
|
4319
|
-
node?.type === 'JSXElement' &&
|
|
4320
|
-
(node.dynamic === true ||
|
|
4321
|
-
node.openingElement?.dynamic === true ||
|
|
4322
|
-
is_dynamic_jsx_name(node.openingElement?.name))
|
|
4323
|
-
);
|
|
4324
|
-
}
|
|
4325
|
-
|
|
4326
|
-
/**
|
|
4327
|
-
* @param {any} name
|
|
4328
|
-
* @returns {boolean}
|
|
4329
|
-
*/
|
|
4330
|
-
function is_dynamic_jsx_name(name) {
|
|
4331
|
-
if (!name || typeof name !== 'object') return false;
|
|
4332
|
-
if (name.dynamic === true) return true;
|
|
4333
|
-
return name.type === 'JSXMemberExpression' && is_dynamic_jsx_name(name.object);
|
|
3792
|
+
function is_if_control_node(node) {
|
|
3793
|
+
return node?.type === 'IfStatement' || node?.type === 'JSXIfExpression';
|
|
4334
3794
|
}
|
|
4335
3795
|
|
|
4336
3796
|
/**
|
|
4337
3797
|
* @param {any} node
|
|
4338
3798
|
* @returns {boolean}
|
|
4339
3799
|
*/
|
|
4340
|
-
function
|
|
4341
|
-
|
|
3800
|
+
function is_render_child_node(node) {
|
|
3801
|
+
if (!node) return false;
|
|
3802
|
+
|
|
3803
|
+
switch (node.type) {
|
|
3804
|
+
case 'JSXElement':
|
|
3805
|
+
case 'JSXFragment':
|
|
3806
|
+
case 'JSXExpressionContainer':
|
|
3807
|
+
case 'JSXText':
|
|
3808
|
+
case 'JSXIfExpression':
|
|
3809
|
+
case 'JSXForExpression':
|
|
3810
|
+
case 'JSXSwitchExpression':
|
|
3811
|
+
case 'JSXTryExpression':
|
|
3812
|
+
return true;
|
|
3813
|
+
case 'IfStatement':
|
|
3814
|
+
return is_template_if_node(node);
|
|
3815
|
+
case 'ForOfStatement':
|
|
3816
|
+
return is_template_for_of_node(node);
|
|
3817
|
+
case 'SwitchStatement':
|
|
3818
|
+
return is_template_switch_node(node);
|
|
3819
|
+
case 'TryStatement':
|
|
3820
|
+
return is_template_try_node(node);
|
|
3821
|
+
default:
|
|
3822
|
+
return false;
|
|
3823
|
+
}
|
|
4342
3824
|
}
|
|
4343
3825
|
|
|
4344
3826
|
/**
|
|
@@ -4357,17 +3839,6 @@ function is_try_control_node(node) {
|
|
|
4357
3839
|
return node?.type === 'TryStatement' || node?.type === 'JSXTryExpression';
|
|
4358
3840
|
}
|
|
4359
3841
|
|
|
4360
|
-
/**
|
|
4361
|
-
* @param {any} node
|
|
4362
|
-
* @returns {boolean}
|
|
4363
|
-
*/
|
|
4364
|
-
function is_for_of_control_node(node) {
|
|
4365
|
-
return (
|
|
4366
|
-
node?.type === 'ForOfStatement' ||
|
|
4367
|
-
(node?.type === 'JSXForExpression' && node.statementType === 'ForOfStatement')
|
|
4368
|
-
);
|
|
4369
|
-
}
|
|
4370
|
-
|
|
4371
3842
|
/**
|
|
4372
3843
|
* @param {any} node
|
|
4373
3844
|
* @param {TransformContext} transform_context
|
|
@@ -4380,9 +3851,6 @@ function to_jsx_child(node, transform_context) {
|
|
|
4380
3851
|
if (is_native_tsrx_node(node)) {
|
|
4381
3852
|
return to_jsx_element(node, transform_context, node.children || [], true);
|
|
4382
3853
|
}
|
|
4383
|
-
if (is_dynamic_jsx_element(node)) {
|
|
4384
|
-
return dynamic_element_to_jsx(node, transform_context, true);
|
|
4385
|
-
}
|
|
4386
3854
|
return node;
|
|
4387
3855
|
case 'JSXFragment':
|
|
4388
3856
|
if (is_native_tsrx_node(node)) {
|
|
@@ -4391,6 +3859,9 @@ function to_jsx_child(node, transform_context) {
|
|
|
4391
3859
|
return node;
|
|
4392
3860
|
case 'JSXIfExpression':
|
|
4393
3861
|
case 'IfStatement':
|
|
3862
|
+
if (node.type === 'IfStatement' && !is_template_if_node(node)) {
|
|
3863
|
+
return node;
|
|
3864
|
+
}
|
|
4394
3865
|
if (node.metadata?.generated_loop_skip_if) {
|
|
4395
3866
|
return node;
|
|
4396
3867
|
}
|
|
@@ -4412,17 +3883,26 @@ function to_jsx_child(node, transform_context) {
|
|
|
4412
3883
|
transform_context.platform.hooks?.controlFlow?.forOf ?? for_of_statement_to_jsx_child
|
|
4413
3884
|
)(jsx_control_expression_to_statement(node), transform_context);
|
|
4414
3885
|
case 'ForOfStatement':
|
|
3886
|
+
if (!is_template_for_of_node(node)) {
|
|
3887
|
+
return node;
|
|
3888
|
+
}
|
|
4415
3889
|
return (
|
|
4416
3890
|
transform_context.platform.hooks?.controlFlow?.forOf ?? for_of_statement_to_jsx_child
|
|
4417
3891
|
)(node, transform_context);
|
|
4418
3892
|
case 'JSXSwitchExpression':
|
|
4419
3893
|
case 'SwitchStatement':
|
|
3894
|
+
if (node.type === 'SwitchStatement' && !is_template_switch_node(node)) {
|
|
3895
|
+
return node;
|
|
3896
|
+
}
|
|
4420
3897
|
return (
|
|
4421
3898
|
transform_context.platform.hooks?.controlFlow?.switchStatement ??
|
|
4422
3899
|
switch_statement_to_jsx_child
|
|
4423
3900
|
)(jsx_control_expression_to_statement(node), transform_context);
|
|
4424
3901
|
case 'JSXTryExpression':
|
|
4425
3902
|
case 'TryStatement':
|
|
3903
|
+
if (node.type === 'TryStatement' && !is_template_try_node(node)) {
|
|
3904
|
+
return node;
|
|
3905
|
+
}
|
|
4426
3906
|
return (
|
|
4427
3907
|
transform_context.platform.hooks?.controlFlow?.tryStatement ?? try_statement_to_jsx_child
|
|
4428
3908
|
)(jsx_control_expression_to_statement(node), transform_context);
|
|
@@ -4910,6 +4390,42 @@ function is_template_if_node(node) {
|
|
|
4910
4390
|
);
|
|
4911
4391
|
}
|
|
4912
4392
|
|
|
4393
|
+
/**
|
|
4394
|
+
* @param {any} node
|
|
4395
|
+
* @returns {boolean}
|
|
4396
|
+
*/
|
|
4397
|
+
function is_template_for_of_node(node) {
|
|
4398
|
+
return (
|
|
4399
|
+
node?.type === 'JSXForExpression' ||
|
|
4400
|
+
node?.metadata?.tsrxDirective === 'for' ||
|
|
4401
|
+
(node?.type === 'ForOfStatement' && node?.statementType === 'ForOfStatement')
|
|
4402
|
+
);
|
|
4403
|
+
}
|
|
4404
|
+
|
|
4405
|
+
/**
|
|
4406
|
+
* @param {any} node
|
|
4407
|
+
* @returns {boolean}
|
|
4408
|
+
*/
|
|
4409
|
+
function is_template_switch_node(node) {
|
|
4410
|
+
return (
|
|
4411
|
+
node?.type === 'JSXSwitchExpression' ||
|
|
4412
|
+
node?.metadata?.tsrxDirective === 'switch' ||
|
|
4413
|
+
(node?.type === 'SwitchStatement' && node?.statementType === 'SwitchStatement')
|
|
4414
|
+
);
|
|
4415
|
+
}
|
|
4416
|
+
|
|
4417
|
+
/**
|
|
4418
|
+
* @param {any} node
|
|
4419
|
+
* @returns {boolean}
|
|
4420
|
+
*/
|
|
4421
|
+
function is_template_try_node(node) {
|
|
4422
|
+
return (
|
|
4423
|
+
node?.type === 'JSXTryExpression' ||
|
|
4424
|
+
node?.metadata?.tsrxDirective === 'try' ||
|
|
4425
|
+
(node?.type === 'TryStatement' && node?.statementType === 'TryStatement')
|
|
4426
|
+
);
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4913
4429
|
/**
|
|
4914
4430
|
* @param {any} node
|
|
4915
4431
|
* @returns {boolean}
|
|
@@ -5273,16 +4789,9 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5273
4789
|
// correctly identifies references to err/reset as non-static
|
|
5274
4790
|
const saved_catch_bindings = transform_context.available_bindings;
|
|
5275
4791
|
transform_context.available_bindings = new Map(saved_catch_bindings);
|
|
5276
|
-
const catch_scoped_names = new Set();
|
|
5277
4792
|
for (const param of catch_params) {
|
|
5278
4793
|
collect_pattern_bindings(param, transform_context.available_bindings);
|
|
5279
|
-
collect_pattern_names(param, catch_scoped_names);
|
|
5280
4794
|
}
|
|
5281
|
-
validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
5282
|
-
catch_body_nodes,
|
|
5283
|
-
transform_context,
|
|
5284
|
-
catch_scoped_names,
|
|
5285
|
-
);
|
|
5286
4795
|
|
|
5287
4796
|
const fallback_fn = b.arrow(
|
|
5288
4797
|
catch_params,
|
|
@@ -5707,7 +5216,7 @@ function build_switch_with_lift(switch_node, transform_context) {
|
|
|
5707
5216
|
has_terminal = true;
|
|
5708
5217
|
break;
|
|
5709
5218
|
}
|
|
5710
|
-
if (
|
|
5219
|
+
if (is_render_child_node(child)) {
|
|
5711
5220
|
render_nodes.push(to_jsx_child(child, transform_context));
|
|
5712
5221
|
} else if (is_bare_render_expression(child)) {
|
|
5713
5222
|
render_nodes.push(to_jsx_expression_container(child, child));
|
|
@@ -6266,57 +5775,6 @@ function value_has_unmappable_jsx_loc(value) {
|
|
|
6266
5775
|
);
|
|
6267
5776
|
}
|
|
6268
5777
|
|
|
6269
|
-
/**
|
|
6270
|
-
* @param {any} node
|
|
6271
|
-
* @param {TransformContext} transform_context
|
|
6272
|
-
* @param {boolean} in_jsx_child
|
|
6273
|
-
* @returns {any}
|
|
6274
|
-
*/
|
|
6275
|
-
function dynamic_element_to_jsx(node, transform_context, in_jsx_child) {
|
|
6276
|
-
const source_name = node.openingElement?.name;
|
|
6277
|
-
const dynamic_id = set_loc(create_generated_identifier('DynamicElement'), source_name || node);
|
|
6278
|
-
const alias_declaration = set_loc(
|
|
6279
|
-
b.const(dynamic_id, jsx_name_to_expression(source_name)),
|
|
6280
|
-
source_name || node,
|
|
6281
|
-
);
|
|
6282
|
-
const jsx_element = create_dynamic_jsx_element(dynamic_id, node, transform_context);
|
|
6283
|
-
|
|
6284
|
-
const expression = b.call(
|
|
6285
|
-
b.arrow(
|
|
6286
|
-
[],
|
|
6287
|
-
b.block([
|
|
6288
|
-
alias_declaration,
|
|
6289
|
-
b.return(b.conditional(clone_identifier(dynamic_id), jsx_element, create_null_literal())),
|
|
6290
|
-
]),
|
|
6291
|
-
),
|
|
6292
|
-
);
|
|
6293
|
-
|
|
6294
|
-
return in_jsx_child ? to_jsx_expression_container(expression, node) : set_loc(expression, node);
|
|
6295
|
-
}
|
|
6296
|
-
|
|
6297
|
-
/**
|
|
6298
|
-
* @param {AST.Identifier} dynamic_id
|
|
6299
|
-
* @param {any} node
|
|
6300
|
-
* @param {TransformContext} transform_context
|
|
6301
|
-
* @returns {ESTreeJSX.JSXElement}
|
|
6302
|
-
*/
|
|
6303
|
-
function create_dynamic_jsx_element(dynamic_id, node, transform_context) {
|
|
6304
|
-
const attributes = transform_element_attributes_dispatch(
|
|
6305
|
-
node.openingElement?.attributes || [],
|
|
6306
|
-
transform_context,
|
|
6307
|
-
node,
|
|
6308
|
-
);
|
|
6309
|
-
const selfClosing = !!node.openingElement?.selfClosing;
|
|
6310
|
-
const children = create_element_children(node.children || [], transform_context);
|
|
6311
|
-
const name = identifier_to_jsx_name(clone_identifier(dynamic_id));
|
|
6312
|
-
|
|
6313
|
-
return b.jsx_element_fresh(
|
|
6314
|
-
b.jsx_opening_element(name, attributes, selfClosing),
|
|
6315
|
-
selfClosing ? null : b.jsx_closing_element(clone_jsx_name(name)),
|
|
6316
|
-
children,
|
|
6317
|
-
);
|
|
6318
|
-
}
|
|
6319
|
-
|
|
6320
5778
|
/**
|
|
6321
5779
|
* @param {any[]} render_nodes
|
|
6322
5780
|
* @returns {any}
|