Add filters and more events to Promise callback. (#4605)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2021-02-24 10:31:08 +01:00
committed by GitHub
parent f0f2a28109
commit c27047da03
8 changed files with 307 additions and 29 deletions
+54 -2
View File
@@ -908,6 +908,19 @@ Possible values:
- JERRY_PROMISE_EVENT_REJECT - Called when a Promise is about to be rejected.
- object - the Promise object
- value - value for rejecting.
- JERRY_PROMISE_EVENT_RESOLVE_FULFILLED - Called when a resolve is called on a fulfilled Promise.
- object - the Promise object
- value - value for resolving
- JERRY_PROMISE_EVENT_REJECT_FULFILLED - Called when a reject is called on a fulfilled Promise.
- object - the Promise object
- value - value for rejecting
- JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER - Called when a Promise is rejected without a handler.
- object - the Promise object
- value - value for rejecting
- JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED - Called when a catch handler is added to a rejected
Promise which did not have a catch handler before.
- object - the Promise object
- value - undefined
- JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB - Called before executing a Promise reaction job.
- object - the Promise object
- value - undefined
@@ -938,6 +951,43 @@ Possible values:
- [jerry_promise_set_callback](#jerry_promise_set_callback)
## jerry_promise_event_filter_t
Filter types for [jerry_promise_set_callback](#jerry_promise_set_callback) callback function.
The callback is only called for those events which are enabled by the filters. The events are
described in [jerry_promise_event_type_t](#jerry_promise_event_type_t).
Possible values:
- JERRY_PROMISE_EVENT_FILTER_DISABLE - Disable reporting of all events.
- JERRY_PROMISE_EVENT_FILTER_MAIN - Enables the following events:
- JERRY_PROMISE_EVENT_CREATE
- JERRY_PROMISE_EVENT_RESOLVE
- JERRY_PROMISE_EVENT_REJECT
- JERRY_PROMISE_EVENT_FILTER_ERROR - Enables the following events:
- JERRY_PROMISE_EVENT_RESOLVE_FULFILLED
- JERRY_PROMISE_EVENT_REJECT_FULFILLED
- JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER
- JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED
- JERRY_PROMISE_EVENT_FILTER_REACTION_JOB - Enables the following events:
- JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB
- JERRY_PROMISE_EVENT_AFTER_REACTION_JOB
- JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN - Enables the following events:
- JERRY_PROMISE_EVENT_ASYNC_AWAIT
- JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB - Enables the following events:
- JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE
- JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT
- JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE
- JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT
*New in version [[NEXT_RELEASE]]*.
**See also**
- [jerry_promise_event_type_t](#jerry_promise_event_type_t)
- [jerry_promise_set_callback](#jerry_promise_set_callback)
## jerry_promise_callback_t
**Summary**
@@ -4311,9 +4361,11 @@ Sets a callback for tracking Promise and async operations.
**Prototype**
```c
void jerry_promise_set_callback (jerry_promise_callback_t callback, void *user_p);
void jerry_promise_set_callback (jerry_promise_event_filter_t filters, jerry_promise_callback_t callback,
void *user_p);
```
- `filters` - combination of [jerry_promise_event_filter_t](#jerry_promise_event_filter_t) options
- `callback` - callback function, the previously set value is overwritten,
and setting NULL disables the tracking
- `user_p` - pointer passed to the callback function, can be NULL
@@ -4351,7 +4403,7 @@ main (void)
{
jerry_init (JERRY_INIT_EMPTY);
jerry_promise_set_callback (promise_callback, NULL);
jerry_promise_set_callback (JERRY_PROMISE_EVENT_FILTER_MAIN, promise_callback, NULL);
const char *source_p = "var p = Promise.resolve(0)\n"
"p.then(function (v) { return v; })";
+10 -1
View File
@@ -4358,15 +4358,24 @@ jerry_get_promise_state (const jerry_value_t promise) /**< promise object to get
* Note:
* the previous callback is overwritten
*/
void jerry_promise_set_callback (jerry_promise_callback_t callback, /**< notification callback */
void jerry_promise_set_callback (jerry_promise_event_filter_t filters, /**< combination of event filters */
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
if (filters == JERRY_PROMISE_EVENT_FILTER_DISABLE || callback == NULL)
{
JERRY_CONTEXT (promise_callback_filters) = JERRY_PROMISE_EVENT_FILTER_DISABLE;
return;
}
JERRY_CONTEXT (promise_callback_filters) = (uint32_t) filters;
JERRY_CONTEXT (promise_callback) = callback;
JERRY_CONTEXT (promise_callback_user_p) = user_p;
#else /* !JERRY_BUILTIN_PROMISE && !JERRY_PROMISE_CALLBACK */
JERRY_UNUSED (filters);
JERRY_UNUSED (callback);
JERRY_UNUSED (user_p);
#endif /* JERRY_BUILTIN_PROMISE && JERRY_PROMISE_CALLBACK */
+8 -4
View File
@@ -188,8 +188,9 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the
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))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_REACTION_JOB))
{
JERRY_ASSERT (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,
@@ -245,8 +246,9 @@ 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))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_REACTION_JOB))
{
JERRY_ASSERT (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,
@@ -269,7 +271,7 @@ 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))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB))
{
jerry_promise_event_type_t type = JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE;
@@ -278,6 +280,7 @@ ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_
type = JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT;
}
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (type,
job_p->executable_object,
job_p->argument,
@@ -370,7 +373,7 @@ ecma_process_promise_async_reaction_job (ecma_job_promise_async_reaction_t *job_
free_job:
#if JERRY_PROMISE_CALLBACK
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB))
{
jerry_promise_event_type_t type = JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE;
@@ -379,6 +382,7 @@ free_job:
type = JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT;
}
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (type,
job_p->executable_object,
job_p->argument,
+106 -14
View File
@@ -115,14 +115,18 @@ ecma_promise_set_state (ecma_object_t *obj_p, /**< points to promise object */
* Take a collection of Reactions and enqueue a new PromiseReactionJob for each Reaction.
*
* See also: ES2015 25.4.1.8
*
* @return true - if JERRY_PROMISE_CALLBACK define is 1, and at least one handler is found
* false - otherwise
*/
static void
static bool
ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reactions */
ecma_value_t value, /**< value for resolve or reject */
bool is_reject) /**< true if promise is rejected, false otherwise */
{
ecma_value_t *buffer_p = reactions->buffer_p;
ecma_value_t *buffer_end_p = buffer_p + reactions->item_count;
bool handler_found = false;
while (buffer_p < buffer_end_p)
{
@@ -133,6 +137,9 @@ ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reac
if (JMEM_CP_GET_THIRD_BIT_FROM_POINTER_TAG (object_with_tag))
{
ecma_enqueue_promise_async_reaction_job (object, value, is_reject);
#if JERRY_PROMISE_CALLBACK
handler_found = true;
#endif /* JERRY_PROMISE_CALLBACK */
continue;
}
@@ -143,6 +150,9 @@ ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reac
if (JMEM_CP_GET_FIRST_BIT_FROM_POINTER_TAG (object_with_tag))
{
handler = *buffer_p++;
#if JERRY_PROMISE_CALLBACK
handler_found = true;
#endif /* JERRY_PROMISE_CALLBACK */
}
ecma_enqueue_promise_reaction_job (object, handler, value);
@@ -159,6 +169,9 @@ ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reac
if (JMEM_CP_GET_SECOND_BIT_FROM_POINTER_TAG (object_with_tag))
{
handler = *buffer_p++;
#if JERRY_PROMISE_CALLBACK
handler_found = true;
#endif /* JERRY_PROMISE_CALLBACK */
}
ecma_enqueue_promise_reaction_job (object, handler, value);
@@ -168,6 +181,8 @@ ecma_promise_trigger_reactions (ecma_collection_t *reactions, /**< lists of reac
buffer_p++;
}
}
return handler_found;
} /* ecma_promise_trigger_reactions */
/**
@@ -212,8 +227,9 @@ 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))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_MAIN))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_REJECT,
promise,
reason,
@@ -230,7 +246,23 @@ ecma_reject_promise (ecma_value_t promise, /**< promise */
ecma_collection_t *reactions = promise_p->reactions;
/* Fulfill reactions will never be triggered. */
#if JERRY_PROMISE_CALLBACK
if (!ecma_promise_trigger_reactions (reactions, reason, true))
{
((ecma_extended_object_t *) obj_p)->u.class_prop.extra_info |= ECMA_PROMISE_UNHANDLED_REJECT;
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ERROR))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER,
promise,
reason,
JERRY_CONTEXT (promise_callback_user_p));
}
}
#else /* !JERRY_PROMISE_CALLBACK */
ecma_promise_trigger_reactions (reactions, reason, true);
#endif /* JERRY_PROMISE_CALLBACK */
promise_p->reactions = ecma_new_collection ();
@@ -283,8 +315,9 @@ ecma_fulfill_promise (ecma_value_t promise, /**< promise */
}
#if JERRY_PROMISE_CALLBACK
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_MAIN))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_RESOLVE,
promise,
value,
@@ -324,15 +357,27 @@ ecma_reject_promise_with_checks (ecma_value_t promise, /**< promise */
JERRY_ASSERT (ecma_is_promise (promise_obj_p));
/* 3., 4. */
if (!ecma_is_resolver_already_called (promise_obj_p))
if (JERRY_UNLIKELY (ecma_is_resolver_already_called (promise_obj_p)))
{
/* 5. */
((ecma_extended_object_t *) promise_obj_p)->u.class_prop.extra_info |= ECMA_PROMISE_ALREADY_RESOLVED;
#if JERRY_PROMISE_CALLBACK
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ERROR))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_REJECT_FULFILLED,
promise,
reason,
JERRY_CONTEXT (promise_callback_user_p));
}
#endif /* JERRY_PROMISE_CALLBACK */
/* 6. */
ecma_reject_promise (promise, reason);
return ECMA_VALUE_UNDEFINED;
}
/* 5. */
((ecma_extended_object_t *) promise_obj_p)->u.class_prop.extra_info |= ECMA_PROMISE_ALREADY_RESOLVED;
/* 6. */
ecma_reject_promise (promise, reason);
return ECMA_VALUE_UNDEFINED;
} /* ecma_reject_promise_with_checks */
@@ -352,14 +397,26 @@ ecma_fulfill_promise_with_checks (ecma_value_t promise, /**< promise */
JERRY_ASSERT (ecma_is_promise (promise_obj_p));
/* 3., 4. */
if (!ecma_is_resolver_already_called (promise_obj_p))
if (JERRY_UNLIKELY (ecma_is_resolver_already_called (promise_obj_p)))
{
/* 5. */
((ecma_extended_object_t *) promise_obj_p)->u.class_prop.extra_info |= ECMA_PROMISE_ALREADY_RESOLVED;
#if JERRY_PROMISE_CALLBACK
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ERROR))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_RESOLVE_FULFILLED,
promise,
value,
JERRY_CONTEXT (promise_callback_user_p));
}
#endif /* JERRY_PROMISE_CALLBACK */
ecma_fulfill_promise (promise, value);
return ECMA_VALUE_UNDEFINED;
}
/* 5. */
((ecma_extended_object_t *) promise_obj_p)->u.class_prop.extra_info |= ECMA_PROMISE_ALREADY_RESOLVED;
ecma_fulfill_promise (promise, value);
return ECMA_VALUE_UNDEFINED;
} /* ecma_fulfill_promise_with_checks */
@@ -490,8 +547,9 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function
promise_object_p->reactions = reactions;
#if JERRY_PROMISE_CALLBACK
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback) != NULL))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_MAIN))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_CREATE,
ecma_make_object_value (object_p),
parent,
@@ -886,6 +944,23 @@ ecma_promise_do_then (ecma_value_t promise, /**< the promise which call 'then' *
ecma_track_promise_rejection (promise_obj_p, JERRY_PROMISE_REJECTION_OPERATION_HANDLE);
ecma_enqueue_promise_reaction_job (ecma_make_object_value (result_capability_obj_p), on_rejected, reason);
ecma_free_value (reason);
#if JERRY_PROMISE_CALLBACK
if (on_rejected != ECMA_VALUE_FALSE
&& ecma_promise_get_flags (promise_obj_p) & ECMA_PROMISE_UNHANDLED_REJECT)
{
promise_p->header.u.class_prop.extra_info &= (uint16_t) ~ECMA_PROMISE_UNHANDLED_REJECT;
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ERROR))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED,
promise,
ECMA_VALUE_UNDEFINED,
JERRY_CONTEXT (promise_callback_user_p));
}
}
#endif /* JERRY_PROMISE_CALLBACK */
}
/* ES11: 11. */
@@ -1162,8 +1237,9 @@ 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))
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_ASYNC_AWAIT,
executable_object,
promise,
@@ -1187,6 +1263,22 @@ ecma_promise_async_then (ecma_value_t promise, /**< promise object */
ecma_value_t value = ecma_promise_get_result (promise_obj_p);
ecma_enqueue_promise_async_reaction_job (executable_object, value, !(flags & ECMA_PROMISE_IS_FULFILLED));
ecma_free_value (value);
#if JERRY_PROMISE_CALLBACK
if (ecma_promise_get_flags (promise_obj_p) & ECMA_PROMISE_UNHANDLED_REJECT)
{
((ecma_extended_object_t *) promise_obj_p)->u.class_prop.extra_info &= (uint16_t) ~ECMA_PROMISE_UNHANDLED_REJECT;
if (JERRY_UNLIKELY (JERRY_CONTEXT (promise_callback_filters) & JERRY_PROMISE_EVENT_FILTER_ERROR))
{
JERRY_ASSERT (JERRY_CONTEXT (promise_callback) != NULL);
JERRY_CONTEXT (promise_callback) (JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED,
promise,
ECMA_VALUE_UNDEFINED,
JERRY_CONTEXT (promise_callback_user_p));
}
}
#endif /* JERRY_PROMISE_CALLBACK */
} /* ecma_promise_async_then */
/**
@@ -35,6 +35,9 @@ typedef enum
ECMA_PROMISE_IS_FULFILLED = (1 << 1), /**< fulfilled state */
ECMA_PROMISE_ALREADY_RESOLVED = (1 << 2), /**< already resolved */
ECMA_PROMISE_HANDLED = (1 << 3), /**< ES11: 25.6.6 [[PromiseIsHandled]] internal slot */
#if JERRY_PROMISE_CALLBACK
ECMA_PROMISE_UNHANDLED_REJECT = (1 << 4), /**< a Promise is rejected without a catch handler */
#endif /* JERRY_PROMISE_CALLBACK */
} ecma_promise_flags_t;
/**
+43 -1
View File
@@ -766,6 +766,19 @@ typedef enum
JERRY_PROMISE_EVENT_REJECT, /**< called when a Promise is about to be rejected
* object: the Promise object
* value: value for rejecting */
JERRY_PROMISE_EVENT_RESOLVE_FULFILLED, /**< called when a resolve is called on a fulfilled Promise
* object: the Promise object
* value: value for resolving */
JERRY_PROMISE_EVENT_REJECT_FULFILLED, /**< called when a reject is called on a fulfilled Promise
* object: the Promise object
* value: value for rejecting */
JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER, /**< called when a Promise is rejected without a handler
* object: the Promise object
* value: value for rejecting */
JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED, /**< called when a catch handler is added to a rejected
* Promise which did not have a catch handler before
* object: the Promise object
* value: undefined */
JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB, /**< called before executing a Promise reaction job
* object: the Promise object
* value: undefined */
@@ -789,6 +802,34 @@ typedef enum
* value: value for rejecting */
} jerry_promise_event_type_t;
/**
* Filter types for jerry_promise_set_callback callback function.
* The callback is only called for those events which are enabled by the filters.
*/
typedef enum
{
JERRY_PROMISE_EVENT_FILTER_DISABLE = 0, /**< disable reporting of all events */
JERRY_PROMISE_EVENT_FILTER_MAIN = (1 << 0), /**< enables the following events:
* JERRY_PROMISE_EVENT_CREATE
* JERRY_PROMISE_EVENT_RESOLVE
* JERRY_PROMISE_EVENT_REJECT */
JERRY_PROMISE_EVENT_FILTER_ERROR = (1 << 1), /**< enables the following events:
* JERRY_PROMISE_EVENT_RESOLVE_FULFILLED
* JERRY_PROMISE_EVENT_REJECT_FULFILLED
* JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER
* JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED */
JERRY_PROMISE_EVENT_FILTER_REACTION_JOB = (1 << 2), /**< enables the following events:
* JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB
* JERRY_PROMISE_EVENT_AFTER_REACTION_JOB */
JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN = (1 << 3), /**< enables the following events:
* JERRY_PROMISE_EVENT_ASYNC_AWAIT */
JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB = (1 << 4), /**< enables the following events:
* JERRY_PROMISE_EVENT_ASYNC_BEFORE_RESOLVE
* JERRY_PROMISE_EVENT_ASYNC_BEFORE_REJECT
* JERRY_PROMISE_EVENT_ASYNC_AFTER_RESOLVE
* JERRY_PROMISE_EVENT_ASYNC_AFTER_REJECT */
} jerry_promise_event_filter_t;
/**
* Notification callback for tracking Promise and async function operations.
*/
@@ -796,7 +837,8 @@ 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);
void jerry_promise_set_callback (jerry_promise_event_filter_t filters, jerry_promise_callback_t callback,
void *user_p);
/**
* Symbol functions.
+1
View File
@@ -184,6 +184,7 @@ struct jerry_context_t
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
uint32_t promise_callback_filters; /**< reported event types for 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 */
+82 -7
View File
@@ -23,6 +23,10 @@ typedef enum
C = JERRY_PROMISE_EVENT_CREATE, /**< same as JERRY_PROMISE_CALLBACK_CREATE with undefined value */
RS = JERRY_PROMISE_EVENT_RESOLVE, /**< same as JERRY_PROMISE_CALLBACK_RESOLVE */
RJ = JERRY_PROMISE_EVENT_REJECT, /**< same as JERRY_PROMISE_CALLBACK_REJECT */
RSF = JERRY_PROMISE_EVENT_RESOLVE_FULFILLED, /**< same as JERRY_PROMISE_EVENT_RESOLVE_FULFILLED */
RJF = JERRY_PROMISE_EVENT_REJECT_FULFILLED, /**< same as JERRY_PROMISE_EVENT_REJECT_FULFILLED */
RWH = JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER, /**< same as JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER */
CHA = JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED, /**< same as JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED */
BR = JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB, /**< same as JERRY_PROMISE_CALLBACK_BEFORE_REACTION_JOB */
AR = JERRY_PROMISE_EVENT_AFTER_REACTION_JOB, /**< same as JERRY_PROMISE_CALLBACK_AFTER_REACTION_JOB */
A = JERRY_PROMISE_EVENT_ASYNC_AWAIT, /**< same as JERRY_PROMISE_CALLBACK_ASYNC_AWAIT */
@@ -61,10 +65,14 @@ promise_callback (jerry_promise_event_type_t event_type, /**< event type */
}
case JERRY_PROMISE_EVENT_RESOLVE:
case JERRY_PROMISE_EVENT_REJECT:
case JERRY_PROMISE_EVENT_RESOLVE_FULFILLED:
case JERRY_PROMISE_EVENT_REJECT_FULFILLED:
case JERRY_PROMISE_EVENT_REJECT_WITHOUT_HANDLER:
{
TEST_ASSERT (jerry_value_is_promise (object));
break;
}
case JERRY_PROMISE_EVENT_CATCH_HANDLER_ADDED:
case JERRY_PROMISE_EVENT_BEFORE_REACTION_JOB:
case JERRY_PROMISE_EVENT_AFTER_REACTION_JOB:
{
@@ -126,7 +134,13 @@ main (void)
jerry_init (JERRY_INIT_EMPTY);
jerry_promise_set_callback (promise_callback, (void *) &user);
jerry_promise_event_filter_t filters = (JERRY_PROMISE_EVENT_FILTER_MAIN
| JERRY_PROMISE_EVENT_FILTER_ERROR
| JERRY_PROMISE_EVENT_FILTER_REACTION_JOB
| JERRY_PROMISE_EVENT_FILTER_ASYNC_MAIN
| JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB);
jerry_promise_set_callback (filters, promise_callback, (void *) &user);
/* Test promise creation. */
static uint8_t events1[] = { C, C, C, E };
@@ -155,7 +169,7 @@ main (void)
"promise.then(() => {})\n");
/* Test resolve and reject calls. */
static uint8_t events4[] = { C, C, RS, RJ, E };
static uint8_t events4[] = { C, C, RS, RJ, RWH, E };
run_eval (events4,
"'use strict'\n"
@@ -191,10 +205,10 @@ main (void)
"Promise.resolve(4).then(() => {})\n");
/* Test Promise.reject. */
static uint8_t events8[] = { C, RJ, CP, BR, RJ, AR, E };
static uint8_t events8[] = { C, RJ, RWH, CP, CHA, BR, RJ, RWH, AR, E };
run_eval (events8,
"Promise.reject(4).then(() => {})\n");
"Promise.reject(4).catch(() => { throw 'Error' })\n");
/* Test Promise.race without resolve */
static uint8_t events9[] = { C, C, C, CP, CP, E };
@@ -206,7 +220,7 @@ main (void)
"Promise.race([p1,p2])\n");
/* Test Promise.race with resolve. */
static uint8_t events10[] = { C, RS, C, RJ, C, CP, CP, BR, RS, RS, AR, BR, RS, AR, E };
static uint8_t events10[] = { C, RS, C, RJ, RWH, C, CP, CP, CHA, BR, RS, RS, AR, BR, RJF, RS, AR, E };
run_eval (events10,
"'use strict'\n"
@@ -224,7 +238,7 @@ main (void)
"Promise.all([p1,p2])\n");
/* Test Promise.all with resolve. */
static uint8_t events12[] = { C, RS, C, RJ, C, CP, CP, BR, RS, AR, BR, RJ, RS, AR, E };
static uint8_t events12[] = { C, RS, C, RJ, RWH, C, CP, CP, CHA, BR, RS, AR, BR, RJ, RWH, RS, AR, E };
run_eval (events12,
"'use strict'\n"
@@ -257,7 +271,7 @@ main (void)
"f(Promise.resolve(1))\n");
/* Test await with rejected Promise. */
static uint8_t events16[] = { C, RJ, A, C, BRJ, C, RS, RS, ARJ, E };
static uint8_t events16[] = { C, RJ, RWH, A, CHA, C, BRJ, C, RS, RS, ARJ, E };
run_eval (events16,
"'use strict'\n"
@@ -281,6 +295,67 @@ main (void)
"async function *g() { yield* f() }\n"
"g().next()\n");
/* Test multiple fulfill operations. */
static uint8_t events19[] = { C, RS, RSF, RJF, E };
run_eval (events19,
"'use strict'\n"
"var resolve, reject\n"
"var p1 = new Promise((res, rej) => { resolve = res, reject = rej })\n"
"resolve(1)\n"
"resolve(2)\n"
"reject(3)\n");
/* Test multiple fulfill operations. */
static uint8_t events20[] = { C, RJ, RWH, RSF, RJF, E };
run_eval (events20,
"'use strict'\n"
"var resolve, reject\n"
"var p1 = new Promise((res, rej) => { resolve = res, reject = rej })\n"
"reject(1)\n"
"resolve(2)\n"
"reject(3)\n");
/* Test catch handler added later is reported only once. */
static uint8_t events21[] = { C, RJ, RWH, CP, CHA, CP, CP, BR, RS, AR, BR, RS, AR, BR, RS, AR, E };
run_eval (events21,
"'use strict'\n"
"var rej = Promise.reject(4)\n"
"rej.catch(() => {})\n"
"rej.catch(() => {})\n"
"rej.catch(() => {})\n");
/* Test catch handler added later is reported only once. */
static uint8_t events22[] = { C, RJ, RWH, A, CHA, C, BRJ, A, ARJ, BRJ, RJ, RWH, ARJ, E };
run_eval (events22,
"'use strict'\n"
"async function f(p) { try { await p; } catch(e) { await p; } }"
"f(Promise.reject(4))\n");
/* Test disabled filters. */
jerry_promise_set_callback (JERRY_PROMISE_EVENT_FILTER_DISABLE, promise_callback, (void *) &user);
static uint8_t events23[] = { E };
run_eval (events23,
"'use strict'\n"
"async function f(p) { await p }"
"f(Promise.resolve(1))\n");
/* Test filtered events. */
filters = JERRY_PROMISE_EVENT_FILTER_REACTION_JOB | JERRY_PROMISE_EVENT_FILTER_ASYNC_REACTION_JOB;
jerry_promise_set_callback (filters, promise_callback, (void *) &user);
static uint8_t events24[] = { BR, AR, BRS, ARS, E };
run_eval (events24,
"'use strict'\n"
"async function f(p) { await p }"
"f(Promise.resolve(1).then(() => {}))\n");
jerry_cleanup ();
return 0;
} /* main */