Update Promise.all/race to ES11 (#4202)

JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai daniel.batyai@h-lab.eu
This commit is contained in:
Dániel Bátyai
2020-09-18 14:05:48 +02:00
committed by GitHub
parent 74f66879c2
commit 55554535b2
3 changed files with 69 additions and 45 deletions
@@ -120,7 +120,7 @@ ecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */
* Runtime Semantics: PerformPromiseRace. * Runtime Semantics: PerformPromiseRace.
* *
* See also: * See also:
* ES2015 25.4.4.3.1 * ES2020 25.6.4.4.1
* *
* @return ecma value of the new promise. * @return ecma value of the new promise.
* Returned value must be freed with ecma_free_value. * 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_is_value_object (iterator));
JERRY_ASSERT (ecma_object_class_is (capability_obj_p, LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); 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; 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) while (true)
{ {
/* a. */ /* a. */
@@ -145,17 +164,15 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for
/* b, c. */ /* b, c. */
if (ECMA_IS_VALUE_ERROR (next)) if (ECMA_IS_VALUE_ERROR (next))
{ {
*done_p = true; goto done;
return next;
} }
/* d. */ /* d. */
if (ecma_is_value_false (next)) if (ecma_is_value_false (next))
{ {
/* i. */
*done_p = true;
/* ii. */ /* 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. */ /* e. */
@@ -165,42 +182,43 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for
/* f, g. */ /* f, g. */
if (ECMA_IS_VALUE_ERROR (next_val)) if (ECMA_IS_VALUE_ERROR (next_val))
{ {
*done_p = true; goto done;
return next_val;
} }
/* h. */ /* 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); ecma_free_value (next_val);
/* i. */
if (ECMA_IS_VALUE_ERROR (next_promise)) 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 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_value_t result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2);
ecma_free_value (next_promise); ecma_free_value (next_promise);
/* k. */
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
return result; goto exit;
} }
ecma_free_value (result); 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 */ } /* ecma_builtin_promise_perform_race */
/** /**
* Runtime Semantics: PerformPromiseAll. * Runtime Semantics: PerformPromiseAll.
* *
* See also: * See also:
* ES2015 25.4.4.1.1 * ES2020 25.6.4.1.1
* *
* @return ecma value of the new promise. * @return ecma value of the new promise.
* Returned value must be freed with ecma_free_value. * 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_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. */ /* 3. */
ecma_object_t *values_array_obj_p = ecma_op_new_fast_array_object (0); 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); 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. */ /* b. - c. */
if (ECMA_IS_VALUE_ERROR (next)) if (ECMA_IS_VALUE_ERROR (next))
{ {
*done_p = true; goto done;
break;
} }
/* d. */ /* d. */
if (ecma_is_value_false (next)) if (ecma_is_value_false (next))
{ {
/* i. */
*done_p = true;
/* ii. - iii. */ /* ii. - iii. */
if (ecma_promise_remaining_inc_or_dec (remaining, false) == 0) 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. */ /* 3. */
if (ECMA_IS_VALUE_ERROR (resolve_result)) if (ECMA_IS_VALUE_ERROR (resolve_result))
{ {
break; goto done;
} }
ecma_free_value (resolve_result); ecma_free_value (resolve_result);
@@ -265,7 +295,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
/* iv. */ /* iv. */
ret_value = ecma_copy_value (capability_p->header.u.class_prop.u.promise); ret_value = ecma_copy_value (capability_p->header.u.class_prop.u.promise);
break; goto done;
} }
/* e. */ /* e. */
@@ -275,8 +305,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
/* f. - g. */ /* f. - g. */
if (ECMA_IS_VALUE_ERROR (next_value)) if (ECMA_IS_VALUE_ERROR (next_value))
{ {
*done_p = true; goto done;
break;
} }
/* h. */ /* h. */
@@ -286,19 +315,19 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
/* i. */ /* 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); ecma_free_value (next_value);
/* j. */ /* j. */
if (ECMA_IS_VALUE_ERROR (next_promise)) if (ECMA_IS_VALUE_ERROR (next_promise))
{ {
break; goto exit;
} }
if (JERRY_UNLIKELY (idx == UINT32_MAX - 1)) if (JERRY_UNLIKELY (idx == UINT32_MAX - 1))
{ {
ecma_raise_range_error (ECMA_ERR_MSG ("Promise.all remaining elements limit reached.")); ecma_raise_range_error (ECMA_ERR_MSG ("Promise.all remaining elements limit reached."));
break; goto exit;
} }
/* k. */ /* k. */
@@ -333,14 +362,18 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
/* s. */ /* s. */
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
break; goto exit;
} }
ecma_free_value (result); ecma_free_value (result);
} }
done:
*done_p = true;
exit:
ecma_free_value (remaining); ecma_free_value (remaining);
ecma_deref_object (values_array_obj_p); ecma_deref_object (values_array_obj_p);
ecma_deref_object (resolve_func_p);
return ret_value; return ret_value;
} /* ecma_builtin_promise_perform_all */ } /* 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 */ ecma_value_t iterable, /**< the items to be resolved */
bool is_race) /**< indicates whether it is race function */ 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); ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg);
if (JERRY_UNLIKELY (capability_obj_p == NULL)) if (JERRY_UNLIKELY (capability_obj_p == NULL))
+2 -2
View File
@@ -47,8 +47,8 @@
<test id="built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js"><reason></reason></test> <test id="built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js"><reason></reason></test>
<test id="built-ins/decodeURI/S15.1.3.1_A2.5_T1.js"><reason></reason></test> <test id="built-ins/decodeURI/S15.1.3.1_A2.5_T1.js"><reason></reason></test>
<test id="built-ins/GeneratorPrototype/next/context-constructor-invocation.js"><reason></reason></test> <test id="built-ins/GeneratorPrototype/next/context-constructor-invocation.js"><reason></reason></test>
<test id="built-ins/Promise/all/species-get-error.js"><reason></reason></test> <test id="built-ins/Promise/all/species-get-error.js"><reason>Promise.all no longer uses @@species</reason></test>
<test id="built-ins/Promise/race/species-get-error.js"><reason></reason></test> <test id="built-ins/Promise/race/species-get-error.js"><reason>Promise.race no longer uses @@species</reason></test>
<test id="built-ins/Proxy/enumerate/call-parameters.js"><reason></reason></test> <test id="built-ins/Proxy/enumerate/call-parameters.js"><reason></reason></test>
<test id="built-ins/Proxy/enumerate/return-is-abrupt.js"><reason></reason></test> <test id="built-ins/Proxy/enumerate/return-is-abrupt.js"><reason></reason></test>
<test id="built-ins/Proxy/enumerate/result-not-an-object-throws-boolean.js"><reason>For-in supports proxy</reason></test> <test id="built-ins/Proxy/enumerate/result-not-an-object-throws-boolean.js"><reason>For-in supports proxy</reason></test>
+4 -8
View File
@@ -817,10 +817,8 @@
<test id="built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js"><reason></reason></test> <test id="built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js"><reason></reason></test>
<test id="built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js"><reason></reason></test> <test id="built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js"><reason></reason></test>
<test id="built-ins/Object/subclass-object-arg.js"><reason></reason></test> <test id="built-ins/Object/subclass-object-arg.js"><reason></reason></test>
<test id="built-ins/Promise/all/invoke-resolve-get-error.js"><reason></reason></test> <test id="built-ins/Promise/all/invoke-resolve-get-error.js"><reason>Test expects incorrect call order</reason></test>
<test id="built-ins/Promise/all/invoke-resolve-get-once-multiple-calls.js"><reason></reason></test> <test id="built-ins/Promise/all/resolve-non-callable.js"><reason>Test expects incorrect call order</reason></test>
<test id="built-ins/Promise/all/invoke-resolve-get-once-no-calls.js"><reason></reason></test>
<test id="built-ins/Promise/all/resolve-non-callable.js"><reason></reason></test>
<test id="built-ins/Promise/allSettled/call-resolve-element-after-return.js"><reason></reason></test> <test id="built-ins/Promise/allSettled/call-resolve-element-after-return.js"><reason></reason></test>
<test id="built-ins/Promise/allSettled/call-resolve-element-items.js"><reason></reason></test> <test id="built-ins/Promise/allSettled/call-resolve-element-items.js"><reason></reason></test>
<test id="built-ins/Promise/allSettled/call-resolve-element.js"><reason></reason></test> <test id="built-ins/Promise/allSettled/call-resolve-element.js"><reason></reason></test>
@@ -919,11 +917,9 @@
<test id="built-ins/Promise/allSettled/returns-promise.js"><reason></reason></test> <test id="built-ins/Promise/allSettled/returns-promise.js"><reason></reason></test>
<test id="built-ins/Promise/allSettled/species-get-error.js"><reason></reason></test> <test id="built-ins/Promise/allSettled/species-get-error.js"><reason></reason></test>
<test id="built-ins/Promise/proto-from-ctor-realm.js"><reason></reason></test> <test id="built-ins/Promise/proto-from-ctor-realm.js"><reason></reason></test>
<test id="built-ins/Promise/race/invoke-resolve-get-error.js"><reason></reason></test> <test id="built-ins/Promise/race/invoke-resolve-get-error.js"><reason>Test expects incorrect call order</reason></test>
<test id="built-ins/Promise/race/invoke-resolve-get-once-multiple-calls.js"><reason></reason></test>
<test id="built-ins/Promise/race/invoke-resolve-get-once-no-calls.js"><reason></reason></test>
<test id="built-ins/Promise/race/resolve-element-function-name.js"><reason></reason></test> <test id="built-ins/Promise/race/resolve-element-function-name.js"><reason></reason></test>
<test id="built-ins/Promise/race/resolve-non-callable.js"><reason></reason></test> <test id="built-ins/Promise/race/resolve-non-callable.js"><reason>Test expects incorrect call order</reason></test>
<test id="built-ins/Proxy/apply/arguments-realm.js"><reason></reason></test> <test id="built-ins/Proxy/apply/arguments-realm.js"><reason></reason></test>
<test id="built-ins/Proxy/apply/null-handler-realm.js"><reason></reason></test> <test id="built-ins/Proxy/apply/null-handler-realm.js"><reason></reason></test>
<test id="built-ins/Proxy/apply/trap-is-not-callable-realm.js"><reason></reason></test> <test id="built-ins/Proxy/apply/trap-is-not-callable-realm.js"><reason></reason></test>