@@ -23,16 +23,20 @@ export function memoize_expression(state, value) {
23
23
/**
24
24
*
25
25
* @param {ComponentClientTransformState } state
26
- * @param {Expression } value
26
+ * @param {Expression } expression
27
+ * @param {boolean } is_async
27
28
*/
28
- export function get_expression_id ( state , value ) {
29
+ export function get_expression_id ( state , expression , is_async ) {
29
30
for ( let i = 0 ; i < state . expressions . length ; i += 1 ) {
30
- if ( compare_expressions ( state . expressions [ i ] , value ) ) {
31
- return b . id ( `$ ${ i } ` ) ;
31
+ if ( compare_expressions ( state . expressions [ i ] . expression , expression ) ) {
32
+ return state . expressions [ i ] . id ;
32
33
}
33
34
}
34
35
35
- return b . id ( `$${ state . expressions . push ( value ) - 1 } ` ) ;
36
+ const id = b . id ( '' ) ; // filled in later
37
+ state . expressions . push ( { id, expression, is_async } ) ;
38
+
39
+ return id ;
36
40
}
37
41
38
42
/**
@@ -79,14 +83,14 @@ function compare_expressions(a, b) {
79
83
* @param {Array<AST.Text | AST.ExpressionTag> } values
80
84
* @param {(node: AST.SvelteNode, state: any) => any } visit
81
85
* @param {ComponentClientTransformState } state
82
- * @param {(value: Expression) => Expression } memoize
83
- * @returns {{ value: Expression, has_state: boolean } }
86
+ * @param {(value: Expression, is_async: boolean ) => Expression } memoize
87
+ * @returns {{ value: Expression, has_state: boolean, is_async: boolean } }
84
88
*/
85
89
export function build_template_chunk (
86
90
values ,
87
91
visit ,
88
92
state ,
89
- memoize = ( value ) => get_expression_id ( state , value )
93
+ memoize = ( value , is_async ) => get_expression_id ( state , value , is_async )
90
94
) {
91
95
/** @type {Expression[] } */
92
96
const expressions = [ ] ;
@@ -95,6 +99,7 @@ export function build_template_chunk(
95
99
const quasis = [ quasi ] ;
96
100
97
101
let has_state = false ;
102
+ let is_async = false ;
98
103
99
104
for ( let i = 0 ; i < values . length ; i ++ ) {
100
105
const node = values [ i ] ;
@@ -108,16 +113,17 @@ export function build_template_chunk(
108
113
} else {
109
114
let value = /** @type {Expression } */ ( visit ( node . expression , state ) ) ;
110
115
111
- has_state ||= node . metadata . expression . has_state ;
116
+ is_async ||= node . metadata . expression . is_async ;
117
+ has_state ||= is_async || node . metadata . expression . has_state ;
112
118
113
- if ( node . metadata . expression . has_call ) {
114
- value = memoize ( value ) ;
119
+ if ( node . metadata . expression . has_call || node . metadata . expression . is_async ) {
120
+ value = memoize ( value , node . metadata . expression . is_async ) ;
115
121
}
116
122
117
123
if ( values . length === 1 ) {
118
124
// If we have a single expression, then pass that in directly to possibly avoid doing
119
125
// extra work in the template_effect (instead we do the work in set_text).
120
- return { value, has_state } ;
126
+ return { value, has_state, is_async } ;
121
127
} else {
122
128
let expression = value ;
123
129
// only add nullish coallescence if it hasn't been added already
@@ -148,25 +154,34 @@ export function build_template_chunk(
148
154
149
155
const value = b . template ( quasis , expressions ) ;
150
156
151
- return { value, has_state } ;
157
+ return { value, has_state, is_async } ;
152
158
}
153
159
154
160
/**
155
161
* @param {ComponentClientTransformState } state
156
162
*/
157
163
export function build_render_statement ( state ) {
164
+ const sync = state . expressions . filter ( ( { is_async } ) => ! is_async ) ;
165
+ const async = state . expressions . filter ( ( { is_async } ) => is_async ) ;
166
+
167
+ const all = [ ...sync , ...async ] ;
168
+
169
+ for ( let i = 0 ; i < all . length ; i += 1 ) {
170
+ all [ i ] . id . name = `$${ i } ` ;
171
+ }
172
+
158
173
return b . stmt (
159
174
b . call (
160
175
'$.template_effect' ,
161
176
b . arrow (
162
- state . expressions . map ( ( _ , i ) => b . id ( `$ ${ i } ` ) ) ,
177
+ all . map ( ( { id } ) => id ) ,
163
178
state . update . length === 1 && state . update [ 0 ] . type === 'ExpressionStatement'
164
179
? state . update [ 0 ] . expression
165
180
: b . block ( state . update )
166
181
) ,
167
- state . expressions . length > 0 &&
168
- b . array ( state . expressions . map ( ( expression ) => b . thunk ( expression ) ) ) ,
169
- state . expressions . length > 0 && ! state . analysis . runes && b . id ( '$.derived_safe_equal' )
182
+ all . length > 0 && b . array ( sync . map ( ( { expression } ) => b . thunk ( expression ) ) ) ,
183
+ async . length > 0 && b . array ( async . map ( ( { expression } ) => b . thunk ( expression , true ) ) ) ,
184
+ ! state . analysis . runes && sync . length > 0 && b . id ( '$.derived_safe_equal' )
170
185
)
171
186
) ;
172
187
}
0 commit comments