1
- /** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement } from 'estree' */
1
+ /** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement, ExpressionStatement } from 'estree' */
2
2
/** @import { Visitors } from 'zimmerframe' */
3
3
/** @import { ComponentAnalysis } from '../phases/types.js' */
4
4
/** @import { Scope, ScopeRoot } from '../phases/scope.js' */
@@ -10,7 +10,7 @@ import { regex_valid_component_name } from '../phases/1-parse/state/element.js';
10
10
import { analyze_component } from '../phases/2-analyze/index.js' ;
11
11
import { get_rune } from '../phases/scope.js' ;
12
12
import { reset , reset_warning_filter } from '../state.js' ;
13
- import { extract_identifiers } from '../utils/ast.js' ;
13
+ import { extract_identifiers , extract_all_identifiers_from_expression } from '../utils/ast.js' ;
14
14
import { migrate_svelte_ignore } from '../utils/extract_svelte_ignore.js' ;
15
15
import { determine_slot } from '../utils/slot.js' ;
16
16
import { validate_component_options } from '../validate-options.js' ;
@@ -493,16 +493,33 @@ const instance_script = {
493
493
) ;
494
494
495
495
const labeled_has_single_assignment =
496
- ( labeled_statement ?. body . type === 'BlockStatement' &&
497
- labeled_statement . body . body . length === 1 ) ||
498
- ( labeled_statement ?. body . type === 'ExpressionStatement' &&
499
- labeled_statement . body . expression . type === 'AssignmentExpression' ) ;
496
+ labeled_statement ?. body . type === 'BlockStatement' &&
497
+ labeled_statement . body . body . length === 1 ;
498
+
499
+ const is_expression_assignment =
500
+ labeled_statement ?. body . type === 'ExpressionStatement' &&
501
+ labeled_statement . body . expression . type === 'AssignmentExpression' ;
502
+
503
+ let should_be_state = false ;
504
+
505
+ if ( is_expression_assignment ) {
506
+ const body = /**@type {ExpressionStatement }*/ ( labeled_statement ?. body ) ;
507
+ const expression = /**@type {AssignmentExpression }*/ ( body . expression ) ;
508
+ const [ , ids ] = extract_all_identifiers_from_expression ( expression . right ) ;
509
+ if ( ids . length === 0 ) {
510
+ should_be_state = true ;
511
+ state . derived_labeled_statements . add (
512
+ /** @type {LabeledStatement } */ ( labeled_statement )
513
+ ) ;
514
+ }
515
+ }
500
516
501
517
if (
518
+ ! should_be_state &&
502
519
possible_derived &&
503
520
assignment_in_labeled &&
504
521
labeled_statement &&
505
- labeled_has_single_assignment
522
+ ( labeled_has_single_assignment || is_expression_assignment )
506
523
) {
507
524
state . str . appendRight (
508
525
/** @type {number } */ ( declarator . id . typeAnnotation ?. end ?? declarator . id . end ) ,
@@ -530,7 +547,30 @@ const instance_script = {
530
547
} else {
531
548
state . str . prependLeft (
532
549
/** @type {number } */ ( declarator . id . typeAnnotation ?. end ?? declarator . id . end ) ,
533
- ' = $state()'
550
+ ' = $state('
551
+ ) ;
552
+ if ( should_be_state ) {
553
+ state . str . appendRight (
554
+ /** @type {number } */ ( declarator . id . typeAnnotation ?. end ?? declarator . id . end ) ,
555
+ state . str
556
+ . snip (
557
+ /** @type {number } */ (
558
+ /** @type {AssignmentExpression } */ ( assignment_in_labeled ) . right . start
559
+ ) ,
560
+ /** @type {number } */ (
561
+ /** @type {AssignmentExpression } */ ( assignment_in_labeled ) . right . end
562
+ )
563
+ )
564
+ . toString ( )
565
+ ) ;
566
+ state . str . remove (
567
+ /** @type {number } */ ( /** @type {LabeledStatement } */ ( labeled_statement ) . start ) ,
568
+ /** @type {number } */ ( /** @type {LabeledStatement } */ ( labeled_statement ) . end )
569
+ ) ;
570
+ }
571
+ state . str . appendRight (
572
+ /** @type {number } */ ( declarator . id . typeAnnotation ?. end ?? declarator . id . end ) ,
573
+ ')'
534
574
) ;
535
575
}
536
576
}
0 commit comments