1
- /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, ObjectExpression, Statement } from 'estree' */
1
+ /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, Statement } from 'estree' */
2
2
/** @import { AST } from '#compiler' */
3
3
/** @import { SourceLocation } from '#shared' */
4
4
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */
@@ -16,7 +16,7 @@ import { is_event_attribute, is_text_attribute } from '../../../../utils/ast.js'
16
16
import * as b from '../../../../utils/builders.js' ;
17
17
import { is_custom_element_node } from '../../../nodes.js' ;
18
18
import { clean_nodes , determine_namespace_for_children } from '../../utils.js' ;
19
- import { build_getter , create_derived } from '../utils.js' ;
19
+ import { build_getter } from '../utils.js' ;
20
20
import {
21
21
get_attribute_name ,
22
22
build_attribute_value ,
@@ -28,8 +28,8 @@ import { process_children } from './shared/fragment.js';
28
28
import {
29
29
build_render_statement ,
30
30
build_template_chunk ,
31
- build_update ,
32
- build_update_assignment
31
+ build_update_assignment ,
32
+ get_expression_id
33
33
} from './shared/utils.js' ;
34
34
import { visit_event_attribute } from './shared/events.js' ;
35
35
@@ -409,7 +409,7 @@ export function RegularElement(node, context) {
409
409
b . block ( [
410
410
...child_state . init ,
411
411
...element_state . init ,
412
- child_state . update . length > 0 ? build_render_statement ( child_state . update ) : b . empty ,
412
+ child_state . update . length > 0 ? build_render_statement ( child_state ) : b . empty ,
413
413
...child_state . after_update ,
414
414
...element_state . after_update
415
415
] )
@@ -536,7 +536,10 @@ function build_element_attribute_update_assignment(
536
536
const name = get_attribute_name ( element , attribute ) ;
537
537
const is_svg = context . state . metadata . namespace === 'svg' || element . name === 'svg' ;
538
538
const is_mathml = context . state . metadata . namespace === 'mathml' ;
539
- let { has_call, value } = build_attribute_value ( attribute . value , context ) ;
539
+
540
+ let { value, has_state } = build_attribute_value ( attribute . value , context , ( value ) =>
541
+ get_expression_id ( state , value )
542
+ ) ;
540
543
541
544
if ( name === 'autofocus' ) {
542
545
state . init . push ( b . stmt ( b . call ( '$.autofocus' , node_id , value ) ) ) ;
@@ -557,15 +560,6 @@ function build_element_attribute_update_assignment(
557
560
value = b . call ( '$.clsx' , value ) ;
558
561
}
559
562
560
- if ( attribute . metadata . expression . has_state && has_call ) {
561
- // ensure we're not creating a separate template effect for this so that
562
- // potential class directives are added to the same effect and therefore always apply
563
- const id = b . id ( state . scope . generate ( 'class_derived' ) ) ;
564
- state . init . push ( b . const ( id , create_derived ( state , b . thunk ( value ) ) ) ) ;
565
- value = b . call ( '$.get' , id ) ;
566
- has_call = false ;
567
- }
568
-
569
563
update = b . stmt (
570
564
b . call (
571
565
is_svg ? '$.set_svg_class' : is_mathml ? '$.set_mathml_class' : '$.set_class' ,
@@ -605,14 +599,6 @@ function build_element_attribute_update_assignment(
605
599
} else if ( is_dom_property ( name ) ) {
606
600
update = b . stmt ( b . assignment ( '=' , b . member ( node_id , name ) , value ) ) ;
607
601
} else {
608
- if ( name === 'style' && attribute . metadata . expression . has_state && has_call ) {
609
- // ensure we're not creating a separate template effect for this so that
610
- // potential style directives are added to the same effect and therefore always apply
611
- const id = b . id ( state . scope . generate ( 'style_derived' ) ) ;
612
- state . init . push ( b . const ( id , create_derived ( state , b . thunk ( value ) ) ) ) ;
613
- value = b . call ( '$.get' , id ) ;
614
- has_call = false ;
615
- }
616
602
const callee = name . startsWith ( 'xlink' ) ? '$.set_xlink_attribute' : '$.set_attribute' ;
617
603
update = b . stmt (
618
604
b . call (
@@ -625,12 +611,8 @@ function build_element_attribute_update_assignment(
625
611
) ;
626
612
}
627
613
628
- if ( attribute . metadata . expression . has_state ) {
629
- if ( has_call ) {
630
- state . init . push ( build_update ( update ) ) ;
631
- } else {
632
- state . update . push ( update ) ;
633
- }
614
+ if ( has_state ) {
615
+ state . update . push ( update ) ;
634
616
return true ;
635
617
} else {
636
618
state . init . push ( update ) ;
@@ -648,7 +630,7 @@ function build_element_attribute_update_assignment(
648
630
function build_custom_element_attribute_update_assignment ( node_id , attribute , context ) {
649
631
const state = context . state ;
650
632
const name = attribute . name ; // don't lowercase, as we set the element's property, which might be case sensitive
651
- let { has_call , value } = build_attribute_value ( attribute . value , context ) ;
633
+ let { value , has_state } = build_attribute_value ( attribute . value , context ) ;
652
634
653
635
// We assume that noone's going to redefine the semantics of the class attribute on custom elements, i.e. it's still used for CSS classes
654
636
if ( name === 'class' && attribute . metadata . needs_clsx ) {
@@ -660,12 +642,10 @@ function build_custom_element_attribute_update_assignment(node_id, attribute, co
660
642
661
643
const update = b . stmt ( b . call ( '$.set_custom_element_data' , node_id , b . literal ( name ) , value ) ) ;
662
644
663
- if ( attribute . metadata . expression . has_state ) {
664
- if ( has_call ) {
665
- state . init . push ( build_update ( update ) ) ;
666
- } else {
667
- state . update . push ( update ) ;
668
- }
645
+ if ( has_state ) {
646
+ // this is different from other updates — it doesn't get grouped,
647
+ // because set_custom_element_data may not be idempotent
648
+ state . init . push ( b . stmt ( b . call ( '$.template_effect' , b . thunk ( update . expression ) ) ) ) ;
669
649
return true ;
670
650
} else {
671
651
state . init . push ( update ) ;
@@ -685,7 +665,9 @@ function build_custom_element_attribute_update_assignment(node_id, attribute, co
685
665
*/
686
666
function build_element_special_value_attribute ( element , node_id , attribute , context ) {
687
667
const state = context . state ;
688
- const { value } = build_attribute_value ( attribute . value , context ) ;
668
+ const { value, has_state } = build_attribute_value ( attribute . value , context , ( value ) =>
669
+ get_expression_id ( state , value )
670
+ ) ;
689
671
690
672
const inner_assignment = b . assignment (
691
673
'=' ,
@@ -719,7 +701,7 @@ function build_element_special_value_attribute(element, node_id, attribute, cont
719
701
state . init . push ( b . stmt ( b . call ( '$.init_select' , node_id , b . thunk ( value ) ) ) ) ;
720
702
}
721
703
722
- if ( attribute . metadata . expression . has_state ) {
704
+ if ( has_state ) {
723
705
const id = state . scope . generate ( `${ node_id . name } _value` ) ;
724
706
build_update_assignment (
725
707
state ,
0 commit comments