@tsrx/core 0.1.22 → 0.1.24
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 +225 -125
- 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 +703 -125
- package/src/transform/scoping.js +1 -1
- package/src/transform/segments.js +13 -43
- package/types/index.d.ts +2 -5
- package/types/jsx-platform.d.ts +8 -0
- 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';
|
|
@@ -64,7 +64,7 @@ const HOOK_CALLBACK_OUTER_MUTATION_ERROR =
|
|
|
64
64
|
const TEMPLATE_FRAGMENT_ERROR =
|
|
65
65
|
'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
66
|
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 @
|
|
67
|
+
'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
68
|
const TSRX_FOR_BREAK_ERROR =
|
|
69
69
|
'Break statements are not allowed inside TSRX template for...of loops.';
|
|
70
70
|
const TSRX_FOR_CONTINUE_ERROR =
|
|
@@ -223,6 +223,86 @@ function expand_child_code_blocks(node, seen = new Set()) {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
/**
|
|
227
|
+
* A `@`-prefixed JSX control-flow expression (`@if`/`@for`/`@switch`/`@try`).
|
|
228
|
+
* These are the only control-flow nodes that can appear in expression position;
|
|
229
|
+
* the plain statement forms (`IfStatement`, `SwitchStatement`, …) never do.
|
|
230
|
+
* @param {any} node
|
|
231
|
+
* @returns {boolean}
|
|
232
|
+
*/
|
|
233
|
+
function is_jsx_control_flow_expression(node) {
|
|
234
|
+
return (
|
|
235
|
+
node?.type === 'JSXIfExpression' ||
|
|
236
|
+
node?.type === 'JSXForExpression' ||
|
|
237
|
+
node?.type === 'JSXSwitchExpression' ||
|
|
238
|
+
node?.type === 'JSXTryExpression'
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Wrap a render-output node in a native TSRX fragment so it flows through the
|
|
244
|
+
* same single-child render path as a `<> … </>` output.
|
|
245
|
+
* @param {any} node
|
|
246
|
+
* @returns {any}
|
|
247
|
+
*/
|
|
248
|
+
function wrap_in_native_tsrx_fragment(node) {
|
|
249
|
+
const fragment = b.jsx_fragment([node]);
|
|
250
|
+
fragment.metadata = { ...(fragment.metadata || {}), native_tsrx: true };
|
|
251
|
+
return fragment;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Wrap a bare JSX control-flow directive that sits directly in an expression
|
|
256
|
+
* position — an expression-bodied arrow (`() => @switch (…) { … }`), a
|
|
257
|
+
* `return @switch (…) { … }`, an unused expression statement,
|
|
258
|
+
* assignment to a variable
|
|
259
|
+
* (`const x = @switch (…) { … }`, `x = @switch (…) { … }`), or a call/`new`
|
|
260
|
+
* argument (`render(@if (…) { … })`) — in a native TSRX fragment.
|
|
261
|
+
* @param {any} node
|
|
262
|
+
* @param {Set<any>} [seen]
|
|
263
|
+
* @returns {void}
|
|
264
|
+
*/
|
|
265
|
+
function wrap_control_flow_expression_values(node, seen = new Set()) {
|
|
266
|
+
if (!node || typeof node !== 'object' || seen.has(node)) return;
|
|
267
|
+
seen.add(node);
|
|
268
|
+
|
|
269
|
+
if (Array.isArray(node)) {
|
|
270
|
+
for (const item of node) wrap_control_flow_expression_values(item, seen);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (
|
|
275
|
+
node.type === 'ArrowFunctionExpression' &&
|
|
276
|
+
node.body?.type !== 'BlockStatement' &&
|
|
277
|
+
is_jsx_control_flow_expression(node.body)
|
|
278
|
+
) {
|
|
279
|
+
node.body = wrap_in_native_tsrx_fragment(node.body);
|
|
280
|
+
} else if (node.type === 'ReturnStatement' && is_jsx_control_flow_expression(node.argument)) {
|
|
281
|
+
node.argument = wrap_in_native_tsrx_fragment(node.argument);
|
|
282
|
+
} else if (
|
|
283
|
+
node.type === 'ExpressionStatement' &&
|
|
284
|
+
is_jsx_control_flow_expression(node.expression)
|
|
285
|
+
) {
|
|
286
|
+
node.expression = wrap_in_native_tsrx_fragment(node.expression);
|
|
287
|
+
} else if (node.type === 'VariableDeclarator' && is_jsx_control_flow_expression(node.init)) {
|
|
288
|
+
node.init = wrap_in_native_tsrx_fragment(node.init);
|
|
289
|
+
} else if (node.type === 'AssignmentExpression' && is_jsx_control_flow_expression(node.right)) {
|
|
290
|
+
node.right = wrap_in_native_tsrx_fragment(node.right);
|
|
291
|
+
} else if (
|
|
292
|
+
(node.type === 'CallExpression' || node.type === 'NewExpression') &&
|
|
293
|
+
Array.isArray(node.arguments)
|
|
294
|
+
) {
|
|
295
|
+
node.arguments = node.arguments.map((/** @type {any} */ arg) =>
|
|
296
|
+
is_jsx_control_flow_expression(arg) ? wrap_in_native_tsrx_fragment(arg) : arg,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
for (const key of Object.keys(node)) {
|
|
301
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') continue;
|
|
302
|
+
wrap_control_flow_expression_values(node[key], seen);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
226
306
|
/**
|
|
227
307
|
* Build a `transform()` function for a specific JSX platform (React, Preact,
|
|
228
308
|
* Solid). Given a `JsxPlatform` descriptor, returns a transform that lowers
|
|
@@ -273,6 +353,7 @@ export function createJsxTransform(platform) {
|
|
|
273
353
|
hook_helpers_enabled: false,
|
|
274
354
|
available_bindings: new Map(),
|
|
275
355
|
lazy_next_id: 0,
|
|
356
|
+
runtime_dynamic_scopes: null,
|
|
276
357
|
filename: filename ?? null,
|
|
277
358
|
source,
|
|
278
359
|
collect,
|
|
@@ -285,6 +366,11 @@ export function createJsxTransform(platform) {
|
|
|
285
366
|
};
|
|
286
367
|
|
|
287
368
|
expand_child_code_blocks(/** @type {any} */ (ast));
|
|
369
|
+
wrap_control_flow_expression_values(/** @type {any} */ (ast));
|
|
370
|
+
transform_context.runtime_dynamic_scopes = create_runtime_dynamic_scopes(
|
|
371
|
+
/** @type {any} */ (ast),
|
|
372
|
+
transform_context,
|
|
373
|
+
);
|
|
288
374
|
|
|
289
375
|
if (!transform_context.typeOnly) {
|
|
290
376
|
preallocate_lazy_ids(/** @type {any} */ (ast), transform_context);
|
|
@@ -321,10 +407,6 @@ export function createJsxTransform(platform) {
|
|
|
321
407
|
},
|
|
322
408
|
|
|
323
409
|
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
410
|
if (!node.metadata?.native_tsrx) {
|
|
329
411
|
return next() ?? node;
|
|
330
412
|
}
|
|
@@ -464,16 +546,26 @@ export function createJsxTransform(platform) {
|
|
|
464
546
|
*
|
|
465
547
|
* @param {any} component
|
|
466
548
|
* @param {any} css
|
|
549
|
+
* @param {TransformContext} transform_context
|
|
467
550
|
* @param {boolean} [export_top_scoped_classes]
|
|
468
551
|
* @returns {void}
|
|
469
552
|
*/
|
|
470
|
-
function apply_css_definition_metadata(
|
|
553
|
+
function apply_css_definition_metadata(
|
|
554
|
+
component,
|
|
555
|
+
css,
|
|
556
|
+
transform_context,
|
|
557
|
+
export_top_scoped_classes = false,
|
|
558
|
+
) {
|
|
471
559
|
analyze_css(css);
|
|
472
560
|
|
|
473
561
|
const metadata = component.metadata || (component.metadata = { path: [] });
|
|
474
562
|
const style_classes = metadata.styleClasses || (metadata.styleClasses = new Map());
|
|
475
563
|
const top_scoped_classes = metadata.topScopedClasses || new Map();
|
|
476
|
-
const elements = collect_css_prunable_elements(
|
|
564
|
+
const elements = collect_css_prunable_elements(
|
|
565
|
+
component.body || component.children || [],
|
|
566
|
+
[],
|
|
567
|
+
transform_context,
|
|
568
|
+
);
|
|
477
569
|
|
|
478
570
|
const prune = () => {
|
|
479
571
|
for (const element of elements) {
|
|
@@ -498,16 +590,17 @@ function apply_css_definition_metadata(component, css, export_top_scoped_classes
|
|
|
498
590
|
/**
|
|
499
591
|
* @param {any} value
|
|
500
592
|
* @param {any[]} [elements]
|
|
593
|
+
* @param {TransformContext | null} [transform_context]
|
|
501
594
|
* @returns {any[]}
|
|
502
595
|
*/
|
|
503
|
-
function collect_css_prunable_elements(value, elements = []) {
|
|
596
|
+
function collect_css_prunable_elements(value, elements = [], transform_context = null) {
|
|
504
597
|
if (!value || typeof value !== 'object') {
|
|
505
598
|
return elements;
|
|
506
599
|
}
|
|
507
600
|
|
|
508
601
|
if (Array.isArray(value)) {
|
|
509
602
|
for (const child of value) {
|
|
510
|
-
collect_css_prunable_elements(child, elements);
|
|
603
|
+
collect_css_prunable_elements(child, elements, transform_context);
|
|
511
604
|
}
|
|
512
605
|
return elements;
|
|
513
606
|
}
|
|
@@ -521,6 +614,7 @@ function collect_css_prunable_elements(value, elements = []) {
|
|
|
521
614
|
}
|
|
522
615
|
|
|
523
616
|
if (value.type === 'JSXElement' && value.metadata?.native_tsrx) {
|
|
617
|
+
mark_runtime_dynamic_element(value, transform_context);
|
|
524
618
|
if (!is_style_element(value)) {
|
|
525
619
|
elements.push(value);
|
|
526
620
|
}
|
|
@@ -530,12 +624,247 @@ function collect_css_prunable_elements(value, elements = []) {
|
|
|
530
624
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata' || key === 'css') {
|
|
531
625
|
continue;
|
|
532
626
|
}
|
|
533
|
-
collect_css_prunable_elements(value[key], elements);
|
|
627
|
+
collect_css_prunable_elements(value[key], elements, transform_context);
|
|
534
628
|
}
|
|
535
629
|
|
|
536
630
|
return elements;
|
|
537
631
|
}
|
|
538
632
|
|
|
633
|
+
/**
|
|
634
|
+
* @param {AST.Program} ast
|
|
635
|
+
* @param {TransformContext} transform_context
|
|
636
|
+
* @returns {Map<any, any> | null}
|
|
637
|
+
*/
|
|
638
|
+
function create_runtime_dynamic_scopes(ast, transform_context) {
|
|
639
|
+
const dynamic_source = transform_context.platform.imports.dynamic;
|
|
640
|
+
if (!dynamic_source) {
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
if (!has_runtime_dynamic_import(ast, dynamic_source)) {
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const { scopes } = create_scopes(ast, new ScopeRoot(), null, {
|
|
648
|
+
collect: true,
|
|
649
|
+
errors: [],
|
|
650
|
+
filename: transform_context.filename ?? '',
|
|
651
|
+
comments: transform_context.comments,
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
return scopes;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* @param {any} node
|
|
659
|
+
* @param {TransformContext | null} transform_context
|
|
660
|
+
* @returns {void}
|
|
661
|
+
*/
|
|
662
|
+
function mark_runtime_dynamic_element(node, transform_context) {
|
|
663
|
+
const dynamic_source = transform_context?.platform.imports.dynamic;
|
|
664
|
+
const scopes = transform_context?.runtime_dynamic_scopes;
|
|
665
|
+
if (
|
|
666
|
+
!dynamic_source ||
|
|
667
|
+
!scopes ||
|
|
668
|
+
node.metadata?.runtime_dynamic_element === true ||
|
|
669
|
+
!has_jsx_attribute(node, 'is') ||
|
|
670
|
+
!is_runtime_dynamic_jsx_name(node.openingElement?.name, scopes.get(node), dynamic_source)
|
|
671
|
+
) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
node.metadata.runtime_dynamic_element = true;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* @param {AST.Program} ast
|
|
680
|
+
* @param {string} dynamic_source
|
|
681
|
+
* @returns {boolean}
|
|
682
|
+
*/
|
|
683
|
+
function has_runtime_dynamic_import(ast, dynamic_source) {
|
|
684
|
+
return ast.body.some(
|
|
685
|
+
(/** @type {any} */ node) =>
|
|
686
|
+
node.type === 'ImportDeclaration' &&
|
|
687
|
+
node.importKind !== 'type' &&
|
|
688
|
+
node.source?.type === 'Literal' &&
|
|
689
|
+
node.source.value === dynamic_source &&
|
|
690
|
+
node.specifiers.some(
|
|
691
|
+
(/** @type {any} */ specifier) =>
|
|
692
|
+
is_runtime_dynamic_import_specifier(specifier, 'component') ||
|
|
693
|
+
is_runtime_dynamic_import_specifier(specifier, 'namespace'),
|
|
694
|
+
),
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* @param {any} node
|
|
700
|
+
* @param {string} name
|
|
701
|
+
* @returns {boolean}
|
|
702
|
+
*/
|
|
703
|
+
function has_jsx_attribute(node, name) {
|
|
704
|
+
return (node.openingElement?.attributes ?? []).some(
|
|
705
|
+
(/** @type {any} */ attr) =>
|
|
706
|
+
attr.type === 'JSXAttribute' &&
|
|
707
|
+
attr.name?.type === 'JSXIdentifier' &&
|
|
708
|
+
attr.name.name === name,
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* @param {any} name
|
|
714
|
+
* @param {any} scope
|
|
715
|
+
* @param {string} dynamic_source
|
|
716
|
+
* @returns {boolean}
|
|
717
|
+
*/
|
|
718
|
+
function is_runtime_dynamic_jsx_name(name, scope, dynamic_source) {
|
|
719
|
+
if (!scope || !name) {
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (name.type === 'JSXIdentifier') {
|
|
724
|
+
return is_runtime_dynamic_binding(scope.get(name.name), dynamic_source, 'component', new Set());
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (
|
|
728
|
+
name.type === 'JSXMemberExpression' &&
|
|
729
|
+
name.object?.type === 'JSXIdentifier' &&
|
|
730
|
+
name.property?.type === 'JSXIdentifier' &&
|
|
731
|
+
name.property.name === 'Dynamic'
|
|
732
|
+
) {
|
|
733
|
+
return is_runtime_dynamic_binding(
|
|
734
|
+
scope.get(name.object.name),
|
|
735
|
+
dynamic_source,
|
|
736
|
+
'namespace',
|
|
737
|
+
new Set(),
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* @param {any} binding
|
|
746
|
+
* @param {string} dynamic_source
|
|
747
|
+
* @param {'component' | 'namespace'} kind
|
|
748
|
+
* @param {Set<any>} seen
|
|
749
|
+
* @returns {boolean}
|
|
750
|
+
*/
|
|
751
|
+
function is_runtime_dynamic_binding(binding, dynamic_source, kind, seen) {
|
|
752
|
+
if (!binding || seen.has(binding)) {
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
seen.add(binding);
|
|
756
|
+
|
|
757
|
+
if (is_runtime_dynamic_import_binding(binding, dynamic_source, kind)) {
|
|
758
|
+
return true;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
if (binding.reassigned) {
|
|
762
|
+
return false;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const initial = unwrap_reference_expression(binding.initial);
|
|
766
|
+
if (!initial) {
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (initial.type === 'Identifier') {
|
|
771
|
+
return is_runtime_dynamic_binding(binding.scope.get(initial.name), dynamic_source, kind, seen);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (
|
|
775
|
+
kind === 'component' &&
|
|
776
|
+
initial.type === 'MemberExpression' &&
|
|
777
|
+
!initial.computed &&
|
|
778
|
+
initial.object?.type === 'Identifier' &&
|
|
779
|
+
initial.property?.type === 'Identifier' &&
|
|
780
|
+
initial.property.name === 'Dynamic'
|
|
781
|
+
) {
|
|
782
|
+
return is_runtime_dynamic_binding(
|
|
783
|
+
binding.scope.get(initial.object.name),
|
|
784
|
+
dynamic_source,
|
|
785
|
+
'namespace',
|
|
786
|
+
new Set(),
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* @param {any} binding
|
|
795
|
+
* @param {string} dynamic_source
|
|
796
|
+
* @param {'component' | 'namespace'} kind
|
|
797
|
+
* @returns {boolean}
|
|
798
|
+
*/
|
|
799
|
+
function is_runtime_dynamic_import_binding(binding, dynamic_source, kind) {
|
|
800
|
+
const declaration = binding?.initial;
|
|
801
|
+
if (
|
|
802
|
+
binding?.declaration_kind !== 'import' ||
|
|
803
|
+
declaration?.type !== 'ImportDeclaration' ||
|
|
804
|
+
declaration.importKind === 'type' ||
|
|
805
|
+
declaration.source?.type !== 'Literal' ||
|
|
806
|
+
declaration.source.value !== dynamic_source
|
|
807
|
+
) {
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
return declaration.specifiers.some(
|
|
812
|
+
(/** @type {any} */ specifier) =>
|
|
813
|
+
specifier.local?.name === binding.node?.name &&
|
|
814
|
+
is_runtime_dynamic_import_specifier(specifier, kind),
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* @param {any} specifier
|
|
820
|
+
* @param {'component' | 'namespace'} kind
|
|
821
|
+
* @returns {boolean}
|
|
822
|
+
*/
|
|
823
|
+
function is_runtime_dynamic_import_specifier(specifier, kind) {
|
|
824
|
+
if (kind === 'namespace') {
|
|
825
|
+
return specifier.type === 'ImportNamespaceSpecifier';
|
|
826
|
+
}
|
|
827
|
+
return (
|
|
828
|
+
specifier.type === 'ImportSpecifier' &&
|
|
829
|
+
specifier.importKind !== 'type' &&
|
|
830
|
+
get_imported_name(specifier) === 'Dynamic'
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* @param {any} specifier
|
|
836
|
+
* @returns {string | null}
|
|
837
|
+
*/
|
|
838
|
+
function get_imported_name(specifier) {
|
|
839
|
+
const imported = specifier.imported;
|
|
840
|
+
if (imported?.type === 'Identifier') {
|
|
841
|
+
return imported.name;
|
|
842
|
+
}
|
|
843
|
+
if (imported?.type === 'Literal') {
|
|
844
|
+
return String(imported.value);
|
|
845
|
+
}
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @param {any} expression
|
|
851
|
+
* @returns {any}
|
|
852
|
+
*/
|
|
853
|
+
function unwrap_reference_expression(expression) {
|
|
854
|
+
let node = expression;
|
|
855
|
+
while (
|
|
856
|
+
node &&
|
|
857
|
+
(node.type === 'TSAsExpression' ||
|
|
858
|
+
node.type === 'TSTypeAssertion' ||
|
|
859
|
+
node.type === 'TSNonNullExpression' ||
|
|
860
|
+
node.type === 'ParenthesizedExpression' ||
|
|
861
|
+
node.type === 'ChainExpression')
|
|
862
|
+
) {
|
|
863
|
+
node = node.expression;
|
|
864
|
+
}
|
|
865
|
+
return node;
|
|
866
|
+
}
|
|
867
|
+
|
|
539
868
|
/**
|
|
540
869
|
* @param {any[]} body_nodes
|
|
541
870
|
* @param {TransformContext} transform_context
|
|
@@ -598,7 +927,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
598
927
|
(node) =>
|
|
599
928
|
!is_loop_skip_return_statement(node) &&
|
|
600
929
|
!is_loop_skip_if_statement(node) &&
|
|
601
|
-
!
|
|
930
|
+
!is_render_child_node(node),
|
|
602
931
|
);
|
|
603
932
|
|
|
604
933
|
if (!continuation_has_setup_statements) {
|
|
@@ -640,7 +969,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
640
969
|
}
|
|
641
970
|
|
|
642
971
|
if (
|
|
643
|
-
|
|
972
|
+
is_template_for_of_node(child) &&
|
|
644
973
|
!child.await &&
|
|
645
974
|
should_extract_hook_helpers(transform_context) &&
|
|
646
975
|
!transform_context.platform.hooks?.isTopLevelSetupCall &&
|
|
@@ -668,7 +997,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
668
997
|
}
|
|
669
998
|
}
|
|
670
999
|
|
|
671
|
-
if (
|
|
1000
|
+
if (is_render_child_node(child)) {
|
|
672
1001
|
const jsx = to_jsx_child(child, transform_context);
|
|
673
1002
|
statements.push(...extract_jsx_setup_declarations(jsx));
|
|
674
1003
|
if (interleaved && is_capturable_jsx_child(jsx)) {
|
|
@@ -705,7 +1034,7 @@ function build_render_statements(body_nodes, return_null_when_empty, transform_c
|
|
|
705
1034
|
* @returns {boolean}
|
|
706
1035
|
*/
|
|
707
1036
|
function is_interleaved_body(body_nodes) {
|
|
708
|
-
return is_interleaved_body_core(body_nodes,
|
|
1037
|
+
return is_interleaved_body_core(body_nodes, is_render_child_node);
|
|
709
1038
|
}
|
|
710
1039
|
|
|
711
1040
|
/**
|
|
@@ -714,10 +1043,12 @@ function is_interleaved_body(body_nodes) {
|
|
|
714
1043
|
* @returns {boolean}
|
|
715
1044
|
*/
|
|
716
1045
|
function needs_hook_split(node, transform_context) {
|
|
1046
|
+
const body = node.body?.body || [];
|
|
717
1047
|
return (
|
|
718
1048
|
transform_context.platform.hooks?.componentBodyHookHelpers === true &&
|
|
719
1049
|
node.body?.type === 'BlockStatement' &&
|
|
720
|
-
find_hook_split_index(
|
|
1050
|
+
(find_hook_split_index(body, transform_context) !== -1 ||
|
|
1051
|
+
body_contains_component_body_branch_hook_return(body, transform_context))
|
|
721
1052
|
);
|
|
722
1053
|
}
|
|
723
1054
|
|
|
@@ -735,29 +1066,35 @@ function create_hook_split_block(node, transform_context) {
|
|
|
735
1066
|
return null;
|
|
736
1067
|
}
|
|
737
1068
|
|
|
738
|
-
const
|
|
1069
|
+
const source_body = node.body.body || [];
|
|
1070
|
+
const branch_rewrite = rewrite_component_body_branch_hook_returns(source_body, transform_context);
|
|
1071
|
+
const body = branch_rewrite.body;
|
|
739
1072
|
const split_index = find_hook_split_index(body, transform_context);
|
|
740
|
-
if (split_index === -1) {
|
|
1073
|
+
if (split_index === -1 && !branch_rewrite.changed) {
|
|
741
1074
|
return null;
|
|
742
1075
|
}
|
|
743
1076
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1077
|
+
let block_body;
|
|
1078
|
+
if (split_index === -1) {
|
|
1079
|
+
block_body = expand_native_tsrx_return_statement_list(body, transform_context);
|
|
1080
|
+
} else {
|
|
1081
|
+
const split_statement = body[split_index];
|
|
1082
|
+
const continuation_body = body.slice(split_index + 1);
|
|
1083
|
+
const helper = create_hook_safe_helper(
|
|
1084
|
+
expand_native_tsrx_return_statement_list(continuation_body, transform_context),
|
|
1085
|
+
undefined,
|
|
1086
|
+
get_body_source_node(continuation_body) || split_statement,
|
|
1087
|
+
transform_context,
|
|
1088
|
+
);
|
|
752
1089
|
|
|
753
|
-
|
|
754
|
-
[
|
|
1090
|
+
block_body = [
|
|
755
1091
|
...body.slice(0, split_index + 1),
|
|
756
1092
|
...helper.setup_statements,
|
|
757
1093
|
set_loc(b.return(helper.component_element), split_statement),
|
|
758
|
-
]
|
|
759
|
-
|
|
760
|
-
|
|
1094
|
+
];
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
const block = b.block(block_body, node.body);
|
|
761
1098
|
block.metadata = {
|
|
762
1099
|
...(block.metadata || {}),
|
|
763
1100
|
hook_split_block: true,
|
|
@@ -765,6 +1102,228 @@ function create_hook_split_block(node, transform_context) {
|
|
|
765
1102
|
return block;
|
|
766
1103
|
}
|
|
767
1104
|
|
|
1105
|
+
/**
|
|
1106
|
+
* @param {any[]} body_nodes
|
|
1107
|
+
* @param {TransformContext} transform_context
|
|
1108
|
+
* @returns {boolean}
|
|
1109
|
+
*/
|
|
1110
|
+
function body_contains_component_body_branch_hook_return(body_nodes, transform_context) {
|
|
1111
|
+
return body_nodes.some((node) =>
|
|
1112
|
+
statement_contains_component_body_branch_hook_return(node, transform_context),
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
/**
|
|
1117
|
+
* @param {any} node
|
|
1118
|
+
* @param {TransformContext} transform_context
|
|
1119
|
+
* @returns {boolean}
|
|
1120
|
+
*/
|
|
1121
|
+
function statement_contains_component_body_branch_hook_return(node, transform_context) {
|
|
1122
|
+
if (!node || typeof node !== 'object') {
|
|
1123
|
+
return false;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
if (Array.isArray(node)) {
|
|
1127
|
+
return body_contains_component_body_branch_hook_return(node, transform_context);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
if (is_function_or_class_boundary(node)) {
|
|
1131
|
+
return false;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
if (is_plain_if_statement(node)) {
|
|
1135
|
+
return (
|
|
1136
|
+
branch_needs_component_body_hook_helper(node.consequent, transform_context) ||
|
|
1137
|
+
statement_contains_component_body_branch_hook_return(node.consequent, transform_context) ||
|
|
1138
|
+
branch_needs_component_body_hook_helper(node.alternate, transform_context) ||
|
|
1139
|
+
statement_contains_component_body_branch_hook_return(node.alternate, transform_context)
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
if (node.type === 'BlockStatement') {
|
|
1144
|
+
return body_contains_component_body_branch_hook_return(node.body || [], transform_context);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
return false;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* @param {any[]} body_nodes
|
|
1152
|
+
* @param {TransformContext} transform_context
|
|
1153
|
+
* @returns {{ body: any[], changed: boolean }}
|
|
1154
|
+
*/
|
|
1155
|
+
function rewrite_component_body_branch_hook_returns(body_nodes, transform_context) {
|
|
1156
|
+
let changed = false;
|
|
1157
|
+
const body = body_nodes.map((node) => {
|
|
1158
|
+
const next_node = rewrite_component_body_branch_hook_return_statement(node, transform_context);
|
|
1159
|
+
if (next_node !== node) {
|
|
1160
|
+
changed = true;
|
|
1161
|
+
}
|
|
1162
|
+
return next_node;
|
|
1163
|
+
});
|
|
1164
|
+
return changed ? { body, changed } : { body: body_nodes, changed: false };
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* @param {any} node
|
|
1169
|
+
* @param {TransformContext} transform_context
|
|
1170
|
+
* @returns {any}
|
|
1171
|
+
*/
|
|
1172
|
+
function rewrite_component_body_branch_hook_return_statement(node, transform_context) {
|
|
1173
|
+
if (!node || typeof node !== 'object' || is_function_or_class_boundary(node)) {
|
|
1174
|
+
return node;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
if (is_plain_if_statement(node)) {
|
|
1178
|
+
const consequent = rewrite_component_body_hook_return_branch(
|
|
1179
|
+
node.consequent,
|
|
1180
|
+
transform_context,
|
|
1181
|
+
);
|
|
1182
|
+
const alternate = node.alternate
|
|
1183
|
+
? rewrite_component_body_hook_return_branch(node.alternate, transform_context)
|
|
1184
|
+
: { node: node.alternate, changed: false };
|
|
1185
|
+
|
|
1186
|
+
if (!consequent.changed && !alternate.changed) {
|
|
1187
|
+
return node;
|
|
1188
|
+
}
|
|
1189
|
+
return set_loc(b.if(node.test, consequent.node, alternate.node), node);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
if (node.type === 'BlockStatement') {
|
|
1193
|
+
const rewritten = rewrite_component_body_branch_hook_returns(
|
|
1194
|
+
node.body || [],
|
|
1195
|
+
transform_context,
|
|
1196
|
+
);
|
|
1197
|
+
return rewritten.changed ? set_loc(b.block(rewritten.body, node), node) : node;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
return node;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
/**
|
|
1204
|
+
* @param {any} branch
|
|
1205
|
+
* @param {TransformContext} transform_context
|
|
1206
|
+
* @returns {{ node: any, changed: boolean }}
|
|
1207
|
+
*/
|
|
1208
|
+
function rewrite_component_body_hook_return_branch(branch, transform_context) {
|
|
1209
|
+
if (!branch || typeof branch !== 'object') {
|
|
1210
|
+
return { node: branch, changed: false };
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
if (is_plain_if_statement(branch)) {
|
|
1214
|
+
const next_node = rewrite_component_body_branch_hook_return_statement(
|
|
1215
|
+
branch,
|
|
1216
|
+
transform_context,
|
|
1217
|
+
);
|
|
1218
|
+
return { node: next_node, changed: next_node !== branch };
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
const branch_body = branch.type === 'BlockStatement' ? branch.body || [] : [branch];
|
|
1222
|
+
const rewritten = rewrite_component_body_branch_hook_returns(branch_body, transform_context);
|
|
1223
|
+
const body = rewritten.body;
|
|
1224
|
+
const needs_helper = branch_needs_component_body_hook_helper_body(body, transform_context);
|
|
1225
|
+
|
|
1226
|
+
if (!needs_helper) {
|
|
1227
|
+
if (!rewritten.changed) {
|
|
1228
|
+
return { node: branch, changed: false };
|
|
1229
|
+
}
|
|
1230
|
+
const node =
|
|
1231
|
+
branch.type === 'BlockStatement'
|
|
1232
|
+
? set_loc(b.block(body, branch), branch)
|
|
1233
|
+
: (body[0] ?? branch);
|
|
1234
|
+
return { node, changed: true };
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
const helper_body = expand_native_tsrx_return_statement_list(body, transform_context);
|
|
1238
|
+
const helper = create_hook_safe_helper(
|
|
1239
|
+
helper_body,
|
|
1240
|
+
undefined,
|
|
1241
|
+
get_body_source_node(body) || branch,
|
|
1242
|
+
transform_context,
|
|
1243
|
+
);
|
|
1244
|
+
const node = set_loc(
|
|
1245
|
+
b.block([...helper.setup_statements, set_loc(b.return(helper.component_element), branch)]),
|
|
1246
|
+
branch,
|
|
1247
|
+
);
|
|
1248
|
+
return { node, changed: true };
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* @param {any} branch
|
|
1253
|
+
* @param {TransformContext} transform_context
|
|
1254
|
+
* @returns {boolean}
|
|
1255
|
+
*/
|
|
1256
|
+
function branch_needs_component_body_hook_helper(branch, transform_context) {
|
|
1257
|
+
if (!branch || typeof branch !== 'object' || is_plain_if_statement(branch)) {
|
|
1258
|
+
return false;
|
|
1259
|
+
}
|
|
1260
|
+
const body = branch.type === 'BlockStatement' ? branch.body || [] : [branch];
|
|
1261
|
+
return branch_needs_component_body_hook_helper_body(body, transform_context);
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* @param {any[]} body
|
|
1266
|
+
* @param {TransformContext} transform_context
|
|
1267
|
+
* @returns {boolean}
|
|
1268
|
+
*/
|
|
1269
|
+
function branch_needs_component_body_hook_helper_body(body, transform_context) {
|
|
1270
|
+
return (
|
|
1271
|
+
body_has_top_level_component_body_return(body) &&
|
|
1272
|
+
body_contains_direct_top_level_hook_call(body, transform_context, true)
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* @param {any[]} body
|
|
1278
|
+
* @returns {boolean}
|
|
1279
|
+
*/
|
|
1280
|
+
function body_has_top_level_component_body_return(body) {
|
|
1281
|
+
return body.some((node) => node?.type === 'ReturnStatement');
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
* @param {any[]} body
|
|
1286
|
+
* @param {TransformContext} transform_context
|
|
1287
|
+
* @param {boolean} include_platform_setup
|
|
1288
|
+
* @returns {boolean}
|
|
1289
|
+
*/
|
|
1290
|
+
function body_contains_direct_top_level_hook_call(body, transform_context, include_platform_setup) {
|
|
1291
|
+
return body.some((node) =>
|
|
1292
|
+
statement_contains_direct_top_level_hook_call(node, transform_context, include_platform_setup),
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* @param {any} node
|
|
1298
|
+
* @param {TransformContext} transform_context
|
|
1299
|
+
* @param {boolean} include_platform_setup
|
|
1300
|
+
* @returns {boolean}
|
|
1301
|
+
*/
|
|
1302
|
+
function statement_contains_direct_top_level_hook_call(
|
|
1303
|
+
node,
|
|
1304
|
+
transform_context,
|
|
1305
|
+
include_platform_setup,
|
|
1306
|
+
) {
|
|
1307
|
+
if (!node || typeof node !== 'object') {
|
|
1308
|
+
return false;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
if (is_function_or_class_boundary(node)) {
|
|
1312
|
+
return false;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
if (
|
|
1316
|
+
is_plain_if_statement(node) ||
|
|
1317
|
+
is_switch_control_node(node) ||
|
|
1318
|
+
is_try_control_node(node) ||
|
|
1319
|
+
is_for_of_control_node(node)
|
|
1320
|
+
) {
|
|
1321
|
+
return false;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
return statement_contains_top_level_hook_call(node, transform_context, include_platform_setup);
|
|
1325
|
+
}
|
|
1326
|
+
|
|
768
1327
|
/**
|
|
769
1328
|
* @param {any[]} body_nodes
|
|
770
1329
|
* @param {TransformContext} transform_context
|
|
@@ -1114,7 +1673,7 @@ function transform_block_statement(node, { next, visit, state, path }) {
|
|
|
1114
1673
|
}
|
|
1115
1674
|
}
|
|
1116
1675
|
|
|
1117
|
-
if (get_active_native_tsrx_function(path)) {
|
|
1676
|
+
if (get_active_native_tsrx_function(path)?.metadata?.native_tsrx_body) {
|
|
1118
1677
|
const block = create_native_tsrx_statement_list_block(node, state);
|
|
1119
1678
|
if (block) {
|
|
1120
1679
|
return visit(block, state);
|
|
@@ -1130,7 +1689,22 @@ function transform_block_statement(node, { next, visit, state, path }) {
|
|
|
1130
1689
|
* @returns {any}
|
|
1131
1690
|
*/
|
|
1132
1691
|
function transform_return_statement(node, { next, visit, state, path }) {
|
|
1133
|
-
|
|
1692
|
+
const active_native_tsrx_function = get_active_native_tsrx_function(path);
|
|
1693
|
+
if (active_native_tsrx_function && is_native_tsrx_node(node.argument)) {
|
|
1694
|
+
if (!active_native_tsrx_function.metadata?.native_tsrx_body) {
|
|
1695
|
+
const statements = mark_native_pretransformed_jsx(
|
|
1696
|
+
create_native_tsrx_render_statements(node.argument, state),
|
|
1697
|
+
);
|
|
1698
|
+
if (statements.length === 1) {
|
|
1699
|
+
return visit(statements[0], state);
|
|
1700
|
+
}
|
|
1701
|
+
const block = b.block(statements, node.argument);
|
|
1702
|
+
block.metadata = {
|
|
1703
|
+
...(block.metadata || {}),
|
|
1704
|
+
native_return_block: true,
|
|
1705
|
+
};
|
|
1706
|
+
return visit(block, state);
|
|
1707
|
+
}
|
|
1134
1708
|
return visit(create_native_tsrx_render_block(node.argument, state), state);
|
|
1135
1709
|
}
|
|
1136
1710
|
|
|
@@ -1190,10 +1764,17 @@ function transform_function(node, context) {
|
|
|
1190
1764
|
// render output. The parser already marks the render JSX as native_tsrx, so
|
|
1191
1765
|
// from here it flows through the existing native-component machinery exactly
|
|
1192
1766
|
// like the older fenced `{ return <> … </> }` shape.
|
|
1767
|
+
const has_jsx_code_block_body = node.body?.type === 'JSXCodeBlock';
|
|
1193
1768
|
lower_jsx_code_block_function_body(node);
|
|
1194
1769
|
|
|
1195
|
-
if (
|
|
1196
|
-
|
|
1770
|
+
if (
|
|
1771
|
+
has_jsx_code_block_body ||
|
|
1772
|
+
node.metadata?.native_tsrx_function ||
|
|
1773
|
+
function_has_native_tsrx_return(node)
|
|
1774
|
+
) {
|
|
1775
|
+
return transform_native_tsrx_function(node, context, {
|
|
1776
|
+
nativeBody: has_jsx_code_block_body || !!node.metadata?.native_tsrx_function,
|
|
1777
|
+
});
|
|
1197
1778
|
}
|
|
1198
1779
|
|
|
1199
1780
|
return transform_function_with_hook_helpers(node, context);
|
|
@@ -1230,9 +1811,10 @@ function lower_jsx_code_block_function_body(node) {
|
|
|
1230
1811
|
/**
|
|
1231
1812
|
* @param {any} node
|
|
1232
1813
|
* @param {{ next: () => any, state: TransformContext }} context
|
|
1814
|
+
* @param {{ nativeBody?: boolean }} [options]
|
|
1233
1815
|
* @returns {any}
|
|
1234
1816
|
*/
|
|
1235
|
-
function transform_native_tsrx_function(node, { next, state }) {
|
|
1817
|
+
function transform_native_tsrx_function(node, { next, state }, { nativeBody = false } = {}) {
|
|
1236
1818
|
const helper_state =
|
|
1237
1819
|
state.helper_state || create_helper_state(get_function_helper_base_name(node));
|
|
1238
1820
|
const saved_helper_state = state.helper_state;
|
|
@@ -1244,7 +1826,8 @@ function transform_native_tsrx_function(node, { next, state }) {
|
|
|
1244
1826
|
node.metadata = {
|
|
1245
1827
|
...(node.metadata || {}),
|
|
1246
1828
|
native_tsrx: true,
|
|
1247
|
-
...(
|
|
1829
|
+
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1830
|
+
...(nativeBody && needs_hook_split(node, state) ? { hook_split: true } : {}),
|
|
1248
1831
|
};
|
|
1249
1832
|
state.available_bindings = merge_binding_maps(
|
|
1250
1833
|
saved_bindings,
|
|
@@ -1270,6 +1853,7 @@ function transform_native_tsrx_function(node, { next, state }) {
|
|
|
1270
1853
|
inner.metadata = {
|
|
1271
1854
|
...strip_function_transform_metadata(inner.metadata),
|
|
1272
1855
|
native_tsrx_function: true,
|
|
1856
|
+
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1273
1857
|
...(!saved_helper_state ? create_generated_helper_metadata(helper_state) || {} : {}),
|
|
1274
1858
|
};
|
|
1275
1859
|
|
|
@@ -1396,12 +1980,7 @@ function find_native_await_in_statement(statement) {
|
|
|
1396
1980
|
*/
|
|
1397
1981
|
function transform_function_with_hook_helpers(node, { next, state }) {
|
|
1398
1982
|
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
|
-
) {
|
|
1983
|
+
if (state.helper_state || !is_uppercase_function_like(node) || !has_hook_bearing_tsrx) {
|
|
1405
1984
|
return next() ?? node;
|
|
1406
1985
|
}
|
|
1407
1986
|
|
|
@@ -1412,12 +1991,6 @@ function transform_function_with_hook_helpers(node, { next, state }) {
|
|
|
1412
1991
|
|
|
1413
1992
|
state.helper_state = helper_state;
|
|
1414
1993
|
state.hook_helpers_enabled = true;
|
|
1415
|
-
if (has_hook_split) {
|
|
1416
|
-
node.metadata = {
|
|
1417
|
-
...(node.metadata || {}),
|
|
1418
|
-
hook_split: true,
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
1994
|
state.available_bindings = collect_function_scope_bindings(node);
|
|
1422
1995
|
|
|
1423
1996
|
const inner = /** @type {any} */ (next() ?? node);
|
|
@@ -1681,7 +2254,7 @@ function prepare_tsrx_fragment_styles(node, transform_context) {
|
|
|
1681
2254
|
if (!css) return null;
|
|
1682
2255
|
|
|
1683
2256
|
const style_refs = collect_style_ref_attributes(node);
|
|
1684
|
-
apply_css_definition_metadata(node, css, style_refs.length > 0);
|
|
2257
|
+
apply_css_definition_metadata(node, css, transform_context, style_refs.length > 0);
|
|
1685
2258
|
transform_context.stylesheets.push(css);
|
|
1686
2259
|
const fragment = annotate_tsrx_with_hash(
|
|
1687
2260
|
node,
|
|
@@ -3056,7 +3629,7 @@ function to_jsx_element(
|
|
|
3056
3629
|
raw_children = node.children || [],
|
|
3057
3630
|
in_jsx_child = false,
|
|
3058
3631
|
) {
|
|
3059
|
-
if (node.type === 'JSXElement' && !node.metadata?.native_tsrx
|
|
3632
|
+
if (node.type === 'JSXElement' && !node.metadata?.native_tsrx) {
|
|
3060
3633
|
return node;
|
|
3061
3634
|
}
|
|
3062
3635
|
|
|
@@ -3066,10 +3639,6 @@ function to_jsx_element(
|
|
|
3066
3639
|
report_jsx_fragment_in_tsrx_error(node, transform_context);
|
|
3067
3640
|
return set_loc(b.jsx_fragment(), node);
|
|
3068
3641
|
}
|
|
3069
|
-
if (is_dynamic_jsx_element(node)) {
|
|
3070
|
-
return dynamic_element_to_jsx(node, transform_context, in_jsx_child);
|
|
3071
|
-
}
|
|
3072
|
-
|
|
3073
3642
|
const name = clone_jsx_name(source_name);
|
|
3074
3643
|
const attributes = transform_element_attributes_dispatch(
|
|
3075
3644
|
source_opening.attributes || [],
|
|
@@ -3205,7 +3774,7 @@ function child_contains_return_semantics(node) {
|
|
|
3205
3774
|
* @returns {boolean}
|
|
3206
3775
|
*/
|
|
3207
3776
|
function is_inline_element_child(node) {
|
|
3208
|
-
return node &&
|
|
3777
|
+
return node && is_render_child_node(node);
|
|
3209
3778
|
}
|
|
3210
3779
|
|
|
3211
3780
|
/**
|
|
@@ -4314,31 +4883,46 @@ function is_native_tsrx_node(node) {
|
|
|
4314
4883
|
* @param {any} node
|
|
4315
4884
|
* @returns {boolean}
|
|
4316
4885
|
*/
|
|
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
|
-
);
|
|
4886
|
+
function is_if_control_node(node) {
|
|
4887
|
+
return node?.type === 'IfStatement' || node?.type === 'JSXIfExpression';
|
|
4324
4888
|
}
|
|
4325
4889
|
|
|
4326
4890
|
/**
|
|
4327
|
-
* @param {any}
|
|
4891
|
+
* @param {any} node
|
|
4328
4892
|
* @returns {boolean}
|
|
4329
4893
|
*/
|
|
4330
|
-
function
|
|
4331
|
-
|
|
4332
|
-
if (name.dynamic === true) return true;
|
|
4333
|
-
return name.type === 'JSXMemberExpression' && is_dynamic_jsx_name(name.object);
|
|
4894
|
+
function is_plain_if_statement(node) {
|
|
4895
|
+
return node?.type === 'IfStatement' && !is_template_if_node(node);
|
|
4334
4896
|
}
|
|
4335
4897
|
|
|
4336
4898
|
/**
|
|
4337
4899
|
* @param {any} node
|
|
4338
4900
|
* @returns {boolean}
|
|
4339
4901
|
*/
|
|
4340
|
-
function
|
|
4341
|
-
|
|
4902
|
+
function is_render_child_node(node) {
|
|
4903
|
+
if (!node) return false;
|
|
4904
|
+
|
|
4905
|
+
switch (node.type) {
|
|
4906
|
+
case 'JSXElement':
|
|
4907
|
+
case 'JSXFragment':
|
|
4908
|
+
case 'JSXExpressionContainer':
|
|
4909
|
+
case 'JSXText':
|
|
4910
|
+
case 'JSXIfExpression':
|
|
4911
|
+
case 'JSXForExpression':
|
|
4912
|
+
case 'JSXSwitchExpression':
|
|
4913
|
+
case 'JSXTryExpression':
|
|
4914
|
+
return true;
|
|
4915
|
+
case 'IfStatement':
|
|
4916
|
+
return is_template_if_node(node);
|
|
4917
|
+
case 'ForOfStatement':
|
|
4918
|
+
return is_template_for_of_node(node);
|
|
4919
|
+
case 'SwitchStatement':
|
|
4920
|
+
return is_template_switch_node(node);
|
|
4921
|
+
case 'TryStatement':
|
|
4922
|
+
return is_template_try_node(node);
|
|
4923
|
+
default:
|
|
4924
|
+
return false;
|
|
4925
|
+
}
|
|
4342
4926
|
}
|
|
4343
4927
|
|
|
4344
4928
|
/**
|
|
@@ -4380,9 +4964,6 @@ function to_jsx_child(node, transform_context) {
|
|
|
4380
4964
|
if (is_native_tsrx_node(node)) {
|
|
4381
4965
|
return to_jsx_element(node, transform_context, node.children || [], true);
|
|
4382
4966
|
}
|
|
4383
|
-
if (is_dynamic_jsx_element(node)) {
|
|
4384
|
-
return dynamic_element_to_jsx(node, transform_context, true);
|
|
4385
|
-
}
|
|
4386
4967
|
return node;
|
|
4387
4968
|
case 'JSXFragment':
|
|
4388
4969
|
if (is_native_tsrx_node(node)) {
|
|
@@ -4391,6 +4972,9 @@ function to_jsx_child(node, transform_context) {
|
|
|
4391
4972
|
return node;
|
|
4392
4973
|
case 'JSXIfExpression':
|
|
4393
4974
|
case 'IfStatement':
|
|
4975
|
+
if (node.type === 'IfStatement' && !is_template_if_node(node)) {
|
|
4976
|
+
return node;
|
|
4977
|
+
}
|
|
4394
4978
|
if (node.metadata?.generated_loop_skip_if) {
|
|
4395
4979
|
return node;
|
|
4396
4980
|
}
|
|
@@ -4412,17 +4996,26 @@ function to_jsx_child(node, transform_context) {
|
|
|
4412
4996
|
transform_context.platform.hooks?.controlFlow?.forOf ?? for_of_statement_to_jsx_child
|
|
4413
4997
|
)(jsx_control_expression_to_statement(node), transform_context);
|
|
4414
4998
|
case 'ForOfStatement':
|
|
4999
|
+
if (!is_template_for_of_node(node)) {
|
|
5000
|
+
return node;
|
|
5001
|
+
}
|
|
4415
5002
|
return (
|
|
4416
5003
|
transform_context.platform.hooks?.controlFlow?.forOf ?? for_of_statement_to_jsx_child
|
|
4417
5004
|
)(node, transform_context);
|
|
4418
5005
|
case 'JSXSwitchExpression':
|
|
4419
5006
|
case 'SwitchStatement':
|
|
5007
|
+
if (node.type === 'SwitchStatement' && !is_template_switch_node(node)) {
|
|
5008
|
+
return node;
|
|
5009
|
+
}
|
|
4420
5010
|
return (
|
|
4421
5011
|
transform_context.platform.hooks?.controlFlow?.switchStatement ??
|
|
4422
5012
|
switch_statement_to_jsx_child
|
|
4423
5013
|
)(jsx_control_expression_to_statement(node), transform_context);
|
|
4424
5014
|
case 'JSXTryExpression':
|
|
4425
5015
|
case 'TryStatement':
|
|
5016
|
+
if (node.type === 'TryStatement' && !is_template_try_node(node)) {
|
|
5017
|
+
return node;
|
|
5018
|
+
}
|
|
4426
5019
|
return (
|
|
4427
5020
|
transform_context.platform.hooks?.controlFlow?.tryStatement ?? try_statement_to_jsx_child
|
|
4428
5021
|
)(jsx_control_expression_to_statement(node), transform_context);
|
|
@@ -4910,6 +5503,42 @@ function is_template_if_node(node) {
|
|
|
4910
5503
|
);
|
|
4911
5504
|
}
|
|
4912
5505
|
|
|
5506
|
+
/**
|
|
5507
|
+
* @param {any} node
|
|
5508
|
+
* @returns {boolean}
|
|
5509
|
+
*/
|
|
5510
|
+
function is_template_for_of_node(node) {
|
|
5511
|
+
return (
|
|
5512
|
+
node?.type === 'JSXForExpression' ||
|
|
5513
|
+
node?.metadata?.tsrxDirective === 'for' ||
|
|
5514
|
+
(node?.type === 'ForOfStatement' && node?.statementType === 'ForOfStatement')
|
|
5515
|
+
);
|
|
5516
|
+
}
|
|
5517
|
+
|
|
5518
|
+
/**
|
|
5519
|
+
* @param {any} node
|
|
5520
|
+
* @returns {boolean}
|
|
5521
|
+
*/
|
|
5522
|
+
function is_template_switch_node(node) {
|
|
5523
|
+
return (
|
|
5524
|
+
node?.type === 'JSXSwitchExpression' ||
|
|
5525
|
+
node?.metadata?.tsrxDirective === 'switch' ||
|
|
5526
|
+
(node?.type === 'SwitchStatement' && node?.statementType === 'SwitchStatement')
|
|
5527
|
+
);
|
|
5528
|
+
}
|
|
5529
|
+
|
|
5530
|
+
/**
|
|
5531
|
+
* @param {any} node
|
|
5532
|
+
* @returns {boolean}
|
|
5533
|
+
*/
|
|
5534
|
+
function is_template_try_node(node) {
|
|
5535
|
+
return (
|
|
5536
|
+
node?.type === 'JSXTryExpression' ||
|
|
5537
|
+
node?.metadata?.tsrxDirective === 'try' ||
|
|
5538
|
+
(node?.type === 'TryStatement' && node?.statementType === 'TryStatement')
|
|
5539
|
+
);
|
|
5540
|
+
}
|
|
5541
|
+
|
|
4913
5542
|
/**
|
|
4914
5543
|
* @param {any} node
|
|
4915
5544
|
* @returns {boolean}
|
|
@@ -5707,7 +6336,7 @@ function build_switch_with_lift(switch_node, transform_context) {
|
|
|
5707
6336
|
has_terminal = true;
|
|
5708
6337
|
break;
|
|
5709
6338
|
}
|
|
5710
|
-
if (
|
|
6339
|
+
if (is_render_child_node(child)) {
|
|
5711
6340
|
render_nodes.push(to_jsx_child(child, transform_context));
|
|
5712
6341
|
} else if (is_bare_render_expression(child)) {
|
|
5713
6342
|
render_nodes.push(to_jsx_expression_container(child, child));
|
|
@@ -6266,57 +6895,6 @@ function value_has_unmappable_jsx_loc(value) {
|
|
|
6266
6895
|
);
|
|
6267
6896
|
}
|
|
6268
6897
|
|
|
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
6898
|
/**
|
|
6321
6899
|
* @param {any[]} render_nodes
|
|
6322
6900
|
* @returns {any}
|