mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implement other routines of Promise (#1729)
Add Promise.resolve, Promise.reject, Promise.race, Promise.all and Promise.prototype.catch Also it fixes the issue 1763 JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
parent
9d4123c3c4
commit
078f6e101d
@ -13,9 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-promise-object.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||
@ -42,34 +40,36 @@
|
||||
*
|
||||
* See also: 25.4.5.3
|
||||
*
|
||||
* @return ecma value of a new promise object
|
||||
* Returned value must be freed with ecma_free_value
|
||||
* @return ecma value of a new promise object.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_prototype_then (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_value_t on_fulfilled, /**< on_fulfilled function */
|
||||
ecma_value_t on_rejected) /**< on_rejected function */
|
||||
{
|
||||
ecma_object_t *obj = ecma_get_object_from_value (this_arg);
|
||||
|
||||
if (!ecma_is_promise (obj))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a Promise."));
|
||||
}
|
||||
|
||||
ecma_value_t result_capability = ecma_promise_new_capability ();
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result_capability))
|
||||
{
|
||||
return result_capability;
|
||||
}
|
||||
|
||||
ecma_value_t ret = ecma_promise_then (this_arg, on_fulfilled, on_rejected, result_capability);
|
||||
ecma_free_value (result_capability);
|
||||
|
||||
return ret;
|
||||
return ecma_promise_then (this_arg,
|
||||
on_fulfilled,
|
||||
on_rejected);
|
||||
} /* ecma_builtin_promise_prototype_then */
|
||||
|
||||
/**
|
||||
* Promise routine: catch.
|
||||
*
|
||||
* See also: 25.4.5.1
|
||||
*
|
||||
* @return ecma value of a new promise object.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_prototype_catch (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_value_t on_rejected) /**< on_rejected function */
|
||||
{
|
||||
return ecma_promise_then (this_arg,
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||
on_rejected);
|
||||
} /* ecma_builtin_promise_prototype_catch */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@ -29,6 +29,7 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE)
|
||||
|
||||
ROUTINE (LIT_MAGIC_STRING_THEN, ecma_builtin_promise_prototype_then, 2, 2)
|
||||
ROUTINE (LIT_MAGIC_STRING_CATCH, ecma_builtin_promise_prototype_catch, 1, 1)
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||
|
||||
|
||||
@ -13,9 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-number-object.h"
|
||||
#include "ecma-promise-object.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||
@ -37,6 +40,615 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The common function for 'reject' and 'resolve'.
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */
|
||||
ecma_value_t argument, /**< argument for reject or resolve */
|
||||
bool is_resolve) /**< whether it is for resolve routine */
|
||||
{
|
||||
if (!ecma_is_value_object (this_arg))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
|
||||
}
|
||||
|
||||
uint8_t builtin_id = ecma_get_object_builtin_id (ecma_get_object_from_value (this_arg));
|
||||
|
||||
if (builtin_id != ECMA_BUILTIN_ID_PROMISE)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not the Promise constructor."));
|
||||
}
|
||||
|
||||
if (is_resolve
|
||||
&& ecma_is_value_object (argument)
|
||||
&& ecma_is_promise (ecma_get_object_from_value (argument)))
|
||||
{
|
||||
return ecma_copy_value (argument);
|
||||
}
|
||||
|
||||
|
||||
ecma_value_t capability = ecma_promise_new_capability ();
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (capability))
|
||||
{
|
||||
return capability;
|
||||
}
|
||||
|
||||
ecma_string_t *str;
|
||||
|
||||
if (is_resolve)
|
||||
{
|
||||
str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
}
|
||||
|
||||
ecma_value_t func = ecma_op_object_get (ecma_get_object_from_value (capability), str);
|
||||
ecma_deref_ecma_string (str);
|
||||
|
||||
ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func),
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||
&argument,
|
||||
1);
|
||||
|
||||
ecma_free_value (func);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (call_ret))
|
||||
{
|
||||
return call_ret;
|
||||
}
|
||||
|
||||
ecma_free_value (call_ret);
|
||||
|
||||
ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
|
||||
ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise);
|
||||
ecma_deref_ecma_string (str_promise);
|
||||
ecma_free_value (capability);
|
||||
|
||||
return promise_new;
|
||||
} /* ecma_builtin_promise_reject_or_resolve */
|
||||
|
||||
/**
|
||||
* Reject the promise if the value is error.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.1.1.1
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
inline static ecma_value_t
|
||||
ecma_builtin_promise_reject_abrupt (ecma_value_t abrupt_value,
|
||||
ecma_value_t capability)
|
||||
{
|
||||
ecma_value_t reason = ecma_get_value_from_error_value (abrupt_value);
|
||||
ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
|
||||
ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (reject),
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||
&reason,
|
||||
1);
|
||||
ecma_free_value (reject);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (call_ret))
|
||||
{
|
||||
return call_ret;
|
||||
}
|
||||
|
||||
ecma_free_value (call_ret);
|
||||
|
||||
ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
|
||||
ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise);
|
||||
ecma_deref_ecma_string (str_promise);
|
||||
|
||||
return promise_new;
|
||||
} /* ecma_builtin_promise_reject_abrupt */
|
||||
|
||||
/**
|
||||
* The Promise.reject routine.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.4.4
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_reject (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t reason) /**< the reason for reject */
|
||||
{
|
||||
return ecma_builtin_promise_reject_or_resolve (this_arg, reason, false);
|
||||
} /* ecma_builtin_promise_reject */
|
||||
|
||||
/**
|
||||
* The Promise.resolve routine.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.4.5
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t argument) /**< the argument for resolve */
|
||||
{
|
||||
return ecma_builtin_promise_reject_or_resolve (this_arg, argument, true);
|
||||
} /* ecma_builtin_promise_resolve */
|
||||
|
||||
/**
|
||||
* Runtime Semantics: PerformPromiseRace.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.4.3.1
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
inline static ecma_value_t
|
||||
ecma_builtin_promise_do_race (ecma_value_t array, /**< the array for race */
|
||||
ecma_value_t capability, /**< PromiseCapability record */
|
||||
ecma_value_t ctor) /**< the caller of Promise.race */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_object (capability)
|
||||
&& ecma_is_value_object (array)
|
||||
&& ecma_is_value_object (ctor));
|
||||
JERRY_ASSERT (ecma_get_object_builtin_id (ecma_get_object_from_value (ctor)) == ECMA_BUILTIN_ID_PROMISE);
|
||||
JERRY_ASSERT (ecma_get_object_type (ecma_get_object_from_value (array)) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();
|
||||
ecma_object_t *array_p = ecma_get_object_from_value (array);
|
||||
ecma_value_t len_value = ecma_op_object_get (array_p, magic_string_length_p);
|
||||
ecma_deref_ecma_string (magic_string_length_p);
|
||||
ecma_length_t len = (ecma_length_t) ecma_get_integer_from_value (len_value);
|
||||
ecma_fast_free_value (len_value);
|
||||
|
||||
ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
|
||||
ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability),
|
||||
str_resolve);
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability),
|
||||
str_reject);
|
||||
|
||||
for (ecma_length_t index = 0; index <= len; index++)
|
||||
{
|
||||
/* b-d. */
|
||||
if (index == len)
|
||||
{
|
||||
ret = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise);
|
||||
break;
|
||||
}
|
||||
|
||||
/* e. */
|
||||
ecma_string_t *str_index = ecma_new_ecma_string_from_uint32 (index);
|
||||
ecma_value_t array_item = ecma_op_object_get (array_p, str_index);
|
||||
ecma_deref_ecma_string (str_index);
|
||||
|
||||
/* h. */
|
||||
ecma_value_t next_promise = ecma_builtin_promise_resolve (ctor, array_item);
|
||||
ecma_free_value (array_item);
|
||||
|
||||
/* i. */
|
||||
if (ECMA_IS_VALUE_ERROR (next_promise))
|
||||
{
|
||||
ret = next_promise;
|
||||
break;
|
||||
}
|
||||
|
||||
/* j. */
|
||||
ecma_value_t then_result = ecma_promise_then (next_promise, resolve, reject);
|
||||
ecma_free_value (next_promise);
|
||||
|
||||
/* k. */
|
||||
if (ECMA_IS_VALUE_ERROR (then_result))
|
||||
{
|
||||
ret = then_result;
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_free_value (then_result);
|
||||
}
|
||||
|
||||
ecma_free_value (reject);
|
||||
ecma_free_value (resolve);
|
||||
ecma_deref_ecma_string (str_promise);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
|
||||
JERRY_ASSERT (!ecma_is_value_empty (ret));
|
||||
|
||||
return ret;
|
||||
} /* ecma_builtin_promise_do_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);
|
||||
|
||||
ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
/* 1. */
|
||||
ecma_object_t *function_p = ecma_get_object_from_value (function);
|
||||
ecma_string_t *str_already_called = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_ALREADY_CALLED);
|
||||
ecma_value_t already_called = ecma_op_object_get (function_p, str_already_called);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (already_called));
|
||||
|
||||
/* 2. */
|
||||
if (ecma_is_value_true (already_called))
|
||||
{
|
||||
ecma_fast_free_value (already_called);
|
||||
ecma_deref_ecma_string (str_already_called);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 3. */
|
||||
ecma_op_object_put (function_p,
|
||||
str_already_called,
|
||||
ecma_make_boolean_value (true),
|
||||
false);
|
||||
|
||||
ecma_string_t *str_index = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_INDEX);
|
||||
ecma_string_t *str_value = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_VALUE);
|
||||
ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
|
||||
ecma_string_t *str_remaining = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REMAINING_ELEMENT);
|
||||
|
||||
/* 4-7. */
|
||||
ecma_value_t index_val = ecma_op_object_get (function_p, str_index);
|
||||
ecma_value_t value_array = ecma_op_object_get (function_p, str_value);
|
||||
ecma_value_t capability = ecma_op_object_get (function_p, str_capability);
|
||||
ecma_value_t remaining = ecma_op_object_get (function_p, str_remaining);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_integer_number (index_val));
|
||||
|
||||
/* 8. */
|
||||
ecma_string_t *index_str = ecma_new_ecma_string_from_uint32 ((uint32_t) ecma_get_integer_from_value (index_val));
|
||||
|
||||
ecma_op_object_put (ecma_get_object_from_value (value_array),
|
||||
index_str,
|
||||
argv[0],
|
||||
false);
|
||||
ecma_deref_ecma_string (index_str);
|
||||
|
||||
/* 9-10. */
|
||||
if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0)
|
||||
{
|
||||
ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability),
|
||||
str_resolve);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ret = ecma_op_function_call (ecma_get_object_from_value (resolve),
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||
&value_array,
|
||||
1);
|
||||
ecma_free_value (resolve);
|
||||
}
|
||||
|
||||
ecma_free_value (remaining);
|
||||
ecma_free_value (capability);
|
||||
ecma_free_value (value_array);
|
||||
ecma_fast_free_value (index_val);
|
||||
ecma_fast_free_value (already_called);
|
||||
ecma_deref_ecma_string (str_already_called);
|
||||
ecma_deref_ecma_string (str_index);
|
||||
ecma_deref_ecma_string (str_value);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_remaining);
|
||||
|
||||
return ret;
|
||||
} /* ecma_builtin_promise_all_handler */
|
||||
|
||||
/**
|
||||
* Runtime Semantics: PerformPromiseAll.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.4.1.1
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
inline static ecma_value_t
|
||||
ecma_builtin_promise_do_all (ecma_value_t array, /**< the array for all */
|
||||
ecma_value_t capability, /**< PromiseCapability record */
|
||||
ecma_value_t ctor) /**< the caller of Promise.race */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_object (capability)
|
||||
&& ecma_is_value_object (array)
|
||||
&& ecma_is_value_object (ctor));
|
||||
JERRY_ASSERT (ecma_get_object_builtin_id (ecma_get_object_from_value (ctor)) == ECMA_BUILTIN_ID_PROMISE);
|
||||
JERRY_ASSERT (ecma_get_object_type (ecma_get_object_from_value (array)) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();
|
||||
ecma_object_t *array_p = ecma_get_object_from_value (array);
|
||||
ecma_value_t len_value = ecma_op_object_get (array_p, magic_string_length_p);
|
||||
ecma_deref_ecma_string (magic_string_length_p);
|
||||
ecma_length_t len = (ecma_length_t) ecma_get_integer_from_value (len_value);
|
||||
ecma_fast_free_value (len_value);
|
||||
|
||||
ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
|
||||
ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
ecma_string_t *str_already_called = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_ALREADY_CALLED);
|
||||
ecma_string_t *str_index = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_INDEX);
|
||||
ecma_string_t *str_value = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_VALUE);
|
||||
ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
|
||||
ecma_string_t *str_remaining = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REMAINING_ELEMENT);
|
||||
|
||||
ecma_value_t undefined_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
/* String '1' indicates [[Resolve]] and '2' indicates [[Reject]]. */
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability),
|
||||
str_resolve);
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability),
|
||||
str_reject);
|
||||
/* 3. */
|
||||
ecma_value_t result_array_length_val = ecma_make_uint32_value (0);
|
||||
ecma_value_t value_array = ecma_op_create_array_object (&result_array_length_val, 1, true);
|
||||
ecma_free_value (result_array_length_val);
|
||||
/* 4. */
|
||||
ecma_value_t remaining = ecma_op_create_number_object (ecma_make_integer_value (1));
|
||||
/* 5. */
|
||||
ecma_length_t index = 0;
|
||||
|
||||
/* 6 */
|
||||
while (true)
|
||||
{
|
||||
JERRY_ASSERT (index <= len);
|
||||
/* d. */
|
||||
if (index == len)
|
||||
{
|
||||
/* ii. */
|
||||
if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0)
|
||||
{
|
||||
/* iii. */
|
||||
ecma_value_t resolve_ret = ecma_op_function_call (ecma_get_object_from_value (resolve),
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||
&value_array,
|
||||
1);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (resolve_ret))
|
||||
{
|
||||
ret = resolve_ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* iv. */
|
||||
ret = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise);
|
||||
break;
|
||||
}
|
||||
|
||||
/* e. h. */
|
||||
ecma_string_t *index_str = ecma_new_ecma_string_from_uint32 (index);
|
||||
ecma_value_t array_item = ecma_op_object_get (array_p, index_str);
|
||||
ecma_op_object_put (ecma_get_object_from_value (value_array),
|
||||
index_str,
|
||||
undefined_val,
|
||||
false);
|
||||
ecma_deref_ecma_string (index_str);
|
||||
/* i. */
|
||||
ecma_value_t next_promise = ecma_builtin_promise_resolve (ctor, array_item);
|
||||
ecma_free_value (array_item);
|
||||
|
||||
/* j. */
|
||||
if (ECMA_IS_VALUE_ERROR (next_promise))
|
||||
{
|
||||
ret = next_promise;
|
||||
break;
|
||||
}
|
||||
|
||||
/* k. */
|
||||
ecma_object_t *res_ele_p;
|
||||
res_ele_p = ecma_op_create_external_function_object ((ecma_external_pointer_t) ecma_builtin_promise_all_handler);
|
||||
/* l. */
|
||||
ecma_op_object_put (res_ele_p,
|
||||
str_already_called,
|
||||
ecma_make_boolean_value (false),
|
||||
false);
|
||||
/* m. */
|
||||
ecma_op_object_put (res_ele_p,
|
||||
str_index,
|
||||
ecma_make_uint32_value (index),
|
||||
false);
|
||||
/* n. */
|
||||
ecma_op_object_put (res_ele_p,
|
||||
str_value,
|
||||
value_array,
|
||||
false);
|
||||
/* o. */
|
||||
ecma_op_object_put (res_ele_p,
|
||||
str_capability,
|
||||
capability,
|
||||
false);
|
||||
/* p. */
|
||||
ecma_op_object_put (res_ele_p,
|
||||
str_remaining,
|
||||
remaining,
|
||||
false);
|
||||
|
||||
/* q. */
|
||||
ecma_builtin_promise_remaining_inc_or_dec (remaining, true);
|
||||
/* r. */
|
||||
ecma_value_t then_result = ecma_promise_then (next_promise,
|
||||
ecma_make_object_value (res_ele_p),
|
||||
reject);
|
||||
ecma_deref_object (res_ele_p);
|
||||
ecma_free_value (next_promise);
|
||||
|
||||
/* s. */
|
||||
if (ECMA_IS_VALUE_ERROR (then_result))
|
||||
{
|
||||
ret = then_result;
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_free_value (then_result);
|
||||
index ++;
|
||||
}
|
||||
|
||||
ecma_free_value (reject);
|
||||
ecma_free_value (resolve);
|
||||
ecma_free_value (remaining);
|
||||
ecma_free_value (value_array);
|
||||
ecma_deref_ecma_string (str_already_called);
|
||||
ecma_deref_ecma_string (str_index);
|
||||
ecma_deref_ecma_string (str_value);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_remaining);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
ecma_deref_ecma_string (str_promise);
|
||||
|
||||
JERRY_ASSERT (!ecma_is_value_empty (ret));
|
||||
|
||||
return ret;
|
||||
} /* ecma_builtin_promise_do_all */
|
||||
|
||||
/**
|
||||
* The common function for both Promise.race and Promise.all.
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t array, /**< the items to be resolved */
|
||||
bool is_race) /**< indicates whether it is race function */
|
||||
{
|
||||
if (!ecma_is_value_object (this_arg))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
|
||||
}
|
||||
|
||||
uint8_t builtin_id = ecma_get_object_builtin_id (ecma_get_object_from_value (this_arg));
|
||||
|
||||
if (builtin_id != ECMA_BUILTIN_ID_PROMISE)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not the Promise constructor."));
|
||||
}
|
||||
|
||||
ecma_value_t capability = ecma_promise_new_capability ();
|
||||
ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
if (!ecma_is_value_object (array)
|
||||
|| ecma_get_object_type (ecma_get_object_from_value (array)) != ECMA_OBJECT_TYPE_ARRAY)
|
||||
{
|
||||
ecma_value_t error = ecma_raise_type_error (ECMA_ERR_MSG ("Second argument is not an array."));
|
||||
ret = ecma_builtin_promise_reject_abrupt (error, capability);
|
||||
ecma_free_value (error);
|
||||
ecma_free_value (capability);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_race)
|
||||
{
|
||||
ret = ecma_builtin_promise_do_race (array, capability, this_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ecma_builtin_promise_do_all (array, capability, this_arg);
|
||||
}
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret))
|
||||
{
|
||||
ret = ecma_get_value_from_error_value (ret);
|
||||
}
|
||||
|
||||
ecma_free_value (capability);
|
||||
|
||||
return ret;
|
||||
} /* ecma_builtin_promise_race_or_all */
|
||||
|
||||
/**
|
||||
* The Promise.race routine.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.4.3
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_race (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t array) /**< the items to be resolved */
|
||||
{
|
||||
return ecma_builtin_promise_race_or_all (this_arg, array, true);
|
||||
} /* ecma_builtin_promise_race */
|
||||
|
||||
/**
|
||||
* The Promise.all routine.
|
||||
*
|
||||
* See also:
|
||||
* ES2015 25.4.4.1
|
||||
*
|
||||
* @return ecma value of the new promise.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_promise_all (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t array) /**< the items to be resolved */
|
||||
{
|
||||
return ecma_builtin_promise_race_or_all (this_arg, array, false);
|
||||
} /* ecma_builtin_promise_all */
|
||||
|
||||
/**
|
||||
* Handle calling [[Call]] of built-in Promise object.
|
||||
*
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||
|
||||
/* Number properties:
|
||||
* (property name, number value, writable, enumerable, configurable) */
|
||||
|
||||
@ -35,5 +37,11 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
ROUTINE (LIT_MAGIC_STRING_REJECT, ecma_builtin_promise_reject, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_RESOLVE, ecma_builtin_promise_resolve, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_RACE, ecma_builtin_promise_race, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_ALL, ecma_builtin_promise_all, 1, 1)
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
||||
|
||||
@ -136,13 +136,15 @@ ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */
|
||||
ecma_job_promise_reaction_t *job_p = (ecma_job_promise_reaction_t *) obj_p;
|
||||
ecma_object_t *reaction_p = ecma_get_object_from_value (job_p->reaction);
|
||||
|
||||
ecma_string_t *str_0 = ecma_new_ecma_string_from_uint32 (0);
|
||||
ecma_string_t *str_1 = ecma_new_ecma_string_from_uint32 (1);
|
||||
ecma_string_t *str_2 = ecma_new_ecma_string_from_uint32 (2);
|
||||
/* 2. string '0' indicates the [[Capability]] of reaction. */
|
||||
ecma_value_t capability = ecma_op_object_get (reaction_p, str_0);
|
||||
/* 3. string '1' indicates the [[Handler]] of reaction. */
|
||||
ecma_value_t handler = ecma_op_object_get (reaction_p, str_1);
|
||||
ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
|
||||
ecma_string_t *str_handler = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_HANDLER);
|
||||
ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
|
||||
/* 2. */
|
||||
ecma_value_t capability = ecma_op_object_get (reaction_p, str_capability);
|
||||
/* 3. */
|
||||
ecma_value_t handler = ecma_op_object_get (reaction_p, str_handler);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler));
|
||||
|
||||
@ -166,9 +168,13 @@ ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */
|
||||
|
||||
if (ecma_is_value_false (handler) || ECMA_IS_VALUE_ERROR (handler_result))
|
||||
{
|
||||
/* 7. String '2' indicates [[Reject]] of Capability. */
|
||||
handler_result = ecma_get_value_from_error_value (handler_result);
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_2);
|
||||
if (ECMA_IS_VALUE_ERROR (handler_result))
|
||||
{
|
||||
handler_result = ecma_get_value_from_error_value (handler_result);
|
||||
}
|
||||
|
||||
/* 7. */
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject);
|
||||
|
||||
JERRY_ASSERT (ecma_op_is_callable (reject));
|
||||
|
||||
@ -180,8 +186,8 @@ ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 8. String '1' indicates [[Resolve]] of Capability. */
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_1);
|
||||
/* 8. */
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve);
|
||||
|
||||
JERRY_ASSERT (ecma_op_is_callable (resolve));
|
||||
|
||||
@ -195,9 +201,10 @@ ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */
|
||||
ecma_free_value (handler_result);
|
||||
ecma_free_value (handler);
|
||||
ecma_free_value (capability);
|
||||
ecma_deref_ecma_string (str_0);
|
||||
ecma_deref_ecma_string (str_1);
|
||||
ecma_deref_ecma_string (str_2);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_handler);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
ecma_free_promise_reaction_job (job_p);
|
||||
|
||||
return status;
|
||||
|
||||
@ -344,54 +344,55 @@ 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 *str_0 = ecma_new_ecma_string_from_uint32 (0);
|
||||
ecma_string_t *str_1 = ecma_new_ecma_string_from_uint32 (1);
|
||||
ecma_string_t *str_2 = ecma_new_ecma_string_from_uint32 (2);
|
||||
/* 2. String '0' indicates [[Capability]] of the executor. */
|
||||
ecma_value_t capability = ecma_op_object_get (executor_p, str_0);
|
||||
/* 3. String '1' indicates [[Resolve]] of the capability. */
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_1);
|
||||
ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
|
||||
ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
|
||||
/* 2. */
|
||||
ecma_value_t capability = ecma_op_object_get (executor_p, str_capability);
|
||||
/* 3. */
|
||||
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve);
|
||||
|
||||
if (resolve != ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED))
|
||||
{
|
||||
ecma_free_value (resolve);
|
||||
ecma_free_value (capability);
|
||||
ecma_deref_ecma_string (str_0);
|
||||
ecma_deref_ecma_string (str_1);
|
||||
ecma_deref_ecma_string (str_2);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'resolve' function should be undefined."));
|
||||
}
|
||||
|
||||
/* 4. String '2' indicates [[Reject]] of the capability. */
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_2);
|
||||
/* 4. */
|
||||
ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject);
|
||||
|
||||
if (reject != ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED))
|
||||
{
|
||||
ecma_free_value (reject);
|
||||
ecma_free_value (capability);
|
||||
ecma_deref_ecma_string (str_0);
|
||||
ecma_deref_ecma_string (str_1);
|
||||
ecma_deref_ecma_string (str_2);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'reject' function should be undefined."));
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
ecma_op_object_put (ecma_get_object_from_value (capability),
|
||||
str_1,
|
||||
str_resolve,
|
||||
resolve_func,
|
||||
false);
|
||||
/* 6. */
|
||||
ecma_op_object_put (ecma_get_object_from_value (capability),
|
||||
str_2,
|
||||
str_reject,
|
||||
reject_func,
|
||||
false);
|
||||
|
||||
ecma_free_value (capability);
|
||||
ecma_deref_ecma_string (str_0);
|
||||
ecma_deref_ecma_string (str_1);
|
||||
ecma_deref_ecma_string (str_2);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
} /* ecma_call_builtin_executor */
|
||||
@ -558,29 +559,30 @@ ecma_promise_new_capability (void)
|
||||
{
|
||||
/* 3. */
|
||||
ecma_object_t *capability_p = ecma_op_create_object_object_noarg ();
|
||||
ecma_string_t *str_0 = ecma_new_ecma_string_from_uint32 (0);
|
||||
|
||||
ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
|
||||
ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
|
||||
/* 4. */
|
||||
ecma_object_t *executor_p;
|
||||
executor_p = ecma_op_create_object_object_noarg ();
|
||||
ecma_value_t executor = ecma_make_object_value (executor_p);
|
||||
/* 5. String '0' here indicates the [[Capability]] of executor. */
|
||||
/* 5. */
|
||||
ecma_op_object_put (executor_p,
|
||||
str_0,
|
||||
str_capability,
|
||||
ecma_make_object_value (capability_p),
|
||||
false);
|
||||
|
||||
/* 6. */
|
||||
ecma_value_t promise = ecma_op_create_promise_object (executor, false);
|
||||
|
||||
/* 10. String '0' here indicates the [[Promise]] of Capability. */
|
||||
/* 10. */
|
||||
ecma_op_object_put (capability_p,
|
||||
str_0,
|
||||
str_promise,
|
||||
promise,
|
||||
false);
|
||||
|
||||
ecma_deref_object (executor_p);
|
||||
ecma_deref_ecma_string (str_0);
|
||||
ecma_deref_ecma_string (str_promise);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
/* 7. */
|
||||
if (ECMA_IS_VALUE_ERROR (promise))
|
||||
{
|
||||
@ -590,10 +592,10 @@ ecma_promise_new_capability (void)
|
||||
}
|
||||
|
||||
ecma_free_value (promise);
|
||||
/* 8. str '1' indicates [[Resolve]] of Capability. */
|
||||
ecma_string_t *str_1 = ecma_new_ecma_string_from_uint32 (1);
|
||||
ecma_value_t resolve = ecma_op_object_get (capability_p, str_1);
|
||||
ecma_deref_ecma_string (str_1);
|
||||
/* 8. */
|
||||
ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
|
||||
ecma_value_t resolve = ecma_op_object_get (capability_p, str_resolve);
|
||||
ecma_deref_ecma_string (str_resolve);
|
||||
|
||||
if (!ecma_op_is_callable (resolve))
|
||||
{
|
||||
@ -603,10 +605,10 @@ ecma_promise_new_capability (void)
|
||||
}
|
||||
|
||||
ecma_free_value (resolve);
|
||||
/* 9. str '2' indicates [[Reject]] of Capability. */
|
||||
ecma_string_t *str_2 = ecma_new_ecma_string_from_uint32 (2);
|
||||
ecma_value_t reject = ecma_op_object_get (capability_p, str_2);
|
||||
ecma_deref_ecma_string (str_2);
|
||||
/* 9. */
|
||||
ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
|
||||
ecma_value_t reject = ecma_op_object_get (capability_p, str_reject);
|
||||
ecma_deref_ecma_string (str_reject);
|
||||
|
||||
if (!ecma_op_is_callable (reject))
|
||||
{
|
||||
@ -629,14 +631,15 @@ ecma_promise_new_capability (void)
|
||||
* @return ecma value of the new promise object
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_promise_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 */
|
||||
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_string_t *str_0 = ecma_new_ecma_string_from_uint32 (0);
|
||||
ecma_string_t *str_1 = ecma_new_ecma_string_from_uint32 (1);
|
||||
ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
|
||||
ecma_string_t *str_handler = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_HANDLER);
|
||||
ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
|
||||
|
||||
/* 3. boolean true indicates "indentity" */
|
||||
if (!ecma_op_is_callable (on_fulfilled))
|
||||
@ -650,24 +653,24 @@ ecma_promise_then (ecma_value_t promise, /**< the promise which call 'then' */
|
||||
on_rejected = ecma_make_boolean_value (false);
|
||||
}
|
||||
|
||||
/* 5-6. String '0' indicates [[Capability]] of a PromiseReaction, '1' indicates [[Handler]]. */
|
||||
/* 5-6. */
|
||||
ecma_object_t *fulfill_reaction_p = ecma_op_create_object_object_noarg ();
|
||||
ecma_object_t *reject_reaction_p = ecma_op_create_object_object_noarg ();
|
||||
ecma_op_object_put (fulfill_reaction_p,
|
||||
str_0,
|
||||
str_capability,
|
||||
result_capability,
|
||||
false);
|
||||
ecma_op_object_put (fulfill_reaction_p,
|
||||
str_1,
|
||||
str_handler,
|
||||
on_fulfilled,
|
||||
false);
|
||||
|
||||
ecma_op_object_put (reject_reaction_p,
|
||||
str_0,
|
||||
str_capability,
|
||||
result_capability,
|
||||
false);
|
||||
ecma_op_object_put (reject_reaction_p,
|
||||
str_1,
|
||||
str_handler,
|
||||
on_rejected,
|
||||
false);
|
||||
|
||||
@ -700,13 +703,45 @@ ecma_promise_then (ecma_value_t promise, /**< the promise which call 'then' */
|
||||
ecma_free_value (reason);
|
||||
}
|
||||
|
||||
/* 10. String '0' indicates [[Promise]] of a Capability. */
|
||||
ecma_value_t ret = ecma_op_object_get (ecma_get_object_from_value (result_capability), str_0);
|
||||
/* 10. */
|
||||
ecma_value_t ret = ecma_op_object_get (ecma_get_object_from_value (result_capability), str_promise);
|
||||
|
||||
ecma_deref_object (fulfill_reaction_p);
|
||||
ecma_deref_object (reject_reaction_p);
|
||||
ecma_deref_ecma_string (str_0);
|
||||
ecma_deref_ecma_string (str_1);
|
||||
ecma_deref_ecma_string (str_capability);
|
||||
ecma_deref_ecma_string (str_handler);
|
||||
ecma_deref_ecma_string (str_promise);
|
||||
return ret;
|
||||
} /* ecma_promise_do_then */
|
||||
|
||||
/**
|
||||
* The common function for ecma_builtin_promise_prototype_then
|
||||
* and ecma_builtin_promise_prototype_catch.
|
||||
*
|
||||
* @return ecma value of a new promise object.
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_promise_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_object_t *obj = ecma_get_object_from_value (promise);
|
||||
|
||||
if (!ecma_is_promise (obj))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a Promise."));
|
||||
}
|
||||
|
||||
ecma_value_t result_capability = ecma_promise_new_capability ();
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result_capability))
|
||||
{
|
||||
return result_capability;
|
||||
}
|
||||
|
||||
ecma_value_t ret = ecma_promise_do_then (promise, on_fulfilled, on_rejected, result_capability);
|
||||
ecma_free_value (result_capability);
|
||||
|
||||
return ret;
|
||||
} /* ecma_promise_then */
|
||||
|
||||
@ -58,6 +58,23 @@ typedef struct
|
||||
ecma_collection_header_t *reject_reactions; /**< list of PromiseRejectReactions */
|
||||
} ecma_promise_object_t;
|
||||
|
||||
/**
|
||||
* Use symbolic constant to represent the internal property name of
|
||||
* promise related structures.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_PROMISE_PROPERTY_PROMISE, /**< [[Promise]] property */
|
||||
ECMA_PROMISE_PROPERTY_RESOLVE, /**< [[Resolve]] property */
|
||||
ECMA_PROMISE_PROPERTY_REJECT, /**< [[Reject]] property */
|
||||
ECMA_PROMISE_PROPERTY_CAPABILITY, /**< [[Capability]] property */
|
||||
ECMA_PROMISE_PROPERTY_HANDLER, /**< [[Handler]] property */
|
||||
ECMA_PROMISE_PROPERTY_ALREADY_CALLED, /**< [[AlreadyCalled]] property */
|
||||
ECMA_PROMISE_PROPERTY_INDEX, /**< [[Index]] property */
|
||||
ECMA_PROMISE_PROPERTY_VALUE, /**< [[Values]] property */
|
||||
ECMA_PROMISE_PROPERTY_REMAINING_ELEMENT /**< [[RemainingElement]] property */
|
||||
} ecma_promise_property_symbolic_constant_t;
|
||||
|
||||
bool ecma_is_promise (ecma_object_t *obj_p);
|
||||
ecma_value_t ecma_promise_get_result (ecma_object_t *obj_p);
|
||||
void ecma_promise_set_result (ecma_object_t *obj_p, ecma_value_t result);
|
||||
@ -72,8 +89,8 @@ ecma_value_t ecma_promise_new_capability (void);
|
||||
ecma_value_t
|
||||
ecma_promise_then (ecma_value_t promise,
|
||||
ecma_value_t on_fulfilled,
|
||||
ecma_value_t on_rejected,
|
||||
ecma_value_t result_capability);
|
||||
ecma_value_t on_rejected);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@ -63,6 +63,11 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UTC_U, "UTC")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_MATH_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ABS, "abs")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ALL, "all")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_MATH_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COS, "cos")
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXP, "exp")
|
||||
#endif
|
||||
@ -130,6 +135,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NULL, "null")
|
||||
#if !defined (CONFIG_DISABLE_ARRAY_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PUSH, "push")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RACE, "race")
|
||||
#endif
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEAL, "seal")
|
||||
#if !defined (CONFIG_DISABLE_ARRAY_BUILTIN) \
|
||||
|| !defined (CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN)
|
||||
@ -161,6 +169,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_APPLY, "apply")
|
||||
#if !defined (CONFIG_DISABLE_MATH_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ATAN2, "atan2")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CATCH, "catch")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ARRAY_BUILTIN) \
|
||||
|| !defined (CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EVERY, "every")
|
||||
@ -244,6 +255,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RANDOM, "random")
|
||||
|| !defined (CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REDUCE, "reduce")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REJECT, "reject")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEARCH, "search")
|
||||
#endif
|
||||
@ -294,6 +308,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MESSAGE, "message")
|
||||
#if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPLACE, "replace")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RESOLVE, "resolve")
|
||||
#endif
|
||||
#if !defined (CONFIG_DISABLE_ARRAY_BUILTIN) \
|
||||
|| !defined (CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVERSE, "reverse")
|
||||
|
||||
@ -47,6 +47,7 @@ LIT_MAGIC_STRING_LN2_U = "LN2"
|
||||
LIT_MAGIC_STRING_NAN = "NaN"
|
||||
LIT_MAGIC_STRING_UTC_U = "UTC"
|
||||
LIT_MAGIC_STRING_ABS = "abs"
|
||||
LIT_MAGIC_STRING_ALL = "all"
|
||||
LIT_MAGIC_STRING_COS = "cos"
|
||||
LIT_MAGIC_STRING_EXP = "exp"
|
||||
LIT_MAGIC_STRING_GET = "get"
|
||||
@ -80,6 +81,7 @@ LIT_MAGIC_STRING_KEYS = "keys"
|
||||
LIT_MAGIC_STRING_NAME = "name"
|
||||
LIT_MAGIC_STRING_NULL = "null"
|
||||
LIT_MAGIC_STRING_PUSH = "push"
|
||||
LIT_MAGIC_STRING_RACE = "race"
|
||||
LIT_MAGIC_STRING_SEAL = "seal"
|
||||
LIT_MAGIC_STRING_SOME = "some"
|
||||
LIT_MAGIC_STRING_SORT = "sort"
|
||||
@ -94,6 +96,7 @@ LIT_MAGIC_STRING_LOG2E_U = "LOG2E"
|
||||
LIT_MAGIC_STRING_SQRT2_U = "SQRT2"
|
||||
LIT_MAGIC_STRING_APPLY = "apply"
|
||||
LIT_MAGIC_STRING_ATAN2 = "atan2"
|
||||
LIT_MAGIC_STRING_CATCH = "catch"
|
||||
LIT_MAGIC_STRING_EVERY = "every"
|
||||
LIT_MAGIC_STRING_FALSE = "false"
|
||||
LIT_MAGIC_STRING_FLOOR = "floor"
|
||||
@ -130,6 +133,7 @@ LIT_MAGIC_STRING_NUMBER = "number"
|
||||
LIT_MAGIC_STRING_OBJECT = "object"
|
||||
LIT_MAGIC_STRING_RANDOM = "random"
|
||||
LIT_MAGIC_STRING_REDUCE = "reduce"
|
||||
LIT_MAGIC_STRING_REJECT = "reject"
|
||||
LIT_MAGIC_STRING_SEARCH = "search"
|
||||
LIT_MAGIC_STRING_SOURCE = "source"
|
||||
LIT_MAGIC_STRING_SPLICE = "splice"
|
||||
@ -149,6 +153,7 @@ LIT_MAGIC_STRING_INDEX_OF_UL = "indexOf"
|
||||
LIT_MAGIC_STRING_IS_ARRAY_UL = "isArray"
|
||||
LIT_MAGIC_STRING_MESSAGE = "message"
|
||||
LIT_MAGIC_STRING_REPLACE = "replace"
|
||||
LIT_MAGIC_STRING_RESOLVE = "resolve"
|
||||
LIT_MAGIC_STRING_REVERSE = "reverse"
|
||||
LIT_MAGIC_STRING_SET_DATE_UL = "setDate"
|
||||
LIT_MAGIC_STRING_SET_TIME_UL = "setTime"
|
||||
|
||||
@ -13,4 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
assert (Promise.prototype.length === 1);
|
||||
Promise.resolve("abc").then(function(x)
|
||||
{
|
||||
assert (x === "abc");
|
||||
});
|
||||
|
||||
@ -13,24 +13,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var obj = {name:""};
|
||||
var a = new Promise(function(f)
|
||||
{
|
||||
var o = {name: "abc"};
|
||||
f(o);
|
||||
})
|
||||
|
||||
var a = new Promise(function(f, r){
|
||||
obj.name = obj.name + "a";
|
||||
f(obj);
|
||||
Promise.resolve(a).then(function(x)
|
||||
{
|
||||
assert (x.name === "abc");
|
||||
});
|
||||
|
||||
a.then(function(x) {
|
||||
x.name = x.name + "b";
|
||||
return x;
|
||||
}).then(null, function(x) {
|
||||
x.name = x.name + "c"; // unreachable
|
||||
return x;
|
||||
}).then(function(x) {
|
||||
x.name = x.name + "d";
|
||||
assert (obj.name === "aebd");
|
||||
});
|
||||
|
||||
obj.name = obj.name + "e";
|
||||
|
||||
assert (obj.name === "ae")
|
||||
|
||||
@ -13,24 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var a = new Promise(function(f, r){
|
||||
r(0);
|
||||
Promise.reject("abc").then(function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
}, function(x)
|
||||
{
|
||||
assert (x === "abc");
|
||||
});
|
||||
|
||||
a
|
||||
.then(function f1(x) {
|
||||
return x + 1; // unreachable
|
||||
}, function r1(x){
|
||||
return x + 10;
|
||||
})
|
||||
.then(function f2(x) {
|
||||
throw x + 100
|
||||
})
|
||||
.then(function f3(x) {
|
||||
return x + 1000 //unreachable
|
||||
}, function r3(x) {
|
||||
return x + 10000
|
||||
})
|
||||
.then(function(x) {
|
||||
assert (x === 10110);
|
||||
})
|
||||
|
||||
@ -13,14 +13,37 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var a = new Promise(function(f, r){
|
||||
f("a");
|
||||
var a = Promise.resolve('a');
|
||||
var b = Promise.reject('b');
|
||||
|
||||
Promise.race([a, b]).then(function(x)
|
||||
{
|
||||
assert (x === 'a');
|
||||
}, function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
});
|
||||
|
||||
var b = new Promise(function(f, r){
|
||||
f(a);
|
||||
})
|
||||
Promise.race([b, a]).then(function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
}, function(x)
|
||||
{
|
||||
assert (x === 'b');
|
||||
});
|
||||
|
||||
b.then(function(x) {
|
||||
assert (x === "a");
|
||||
})
|
||||
Promise.race([ ,b, a]).then(function(x)
|
||||
{
|
||||
assert (x === undefined);
|
||||
}, function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
});
|
||||
|
||||
Promise.race(a).then(function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
}, function(x)
|
||||
{
|
||||
assert(x.name === "TypeError");
|
||||
});
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var a = Promise.resolve('a');
|
||||
var b = Promise.resolve('b');
|
||||
var c = Promise.reject('c');
|
||||
|
||||
Promise.all([a, b, 1]).then(function(x)
|
||||
{
|
||||
assert (x[0] === 'a');
|
||||
assert (x[1] === 'b');
|
||||
assert (x[2] === 1);
|
||||
}, function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
});
|
||||
|
||||
Promise.all([a, b, c, 1]).then(function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
}, function(x)
|
||||
{
|
||||
assert (x === 'c');
|
||||
});
|
||||
|
||||
Promise.all([]).then(function(x)
|
||||
{
|
||||
assert (x.length === 0);
|
||||
}, function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
});
|
||||
|
||||
Promise.all(a).then(function(x)
|
||||
{
|
||||
assert (false); // should not run here.
|
||||
}, function(x)
|
||||
{
|
||||
assert(x.name === "TypeError");
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
assert (Promise.prototype.length === 1);
|
||||
@ -0,0 +1,36 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var obj = {name:""};
|
||||
|
||||
var a = new Promise(function(f, r){
|
||||
obj.name = obj.name + "a";
|
||||
f(obj);
|
||||
});
|
||||
|
||||
a.then(function(x) {
|
||||
x.name = x.name + "b";
|
||||
return x;
|
||||
}).then(null, function(x) {
|
||||
x.name = x.name + "c"; // unreachable
|
||||
return x;
|
||||
}).then(function(x) {
|
||||
x.name = x.name + "d";
|
||||
assert (obj.name === "aebd");
|
||||
});
|
||||
|
||||
obj.name = obj.name + "e";
|
||||
|
||||
assert (obj.name === "ae")
|
||||
@ -0,0 +1,36 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var a = new Promise(function(f, r){
|
||||
r(0);
|
||||
});
|
||||
|
||||
a
|
||||
.then(function f1(x) {
|
||||
return x + 1; // unreachable
|
||||
}, function r1(x){
|
||||
return x + 10;
|
||||
})
|
||||
.then(function f2(x) {
|
||||
throw x + 100
|
||||
})
|
||||
.then(function f3(x) {
|
||||
return x + 1000 //unreachable
|
||||
}, function r3(x) {
|
||||
return x + 10000
|
||||
})
|
||||
.then(function(x) {
|
||||
assert (x === 10110);
|
||||
})
|
||||
@ -0,0 +1,26 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var a = new Promise(function(f, r){
|
||||
f("a");
|
||||
});
|
||||
|
||||
var b = new Promise(function(f, r){
|
||||
f(a);
|
||||
})
|
||||
|
||||
b.then(function(x) {
|
||||
assert (x === "a");
|
||||
})
|
||||
@ -0,0 +1,22 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
Promise.reject("abc").catch(function(x)
|
||||
{
|
||||
assert (x === "abc");
|
||||
return "def";
|
||||
}).then(function(x) {
|
||||
assert (x === "def");
|
||||
});
|
||||
15
tests/jerry/es2015/regression-test-issue-1763.js
Normal file
15
tests/jerry/es2015/regression-test-issue-1763.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright JS Foundation and other contributors, http://js.foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
new Promise(Math.max.propertyIsEnumerable.toString).then()
|
||||
Loading…
x
Reference in New Issue
Block a user