@@ -219,7 +219,113 @@ impl FunctionCompiler {
219219
220220 {
221221 let mut compiler = compiler. position_guard ( body) ;
222- compiler. compile_statement_list ( body. statement_list ( ) , false , false ) ;
222+
223+ // Check if the function body contains `using` declarations
224+ #[ cfg( feature = "experimental" ) ]
225+ let using_count: u32 = {
226+ use boa_ast:: {
227+ declaration:: LexicalDeclaration ,
228+ operations:: { LexicallyScopedDeclaration , lexically_scoped_declarations} ,
229+ } ;
230+
231+ lexically_scoped_declarations ( body. statement_list ( ) )
232+ . iter ( )
233+ . filter_map ( |decl| {
234+ if let LexicallyScopedDeclaration :: LexicalDeclaration (
235+ LexicalDeclaration :: Using ( u) | LexicalDeclaration :: AwaitUsing ( u) ,
236+ ) = decl
237+ {
238+ Some ( u. as_ref ( ) . len ( ) as u32 )
239+ } else {
240+ None
241+ }
242+ } )
243+ . sum ( )
244+ } ;
245+
246+ #[ cfg( not( feature = "experimental" ) ) ]
247+ let using_count: u32 = 0 ;
248+
249+ if using_count > 0 {
250+ #[ cfg( feature = "experimental" ) ]
251+ {
252+ use crate :: bytecompiler:: jump_control:: JumpControlInfoFlags ;
253+
254+ // Function body with `using` declarations needs try-finally semantics
255+ let finally_re_throw = compiler. register_allocator . alloc ( ) ;
256+ let finally_jump_index = compiler. register_allocator . alloc ( ) ;
257+
258+ compiler. bytecode . emit_store_true ( finally_re_throw. variable ( ) ) ;
259+ compiler. bytecode . emit_store_zero ( finally_jump_index. variable ( ) ) ;
260+
261+ // Push jump control info to handle break/continue/return through disposal
262+ compiler. push_try_with_finally_control_info (
263+ & finally_re_throw,
264+ & finally_jump_index,
265+ false ,
266+ ) ;
267+
268+ // Push exception handler
269+ let handler = compiler. push_handler ( ) ;
270+
271+ // Compile the function body
272+ compiler. compile_statement_list ( body. statement_list ( ) , false , false ) ;
273+
274+ // Normal exit: mark that we don't need to re-throw
275+ compiler. bytecode . emit_store_false ( finally_re_throw. variable ( ) ) ;
276+
277+ let finally_jump = compiler. jump ( ) ;
278+
279+ // Exception path: patch the handler
280+ compiler. patch_handler ( handler) ;
281+
282+ // Push a second handler for exceptions during exception handling
283+ let catch_handler = compiler. push_handler ( ) ;
284+ let error = compiler. register_allocator . alloc ( ) ;
285+ compiler. bytecode . emit_exception ( error. variable ( ) ) ;
286+ compiler. bytecode . emit_store_true ( finally_re_throw. variable ( ) ) ;
287+
288+ let no_throw = compiler. jump ( ) ;
289+ compiler. patch_handler ( catch_handler) ;
290+
291+ compiler. patch_jump ( no_throw) ;
292+ compiler. patch_jump ( finally_jump) ;
293+
294+ // Finally block: dispose resources
295+ let finally_start = compiler. next_opcode_location ( ) ;
296+ compiler. jump_info
297+ . last_mut ( )
298+ . expect ( "there should be a jump control info" )
299+ . flags |= JumpControlInfoFlags :: IN_FINALLY ;
300+
301+ // Save accumulator
302+ let value = compiler. register_allocator . alloc ( ) ;
303+ compiler. bytecode
304+ . emit_set_register_from_accumulator ( value. variable ( ) ) ;
305+
306+ // Emit disposal logic
307+ compiler. bytecode . emit_dispose_resources ( using_count. into ( ) ) ;
308+
309+ // Restore accumulator
310+ compiler. bytecode . emit_set_accumulator ( value. variable ( ) ) ;
311+ compiler. register_allocator . dealloc ( value) ;
312+
313+ // Re-throw if there was an exception
314+ let do_not_throw_exit = compiler. jump_if_false ( & finally_re_throw) ;
315+ compiler. bytecode . emit_throw ( error. variable ( ) ) ;
316+ compiler. register_allocator . dealloc ( error) ;
317+ compiler. patch_jump ( do_not_throw_exit) ;
318+
319+ // Pop jump control info (this handles break/continue/return via jump table)
320+ compiler. pop_try_with_finally_control_info ( finally_start) ;
321+
322+ compiler. register_allocator . dealloc ( finally_re_throw) ;
323+ compiler. register_allocator . dealloc ( finally_jump_index) ;
324+ }
325+ } else {
326+ // Normal function body compilation (no using declarations)
327+ compiler. compile_statement_list ( body. statement_list ( ) , false , false ) ;
328+ }
223329 }
224330
225331 compiler. params = parameters. clone ( ) ;
0 commit comments