11use crate :: {
22 ecmascript:: {
3+ abstract_operations:: operations_on_objects:: define_property_or_throw,
34 builtins:: {
45 Array ,
6+ error:: ErrorHeapData ,
57 promise:: Promise ,
68 promise_objects:: promise_abstract_operations:: {
79 promise_capability_records:: PromiseCapability ,
810 promise_reaction_records:: PromiseReactionType ,
911 } ,
1012 } ,
11- execution:: Agent ,
12- types:: { BUILTIN_STRING_MEMORY , IntoValue , OrdinaryObject , Value } ,
13+ execution:: { Agent , agent :: ExceptionType } ,
14+ types:: { BUILTIN_STRING_MEMORY , IntoValue , OrdinaryObject , PropertyDescriptor , Value } ,
1315 } ,
1416 engine:: {
1517 context:: { Bindable , GcScope , NoGcScope , bindable_handle} ,
@@ -23,8 +25,9 @@ use crate::{
2325
2426#[ derive( Debug , Clone , Copy ) ]
2527pub enum PromiseGroupType {
26- PromiseAll ,
27- PromiseAllSettled ,
28+ All ,
29+ AllSettled ,
30+ Any ,
2831}
2932
3033#[ derive( Debug , Clone , Copy ) ]
@@ -64,30 +67,32 @@ impl<'a> PromiseGroup<'a> {
6467 let record = self . get ( agent) ;
6568
6669 match record. promise_group_type {
67- PromiseGroupType :: PromiseAll => match reaction_type {
70+ PromiseGroupType :: All => match reaction_type {
6871 PromiseReactionType :: Fulfill => {
6972 self . fulfill ( agent, index, value. unbind ( ) , gc. reborrow ( ) ) ;
7073 }
7174 PromiseReactionType :: Reject => {
72- self . reject ( agent, value. unbind ( ) , gc. nogc ( ) ) ;
75+ self . immediately_reject ( agent, value. unbind ( ) , gc. nogc ( ) ) ;
7376 }
7477 } ,
75- PromiseGroupType :: PromiseAllSettled => {
78+ PromiseGroupType :: AllSettled => {
7679 let obj = self
7780 . to_all_settled_obj ( agent, reaction_type, value. unbind ( ) , gc. nogc ( ) )
7881 . bind ( gc. nogc ( ) ) ;
7982 self . fulfill ( agent, index, obj. unbind ( ) , gc. reborrow ( ) ) ;
8083 }
84+ PromiseGroupType :: Any => match reaction_type {
85+ PromiseReactionType :: Fulfill => {
86+ self . immediately_resolve ( agent, value. unbind ( ) , gc. reborrow ( ) ) ;
87+ }
88+ PromiseReactionType :: Reject => {
89+ self . reject ( agent, index, value. unbind ( ) , gc. reborrow ( ) ) ;
90+ }
91+ } ,
8192 }
8293 }
8394
84- pub ( crate ) fn fulfill (
85- self ,
86- agent : & mut Agent ,
87- index : u32 ,
88- value : Value < ' a > ,
89- mut gc : GcScope < ' a , ' _ > ,
90- ) {
95+ fn fulfill ( self , agent : & mut Agent , index : u32 , value : Value < ' a > , mut gc : GcScope < ' a , ' _ > ) {
9196 let promise_group = self . bind ( gc. nogc ( ) ) ;
9297 let value = value. bind ( gc. nogc ( ) ) ;
9398
@@ -98,17 +103,72 @@ impl<'a> PromiseGroup<'a> {
98103 elements[ index as usize ] = Some ( value. unbind ( ) ) ;
99104
100105 if let Some ( promise_to_resolve) = promise_to_resolve {
106+ promise_group. pop_empty_records ( agent) ;
107+
101108 let capability = PromiseCapability :: from_promise ( promise_to_resolve, true ) ;
102109 capability. resolve ( agent, result_array. into_value ( ) . unbind ( ) , gc. reborrow ( ) ) ;
103110 }
104111 }
105112
106- pub ( crate ) fn reject ( self , agent : & mut Agent , value : Value < ' a > , gc : NoGcScope < ' a , ' _ > ) {
113+ fn reject ( self , agent : & mut Agent , index : u32 , error : Value < ' a > , mut gc : GcScope < ' a , ' _ > ) {
114+ let promise_group = self . bind ( gc. nogc ( ) ) ;
115+ let error = error. bind ( gc. nogc ( ) ) ;
116+
117+ let promise_group_record = promise_group. get_mut ( agent) ;
118+ let ( result_array, promise_to_resolve) = promise_group_record. take_result_and_promise ( ) ;
119+
120+ let elements = result_array. as_mut_slice ( agent) ;
121+ elements[ index as usize ] = Some ( error. unbind ( ) ) ;
122+
123+ if let Some ( promise_to_resolve) = promise_to_resolve {
124+ promise_group. pop_empty_records ( agent) ;
125+
126+ let aggregate_error = agent. heap . create ( ErrorHeapData :: new (
127+ ExceptionType :: AggregateError ,
128+ None ,
129+ None ,
130+ ) ) ;
131+
132+ let capability = PromiseCapability :: from_promise ( promise_to_resolve, true ) ;
133+ define_property_or_throw (
134+ agent,
135+ aggregate_error,
136+ BUILTIN_STRING_MEMORY . errors . into ( ) ,
137+ PropertyDescriptor {
138+ value : Some ( result_array. into_value ( ) . unbind ( ) ) ,
139+ writable : Some ( true ) ,
140+ get : None ,
141+ set : None ,
142+ enumerable : Some ( true ) ,
143+ configurable : Some ( true ) ,
144+ } ,
145+ gc. reborrow ( ) ,
146+ )
147+ . unwrap ( ) ;
148+
149+ capability. reject ( agent, aggregate_error. into_value ( ) , gc. nogc ( ) ) ;
150+ }
151+ }
152+
153+ fn immediately_resolve ( self , agent : & mut Agent , value : Value < ' a > , gc : GcScope < ' a , ' _ > ) {
154+ let value = value. bind ( gc. nogc ( ) ) ;
155+ let promise_group = self . bind ( gc. nogc ( ) ) ;
156+ let data = promise_group. get_mut ( agent) ;
157+
158+ let capability = PromiseCapability :: from_promise ( data. promise , true ) ;
159+
160+ promise_group. pop_empty_records ( agent) ;
161+ capability. resolve ( agent, value. unbind ( ) , gc) ;
162+ }
163+
164+ fn immediately_reject ( self , agent : & mut Agent , value : Value < ' a > , gc : NoGcScope < ' a , ' _ > ) {
107165 let value = value. bind ( gc) ;
108166 let promise_group = self . bind ( gc) ;
109167 let data = promise_group. get_mut ( agent) ;
110168
111169 let capability = PromiseCapability :: from_promise ( data. promise , true ) ;
170+
171+ promise_group. pop_empty_records ( agent) ;
112172 capability. reject ( agent, value. unbind ( ) , gc) ;
113173 }
114174
@@ -121,47 +181,35 @@ impl<'a> PromiseGroup<'a> {
121181 ) -> Value < ' a > {
122182 let value = value. bind ( gc) ;
123183
124- let obj = match reaction_type {
125- PromiseReactionType :: Fulfill => OrdinaryObject :: create_object (
126- agent,
127- Some (
128- agent
129- . current_realm_record ( )
130- . intrinsics ( )
131- . object_prototype ( )
132- . into ( ) ,
133- ) ,
134- & [
135- ObjectEntry :: new_data_entry (
136- BUILTIN_STRING_MEMORY . status . into ( ) ,
137- BUILTIN_STRING_MEMORY . fulfilled . into ( ) ,
138- ) ,
139- ObjectEntry :: new_data_entry ( BUILTIN_STRING_MEMORY . value . into ( ) , value. unbind ( ) ) ,
140- ] ,
141- )
142- . bind ( gc) ,
143- PromiseReactionType :: Reject => OrdinaryObject :: create_object (
144- agent,
145- Some (
146- agent
147- . current_realm_record ( )
148- . intrinsics ( )
149- . object_prototype ( )
150- . into ( ) ,
151- ) ,
152- & [
153- ObjectEntry :: new_data_entry (
154- BUILTIN_STRING_MEMORY . status . into ( ) ,
155- BUILTIN_STRING_MEMORY . rejected . into ( ) ,
156- ) ,
157- ObjectEntry :: new_data_entry (
158- BUILTIN_STRING_MEMORY . reason . into ( ) ,
159- value. unbind ( ) ,
160- ) ,
161- ] ,
162- )
163- . bind ( gc) ,
164- } ;
184+ let entries = vec ! [
185+ ObjectEntry :: new_data_entry(
186+ BUILTIN_STRING_MEMORY . status. into( ) ,
187+ match reaction_type {
188+ PromiseReactionType :: Fulfill => BUILTIN_STRING_MEMORY . fulfilled. into( ) ,
189+ PromiseReactionType :: Reject => BUILTIN_STRING_MEMORY . rejected. into( ) ,
190+ } ,
191+ ) ,
192+ ObjectEntry :: new_data_entry(
193+ match reaction_type {
194+ PromiseReactionType :: Fulfill => BUILTIN_STRING_MEMORY . value. into( ) ,
195+ PromiseReactionType :: Reject => BUILTIN_STRING_MEMORY . reason. into( ) ,
196+ } ,
197+ value. unbind( ) ,
198+ ) ,
199+ ] ;
200+
201+ let obj = OrdinaryObject :: create_object (
202+ agent,
203+ Some (
204+ agent
205+ . current_realm_record ( )
206+ . intrinsics ( )
207+ . object_prototype ( )
208+ . into ( ) ,
209+ ) ,
210+ & entries,
211+ )
212+ . bind ( gc) ;
165213
166214 obj. into_value ( ) . unbind ( )
167215 }
@@ -186,6 +234,16 @@ impl<'a> PromiseGroup<'a> {
186234 . expect ( "PromiseGroupRecord not found" )
187235 }
188236
237+ fn pop_empty_records ( self , agent : & mut Agent ) {
238+ while let Some ( last) = agent. heap . promise_group_records . last ( ) {
239+ if last. remaining_elements_count == 0 {
240+ agent. heap . promise_group_records . pop ( ) ;
241+ } else {
242+ break ;
243+ }
244+ }
245+ }
246+
189247 pub ( crate ) const _DEF: Self = { Self ( BaseIndex :: from_u32_index ( 0 ) ) } ;
190248}
191249
0 commit comments