@@ -25,6 +25,9 @@ bitflags::bitflags! {
2525
2626 /// Was this [`CallFrame`] created from the `__construct__()` internal object method?
2727 const CONSTRUCT = 0b0000_0010 ;
28+
29+ /// Does this [`CallFrame`] need to push local variables on [`Vm::push_frame()`].
30+ const LOCALS_ALREADY_PUSHED = 0b0000_0100 ;
2831 }
2932}
3033
@@ -40,10 +43,6 @@ pub struct CallFrame {
4043 pub ( crate ) argument_count : u32 ,
4144 pub ( crate ) promise_capability : Option < PromiseCapability > ,
4245
43- // When an async generator is resumed, the generator object is needed
44- // to fulfill the steps 4.e-j in [AsyncGeneratorStart](https://tc39.es/ecma262/#sec-asyncgeneratorstart).
45- pub ( crate ) async_generator : Option < JsObject > ,
46-
4746 // Iterators and their `[[Done]]` flags that must be closed when an abrupt completion is thrown.
4847 pub ( crate ) iterators : ThinVec < IteratorRecord > ,
4948
@@ -123,6 +122,7 @@ impl CallFrame {
123122 pub ( crate ) const FUNCTION_PROLOGUE : u32 = 2 ;
124123 pub ( crate ) const THIS_POSITION : u32 = 2 ;
125124 pub ( crate ) const FUNCTION_POSITION : u32 = 1 ;
125+ pub ( crate ) const ASYNC_GENERATOR_OBJECT_LOCAL_INDEX : u32 = 0 ;
126126
127127 /// Creates a new `CallFrame` with the provided `CodeBlock`.
128128 pub ( crate ) fn new (
@@ -138,7 +138,6 @@ impl CallFrame {
138138 env_fp : 0 ,
139139 argument_count : 0 ,
140140 promise_capability : None ,
141- async_generator : None ,
142141 iterators : ThinVec :: new ( ) ,
143142 binding_stack : Vec :: new ( ) ,
144143 loop_iteration_count : 0 ,
@@ -201,6 +200,28 @@ impl CallFrame {
201200 vm. stack . truncate ( fp as usize ) ;
202201 }
203202
203+ /// Returns the async generator object, if the function that this [`GeneratorContext`] is from an async generator, [`None`] otherwise.
204+ pub ( crate ) fn async_generator_object ( & self , stack : & [ JsValue ] ) -> Option < JsObject > {
205+ if !self . code_block ( ) . is_async_generator ( ) {
206+ return None ;
207+ }
208+
209+ self . local ( Self :: ASYNC_GENERATOR_OBJECT_LOCAL_INDEX , stack)
210+ . as_object ( )
211+ . cloned ( )
212+ }
213+
214+ /// Returns the local at the given index.
215+ ///
216+ /// # Panics
217+ ///
218+ /// If the index is out of bounds.
219+ pub ( crate ) fn local < ' stack > ( & self , index : u32 , stack : & ' stack [ JsValue ] ) -> & ' stack JsValue {
220+ debug_assert ! ( index < self . code_block( ) . locals_count) ;
221+ let at = self . fp + index;
222+ & stack[ at as usize ]
223+ }
224+
204225 /// Does this have the [`CallFrameFlags::EXIT_EARLY`] flag.
205226 pub ( crate ) fn exit_early ( & self ) -> bool {
206227 self . flags . contains ( CallFrameFlags :: EXIT_EARLY )
@@ -213,6 +234,10 @@ impl CallFrame {
213234 pub ( crate ) fn construct ( & self ) -> bool {
214235 self . flags . contains ( CallFrameFlags :: CONSTRUCT )
215236 }
237+ /// Does this [`CallFrame`] need to push local variables on [`Vm::push_frame()`].
238+ pub ( crate ) fn locals_already_pushed ( & self ) -> bool {
239+ self . flags . contains ( CallFrameFlags :: LOCALS_ALREADY_PUSHED )
240+ }
216241}
217242
218243/// ---- `CallFrame` stack methods ----
0 commit comments