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