@@ -161,6 +161,38 @@ ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reac
161161 }
162162} /* ecma_promise_trigger_reactions */
163163
164+ /**
165+ * Checks whether a resolver is called before.
166+ *
167+ * @return true if it was called before, false otherwise
168+ */
169+ static bool
170+ ecma_is_resolver_already_called (ecma_object_t * resolver_p , /**< resolver */
171+ ecma_object_t * promise_obj_p ) /**< promise */
172+ {
173+ ecma_string_t * str_already_resolved_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED );
174+ ecma_property_t * property_p = ecma_find_named_property (resolver_p , str_already_resolved_p );
175+
176+ if (property_p == NULL )
177+ {
178+ return (ecma_promise_get_flags (promise_obj_p ) & ECMA_PROMISE_ALREADY_RESOLVED ) != 0 ;
179+ }
180+
181+ JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (* property_p ) == ECMA_PROPERTY_TYPE_NAMEDDATA );
182+
183+ ecma_value_t already_resolved = ECMA_PROPERTY_VALUE_PTR (property_p )-> value ;
184+ ecma_object_t * object_p = ecma_get_object_from_value (already_resolved );
185+ JERRY_ASSERT (ecma_get_object_type (object_p ) == ECMA_OBJECT_TYPE_CLASS );
186+
187+ ecma_extended_object_t * already_resolved_p = (ecma_extended_object_t * ) object_p ;
188+ JERRY_ASSERT (already_resolved_p -> u .class_prop .class_id == LIT_MAGIC_STRING_BOOLEAN_UL );
189+
190+ ecma_value_t current_value = already_resolved_p -> u .class_prop .u .value ;
191+ already_resolved_p -> u .class_prop .u .value = ECMA_VALUE_TRUE ;
192+
193+ return current_value == ECMA_VALUE_TRUE ;
194+ } /* ecma_is_resolver_already_called */
195+
164196/**
165197 * Reject a Promise with a reason.
166198 *
@@ -242,18 +274,16 @@ ecma_promise_reject_handler (const ecma_value_t function, /**< the function itse
242274 JERRY_ASSERT (ecma_is_promise (promise_obj_p ));
243275
244276 /* 3., 4. */
245- if (ecma_promise_get_flags ( promise_obj_p ) & ECMA_PROMISE_ALREADY_RESOLVED )
277+ if (! ecma_is_resolver_already_called ( function_p , promise_obj_p ))
246278 {
247- ecma_free_value (promise );
248- return ECMA_VALUE_UNDEFINED ;
249- }
279+ /* 5. */
280+ ((ecma_extended_object_t * ) promise_obj_p )-> u .class_prop .extra_info |= ECMA_PROMISE_ALREADY_RESOLVED ;
250281
251- /* 5. */
252- ((ecma_extended_object_t * ) promise_obj_p )-> u .class_prop .extra_info |= ECMA_PROMISE_ALREADY_RESOLVED ;
282+ /* 6. */
283+ ecma_value_t reject_value = (argc == 0 ) ? ECMA_VALUE_UNDEFINED : argv [0 ];
284+ ecma_reject_promise (promise , reject_value );
285+ }
253286
254- /* 6. */
255- ecma_value_t reject_value = (argc == 0 ) ? ECMA_VALUE_UNDEFINED : argv [0 ];
256- ecma_reject_promise (promise , reject_value );
257287 ecma_free_value (promise );
258288 return ECMA_VALUE_UNDEFINED ;
259289} /* ecma_promise_reject_handler */
@@ -281,7 +311,7 @@ ecma_promise_resolve_handler (const ecma_value_t function, /**< the function its
281311 JERRY_ASSERT (ecma_is_promise (promise_obj_p ));
282312
283313 /* 3., 4. */
284- if (ecma_promise_get_flags ( promise_obj_p ) & ECMA_PROMISE_ALREADY_RESOLVED )
314+ if (ecma_is_resolver_already_called ( function_p , promise_obj_p ))
285315 {
286316 goto end_of_resolve_function ;
287317 }
@@ -428,7 +458,8 @@ ecma_promise_create_resolving_functions_helper (ecma_object_t *obj_p, /**< Promi
428458 */
429459void
430460ecma_promise_create_resolving_functions (ecma_object_t * object_p , /**< the promise object */
431- ecma_promise_resolving_functions_t * funcs ) /**< [out] resolving functions */
461+ ecma_promise_resolving_functions_t * funcs , /**< [out] resolving functions */
462+ bool create_already_resolved ) /**< create already resolved flag */
432463{
433464 /* 2. - 4. */
434465 funcs -> resolve = ecma_promise_create_resolving_functions_helper (object_p ,
@@ -437,6 +468,28 @@ ecma_promise_create_resolving_functions (ecma_object_t *object_p, /**< the promi
437468 /* 5. - 7. */
438469 funcs -> reject = ecma_promise_create_resolving_functions_helper (object_p ,
439470 ecma_promise_reject_handler );
471+ if (!create_already_resolved )
472+ {
473+ return ;
474+ }
475+
476+ ecma_value_t already_resolved = ecma_op_create_boolean_object (ECMA_VALUE_FALSE );
477+ ecma_string_t * str_already_resolved_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED );
478+ ecma_property_value_t * value_p ;
479+
480+ value_p = ecma_create_named_data_property (ecma_get_object_from_value (funcs -> resolve ),
481+ str_already_resolved_p ,
482+ ECMA_PROPERTY_FIXED ,
483+ NULL );
484+ value_p -> value = already_resolved ;
485+
486+ value_p = ecma_create_named_data_property (ecma_get_object_from_value (funcs -> reject ),
487+ str_already_resolved_p ,
488+ ECMA_PROPERTY_FIXED ,
489+ NULL );
490+ value_p -> value = already_resolved ;
491+
492+ ecma_free_value (already_resolved );
440493} /* ecma_promise_create_resolving_functions */
441494
442495/**
@@ -490,7 +543,7 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
490543 promise_object_p -> reactions = reactions ;
491544 /* 8. */
492545 ecma_promise_resolving_functions_t funcs ;
493- ecma_promise_create_resolving_functions (object_p , & funcs );
546+ ecma_promise_create_resolving_functions (object_p , & funcs , false );
494547
495548 ecma_string_t * str_resolve_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION );
496549 ecma_string_t * str_reject_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION );
0 commit comments