diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index e293538b4..4e01f066b 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -633,6 +633,24 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ ecma_gc_mark_executable_object (object_p); break; } + case LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY: + { + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) object_p; + + if (ecma_is_value_object (capability_p->header.u.class_prop.u.promise)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->header.u.class_prop.u.promise)); + } + if (ecma_is_value_object (capability_p->resolve)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->resolve)); + } + if (ecma_is_value_object (capability_p->reject)) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (capability_p->reject)); + } + break; + } #endif /* ENABLED (JERRY_ESNEXT) */ default: { @@ -765,6 +783,18 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ ecma_gc_set_object_visited (ecma_get_object_from_value (rev_proxy_p->proxy)); } } + else if (ext_func_p->u.external_handler_cb == ecma_op_get_capabilities_executor_cb) + { + ecma_promise_capability_executor_t *executor_p = (ecma_promise_capability_executor_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->capability)); + } + else if (ext_func_p->u.external_handler_cb == ecma_promise_all_handler_cb) + { + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) object_p; + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->capability)); + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->values)); + ecma_gc_set_object_visited (ecma_get_object_from_value (executor_p->remaining_elements)); + } break; } #endif /* ENABLED (JERRY_ESNEXT) */ @@ -1124,6 +1154,14 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ { ext_object_size = sizeof (ecma_revocable_proxy_object_t); } + else if (ext_func_p->u.external_handler_cb == ecma_op_get_capabilities_executor_cb) + { + ext_object_size = sizeof (ecma_promise_capability_executor_t); + } + else if (ext_func_p->u.external_handler_cb == ecma_promise_all_handler_cb) + { + ext_object_size = sizeof (ecma_promise_all_executor_t); + } #endif /* ENABLED (JERRY_ESNEXT) */ break; } @@ -1234,6 +1272,11 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ ext_object_size = ecma_gc_free_executable_object (object_p); break; } + case LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY: + { + ext_object_size = sizeof (ecma_promise_capabality_t); + break; + } #endif /* ENABLED (JERRY_ESNEXT) */ default: { diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 69d0693ac..64eb1b8d5 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -880,6 +880,7 @@ typedef struct uint32_t length; /**< length related property (e.g. length of ArrayBuffer) */ ecma_value_t target; /**< [[ProxyTarget]] internal property */ ecma_value_t head; /**< points to the async generator task queue head item */ + ecma_value_t promise; /**< PromiseCapability[[Promise]] internal slot */ } u; } class_prop; @@ -1933,6 +1934,39 @@ typedef struct uint8_t operation_type; /**< type of operation (see ecma_async_generator_operation_type_t) */ } ecma_async_generator_task_t; +/** + * Definition of PromiseCapability Records + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header, and [[Promise]] internal slot */ + ecma_value_t resolve; /**< [[Resolve]] internal slot */ + ecma_value_t reject; /**< [[Reject]] internal slot */ +} ecma_promise_capabality_t; + +/** + * Definition of GetCapabilitiesExecutor Functions + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t capability; /**< [[Capability]] internal slot */ +} ecma_promise_capability_executor_t; + +/** + * Definition of Promise.all Resolve Element Functions + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t remaining_elements; /**< [[Remaining elements]] internal slot */ + ecma_value_t capability; /**< [[Capabilities]] internal slot */ + ecma_value_t values; /**< [[Values]] internal slot */ + uint32_t index; /**< [[Index]] and [[AlreadyCalled]] internal slot + * 0 - if the element has been resolved + * real index + 1 in the [[Values]] list - otherwise */ +} ecma_promise_all_executor_t; + #endif /* ENABLED (JERRY_ESNEXT) */ #if ENABLED (JERRY_BUILTIN_DATAVIEW) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c index eb4c06f4f..fb660c981 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "ecma-alloc.h" #include "ecma-array-object.h" #include "ecma-builtin-helpers.h" #include "ecma-exceptions.h" @@ -54,22 +55,22 @@ */ inline static ecma_value_t ecma_builtin_promise_reject_abrupt (ecma_value_t value, /**< value */ - ecma_value_t capability) /**< capability */ + ecma_object_t *capability_obj_p) /**< capability */ { + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); + if (!ECMA_IS_VALUE_ERROR (value)) { return value; } ecma_value_t reason = jcontext_take_exception (); - ecma_value_t reject = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (capability), - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); - ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (reject), + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &reason, 1); - ecma_free_value (reject); ecma_free_value (reason); if (ECMA_IS_VALUE_ERROR (call_ret)) @@ -79,8 +80,7 @@ ecma_builtin_promise_reject_abrupt (ecma_value_t value, /**< value */ ecma_free_value (call_ret); - return ecma_op_object_get_by_magic_id (ecma_get_object_from_value (capability), - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); + return ecma_copy_value (capability_p->header.u.class_prop.u.promise); } /* ecma_builtin_promise_reject_abrupt */ /** @@ -127,14 +127,15 @@ ecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */ inline static ecma_value_t ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for race */ ecma_value_t next_method, /**< next method */ - ecma_value_t capability, /**< PromiseCapability record */ + ecma_object_t *capability_obj_p, /**< PromiseCapability record */ ecma_value_t ctor, /**< Constructor value */ bool *done_p) /**< [out] iteratorRecord[[done]] */ { - JERRY_ASSERT (ecma_is_value_object (iterator) - && ecma_is_value_object (capability)); + JERRY_ASSERT (ecma_is_value_object (iterator)); + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; - ecma_object_t *capability_obj_p = ecma_get_object_from_value (capability); /* 1. */ while (true) { @@ -153,7 +154,7 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for /* i. */ *done_p = true; /* ii. */ - return ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); + return ecma_copy_value (capability_p->header.u.class_prop.u.promise); } /* e. */ @@ -178,17 +179,10 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for } /* j. */ - ecma_value_t args[2]; - args[0] = ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - args[1] = ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_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_free_value (next_promise); - for (uint8_t i = 0; i < 2; i++) - { - ecma_free_value (args[i]); - } - /* k. */ if (ECMA_IS_VALUE_ERROR (result)) { @@ -201,116 +195,6 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for JERRY_UNREACHABLE (); } /* ecma_builtin_promise_perform_race */ -/** - * Helper function for increase or decrease the remaining count. - * - * @return the current remaining count after increase or decrease. - */ -static ecma_length_t -ecma_builtin_promise_remaining_inc_or_dec (ecma_value_t remaining, /**< the remaining count */ - bool is_inc) /**< whether to increase the count */ -{ - JERRY_ASSERT (ecma_is_value_object (remaining)); - - ecma_object_t *remaining_p = ecma_get_object_from_value (remaining); - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) remaining_p; - - JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_NUMBER_UL); - - JERRY_ASSERT (ecma_is_value_integer_number (ext_object_p->u.class_prop.u.value)); - - ecma_length_t current = (ecma_length_t) ecma_get_integer_from_value (ext_object_p->u.class_prop.u.value); - - if (is_inc) - { - current++; - } - else - { - current--; - } - ext_object_p->u.class_prop.u.value = ecma_make_uint32_value (current); - - return current; -} /* ecma_builtin_promise_remaining_inc_or_dec */ - -/** - * Native handler for Promise.all Resolve Element Function. - * - * See also: - * ES2015 25.4.4.1.2 - * - * @return ecma value of undefined. - */ -static ecma_value_t -ecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function itself */ - const ecma_value_t this, /**< this_arg of the function */ - const ecma_value_t argv[], /**< argument list */ - const ecma_length_t argc) /**< argument number */ -{ - JERRY_UNUSED (this); - JERRY_UNUSED (argc); - - /* 1. */ - ecma_object_t *function_p = ecma_get_object_from_value (function); - ecma_string_t *already_called_str_p; - already_called_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_ALREADY_CALLED); - ecma_value_t already_called = ecma_op_object_get (function_p, already_called_str_p); - - JERRY_ASSERT (ecma_is_value_boolean (already_called)); - - /* 2. */ - if (ecma_is_value_true (already_called)) - { - return ECMA_VALUE_UNDEFINED; - } - - /* 3. */ - ecma_op_object_put (function_p, - already_called_str_p, - ECMA_VALUE_TRUE, - false); - - ecma_string_t *str_index_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX); - ecma_string_t *str_value_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE); - ecma_string_t *str_capability_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); - ecma_string_t *str_remaining_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT); - - /* 4-7. */ - ecma_value_t index_val = ecma_op_object_get (function_p, str_index_p); - ecma_value_t values_array = ecma_op_object_get (function_p, str_value_p); - ecma_value_t capability = ecma_op_object_get (function_p, str_capability_p); - ecma_value_t remaining = ecma_op_object_get (function_p, str_remaining_p); - - JERRY_ASSERT (ecma_is_value_integer_number (index_val)); - - /* 8. */ - ecma_op_object_put_by_uint32_index (ecma_get_object_from_value (values_array), - (uint32_t) ecma_get_integer_from_value (index_val), - argv[0], - false); - - /* 9-10. */ - ecma_value_t ret = ECMA_VALUE_UNDEFINED; - if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0) - { - ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (capability), - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - ret = ecma_op_function_call (ecma_get_object_from_value (resolve), - ECMA_VALUE_UNDEFINED, - &values_array, - 1); - ecma_free_value (resolve); - } - - ecma_free_value (remaining); - ecma_free_value (capability); - ecma_free_value (values_array); - ecma_free_value (index_val); - - return ret; -} /* ecma_builtin_promise_all_handler */ - /** * Runtime Semantics: PerformPromiseAll. * @@ -323,12 +207,15 @@ ecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function inline static ecma_value_t ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ ecma_value_t next_method, /**< next method */ - ecma_value_t capability, /**< PromiseCapability record */ + ecma_object_t *capability_obj_p, /**< PromiseCapability record */ ecma_value_t ctor, /**< the caller of Promise.race */ bool *done_p) /**< [out] iteratorRecord[[done]] */ { /* 1. - 2. */ - JERRY_ASSERT (ecma_is_value_object (capability) && ecma_is_constructor (ctor)); + 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; /* 3. */ ecma_object_t *values_array_obj_p = ecma_op_new_fast_array_object (0); @@ -339,14 +226,6 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ uint32_t idx = 0; ecma_value_t ret_value = ECMA_VALUE_ERROR; - ecma_object_t *capability_obj_p = ecma_get_object_from_value (capability); - - ecma_string_t *already_called_str_p; - already_called_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_ALREADY_CALLED); - ecma_string_t *index_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX); - ecma_string_t *value_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE); - ecma_string_t *capability_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); - ecma_string_t *remaining_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT); /* 6. */ while (true) @@ -367,17 +246,13 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ *done_p = true; /* ii. - iii. */ - if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0) + if (ecma_promise_remaining_inc_or_dec (remaining, false) == 0) { /* 2. */ - ecma_value_t resolve = ecma_op_object_get_by_magic_id (capability_obj_p, - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - ecma_value_t resolve_result = ecma_op_function_call (ecma_get_object_from_value (resolve), + ecma_value_t resolve_result = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), ECMA_VALUE_UNDEFINED, &values_array, 1); - ecma_free_value (resolve); - /* 3. */ if (ECMA_IS_VALUE_ERROR (resolve_result)) { @@ -388,8 +263,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ } /* iv. */ - ret_value = ecma_op_object_get_by_magic_id (capability_obj_p, - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); + ret_value = ecma_copy_value (capability_p->header.u.class_prop.u.promise); break; } @@ -421,52 +295,43 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ } /* k. */ - ecma_object_t *res_ele_p; - res_ele_p = ecma_op_create_external_function_object (ecma_builtin_promise_all_handler); + ecma_object_t *executor_func_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), + sizeof (ecma_promise_all_executor_t), + ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION); + + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) executor_func_p; + executor_p->header.u.external_handler_cb = ecma_promise_all_handler_cb; + /* l. */ - ecma_op_object_put (res_ele_p, - already_called_str_p, - ECMA_VALUE_FALSE, - false); - /* m. */ - ecma_value_t idx_value = ecma_make_uint32_value (idx); - ecma_op_object_put (res_ele_p, - index_str_p, - idx_value, - false); - ecma_free_value (idx_value); + if (JERRY_UNLIKELY (idx == UINT32_MAX - 1)) + { + ecma_deref_object (executor_func_p); + ecma_raise_range_error (ECMA_ERR_MSG ("Promise.all remaining elements limit reached.")); + break; + } + + /* m. + t. */ + executor_p->index = ++idx; /* n. */ - ecma_op_object_put (res_ele_p, - value_str_p, - values_array, - false); + executor_p->values = values_array; /* o. */ - ecma_op_object_put (res_ele_p, - capability_str_p, - capability, - false); + executor_p->capability = ecma_make_object_value (capability_obj_p); + /* p. */ - ecma_op_object_put (res_ele_p, - remaining_str_p, - remaining, - false); + executor_p->remaining_elements = remaining; /* q. */ - ecma_builtin_promise_remaining_inc_or_dec (remaining, true); + ecma_promise_remaining_inc_or_dec (remaining, true); /* r. */ ecma_value_t args[2]; - args[0] = ecma_make_object_value (res_ele_p); - args[1] = ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); + args[0] = ecma_make_object_value (executor_func_p); + args[1] = 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); - - for (uint8_t i = 0; i < 2; i++) - { - ecma_free_value (args[i]); - } + ecma_deref_object (executor_func_p); /* s. */ if (ECMA_IS_VALUE_ERROR (result)) @@ -475,13 +340,11 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ } ecma_free_value (result); - - /* t. */ - idx++; } ecma_free_value (remaining); ecma_deref_object (values_array_obj_p); + return ret_value; } /* ecma_builtin_promise_perform_all */ @@ -501,20 +364,20 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object.")); } - ecma_value_t capability = ecma_promise_new_capability (this_arg); + ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg); - if (ECMA_IS_VALUE_ERROR (capability)) + if (JERRY_UNLIKELY (capability_obj_p == NULL)) { - return capability; + return ECMA_VALUE_ERROR; } ecma_value_t next_method; ecma_value_t iterator = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method); - iterator = ecma_builtin_promise_reject_abrupt (iterator, capability); + iterator = ecma_builtin_promise_reject_abrupt (iterator, capability_obj_p); if (ECMA_IS_VALUE_ERROR (iterator)) { - ecma_free_value (capability); + ecma_deref_object (capability_obj_p); return iterator; } @@ -523,11 +386,11 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ if (is_race) { - ret = ecma_builtin_promise_perform_race (iterator, next_method, capability, this_arg, &is_done); + ret = ecma_builtin_promise_perform_race (iterator, next_method, capability_obj_p, this_arg, &is_done); } else { - ret = ecma_builtin_promise_perform_all (iterator, next_method, capability, this_arg, &is_done); + ret = ecma_builtin_promise_perform_all (iterator, next_method, capability_obj_p, this_arg, &is_done); } if (ECMA_IS_VALUE_ERROR (ret)) @@ -537,12 +400,12 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ ret = ecma_op_iterator_close (iterator); } - ret = ecma_builtin_promise_reject_abrupt (ret, capability); + ret = ecma_builtin_promise_reject_abrupt (ret, capability_obj_p); } ecma_free_value (iterator); ecma_free_value (next_method); - ecma_free_value (capability); + ecma_deref_object (capability_obj_p); return ret; } /* ecma_builtin_promise_race_or_all */ diff --git a/jerry-core/ecma/operations/ecma-jobqueue.c b/jerry-core/ecma/operations/ecma-jobqueue.c index 9036b7ea2..0b1f2153f 100644 --- a/jerry-core/ecma/operations/ecma-jobqueue.c +++ b/jerry-core/ecma/operations/ecma-jobqueue.c @@ -181,11 +181,11 @@ ecma_free_promise_resolve_thenable_job (ecma_job_promise_resolve_thenable_t *job static ecma_value_t ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the job to be operated */ { - ecma_string_t *resolve_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - ecma_string_t *reject_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); - /* 2. */ - ecma_value_t capability = job_p->capability; + JERRY_ASSERT (ecma_object_class_is (ecma_get_object_from_value (job_p->capability), + LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); + ecma_promise_capabality_t *capability_p; + capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (job_p->capability); /* 3. */ ecma_value_t handler = job_p->handler; @@ -217,28 +217,18 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the } /* 7. */ - ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), reject_str_p); - - JERRY_ASSERT (ecma_op_is_callable (reject)); - - status = ecma_op_function_call (ecma_get_object_from_value (reject), + status = ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &handler_result, 1); - ecma_free_value (reject); } else { /* 8. */ - ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), resolve_str_p); - - JERRY_ASSERT (ecma_op_is_callable (resolve)); - - status = ecma_op_function_call (ecma_get_object_from_value (resolve), + status = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), ECMA_VALUE_UNDEFINED, &handler_result, 1); - ecma_free_value (resolve); } ecma_free_value (handler_result); diff --git a/jerry-core/ecma/operations/ecma-promise-object.c b/jerry-core/ecma/operations/ecma-promise-object.c index 518747cba..623c60014 100644 --- a/jerry-core/ecma/operations/ecma-promise-object.c +++ b/jerry-core/ecma/operations/ecma-promise-object.c @@ -13,6 +13,8 @@ * limitations under the License. */ +#include "ecma-alloc.h" +#include "ecma-array-object.h" #include "ecma-boolean-object.h" #include "ecma-builtins.h" #include "ecma-exceptions.h" @@ -361,63 +363,6 @@ ecma_promise_resolve_handler (const ecma_value_t function, /**< the function its return ECMA_VALUE_UNDEFINED; } /* ecma_promise_resolve_handler */ -/** - * CapabilitiesExecutor Function. - * - * See also: ES2015 25.4.1.5.1 - * - * @return ecma value of undefined or typerror. - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t -ecma_call_builtin_executor (ecma_object_t *executor_p, /**< the executor object */ - ecma_value_t resolve_func, /**< the resolve function */ - ecma_value_t reject_func) /**< the reject function */ -{ - ecma_string_t *capability_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); - ecma_string_t *resolve_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - ecma_string_t *reject_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); - - /* 2. */ - ecma_value_t capability = ecma_op_object_get (executor_p, capability_str_p); - /* 3. */ - ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), resolve_str_p); - - if (resolve != ECMA_VALUE_UNDEFINED) - { - ecma_free_value (resolve); - ecma_free_value (capability); - - return ecma_raise_type_error (ECMA_ERR_MSG ("'resolve' function should be undefined.")); - } - - /* 4. */ - ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), reject_str_p); - - if (reject != ECMA_VALUE_UNDEFINED) - { - ecma_free_value (reject); - ecma_free_value (capability); - - return ecma_raise_type_error (ECMA_ERR_MSG ("'reject' function should be undefined.")); - } - - /* 5. */ - ecma_op_object_put (ecma_get_object_from_value (capability), - resolve_str_p, - resolve_func, - false); - /* 6. */ - ecma_op_object_put (ecma_get_object_from_value (capability), - reject_str_p, - reject_func, - false); - - ecma_free_value (capability); - - return ECMA_VALUE_UNDEFINED; -} /* ecma_call_builtin_executor */ - /** * Helper function for PromiseCreateResovingFucntions. * @@ -561,14 +506,6 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function argv, 2); } - else if (type == ECMA_PROMISE_EXECUTOR_OBJECT) - { - JERRY_ASSERT (ecma_is_value_object (executor)); - - completion = ecma_call_builtin_executor (ecma_get_object_from_value (executor), - funcs.resolve, - funcs.reject); - } else { JERRY_ASSERT (type == ECMA_PROMISE_EXECUTOR_EMPTY); @@ -603,6 +540,86 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function return ecma_make_object_value (object_p); } /* ecma_op_create_promise_object */ +/** + * Helper function for increase or decrease the remaining count. + * + * @return the current remaining count after increase or decrease. + */ +ecma_length_t +ecma_promise_remaining_inc_or_dec (ecma_value_t remaining, /**< the remaining count */ + bool is_inc) /**< whether to increase the count */ +{ + JERRY_ASSERT (ecma_is_value_object (remaining)); + + ecma_object_t *remaining_p = ecma_get_object_from_value (remaining); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) remaining_p; + + JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_NUMBER_UL); + + JERRY_ASSERT (ecma_is_value_integer_number (ext_object_p->u.class_prop.u.value)); + + ecma_length_t current = (ecma_length_t) ecma_get_integer_from_value (ext_object_p->u.class_prop.u.value); + + if (is_inc) + { + current++; + } + else + { + current--; + } + ext_object_p->u.class_prop.u.value = ecma_make_uint32_value (current); + + return current; +} /* ecma_promise_remaining_inc_or_dec */ + +/** + * Native handler for Promise.all Resolve Element Function. + * + * See also: + * ES2015 25.4.4.1.2 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_promise_all_handler_cb (const ecma_value_t function_obj, /**< the function itself */ + const ecma_value_t this_val, /**< this_arg of the function */ + const ecma_value_t args_p[], /**< argument list */ + const ecma_length_t args_count) /**< argument number */ +{ + JERRY_UNUSED (this_val); + JERRY_UNUSED (args_count); + ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) ecma_get_object_from_value (function_obj); + + /* 1 - 2. */ + if (executor_p->index == 0) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 8. */ + ecma_op_object_put_by_uint32_index (ecma_get_object_from_value (executor_p->values), + (uint32_t) (executor_p->index - 1), + args_p[0], + false); + /* 3. */ + executor_p->index = 0; + + /* 9-10. */ + ecma_value_t ret = ECMA_VALUE_UNDEFINED; + if (ecma_promise_remaining_inc_or_dec (executor_p->remaining_elements, false) == 0) + { + ecma_value_t capability = executor_p->capability; + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (capability); + ret = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &executor_p->values, + 1); + } + + return ret; +} /* ecma_promise_all_handler_cb */ + /** * 25.4.1.5.1 GetCapabilitiesExecutor Functions * @@ -611,58 +628,39 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function * @return ECMA_VALUE_UNDEFINED or TypeError * returned value must be freed with ecma_free_value */ -static ecma_value_t +ecma_value_t ecma_op_get_capabilities_executor_cb (const ecma_value_t function_obj, /**< the function itself */ const ecma_value_t this_val, /**< this_arg of the function */ const ecma_value_t args_p[], /**< argument list */ const ecma_length_t args_count) /**< argument number */ { JERRY_UNUSED (this_val); - /* 1. */ - ecma_value_t capability = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (function_obj), - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); - JERRY_ASSERT (ecma_is_value_object (capability)); + JERRY_ASSERT (args_count >= 2); + + ecma_promise_capability_executor_t *executor_p; + executor_p = (ecma_promise_capability_executor_t *) ecma_get_object_from_value (function_obj); /* 2. */ - ecma_object_t *capability_obj_p = ecma_get_object_from_value (capability); + ecma_object_t *capability_obj_p = ecma_get_object_from_value (executor_p->capability); + JERRY_ASSERT (ecma_object_class_is (capability_obj_p, LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; /* 3. */ - ecma_value_t resolve = ecma_op_object_get_by_magic_id (capability_obj_p, - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - - if (!ecma_is_value_undefined (resolve)) + if (!ecma_is_value_undefined (capability_p->resolve)) { - ecma_free_value (resolve); - ecma_deref_object (capability_obj_p); - return ecma_raise_type_error (ECMA_ERR_MSG ("Resolve must be undefined")); } /* 4. */ - ecma_value_t reject = ecma_op_object_get_by_magic_id (capability_obj_p, - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); - - if (!ecma_is_value_undefined (reject)) + if (!ecma_is_value_undefined (capability_p->reject)) { - ecma_free_value (reject); - ecma_deref_object (capability_obj_p); - return ecma_raise_type_error (ECMA_ERR_MSG ("Reject must be undefined")); } /* 5. */ - ecma_op_object_put (capability_obj_p, - ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE), - args_count > 0 ? args_p[0] : ECMA_VALUE_UNDEFINED, - false); - + capability_p->resolve = args_p[0]; /* 6. */ - ecma_op_object_put (capability_obj_p, - ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT), - args_count > 1 ? args_p[1] : ECMA_VALUE_UNDEFINED, - false); - - ecma_deref_object (capability_obj_p); + capability_p->reject = args_p[1]; /* 7. */ return ECMA_VALUE_UNDEFINED; @@ -673,34 +671,44 @@ ecma_op_get_capabilities_executor_cb (const ecma_value_t function_obj, /**< the * * See also: ES2015 25.4.1.5 * - * @return ecma value of the new PromiseCapability - * Returned value must be freed with ecma_free_value + * @return NULL - if the operation raises error + * new PromiseCapability object - otherwise */ -ecma_value_t +ecma_object_t * ecma_promise_new_capability (ecma_value_t constructor) { /* 1. */ if (!ecma_is_constructor (constructor)) { - return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid capability")); + ecma_raise_type_error (ECMA_ERR_MSG ("Invalid capability")); + return NULL; } ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); - /* 3. */ - ecma_object_t *capability_p = ecma_op_create_object_object_noarg (); - ecma_string_t *capability_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); - ecma_string_t *promise_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); + /* 3. */ + ecma_object_t *capability_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), + sizeof (ecma_promise_capabality_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; + capability_p->header.u.class_prop.class_id = LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY; + capability_p->header.u.class_prop.u.promise = ECMA_VALUE_UNDEFINED; + capability_p->resolve = ECMA_VALUE_UNDEFINED; + capability_p->reject = ECMA_VALUE_UNDEFINED; + /* 4. */ - ecma_object_t *executor_p = ecma_op_create_external_function_object (ecma_op_get_capabilities_executor_cb); - ecma_value_t executor = ecma_make_object_value (executor_p); + ecma_object_t *executor_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), + sizeof (ecma_promise_capability_executor_t), + ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION); + /* 5. */ - ecma_op_object_put (executor_p, - capability_str_p, - ecma_make_object_value (capability_p), - false); + ecma_promise_capability_executor_t *executor_func_p = (ecma_promise_capability_executor_t *) executor_p; + executor_func_p->header.u.external_handler_cb = ecma_op_get_capabilities_executor_cb; + executor_func_p->capability = ecma_make_object_value (capability_obj_p); /* 6. */ + ecma_value_t executor = ecma_make_object_value (executor_p); ecma_value_t promise = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &executor, @@ -710,44 +718,35 @@ ecma_promise_new_capability (ecma_value_t constructor) /* 7. */ if (ECMA_IS_VALUE_ERROR (promise)) { - ecma_deref_object (capability_p); - return promise; + ecma_deref_object (capability_obj_p); + return NULL; + } + + /* 8. */ + if (!ecma_op_is_callable (capability_p->resolve)) + { + ecma_free_value (promise); + ecma_deref_object (capability_obj_p); + ecma_raise_type_error (ECMA_ERR_MSG ("'resolve' parameter must be callable.")); + return NULL; + } + + /* 9. */ + if (!ecma_op_is_callable (capability_p->reject)) + { + ecma_free_value (promise); + ecma_deref_object (capability_obj_p); + ecma_raise_type_error (ECMA_ERR_MSG ("'reject' parameter must be callable.")); + return NULL; } /* 10. */ - ecma_op_object_put (capability_p, - promise_str_p, - promise, - false); + capability_p->header.u.class_prop.u.promise = promise; ecma_free_value (promise); - /* 8. */ - ecma_string_t *resolve_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - ecma_value_t resolve = ecma_op_object_get (capability_p, resolve_str_p); - - if (!ecma_op_is_callable (resolve)) - { - ecma_free_value (resolve); - ecma_deref_object (capability_p); - return ecma_raise_type_error (ECMA_ERR_MSG ("'resolve' parameter must be callable.")); - } - - ecma_free_value (resolve); - /* 9. */ - ecma_string_t *reject_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); - ecma_value_t reject = ecma_op_object_get (capability_p, reject_str_p); - - if (!ecma_op_is_callable (reject)) - { - ecma_free_value (reject); - ecma_deref_object (capability_p); - return ecma_raise_type_error (ECMA_ERR_MSG ("'reject' parameter must be callable.")); - } - - ecma_free_value (reject); /* 11. */ - return ecma_make_object_value (capability_p); + return capability_obj_p; } /* ecma_promise_new_capability */ /** @@ -788,33 +787,22 @@ ecma_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ } } - ecma_value_t capability = ecma_promise_new_capability (this_arg); + ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg); - if (ECMA_IS_VALUE_ERROR (capability)) + if (JERRY_UNLIKELY (capability_obj_p == NULL)) { - return capability; + return ECMA_VALUE_ERROR; } - ecma_string_t *property_str_p; + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; - if (is_resolve) - { - property_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); - } - else - { - property_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); - } - - ecma_value_t func = ecma_op_object_get (ecma_get_object_from_value (capability), property_str_p); + ecma_value_t func = is_resolve ? capability_p->resolve : capability_p->reject; ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func), ECMA_VALUE_UNDEFINED, &value, 1); - ecma_free_value (func); - if (ECMA_IS_VALUE_ERROR (call_ret)) { return call_ret; @@ -822,9 +810,8 @@ ecma_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ ecma_free_value (call_ret); - ecma_string_t *promise_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); - ecma_value_t promise = ecma_op_object_get (ecma_get_object_from_value (capability), promise_str_p); - ecma_free_value (capability); + ecma_value_t promise = ecma_copy_value (capability_p->header.u.class_prop.u.promise); + ecma_deref_object (capability_obj_p); return promise; } /* ecma_promise_reject_or_resolve */ @@ -842,9 +829,11 @@ static ecma_value_t ecma_promise_do_then (ecma_value_t promise, /**< the promise which call 'then' */ ecma_value_t on_fulfilled, /**< on_fulfilled function */ ecma_value_t on_rejected, /**< on_rejected function */ - ecma_value_t result_capability) /**< promise capability */ + ecma_object_t *result_capability_obj_p) /**< promise capability */ { - ecma_string_t *promise_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); + JERRY_ASSERT (ecma_object_class_is (result_capability_obj_p, LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY)); + + ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) result_capability_obj_p; /* 3. boolean true indicates "indentity" */ if (!ecma_op_is_callable (on_fulfilled)) @@ -867,7 +856,7 @@ ecma_promise_do_then (ecma_value_t promise, /**< the promise which call 'then' * { /* 7. */ ecma_value_t capability_with_tag; - ECMA_SET_NON_NULL_POINTER_TAG (capability_with_tag, ecma_get_object_from_value (result_capability), 0); + ECMA_SET_NON_NULL_POINTER_TAG (capability_with_tag, result_capability_obj_p, 0); if (on_fulfilled != ECMA_VALUE_TRUE) { @@ -895,19 +884,19 @@ ecma_promise_do_then (ecma_value_t promise, /**< the promise which call 'then' * { /* 8. */ ecma_value_t value = ecma_promise_get_result (promise_obj_p); - ecma_enqueue_promise_reaction_job (result_capability, on_fulfilled, value); + ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_fulfilled, value); ecma_free_value (value); } else { /* 9. */ ecma_value_t reason = ecma_promise_get_result (promise_obj_p); - ecma_enqueue_promise_reaction_job (result_capability, on_rejected, reason); + ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_rejected, reason); ecma_free_value (reason); } /* 10. */ - return ecma_op_object_get (ecma_get_object_from_value (result_capability), promise_str_p); + return ecma_copy_value (capability_p->header.u.class_prop.u.promise); } /* ecma_promise_do_then */ /** @@ -940,16 +929,16 @@ ecma_promise_then (ecma_value_t promise, /**< the promise which call 'then' */ return species; } - ecma_value_t result_capability = ecma_promise_new_capability (species); + ecma_object_t *result_capability_obj_p = ecma_promise_new_capability (species); ecma_free_value (species); - if (ECMA_IS_VALUE_ERROR (result_capability)) + if (JERRY_UNLIKELY (result_capability_obj_p == NULL)) { - return result_capability; + return ECMA_VALUE_ERROR; } - ecma_value_t ret = ecma_promise_do_then (promise, on_fulfilled, on_rejected, result_capability); - ecma_free_value (result_capability); + ecma_value_t ret = ecma_promise_do_then (promise, on_fulfilled, on_rejected, result_capability_obj_p); + ecma_deref_object (result_capability_obj_p); return ret; } /* ecma_promise_then */ diff --git a/jerry-core/ecma/operations/ecma-promise-object.h b/jerry-core/ecma/operations/ecma-promise-object.h index a32ef6502..22640bbef 100644 --- a/jerry-core/ecma/operations/ecma-promise-object.h +++ b/jerry-core/ecma/operations/ecma-promise-object.h @@ -42,7 +42,6 @@ typedef enum typedef enum { ECMA_PROMISE_EXECUTOR_FUNCTION, /**< the executor is a function, it is for the usual constructor */ - ECMA_PROMISE_EXECUTOR_OBJECT, /**< the executor is an object, it is for the `then` routine */ ECMA_PROMISE_EXECUTOR_EMPTY /**< the executor is empty, it is for external C API */ } ecma_promise_executor_type_t; @@ -88,7 +87,7 @@ uint16_t ecma_promise_get_flags (ecma_object_t *promise_p); ecma_value_t ecma_promise_get_result (ecma_object_t *promise_p); void ecma_reject_promise (ecma_value_t promise, ecma_value_t reason); void ecma_fulfill_promise (ecma_value_t promise, ecma_value_t value); -ecma_value_t ecma_promise_new_capability (ecma_value_t constructor); +ecma_object_t *ecma_promise_new_capability (ecma_value_t constructor); ecma_value_t ecma_promise_reject_or_resolve (ecma_value_t this_arg, ecma_value_t value, bool is_resolve); ecma_value_t ecma_promise_then (ecma_value_t promise, ecma_value_t on_fulfilled, ecma_value_t on_rejected); void ecma_promise_async_then (ecma_value_t promise, ecma_value_t executable_object); @@ -97,6 +96,13 @@ void ecma_promise_create_resolving_functions (ecma_object_t *object_p, ecma_prom bool create_already_resolved); void ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs); +ecma_length_t ecma_promise_remaining_inc_or_dec (ecma_value_t remaining, bool is_inc); +ecma_value_t ecma_promise_all_handler_cb (const ecma_value_t function_obj, const ecma_value_t this_val, + const ecma_value_t args_p[], const ecma_length_t args_count); + +ecma_value_t ecma_op_get_capabilities_executor_cb (const ecma_value_t function_obj, const ecma_value_t this_val, + const ecma_value_t args_p[], const ecma_length_t args_count); + /** * @} * @} diff --git a/jerry-core/lit/lit-magic-strings.h b/jerry-core/lit/lit-magic-strings.h index 24a65724c..a38286b33 100644 --- a/jerry-core/lit/lit-magic-strings.h +++ b/jerry-core/lit/lit-magic-strings.h @@ -37,20 +37,13 @@ typedef enum LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED, /**< [[AlreadyResolved]] of promise reject or resolve functions */ LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION, /**< the resolve funtion of the promise object */ LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION, /**< the reject function of the promise object */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE, /**< [[Promise]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE, /**< [[Resolve]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT, /**< [[Reject]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY, /**< [[Capability]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_ALREADY_CALLED, /**< [[AlreadyCalled]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX, /**< [[Index]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE, /**< [[Values]] property */ - LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT, /**< [[RemainingElement]] property */ LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX, /**< [[%Iterator%NextIndex]] property */ LIT_INTERNAL_MAGIC_STRING_MAP_KEY, /**< Property key used when an object is a key in a map object */ LIT_INTERNAL_MAGIC_API_INTERNAL, /**< Property key used to add non-visible JS properties from the public API */ LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, /**< %ArrayProto_values% intrinsic routine */ LIT_INTERNAL_MAGIC_STRING_SET_PROTOTYPE_KEYS, /**< Set.prototype values, keys and [@@iterator] routines */ LIT_INTERNAL_MAGIC_THIS_BINDING_VALUE, /**< FunctionEnvironmentRecord [[ThisBindingValue]] internal slot */ + LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY, /**< PromiseCapability record */ /* List of well known symbols */ LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known symbol */ LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */