@@ -38,6 +38,7 @@ import compiler_warnings from './compiler_warnings';
3838import compiler_errors from './compiler_errors' ;
3939import { extract_ignores_above_position , extract_svelte_ignore_from_comments } from '../utils/extract_svelte_ignore' ;
4040import check_enable_sourcemap from './utils/check_enable_sourcemap' ;
41+ import { flatten } from '../utils/flatten' ;
4142
4243interface ComponentOptions {
4344 namespace ?: string ;
@@ -1136,7 +1137,9 @@ export default class Component {
11361137 add_new_props ( { type : 'Identifier' , name : variable . export_name } , declarator . id , declarator . init ) ;
11371138 node . declarations . splice ( index -- , 1 ) ;
11381139 }
1139- if ( variable . subscribable && ( is_props || declarator . init ) ) {
1140+
1141+ const for_in_of_loop_init = key === 'left' && ( parent . type === 'ForInStatement' || parent . type === 'ForOfStatement' ) ;
1142+ if ( variable . subscribable && ( is_props || declarator . init || for_in_of_loop_init ) ) {
11401143 subscriptions . push ( get_subscriptions ( variable ) ) ;
11411144 }
11421145 }
@@ -1147,31 +1150,52 @@ export default class Component {
11471150 throw new Error ( 'export is not at the top level' ) ;
11481151 }
11491152
1153+ const flattened_subscriptions = flatten ( subscriptions ) ;
1154+ // parent.type === 'Program' or 'BlockStatement' or 'SwitchCase' and key === 'body'
11501155 if ( Array . isArray ( parent [ key ] ) ) {
11511156 // If the variable declaration is part of some block, that is, among an array of statements
11521157 // then, we add the subscriptions and the $$props declaration after declaration
11531158 if ( subscriptions . length > 0 ) {
1154- subscriptions . reverse ( ) . forEach ( ( subscription ) => {
1155- parent [ key ] . splice ( index + 1 , 0 , ...subscription ) ;
1156- } ) ;
1159+ parent [ key ] . splice ( index + 1 , 0 , ...flattened_subscriptions ) ;
11571160 }
11581161 if ( props . length > 0 ) {
11591162 // b`` might return a Node array, but the $$props declaration will be flattened later
11601163 parent [ key ] . splice ( index + 1 , 0 , b `let { ${ props } } = $$props;` ) ;
1161- }
1164+ }
11621165 if ( node . declarations . length == 0 ) {
11631166 parent [ key ] . splice ( index , 1 ) ;
11641167 }
11651168 } else if ( subscriptions . length > 0 ) {
1166- // If the variable declaration is not part of a block, we instead get a dummy variable setting
1167- // calling an immediately-invoked function expression containing all the subscription functions
1168- node . declarations . push ( {
1169- type : 'VariableDeclarator' ,
1170- id : component . get_unique_name ( '$$subscriptions' , scope ) ,
1171- init : x `(() => {
1172- ${ subscriptions }
1173- })()`
1174- } ) ;
1169+ // if it is for (var x in array) or for (var x of array)
1170+ // we are transforming from:
1171+ //
1172+ // for (var x of array) {
1173+ // // body
1174+ // }
1175+ // to:
1176+ // for (var x of array) {
1177+ // // subscription inserts
1178+ // // body
1179+ // }
1180+ if ( key === 'left' && ( parent . type === 'ForInStatement' || parent . type === 'ForOfStatement' ) ) {
1181+ if ( parent . body . type !== 'BlockStatement' ) {
1182+ parent . body = {
1183+ type : 'BlockStatement' ,
1184+ body : [ parent . body ]
1185+ } ;
1186+ }
1187+ parent . body . body . unshift ( ...flattened_subscriptions ) ;
1188+ } else {
1189+ // If the variable declaration is not part of a block, we instead get a dummy variable setting
1190+ // calling an immediately-invoked function expression containing all the subscription functions
1191+ node . declarations . push ( {
1192+ type : 'VariableDeclarator' ,
1193+ id : component . get_unique_name ( '$$subscriptions' , scope ) ,
1194+ init : x `(() => {
1195+ ${ flattened_subscriptions }
1196+ })()`
1197+ } ) ;
1198+ }
11751199 }
11761200
11771201 return this . skip ( ) ;
0 commit comments