Add promise C API (#1796)

Add API: jerry_create_promise, jerry_value_is_promise and jerry_resolve_or_reject_promise.

related issue: 1794

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
Zidong Jiang
2017-05-04 16:13:26 +08:00
committed by GitHub
parent 240411771a
commit ede13835b2
11 changed files with 457 additions and 24 deletions
@@ -683,7 +683,7 @@ ecma_builtin_promise_dispatch_construct (const ecma_value_t *arguments_list_p, /
return ecma_raise_type_error (ECMA_ERR_MSG ("First parameter must be callable."));
}
return ecma_op_create_promise_object (arguments_list_p[0], true);
return ecma_op_create_promise_object (arguments_list_p[0], ECMA_PROMISE_EXECUTOR_FUNCTION);
} /* ecma_builtin_promise_dispatch_construct */
/**
+10 -5
View File
@@ -223,10 +223,14 @@ ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be opera
{
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_string_t str_resolve, str_reject;
ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION);
ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);
ecma_value_t argv[] = { funcs->resolve, funcs->reject };
ecma_value_t resolve = ecma_op_object_get (promise_p, &str_resolve);
ecma_value_t reject = ecma_op_object_get (promise_p, &str_reject);
ecma_value_t argv[] = { resolve, 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,
@@ -237,7 +241,7 @@ ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be opera
if (ECMA_IS_VALUE_ERROR (then_call_result))
{
ret = ecma_op_function_call (ecma_get_object_from_value (funcs->reject),
ret = ecma_op_function_call (ecma_get_object_from_value (reject),
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
&then_call_result,
1);
@@ -245,7 +249,8 @@ ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be opera
ecma_free_value (then_call_result);
}
ecma_promise_free_resolving_functions (funcs);
ecma_free_value (resolve);
ecma_free_value (reject);
ecma_free_promise_resolve_thenable_job (job_p);
return ret;
@@ -404,7 +404,7 @@ ecma_call_builtin_executor (ecma_object_t *executor_p, /**< the executor object
*
* @return pointer to the resolving functions
*/
ecma_promise_resolving_functions_t *
static ecma_promise_resolving_functions_t *
ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promise object */
{
/* 1. */
@@ -455,7 +455,7 @@ ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promi
/**
* Free the heap and the member of the resolving functions.
*/
void
static void
ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs) /**< points to the functions */
{
ecma_free_value (funcs->resolve);
@@ -473,7 +473,7 @@ ecma_promise_free_resolving_functions (ecma_promise_resolving_functions_t *funcs
*/
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 */
ecma_promise_executor_type_t type) /**< indicates the type of executor */
{
/* 3. */
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE_PROTOTYPE);
@@ -496,10 +496,22 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
/* 8. */
ecma_promise_resolving_functions_t *funcs = ecma_promise_create_resolving_functions (object_p);
/* 9. */
ecma_value_t completion;
ecma_string_t str_resolve, str_reject;
ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION);
ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);
ecma_op_object_put (object_p,
&str_resolve,
funcs->resolve,
false);
ecma_op_object_put (object_p,
&str_reject,
funcs->reject,
false);
if (is_func)
/* 9. */
ecma_value_t completion = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
if (type == ECMA_PROMISE_EXECUTOR_FUNCTION)
{
JERRY_ASSERT (ecma_op_is_callable (executor));
@@ -509,7 +521,7 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
argv,
2);
}
else
else if (type == ECMA_PROMISE_EXECUTOR_OBJECT)
{
JERRY_ASSERT (ecma_is_value_object (executor));
@@ -517,6 +529,11 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
funcs->resolve,
funcs->reject);
}
else
{
JERRY_ASSERT (type == ECMA_PROMISE_EXECUTOR_EMPTY);
JERRY_UNUSED (executor);
}
ecma_value_t status = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
@@ -572,7 +589,7 @@ ecma_promise_new_capability (void)
false);
/* 6. */
ecma_value_t promise = ecma_op_create_promise_object (executor, false);
ecma_value_t promise = ecma_op_create_promise_object (executor, ECMA_PROMISE_EXECUTOR_OBJECT);
/* 10. */
ecma_op_object_put (capability_p,
@@ -37,6 +37,16 @@ typedef enum
ECMA_PROMISE_STATE__COUNT /**< number of states */
} ecma_promise_state_t;
/**
* Indicates the type of the executor in promise construct.
*/
typedef enum
{
ECMA_PROMISE_EXECUTOR_FUNCTION, /**< the executor is a function, it is for the usual constructor */
ECMA_PROMISE_EXECUTOR_OBJECT, /**< the executor is an object, it is for the `then` routine */
ECMA_PROMISE_EXECUTOR_EMPTY /**< the executor is empty, it is for external C API */
} ecma_promise_executor_type_t;
/**
* Description of the promise resolving functions.
*/
@@ -81,10 +91,7 @@ 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_op_create_promise_object (ecma_value_t executor, ecma_promise_executor_type_t type);
ecma_value_t ecma_promise_new_capability (void);
ecma_value_t
ecma_promise_then (ecma_value_t promise,
+86
View File
@@ -29,6 +29,7 @@
#include "ecma-literal-storage.h"
#include "ecma-objects.h"
#include "ecma-objects-general.h"
#include "ecma-promise-object.h"
#include "jcontext.h"
#include "jerryscript.h"
#include "jerry-debugger.h"
@@ -552,6 +553,25 @@ jerry_value_is_object (const jerry_value_t value) /**< api value */
return ecma_is_value_object (value);
} /* jerry_value_is_object */
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
/**
* Check if the specified value is promise.
*
* @return true - if the specified value is promise,
* false - otherwise
*/
bool
jerry_value_is_promise (const jerry_value_t value) /**< api value */
{
jerry_assert_api_available ();
return (ecma_is_value_object (value)
&& ecma_is_promise (ecma_get_object_from_value (value)));
} /* jerry_value_is_promise */
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
/**
* Check if the specified value is string.
*
@@ -1018,6 +1038,27 @@ jerry_create_object (void)
return ecma_make_object_value (ecma_op_create_object_object_noarg ());
} /* jerry_create_object */
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
/**
* Create an empty Promise object which can be resolve/reject later
* by calling jerry_resolve_or_reject_promise.
*
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return value of the created object
*/
jerry_value_t
jerry_create_promise (void)
{
jerry_assert_api_available ();
return ecma_op_create_promise_object (ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY), ECMA_PROMISE_EXECUTOR_EMPTY);
} /* jerry_create_promise */
#endif /* CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
/**
* Create string from a valid UTF-8 string
*
@@ -2120,6 +2161,51 @@ jerry_foreach_object_property (const jerry_value_t obj_val, /**< object value */
return false;
} /* jerry_foreach_object_property */
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
/**
* Resolve or reject the promise with an argument.
*
* @return undefined value - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value */
jerry_value_t argument, /**< the argument */
bool is_resolve) /**< whether the promise should be resolved or rejected */
{
jerry_assert_api_available ();
if (!ecma_is_value_object (promise) || !ecma_is_promise (ecma_get_object_from_value (promise)))
{
return ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p));
}
ecma_string_t str;
if (is_resolve)
{
ecma_init_ecma_magic_string (&str, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION);
}
else
{
ecma_init_ecma_magic_string (&str, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);
}
ecma_value_t function = ecma_op_object_get (ecma_get_object_from_value (promise), &str);
ecma_value_t ret = ecma_op_function_call (ecma_get_object_from_value (function),
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
&argument,
1);
ecma_free_value (function);
return ret;
} /* jerry_resolve_or_reject_promise */
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
/**
* Validate UTF-8 string
*
+7
View File
@@ -251,6 +251,7 @@ bool jerry_value_is_function (const jerry_value_t value);
bool jerry_value_is_number (const jerry_value_t value);
bool jerry_value_is_null (const jerry_value_t value);
bool jerry_value_is_object (const jerry_value_t value);
bool jerry_value_is_promise (const jerry_value_t value);
bool jerry_value_is_string (const jerry_value_t value);
bool jerry_value_is_undefined (const jerry_value_t value);
@@ -332,6 +333,7 @@ jerry_value_t jerry_create_number_infinity (bool sign);
jerry_value_t jerry_create_number_nan (void);
jerry_value_t jerry_create_null (void);
jerry_value_t jerry_create_object (void);
jerry_value_t jerry_create_promise (void);
jerry_value_t jerry_create_string_from_utf8 (const jerry_char_t *str_p);
jerry_value_t jerry_create_string_sz_from_utf8 (const jerry_char_t *str_p, jerry_size_t str_size);
jerry_value_t jerry_create_string (const jerry_char_t *str_p);
@@ -387,6 +389,11 @@ void jerry_set_object_native_pointer (const jerry_value_t obj_val,
bool jerry_foreach_object_property (const jerry_value_t obj_val, jerry_object_property_foreach_t foreach_p,
void *user_data_p);
/**
* Promise resolve/reject functions.
*/
jerry_value_t jerry_resolve_or_reject_promise (jerry_value_t promise, jerry_value_t argument, bool is_resolve);
/**
* Input validator functions.
*/
+2
View File
@@ -38,6 +38,8 @@ typedef enum
LIT_INTERNAL_MAGIC_STRING_PROMISE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< [[Promise]] of promise
* reject or resolve functions */
LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED, /**< [[AlreadyResolved]] of promise reject or resolve functions */
LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION, /**< the resolve funtion of the promise object */
LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION, /**< the reject function of the promise object */
LIT_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