@tsrx/core 0.1.6 → 0.1.8

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.
@@ -34,12 +34,7 @@ import {
34
34
  jsx_id as build_jsx_id,
35
35
  } from '../../utils/builders.js';
36
36
  import * as b from '../../utils/builders.js';
37
- import {
38
- apply_lazy_transforms,
39
- collect_lazy_bindings_from_component,
40
- preallocate_lazy_ids,
41
- replace_lazy_params,
42
- } from '../lazy.js';
37
+ import { apply_lazy_transforms, preallocate_lazy_ids } from '../lazy.js';
43
38
  import { find_first_top_level_await_in_component_body } from '../await.js';
44
39
  import { prepare_stylesheet_for_render, annotate_component_with_hash } from '../scoping.js';
45
40
  import {
@@ -50,7 +45,7 @@ import {
50
45
  validate_component_return_statement,
51
46
  validate_component_unsupported_loop_statement,
52
47
  } from '../../analyze/validation.js';
53
- import { get_component_from_path } from '../../utils/ast.js';
48
+ import { get_component_from_path, is_function_or_component_node } from '../../utils/ast.js';
54
49
  import {
55
50
  is_interleaved_body as is_interleaved_body_core,
56
51
  is_capturable_jsx_child,
@@ -646,15 +641,6 @@ export function component_to_function_declaration(component, transform_context,
646
641
  // Collect param bindings from original patterns (lazy patterns still intact).
647
642
  const param_bindings = collect_param_bindings(params);
648
643
 
649
- // Collect lazy binding info WITHOUT mutating patterns. Stores lazy_id on metadata
650
- // for later replacement. Body bindings (count, setCount, etc.) are still in the
651
- // original patterns, so collect_statement_bindings during build will find them.
652
- // In type-only mode the lazy rewrite is skipped entirely so destructuring
653
- // patterns survive into the virtual TSX and TypeScript can flow real types.
654
- const lazy_bindings = transform_context.typeOnly
655
- ? new Map()
656
- : collect_lazy_bindings_from_component(params, body, transform_context);
657
-
658
644
  // Save and set context for this component scope
659
645
  const saved_helper_state = transform_context.helper_state;
660
646
  const saved_bindings = transform_context.available_bindings;
@@ -662,16 +648,7 @@ export function component_to_function_declaration(component, transform_context,
662
648
  transform_context.available_bindings = new Map(param_bindings);
663
649
 
664
650
  const body_statements = build_component_statements(body, transform_context);
665
-
666
- // Replace lazy param patterns with generated identifiers
667
- const final_params = lazy_bindings.size > 0 ? replace_lazy_params(params) : params;
668
-
669
- // Wrap body_statements in a BlockStatement so that apply_lazy_transforms
670
- // runs collect_block_shadowed_names and detects body-level declarations
671
- // (e.g. `const name = ...`) that shadow lazy binding names.
672
651
  const body_block = b.block(body_statements);
673
- const final_body =
674
- lazy_bindings.size > 0 ? apply_lazy_transforms(body_block, lazy_bindings) : body_block;
675
652
 
676
653
  /** @type {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression} */
677
654
  let fn;
@@ -679,18 +656,38 @@ export function component_to_function_declaration(component, transform_context,
679
656
  if (component.id) {
680
657
  fn = b.function_declaration(
681
658
  component.id,
682
- final_params,
683
- final_body,
659
+ params,
660
+ body_block,
684
661
  is_async_component,
685
662
  component.typeParameters,
686
663
  );
687
664
  } else if (component.metadata?.arrow) {
688
- fn = b.arrow(final_params, final_body, is_async_component, component.typeParameters);
665
+ fn = b.arrow(params, body_block, is_async_component, component.typeParameters);
689
666
  } else {
690
- fn = b.function(null, final_params, final_body, is_async_component, component.typeParameters);
667
+ fn = b.function(null, params, body_block, is_async_component, component.typeParameters);
691
668
  }
692
669
  /** @type {any} */ (fn.metadata).is_component = true;
693
670
 
671
+ // `preallocate_lazy_ids` stamped `has_lazy_descendants` on the source
672
+ // `Component` node; the freshly-built `fn` shares the same params/body
673
+ // subtree, so the flag is equally applicable. Propagating it lets
674
+ // `apply_lazy_transforms` honor its constant-time early-return path.
675
+ if (/** @type {any} */ (component).metadata?.has_lazy_descendants) {
676
+ /** @type {any} */ (fn.metadata).has_lazy_descendants = true;
677
+ }
678
+
679
+ // Apply lazy `&{}` / `&[]` rewrites end-to-end: the function-handler in
680
+ // `apply_lazy_transforms` collects param bindings, merges with body bindings
681
+ // discovered by the BlockStatement handler, replaces lazy params with their
682
+ // `__lazyN` ids, and rewrites every reference. Constant-time fast-path for
683
+ // functions whose subtrees contain no lazy patterns (flagged ahead of time
684
+ // by `preallocate_lazy_ids`). In type-only mode the rewrite is skipped so
685
+ // destructuring patterns survive into the virtual TSX and TypeScript can
686
+ // flow real types.
687
+ if (!transform_context.typeOnly) {
688
+ fn = /** @type {typeof fn} */ (apply_lazy_transforms(fn, new Map()));
689
+ }
690
+
694
691
  // Restore context
695
692
  transform_context.helper_state = saved_helper_state;
696
693
  transform_context.available_bindings = saved_bindings;
@@ -2689,7 +2686,7 @@ function validate_hook_outer_assignments_in_node(
2689
2686
  return;
2690
2687
  }
2691
2688
 
2692
- if (is_function_like_node(node)) {
2689
+ if (is_function_or_component_node(node)) {
2693
2690
  return;
2694
2691
  }
2695
2692
 
@@ -2831,7 +2828,7 @@ function validate_hook_outer_assignments_in_node(
2831
2828
  function validate_hook_callback_outer_mutations(call_node, shadowed_names, transform_context) {
2832
2829
  const hook_name = get_hook_callee_name(call_node.callee);
2833
2830
  for (const argument of call_node.arguments || []) {
2834
- if (!is_function_like_node(argument)) {
2831
+ if (!is_function_or_component_node(argument)) {
2835
2832
  continue;
2836
2833
  }
2837
2834
  const callback_shadowed_names = create_function_like_shadowed_names(argument, shadowed_names);
@@ -2844,21 +2841,6 @@ function validate_hook_callback_outer_mutations(call_node, shadowed_names, trans
2844
2841
  }
2845
2842
  }
2846
2843
 
2847
- /**
2848
- * @param {any} node
2849
- * @returns {boolean}
2850
- */
2851
- function is_function_like_node(node) {
2852
- return (
2853
- node.type === 'FunctionDeclaration' ||
2854
- node.type === 'FunctionExpression' ||
2855
- node.type === 'ArrowFunctionExpression' ||
2856
- // this is just in case but we should already
2857
- // have a component replaced with a function node
2858
- node.type === 'Component'
2859
- );
2860
- }
2861
-
2862
2844
  /**
2863
2845
  * @param {any} node
2864
2846
  * @param {Set<string>} shadowed_names
@@ -2906,7 +2888,7 @@ function validate_hook_callback_outer_mutations_in_node(
2906
2888
  return;
2907
2889
  }
2908
2890
 
2909
- if (is_function_like_node(node)) {
2891
+ if (is_function_or_component_node(node)) {
2910
2892
  validate_hook_callback_outer_mutations_in_node(
2911
2893
  node.body,
2912
2894
  create_function_like_shadowed_names(node, shadowed_names),