Rework module linking (#4632)
The module linking process from jerry_parse is moved out into a new jerry_module_link function, and jerry_parse is limited to create unlinked modules. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -747,6 +747,37 @@ typedef void (*jerry_error_object_created_callback_t) (const jerry_value_t error
|
||||
|
||||
- [jerry_set_error_object_created_callback](#jerry_set_error_object_created_callback)
|
||||
|
||||
## jerry_module_resolve_callback_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback which is called by [jerry_module_link](#jerry_module_link) to get the referenced module.
|
||||
|
||||
*Note*:
|
||||
- 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_resolve_callback_t) (const jerry_value_t specifier,
|
||||
const jerry_value_t referrer,
|
||||
void *user_p);
|
||||
```
|
||||
|
||||
- `specifier` - a module specifier string (usually used as a path to the module)
|
||||
- `referrer` - a module object which contains the `specifier` in its source code
|
||||
- `user_p` - pointer passed to [jerry_module_link](#jerry_module_link).
|
||||
- return value
|
||||
- a module object - if it can be resolved successfully
|
||||
- an error - otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
- [jerry_get_global_object](#jerry_get_global_object)
|
||||
|
||||
## jerry_backtrace_callback_t
|
||||
|
||||
**Summary**
|
||||
@@ -4244,6 +4275,96 @@ jerry_value_as_uint32 (const jerry_value_t value);
|
||||
}
|
||||
```
|
||||
|
||||
# Functions for module objects
|
||||
|
||||
These APIs all depend on module support.
|
||||
|
||||
## jerry_module_link
|
||||
|
||||
**Summary**
|
||||
|
||||
Link modules to their dependencies. The dependencies are resolved by a user callback.
|
||||
|
||||
*Notes*:
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
|
||||
is no longer needed.
|
||||
- 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
|
||||
jerry_value_t jerry_module_link (const jerry_value_t module_val,
|
||||
jerry_module_resolve_callback_t callback, void *user_p)
|
||||
```
|
||||
|
||||
- `module_val` - module object in unlinked state
|
||||
- `callback` - user callback which is called to resolve dependencies,
|
||||
uses `jerry_port_module_resolve` when NULL is passed
|
||||
- `user_p` - user pointer passed to the callback
|
||||
- return
|
||||
- true - if linking is successful
|
||||
- error - otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
|
||||
static jerry_value_t
|
||||
module_resolve_callback (const jerry_value_t specifier,
|
||||
const jerry_value_t referrer,
|
||||
void *user_data_p)
|
||||
{
|
||||
/* In this case, the specifier contains 'b.mjs', and the referrer is the module
|
||||
* created in the main() function below. Normally the specifier string should be
|
||||
* extended to a full file system path, and it should be checked whether a module
|
||||
* corresponding to this path has been loaded already. For simplicity, this function
|
||||
* returns with a new module. */
|
||||
|
||||
const jerry_char_t script[] = "export var a = 5";
|
||||
const jerry_char_t file[] = "b.mjs";
|
||||
|
||||
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;
|
||||
|
||||
return jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
} /* module_resolve_callback */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
const jerry_char_t script[] = "import a from 'b.mjs'";
|
||||
const jerry_char_t file[] = "a.mjs";
|
||||
|
||||
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 ret_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
jerry_module_link (ret_value, module_resolve_callback, NULL);
|
||||
|
||||
jerry_release_value (ret_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
- [jerry_module_resolve_callback_t](#jerry_module_resolve_callback_t)
|
||||
|
||||
# Functions for promise objects
|
||||
|
||||
These APIs all depend on the es.next profile (or on some build options).
|
||||
|
||||
+32
-36
@@ -85,12 +85,10 @@ void jerry_port_print_char (char c);
|
||||
|
||||
### Jerry Module system
|
||||
|
||||
The port API provides functions that can be used by the module system to open
|
||||
and close source files, and normalize file paths.
|
||||
The `jerry_port_get_native_module` port function can be used to provide native
|
||||
modules to the engine. This function will be called when an import/export
|
||||
statement is encountered with an unknown module specifier, which embedders can
|
||||
use to supply native module objects based on the module name argument.
|
||||
The port API provides optional functions that can be used by the
|
||||
user application to resolve modules. If no callback is provided
|
||||
to `jerry_module_link`, the `jerry_port_module_resolve` function
|
||||
is used for resolving modules.
|
||||
|
||||
```c
|
||||
/**
|
||||
@@ -115,40 +113,38 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
* Default module resolver.
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size, /**< size of output buffer */
|
||||
char *base_file_p) /**< base file path */
|
||||
{
|
||||
// normalize in_path_p by expanding relative paths etc.
|
||||
// if base_file_p is not NULL, in_path_p is relative to that file
|
||||
// write to out_buf_p the normalized path
|
||||
// return length of written path
|
||||
} /* jerry_port_normalize_path */
|
||||
|
||||
/**
|
||||
* Get the module object of a native module.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when JERRY_MODULE_SYSTEM
|
||||
* is enabled.
|
||||
*
|
||||
* @param name String value of the module specifier.
|
||||
*
|
||||
* @return Undefined, if 'name' is not a native module
|
||||
* jerry_value_t containing the module object, otherwise
|
||||
* @return a module object if resolving is successful, an error otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_port_get_native_module (jerry_value_t name) /**< module specifier */
|
||||
jerry_port_module_resolve (const jerry_value_t specifier, /**< module specifier string */
|
||||
const jerry_value_t referrer, /**< parent module */
|
||||
void *user_p) /**< user data */
|
||||
{
|
||||
(void) name;
|
||||
return jerry_create_undefined ();
|
||||
}
|
||||
// Resolves a module using the specifier string. If a referrer is a module,
|
||||
// and specifier is a relative path, the base path should be the directory
|
||||
// part extracted from the path of the referrer module.
|
||||
|
||||
// The callback function of jerry_module_link may call this function
|
||||
// if it cannot resolve a module. Furthermore if the callback is NULL,
|
||||
// this function is used for resolving modules.
|
||||
|
||||
// The default implementation only resolves ECMAScript modules, and does
|
||||
// not (currently) use the user data.
|
||||
} /* jerry_port_module_resolve */
|
||||
|
||||
/**
|
||||
* Release known modules.
|
||||
*/
|
||||
void
|
||||
jerry_port_module_release (const jerry_value_t realm) /**< if this argument is object, release only those modules,
|
||||
* which realm value is equal to this argument. */
|
||||
{
|
||||
// This function releases the known modules, forcing their reload
|
||||
// when resolved again later. The released modules can be filtered
|
||||
// by realms. This function is only called by user applications.
|
||||
} /* jerry_port_module_release */
|
||||
```
|
||||
|
||||
## Date
|
||||
|
||||
Reference in New Issue
Block a user