Support dynamic import calls (#4652)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -830,6 +830,48 @@ 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_import_callback_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback which is called when an import is resolved dynamically to get the referenced module.
|
||||
|
||||
*Note*:
|
||||
- If the function returns with a promise, the import call returns with this promise. The
|
||||
application should try to resolve the requested module later. If the module is evaluated
|
||||
successfully, the returned promise should be resolved with the namespace object of the
|
||||
module. Otherwise, the returned promise should be rejected with an error.
|
||||
- If the function returns with a resolved module, a promise is created and resolved with the
|
||||
namespace object of the module. The import call returns with the resolved promise.
|
||||
- If the function returns with an error, a promise is created and rejected with the
|
||||
return error. The import call returns with the rejected promise.
|
||||
- All other return values are considered invalid. In this case the import call returns
|
||||
with a rejected promise. The rejected promise has a fixed error message, it does not
|
||||
specify the reason of the fail.
|
||||
- If realms are enabled, the returned module should be created in the current realm
|
||||
(see: [jerry_get_global_object](#jerry_get_global_object))
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef jerry_value_t (*jerry_module_import_callback_t) (const jerry_value_t specifier,
|
||||
const jerry_value_t user_value,
|
||||
void *user_p);
|
||||
```
|
||||
|
||||
- `specifier` - a module specifier string (usually used as a path to the module)
|
||||
- `user_value` - the user value assigned to the script (see [jerry_parse_options_t](#jerry_parse_options_t))
|
||||
- `user_p` - pointer passed to [jerry_module_set_import_callback](#jerry_module_set_import_callback).
|
||||
- return value
|
||||
- promise or resolved module - if the operation is successful
|
||||
- an error - otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
- [jerry_module_set_import_callback](#jerry_module_set_import_callback)
|
||||
- [jerry_get_global_object](#jerry_get_global_object)
|
||||
|
||||
## jerry_module_state_changed_callback_t
|
||||
|
||||
**Summary**
|
||||
@@ -5018,6 +5060,132 @@ main (void)
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
- [jerry_module_evaluate](#jerry_module_evaluate)
|
||||
|
||||
## jerry_module_set_import_callback
|
||||
|
||||
Sets the callback which is called when dynamic imports are resolved. The resolver
|
||||
receives the `user_value` assigned to the currently executed script, which should
|
||||
provide all the information that is necessary for the resolve.
|
||||
|
||||
*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).
|
||||
- The possible return values of the callback is explained
|
||||
in [jerry_module_import_callback_t](#jerry_module_import_callback_t)
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_module_set_import_callback (jerry_module_import_callback_t callback_p,
|
||||
void *user_p)
|
||||
```
|
||||
|
||||
- `callback_p` - a [jerry_module_import_callback_t](#jerry_module_import_callback_t) callback which handles `import()` calls
|
||||
- `user_p` - user pointer passed to the callback
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
jerry_value_t specifier;
|
||||
jerry_value_t user_value;
|
||||
jerry_value_t promise;
|
||||
} resolve_module_task_t;
|
||||
|
||||
static jerry_value_t
|
||||
resolve_dynamic (const jerry_value_t specifier, /**< module specifier */
|
||||
const jerry_value_t user_value, /**< user value assigned to the script */
|
||||
void *user_p) /**< user data */
|
||||
{
|
||||
/* If the specified module has already been evaluated, this callback can
|
||||
* return with it and the promise creation is automatically done by the engine.
|
||||
* Otherwise the application usually adds a resolve task to a command queue. */
|
||||
|
||||
/* This very simple command queue supports only one task. */
|
||||
resolve_module_task_t *task_p = (resolve_module_task_t *) user_p;
|
||||
task_p->specifier = jerry_acquire_value (specifier);
|
||||
task_p->user_value = jerry_acquire_value (user_value);
|
||||
|
||||
/* This Promise should be evaluated later. */
|
||||
jerry_value_t promise = jerry_create_promise ();
|
||||
task_p->promise = jerry_acquire_value (promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
resolve_module_task_t task;
|
||||
jerry_module_set_import_callback (resolve_dynamic, &task);
|
||||
|
||||
const jerry_char_t script[] = "import('modules/my_module.mjs').then(\n"
|
||||
" function (namespace) { /* use namespace */},\n"
|
||||
" function (error) { /* handle error */}\n"
|
||||
")";
|
||||
const jerry_char_t resource[] = "dir/my_script.js";
|
||||
|
||||
jerry_parse_options_t parse_options;
|
||||
parse_options.options = JERRY_PARSE_HAS_RESOURCE | JERRY_PARSE_HAS_USER_VALUE;
|
||||
|
||||
/* Resource is usually used for debugging purposes, e.g. for generating backtrace. */
|
||||
parse_options.resource_name_p = resource;
|
||||
parse_options.resource_name_length = sizeof (resource) - 1;
|
||||
|
||||
/* User value should provide information for resolving dynamic imports.
|
||||
* In this case it contains the full path excluding the filename. */
|
||||
parse_options.user_value = jerry_create_string ((const jerry_char_t *) "/home/user/dir");
|
||||
|
||||
jerry_value_t script_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
jerry_release_value (parse_options.user_value);
|
||||
jerry_release_value (jerry_run (script_value));
|
||||
jerry_release_value (script_value);
|
||||
|
||||
/* The application resolves both the module and the promise using the specifier
|
||||
* and the user_value. In this example the specifier is modules/my_module.mjs. */
|
||||
const jerry_char_t module_script[] = "export var a = 5";
|
||||
const jerry_char_t module_resource[] = "modules/my_module.mjs";
|
||||
|
||||
parse_options.options = JERRY_PARSE_MODULE | JERRY_PARSE_HAS_RESOURCE | JERRY_PARSE_HAS_USER_VALUE;
|
||||
parse_options.resource_name_p = module_resource;
|
||||
parse_options.resource_name_length = sizeof (module_resource) - 1;
|
||||
parse_options.user_value = jerry_create_string ((const jerry_char_t *) "/home/user/dir/modules");
|
||||
|
||||
jerry_value_t module_value = jerry_parse (module_script, sizeof (module_script) - 1, &parse_options);
|
||||
jerry_release_value (parse_options.user_value);
|
||||
jerry_release_value (jerry_module_link (module_value, NULL, NULL));
|
||||
jerry_release_value (jerry_module_evaluate (module_value));
|
||||
|
||||
/* The promise must be resolved with the namespace object, not the module. */
|
||||
jerry_value_t namespace_value = jerry_module_get_namespace (module_value);
|
||||
jerry_release_value (jerry_resolve_or_reject_promise (task.promise, namespace_value, true));
|
||||
|
||||
jerry_release_value (namespace_value);
|
||||
jerry_release_value (module_value);
|
||||
jerry_release_value (task.specifier);
|
||||
jerry_release_value (task.user_value);
|
||||
jerry_release_value (task.promise);
|
||||
|
||||
/* Process promise handlers. */
|
||||
jerry_release_value (jerry_run_all_enqueued_jobs ());
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
- [jerry_module_import_callback_t](#jerry_module_import_callback_t)
|
||||
|
||||
## jerry_native_module_create
|
||||
|
||||
Creates a native module with a list of exports. The initial state of the module is linked.
|
||||
|
||||
Reference in New Issue
Block a user