@@ -176,45 +176,83 @@ export function VariableDeclaration(node, context) {
176
176
const value = /** @type {Expression } */ ( args [ 0 ] ) ?? b . void0 ; // TODO do we need the void 0? can we just omit it altogether?
177
177
178
178
if ( rune === '$state' || rune === '$state.raw' ) {
179
+ const state_declarators = [ ] ;
180
+ const current_chunk = context . state . current_parallelized_chunk ;
181
+ const parallelize =
182
+ declarator . id . type === 'Identifier' &&
183
+ context . state . analysis . instance ?. scope === context . state . scope &&
184
+ value . type === 'AwaitExpression' &&
185
+ can_be_parallelized ( value . argument , context . state . scope , context . state . analysis , [
186
+ ...( current_chunk ?. bindings ?? [ ] ) ,
187
+ ...bindings
188
+ ] ) ;
179
189
/**
180
190
* @param {Identifier } id
191
+ * @param {Expression } visited
181
192
* @param {Expression } value
182
193
*/
183
- const create_state_declarator = ( id , value ) => {
194
+ const create_state_declarator = ( id , visited , value ) => {
184
195
const binding = /** @type {Binding } */ ( context . state . scope . get ( id . name ) ) ;
185
196
const is_state = is_state_source ( binding , context . state . analysis ) ;
186
- const is_proxy = should_proxy ( value , context . state . scope ) ;
197
+ const is_proxy = should_proxy ( visited , context . state . scope ) ;
198
+ const compose = [ ] ;
199
+ if ( parallelize ) {
200
+ if ( rune === '$state' && is_proxy ) {
201
+ compose . push ( b . id ( '$.proxy' ) ) ;
187
202
188
- if ( rune === '$state' && is_proxy ) {
189
- value = b . call ( '$.proxy' , value ) ;
203
+ if ( dev && ! is_state ) {
204
+ compose . push (
205
+ b . arrow ( [ b . id ( 'proxy' ) ] , b . call ( '$.tag_proxy' , b . id ( 'proxy' ) , b . literal ( id . name ) ) )
206
+ ) ;
207
+ }
208
+ }
190
209
191
- if ( dev && ! is_state ) {
192
- value = b . call ( '$.tag_proxy' , value , b . literal ( id . name ) ) ;
210
+ if ( is_state ) {
211
+ compose . push ( b . id ( '$.state' ) ) ;
212
+ if ( dev ) {
213
+ compose . push (
214
+ b . arrow ( [ b . id ( 'source' ) ] , b . call ( '$.tag' , b . id ( 'source' ) , b . literal ( id . name ) ) )
215
+ ) ;
216
+ }
217
+ }
218
+ } else {
219
+ if ( rune === '$state' && is_proxy ) {
220
+ value = b . call ( '$.proxy' , value ) ;
221
+
222
+ if ( dev && ! is_state ) {
223
+ value = b . call ( '$.tag_proxy' , value , b . literal ( id . name ) ) ;
224
+ }
193
225
}
194
- }
195
226
196
- if ( is_state ) {
197
- value = b . call ( '$.state' , value ) ;
227
+ if ( is_state ) {
228
+ value = b . call ( '$.state' , value ) ;
198
229
199
- if ( dev ) {
200
- value = b . call ( '$.tag' , value , b . literal ( id . name ) ) ;
230
+ if ( dev ) {
231
+ value = b . call ( '$.tag' , value , b . literal ( id . name ) ) ;
232
+ }
201
233
}
202
234
}
203
235
204
- return value ;
236
+ return parallelize && value . type === 'AwaitExpression'
237
+ ? b . call (
238
+ '$.async_compose' ,
239
+ /** @type {Expression } */ ( context . visit ( value . argument ) ) ,
240
+ ...compose
241
+ )
242
+ : visited ;
205
243
} ;
206
244
207
245
if ( declarator . id . type === 'Identifier' ) {
208
246
const expression = /** @type {Expression } */ ( context . visit ( value ) ) ;
209
247
210
- declarations . push (
211
- b . declarator ( declarator . id , create_state_declarator ( declarator . id , expression ) )
248
+ state_declarators . push (
249
+ b . declarator ( declarator . id , create_state_declarator ( declarator . id , expression , value ) )
212
250
) ;
213
251
} else {
214
252
const tmp = b . id ( context . state . scope . generate ( 'tmp' ) ) ;
215
253
const { inserts, paths } = extract_paths ( declarator . id , tmp ) ;
216
254
217
- declarations . push (
255
+ state_declarators . push (
218
256
b . declarator ( tmp , /** @type {Expression } */ ( context . visit ( value ) ) ) ,
219
257
...inserts . map ( ( { id, value } ) => {
220
258
id . name = context . state . scope . generate ( '$$array' ) ;
@@ -236,12 +274,36 @@ export function VariableDeclaration(node, context) {
236
274
return b . declarator (
237
275
path . node ,
238
276
binding ?. kind === 'state' || binding ?. kind === 'raw_state'
239
- ? create_state_declarator ( binding . node , value )
277
+ ? create_state_declarator ( binding . node , value , path . expression )
240
278
: value
241
279
) ;
242
280
} )
243
281
) ;
244
282
}
283
+ if ( ! parallelize ) {
284
+ declarations . push ( ...state_declarators ) ;
285
+ } else {
286
+ const declarators = state_declarators . map ( ( { id, init } ) => ( {
287
+ id,
288
+ init : /** @type {Expression } */ ( init )
289
+ } ) ) ;
290
+ if ( current_chunk && ( current_chunk . kind === node . kind || current_chunk . kind === null ) ) {
291
+ current_chunk . declarators . push ( ...declarators ) ;
292
+ current_chunk . bindings . push ( ...bindings ) ;
293
+ current_chunk . position = position ;
294
+ current_chunk . kind = node . kind ;
295
+ } else {
296
+ /** @type {ParallelizedChunk } */
297
+ const chunk = {
298
+ kind : node . kind ,
299
+ declarators,
300
+ position,
301
+ bindings
302
+ } ;
303
+ context . state . current_parallelized_chunk = chunk ;
304
+ context . state . parallelized_chunks . push ( chunk ) ;
305
+ }
306
+ }
245
307
246
308
continue ;
247
309
}
0 commit comments