@tsrx/core 0.1.29 → 0.1.31

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Core compiler infrastructure for TSRX syntax",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.1.29",
6
+ "version": "0.1.31",
7
7
  "type": "module",
8
8
  "repository": {
9
9
  "type": "git",
package/src/index.js CHANGED
@@ -164,6 +164,10 @@ export {
164
164
  in_jsx_child_context as inJsxChildContext,
165
165
  tsx_node_to_jsx_expression as tsxNodeToJsxExpression,
166
166
  tsx_with_ts_locations as tsxWithTsLocations,
167
+ is_template_if_node as isTemplateIfNode,
168
+ is_template_for_of_node as isTemplateForOfNode,
169
+ is_template_switch_node as isTemplateSwitchNode,
170
+ is_template_try_node as isTemplateTryNode,
167
171
  } from './transform/jsx/helpers.js';
168
172
  export {
169
173
  collect_style_ref_attributes as collectStyleRefAttributes,
package/src/plugin.js CHANGED
@@ -3650,15 +3650,17 @@ export function TSRXPlugin(config) {
3650
3650
  }
3651
3651
 
3652
3652
  /**
3653
- * `@try`/`@pending`/`@catch` blocks lower their direct `return`
3654
- * values into reactive boundary fallbacks, so unlike `@if`/`@for`/`@switch`
3655
- * blocks they legitimately allow `return <markup>` statements. Set the flag
3656
- * immediately before parsing each such block so its body sees it.
3653
+ * `@try`/`@pending`/`@catch` blocks are template control-flow blocks like
3654
+ * `@if`/`@for`/`@switch`: `return` is not allowed inside them. A `return`
3655
+ * is only valid in the JS setup at the top of a `@{ … }` code block, never
3656
+ * inside a `@`-directive block. Report any direct `return` with the same
3657
+ * template-return diagnostic used elsewhere.
3657
3658
  * @returns {AST.BlockStatement}
3658
3659
  */
3659
3660
  #parseTemplateControlFlowReturnBlock(createNewLexicalScope = true) {
3660
- this.#controlFlowBlockAllowsNativeReturn = true;
3661
- return this.#parseTemplateControlFlowBlock(createNewLexicalScope);
3661
+ const block = this.#parseTemplateControlFlowBlock(createNewLexicalScope);
3662
+ this.#report_invalid_template_return_statements(block.body);
3663
+ return block;
3662
3664
  }
3663
3665
 
3664
3666
  /**
@@ -260,3 +260,51 @@ export function tsx_with_ts_locations() {
260
260
 
261
261
  return { ...base, ...wrappers };
262
262
  }
263
+
264
+ /**
265
+ * @param {any} node
266
+ * @returns {boolean}
267
+ */
268
+ export function is_template_if_node(node) {
269
+ return (
270
+ node?.type === 'JSXIfExpression' ||
271
+ node?.metadata?.tsrxDirective === 'if' ||
272
+ (node?.type === 'IfStatement' && node?.statementType === 'IfStatement')
273
+ );
274
+ }
275
+
276
+ /**
277
+ * @param {any} node
278
+ * @returns {boolean}
279
+ */
280
+ export function is_template_for_of_node(node) {
281
+ return (
282
+ node?.type === 'JSXForExpression' ||
283
+ node?.metadata?.tsrxDirective === 'for' ||
284
+ (node?.type === 'ForOfStatement' && node?.statementType === 'ForOfStatement')
285
+ );
286
+ }
287
+
288
+ /**
289
+ * @param {any} node
290
+ * @returns {boolean}
291
+ */
292
+ export function is_template_switch_node(node) {
293
+ return (
294
+ node?.type === 'JSXSwitchExpression' ||
295
+ node?.metadata?.tsrxDirective === 'switch' ||
296
+ (node?.type === 'SwitchStatement' && node?.statementType === 'SwitchStatement')
297
+ );
298
+ }
299
+
300
+ /**
301
+ * @param {any} node
302
+ * @returns {boolean}
303
+ */
304
+ export function is_template_try_node(node) {
305
+ return (
306
+ node?.type === 'JSXTryExpression' ||
307
+ node?.metadata?.tsrxDirective === 'try' ||
308
+ (node?.type === 'TryStatement' && node?.statementType === 'TryStatement')
309
+ );
310
+ }
@@ -10,8 +10,11 @@ import { prune_css } from '../../analyze/prune.js';
10
10
  import {
11
11
  in_jsx_child_context,
12
12
  set_node_path_metadata,
13
- tsx_node_to_jsx_expression,
14
13
  tsx_with_ts_locations,
14
+ is_template_if_node,
15
+ is_template_for_of_node,
16
+ is_template_switch_node,
17
+ is_template_try_node,
15
18
  } from './helpers.js';
16
19
  import {
17
20
  add_extra_source_mappings_from_matching_expression,
@@ -779,19 +782,25 @@ function apply_css_definition_metadata(
779
782
  }
780
783
 
781
784
  /**
785
+ * Pruning runs from the fragment visitor, before the walker has descended into
786
+ * the subtree and stamped walker paths, so each collected element gets its
787
+ * ancestor chain (`metadata.path`) here — descendant/sibling selector matching
788
+ * in `prune_css` reads it.
789
+ *
782
790
  * @param {any} value
783
791
  * @param {any[]} [elements]
784
792
  * @param {TransformContext | null} [transform_context]
793
+ * @param {any[]} [path]
785
794
  * @returns {any[]}
786
795
  */
787
- function collect_css_prunable_elements(value, elements = [], transform_context = null) {
796
+ function collect_css_prunable_elements(value, elements = [], transform_context = null, path = []) {
788
797
  if (!value || typeof value !== 'object') {
789
798
  return elements;
790
799
  }
791
800
 
792
801
  if (Array.isArray(value)) {
793
802
  for (const child of value) {
794
- collect_css_prunable_elements(child, elements, transform_context);
803
+ collect_css_prunable_elements(child, elements, transform_context, path);
795
804
  }
796
805
  return elements;
797
806
  }
@@ -810,15 +819,18 @@ function collect_css_prunable_elements(value, elements = [], transform_context =
810
819
 
811
820
  if (value.type === 'JSXElement' && value.metadata?.native_tsrx) {
812
821
  if (!is_style_element(value)) {
822
+ set_node_path_metadata(value, path);
813
823
  elements.push(value);
814
824
  }
815
825
  }
816
826
 
827
+ const child_path = value.type ? [...path, value] : path;
828
+
817
829
  for (const key of Object.keys(value)) {
818
830
  if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata' || key === 'css') {
819
831
  continue;
820
832
  }
821
- collect_css_prunable_elements(value[key], elements, transform_context);
833
+ collect_css_prunable_elements(value[key], elements, transform_context, child_path);
822
834
  }
823
835
 
824
836
  return elements;
@@ -4476,54 +4488,6 @@ function validate_if_body_control_flow(node, transform_context) {
4476
4488
  }
4477
4489
  }
4478
4490
 
4479
- /**
4480
- * @param {any} node
4481
- * @returns {boolean}
4482
- */
4483
- function is_template_if_node(node) {
4484
- return (
4485
- node?.type === 'JSXIfExpression' ||
4486
- node?.metadata?.tsrxDirective === 'if' ||
4487
- (node?.type === 'IfStatement' && node?.statementType === 'IfStatement')
4488
- );
4489
- }
4490
-
4491
- /**
4492
- * @param {any} node
4493
- * @returns {boolean}
4494
- */
4495
- function is_template_for_of_node(node) {
4496
- return (
4497
- node?.type === 'JSXForExpression' ||
4498
- node?.metadata?.tsrxDirective === 'for' ||
4499
- (node?.type === 'ForOfStatement' && node?.statementType === 'ForOfStatement')
4500
- );
4501
- }
4502
-
4503
- /**
4504
- * @param {any} node
4505
- * @returns {boolean}
4506
- */
4507
- function is_template_switch_node(node) {
4508
- return (
4509
- node?.type === 'JSXSwitchExpression' ||
4510
- node?.metadata?.tsrxDirective === 'switch' ||
4511
- (node?.type === 'SwitchStatement' && node?.statementType === 'SwitchStatement')
4512
- );
4513
- }
4514
-
4515
- /**
4516
- * @param {any} node
4517
- * @returns {boolean}
4518
- */
4519
- function is_template_try_node(node) {
4520
- return (
4521
- node?.type === 'JSXTryExpression' ||
4522
- node?.metadata?.tsrxDirective === 'try' ||
4523
- (node?.type === 'TryStatement' && node?.statementType === 'TryStatement')
4524
- );
4525
- }
4526
-
4527
4491
  /**
4528
4492
  * @param {any} node
4529
4493
  * @returns {boolean}