Implement the basic Promise (#1695)
Implement the Promise Constructor and routine: 'then' JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
@@ -34,6 +34,9 @@
|
|||||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||||
#include "ecma-typedarray-object.h"
|
#include "ecma-typedarray-object.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
#include "ecma-promise-object.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define JERRY_INTERNAL
|
#define JERRY_INTERNAL
|
||||||
#include "jerry-internal.h"
|
#include "jerry-internal.h"
|
||||||
@@ -177,7 +180,7 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair
|
|||||||
case ECMA_PROPERTY_TYPE_NAMEDDATA:
|
case ECMA_PROPERTY_TYPE_NAMEDDATA:
|
||||||
{
|
{
|
||||||
if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_STRING_CONTAINER_MAGIC_STRING
|
if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_STRING_CONTAINER_MAGIC_STRING
|
||||||
&& property_pair_p->names_cp[index] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT)
|
&& property_pair_p->names_cp[index] >= LIT_NEED_MARK_MAGIC_STRING__COUNT)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -260,6 +263,41 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
|
|
||||||
switch (ecma_get_object_type (object_p))
|
switch (ecma_get_object_type (object_p))
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
case ECMA_OBJECT_TYPE_CLASS:
|
||||||
|
{
|
||||||
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||||
|
|
||||||
|
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_PROMISE_UL)
|
||||||
|
{
|
||||||
|
/* Mark promise result. */
|
||||||
|
ecma_value_t result = ext_object_p->u.class_prop.u.value;
|
||||||
|
|
||||||
|
if (ecma_is_value_object (result))
|
||||||
|
{
|
||||||
|
ecma_gc_set_object_visited (ecma_get_object_from_value (result), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark all reactions. */
|
||||||
|
ecma_collection_iterator_t iter;
|
||||||
|
ecma_collection_iterator_init (&iter, ((ecma_promise_object_t *) ext_object_p)->fulfill_reactions);
|
||||||
|
|
||||||
|
while (ecma_collection_iterator_next (&iter))
|
||||||
|
{
|
||||||
|
ecma_gc_set_object_visited (ecma_get_object_from_value (*iter.current_value_p), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_collection_iterator_init (&iter, ((ecma_promise_object_t *) ext_object_p)->reject_reactions);
|
||||||
|
|
||||||
|
while (ecma_collection_iterator_next (&iter))
|
||||||
|
{
|
||||||
|
ecma_gc_set_object_visited (ecma_get_object_from_value (*iter.current_value_p), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /*! CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||||
{
|
{
|
||||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||||
@@ -274,14 +312,14 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
ecma_gc_set_object_visited (lex_env_p, true);
|
ecma_gc_set_object_visited (lex_env_p, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||||
case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
|
case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
|
||||||
case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
|
case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_typedarray_get_arraybuffer (object_p), true);
|
ecma_gc_set_object_visited (ecma_typedarray_get_arraybuffer (object_p), true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
JERRY_UNREACHABLE ();
|
JERRY_UNREACHABLE ();
|
||||||
@@ -528,7 +566,18 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
|||||||
ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, size);
|
ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
case LIT_MAGIC_STRING_PROMISE_UL:
|
||||||
|
{
|
||||||
|
ecma_free_value_if_not_object (ext_object_p->u.class_prop.u.value);
|
||||||
|
ecma_free_values_collection (((ecma_promise_object_t *) object_p)->fulfill_reactions, false);
|
||||||
|
ecma_free_values_collection (((ecma_promise_object_t *) object_p)->reject_reactions, false);
|
||||||
|
ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, sizeof (ecma_promise_object_t));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
JERRY_UNREACHABLE ();
|
JERRY_UNREACHABLE ();
|
||||||
|
|||||||
@@ -191,6 +191,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL,
|
|||||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
OBJECT_VALUE (LIT_MAGIC_STRING_PROMISE_UL,
|
||||||
|
ECMA_BUILTIN_ID_PROMISE,
|
||||||
|
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
|
|
||||||
/* Routine properties:
|
/* Routine properties:
|
||||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ecma-exceptions.h"
|
||||||
|
#include "ecma-globals.h"
|
||||||
|
#include "ecma-helpers.h"
|
||||||
|
#include "ecma-promise-object.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
|
||||||
|
#define ECMA_BUILTINS_INTERNAL
|
||||||
|
#include "ecma-builtins-internal.h"
|
||||||
|
|
||||||
|
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise-prototype.inc.h"
|
||||||
|
#define BUILTIN_UNDERSCORED_ID promise_prototype
|
||||||
|
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||||
|
|
||||||
|
/** \addtogroup ecma ECMA
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \addtogroup ecmabuiltins
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \addtogroup promiseprototype ECMA Promise.prototype object built-in
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Promise routine: then.
|
||||||
|
*
|
||||||
|
* See also: 25.4.5.3
|
||||||
|
*
|
||||||
|
* @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;
|
||||||
|
} /* ecma_builtin_promise_prototype_then */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||||
|
|
||||||
|
/* Object properties:
|
||||||
|
* (property name, object pointer getter) */
|
||||||
|
|
||||||
|
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
|
||||||
|
ECMA_BUILTIN_ID_PROMISE,
|
||||||
|
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||||
|
|
||||||
|
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||||
|
1,
|
||||||
|
ECMA_PROPERTY_FLAG_WRITABLE)
|
||||||
|
|
||||||
|
ROUTINE (LIT_MAGIC_STRING_THEN, ecma_builtin_promise_prototype_then, 2, 2)
|
||||||
|
|
||||||
|
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ecma-exceptions.h"
|
||||||
|
#include "ecma-function-object.h"
|
||||||
|
#include "ecma-globals.h"
|
||||||
|
#include "ecma-promise-object.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
|
||||||
|
#define ECMA_BUILTINS_INTERNAL
|
||||||
|
#include "ecma-builtins-internal.h"
|
||||||
|
|
||||||
|
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-promise.inc.h"
|
||||||
|
#define BUILTIN_UNDERSCORED_ID promise
|
||||||
|
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||||
|
|
||||||
|
/** \addtogroup ecma ECMA
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \addtogroup ecmabuiltins
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \addtogroup promise ECMA Promise object built-in
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle calling [[Call]] of built-in Promise object.
|
||||||
|
*
|
||||||
|
* ES2015 25.4.3 Promise is not intended to be called
|
||||||
|
* as a function and will throw an exception when called
|
||||||
|
* in that manner.
|
||||||
|
*
|
||||||
|
* @return ecma value
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
ecma_builtin_promise_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||||
|
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||||
|
|
||||||
|
return ecma_raise_type_error (ECMA_ERR_MSG ("Constructor Promise requires 'new'."));
|
||||||
|
} /* ecma_builtin_promise_dispatch_call */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle calling [[Construct]] of built-in Promise object.
|
||||||
|
*
|
||||||
|
* @return ecma value
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
ecma_builtin_promise_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||||
|
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||||
|
|
||||||
|
if (arguments_list_len == 0 || !ecma_op_is_callable (arguments_list_p[0]))
|
||||||
|
{
|
||||||
|
return ecma_raise_type_error (ECMA_ERR_MSG ("First parameter must be callable."));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ecma_op_create_promise_object (arguments_list_p[0], true);
|
||||||
|
} /* ecma_builtin_promise_dispatch_construct */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Promose built-in description
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||||
|
|
||||||
|
/* Number properties:
|
||||||
|
* (property name, number value, writable, enumerable, configurable) */
|
||||||
|
|
||||||
|
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||||
|
1,
|
||||||
|
ECMA_PROPERTY_FIXED)
|
||||||
|
|
||||||
|
/* Object properties:
|
||||||
|
* (property name, object pointer getter) */
|
||||||
|
|
||||||
|
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
|
||||||
|
ECMA_BUILTIN_ID_PROMISE_PROTOTYPE,
|
||||||
|
ECMA_PROPERTY_FIXED)
|
||||||
|
|
||||||
|
/* Routine properties:
|
||||||
|
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||||
|
|
||||||
|
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
||||||
@@ -462,6 +462,24 @@ BUILTIN (ECMA_BUILTIN_ID_UINT8CLAMPEDARRAY,
|
|||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
|
||||||
|
BUILTIN (ECMA_BUILTIN_ID_PROMISE_PROTOTYPE,
|
||||||
|
ECMA_OBJECT_TYPE_GENERAL,
|
||||||
|
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
promise_prototype)
|
||||||
|
|
||||||
|
BUILTIN (ECMA_BUILTIN_ID_PROMISE,
|
||||||
|
ECMA_OBJECT_TYPE_FUNCTION,
|
||||||
|
ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
promise)
|
||||||
|
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
|
|
||||||
/* The Global object (15.1) */
|
/* The Global object (15.1) */
|
||||||
BUILTIN (ECMA_BUILTIN_ID_GLOBAL,
|
BUILTIN (ECMA_BUILTIN_ID_GLOBAL,
|
||||||
ECMA_OBJECT_TYPE_GENERAL,
|
ECMA_OBJECT_TYPE_GENERAL,
|
||||||
|
|||||||
@@ -13,9 +13,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "ecma-function-object.h"
|
||||||
#include "ecma-globals.h"
|
#include "ecma-globals.h"
|
||||||
#include "ecma-helpers.h"
|
#include "ecma-helpers.h"
|
||||||
#include "ecma-jobqueue.h"
|
#include "ecma-jobqueue.h"
|
||||||
|
#include "ecma-objects.h"
|
||||||
|
#include "ecma-promise-object.h"
|
||||||
#include "jerry-port.h"
|
#include "jerry-port.h"
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
@@ -28,26 +31,243 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The processor for PromiseReactionJob
|
* Description of the PromiseReactionJob
|
||||||
*/
|
*/
|
||||||
static ecma_value_t __attribute__ ((unused))
|
typedef struct
|
||||||
ecma_job_process_promise_reaction_job (void *job_p) /**< the job to be operated */
|
|
||||||
{
|
{
|
||||||
JERRY_UNUSED (job_p);
|
ecma_value_t reaction; /**< the PromiseReaction */
|
||||||
/** TODO: implement the function body */
|
ecma_value_t argument; /**< argument for the reaction */
|
||||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
} ecma_job_promise_reaction_t;
|
||||||
} /* ecma_job_process_promise_reaction_job */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The processor for PromiseResolveThenableJob
|
* Description of the PromiseResolveThenableJob
|
||||||
*/
|
*/
|
||||||
static ecma_value_t __attribute__ ((unused))
|
typedef struct
|
||||||
ecma_job_process_promise_thenable_job (void *job_p) /**< the job to be operated */
|
|
||||||
{
|
{
|
||||||
JERRY_UNUSED (job_p);
|
ecma_value_t promise; /**< promise to be resolved */
|
||||||
/** TODO: implement the function body */
|
ecma_value_t thenable; /**< thenbale object */
|
||||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
ecma_value_t then; /** 'then' function */
|
||||||
} /* ecma_job_process_promise_thenable_job */
|
} ecma_job_promise_resolve_thenable_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PromiseReactionJob.
|
||||||
|
*
|
||||||
|
* @return pointer to the PromiseReactionJob
|
||||||
|
*/
|
||||||
|
static ecma_job_promise_reaction_t *
|
||||||
|
ecma_create_promise_reaction_job (ecma_value_t reaction, /**< PromiseReaction */
|
||||||
|
ecma_value_t argument) /**< argument for the reaction */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_value_object (reaction));
|
||||||
|
|
||||||
|
ecma_job_promise_reaction_t *job_p;
|
||||||
|
job_p = (ecma_job_promise_reaction_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_reaction_t));
|
||||||
|
job_p->reaction = ecma_copy_value (reaction);
|
||||||
|
job_p->argument = ecma_copy_value (argument);
|
||||||
|
|
||||||
|
return job_p;
|
||||||
|
} /* ecma_create_promise_reaction_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the heap and the member of the PromiseReactionJob.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ecma_free_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< points to the PromiseReactionJob */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (job_p != NULL);
|
||||||
|
|
||||||
|
ecma_free_value (job_p->reaction);
|
||||||
|
ecma_free_value (job_p->argument);
|
||||||
|
|
||||||
|
jmem_heap_free_block (job_p, sizeof (ecma_job_promise_reaction_t));
|
||||||
|
} /* ecma_free_promise_reaction_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PromiseResolveThenableJob
|
||||||
|
*
|
||||||
|
* @return pointer to the PromiseResolveThenableJob
|
||||||
|
*/
|
||||||
|
static ecma_job_promise_resolve_thenable_t *
|
||||||
|
ecma_create_promise_resolve_thenable_job (ecma_value_t promise, /**< promise to be resolved */
|
||||||
|
ecma_value_t thenable, /**< thenable object */
|
||||||
|
ecma_value_t then) /**< 'then' function */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise)));
|
||||||
|
JERRY_ASSERT (ecma_is_value_object (thenable));
|
||||||
|
JERRY_ASSERT (ecma_op_is_callable (then));
|
||||||
|
|
||||||
|
ecma_job_promise_resolve_thenable_t *job_p;
|
||||||
|
job_p = (ecma_job_promise_resolve_thenable_t *) jmem_heap_alloc_block (sizeof (ecma_job_promise_resolve_thenable_t));
|
||||||
|
|
||||||
|
job_p->promise = ecma_copy_value (promise);
|
||||||
|
job_p->thenable = ecma_copy_value (thenable);
|
||||||
|
job_p->then = ecma_copy_value (then);
|
||||||
|
|
||||||
|
return job_p;
|
||||||
|
} /* ecma_create_promise_resolve_thenable_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the heap and the member of the PromiseResolveThenableJob.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ecma_free_promise_resolve_thenable_job (ecma_job_promise_resolve_thenable_t *job_p) /**< points to the
|
||||||
|
* PromiseResolveThenableJob */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (job_p != NULL);
|
||||||
|
|
||||||
|
ecma_free_value (job_p->promise);
|
||||||
|
ecma_free_value (job_p->thenable);
|
||||||
|
ecma_free_value (job_p->then);
|
||||||
|
|
||||||
|
jmem_heap_free_block (job_p, sizeof (ecma_job_promise_resolve_thenable_t));
|
||||||
|
} /* ecma_free_promise_resolve_thenable_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The processor for PromiseReactionJob.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.2.1
|
||||||
|
*
|
||||||
|
* @return ecma value
|
||||||
|
* Returned value must be freed with ecma_free_value
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
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);
|
||||||
|
|
||||||
|
JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler));
|
||||||
|
|
||||||
|
ecma_value_t handler_result;
|
||||||
|
|
||||||
|
if (ecma_is_value_boolean (handler))
|
||||||
|
{
|
||||||
|
/* 4-5. True indicates "identity" and false indicates "thrower" */
|
||||||
|
handler_result = ecma_copy_value (job_p->argument);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 6. */
|
||||||
|
handler_result = ecma_op_function_call (ecma_get_object_from_value (handler),
|
||||||
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||||
|
&(job_p->argument),
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_value_t status;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
JERRY_ASSERT (ecma_op_is_callable (reject));
|
||||||
|
|
||||||
|
status = ecma_op_function_call (ecma_get_object_from_value (reject),
|
||||||
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||||
|
&handler_result,
|
||||||
|
1);
|
||||||
|
ecma_free_value (reject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 8. String '1' indicates [[Resolve]] of Capability. */
|
||||||
|
ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_1);
|
||||||
|
|
||||||
|
JERRY_ASSERT (ecma_op_is_callable (resolve));
|
||||||
|
|
||||||
|
status = ecma_op_function_call (ecma_get_object_from_value (resolve),
|
||||||
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||||
|
&handler_result,
|
||||||
|
1);
|
||||||
|
ecma_free_value (resolve);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_free_promise_reaction_job (job_p);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
} /* ecma_process_promise_reaction_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the PromiseResolveThenableJob.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.2.2
|
||||||
|
*
|
||||||
|
* @return ecma value
|
||||||
|
* Returned value must be freed with ecma_free_value
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be operated */
|
||||||
|
{
|
||||||
|
ecma_job_promise_resolve_thenable_t *job_p = (ecma_job_promise_resolve_thenable_t *) obj_p;
|
||||||
|
ecma_object_t *promise_p = ecma_get_object_from_value (job_p->promise);
|
||||||
|
ecma_promise_resolving_functions_t *funcs;
|
||||||
|
funcs = ecma_promise_create_resolving_functions (promise_p);
|
||||||
|
|
||||||
|
ecma_value_t argv[] = { funcs->resolve, funcs->reject };
|
||||||
|
ecma_value_t ret;
|
||||||
|
ecma_value_t then_call_result = ecma_op_function_call (ecma_get_object_from_value (job_p->then),
|
||||||
|
job_p->thenable,
|
||||||
|
argv,
|
||||||
|
2);
|
||||||
|
|
||||||
|
ret = then_call_result;
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (then_call_result))
|
||||||
|
{
|
||||||
|
ret = ecma_op_function_call (ecma_get_object_from_value (funcs->reject),
|
||||||
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||||
|
&then_call_result,
|
||||||
|
1);
|
||||||
|
|
||||||
|
ecma_free_value (then_call_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_promise_free_resolving_functions (funcs);
|
||||||
|
ecma_free_promise_resolve_thenable_job (job_p);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
} /* ecma_process_promise_resolve_thenable_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a PromiseReactionJob into a jobqueue.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ecma_enqueue_promise_reaction_job (ecma_value_t reaction, /**< PromiseReaction */
|
||||||
|
ecma_value_t argument) /**< argument for the reaction */
|
||||||
|
{
|
||||||
|
ecma_job_promise_reaction_t *job_p = ecma_create_promise_reaction_job (reaction, argument);
|
||||||
|
jerry_port_jobqueue_enqueue (ecma_process_promise_reaction_job, job_p);
|
||||||
|
} /* ecma_enqueue_promise_reaction_job */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a PromiseResolveThenableJob into a jobqueue.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ecma_enqueue_promise_resolve_thenable_job (ecma_value_t promise, /**< promise to be resolved */
|
||||||
|
ecma_value_t thenable, /**< thenable object */
|
||||||
|
ecma_value_t then) /**< 'then' function */
|
||||||
|
{
|
||||||
|
ecma_job_promise_resolve_thenable_t *job_p = ecma_create_promise_resolve_thenable_job (promise,
|
||||||
|
thenable,
|
||||||
|
then);
|
||||||
|
jerry_port_jobqueue_enqueue (ecma_process_promise_resolve_thenable_job, job_p);
|
||||||
|
} /* ecma_enqueue_promise_resolve_thenable_job */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void ecma_enqueue_promise_reaction_job (ecma_value_t reaction, ecma_value_t argument);
|
||||||
|
void ecma_enqueue_promise_resolve_thenable_job (ecma_value_t promise, ecma_value_t thenable, ecma_value_t then);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -0,0 +1,718 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ecma-boolean-object.h"
|
||||||
|
#include "ecma-builtins.h"
|
||||||
|
#include "ecma-exceptions.h"
|
||||||
|
#include "ecma-function-object.h"
|
||||||
|
#include "ecma-gc.h"
|
||||||
|
#include "ecma-globals.h"
|
||||||
|
#include "ecma-helpers.h"
|
||||||
|
#include "ecma-jobqueue.h"
|
||||||
|
#include "ecma-objects.h"
|
||||||
|
#include "ecma-objects-general.h"
|
||||||
|
#include "ecma-promise-object.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
|
||||||
|
/** \addtogroup ecma ECMA
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \addtogroup ecmapromiseobject ECMA Promise object related routines
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an object is promise.
|
||||||
|
*
|
||||||
|
* @return true - if the object is a promise.
|
||||||
|
* false - otherwise.
|
||||||
|
*/
|
||||||
|
inline bool __attr_always_inline___
|
||||||
|
ecma_is_promise (ecma_object_t *obj_p) /**< points to object */
|
||||||
|
{
|
||||||
|
return ecma_object_class_is (obj_p, LIT_MAGIC_STRING_PROMISE_UL);
|
||||||
|
} /* ecma_is_promise */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of the promise.
|
||||||
|
*
|
||||||
|
* @return ecma value of the promise result.
|
||||||
|
* Returned value must be freed with ecma_free_value
|
||||||
|
*/
|
||||||
|
inline ecma_value_t
|
||||||
|
ecma_promise_get_result (ecma_object_t *obj_p) /**< points to promise object */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_promise (obj_p));
|
||||||
|
|
||||||
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||||
|
|
||||||
|
return ecma_copy_value (ext_object_p->u.class_prop.u.value);
|
||||||
|
} /* ecma_promise_get_result */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the PromiseResult of promise.
|
||||||
|
*/
|
||||||
|
inline void __attr_always_inline___
|
||||||
|
ecma_promise_set_result (ecma_object_t *obj_p, /**< points to promise object */
|
||||||
|
ecma_value_t result) /**< the result value */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_promise (obj_p));
|
||||||
|
|
||||||
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||||
|
|
||||||
|
JERRY_ASSERT (ext_object_p->u.class_prop.u.value == ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED));
|
||||||
|
|
||||||
|
ext_object_p->u.class_prop.u.value = result;
|
||||||
|
} /* ecma_promise_set_result */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the PromiseState of promise.
|
||||||
|
*
|
||||||
|
* @return the state's enum value
|
||||||
|
*/
|
||||||
|
inline uint8_t __attr_always_inline___
|
||||||
|
ecma_promise_get_state (ecma_object_t *obj_p) /**< points to promise object */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_promise (obj_p));
|
||||||
|
|
||||||
|
return ((ecma_promise_object_t *) obj_p)->state;
|
||||||
|
} /* ecma_promise_get_state */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the PromiseState of promise.
|
||||||
|
*/
|
||||||
|
inline void __attr_always_inline___
|
||||||
|
ecma_promise_set_state (ecma_object_t *obj_p, /**< points to promise object */
|
||||||
|
uint8_t state) /**< the state */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_promise (obj_p));
|
||||||
|
|
||||||
|
((ecma_promise_object_t *) obj_p)->state = state;
|
||||||
|
} /* ecma_promise_set_state */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the bool value of alreadyResolved.
|
||||||
|
*
|
||||||
|
* @return bool value of alreadyResolved.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ecma_get_already_resolved_bool_value (ecma_value_t already_resolved) /**< the alreadyResolved */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_value_object (already_resolved));
|
||||||
|
|
||||||
|
ecma_object_t *already_resolved_p = ecma_get_object_from_value (already_resolved);
|
||||||
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) already_resolved_p;
|
||||||
|
|
||||||
|
JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_BOOLEAN_UL);
|
||||||
|
|
||||||
|
return ext_object_p->u.class_prop.u.value == ecma_make_boolean_value (true);
|
||||||
|
} /* ecma_get_already_resolved_bool_value */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of alreadyResolved.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ecma_set_already_resolved_value (ecma_value_t already_resolved, /**< the alreadyResolved */
|
||||||
|
bool value) /**< the value to set */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_value_object (already_resolved));
|
||||||
|
|
||||||
|
ecma_object_t *already_resolved_p = ecma_get_object_from_value (already_resolved);
|
||||||
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) already_resolved_p;
|
||||||
|
|
||||||
|
JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_BOOLEAN_UL);
|
||||||
|
|
||||||
|
ext_object_p->u.class_prop.u.value = ecma_make_boolean_value (value);
|
||||||
|
} /* ecma_set_already_resolved_value */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take a collection of Reactions and enqueue a new PromiseReactionJob for each Reaction.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.8
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ecma_promise_trigger_reactions (ecma_collection_header_t *reactions, /**< lists of reactions */
|
||||||
|
ecma_value_t value) /**< value for resolve or reject */
|
||||||
|
{
|
||||||
|
ecma_collection_iterator_t iter;
|
||||||
|
ecma_collection_iterator_init (&iter, reactions);
|
||||||
|
|
||||||
|
while (ecma_collection_iterator_next (&iter))
|
||||||
|
{
|
||||||
|
ecma_enqueue_promise_reaction_job (*iter.current_value_p, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_free_values_collection (reactions, false);
|
||||||
|
} /* ecma_promise_trigger_reactions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject a Promise with a reason.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.7
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ecma_reject_promise (ecma_value_t promise, /**< promise */
|
||||||
|
ecma_value_t reason) /**< reason for reject */
|
||||||
|
{
|
||||||
|
ecma_object_t *obj_p = ecma_get_object_from_value (promise);
|
||||||
|
|
||||||
|
JERRY_ASSERT (ecma_promise_get_state (obj_p) == ECMA_PROMISE_STATE_PENDING);
|
||||||
|
|
||||||
|
ecma_promise_set_state (obj_p, ECMA_PROMISE_STATE_REJECTED);
|
||||||
|
ecma_promise_set_result (obj_p, ecma_copy_value_if_not_object (reason));
|
||||||
|
ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p;
|
||||||
|
ecma_promise_trigger_reactions (promise_p->reject_reactions, reason);
|
||||||
|
promise_p->reject_reactions = ecma_new_values_collection (NULL, 0, false);
|
||||||
|
/* Free all fullfill_reactions. */
|
||||||
|
ecma_free_values_collection (promise_p->fulfill_reactions, false);
|
||||||
|
promise_p->fulfill_reactions = ecma_new_values_collection (NULL, 0, false);
|
||||||
|
} /* ecma_reject_promise */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fulfill a Promise with a value.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.4
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ecma_fulfill_promise (ecma_value_t promise, /**< promise */
|
||||||
|
ecma_value_t value) /**< fulfilled value */
|
||||||
|
{
|
||||||
|
ecma_object_t *obj_p = ecma_get_object_from_value (promise);
|
||||||
|
|
||||||
|
JERRY_ASSERT (ecma_promise_get_state (obj_p) == ECMA_PROMISE_STATE_PENDING);
|
||||||
|
|
||||||
|
ecma_promise_set_state (obj_p, ECMA_PROMISE_STATE_FULFILLED);
|
||||||
|
ecma_promise_set_result (obj_p, ecma_copy_value_if_not_object (value));
|
||||||
|
ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p;
|
||||||
|
ecma_promise_trigger_reactions (promise_p->fulfill_reactions, value);
|
||||||
|
promise_p->fulfill_reactions = ecma_new_values_collection (NULL, 0, false);
|
||||||
|
/* Free all reject_reactions. */
|
||||||
|
ecma_free_values_collection (promise_p->reject_reactions, false);
|
||||||
|
promise_p->reject_reactions = ecma_new_values_collection (NULL, 0, false);
|
||||||
|
} /* ecma_fulfill_promise */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native handler for Promise Reject Function.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.3.1
|
||||||
|
*
|
||||||
|
* @return ecma value of undefined.
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_promise_reject_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_string_t str_promise;
|
||||||
|
ecma_string_t str_already_resolved;
|
||||||
|
ecma_init_ecma_magic_string (&str_promise, LIT_INTERNAL_MAGIC_STRING_PROMISE);
|
||||||
|
ecma_init_ecma_magic_string (&str_already_resolved, LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED);
|
||||||
|
ecma_object_t *function_p = ecma_get_object_from_value (function);
|
||||||
|
/* 2. */
|
||||||
|
ecma_value_t promise = ecma_op_object_get (function_p, &str_promise);
|
||||||
|
/* 1. */
|
||||||
|
JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise)));
|
||||||
|
/* 3. */
|
||||||
|
ecma_value_t already_resolved = ecma_op_object_get (function_p, &str_already_resolved);
|
||||||
|
|
||||||
|
/* 4. */
|
||||||
|
if (ecma_get_already_resolved_bool_value (already_resolved))
|
||||||
|
{
|
||||||
|
ecma_free_value (promise);
|
||||||
|
ecma_free_value (already_resolved);
|
||||||
|
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5. */
|
||||||
|
ecma_set_already_resolved_value (already_resolved, true);
|
||||||
|
/* 6. */
|
||||||
|
ecma_reject_promise (promise, argv[0]);
|
||||||
|
ecma_free_value (promise);
|
||||||
|
ecma_free_value (already_resolved);
|
||||||
|
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||||
|
} /* ecma_promise_reject_handler */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native handler for Promise Resolve Function.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.3.2
|
||||||
|
*
|
||||||
|
* @return ecma value of undefined.
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_promise_resolve_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_string_t str_promise;
|
||||||
|
ecma_string_t str_already_resolved;
|
||||||
|
ecma_init_ecma_magic_string (&str_promise, LIT_INTERNAL_MAGIC_STRING_PROMISE);
|
||||||
|
ecma_init_ecma_magic_string (&str_already_resolved, LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED);
|
||||||
|
ecma_object_t *function_p = ecma_get_object_from_value (function);
|
||||||
|
/* 2. */
|
||||||
|
ecma_value_t promise = ecma_op_object_get (function_p, &str_promise);
|
||||||
|
/* 1. */
|
||||||
|
JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise)));
|
||||||
|
/* 3. */
|
||||||
|
ecma_value_t already_resolved = ecma_op_object_get (function_p, &str_already_resolved);
|
||||||
|
|
||||||
|
/* 4. */
|
||||||
|
if (ecma_get_already_resolved_bool_value (already_resolved))
|
||||||
|
{
|
||||||
|
goto end_of_resolve_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5. */
|
||||||
|
ecma_set_already_resolved_value (already_resolved, true);
|
||||||
|
|
||||||
|
/* 6. */
|
||||||
|
if (argv[0] == promise)
|
||||||
|
{
|
||||||
|
ecma_object_t *error_p = ecma_new_standard_error (ECMA_ERROR_TYPE);
|
||||||
|
ecma_reject_promise (promise, ecma_make_object_value (error_p));
|
||||||
|
ecma_deref_object (error_p);
|
||||||
|
goto end_of_resolve_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 7. */
|
||||||
|
if (!ecma_is_value_object (argv[0]))
|
||||||
|
{
|
||||||
|
ecma_fulfill_promise (promise, argv[0]);
|
||||||
|
goto end_of_resolve_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8. */
|
||||||
|
ecma_string_t *str_then = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_THEN);
|
||||||
|
ecma_value_t then = ecma_op_object_get (ecma_get_object_from_value (argv[0]), str_then);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (then))
|
||||||
|
{
|
||||||
|
/* 9. */
|
||||||
|
ecma_reject_promise (promise, then);
|
||||||
|
}
|
||||||
|
else if (!ecma_op_is_callable (then))
|
||||||
|
{
|
||||||
|
/* 11 .*/
|
||||||
|
ecma_fulfill_promise (promise, argv[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 12 */
|
||||||
|
ecma_enqueue_promise_resolve_thenable_job (promise, argv[0], then);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_deref_ecma_string (str_then);
|
||||||
|
ecma_free_value (then);
|
||||||
|
|
||||||
|
end_of_resolve_function:
|
||||||
|
ecma_free_value (promise);
|
||||||
|
ecma_free_value (already_resolved);
|
||||||
|
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||||
|
} /* ecma_promise_resolve_handler */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CapabilityiesExecutor Function.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.5.1
|
||||||
|
*
|
||||||
|
* @return ecma value of undefined or typerror.
|
||||||
|
* Returned value must be freed with ecma_free_value
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_call_builtin_executor (ecma_object_t *executor_p, /**< the executor object */
|
||||||
|
ecma_value_t resolve_func, /**< the resolve function */
|
||||||
|
ecma_value_t reject_func) /**< the reject function */
|
||||||
|
{
|
||||||
|
ecma_string_t *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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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,
|
||||||
|
resolve_func,
|
||||||
|
false);
|
||||||
|
/* 6. */
|
||||||
|
ecma_op_object_put (ecma_get_object_from_value (capability),
|
||||||
|
str_2,
|
||||||
|
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);
|
||||||
|
|
||||||
|
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||||
|
} /* ecma_call_builtin_executor */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PromiseCreateResovingFucntions.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.3
|
||||||
|
*
|
||||||
|
* @return pointer to the resolving functions
|
||||||
|
*/
|
||||||
|
ecma_promise_resolving_functions_t *
|
||||||
|
ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promise object */
|
||||||
|
{
|
||||||
|
/* 1. */
|
||||||
|
ecma_value_t already_resolved = ecma_op_create_boolean_object (ecma_make_boolean_value (false));
|
||||||
|
|
||||||
|
ecma_string_t str_promise;
|
||||||
|
ecma_string_t str_already_resolved;
|
||||||
|
ecma_init_ecma_magic_string (&str_promise, LIT_INTERNAL_MAGIC_STRING_PROMISE);
|
||||||
|
ecma_init_ecma_magic_string (&str_already_resolved, LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED);
|
||||||
|
/* 2. */
|
||||||
|
ecma_object_t *resolve_p;
|
||||||
|
resolve_p = ecma_op_create_external_function_object ((ecma_external_pointer_t) ecma_promise_resolve_handler);
|
||||||
|
|
||||||
|
/* 3. */
|
||||||
|
ecma_op_object_put (resolve_p,
|
||||||
|
&str_promise,
|
||||||
|
ecma_make_object_value (object_p),
|
||||||
|
false);
|
||||||
|
/* 4. */
|
||||||
|
ecma_op_object_put (resolve_p,
|
||||||
|
&str_already_resolved,
|
||||||
|
already_resolved,
|
||||||
|
false);
|
||||||
|
/* 5. */
|
||||||
|
ecma_object_t *reject_p;
|
||||||
|
reject_p = ecma_op_create_external_function_object ((ecma_external_pointer_t) ecma_promise_reject_handler);
|
||||||
|
/* 6. */
|
||||||
|
ecma_op_object_put (reject_p,
|
||||||
|
&str_promise,
|
||||||
|
ecma_make_object_value (object_p),
|
||||||
|
false);
|
||||||
|
/* 7. */
|
||||||
|
ecma_op_object_put (reject_p,
|
||||||
|
&str_already_resolved,
|
||||||
|
already_resolved,
|
||||||
|
false);
|
||||||
|
|
||||||
|
/* 8. */
|
||||||
|
ecma_promise_resolving_functions_t *funcs = jmem_heap_alloc_block (sizeof (ecma_promise_resolving_functions_t));
|
||||||
|
funcs->resolve = ecma_make_object_value (resolve_p);
|
||||||
|
funcs->reject = ecma_make_object_value (reject_p);
|
||||||
|
|
||||||
|
ecma_free_value (already_resolved);
|
||||||
|
|
||||||
|
return funcs;
|
||||||
|
} /* ecma_promise_create_resolving_functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the heap and the member of the resolving functions.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs) /**< points to the functions */
|
||||||
|
{
|
||||||
|
ecma_free_value (funcs->resolve);
|
||||||
|
ecma_free_value (funcs->reject);
|
||||||
|
jmem_heap_free_block (funcs, sizeof (ecma_promise_resolving_functions_t));
|
||||||
|
} /* ecma_promise_free_resolving_functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a promise object.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.3.1
|
||||||
|
*
|
||||||
|
* @return ecma value of the new promise object
|
||||||
|
* Returned value must be freed with ecma_free_value
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function or object */
|
||||||
|
bool is_func) /**< indicates whether executor is a function */
|
||||||
|
{
|
||||||
|
/* 3. */
|
||||||
|
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE_PROTOTYPE);
|
||||||
|
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||||
|
sizeof (ecma_promise_object_t),
|
||||||
|
ECMA_OBJECT_TYPE_CLASS);
|
||||||
|
ecma_deref_object (prototype_obj_p);
|
||||||
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||||
|
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_PROMISE_UL;
|
||||||
|
ext_object_p->u.class_prop.u.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||||
|
ecma_promise_object_t *promise_object_p = (ecma_promise_object_t *) object_p;
|
||||||
|
promise_object_p->fulfill_reactions = NULL;
|
||||||
|
promise_object_p->reject_reactions = NULL;
|
||||||
|
|
||||||
|
/* 5 */
|
||||||
|
ecma_promise_set_state (object_p, ECMA_PROMISE_STATE_PENDING);
|
||||||
|
/* 6-7. */
|
||||||
|
promise_object_p->fulfill_reactions = ecma_new_values_collection (NULL, 0, false);
|
||||||
|
promise_object_p->reject_reactions = ecma_new_values_collection (NULL, 0, false);
|
||||||
|
/* 8. */
|
||||||
|
ecma_promise_resolving_functions_t *funcs = ecma_promise_create_resolving_functions (object_p);
|
||||||
|
|
||||||
|
/* 9. */
|
||||||
|
ecma_value_t completion;
|
||||||
|
|
||||||
|
if (is_func)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_op_is_callable (executor));
|
||||||
|
|
||||||
|
ecma_value_t argv[] = { funcs->resolve, funcs->reject };
|
||||||
|
completion = ecma_op_function_call (ecma_get_object_from_value (executor),
|
||||||
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||||
|
argv,
|
||||||
|
2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (ecma_is_value_object (executor));
|
||||||
|
|
||||||
|
completion = ecma_call_builtin_executor (ecma_get_object_from_value (executor),
|
||||||
|
funcs->resolve,
|
||||||
|
funcs->reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_value_t status = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (completion))
|
||||||
|
{
|
||||||
|
/* 10.a. */
|
||||||
|
completion = ecma_get_value_from_error_value (completion);
|
||||||
|
status = ecma_op_function_call (ecma_get_object_from_value (funcs->reject),
|
||||||
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||||
|
&completion,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_promise_free_resolving_functions (funcs);
|
||||||
|
ecma_free_value (completion);
|
||||||
|
|
||||||
|
/* 10.b. */
|
||||||
|
if (ECMA_IS_VALUE_ERROR (status))
|
||||||
|
{
|
||||||
|
ecma_deref_object (object_p);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 11. */
|
||||||
|
ecma_free_value (status);
|
||||||
|
|
||||||
|
return ecma_make_object_value (object_p);
|
||||||
|
} /* ecma_op_create_promise_object */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PromiseCapability.
|
||||||
|
*
|
||||||
|
* See also: ES2015 25.4.1.5
|
||||||
|
*
|
||||||
|
* @return ecma value of the new PromiseCapability
|
||||||
|
* Returned value must be freed with ecma_free_value
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
ecma_op_object_put (executor_p,
|
||||||
|
str_0,
|
||||||
|
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. */
|
||||||
|
ecma_op_object_put (capability_p,
|
||||||
|
str_0,
|
||||||
|
promise,
|
||||||
|
false);
|
||||||
|
|
||||||
|
ecma_deref_object (executor_p);
|
||||||
|
ecma_deref_ecma_string (str_0);
|
||||||
|
/* 7. */
|
||||||
|
if (ECMA_IS_VALUE_ERROR (promise))
|
||||||
|
{
|
||||||
|
ecma_free_value (promise);
|
||||||
|
ecma_deref_object (capability_p);
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!ecma_op_is_callable (resolve))
|
||||||
|
{
|
||||||
|
ecma_free_value (resolve);
|
||||||
|
ecma_deref_object (capability_p);
|
||||||
|
return ecma_raise_type_error (ECMA_ERR_MSG ("'resolve' parameter must be callable."));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_free_value (resolve);
|
||||||
|
/* 9. 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);
|
||||||
|
|
||||||
|
if (!ecma_op_is_callable (reject))
|
||||||
|
{
|
||||||
|
ecma_free_value (reject);
|
||||||
|
ecma_deref_object (capability_p);
|
||||||
|
return ecma_raise_type_error (ECMA_ERR_MSG ("'reject' parameter must be callable."));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_free_value (reject);
|
||||||
|
/* 11. */
|
||||||
|
return ecma_make_object_value (capability_p);
|
||||||
|
} /* ecma_promise_new_capability */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It performs the "then" operation on promiFulfilled
|
||||||
|
* and onRejected as its settlement actions.
|
||||||
|
*
|
||||||
|
* See also: 25.4.5.3.1
|
||||||
|
*
|
||||||
|
* @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 */
|
||||||
|
{
|
||||||
|
ecma_string_t *str_0 = ecma_new_ecma_string_from_uint32 (0);
|
||||||
|
ecma_string_t *str_1 = ecma_new_ecma_string_from_uint32 (1);
|
||||||
|
|
||||||
|
/* 3. boolean true indicates "indentity" */
|
||||||
|
if (!ecma_op_is_callable (on_fulfilled))
|
||||||
|
{
|
||||||
|
on_fulfilled = ecma_make_boolean_value (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4. boolean false indicates "thrower" */
|
||||||
|
if (!ecma_op_is_callable (on_rejected))
|
||||||
|
{
|
||||||
|
on_rejected = ecma_make_boolean_value (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5-6. String '0' indicates [[Capability]] of a PromiseReaction, '1' indicates [[Handler]]. */
|
||||||
|
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,
|
||||||
|
result_capability,
|
||||||
|
false);
|
||||||
|
ecma_op_object_put (fulfill_reaction_p,
|
||||||
|
str_1,
|
||||||
|
on_fulfilled,
|
||||||
|
false);
|
||||||
|
|
||||||
|
ecma_op_object_put (reject_reaction_p,
|
||||||
|
str_0,
|
||||||
|
result_capability,
|
||||||
|
false);
|
||||||
|
ecma_op_object_put (reject_reaction_p,
|
||||||
|
str_1,
|
||||||
|
on_rejected,
|
||||||
|
false);
|
||||||
|
|
||||||
|
ecma_object_t *obj_p = ecma_get_object_from_value (promise);
|
||||||
|
ecma_promise_object_t *promise_p = (ecma_promise_object_t *) obj_p;
|
||||||
|
|
||||||
|
if (ecma_promise_get_state (obj_p) == ECMA_PROMISE_STATE_PENDING)
|
||||||
|
{
|
||||||
|
/* 7. */
|
||||||
|
ecma_append_to_values_collection (promise_p->fulfill_reactions,
|
||||||
|
ecma_make_object_value (fulfill_reaction_p),
|
||||||
|
false);
|
||||||
|
|
||||||
|
ecma_append_to_values_collection (promise_p->reject_reactions,
|
||||||
|
ecma_make_object_value (reject_reaction_p),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
else if (ecma_promise_get_state (obj_p) == ECMA_PROMISE_STATE_FULFILLED)
|
||||||
|
{
|
||||||
|
/* 8. */
|
||||||
|
ecma_value_t value = ecma_promise_get_result (obj_p);
|
||||||
|
ecma_enqueue_promise_reaction_job (ecma_make_object_value (fulfill_reaction_p), value);
|
||||||
|
ecma_free_value (value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 9. */
|
||||||
|
ecma_value_t reason = ecma_promise_get_result (obj_p);
|
||||||
|
ecma_enqueue_promise_reaction_job (ecma_make_object_value (reject_reaction_p), reason);
|
||||||
|
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);
|
||||||
|
|
||||||
|
ecma_deref_object (fulfill_reaction_p);
|
||||||
|
ecma_deref_object (reject_reaction_p);
|
||||||
|
ecma_deref_ecma_string (str_0);
|
||||||
|
ecma_deref_ecma_string (str_1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
} /* ecma_promise_then */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ECMA_PROMISE_OBJECT_H
|
||||||
|
#define ECMA_PROMISE_OBJECT_H
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
#include "ecma-globals.h"
|
||||||
|
|
||||||
|
/** \addtogroup ecma ECMA
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* \addtogroup ecmaarraybufferobject ECMA ArrayBuffer object related routines
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PromiseState of promise object.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ECMA_PROMISE_STATE_PENDING, /**< pending state */
|
||||||
|
ECMA_PROMISE_STATE_FULFILLED, /**< fulfilled state */
|
||||||
|
ECMA_PROMISE_STATE_REJECTED, /** rejected state */
|
||||||
|
ECMA_PROMISE_STATE__COUNT /**< number of states */
|
||||||
|
} ecma_promise_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the promise resolving functions.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ecma_value_t resolve; /**< the resolve function */
|
||||||
|
ecma_value_t reject; /**< the reject function */
|
||||||
|
} ecma_promise_resolving_functions_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the promise object.
|
||||||
|
* It need more space than normal object to store builtin properties.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ecma_extended_object_t ecma_extended_object_t; /**< extended object part */
|
||||||
|
uint8_t state; /**< promise state, see ecma_promise_state_t */
|
||||||
|
ecma_collection_header_t *fulfill_reactions; /**< list of PromiseFullfillReactions */
|
||||||
|
ecma_collection_header_t *reject_reactions; /**< list of PromiseRejectReactions */
|
||||||
|
} ecma_promise_object_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);
|
||||||
|
uint8_t ecma_promise_get_state (ecma_object_t *obj_p);
|
||||||
|
void ecma_promise_set_state (ecma_object_t *obj_p, uint8_t state);
|
||||||
|
ecma_value_t
|
||||||
|
ecma_op_create_promise_object (ecma_value_t executor, bool is_func);
|
||||||
|
ecma_promise_resolving_functions_t *
|
||||||
|
ecma_promise_create_resolving_functions (ecma_object_t *obj_p);
|
||||||
|
void ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs);
|
||||||
|
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);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
||||||
|
#endif /* !ECMA_PROMISE_OBJECT_H */
|
||||||
@@ -142,6 +142,8 @@ double jerry_port_get_current_time (void);
|
|||||||
|
|
||||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||||
|
|
||||||
|
#define JERRY_PORT_ENABLE_JOBQUEUE
|
||||||
|
|
||||||
typedef uint32_t (*jerry_job_handler_t) (void *);
|
typedef uint32_t (*jerry_job_handler_t) (void *);
|
||||||
|
|
||||||
void jerry_port_jobqueue_enqueue (jerry_job_handler_t handler, void *job_p);
|
void jerry_port_jobqueue_enqueue (jerry_job_handler_t handler, void *job_p);
|
||||||
|
|||||||
@@ -35,9 +35,13 @@ typedef enum
|
|||||||
#undef LIT_MAGIC_STRING_DEF
|
#undef LIT_MAGIC_STRING_DEF
|
||||||
#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE
|
#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE
|
||||||
LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< number of non-internal magic strings */
|
LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< number of non-internal magic strings */
|
||||||
|
LIT_INTERNAL_MAGIC_STRING_PROMISE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< [[Promise]] of promise
|
||||||
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< native handle package
|
* reject or resolve functions */
|
||||||
* associated with an object */
|
LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED, /**< [[AlreadyResolved]] of promise reject or resolve functions */
|
||||||
|
LIT_NEED_MARK_MAGIC_STRING__COUNT, /**< number of internal magic strings which will be used as properties' names,
|
||||||
|
* and the properties need to be marked during gc. */
|
||||||
|
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE = LIT_NEED_MARK_MAGIC_STRING__COUNT, /**< native handle package
|
||||||
|
* associated with an object */
|
||||||
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< native pointer package associated with an object */
|
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< native pointer package associated with an object */
|
||||||
LIT_MAGIC_STRING__COUNT /**< number of magic strings */
|
LIT_MAGIC_STRING__COUNT /**< number of magic strings */
|
||||||
} lit_magic_string_id_t;
|
} lit_magic_string_id_t;
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SOME, "some")
|
|||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SORT, "sort")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SORT, "sort")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT, "sqrt")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT, "sqrt")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TEST, "test")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TEST, "test")
|
||||||
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_THEN, "then")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM, "trim")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRIM, "trim")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUE, "true")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUE, "true")
|
||||||
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (5, LIT_MAGIC_STRING_ARRAY_UL)
|
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (5, LIT_MAGIC_STRING_ARRAY_UL)
|
||||||
@@ -148,6 +149,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTR, "substr")
|
|||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_JSON_UL, "toJSON")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_JSON_UL, "toJSON")
|
||||||
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_BOOLEAN_UL)
|
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_BOOLEAN_UL)
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN_UL, "Boolean")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN_UL, "Boolean")
|
||||||
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROMISE_UL, "Promise")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT1_2_U, "SQRT1_2")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT1_2_U, "SQRT1_2")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN, "boolean")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN, "boolean")
|
||||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile")
|
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile")
|
||||||
|
|||||||
@@ -648,6 +648,9 @@ main (int argc,
|
|||||||
is_repl_mode = true;
|
is_repl_mode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JERRY_PORT_ENABLE_JOBQUEUE
|
||||||
|
jerry_port_jobqueue_init ();
|
||||||
|
#endif /* JERRY_PORT_ENABLE_JOBQUEUE */
|
||||||
jerry_init (flags);
|
jerry_init (flags);
|
||||||
|
|
||||||
register_js_function ("assert", assert_handler);
|
register_js_function ("assert", assert_handler);
|
||||||
@@ -828,6 +831,15 @@ main (int argc,
|
|||||||
args,
|
args,
|
||||||
1);
|
1);
|
||||||
jerry_release_value (ret_val_print);
|
jerry_release_value (ret_val_print);
|
||||||
|
#ifdef JERRY_PORT_ENABLE_JOBQUEUE
|
||||||
|
jerry_release_value (ret_val_eval);
|
||||||
|
ret_val_eval = jerry_port_jobqueue_run ();
|
||||||
|
|
||||||
|
if (jerry_value_has_error_flag (ret_value))
|
||||||
|
{
|
||||||
|
print_unhandled_exception (ret_value);
|
||||||
|
}
|
||||||
|
#endif /* JERRY_PORT_ENABLE_JOBQUEUE */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -850,7 +862,19 @@ main (int argc,
|
|||||||
|
|
||||||
ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
|
ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||||
}
|
}
|
||||||
|
#ifdef JERRY_PORT_ENABLE_JOBQUEUE
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jerry_release_value (ret_value);
|
||||||
|
ret_value = jerry_port_jobqueue_run ();
|
||||||
|
|
||||||
|
if (jerry_value_has_error_flag (ret_value))
|
||||||
|
{
|
||||||
|
print_unhandled_exception (ret_value);
|
||||||
|
ret_code = JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* JERRY_PORT_ENABLE_JOBQUEUE */
|
||||||
jerry_release_value (ret_value);
|
jerry_release_value (ret_value);
|
||||||
jerry_cleanup ();
|
jerry_cleanup ();
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#include "jmem.h"
|
#include "jmem.h"
|
||||||
#include "jrt.h"
|
#include "jrt.h"
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
#ifdef JERRY_PORT_ENABLE_JOBQUEUE
|
||||||
|
|
||||||
typedef struct jerry_port_queueitem_t jerry_port_queueitem_t;
|
typedef struct jerry_port_queueitem_t jerry_port_queueitem_t;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ struct jerry_port_queueitem_t
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of a job queue (FIFO)
|
* Description of a job queue (FIFO).
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ typedef struct
|
|||||||
static jerry_port_jobqueue_t queue;
|
static jerry_port_jobqueue_t queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the job queue
|
* Initialize the job queue.
|
||||||
*/
|
*/
|
||||||
void jerry_port_jobqueue_init (void)
|
void jerry_port_jobqueue_init (void)
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ void jerry_port_jobqueue_init (void)
|
|||||||
} /* jerry_port_jobqueue_init */
|
} /* jerry_port_jobqueue_init */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enqueue a job
|
* Enqueue a job.
|
||||||
*/
|
*/
|
||||||
void jerry_port_jobqueue_enqueue (jerry_job_handler_t handler, /**< the handler for the job */
|
void jerry_port_jobqueue_enqueue (jerry_job_handler_t handler, /**< the handler for the job */
|
||||||
void *job_p) /**< the job */
|
void *job_p) /**< the job */
|
||||||
@@ -62,41 +62,34 @@ void jerry_port_jobqueue_enqueue (jerry_job_handler_t handler, /**< the handler
|
|||||||
jerry_port_queueitem_t *item_p = jmem_heap_alloc_block (sizeof (jerry_port_queueitem_t));
|
jerry_port_queueitem_t *item_p = jmem_heap_alloc_block (sizeof (jerry_port_queueitem_t));
|
||||||
item_p->job_p = job_p;
|
item_p->job_p = job_p;
|
||||||
item_p->handler = handler;
|
item_p->handler = handler;
|
||||||
|
item_p->next_p = NULL;
|
||||||
|
|
||||||
if (queue.head_p == NULL)
|
if (queue.head_p == NULL)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (queue.tail_p == NULL);
|
|
||||||
|
|
||||||
queue.head_p = item_p;
|
queue.head_p = item_p;
|
||||||
item_p->next_p = NULL;
|
|
||||||
queue.tail_p = item_p;
|
queue.tail_p = item_p;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JERRY_ASSERT (queue.tail_p != NULL);
|
|
||||||
|
|
||||||
queue.tail_p->next_p = item_p;
|
queue.tail_p->next_p = item_p;
|
||||||
queue.tail_p = item_p;
|
queue.tail_p = item_p;
|
||||||
} /* jerry_port_jobqueue_enqueue */
|
} /* jerry_port_jobqueue_enqueue */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dequeue and get the job.
|
* Dequeue and get the job.
|
||||||
* @return pointer to jerry_port_queueitem_t
|
*
|
||||||
* It should be freed with jmem_heap_free_block
|
* @return pointer to jerry_port_queueitem_t.
|
||||||
|
* It should be freed with jmem_heap_free_block.
|
||||||
*/
|
*/
|
||||||
static jerry_port_queueitem_t *
|
static jerry_port_queueitem_t *
|
||||||
jerry_port_jobqueue_dequeue (void)
|
jerry_port_jobqueue_dequeue (void)
|
||||||
{
|
{
|
||||||
if (queue.head_p == NULL)
|
if (queue.head_p == NULL)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (queue.tail_p == NULL);
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JERRY_ASSERT (queue.tail_p != NULL);
|
|
||||||
|
|
||||||
jerry_port_queueitem_t *item_p = queue.head_p;
|
jerry_port_queueitem_t *item_p = queue.head_p;
|
||||||
queue.head_p = queue.head_p->next_p;
|
queue.head_p = queue.head_p->next_p;
|
||||||
|
|
||||||
@@ -105,10 +98,11 @@ jerry_port_jobqueue_dequeue (void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the jobqueue.
|
* Start the jobqueue.
|
||||||
* @return jerry value
|
*
|
||||||
|
* @return jerry value.
|
||||||
* If exception happens in the handler, stop the queue
|
* If exception happens in the handler, stop the queue
|
||||||
* and return the exception.
|
* and return the exception.
|
||||||
* Otherwise, return undefined
|
* Otherwise, return undefined.
|
||||||
*/
|
*/
|
||||||
jerry_value_t
|
jerry_value_t
|
||||||
jerry_port_jobqueue_run (void)
|
jerry_port_jobqueue_run (void)
|
||||||
@@ -138,4 +132,4 @@ jerry_port_jobqueue_run (void)
|
|||||||
}
|
}
|
||||||
} /* jerry_port_jobqueue_run */
|
} /* jerry_port_jobqueue_run */
|
||||||
|
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
#endif /* JERRY_PORT_ENABLE_JOBQUEUE */
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ bool jerry_port_default_is_abort_on_fail (void);
|
|||||||
jerry_log_level_t jerry_port_default_get_log_level (void);
|
jerry_log_level_t jerry_port_default_get_log_level (void);
|
||||||
void jerry_port_default_set_log_level (jerry_log_level_t level);
|
void jerry_port_default_set_log_level (jerry_log_level_t level);
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
#ifdef JERRY_PORT_ENABLE_JOBQUEUE
|
||||||
void jerry_port_jobqueue_init (void);
|
void jerry_port_jobqueue_init (void);
|
||||||
jerry_value_t jerry_port_jobqueue_run (void);
|
jerry_value_t jerry_port_jobqueue_run (void);
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
|
#endif /* JERRY_PORT_ENABLE_JOBQUEUE */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function foo() {};
|
||||||
|
|
||||||
|
var a = new Promise(foo);
|
||||||
|
|
||||||
|
assert (a instanceof Promise);
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/* 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 name1 = "";
|
||||||
|
var name2 = "";
|
||||||
|
var name3 = "";
|
||||||
|
function foo() {};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new Promise();
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
name1 = e.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Promise(foo);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
name2 = e.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new Promise("string");
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
name3 = e.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (name1 === "TypeError");
|
||||||
|
assert (name2 === "TypeError");
|
||||||
|
assert (name3 === "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");
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user