Add module C API functions (#4636)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -747,6 +747,21 @@ 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_state_t
|
||||
|
||||
An enum representing the current status of a module
|
||||
|
||||
- JERRY_MODULE_STATE_INVALID - Return value for jerry_module_get_state when its argument is not a module
|
||||
- JERRY_MODULE_STATE_UNLINKED - Module is currently unlinked
|
||||
- JERRY_MODULE_STATE_LINKING - Module is currently being linked
|
||||
- JERRY_MODULE_STATE_LINKED - Module has been linked (its depencencies has been resolved)
|
||||
- JERRY_MODULE_STATE_EVALUATING - Module is currently being evaluated
|
||||
- JERRY_MODULE_STATE_EVALUATED - Module has been evaluated (its source code has been executed)
|
||||
- JERRY_MODULE_STATE_ERROR - An error has been encountered before the evaluated state is reached
|
||||
- JERRY_MODULE_STATE_NATIVE - Module is native module
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
## jerry_module_resolve_callback_t
|
||||
|
||||
**Summary**
|
||||
@@ -4365,6 +4380,341 @@ main (void)
|
||||
**See also**
|
||||
- [jerry_module_resolve_callback_t](#jerry_module_resolve_callback_t)
|
||||
|
||||
## jerry_module_evaluate
|
||||
|
||||
Evaluate a module and its dependencies. The module must be in linked state.
|
||||
|
||||
*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_evaluate (const jerry_value_t module_val);
|
||||
```
|
||||
|
||||
- `module_val` - module object
|
||||
- return
|
||||
- result of module bytecode execution - if evaluation was successful
|
||||
- error, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
const jerry_char_t script[] = "export var a = 6";
|
||||
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 module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
jerry_release_value (jerry_module_link (module_value, NULL, NULL));
|
||||
jerry_release_value (jerry_module_evaluate (module_value));
|
||||
|
||||
jerry_release_value (module_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
|
||||
## jerry_module_get_state
|
||||
|
||||
**Summary**
|
||||
|
||||
Returns the current status of a module. The available values
|
||||
are listed in [jerry_module_state_t](#jerry_module_state_t)
|
||||
|
||||
*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
|
||||
jerry_module_state_t jerry_module_get_state (const jerry_value_t module_val);
|
||||
```
|
||||
|
||||
- `module_val` - module object
|
||||
- return
|
||||
- current status - if module_val is a module
|
||||
- JERRY_MODULE_STATE_INVALID - otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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 module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
if (jerry_module_get_state (module_value) == JERRY_MODULE_STATE_UNLINKED)
|
||||
{
|
||||
printf ("Module parsing has been successful\n");
|
||||
}
|
||||
|
||||
jerry_release_value (module_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_state_t](#jerry_module_state_t)
|
||||
|
||||
## jerry_module_get_number_of_requests
|
||||
|
||||
**Summary**
|
||||
|
||||
Returns the number of import/export requests of a module.
|
||||
The requests can be queried by [jerry_module_get_request](#jerry_module_get_request).
|
||||
|
||||
|
||||
*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
|
||||
size_t jerry_module_get_number_of_requests (const jerry_value_t module_val);
|
||||
```
|
||||
|
||||
- `module_val` - module object
|
||||
- return
|
||||
- number of import/export requests of a module, if `module_val` is module,
|
||||
- 0, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
const jerry_char_t script[] = "export * from 'b.mjs'"
|
||||
"import a from 'c.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 module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
/* Prints 2. */
|
||||
printf ("Number of requests: %d\n", (int) jerry_module_get_number_of_requests (module_value));
|
||||
|
||||
jerry_release_value (module_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_get_request](#jerry_module_get_request)
|
||||
- [jerry_parse](#jerry_parse)
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
|
||||
## jerry_module_get_request
|
||||
|
||||
**Summary**
|
||||
|
||||
Returns the module request specified by the `request_index` argument. The requests
|
||||
are ordered in source code occurence. When parsing is completed, all returned values
|
||||
are strings. If [jerry_module_link](#jerry_module_link) is completed successfully
|
||||
all returned values are module objects instead. If linking is in progress or fails,
|
||||
the successfully resolved dependencies are module objects, the rest are strings.
|
||||
The number of requests can be queried by
|
||||
[jerry_module_get_number_of_requests](#jerry_module_get_number_of_requests).
|
||||
|
||||
*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_get_request (const jerry_value_t module_val, size_t request_index);
|
||||
```
|
||||
|
||||
- `module_val` - module object
|
||||
- return
|
||||
- string, if the request has not been resolved yet
|
||||
- module object, if the request has been resolved successfully
|
||||
- error, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
const jerry_char_t script[] = "export * from 'b.mjs'"
|
||||
"import a from 'c.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 module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
jerry_value_t request_value = jerry_module_get_request (module_value, 0);
|
||||
/* Returns with b.mjs */
|
||||
jerry_release_value (request_value);
|
||||
|
||||
request_value = jerry_module_get_request (module_value, 1);
|
||||
/* Returns with c.mjs */
|
||||
jerry_release_value (request_value);
|
||||
|
||||
jerry_release_value (module_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_get_number_of_requests](#jerry_module_get_number_of_requests)
|
||||
- [jerry_parse](#jerry_parse)
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
|
||||
## jerry_module_get_namespace
|
||||
|
||||
Returns the namespace object of a module
|
||||
|
||||
*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_get_namespace (const jerry_value_t module_val);
|
||||
```
|
||||
|
||||
- `module_val` - module object
|
||||
- return
|
||||
- object, if namespace object is available
|
||||
- error, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
const jerry_char_t script[] = "export var a = 6";
|
||||
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 module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
|
||||
|
||||
jerry_release_value (jerry_module_link (module_value, NULL, NULL));
|
||||
jerry_release_value (jerry_module_evaluate (module_value));
|
||||
|
||||
jerry_value_t namespace_value = jerry_module_get_namespace (module_value);
|
||||
|
||||
/* Exports can be checked. */
|
||||
|
||||
jerry_release_value (namespace_value);
|
||||
jerry_release_value (module_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
- [jerry_module_evaluate](#jerry_module_evaluate)
|
||||
|
||||
# Functions for promise objects
|
||||
|
||||
These APIs all depend on the es.next profile (or on some build options).
|
||||
|
||||
+187
-14
@@ -689,20 +689,6 @@ jerry_run (const jerry_value_t func_val) /**< function to run */
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (JERRY_UNLIKELY (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_MODULE_UL))
|
||||
{
|
||||
ecma_module_t *root_module_p = (ecma_module_t *) ext_object_p;
|
||||
|
||||
if (root_module_p->header.u.class_prop.extra_info != ECMA_MODULE_STATE_LINKED)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Module must be in linked state")));
|
||||
}
|
||||
|
||||
return jerry_return (ecma_module_evaluate (root_module_p));
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
if (ext_object_p->u.class_prop.class_id != LIT_MAGIC_STRING_SCRIPT_UL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
|
||||
@@ -757,6 +743,8 @@ jerry_module_link (const jerry_value_t module_val, /**< root module */
|
||||
* jerry_port_module_resolve when NULL is passed */
|
||||
void *user_p) /**< pointer passed to the resolve callback */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (callback == NULL)
|
||||
{
|
||||
@@ -780,6 +768,191 @@ jerry_module_link (const jerry_value_t module_val, /**< root module */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_link */
|
||||
|
||||
/**
|
||||
* Evaluate a module and its dependencies. The module must be in linked state.
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return result of module bytecode execution - if evaluation was successful
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_module_evaluate (const jerry_value_t module_val) /**< root module */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_not_module_p)));
|
||||
}
|
||||
|
||||
if (module_p->header.u.class_prop.extra_info != JERRY_MODULE_STATE_LINKED)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Module must be in linked state")));
|
||||
}
|
||||
|
||||
return jerry_return (ecma_module_evaluate (module_p));
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (module_val);
|
||||
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_evaluate */
|
||||
|
||||
/**
|
||||
* Returns the current status of a module
|
||||
*
|
||||
* @return current status - if module_val is a module,
|
||||
* JERRY_MODULE_STATE_INVALID - otherwise
|
||||
*/
|
||||
jerry_module_state_t
|
||||
jerry_module_get_state (const jerry_value_t module_val) /**< module object */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return JERRY_MODULE_STATE_INVALID;
|
||||
}
|
||||
|
||||
return (jerry_module_state_t) module_p->header.u.class_prop.extra_info;
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (module_val);
|
||||
|
||||
return JERRY_MODULE_STATE_INVALID;
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_get_state */
|
||||
|
||||
/**
|
||||
* Returns the number of import/export requests of a module
|
||||
*
|
||||
* @return number of import/export requests of a module
|
||||
*/
|
||||
size_t
|
||||
jerry_module_get_number_of_requests (const jerry_value_t module_val) /**< module */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t number_of_requests = 0;
|
||||
|
||||
ecma_module_node_t *node_p = module_p->imports_p;
|
||||
|
||||
while (node_p != NULL)
|
||||
{
|
||||
number_of_requests++;
|
||||
node_p = node_p->next_p;
|
||||
}
|
||||
|
||||
return number_of_requests;
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (module_val);
|
||||
|
||||
return 0;
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_get_number_of_requests */
|
||||
|
||||
/**
|
||||
* Returns the module request specified by the request_index argument
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return string - if the request has not been resolved yet,
|
||||
* module object - if the request has been resolved successfully,
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_module_get_request (const jerry_value_t module_val, /**< module */
|
||||
size_t request_index) /**< request index */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_not_module_p)));
|
||||
}
|
||||
|
||||
ecma_module_node_t *node_p = module_p->imports_p;
|
||||
|
||||
while (node_p != NULL)
|
||||
{
|
||||
if (request_index == 0)
|
||||
{
|
||||
return ecma_copy_value (node_p->u.path_or_module);
|
||||
}
|
||||
|
||||
--request_index;
|
||||
node_p = node_p->next_p;
|
||||
}
|
||||
|
||||
return jerry_throw (ecma_raise_range_error (ECMA_ERR_MSG ("Request is not available")));
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (module_val);
|
||||
JERRY_UNUSED (request_index);
|
||||
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_get_request */
|
||||
|
||||
/**
|
||||
* Returns the namespace object of a module
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return object - if namespace object is available,
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_module_get_namespace (const jerry_value_t module_val) /**< module */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_not_module_p)));
|
||||
}
|
||||
|
||||
if (module_p->namespace_object_p == NULL)
|
||||
{
|
||||
if (module_p->header.u.class_prop.extra_info != JERRY_MODULE_STATE_EVALUATED)
|
||||
{
|
||||
return jerry_throw (ecma_raise_range_error (ECMA_ERR_MSG ("Namespace object has not been created yet")));
|
||||
}
|
||||
|
||||
ecma_module_create_namespace_object (module_p);
|
||||
}
|
||||
|
||||
ecma_ref_object (module_p->namespace_object_p);
|
||||
return ecma_make_object_value (module_p->namespace_object_p);
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (module_val);
|
||||
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_get_namespace */
|
||||
|
||||
/**
|
||||
* Run enqueued Promise jobs until the first thrown error or until all get executed.
|
||||
*
|
||||
|
||||
@@ -40,7 +40,7 @@ ecma_module_initialize_context (void)
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_MODULE_UL;
|
||||
ext_object_p->u.class_prop.extra_info = ECMA_MODULE_STATE_UNLINKED;
|
||||
ext_object_p->u.class_prop.extra_info = JERRY_MODULE_STATE_UNLINKED;
|
||||
|
||||
ecma_module_t *module_p = (ecma_module_t *) obj_p;
|
||||
|
||||
@@ -219,7 +219,7 @@ ecma_module_resolve_export (ecma_module_t *const module_p, /**< base module */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_NATIVE)
|
||||
if (current_module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_NATIVE)
|
||||
{
|
||||
ecma_object_t *object_p = current_module_p->namespace_object_p;
|
||||
ecma_value_t prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p),
|
||||
@@ -382,17 +382,17 @@ ecma_module_resolve_export (ecma_module_t *const module_p, /**< base module */
|
||||
ecma_value_t
|
||||
ecma_module_evaluate (ecma_module_t *module_p) /**< module */
|
||||
{
|
||||
if (module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_ERROR)
|
||||
if (module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_ERROR)
|
||||
{
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Module is in error state"));
|
||||
}
|
||||
|
||||
if (module_p->header.u.class_prop.extra_info >= ECMA_MODULE_STATE_EVALUATING)
|
||||
if (module_p->header.u.class_prop.extra_info >= JERRY_MODULE_STATE_EVALUATING)
|
||||
{
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_LINKED);
|
||||
JERRY_ASSERT (module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_LINKED);
|
||||
|
||||
#if JERRY_BUILTIN_REALMS
|
||||
ecma_object_t *global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->compiled_code_p);
|
||||
@@ -400,18 +400,18 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
#endif /* JERRY_BUILTIN_REALMS */
|
||||
|
||||
module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_EVALUATING;
|
||||
module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_EVALUATING;
|
||||
module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p));
|
||||
|
||||
ecma_value_t ret_value;
|
||||
ret_value = vm_run_module (module_p);
|
||||
|
||||
module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_ERROR;
|
||||
module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_ERROR;
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ecma_free_value (ret_value);
|
||||
module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_EVALUATED;
|
||||
module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_EVALUATED;
|
||||
ret_value = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ ecma_module_namespace_object_add_export_if_needed (ecma_module_t *module_p, /**<
|
||||
* @return ECMA_VALUE_ERROR - if an error occured
|
||||
* ECMA_VALUE_EMPTY - otherwise
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_value_t
|
||||
ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
|
||||
{
|
||||
ecma_value_t result = ECMA_VALUE_EMPTY;
|
||||
@@ -491,7 +491,7 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
|
||||
return result;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_EVALUATED);
|
||||
JERRY_ASSERT (module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_EVALUATED);
|
||||
ecma_module_resolve_set_t *resolve_set_p = NULL;
|
||||
ecma_module_resolve_stack_t *stack_p = NULL;
|
||||
|
||||
@@ -688,7 +688,7 @@ ecma_module_connect_imports (ecma_module_t *module_p)
|
||||
return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous import request"));
|
||||
}
|
||||
|
||||
if (record.module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_NATIVE)
|
||||
if (record.module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_NATIVE)
|
||||
{
|
||||
ecma_object_t *object_p = record.module_p->namespace_object_p;
|
||||
prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p), object_p, record.name_p);
|
||||
@@ -858,12 +858,12 @@ ecma_module_link (ecma_module_t *module_p, /**< root module */
|
||||
jerry_module_resolve_callback_t callback, /**< resolve module callback */
|
||||
void *user_p) /**< pointer passed to the resolve callback */
|
||||
{
|
||||
if (module_p->header.u.class_prop.extra_info != ECMA_MODULE_STATE_UNLINKED)
|
||||
if (module_p->header.u.class_prop.extra_info != JERRY_MODULE_STATE_UNLINKED)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Module must be in unlinked state"));
|
||||
}
|
||||
|
||||
module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_LINKING;
|
||||
module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_LINKING;
|
||||
|
||||
uint32_t dfs_index = 0;
|
||||
ecma_module_stack_item_t *last_p;
|
||||
@@ -919,7 +919,7 @@ restart:
|
||||
node_p->u.path_or_module = resolve_result;
|
||||
ecma_deref_object (ecma_get_object_from_value (resolve_result));
|
||||
|
||||
if (resolved_module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_ERROR)
|
||||
if (resolved_module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_ERROR)
|
||||
{
|
||||
ecma_raise_type_error (ECMA_ERR_MSG ("Cannot link to a module which is in error state"));
|
||||
goto error;
|
||||
@@ -938,10 +938,10 @@ restart:
|
||||
{
|
||||
module_p = ecma_module_get_from_object (node_p->u.path_or_module);
|
||||
|
||||
if (module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_UNLINKED)
|
||||
if (module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_UNLINKED)
|
||||
{
|
||||
current_p->node_p = node_p->next_p;
|
||||
module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_LINKING;
|
||||
module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_LINKING;
|
||||
|
||||
ecma_module_stack_item_t *item_p;
|
||||
item_p = (ecma_module_stack_item_t *) jmem_heap_alloc_block (sizeof (ecma_module_stack_item_t));
|
||||
@@ -962,7 +962,7 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
|
||||
if (module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_LINKING)
|
||||
if (module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_LINKING)
|
||||
{
|
||||
uint32_t dfs_ancestor_index = module_p->header.u.class_prop.u.dfs_ancestor_index;
|
||||
|
||||
@@ -996,8 +996,8 @@ restart:
|
||||
{
|
||||
ecma_module_stack_item_t *prev_p = last_p->prev_p;
|
||||
|
||||
JERRY_ASSERT (last_p->module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_LINKING);
|
||||
last_p->module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_LINKED;
|
||||
JERRY_ASSERT (last_p->module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_LINKING);
|
||||
last_p->module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_LINKED;
|
||||
|
||||
jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t));
|
||||
last_p = prev_p;
|
||||
@@ -1017,8 +1017,8 @@ error:
|
||||
{
|
||||
ecma_module_stack_item_t *prev_p = last_p->prev_p;
|
||||
|
||||
JERRY_ASSERT (last_p->module_p->header.u.class_prop.extra_info == ECMA_MODULE_STATE_LINKING);
|
||||
last_p->module_p->header.u.class_prop.extra_info = ECMA_MODULE_STATE_UNLINKED;
|
||||
JERRY_ASSERT (last_p->module_p->header.u.class_prop.extra_info == JERRY_MODULE_STATE_LINKING);
|
||||
last_p->module_p->header.u.class_prop.extra_info = JERRY_MODULE_STATE_UNLINKED;
|
||||
|
||||
jmem_heap_free_block (last_p, sizeof (ecma_module_stack_item_t));
|
||||
last_p = prev_p;
|
||||
@@ -1075,7 +1075,9 @@ ecma_module_release_module_nodes (ecma_module_node_t *module_node_p, /**< first
|
||||
void
|
||||
ecma_module_release_module (ecma_module_t *module_p) /**< module */
|
||||
{
|
||||
ecma_module_state_t state = (ecma_module_state_t) module_p->header.u.class_prop.extra_info;
|
||||
jerry_module_state_t state = (jerry_module_state_t) module_p->header.u.class_prop.extra_info;
|
||||
|
||||
JERRY_ASSERT (state != JERRY_MODULE_STATE_INVALID);
|
||||
|
||||
if (module_p->namespace_object_p != NULL)
|
||||
{
|
||||
@@ -1087,7 +1089,7 @@ ecma_module_release_module (ecma_module_t *module_p) /**< module */
|
||||
#endif /* JERRY_NDEBUG */
|
||||
}
|
||||
|
||||
if (state == ECMA_MODULE_STATE_NATIVE)
|
||||
if (state == JERRY_MODULE_STATE_NATIVE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1097,7 +1099,7 @@ ecma_module_release_module (ecma_module_t *module_p) /**< module */
|
||||
ecma_module_release_module_nodes (module_p->indirect_exports_p, false);
|
||||
ecma_module_release_module_nodes (module_p->star_exports_p, false);
|
||||
|
||||
if (state >= ECMA_MODULE_STATE_EVALUATING)
|
||||
if (state >= JERRY_MODULE_STATE_EVALUATING)
|
||||
{
|
||||
/* The module structure keeps a strong reference to the module scope, which will require an extra GC call. */
|
||||
JERRY_CONTEXT (ecma_gc_new_objects)++;
|
||||
|
||||
@@ -35,20 +35,6 @@ typedef struct ecma_module_names
|
||||
ecma_string_t *local_name_p; /**< Local name of the item */
|
||||
} ecma_module_names_t;
|
||||
|
||||
/**
|
||||
* An enum identifing the current state of the module
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_MODULE_STATE_UNLINKED = 0, /**< module is currently unlinked */
|
||||
ECMA_MODULE_STATE_LINKING = 1, /**< module is currently being linked */
|
||||
ECMA_MODULE_STATE_LINKED = 2, /**< module has been linked */
|
||||
ECMA_MODULE_STATE_EVALUATING = 3, /**< module is currently being evaluated */
|
||||
ECMA_MODULE_STATE_EVALUATED = 4, /**< module has been evaluated */
|
||||
ECMA_MODULE_STATE_ERROR = 5, /**< error is encountered during module init */
|
||||
ECMA_MODULE_STATE_NATIVE = 6, /**< module is native */
|
||||
} ecma_module_state_t;
|
||||
|
||||
/**
|
||||
* Module structure storing an instance of a module
|
||||
*
|
||||
@@ -130,6 +116,7 @@ ecma_value_t ecma_module_evaluate (ecma_module_t *module_p);
|
||||
|
||||
void ecma_module_initialize_context (void);
|
||||
void ecma_module_cleanup_context (void);
|
||||
ecma_value_t ecma_module_create_namespace_object (ecma_module_t *module_p);
|
||||
|
||||
void ecma_module_release_module_names (ecma_module_names_t *module_name_p);
|
||||
void ecma_module_release_module (ecma_module_t *module_p);
|
||||
|
||||
@@ -267,6 +267,11 @@ jerry_value_t jerry_to_property_descriptor (jerry_value_t obj_value, jerry_prope
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
/**
|
||||
* Promise functions.
|
||||
|
||||
@@ -288,13 +288,6 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p);
|
||||
*/
|
||||
typedef void (*jerry_error_object_created_callback_t) (const jerry_value_t error_object, void *user_p);
|
||||
|
||||
/**
|
||||
* Callback which is called by jerry_module_link to get the referenced module.
|
||||
*/
|
||||
typedef jerry_value_t (*jerry_module_resolve_callback_t) (const jerry_value_t specifier,
|
||||
const jerry_value_t referrer,
|
||||
void *user_p);
|
||||
|
||||
/**
|
||||
* Callback which tells whether the ECMAScript execution should be stopped.
|
||||
*
|
||||
@@ -522,6 +515,32 @@ typedef enum
|
||||
JERRY_ITERATOR_TYPE_SET, /**< Set iterator */
|
||||
} jerry_iterator_type_t;
|
||||
|
||||
/**
|
||||
* Module related types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An enum representing the current status of a module
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_MODULE_STATE_INVALID = 0, /**< return value for jerry_module_get_state when its argument is not a module */
|
||||
JERRY_MODULE_STATE_UNLINKED = 1, /**< module is currently unlinked */
|
||||
JERRY_MODULE_STATE_LINKING = 2, /**< module is currently being linked */
|
||||
JERRY_MODULE_STATE_LINKED = 3, /**< module has been linked (its depencencies has been resolved) */
|
||||
JERRY_MODULE_STATE_EVALUATING = 4, /**< module is currently being evaluated */
|
||||
JERRY_MODULE_STATE_EVALUATED = 5, /**< module has been evaluated (its source code has been executed) */
|
||||
JERRY_MODULE_STATE_ERROR = 6, /**< an error has been encountered before the evaluated state is reached */
|
||||
JERRY_MODULE_STATE_NATIVE = 7, /**< module is native module */
|
||||
} jerry_module_state_t;
|
||||
|
||||
/**
|
||||
* Callback which is called by jerry_module_link to get the referenced module.
|
||||
*/
|
||||
typedef jerry_value_t (*jerry_module_resolve_callback_t) (const jerry_value_t specifier,
|
||||
const jerry_value_t referrer,
|
||||
void *user_p);
|
||||
|
||||
/**
|
||||
* Proxy related types.
|
||||
*/
|
||||
|
||||
+10
-3
@@ -88,6 +88,13 @@ restart:
|
||||
|
||||
if (!jerry_value_is_error (ret_value))
|
||||
{
|
||||
if (jerry_module_get_state (ret_value) != JERRY_MODULE_STATE_UNLINKED)
|
||||
{
|
||||
/* A module can be evaluated only once. */
|
||||
jerry_release_value (ret_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
jerry_value_t link_val = jerry_module_link (ret_value, NULL, NULL);
|
||||
|
||||
if (jerry_value_is_error (link_val))
|
||||
@@ -99,9 +106,9 @@ restart:
|
||||
{
|
||||
jerry_release_value (link_val);
|
||||
|
||||
jerry_value_t func_val = ret_value;
|
||||
ret_value = jerry_run (func_val);
|
||||
jerry_release_value (func_val);
|
||||
jerry_value_t module_val = ret_value;
|
||||
ret_value = jerry_module_evaluate (module_val);
|
||||
jerry_release_value (module_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,21 @@ compare_specifier (jerry_value_t specifier, /* string value */
|
||||
TEST_ASSERT (memcmp (buffer, string, length) == 0);
|
||||
} /* compare_specifier */
|
||||
|
||||
static void
|
||||
compare_property (jerry_value_t namespace_object, /**< namespace object */
|
||||
const char *name_p, /**< property name */
|
||||
double expected_value) /**< property value (number for simplicity) */
|
||||
{
|
||||
jerry_value_t name = jerry_create_string ((const jerry_char_t *) name_p);
|
||||
jerry_value_t result = jerry_get_property (namespace_object, name);
|
||||
|
||||
TEST_ASSERT (jerry_value_is_number (result));
|
||||
TEST_ASSERT (jerry_get_number_value (result) == expected_value);
|
||||
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (name);
|
||||
} /* compare_property */
|
||||
|
||||
static jerry_value_t
|
||||
create_module (int id) /**< module id */
|
||||
{
|
||||
@@ -110,6 +125,18 @@ resolve_callback2 (const jerry_value_t specifier, /**< module specifier */
|
||||
return prev_module;
|
||||
} /* resolve_callback2 */
|
||||
|
||||
static jerry_value_t
|
||||
resolve_callback3 (const jerry_value_t specifier, /**< module specifier */
|
||||
const jerry_value_t referrer, /**< parent module */
|
||||
void *user_p) /**< user data */
|
||||
{
|
||||
(void) specifier;
|
||||
(void) referrer;
|
||||
(void) user_p;
|
||||
|
||||
TEST_ASSERT (false);
|
||||
} /* resolve_callback3 */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@@ -163,6 +190,13 @@ main (void)
|
||||
TEST_ASSERT (jerry_value_is_boolean (result) && jerry_get_boolean_value (result));
|
||||
TEST_ASSERT (counter == 32);
|
||||
jerry_release_value (result);
|
||||
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_LINKED);
|
||||
TEST_ASSERT (jerry_module_get_number_of_requests (module) == 1);
|
||||
result = jerry_module_get_request (module, 0);
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_LINKED);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
module = create_module (1);
|
||||
@@ -176,6 +210,82 @@ main (void)
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (module);
|
||||
|
||||
TEST_ASSERT (jerry_module_get_state (number) == JERRY_MODULE_STATE_INVALID);
|
||||
|
||||
jerry_parse_options_t module_parse_options;
|
||||
module_parse_options.options = JERRY_PARSE_MODULE;
|
||||
|
||||
jerry_char_t source1[] = TEST_STRING_LITERAL (
|
||||
"import a from '16_module.mjs'\n"
|
||||
"export * from '07_module.mjs'\n"
|
||||
"export * from '44_module.mjs'\n"
|
||||
"import * as b from '36_module.mjs'\n"
|
||||
);
|
||||
module = jerry_parse (source1, sizeof (source1) - 1, &module_parse_options);
|
||||
TEST_ASSERT (!jerry_value_is_error (module));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_UNLINKED);
|
||||
|
||||
TEST_ASSERT (jerry_module_get_number_of_requests (number) == 0);
|
||||
TEST_ASSERT (jerry_module_get_number_of_requests (module) == 4);
|
||||
|
||||
result = jerry_module_get_request (object, 0);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_get_request (module, 0);
|
||||
compare_specifier (result, 16);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_get_request (module, 1);
|
||||
compare_specifier (result, 7);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_get_request (module, 2);
|
||||
compare_specifier (result, 44);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_get_request (module, 3);
|
||||
compare_specifier (result, 36);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_module_get_request (module, 4);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
result = jerry_module_get_namespace (number);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_char_t source2[] = TEST_STRING_LITERAL (
|
||||
"export let a = 6\n"
|
||||
"export let b = 8.5\n"
|
||||
);
|
||||
module = jerry_parse (source2, sizeof (source2) - 1, &module_parse_options);
|
||||
TEST_ASSERT (!jerry_value_is_error (module));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_UNLINKED);
|
||||
|
||||
result = jerry_module_link (module, resolve_callback3, NULL);
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_LINKED);
|
||||
|
||||
result = jerry_module_evaluate (module);
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_EVALUATED);
|
||||
|
||||
result = jerry_module_get_namespace (module);
|
||||
TEST_ASSERT (jerry_value_is_object (result));
|
||||
compare_property (result, "a", 6);
|
||||
compare_property (result, "b", 8.5);
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
jerry_release_value (object);
|
||||
jerry_release_value (number);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user