1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "ecma-array-object.h" 17425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h" 18425bb815Sopenharmony_ci#include "ecma-exceptions.h" 19425bb815Sopenharmony_ci#include "ecma-function-object.h" 20425bb815Sopenharmony_ci#include "ecma-gc.h" 21425bb815Sopenharmony_ci#include "ecma-globals.h" 22425bb815Sopenharmony_ci#include "ecma-iterator-object.h" 23425bb815Sopenharmony_ci#include "ecma-number-object.h" 24425bb815Sopenharmony_ci#include "ecma-promise-object.h" 25425bb815Sopenharmony_ci#include "jcontext.h" 26425bb815Sopenharmony_ci 27425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROMISE) 28425bb815Sopenharmony_ci 29425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL 30425bb815Sopenharmony_ci#include "ecma-builtins-internal.h" 31425bb815Sopenharmony_ci 32425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise.inc.h" 33425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID promise 34425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h" 35425bb815Sopenharmony_ci 36425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 37425bb815Sopenharmony_ci * @{ 38425bb815Sopenharmony_ci * 39425bb815Sopenharmony_ci * \addtogroup ecmabuiltins 40425bb815Sopenharmony_ci * @{ 41425bb815Sopenharmony_ci * 42425bb815Sopenharmony_ci * \addtogroup promise ECMA Promise object built-in 43425bb815Sopenharmony_ci * @{ 44425bb815Sopenharmony_ci */ 45425bb815Sopenharmony_ci 46425bb815Sopenharmony_ci/** 47425bb815Sopenharmony_ci * Reject the promise if the value is error. 48425bb815Sopenharmony_ci * 49425bb815Sopenharmony_ci * See also: 50425bb815Sopenharmony_ci * ES2015 25.4.1.1.1 51425bb815Sopenharmony_ci * 52425bb815Sopenharmony_ci * @return ecma value of the new promise. 53425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 54425bb815Sopenharmony_ci */ 55425bb815Sopenharmony_ciinline static ecma_value_t 56425bb815Sopenharmony_ciecma_builtin_promise_reject_abrupt (ecma_value_t value, /**< value */ 57425bb815Sopenharmony_ci ecma_value_t capability) /**< capability */ 58425bb815Sopenharmony_ci{ 59425bb815Sopenharmony_ci if (!ECMA_IS_VALUE_ERROR (value)) 60425bb815Sopenharmony_ci { 61425bb815Sopenharmony_ci return value; 62425bb815Sopenharmony_ci } 63425bb815Sopenharmony_ci 64425bb815Sopenharmony_ci ecma_value_t reason = jcontext_take_exception (); 65425bb815Sopenharmony_ci ecma_value_t reject = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (capability), 66425bb815Sopenharmony_ci LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); 67425bb815Sopenharmony_ci 68425bb815Sopenharmony_ci ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (reject), 69425bb815Sopenharmony_ci ECMA_VALUE_UNDEFINED, 70425bb815Sopenharmony_ci &reason, 71425bb815Sopenharmony_ci 1); 72425bb815Sopenharmony_ci ecma_free_value (reject); 73425bb815Sopenharmony_ci ecma_free_value (reason); 74425bb815Sopenharmony_ci 75425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (call_ret)) 76425bb815Sopenharmony_ci { 77425bb815Sopenharmony_ci return call_ret; 78425bb815Sopenharmony_ci } 79425bb815Sopenharmony_ci 80425bb815Sopenharmony_ci ecma_free_value (call_ret); 81425bb815Sopenharmony_ci 82425bb815Sopenharmony_ci return ecma_op_object_get_by_magic_id (ecma_get_object_from_value (capability), 83425bb815Sopenharmony_ci LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); 84425bb815Sopenharmony_ci} /* ecma_builtin_promise_reject_abrupt */ 85425bb815Sopenharmony_ci 86425bb815Sopenharmony_ci/** 87425bb815Sopenharmony_ci * The Promise.reject routine. 88425bb815Sopenharmony_ci * 89425bb815Sopenharmony_ci * See also: 90425bb815Sopenharmony_ci * ES2015 25.4.4.4 91425bb815Sopenharmony_ci * 92425bb815Sopenharmony_ci * @return ecma value of the new promise. 93425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 94425bb815Sopenharmony_ci */ 95425bb815Sopenharmony_cistatic ecma_value_t 96425bb815Sopenharmony_ciecma_builtin_promise_reject (ecma_value_t this_arg, /**< 'this' argument */ 97425bb815Sopenharmony_ci ecma_value_t reason) /**< the reason for reject */ 98425bb815Sopenharmony_ci{ 99425bb815Sopenharmony_ci return ecma_promise_reject_or_resolve (this_arg, reason, false); 100425bb815Sopenharmony_ci} /* ecma_builtin_promise_reject */ 101425bb815Sopenharmony_ci 102425bb815Sopenharmony_ci/** 103425bb815Sopenharmony_ci * The Promise.resolve routine. 104425bb815Sopenharmony_ci * 105425bb815Sopenharmony_ci * See also: 106425bb815Sopenharmony_ci * ES2015 25.4.4.5 107425bb815Sopenharmony_ci * 108425bb815Sopenharmony_ci * @return ecma value of the new promise. 109425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 110425bb815Sopenharmony_ci */ 111425bb815Sopenharmony_cistatic ecma_value_t 112425bb815Sopenharmony_ciecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */ 113425bb815Sopenharmony_ci ecma_value_t argument) /**< the argument for resolve */ 114425bb815Sopenharmony_ci{ 115425bb815Sopenharmony_ci return ecma_promise_reject_or_resolve (this_arg, argument, true); 116425bb815Sopenharmony_ci} /* ecma_builtin_promise_resolve */ 117425bb815Sopenharmony_ci 118425bb815Sopenharmony_ci/** 119425bb815Sopenharmony_ci * Runtime Semantics: PerformPromiseRace. 120425bb815Sopenharmony_ci * 121425bb815Sopenharmony_ci * See also: 122425bb815Sopenharmony_ci * ES2015 25.4.4.3.1 123425bb815Sopenharmony_ci * 124425bb815Sopenharmony_ci * @return ecma value of the new promise. 125425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 126425bb815Sopenharmony_ci */ 127425bb815Sopenharmony_ciinline static ecma_value_t 128425bb815Sopenharmony_ciecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for race */ 129425bb815Sopenharmony_ci ecma_value_t capability, /**< PromiseCapability record */ 130425bb815Sopenharmony_ci ecma_value_t ctor, /**< Constructor value */ 131425bb815Sopenharmony_ci bool *done_p) /**< [out] iteratorRecord[[done]] */ 132425bb815Sopenharmony_ci{ 133425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_object (iterator) 134425bb815Sopenharmony_ci && ecma_is_value_object (capability)); 135425bb815Sopenharmony_ci 136425bb815Sopenharmony_ci ecma_object_t *capability_obj_p = ecma_get_object_from_value (capability); 137425bb815Sopenharmony_ci /* 1. */ 138425bb815Sopenharmony_ci while (true) 139425bb815Sopenharmony_ci { 140425bb815Sopenharmony_ci /* a. */ 141425bb815Sopenharmony_ci ecma_value_t next = ecma_op_iterator_step (iterator); 142425bb815Sopenharmony_ci /* b, c. */ 143425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (next)) 144425bb815Sopenharmony_ci { 145425bb815Sopenharmony_ci *done_p = true; 146425bb815Sopenharmony_ci return next; 147425bb815Sopenharmony_ci } 148425bb815Sopenharmony_ci 149425bb815Sopenharmony_ci /* d. */ 150425bb815Sopenharmony_ci if (ecma_is_value_false (next)) 151425bb815Sopenharmony_ci { 152425bb815Sopenharmony_ci /* i. */ 153425bb815Sopenharmony_ci *done_p = true; 154425bb815Sopenharmony_ci /* ii. */ 155425bb815Sopenharmony_ci return ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); 156425bb815Sopenharmony_ci } 157425bb815Sopenharmony_ci 158425bb815Sopenharmony_ci /* e. */ 159425bb815Sopenharmony_ci ecma_value_t next_val = ecma_op_iterator_value (next); 160425bb815Sopenharmony_ci ecma_free_value (next); 161425bb815Sopenharmony_ci 162425bb815Sopenharmony_ci /* f, g. */ 163425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (next_val)) 164425bb815Sopenharmony_ci { 165425bb815Sopenharmony_ci *done_p = true; 166425bb815Sopenharmony_ci return next_val; 167425bb815Sopenharmony_ci } 168425bb815Sopenharmony_ci 169425bb815Sopenharmony_ci /* h. */ 170425bb815Sopenharmony_ci ecma_value_t next_promise = ecma_op_invoke_by_magic_id (ctor, LIT_MAGIC_STRING_RESOLVE, &next_val, 1); 171425bb815Sopenharmony_ci ecma_free_value (next_val); 172425bb815Sopenharmony_ci 173425bb815Sopenharmony_ci /* i. */ 174425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (next_promise)) 175425bb815Sopenharmony_ci { 176425bb815Sopenharmony_ci return next_promise; 177425bb815Sopenharmony_ci } 178425bb815Sopenharmony_ci 179425bb815Sopenharmony_ci /* j. */ 180425bb815Sopenharmony_ci ecma_value_t args[2]; 181425bb815Sopenharmony_ci args[0] = ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); 182425bb815Sopenharmony_ci args[1] = ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); 183425bb815Sopenharmony_ci ecma_value_t result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); 184425bb815Sopenharmony_ci ecma_free_value (next_promise); 185425bb815Sopenharmony_ci 186425bb815Sopenharmony_ci for (uint8_t i = 0; i < 2; i++) 187425bb815Sopenharmony_ci { 188425bb815Sopenharmony_ci ecma_free_value (args[i]); 189425bb815Sopenharmony_ci } 190425bb815Sopenharmony_ci 191425bb815Sopenharmony_ci /* k. */ 192425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 193425bb815Sopenharmony_ci { 194425bb815Sopenharmony_ci return result; 195425bb815Sopenharmony_ci } 196425bb815Sopenharmony_ci 197425bb815Sopenharmony_ci ecma_free_value (result); 198425bb815Sopenharmony_ci } 199425bb815Sopenharmony_ci 200425bb815Sopenharmony_ci JERRY_UNREACHABLE (); 201425bb815Sopenharmony_ci} /* ecma_builtin_promise_perform_race */ 202425bb815Sopenharmony_ci 203425bb815Sopenharmony_ci/** 204425bb815Sopenharmony_ci * Helper function for increase or decrease the remaining count. 205425bb815Sopenharmony_ci * 206425bb815Sopenharmony_ci * @return the current remaining count after increase or decrease. 207425bb815Sopenharmony_ci */ 208425bb815Sopenharmony_cistatic ecma_length_t 209425bb815Sopenharmony_ciecma_builtin_promise_remaining_inc_or_dec (ecma_value_t remaining, /**< the remaining count */ 210425bb815Sopenharmony_ci bool is_inc) /**< whether to increase the count */ 211425bb815Sopenharmony_ci{ 212425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_object (remaining)); 213425bb815Sopenharmony_ci 214425bb815Sopenharmony_ci ecma_object_t *remaining_p = ecma_get_object_from_value (remaining); 215425bb815Sopenharmony_ci ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) remaining_p; 216425bb815Sopenharmony_ci 217425bb815Sopenharmony_ci JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_NUMBER_UL); 218425bb815Sopenharmony_ci 219425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_integer_number (ext_object_p->u.class_prop.u.value)); 220425bb815Sopenharmony_ci 221425bb815Sopenharmony_ci ecma_length_t current = (ecma_length_t) ecma_get_integer_from_value (ext_object_p->u.class_prop.u.value); 222425bb815Sopenharmony_ci 223425bb815Sopenharmony_ci if (is_inc) 224425bb815Sopenharmony_ci { 225425bb815Sopenharmony_ci current++; 226425bb815Sopenharmony_ci } 227425bb815Sopenharmony_ci else 228425bb815Sopenharmony_ci { 229425bb815Sopenharmony_ci current--; 230425bb815Sopenharmony_ci } 231425bb815Sopenharmony_ci ext_object_p->u.class_prop.u.value = ecma_make_uint32_value (current); 232425bb815Sopenharmony_ci 233425bb815Sopenharmony_ci return current; 234425bb815Sopenharmony_ci} /* ecma_builtin_promise_remaining_inc_or_dec */ 235425bb815Sopenharmony_ci 236425bb815Sopenharmony_ci/** 237425bb815Sopenharmony_ci * Native handler for Promise.all Resolve Element Function. 238425bb815Sopenharmony_ci * 239425bb815Sopenharmony_ci * See also: 240425bb815Sopenharmony_ci * ES2015 25.4.4.1.2 241425bb815Sopenharmony_ci * 242425bb815Sopenharmony_ci * @return ecma value of undefined. 243425bb815Sopenharmony_ci */ 244425bb815Sopenharmony_cistatic ecma_value_t 245425bb815Sopenharmony_ciecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function itself */ 246425bb815Sopenharmony_ci const ecma_value_t this, /**< this_arg of the function */ 247425bb815Sopenharmony_ci const ecma_value_t argv[], /**< argument list */ 248425bb815Sopenharmony_ci const ecma_length_t argc) /**< argument number */ 249425bb815Sopenharmony_ci{ 250425bb815Sopenharmony_ci JERRY_UNUSED (this); 251425bb815Sopenharmony_ci JERRY_UNUSED (argc); 252425bb815Sopenharmony_ci 253425bb815Sopenharmony_ci /* 1. */ 254425bb815Sopenharmony_ci ecma_object_t *function_p = ecma_get_object_from_value (function); 255425bb815Sopenharmony_ci ecma_string_t *already_called_str_p; 256425bb815Sopenharmony_ci already_called_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_ALREADY_CALLED); 257425bb815Sopenharmony_ci ecma_value_t already_called = ecma_op_object_get (function_p, already_called_str_p); 258425bb815Sopenharmony_ci 259425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_boolean (already_called)); 260425bb815Sopenharmony_ci 261425bb815Sopenharmony_ci /* 2. */ 262425bb815Sopenharmony_ci if (ecma_is_value_true (already_called)) 263425bb815Sopenharmony_ci { 264425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 265425bb815Sopenharmony_ci } 266425bb815Sopenharmony_ci 267425bb815Sopenharmony_ci /* 3. */ 268425bb815Sopenharmony_ci ecma_op_object_put (function_p, 269425bb815Sopenharmony_ci already_called_str_p, 270425bb815Sopenharmony_ci ECMA_VALUE_TRUE, 271425bb815Sopenharmony_ci false); 272425bb815Sopenharmony_ci 273425bb815Sopenharmony_ci ecma_string_t *str_index_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX); 274425bb815Sopenharmony_ci ecma_string_t *str_value_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE); 275425bb815Sopenharmony_ci ecma_string_t *str_capability_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); 276425bb815Sopenharmony_ci ecma_string_t *str_remaining_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT); 277425bb815Sopenharmony_ci 278425bb815Sopenharmony_ci /* 4-7. */ 279425bb815Sopenharmony_ci ecma_value_t index_val = ecma_op_object_get (function_p, str_index_p); 280425bb815Sopenharmony_ci ecma_value_t values_array = ecma_op_object_get (function_p, str_value_p); 281425bb815Sopenharmony_ci ecma_value_t capability = ecma_op_object_get (function_p, str_capability_p); 282425bb815Sopenharmony_ci ecma_value_t remaining = ecma_op_object_get (function_p, str_remaining_p); 283425bb815Sopenharmony_ci 284425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_integer_number (index_val)); 285425bb815Sopenharmony_ci 286425bb815Sopenharmony_ci /* 8. */ 287425bb815Sopenharmony_ci ecma_op_object_put_by_uint32_index (ecma_get_object_from_value (values_array), 288425bb815Sopenharmony_ci (uint32_t) ecma_get_integer_from_value (index_val), 289425bb815Sopenharmony_ci argv[0], 290425bb815Sopenharmony_ci false); 291425bb815Sopenharmony_ci 292425bb815Sopenharmony_ci /* 9-10. */ 293425bb815Sopenharmony_ci ecma_value_t ret = ECMA_VALUE_UNDEFINED; 294425bb815Sopenharmony_ci if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0) 295425bb815Sopenharmony_ci { 296425bb815Sopenharmony_ci ecma_value_t resolve = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (capability), 297425bb815Sopenharmony_ci LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); 298425bb815Sopenharmony_ci ret = ecma_op_function_call (ecma_get_object_from_value (resolve), 299425bb815Sopenharmony_ci ECMA_VALUE_UNDEFINED, 300425bb815Sopenharmony_ci &values_array, 301425bb815Sopenharmony_ci 1); 302425bb815Sopenharmony_ci ecma_free_value (resolve); 303425bb815Sopenharmony_ci } 304425bb815Sopenharmony_ci 305425bb815Sopenharmony_ci ecma_free_value (remaining); 306425bb815Sopenharmony_ci ecma_free_value (capability); 307425bb815Sopenharmony_ci ecma_free_value (values_array); 308425bb815Sopenharmony_ci ecma_free_value (index_val); 309425bb815Sopenharmony_ci 310425bb815Sopenharmony_ci return ret; 311425bb815Sopenharmony_ci} /* ecma_builtin_promise_all_handler */ 312425bb815Sopenharmony_ci 313425bb815Sopenharmony_ci/** 314425bb815Sopenharmony_ci * Runtime Semantics: PerformPromiseAll. 315425bb815Sopenharmony_ci * 316425bb815Sopenharmony_ci * See also: 317425bb815Sopenharmony_ci * ES2015 25.4.4.1.1 318425bb815Sopenharmony_ci * 319425bb815Sopenharmony_ci * @return ecma value of the new promise. 320425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 321425bb815Sopenharmony_ci */ 322425bb815Sopenharmony_ciinline static ecma_value_t 323425bb815Sopenharmony_ciecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ 324425bb815Sopenharmony_ci ecma_value_t ctor, /**< the caller of Promise.race */ 325425bb815Sopenharmony_ci ecma_value_t capability, /**< PromiseCapability record */ 326425bb815Sopenharmony_ci bool *done_p) /**< [out] iteratorRecord[[done]] */ 327425bb815Sopenharmony_ci{ 328425bb815Sopenharmony_ci /* 1. - 2. */ 329425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_object (capability) && ecma_is_constructor (ctor)); 330425bb815Sopenharmony_ci 331425bb815Sopenharmony_ci /* 3. */ 332425bb815Sopenharmony_ci ecma_object_t *values_array_obj_p = ecma_op_new_fast_array_object (0); 333425bb815Sopenharmony_ci ecma_value_t values_array = ecma_make_object_value (values_array_obj_p); 334425bb815Sopenharmony_ci /* 4. */ 335425bb815Sopenharmony_ci ecma_value_t remaining = ecma_op_create_number_object (ecma_make_integer_value (1)); 336425bb815Sopenharmony_ci /* 5. */ 337425bb815Sopenharmony_ci uint32_t idx = 0; 338425bb815Sopenharmony_ci 339425bb815Sopenharmony_ci ecma_value_t ret_value = ECMA_VALUE_ERROR; 340425bb815Sopenharmony_ci ecma_object_t *capability_obj_p = ecma_get_object_from_value (capability); 341425bb815Sopenharmony_ci 342425bb815Sopenharmony_ci ecma_string_t *already_called_str_p; 343425bb815Sopenharmony_ci already_called_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_ALREADY_CALLED); 344425bb815Sopenharmony_ci ecma_string_t *index_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX); 345425bb815Sopenharmony_ci ecma_string_t *value_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE); 346425bb815Sopenharmony_ci ecma_string_t *capability_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_CAPABILITY); 347425bb815Sopenharmony_ci ecma_string_t *remaining_str_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT); 348425bb815Sopenharmony_ci 349425bb815Sopenharmony_ci /* 6. */ 350425bb815Sopenharmony_ci while (true) 351425bb815Sopenharmony_ci { 352425bb815Sopenharmony_ci /* a. */ 353425bb815Sopenharmony_ci ecma_value_t next = ecma_op_iterator_step (iterator); 354425bb815Sopenharmony_ci /* b. - c. */ 355425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (next)) 356425bb815Sopenharmony_ci { 357425bb815Sopenharmony_ci *done_p = true; 358425bb815Sopenharmony_ci break; 359425bb815Sopenharmony_ci } 360425bb815Sopenharmony_ci 361425bb815Sopenharmony_ci /* d. */ 362425bb815Sopenharmony_ci if (ecma_is_value_false (next)) 363425bb815Sopenharmony_ci { 364425bb815Sopenharmony_ci /* i. */ 365425bb815Sopenharmony_ci *done_p = true; 366425bb815Sopenharmony_ci 367425bb815Sopenharmony_ci /* ii. - iii. */ 368425bb815Sopenharmony_ci if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0) 369425bb815Sopenharmony_ci { 370425bb815Sopenharmony_ci /* 2. */ 371425bb815Sopenharmony_ci ecma_value_t resolve = ecma_op_object_get_by_magic_id (capability_obj_p, 372425bb815Sopenharmony_ci LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_RESOLVE); 373425bb815Sopenharmony_ci ecma_value_t resolve_result = ecma_op_function_call (ecma_get_object_from_value (resolve), 374425bb815Sopenharmony_ci ECMA_VALUE_UNDEFINED, 375425bb815Sopenharmony_ci &values_array, 376425bb815Sopenharmony_ci 1); 377425bb815Sopenharmony_ci ecma_free_value (resolve); 378425bb815Sopenharmony_ci 379425bb815Sopenharmony_ci /* 3. */ 380425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (resolve_result)) 381425bb815Sopenharmony_ci { 382425bb815Sopenharmony_ci break; 383425bb815Sopenharmony_ci } 384425bb815Sopenharmony_ci 385425bb815Sopenharmony_ci ecma_free_value (resolve_result); 386425bb815Sopenharmony_ci } 387425bb815Sopenharmony_ci 388425bb815Sopenharmony_ci /* iv. */ 389425bb815Sopenharmony_ci ret_value = ecma_op_object_get_by_magic_id (capability_obj_p, 390425bb815Sopenharmony_ci LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_PROMISE); 391425bb815Sopenharmony_ci break; 392425bb815Sopenharmony_ci } 393425bb815Sopenharmony_ci 394425bb815Sopenharmony_ci /* e. */ 395425bb815Sopenharmony_ci ecma_value_t next_value = ecma_op_iterator_value (next); 396425bb815Sopenharmony_ci ecma_free_value (next); 397425bb815Sopenharmony_ci 398425bb815Sopenharmony_ci /* f. - g. */ 399425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (next_value)) 400425bb815Sopenharmony_ci { 401425bb815Sopenharmony_ci *done_p = true; 402425bb815Sopenharmony_ci break; 403425bb815Sopenharmony_ci } 404425bb815Sopenharmony_ci 405425bb815Sopenharmony_ci /* h. */ 406425bb815Sopenharmony_ci ecma_builtin_helper_def_prop_by_index (values_array_obj_p, 407425bb815Sopenharmony_ci idx, 408425bb815Sopenharmony_ci ECMA_VALUE_UNDEFINED, 409425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); 410425bb815Sopenharmony_ci 411425bb815Sopenharmony_ci /* i. */ 412425bb815Sopenharmony_ci ecma_value_t next_promise = ecma_op_invoke_by_magic_id (ctor, LIT_MAGIC_STRING_RESOLVE, &next_value, 1); 413425bb815Sopenharmony_ci ecma_free_value (next_value); 414425bb815Sopenharmony_ci 415425bb815Sopenharmony_ci /* j. */ 416425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (next_promise)) 417425bb815Sopenharmony_ci { 418425bb815Sopenharmony_ci break; 419425bb815Sopenharmony_ci } 420425bb815Sopenharmony_ci 421425bb815Sopenharmony_ci /* k. */ 422425bb815Sopenharmony_ci ecma_object_t *res_ele_p; 423425bb815Sopenharmony_ci res_ele_p = ecma_op_create_external_function_object (ecma_builtin_promise_all_handler); 424425bb815Sopenharmony_ci /* l. */ 425425bb815Sopenharmony_ci ecma_op_object_put (res_ele_p, 426425bb815Sopenharmony_ci already_called_str_p, 427425bb815Sopenharmony_ci ECMA_VALUE_FALSE, 428425bb815Sopenharmony_ci false); 429425bb815Sopenharmony_ci /* m. */ 430425bb815Sopenharmony_ci ecma_value_t idx_value = ecma_make_uint32_value (idx); 431425bb815Sopenharmony_ci ecma_op_object_put (res_ele_p, 432425bb815Sopenharmony_ci index_str_p, 433425bb815Sopenharmony_ci idx_value, 434425bb815Sopenharmony_ci false); 435425bb815Sopenharmony_ci ecma_free_value (idx_value); 436425bb815Sopenharmony_ci 437425bb815Sopenharmony_ci /* n. */ 438425bb815Sopenharmony_ci ecma_op_object_put (res_ele_p, 439425bb815Sopenharmony_ci value_str_p, 440425bb815Sopenharmony_ci values_array, 441425bb815Sopenharmony_ci false); 442425bb815Sopenharmony_ci 443425bb815Sopenharmony_ci /* o. */ 444425bb815Sopenharmony_ci ecma_op_object_put (res_ele_p, 445425bb815Sopenharmony_ci capability_str_p, 446425bb815Sopenharmony_ci capability, 447425bb815Sopenharmony_ci false); 448425bb815Sopenharmony_ci /* p. */ 449425bb815Sopenharmony_ci ecma_op_object_put (res_ele_p, 450425bb815Sopenharmony_ci remaining_str_p, 451425bb815Sopenharmony_ci remaining, 452425bb815Sopenharmony_ci false); 453425bb815Sopenharmony_ci 454425bb815Sopenharmony_ci /* q. */ 455425bb815Sopenharmony_ci ecma_builtin_promise_remaining_inc_or_dec (remaining, true); 456425bb815Sopenharmony_ci 457425bb815Sopenharmony_ci /* r. */ 458425bb815Sopenharmony_ci ecma_value_t args[2]; 459425bb815Sopenharmony_ci args[0] = ecma_make_object_value (res_ele_p); 460425bb815Sopenharmony_ci args[1] = ecma_op_object_get_by_magic_id (capability_obj_p, LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REJECT); 461425bb815Sopenharmony_ci ecma_value_t result = ecma_op_invoke_by_magic_id (next_promise, LIT_MAGIC_STRING_THEN, args, 2); 462425bb815Sopenharmony_ci ecma_free_value (next_promise); 463425bb815Sopenharmony_ci 464425bb815Sopenharmony_ci for (uint8_t i = 0; i < 2; i++) 465425bb815Sopenharmony_ci { 466425bb815Sopenharmony_ci ecma_free_value (args[i]); 467425bb815Sopenharmony_ci } 468425bb815Sopenharmony_ci 469425bb815Sopenharmony_ci /* s. */ 470425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 471425bb815Sopenharmony_ci { 472425bb815Sopenharmony_ci break; 473425bb815Sopenharmony_ci } 474425bb815Sopenharmony_ci 475425bb815Sopenharmony_ci ecma_free_value (result); 476425bb815Sopenharmony_ci 477425bb815Sopenharmony_ci /* t. */ 478425bb815Sopenharmony_ci idx++; 479425bb815Sopenharmony_ci } 480425bb815Sopenharmony_ci 481425bb815Sopenharmony_ci ecma_free_value (remaining); 482425bb815Sopenharmony_ci ecma_deref_object (values_array_obj_p); 483425bb815Sopenharmony_ci return ret_value; 484425bb815Sopenharmony_ci} /* ecma_builtin_promise_perform_all */ 485425bb815Sopenharmony_ci 486425bb815Sopenharmony_ci/** 487425bb815Sopenharmony_ci * The common function for both Promise.race and Promise.all. 488425bb815Sopenharmony_ci * 489425bb815Sopenharmony_ci * @return ecma value of the new promise. 490425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 491425bb815Sopenharmony_ci */ 492425bb815Sopenharmony_cistatic ecma_value_t 493425bb815Sopenharmony_ciecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */ 494425bb815Sopenharmony_ci ecma_value_t iterable, /**< the items to be resolved */ 495425bb815Sopenharmony_ci bool is_race) /**< indicates whether it is race function */ 496425bb815Sopenharmony_ci{ 497425bb815Sopenharmony_ci if (!ecma_is_value_object (this_arg)) 498425bb815Sopenharmony_ci { 499425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object.")); 500425bb815Sopenharmony_ci } 501425bb815Sopenharmony_ci 502425bb815Sopenharmony_ci ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); 503425bb815Sopenharmony_ci ecma_value_t species_symbol = ecma_op_object_get_by_magic_id (this_obj_p, 504425bb815Sopenharmony_ci LIT_MAGIC_STRING_SYMBOL); 505425bb815Sopenharmony_ci 506425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (species_symbol)) 507425bb815Sopenharmony_ci { 508425bb815Sopenharmony_ci return species_symbol; 509425bb815Sopenharmony_ci } 510425bb815Sopenharmony_ci 511425bb815Sopenharmony_ci ecma_value_t constructor_value = this_arg; 512425bb815Sopenharmony_ci 513425bb815Sopenharmony_ci if (!ecma_is_value_null (species_symbol) && !ecma_is_value_undefined (species_symbol)) 514425bb815Sopenharmony_ci { 515425bb815Sopenharmony_ci constructor_value = species_symbol; 516425bb815Sopenharmony_ci } 517425bb815Sopenharmony_ci else 518425bb815Sopenharmony_ci { 519425bb815Sopenharmony_ci ecma_ref_object (this_obj_p); 520425bb815Sopenharmony_ci } 521425bb815Sopenharmony_ci 522425bb815Sopenharmony_ci ecma_value_t capability = ecma_promise_new_capability (constructor_value); 523425bb815Sopenharmony_ci 524425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (capability)) 525425bb815Sopenharmony_ci { 526425bb815Sopenharmony_ci ecma_free_value (constructor_value); 527425bb815Sopenharmony_ci return capability; 528425bb815Sopenharmony_ci } 529425bb815Sopenharmony_ci 530425bb815Sopenharmony_ci ecma_value_t iterator = ecma_builtin_promise_reject_abrupt (ecma_op_get_iterator (iterable, ECMA_VALUE_EMPTY), 531425bb815Sopenharmony_ci capability); 532425bb815Sopenharmony_ci 533425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (iterator)) 534425bb815Sopenharmony_ci { 535425bb815Sopenharmony_ci ecma_free_value (constructor_value); 536425bb815Sopenharmony_ci ecma_free_value (capability); 537425bb815Sopenharmony_ci return iterator; 538425bb815Sopenharmony_ci } 539425bb815Sopenharmony_ci 540425bb815Sopenharmony_ci ecma_value_t ret = ECMA_VALUE_EMPTY; 541425bb815Sopenharmony_ci bool is_done = false; 542425bb815Sopenharmony_ci 543425bb815Sopenharmony_ci if (is_race) 544425bb815Sopenharmony_ci { 545425bb815Sopenharmony_ci ret = ecma_builtin_promise_perform_race (iterator, capability, constructor_value, &is_done); 546425bb815Sopenharmony_ci } 547425bb815Sopenharmony_ci else 548425bb815Sopenharmony_ci { 549425bb815Sopenharmony_ci ret = ecma_builtin_promise_perform_all (iterator, constructor_value, capability, &is_done); 550425bb815Sopenharmony_ci } 551425bb815Sopenharmony_ci 552425bb815Sopenharmony_ci ecma_free_value (constructor_value); 553425bb815Sopenharmony_ci 554425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (ret)) 555425bb815Sopenharmony_ci { 556425bb815Sopenharmony_ci if (!is_done) 557425bb815Sopenharmony_ci { 558425bb815Sopenharmony_ci ret = ecma_op_iterator_close (iterator); 559425bb815Sopenharmony_ci } 560425bb815Sopenharmony_ci 561425bb815Sopenharmony_ci ret = ecma_builtin_promise_reject_abrupt (ret, capability); 562425bb815Sopenharmony_ci } 563425bb815Sopenharmony_ci 564425bb815Sopenharmony_ci ecma_free_value (iterator); 565425bb815Sopenharmony_ci ecma_free_value (capability); 566425bb815Sopenharmony_ci 567425bb815Sopenharmony_ci return ret; 568425bb815Sopenharmony_ci} /* ecma_builtin_promise_race_or_all */ 569425bb815Sopenharmony_ci 570425bb815Sopenharmony_ci/** 571425bb815Sopenharmony_ci * The Promise.race routine. 572425bb815Sopenharmony_ci * 573425bb815Sopenharmony_ci * See also: 574425bb815Sopenharmony_ci * ES2015 25.4.4.3 575425bb815Sopenharmony_ci * 576425bb815Sopenharmony_ci * @return ecma value of the new promise. 577425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 578425bb815Sopenharmony_ci */ 579425bb815Sopenharmony_cistatic ecma_value_t 580425bb815Sopenharmony_ciecma_builtin_promise_race (ecma_value_t this_arg, /**< 'this' argument */ 581425bb815Sopenharmony_ci ecma_value_t array) /**< the items to be resolved */ 582425bb815Sopenharmony_ci{ 583425bb815Sopenharmony_ci return ecma_builtin_promise_race_or_all (this_arg, array, true); 584425bb815Sopenharmony_ci} /* ecma_builtin_promise_race */ 585425bb815Sopenharmony_ci 586425bb815Sopenharmony_ci/** 587425bb815Sopenharmony_ci * The Promise.all routine. 588425bb815Sopenharmony_ci * 589425bb815Sopenharmony_ci * See also: 590425bb815Sopenharmony_ci * ES2015 25.4.4.1 591425bb815Sopenharmony_ci * 592425bb815Sopenharmony_ci * @return ecma value of the new promise. 593425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 594425bb815Sopenharmony_ci */ 595425bb815Sopenharmony_cistatic ecma_value_t 596425bb815Sopenharmony_ciecma_builtin_promise_all (ecma_value_t this_arg, /**< 'this' argument */ 597425bb815Sopenharmony_ci ecma_value_t array) /**< the items to be resolved */ 598425bb815Sopenharmony_ci{ 599425bb815Sopenharmony_ci return ecma_builtin_promise_race_or_all (this_arg, array, false); 600425bb815Sopenharmony_ci} /* ecma_builtin_promise_all */ 601425bb815Sopenharmony_ci 602425bb815Sopenharmony_ci/** 603425bb815Sopenharmony_ci * Handle calling [[Call]] of built-in Promise object. 604425bb815Sopenharmony_ci * 605425bb815Sopenharmony_ci * ES2015 25.4.3 Promise is not intended to be called 606425bb815Sopenharmony_ci * as a function and will throw an exception when called 607425bb815Sopenharmony_ci * in that manner. 608425bb815Sopenharmony_ci * 609425bb815Sopenharmony_ci * @return ecma value 610425bb815Sopenharmony_ci */ 611425bb815Sopenharmony_ciecma_value_t 612425bb815Sopenharmony_ciecma_builtin_promise_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ 613425bb815Sopenharmony_ci ecma_length_t arguments_list_len) /**< number of arguments */ 614425bb815Sopenharmony_ci{ 615425bb815Sopenharmony_ci JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 616425bb815Sopenharmony_ci 617425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Constructor Promise requires 'new'.")); 618425bb815Sopenharmony_ci} /* ecma_builtin_promise_dispatch_call */ 619425bb815Sopenharmony_ci 620425bb815Sopenharmony_ci/** 621425bb815Sopenharmony_ci * Handle calling [[Construct]] of built-in Promise object. 622425bb815Sopenharmony_ci * 623425bb815Sopenharmony_ci * @return ecma value 624425bb815Sopenharmony_ci */ 625425bb815Sopenharmony_ciecma_value_t 626425bb815Sopenharmony_ciecma_builtin_promise_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ 627425bb815Sopenharmony_ci ecma_length_t arguments_list_len) /**< number of arguments */ 628425bb815Sopenharmony_ci{ 629425bb815Sopenharmony_ci JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 630425bb815Sopenharmony_ci 631425bb815Sopenharmony_ci if (arguments_list_len == 0 || !ecma_op_is_callable (arguments_list_p[0])) 632425bb815Sopenharmony_ci { 633425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("First parameter must be callable.")); 634425bb815Sopenharmony_ci } 635425bb815Sopenharmony_ci 636425bb815Sopenharmony_ci return ecma_op_create_promise_object (arguments_list_p[0], ECMA_PROMISE_EXECUTOR_FUNCTION); 637425bb815Sopenharmony_ci} /* ecma_builtin_promise_dispatch_construct */ 638425bb815Sopenharmony_ci 639425bb815Sopenharmony_ci/** 640425bb815Sopenharmony_ci * 25.4.4.6 get Promise [ @@species ] accessor 641425bb815Sopenharmony_ci * 642425bb815Sopenharmony_ci * @return ecma_value 643425bb815Sopenharmony_ci * returned value must be freed with ecma_free_value 644425bb815Sopenharmony_ci */ 645425bb815Sopenharmony_ciecma_value_t 646425bb815Sopenharmony_ciecma_builtin_promise_species_get (ecma_value_t this_value) /**< This Value */ 647425bb815Sopenharmony_ci{ 648425bb815Sopenharmony_ci return ecma_copy_value (this_value); 649425bb815Sopenharmony_ci} /* ecma_builtin_promise_species_get */ 650425bb815Sopenharmony_ci 651425bb815Sopenharmony_ci/** 652425bb815Sopenharmony_ci * @} 653425bb815Sopenharmony_ci * @} 654425bb815Sopenharmony_ci * @} 655425bb815Sopenharmony_ci */ 656425bb815Sopenharmony_ci 657425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */ 658