mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add notification callback for module state changes (#4656)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
a7a4cb29e4
commit
1f2a8d4ac1
@ -820,6 +820,32 @@ typedef jerry_value_t (*jerry_module_resolve_callback_t) (const jerry_value_t sp
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
- [jerry_get_global_object](#jerry_get_global_object)
|
||||
|
||||
## jerry_module_state_changed_callback_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback which is called after the module enters into linked, evaluated or error state.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef void (*jerry_module_state_changed_callback_t) (jerry_module_state_t new_state,
|
||||
const jerry_value_t module,
|
||||
const jerry_value_t value,
|
||||
void *user_p);
|
||||
```
|
||||
|
||||
- `new_state` - new state of the module.
|
||||
- `module` - a module whose state is changed
|
||||
- `value` - depends on the state: undefined for linked, module script result for evaluated,
|
||||
and error value for error state.
|
||||
- `user_p` - pointer passed to [jerry_module_set_state_changed_callback](#jerry_module_set_state_changed_callback).
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
- [jerry_module_set_state_changed_callback](#jerry_module_set_state_changed_callback)
|
||||
|
||||
## jerry_native_module_evaluate_callback_t
|
||||
|
||||
**Summary**
|
||||
@ -4558,6 +4584,85 @@ main (void)
|
||||
|
||||
- [jerry_module_state_t](#jerry_module_state_t)
|
||||
|
||||
## jerry_module_set_state_changed_callback
|
||||
|
||||
**Summary**
|
||||
|
||||
Sets a callback which is called after a module state is changed to linked, evaluated, or error.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_MODULE_SYSTEM`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_MODULE` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t callback,
|
||||
void *user_p)
|
||||
```
|
||||
|
||||
- `callback` - callback, which is called after the state change.
|
||||
- `module_val` - pointer passed to the callback function.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void
|
||||
module_state_changed (jerry_module_state_t new_state, /**< new state of the module */
|
||||
const jerry_value_t module_val, /**< a module whose state is changed */
|
||||
const jerry_value_t value, /**< value argument */
|
||||
void *user_p) /**< user pointer */
|
||||
{
|
||||
(void) module_val;
|
||||
(void) value;
|
||||
(void) user_p;
|
||||
|
||||
if (new_state == JERRY_MODULE_STATE_LINKED)
|
||||
{
|
||||
printf ("A module is entered into linked state\n");
|
||||
}
|
||||
} /* module_state_changed */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
const jerry_char_t script[] = "12";
|
||||
const jerry_char_t file[] = "a.mjs";
|
||||
|
||||
jerry_module_set_state_changed_callback (module_state_changed, NULL);
|
||||
|
||||
jerry_parse_options_t parse_options;
|
||||
parse_options.options = JERRY_PARSE_MODULE | JERRY_PARSE_HAS_RESOURCE;
|
||||
parse_options.resource_name_p = file;
|
||||
parse_options.resource_name_length = sizeof (file) - 1;
|
||||
|
||||
jerry_value_t module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
jerry_release_value (jerry_module_link (module_value, NULL, NULL));
|
||||
|
||||
jerry_release_value (module_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_state_t](#jerry_module_state_t)
|
||||
- [jerry_module_state_changed_callback_t](#jerry_module_state_changed_callback_t)
|
||||
|
||||
## jerry_module_get_number_of_requests
|
||||
|
||||
**Summary**
|
||||
|
||||
@ -755,6 +755,24 @@ jerry_module_get_state (const jerry_value_t module_val) /**< module object */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_get_state */
|
||||
|
||||
/**
|
||||
* Sets a callback which is called after a module state is changed to linked, evaluated, or error.
|
||||
*/
|
||||
void
|
||||
jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t callback, /**< callback */
|
||||
void *user_p) /**< pointer passed to the callback */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
JERRY_CONTEXT (module_state_changed_callback_p) = callback;
|
||||
JERRY_CONTEXT (module_state_changed_callback_user_p) = user_p;
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (callback);
|
||||
JERRY_UNUSED (user_p);
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_set_state_changed_callback */
|
||||
|
||||
/**
|
||||
* Returns the number of import/export requests of a module
|
||||
*
|
||||
|
||||
@ -59,7 +59,7 @@ ecma_module_create (void)
|
||||
} /* ecma_module_create */
|
||||
|
||||
/**
|
||||
* cleanup context variables for the root module.
|
||||
* Cleanup context variables for the root module.
|
||||
*/
|
||||
void
|
||||
ecma_module_cleanup_context (void)
|
||||
@ -70,6 +70,27 @@ ecma_module_cleanup_context (void)
|
||||
#endif /* JERRY_NDEBUG */
|
||||
} /* ecma_module_cleanup_context */
|
||||
|
||||
/**
|
||||
* Sets module state to error.
|
||||
*/
|
||||
static void
|
||||
ecma_module_set_error_state (ecma_module_t *module_p) /**< module */
|
||||
{
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_ERROR;
|
||||
|
||||
if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL
|
||||
&& !jcontext_has_pending_abort ())
|
||||
{
|
||||
jerry_value_t exception = jcontext_take_exception ();
|
||||
|
||||
JERRY_CONTEXT (module_state_changed_callback_p) (JERRY_MODULE_STATE_ERROR,
|
||||
ecma_make_object_value (&module_p->header.object),
|
||||
exception,
|
||||
JERRY_CONTEXT (module_state_changed_callback_user_p));
|
||||
jcontext_raise_exception (exception);
|
||||
}
|
||||
} /* ecma_module_set_error_state */
|
||||
|
||||
/**
|
||||
* Gets the internal module pointer of a module
|
||||
*
|
||||
@ -398,11 +419,21 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
|
||||
ret_value = vm_run_module (module_p);
|
||||
}
|
||||
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_ERROR;
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (ret_value))
|
||||
if (JERRY_LIKELY (!ECMA_IS_VALUE_ERROR (ret_value)))
|
||||
{
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATED;
|
||||
|
||||
if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL)
|
||||
{
|
||||
JERRY_CONTEXT (module_state_changed_callback_p) (JERRY_MODULE_STATE_EVALUATED,
|
||||
ecma_make_object_value (&module_p->header.object),
|
||||
ret_value,
|
||||
JERRY_CONTEXT (module_state_changed_callback_user_p));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_module_set_error_state (module_p);
|
||||
}
|
||||
|
||||
if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE))
|
||||
@ -943,7 +974,7 @@ restart:
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
current_module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_ERROR;
|
||||
ecma_module_set_error_state (current_module_p);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -974,6 +1005,14 @@ restart:
|
||||
JERRY_ASSERT (last_p->module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKING);
|
||||
last_p->module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKED;
|
||||
|
||||
if (JERRY_CONTEXT (module_state_changed_callback_p) != NULL)
|
||||
{
|
||||
JERRY_CONTEXT (module_state_changed_callback_p) (JERRY_MODULE_STATE_LINKED,
|
||||
ecma_make_object_value (&last_p->module_p->header.object),
|
||||
ECMA_VALUE_UNDEFINED,
|
||||
JERRY_CONTEXT (module_state_changed_callback_user_p));
|
||||
}
|
||||
|
||||
jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t));
|
||||
last_p = prev_p;
|
||||
}
|
||||
|
||||
@ -269,6 +269,7 @@ jerry_value_t jerry_module_link (const jerry_value_t module_val,
|
||||
jerry_module_resolve_callback_t callback_p, void *user_p);
|
||||
jerry_value_t jerry_module_evaluate (const jerry_value_t module_val);
|
||||
jerry_module_state_t jerry_module_get_state (const jerry_value_t module_val);
|
||||
void jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t callback, void *user_p);
|
||||
size_t jerry_module_get_number_of_requests (const jerry_value_t module_val);
|
||||
jerry_value_t jerry_module_get_request (const jerry_value_t module_val, size_t request_index);
|
||||
jerry_value_t jerry_module_get_namespace (const jerry_value_t module_val);
|
||||
|
||||
@ -550,6 +550,12 @@ typedef jerry_value_t (*jerry_module_resolve_callback_t) (const jerry_value_t sp
|
||||
const jerry_value_t referrer,
|
||||
void *user_p);
|
||||
|
||||
/**
|
||||
* Callback which is called after the module enters into linked, evaluated or error state.
|
||||
*/
|
||||
typedef void (*jerry_module_state_changed_callback_t) (jerry_module_state_t new_state, const jerry_value_t module,
|
||||
const jerry_value_t value, void *user_p);
|
||||
|
||||
/**
|
||||
* Callback which is called by jerry_module_evaluate to evaluate the native module.
|
||||
*/
|
||||
|
||||
@ -148,7 +148,10 @@ struct jerry_context_t
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_current_p; /**< current module context */
|
||||
ecma_module_t *module_current_p; /**< current module context */
|
||||
jerry_module_state_changed_callback_t module_state_changed_callback_p; /**< callback which is called after the
|
||||
* state of a module is changed */
|
||||
void *module_state_changed_callback_user_p; /**< user pointer for module_state_changed_callback_p */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */
|
||||
|
||||
@ -224,6 +224,43 @@ resolve_callback4 (const jerry_value_t specifier, /**< module specifier */
|
||||
return native_module;
|
||||
} /* resolve_callback4 */
|
||||
|
||||
static void
|
||||
module_state_changed (jerry_module_state_t new_state, /**< new state of the module */
|
||||
const jerry_value_t module_val, /**< a module whose state is changed */
|
||||
const jerry_value_t value, /**< value argument */
|
||||
void *user_p) /**< user pointer */
|
||||
{
|
||||
TEST_ASSERT (jerry_module_get_state (module_val) == new_state);
|
||||
TEST_ASSERT (module_val == module);
|
||||
TEST_ASSERT (user_p == (void *) &counter);
|
||||
|
||||
++counter;
|
||||
|
||||
switch (counter)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
{
|
||||
TEST_ASSERT (new_state == JERRY_MODULE_STATE_LINKED);
|
||||
TEST_ASSERT (jerry_value_is_undefined (value));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
TEST_ASSERT (new_state == JERRY_MODULE_STATE_EVALUATED);
|
||||
TEST_ASSERT (jerry_value_is_number (value) && jerry_get_number_value (value) == 33.5);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
TEST_ASSERT (counter == 4);
|
||||
TEST_ASSERT (new_state == JERRY_MODULE_STATE_ERROR);
|
||||
TEST_ASSERT (jerry_value_is_number (value) && jerry_get_number_value (value) == -5.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* module_state_changed */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -471,6 +508,43 @@ main (void)
|
||||
jerry_release_value (object);
|
||||
jerry_release_value (number);
|
||||
|
||||
counter = 0;
|
||||
jerry_module_set_state_changed_callback (module_state_changed, (void *) &counter);
|
||||
|
||||
jerry_char_t source4[] = TEST_STRING_LITERAL (
|
||||
"33.5\n"
|
||||
);
|
||||
module = jerry_parse (source4, sizeof (source4) - 1, &module_parse_options);
|
||||
|
||||
result = jerry_module_link (module, NULL, NULL);
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_evaluate (module);
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
jerry_char_t source5[] = TEST_STRING_LITERAL (
|
||||
"throw -5.5\n"
|
||||
);
|
||||
module = jerry_parse (source5, sizeof (source5) - 1, &module_parse_options);
|
||||
|
||||
result = jerry_module_link (module, NULL, NULL);
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_evaluate (module);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
jerry_module_set_state_changed_callback (NULL, NULL);
|
||||
|
||||
TEST_ASSERT (counter == 4);
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
return 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user