Add notification callback for Promise operations (#4595)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -30,6 +30,7 @@ set(JERRY_MEM_STATS OFF CACHE BOOL "Enable memory sta
|
||||
set(JERRY_MEM_GC_BEFORE_EACH_ALLOC OFF CACHE BOOL "Enable mem-stress test?")
|
||||
set(JERRY_PARSER_DUMP_BYTE_CODE OFF CACHE BOOL "Enable parser byte-code dumps?")
|
||||
set(JERRY_PROFILE "es.next" CACHE STRING "Use default or other profile?")
|
||||
set(JERRY_PROMISE_CALLBACK OFF CACHE BOOL "Enable Promise callbacks?")
|
||||
set(JERRY_REGEXP_STRICT_MODE OFF CACHE BOOL "Enable regexp strict mode?")
|
||||
set(JERRY_REGEXP_DUMP_BYTE_CODE OFF CACHE BOOL "Enable regexp byte-code dumps?")
|
||||
set(JERRY_SNAPSHOT_EXEC OFF CACHE BOOL "Enable executing snapshot files?")
|
||||
@@ -87,6 +88,7 @@ message(STATUS "JERRY_MEM_STATS " ${JERRY_MEM_STATS})
|
||||
message(STATUS "JERRY_MEM_GC_BEFORE_EACH_ALLOC " ${JERRY_MEM_GC_BEFORE_EACH_ALLOC})
|
||||
message(STATUS "JERRY_PARSER_DUMP_BYTE_CODE " ${JERRY_PARSER_DUMP_BYTE_CODE} ${JERRY_PARSER_DUMP_MESSAGE})
|
||||
message(STATUS "JERRY_PROFILE " ${JERRY_PROFILE})
|
||||
message(STATUS "JERRY_PROMISE_CALLBACK " ${JERRY_PROMISE_CALLBACK})
|
||||
message(STATUS "JERRY_REGEXP_STRICT_MODE " ${JERRY_REGEXP_STRICT_MODE})
|
||||
message(STATUS "JERRY_REGEXP_DUMP_BYTE_CODE " ${JERRY_REGEXP_DUMP_BYTE_CODE})
|
||||
message(STATUS "JERRY_SNAPSHOT_EXEC " ${JERRY_SNAPSHOT_EXEC} ${JERRY_SNAPSHOT_EXEC_MESSAGE})
|
||||
@@ -582,6 +584,9 @@ else()
|
||||
message(FATAL_ERROR "Profile file: '${JERRY_PROFILE}' doesn't exist!")
|
||||
endif()
|
||||
|
||||
# Promise callback
|
||||
jerry_add_define01(JERRY_PROMISE_CALLBACK)
|
||||
|
||||
# RegExp strict mode
|
||||
jerry_add_define01(JERRY_REGEXP_STRICT_MODE)
|
||||
|
||||
|
||||
+24
-1
@@ -1467,6 +1467,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
|
||||
#if JERRY_BUILTIN_REALMS
|
||||
|| feature == JERRY_FEATURE_REALM
|
||||
#endif /* JERRY_BUILTIN_REALMS */
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
|| feature == JERRY_FEATURE_PROMISE_CALLBACK
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
);
|
||||
} /* jerry_is_feature_enabled */
|
||||
|
||||
@@ -2194,7 +2197,7 @@ jerry_create_promise (void)
|
||||
JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE);
|
||||
}
|
||||
|
||||
ecma_value_t promise_value = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_PROMISE_EXECUTOR_EMPTY);
|
||||
ecma_value_t promise_value = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED);
|
||||
|
||||
JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
|
||||
return promise_value;
|
||||
@@ -4353,6 +4356,26 @@ jerry_get_promise_state (const jerry_value_t promise) /**< promise object to get
|
||||
#endif /* JERRY_BUILTIN_PROMISE */
|
||||
} /* jerry_get_promise_state */
|
||||
|
||||
/**
|
||||
* Sets a callback for tracking Promise and async operations.
|
||||
*
|
||||
* Note:
|
||||
* the previous callback is overwritten
|
||||
*/
|
||||
void jerry_promise_set_callback (jerry_promise_callback_t callback, /**< notification callback */
|
||||
void *user_p) /**< user pointer passed to the callback */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_PROMISE && JERRY_PROMISE_CALLBACK
|
||||
JERRY_CONTEXT (promise_callback) = callback;
|
||||
JERRY_CONTEXT (promise_callback_user_p) = user_p;
|
||||
#else /* !JERRY_BUILTIN_PROMISE && !JERRY_PROMISE_CALLBACK */
|
||||
JERRY_UNUSED (callback);
|
||||
JERRY_UNUSED (user_p);
|
||||
#endif /* JERRY_BUILTIN_PROMISE && JERRY_PROMISE_CALLBACK */
|
||||
} /* jerry_promise_set_callback */
|
||||
|
||||
/**
|
||||
* Get the well-knwon symbol represented by the given `symbol` enum value.
|
||||
*
|
||||
|
||||
+21
-1
@@ -348,6 +348,15 @@
|
||||
# define JERRY_PROPRETY_HASHMAP 1
|
||||
#endif /* !defined (JERRY_PROPRETY_HASHMAP) */
|
||||
|
||||
/**
|
||||
* Enables/disables the Promise event callbacks
|
||||
*
|
||||
* Default value: 0
|
||||
*/
|
||||
#ifndef JERRY_PROMISE_CALLBACK
|
||||
# define JERRY_PROMISE_CALLBACK 0
|
||||
#endif /* !defined (JERRY_PROMISE_CALLBACK) */
|
||||
|
||||
/**
|
||||
* Enable/Disable byte code dump functions for RegExp objects.
|
||||
* To dump the RegExp byte code the engine must be initialized with
|
||||
@@ -666,6 +675,10 @@
|
||||
|| ((JERRY_PROPRETY_HASHMAP != 0) && (JERRY_PROPRETY_HASHMAP != 1))
|
||||
# error "Invalid value for 'JERRY_PROPRETY_HASHMAP' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_PROMISE_CALLBACK) \
|
||||
|| ((JERRY_PROMISE_CALLBACK != 0) && (JERRY_PROMISE_CALLBACK != 1))
|
||||
# error "Invalid value for 'JERRY_PROMISE_CALLBACK' macro."
|
||||
#endif
|
||||
#if !defined (JERRY_REGEXP_DUMP_BYTE_CODE) \
|
||||
|| ((JERRY_REGEXP_DUMP_BYTE_CODE != 0) && (JERRY_REGEXP_DUMP_BYTE_CODE != 1))
|
||||
# error "Invalid value for 'JERRY_REGEXP_DUMP_BYTE_CODE' macro."
|
||||
@@ -702,14 +715,21 @@
|
||||
/**
|
||||
* Cross component requirements check.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The date module can only use the float 64 number types.
|
||||
* Do a check for this.
|
||||
*/
|
||||
#if JERRY_BUILTIN_DATE && !JERRY_NUMBER_TYPE_FLOAT64
|
||||
# error "Date does not support float32"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Promise support must be enabled if Promise callback support is enabled.
|
||||
*/
|
||||
#if JERRY_PROMISE_CALLBACK && !JERRY_BUILTIN_PROMISE
|
||||
# error "Promise callback support depends on Promise support"
|
||||
#endif /* JERRY_PROMISE_CALLBACK && !JERRY_BUILTIN_PROMISE */
|
||||
|
||||
/**
|
||||
* Wrap container types into a single guard
|
||||
*/
|
||||
|
||||
@@ -375,7 +375,7 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_value_t iterable, /**< the items to be resolved */
|
||||
bool is_race) /**< indicates whether it is race function */
|
||||
{
|
||||
ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg);
|
||||
ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg, ECMA_VALUE_UNDEFINED);
|
||||
|
||||
if (JERRY_UNLIKELY (capability_obj_p == NULL))
|
||||
{
|
||||
@@ -455,7 +455,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], ECMA_PROMISE_EXECUTOR_FUNCTION);
|
||||
return ecma_op_create_promise_object (arguments_list_p[0], ECMA_VALUE_UNDEFINED);
|
||||
} /* ecma_builtin_promise_dispatch_construct */
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,7 +57,7 @@ ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p,
|
||||
|
||||
ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
|
||||
JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE);
|
||||
ecma_value_t result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_PROMISE_EXECUTOR_EMPTY);
|
||||
ecma_value_t result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED);
|
||||
JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
|
||||
task_p->promise = result;
|
||||
|
||||
|
||||
@@ -186,6 +186,17 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the
|
||||
LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY));
|
||||
ecma_promise_capabality_t *capability_p;
|
||||
capability_p = (ecma_promise_capabality_t *) ecma_get_object_from_value (job_p->capability);
|
||||
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB,
|
||||
capability_p->header.u.class_prop.u.promise,
|
||||
ECMA_VALUE_UNDEFINED,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
/* 3. */
|
||||
ecma_value_t handler = job_p->handler;
|
||||
|
||||
@@ -232,6 +243,17 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the
|
||||
}
|
||||
|
||||
ecma_free_value (handler_result);
|
||||
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_AFTER_REACTION_JOB,
|
||||
capability_p->header.u.class_prop.u.promise,
|
||||
ECMA_VALUE_UNDEFINED,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
ecma_free_promise_reaction_job (job_p);
|
||||
|
||||
return status;
|
||||
@@ -246,6 +268,23 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the
|
||||
static ecma_value_t
|
||||
ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_p) /**< the job to be operated */
|
||||
{
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
jerry_promise_event_type_t type = JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE;
|
||||
|
||||
if (ecma_job_queue_get_type (&job_p->header) == ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED)
|
||||
{
|
||||
type = JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT;
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (promise_callback) (type,
|
||||
job_p->executable_object,
|
||||
job_p->argument,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (job_p->executable_object);
|
||||
vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
|
||||
|
||||
@@ -284,6 +323,8 @@ ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t result;
|
||||
|
||||
if (executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD)
|
||||
{
|
||||
job_p->argument = ecma_await_continue (executable_object_p, job_p->argument);
|
||||
@@ -297,9 +338,8 @@ ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_
|
||||
{
|
||||
/* Continue iteration. */
|
||||
JERRY_ASSERT (job_p->argument == ECMA_VALUE_UNDEFINED);
|
||||
|
||||
ecma_free_promise_async_reaction_job (job_p);
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
result = ECMA_VALUE_UNDEFINED;
|
||||
goto free_job;
|
||||
}
|
||||
|
||||
if (ECMA_AWAIT_GET_STATE (executable_object_p) <= ECMA_AWAIT_YIELD_END)
|
||||
@@ -316,7 +356,7 @@ ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_
|
||||
executable_object_p->extended_object.u.class_prop.extra_info &= ECMA_AWAIT_CLEAR_MASK;
|
||||
}
|
||||
|
||||
ecma_value_t result = opfunc_resume_executable_object (executable_object_p, job_p->argument);
|
||||
result = opfunc_resume_executable_object (executable_object_p, job_p->argument);
|
||||
/* Argument reference has been taken by opfunc_resume_executable_object. */
|
||||
job_p->argument = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
@@ -327,6 +367,25 @@ ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_
|
||||
result = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
free_job:
|
||||
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
jerry_promise_event_type_t type = JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE;
|
||||
|
||||
if (ecma_job_queue_get_type (&job_p->header) == ECMA_JOB_PROMISE_ASYNC_REACTION_REJECTED)
|
||||
{
|
||||
type = JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT;
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (promise_callback) (type,
|
||||
job_p->executable_object,
|
||||
job_p->argument,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
ecma_free_promise_async_reaction_job (job_p);
|
||||
return result;
|
||||
} /* ecma_process_promise_async_reaction_job */
|
||||
|
||||
@@ -211,6 +211,16 @@ ecma_reject_promise (ecma_value_t promise, /**< promise */
|
||||
|
||||
JERRY_ASSERT (ecma_promise_get_flags (obj_p) & ECMA_PROMISE_IS_PENDING);
|
||||
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_REJECT,
|
||||
promise,
|
||||
reason,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
ecma_promise_set_state (obj_p, false);
|
||||
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;
|
||||
@@ -272,6 +282,16 @@ ecma_fulfill_promise (ecma_value_t promise, /**< promise */
|
||||
ecma_free_value (then);
|
||||
}
|
||||
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_RESOLVE,
|
||||
promise,
|
||||
value,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
ecma_promise_set_state (obj_p, true);
|
||||
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;
|
||||
@@ -301,9 +321,10 @@ ecma_promise_reject_handler (ecma_object_t *function_obj_p, /**< function object
|
||||
const uint32_t args_count) /**< argument number */
|
||||
{
|
||||
ecma_promise_resolver_t *function_p = (ecma_promise_resolver_t *) function_obj_p;
|
||||
ecma_value_t promise = function_p->promise;
|
||||
|
||||
/* 1. */
|
||||
ecma_object_t *promise_obj_p = ecma_get_object_from_value (function_p->promise);
|
||||
ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise);
|
||||
JERRY_ASSERT (ecma_is_promise (promise_obj_p));
|
||||
|
||||
/* 3., 4. */
|
||||
@@ -314,7 +335,7 @@ ecma_promise_reject_handler (ecma_object_t *function_obj_p, /**< function object
|
||||
|
||||
/* 6. */
|
||||
ecma_value_t reject_value = (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0];
|
||||
ecma_reject_promise (function_p->promise, reject_value);
|
||||
ecma_reject_promise (promise, reject_value);
|
||||
}
|
||||
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
@@ -333,9 +354,10 @@ ecma_promise_resolve_handler (ecma_object_t *function_obj_p, /**< function objec
|
||||
const uint32_t args_count) /**< argument number */
|
||||
{
|
||||
ecma_promise_resolver_t *function_p = (ecma_promise_resolver_t *) function_obj_p;
|
||||
ecma_value_t promise = function_p->promise;
|
||||
|
||||
/* 1. */
|
||||
ecma_object_t *promise_obj_p = ecma_get_object_from_value (function_p->promise);
|
||||
ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise);
|
||||
JERRY_ASSERT (ecma_is_promise (promise_obj_p));
|
||||
|
||||
/* 3., 4. */
|
||||
@@ -344,14 +366,14 @@ ecma_promise_resolve_handler (ecma_object_t *function_obj_p, /**< function objec
|
||||
/* 5. */
|
||||
((ecma_extended_object_t *) promise_obj_p)->u.class_prop.extra_info |= ECMA_PROMISE_ALREADY_RESOLVED;
|
||||
|
||||
ecma_fulfill_promise (function_p->promise, (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0]);
|
||||
ecma_fulfill_promise (promise, (args_count == 0) ? ECMA_VALUE_UNDEFINED : args_p[0]);
|
||||
}
|
||||
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
} /* ecma_promise_resolve_handler */
|
||||
|
||||
/**
|
||||
* Helper function for PromiseCreateResovingFucntions.
|
||||
* Helper function for PromiseCreateResolvingFunctions.
|
||||
*
|
||||
* See also: ES2015 25.4.1.3 2. - 7.
|
||||
*
|
||||
@@ -370,7 +392,7 @@ ecma_promise_create_resolving_functions_helper (ecma_object_t *promise_p, /**< P
|
||||
} /* ecma_promise_create_resolving_functions_helper */
|
||||
|
||||
/**
|
||||
* Create a PromiseCreateResovingFucntions.
|
||||
* Perform PromiseCreateResolvingFunctions.
|
||||
*
|
||||
* See also: ES2015 25.4.1.3
|
||||
*
|
||||
@@ -401,10 +423,12 @@ ecma_promise_create_resolving_functions (ecma_promise_object_t *promise_p) /**<
|
||||
* 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 */
|
||||
ecma_promise_executor_type_t type) /**< indicates the type of executor */
|
||||
ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function or ECMA_VALUE_EMPTY */
|
||||
ecma_value_t parent) /**< parent promise if available */
|
||||
{
|
||||
JERRY_UNUSED (parent);
|
||||
JERRY_ASSERT (JERRY_CONTEXT (current_new_target_p) != NULL);
|
||||
|
||||
/* 3. */
|
||||
ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target_p),
|
||||
ECMA_BUILTIN_ID_PROMISE_PROTOTYPE);
|
||||
@@ -437,10 +461,20 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
|
||||
|
||||
ecma_promise_create_resolving_functions (promise_object_p);
|
||||
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_CREATE,
|
||||
ecma_make_object_value (object_p),
|
||||
parent,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
/* 9. */
|
||||
ecma_value_t completion = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
if (type == ECMA_PROMISE_EXECUTOR_FUNCTION)
|
||||
if (executor != ECMA_VALUE_EMPTY)
|
||||
{
|
||||
JERRY_ASSERT (ecma_op_is_callable (executor));
|
||||
|
||||
@@ -450,11 +484,6 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
|
||||
argv,
|
||||
2);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (type == ECMA_PROMISE_EXECUTOR_EMPTY);
|
||||
JERRY_UNUSED (executor);
|
||||
}
|
||||
|
||||
ecma_value_t status = ECMA_VALUE_EMPTY;
|
||||
|
||||
@@ -479,7 +508,6 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
|
||||
|
||||
/* 11. */
|
||||
ecma_free_value (status);
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_promise_object */
|
||||
|
||||
@@ -614,7 +642,8 @@ ecma_op_get_capabilities_executor_cb (ecma_object_t *function_obj_p, /**< functi
|
||||
* new PromiseCapability object - otherwise
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_promise_new_capability (ecma_value_t constructor)
|
||||
ecma_promise_new_capability (ecma_value_t constructor, /**< constructor function */
|
||||
ecma_value_t parent) /**< parent promise if available */
|
||||
{
|
||||
/* 1. */
|
||||
if (!ecma_is_constructor (constructor))
|
||||
@@ -646,10 +675,22 @@ ecma_promise_new_capability (ecma_value_t constructor)
|
||||
|
||||
/* 7. */
|
||||
ecma_value_t executor = ecma_make_object_value (executor_p);
|
||||
ecma_value_t promise = ecma_op_function_construct (constructor_obj_p,
|
||||
constructor_obj_p,
|
||||
&executor,
|
||||
1);
|
||||
ecma_value_t promise;
|
||||
|
||||
if (constructor_obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE))
|
||||
{
|
||||
ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
|
||||
JERRY_CONTEXT (current_new_target_p) = constructor_obj_p;
|
||||
|
||||
promise = ecma_op_create_promise_object (executor, parent);
|
||||
|
||||
JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
promise = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &executor, 1);
|
||||
}
|
||||
|
||||
ecma_deref_object (executor_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (promise))
|
||||
@@ -723,7 +764,7 @@ ecma_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */
|
||||
}
|
||||
}
|
||||
|
||||
ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg);
|
||||
ecma_object_t *capability_obj_p = ecma_promise_new_capability (this_arg, ECMA_VALUE_UNDEFINED);
|
||||
|
||||
if (JERRY_UNLIKELY (capability_obj_p == NULL))
|
||||
{
|
||||
@@ -868,7 +909,7 @@ ecma_promise_then (ecma_value_t promise, /**< the promise which call 'then' */
|
||||
return species;
|
||||
}
|
||||
|
||||
ecma_object_t *result_capability_obj_p = ecma_promise_new_capability (species);
|
||||
ecma_object_t *result_capability_obj_p = ecma_promise_new_capability (species, promise);
|
||||
ecma_free_value (species);
|
||||
|
||||
if (JERRY_UNLIKELY (result_capability_obj_p == NULL))
|
||||
@@ -1104,6 +1145,16 @@ void
|
||||
ecma_promise_async_then (ecma_value_t promise, /**< promise object */
|
||||
ecma_value_t executable_object) /**< executable object of the async function */
|
||||
{
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
|
||||
{
|
||||
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_ASYNC_AWAIT,
|
||||
executable_object,
|
||||
promise,
|
||||
JERRY_CONTEXT (promise_callback_user_p));
|
||||
}
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
|
||||
ecma_object_t *promise_obj_p = ecma_get_object_from_value (promise);
|
||||
uint16_t flags = ecma_promise_get_flags (promise_obj_p);
|
||||
|
||||
|
||||
@@ -37,15 +37,6 @@ typedef enum
|
||||
ECMA_PROMISE_HANDLED = (1 << 3), /**< ES11: 25.6.6 [[PromiseIsHandled]] internal slot */
|
||||
} ecma_promise_flags_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_EMPTY /**< the executor is empty, it is for external C API */
|
||||
} ecma_promise_executor_type_t;
|
||||
|
||||
/**
|
||||
* Description of a promise resolving function.
|
||||
*/
|
||||
@@ -104,12 +95,12 @@ typedef struct
|
||||
*/
|
||||
|
||||
bool ecma_is_promise (ecma_object_t *obj_p);
|
||||
ecma_value_t ecma_op_create_promise_object (ecma_value_t executor, ecma_promise_executor_type_t type);
|
||||
ecma_value_t ecma_op_create_promise_object (ecma_value_t executor, ecma_value_t parent);
|
||||
uint16_t ecma_promise_get_flags (ecma_object_t *promise_p);
|
||||
ecma_value_t ecma_promise_get_result (ecma_object_t *promise_p);
|
||||
void ecma_reject_promise (ecma_value_t promise, ecma_value_t reason);
|
||||
void ecma_fulfill_promise (ecma_value_t promise, ecma_value_t value);
|
||||
ecma_object_t *ecma_promise_new_capability (ecma_value_t constructor);
|
||||
ecma_object_t *ecma_promise_new_capability (ecma_value_t constructor, ecma_value_t parent);
|
||||
ecma_value_t ecma_promise_reject_or_resolve (ecma_value_t this_arg, ecma_value_t value, bool is_resolve);
|
||||
ecma_value_t ecma_promise_then (ecma_value_t promise, ecma_value_t on_fulfilled, ecma_value_t on_rejected);
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ typedef enum
|
||||
JERRY_FEATURE_BIGINT, /**< BigInt support */
|
||||
JERRY_FEATURE_REALM, /**< realm support */
|
||||
JERRY_FEATURE_GLOBAL_THIS, /**< GlobalThisValue support */
|
||||
JERRY_FEATURE_PROMISE_CALLBACK, /**< Promise callback support */
|
||||
JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */
|
||||
} jerry_feature_t;
|
||||
|
||||
@@ -726,9 +727,11 @@ bool jerry_foreach_object_property (const jerry_value_t obj_val, jerry_object_pr
|
||||
jerry_value_t jerry_object_get_property_names (const jerry_value_t obj_val, jerry_property_filter_t filter);
|
||||
jerry_value_t jerry_from_property_descriptor (const jerry_property_descriptor_t *src_prop_desc_p);
|
||||
jerry_value_t jerry_to_property_descriptor (jerry_value_t obj_value, jerry_property_descriptor_t *out_prop_desc_p);
|
||||
|
||||
/**
|
||||
* Promise functions.
|
||||
*/
|
||||
|
||||
jerry_value_t jerry_resolve_or_reject_promise (jerry_value_t promise, jerry_value_t argument, bool is_resolve);
|
||||
|
||||
/**
|
||||
@@ -745,6 +748,53 @@ typedef enum
|
||||
jerry_value_t jerry_get_promise_result (const jerry_value_t promise);
|
||||
jerry_promise_state_t jerry_get_promise_state (const jerry_value_t promise);
|
||||
|
||||
/**
|
||||
* Event types for jerry_promise_callback_t callback function.
|
||||
* The description of the 'object' and 'value' arguments are provided for each type.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_PROMISE_EVENT_CREATE = 0u, /**< a new Promise object is created
|
||||
* object: the new Promise object
|
||||
* value: parent Promise for `then` chains, undefined otherwise */
|
||||
JERRY_PROMISE_EVENT_RESOLVE, /**< called when a Promise is about to be resolved
|
||||
* object: the Promise object
|
||||
* value: value for resolving */
|
||||
JERRY_PROMISE_EVENT_REJECT, /**< called when a Promise is about to be rejected
|
||||
* object: the Promise object
|
||||
* value: value for rejecting */
|
||||
JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB, /**< called before executing a Promise reaction job
|
||||
* object: the Promise object
|
||||
* value: undefined */
|
||||
JERRY_PROMISE_EVENT_AFTER_REACTION_JOB, /**< called after a Promise reaction job is completed
|
||||
* object: the Promise object
|
||||
* value: undefined */
|
||||
JERRY_PROMISE_EVENT_ASYNC_AWAIT, /**< called when an async function awaits the result of a Promise object
|
||||
* object: internal object representing the execution status
|
||||
* value: the Promise object */
|
||||
JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE, /**< called when an async function is continued with resolve
|
||||
* object: internal object representing the execution status
|
||||
* value: value for resolving */
|
||||
JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT, /**< called when an async function is continued with reject
|
||||
* object: internal object representing the execution status
|
||||
* value: value for rejecting */
|
||||
JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE, /**< called when an async function resolve is completed
|
||||
* object: internal object representing the execution status
|
||||
* value: value for resolving */
|
||||
JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT, /**< called when an async function reject is completed
|
||||
* object: internal object representing the execution status
|
||||
* value: value for rejecting */
|
||||
} jerry_promise_event_type_t;
|
||||
|
||||
/**
|
||||
* Notification callback for tracking Promise and async function operations.
|
||||
*/
|
||||
typedef void (*jerry_promise_callback_t) (jerry_promise_event_type_t event_type,
|
||||
const jerry_value_t object, const jerry_value_t value,
|
||||
void *user_p);
|
||||
|
||||
void jerry_promise_set_callback (jerry_promise_callback_t callback, void *user_p);
|
||||
|
||||
/**
|
||||
* Symbol functions.
|
||||
*/
|
||||
|
||||
@@ -183,6 +183,10 @@ struct jerry_context_t
|
||||
#if JERRY_BUILTIN_PROMISE
|
||||
ecma_job_queue_item_t *job_queue_head_p; /**< points to the head item of the job queue */
|
||||
ecma_job_queue_item_t *job_queue_tail_p; /**< points to the tail item of the job queue */
|
||||
#if JERRY_PROMISE_CALLBACK
|
||||
void *promise_callback_user_p; /**< user pointer for promise callback */
|
||||
jerry_promise_callback_t promise_callback; /**< user function for tracking Promise object operations */
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
#endif /* JERRY_BUILTIN_PROMISE */
|
||||
|
||||
#if JERRY_VM_EXEC_STOP
|
||||
|
||||
@@ -901,7 +901,7 @@ opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context *
|
||||
ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
|
||||
JERRY_CONTEXT (current_new_target_p) = promise_p;
|
||||
|
||||
result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_PROMISE_EXECUTOR_EMPTY);
|
||||
result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (result));
|
||||
executable_object_p->frame_ctx.block_result = result;
|
||||
|
||||
+1
-1
@@ -2719,7 +2719,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
|
||||
JERRY_CONTEXT (current_new_target_p) = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE);
|
||||
|
||||
result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_PROMISE_EXECUTOR_EMPTY);
|
||||
result = ecma_op_create_promise_object (ECMA_VALUE_EMPTY, ECMA_VALUE_UNDEFINED);
|
||||
|
||||
JERRY_CONTEXT (current_new_target_p) = old_new_target_p;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user