diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c index b6d230f0d..92c6d2027 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c @@ -120,7 +120,7 @@ ecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */ * Runtime Semantics: PerformPromiseRace. * * See also: - * ES2015 25.4.4.3.1 + * ES2020 25.6.4.4.1 * * @return ecma value of the new promise. * Returned value must be freed with ecma_free_value. @@ -134,10 +134,29 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for { JERRY_ASSERT (ecma_is_value_object (iterator)); JERRY_ASSERT (ecma_object_class_is (capability_obj_p, LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); + JERRY_ASSERT (ecma_is_constructor (ctor)); ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; - /* 1. */ + /* 3. */ + ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (ctor), LIT_MAGIC_STRING_RESOLVE); + + if (ECMA_IS_VALUE_ERROR (resolve)) + { + return resolve; + } + + /* 4. */ + if (!ecma_op_is_callable (resolve)) + { + ecma_free_value (resolve); + return ecma_raise_type_error (ECMA_ERR_MSG ("Resolve method must be callable.")); + } + + ecma_object_t *resolve_func_p = ecma_get_object_from_value (resolve); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + + /* 5. */ while (true) { /* a. */ @@ -145,17 +164,15 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for /* b, c. */ if (ECMA_IS_VALUE_ERROR (next)) { - *done_p = true; - return next; + goto done; } /* d. */ if (ecma_is_value_false (next)) { - /* i. */ - *done_p = true; /* ii. */ - return ecma_copy_value (capability_p->header.u.class_prop.u.promise); + ret_value = ecma_copy_value (capability_p->header.u.class_prop.u.promise); + goto done; } /* e. */ @@ -165,42 +182,43 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for /* f, g. */ if (ECMA_IS_VALUE_ERROR (next_val)) { - *done_p = true; - return next_val; + goto done; } /* h. */ - ecma_value_t next_promise = ecma_op_invoke_by_magic_id (ctor, LIT_MAGIC_STRING_RESOLVE, &next_val, 1); + ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_val, 1); ecma_free_value (next_val); - /* i. */ if (ECMA_IS_VALUE_ERROR (next_promise)) { - return next_promise; + goto exit; } - /* j. */ + /* i. */ ecma_value_t args[2] = {capability_p->resolve, capability_p->reject}; ecma_value_t result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); ecma_free_value (next_promise); - /* k. */ if (ECMA_IS_VALUE_ERROR (result)) { - return result; + goto exit; } ecma_free_value (result); } - JERRY_UNREACHABLE (); +done: + *done_p = true; +exit: + ecma_deref_object (resolve_func_p); + return ret_value; } /* ecma_builtin_promise_perform_race */ /** * Runtime Semantics: PerformPromiseAll. * * See also: - * ES2015 25.4.4.1.1 + * ES2020 25.6.4.1.1 * * @return ecma value of the new promise. * Returned value must be freed with ecma_free_value. @@ -218,6 +236,22 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (ctor), + LIT_MAGIC_STRING_RESOLVE); + + if (ECMA_IS_VALUE_ERROR (resolve)) + { + return resolve; + } + + if (!ecma_op_is_callable (resolve)) + { + ecma_free_value (resolve); + return ecma_raise_type_error (ECMA_ERR_MSG ("Resolve method must be callable.")); + } + + ecma_object_t *resolve_func_p = ecma_get_object_from_value (resolve); + /* 3. */ ecma_object_t *values_array_obj_p = ecma_op_new_fast_array_object (0); ecma_value_t values_array = ecma_make_object_value (values_array_obj_p); @@ -236,16 +270,12 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ /* b. - c. */ if (ECMA_IS_VALUE_ERROR (next)) { - *done_p = true; - break; + goto done; } /* d. */ if (ecma_is_value_false (next)) { - /* i. */ - *done_p = true; - /* ii. - iii. */ if (ecma_promise_remaining_inc_or_dec (remaining, false) == 0) { @@ -257,7 +287,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ /* 3. */ if (ECMA_IS_VALUE_ERROR (resolve_result)) { - break; + goto done; } ecma_free_value (resolve_result); @@ -265,7 +295,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ /* iv. */ ret_value = ecma_copy_value (capability_p->header.u.class_prop.u.promise); - break; + goto done; } /* e. */ @@ -275,8 +305,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ /* f. - g. */ if (ECMA_IS_VALUE_ERROR (next_value)) { - *done_p = true; - break; + goto done; } /* h. */ @@ -286,19 +315,19 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); /* i. */ - ecma_value_t next_promise = ecma_op_invoke_by_magic_id (ctor, LIT_MAGIC_STRING_RESOLVE, &next_value, 1); + ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_value, 1); ecma_free_value (next_value); /* j. */ if (ECMA_IS_VALUE_ERROR (next_promise)) { - break; + goto exit; } if (JERRY_UNLIKELY (idx == UINT32_MAX - 1)) { ecma_raise_range_error (ECMA_ERR_MSG ("Promise.all remaining elements limit reached.")); - break; + goto exit; } /* k. */ @@ -333,14 +362,18 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ /* s. */ if (ECMA_IS_VALUE_ERROR (result)) { - break; + goto exit; } ecma_free_value (result); } +done: + *done_p = true; +exit: ecma_free_value (remaining); ecma_deref_object (values_array_obj_p); + ecma_deref_object (resolve_func_p); return ret_value; } /* ecma_builtin_promise_perform_all */ @@ -356,11 +389,6 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ ecma_value_t iterable, /**< the items to be resolved */ bool is_race) /**< indicates whether it is race function */ { - if (!ecma_is_value_object (this_arg)) - { - return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object.")); - } - ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg); if (JERRY_UNLIKELY (capability_obj_p == NULL)) diff --git a/tests/test262-es6-excludelist.xml b/tests/test262-es6-excludelist.xml index 7ebd8b657..da4462903 100644 --- a/tests/test262-es6-excludelist.xml +++ b/tests/test262-es6-excludelist.xml @@ -47,8 +47,8 @@ - - + Promise.all no longer uses @@species + Promise.race no longer uses @@species For-in supports proxy diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index a016c6dd8..5fc972653 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -817,10 +817,8 @@ - - - - + Test expects incorrect call order + Test expects incorrect call order @@ -919,11 +917,9 @@ - - - + Test expects incorrect call order - + Test expects incorrect call order