mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Support native modules (#4649)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
05a4e45ece
commit
7b6743403f
@ -786,7 +786,6 @@ An enum representing the current status of a module
|
||||
- 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]]*.
|
||||
|
||||
@ -821,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_native_module_evaluate_callback_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback which is called by [jerry_module_evaluate](#jerry_module_evaluate) to evaluate the native module.
|
||||
|
||||
Note:
|
||||
- Native pointers can be used to assign private data to a native module,
|
||||
see [jerry_set_object_native_pointer](#jerry_set_object_native_pointer)
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef jerry_value_t (*jerry_native_module_evaluate_callback_t) (const jerry_value_t native_module);
|
||||
```
|
||||
|
||||
- `native_module` - a native module
|
||||
- return value
|
||||
- any non-error value - if the module is evaluated successfully
|
||||
- an error - otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
- [jerry_module_evaluate](#jerry_module_evaluate)
|
||||
|
||||
## jerry_backtrace_callback_t
|
||||
|
||||
**Summary**
|
||||
@ -4743,6 +4768,198 @@ main (void)
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
- [jerry_module_evaluate](#jerry_module_evaluate)
|
||||
|
||||
## jerry_native_module_create
|
||||
|
||||
Creates a native module with a list of exports. The initial state of the module is linked.
|
||||
|
||||
*Notes*:
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
- Native pointers can be used to assign private data to a native module,
|
||||
see [jerry_set_object_native_pointer](#jerry_set_object_native_pointer)
|
||||
- When `callback` is `NULL`, no function is called when the module is evaluated,
|
||||
only its state is changed to evaluated.
|
||||
- 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_native_module_create (jerry_native_module_evaluate_callback_t callback,
|
||||
const jerry_value_t * const exports_p,
|
||||
size_t number_of_exports);
|
||||
```
|
||||
|
||||
- `callback` - a [jerry_native_module_evaluate_callback_t](#jerry_native_module_evaluate_callback_t) callback
|
||||
which is called by [jerry_module_evaluate](#jerry_module_evaluate) to evaluate the native module.
|
||||
- `exports_p` - list of the exported bindings of the module, must be valid string identifiers.
|
||||
- `number_of_exports` - number of exports in the `exports_p` list.
|
||||
- return
|
||||
- a native module, if the module is successfully created
|
||||
- error, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t exports[2] =
|
||||
{
|
||||
jerry_create_string ((const jerry_char_t *) "first_export"),
|
||||
jerry_create_string ((const jerry_char_t *) "second_export")
|
||||
};
|
||||
|
||||
jerry_value_t native_module = jerry_native_module_create (NULL, exports, 2);
|
||||
|
||||
jerry_release_value (exports[0]);
|
||||
jerry_release_value (exports[1]);
|
||||
jerry_release_value (native_module);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_module_link](#jerry_module_link)
|
||||
- [jerry_module_evaluate](#jerry_module_evaluate)
|
||||
- [jerry_native_module_get_export](#jerry_native_module_get_export)
|
||||
- [jerry_native_module_set_export](#jerry_native_module_set_export)
|
||||
|
||||
## jerry_native_module_get_export
|
||||
|
||||
Gets the value of an export binding which belongs to a native 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_native_module_get_export (const jerry_value_t native_module_val,
|
||||
const jerry_value_t export_name_val);
|
||||
```
|
||||
|
||||
- `module_val` - a native module object.
|
||||
- `export_name_val` - string identifier of the export.
|
||||
- return
|
||||
- value of the export, if success
|
||||
- error, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t export = jerry_create_string ((const jerry_char_t *) "an_export");
|
||||
|
||||
jerry_value_t native_module = jerry_native_module_create (NULL, &export, 1);
|
||||
|
||||
jerry_value_t value = jerry_native_module_get_export (native_module, export);
|
||||
jerry_release_value (value);
|
||||
|
||||
jerry_release_value (export);
|
||||
jerry_release_value (native_module);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_native_module_create](#jerry_native_module_create)
|
||||
- [jerry_native_module_set_export](#jerry_native_module_set_export)
|
||||
|
||||
## jerry_native_module_set_export
|
||||
|
||||
Sets the value of an export binding which belongs to a native 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_value_t jerry_native_module_set_export (const jerry_value_t native_mmodule_val,
|
||||
const jerry_value_t export_name_val,
|
||||
const jerry_value_t value_to_set)
|
||||
```
|
||||
|
||||
- `module_val` - a native module object.
|
||||
- `export_name_val` - string identifier of the export.
|
||||
- `value_to_set` - new value of the export.
|
||||
- return
|
||||
- true, if success
|
||||
- error, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include <jerryscript.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t export = jerry_create_string ((const jerry_char_t *) "an_export");
|
||||
|
||||
jerry_value_t native_module = jerry_native_module_create (NULL, &export, 1);
|
||||
|
||||
jerry_value_t number = jerry_create_number (3.5);
|
||||
jerry_value_t value = jerry_native_module_set_export (native_module, export, number);
|
||||
jerry_release_value (value);
|
||||
jerry_release_value (number);
|
||||
|
||||
jerry_release_value (export);
|
||||
jerry_release_value (native_module);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_native_module_create](#jerry_native_module_create)
|
||||
- [jerry_native_module_get_export](#jerry_native_module_get_export)
|
||||
|
||||
# Functions for promise objects
|
||||
|
||||
These APIs all depend on the es.next profile (or on some build options).
|
||||
|
||||
@ -445,7 +445,7 @@ jerry_parse (const jerry_char_t *source_p, /**< script source */
|
||||
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
|
||||
{
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_initialize_context ();
|
||||
JERRY_CONTEXT (module_current_p) = ecma_module_create ();
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG (ecma_error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
@ -474,7 +474,7 @@ jerry_parse (const jerry_char_t *source_p, /**< script source */
|
||||
if (JERRY_UNLIKELY (parse_opts & JERRY_PARSE_MODULE))
|
||||
{
|
||||
ecma_module_t *module_p = JERRY_CONTEXT (module_current_p);
|
||||
module_p->compiled_code_p = bytecode_data_p;
|
||||
module_p->u.compiled_code_p = bytecode_data_p;
|
||||
|
||||
JERRY_CONTEXT (module_current_p) = NULL;
|
||||
|
||||
@ -844,7 +844,7 @@ jerry_module_get_request (const jerry_value_t module_val, /**< module */
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return object - if namespace object is available,
|
||||
* error - otherwise
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_module_get_namespace (const jerry_value_t module_val) /**< module */
|
||||
@ -879,6 +879,221 @@ jerry_module_get_namespace (const jerry_value_t module_val) /**< module */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_module_get_namespace */
|
||||
|
||||
/**
|
||||
* Creates a native module with a list of exports. The initial state of the module is linked.
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return native module - if the module is successfully created,
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_native_module_create (jerry_native_module_evaluate_callback_t callback, /**< evaluation callback for
|
||||
* native modules */
|
||||
const jerry_value_t * const exports_p, /**< list of the exported bindings of the module,
|
||||
* must be valid string identifiers */
|
||||
size_t number_of_exports) /**< number of exports in the exports_p list */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
ecma_object_t *scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p));
|
||||
ecma_module_names_t *local_exports_p = NULL;
|
||||
|
||||
for (size_t i = 0; i < number_of_exports; i++)
|
||||
{
|
||||
if (!ecma_is_value_string (exports_p[i]))
|
||||
{
|
||||
ecma_deref_object (scope_p);
|
||||
ecma_module_release_module_names (local_exports_p);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Module exports must be string values")));
|
||||
}
|
||||
|
||||
ecma_string_t *name_str_p = ecma_get_string_from_value (exports_p[i]);
|
||||
|
||||
bool valid_identifier = false;
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (name_str_p, name_start_p, name_size);
|
||||
|
||||
if (name_size > 0)
|
||||
{
|
||||
const lit_utf8_byte_t *name_p = name_start_p;
|
||||
const lit_utf8_byte_t *name_end_p = name_start_p + name_size;
|
||||
lit_code_point_t code_point;
|
||||
|
||||
lit_utf8_size_t size = lit_read_code_point_from_cesu8 (name_p, name_end_p, &code_point);
|
||||
|
||||
if (lit_code_point_is_identifier_start (code_point))
|
||||
{
|
||||
name_p += size;
|
||||
|
||||
valid_identifier = true;
|
||||
|
||||
while (name_p < name_end_p)
|
||||
{
|
||||
size = lit_read_code_point_from_cesu8 (name_p, name_end_p, &code_point);
|
||||
|
||||
if (!lit_code_point_is_identifier_part (code_point))
|
||||
{
|
||||
valid_identifier = false;
|
||||
break;
|
||||
}
|
||||
|
||||
name_p += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ECMA_FINALIZE_UTF8_STRING (name_start_p, name_size);
|
||||
|
||||
if (!valid_identifier)
|
||||
{
|
||||
ecma_deref_object (scope_p);
|
||||
ecma_module_release_module_names (local_exports_p);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Module exports must be valid identifiers")));
|
||||
}
|
||||
|
||||
if (ecma_find_named_property (scope_p, name_str_p) != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_create_named_data_property (scope_p, name_str_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL);
|
||||
|
||||
ecma_module_names_t *new_export_p;
|
||||
new_export_p = (ecma_module_names_t *) jmem_heap_alloc_block (sizeof (ecma_module_names_t));
|
||||
|
||||
new_export_p->next_p = local_exports_p;
|
||||
local_exports_p = new_export_p;
|
||||
|
||||
ecma_ref_ecma_string (name_str_p);
|
||||
new_export_p->imex_name_p = name_str_p;
|
||||
|
||||
ecma_ref_ecma_string (name_str_p);
|
||||
new_export_p->local_name_p = name_str_p;
|
||||
}
|
||||
|
||||
ecma_module_t *module_p = ecma_module_create ();
|
||||
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_LINKED;
|
||||
module_p->header.u.cls.u2.module_flags |= ECMA_MODULE_IS_NATIVE;
|
||||
module_p->scope_p = scope_p;
|
||||
module_p->local_exports_p = local_exports_p;
|
||||
module_p->u.callback = callback;
|
||||
|
||||
ecma_deref_object (scope_p);
|
||||
|
||||
return ecma_make_object_value (&module_p->header.object);
|
||||
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (callback);
|
||||
JERRY_UNUSED (exports_p);
|
||||
JERRY_UNUSED (number_of_exports);
|
||||
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_native_module_create */
|
||||
|
||||
/**
|
||||
* Gets the value of an export which belongs to a native module.
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return value of the export - if success
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_native_module_get_export (const jerry_value_t native_module_val, /**< a native module object */
|
||||
const jerry_value_t export_name_val) /**< string identifier of the export */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (native_module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_not_module_p)));
|
||||
}
|
||||
|
||||
if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)
|
||||
|| !ecma_is_value_string (export_name_val))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)));
|
||||
}
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (module_p->scope_p,
|
||||
ecma_get_string_from_value (export_name_val));
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_unknown_export_p)));
|
||||
}
|
||||
|
||||
return ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (native_module_val);
|
||||
JERRY_UNUSED (export_name_val);
|
||||
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_native_module_get_export */
|
||||
|
||||
/**
|
||||
* Sets the value of an export which belongs to a native module.
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||
*
|
||||
* @return true value - if the operation was successful
|
||||
* error - otherwise
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_native_module_set_export (const jerry_value_t native_module_val, /**< a native module object */
|
||||
const jerry_value_t export_name_val, /**< string identifier of the export */
|
||||
const jerry_value_t value_to_set) /**< new value of the export */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_module_t *module_p = ecma_module_get_resolved_module (native_module_val);
|
||||
|
||||
if (module_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_not_module_p)));
|
||||
}
|
||||
|
||||
if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)
|
||||
|| !ecma_is_value_string (export_name_val)
|
||||
|| ecma_is_value_error_reference (value_to_set))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)));
|
||||
}
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (module_p->scope_p,
|
||||
ecma_get_string_from_value (export_name_val));
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_unknown_export_p)));
|
||||
}
|
||||
|
||||
ecma_named_data_property_assign_value (module_p->scope_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
value_to_set);
|
||||
return ECMA_VALUE_TRUE;
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_UNUSED (native_module_val);
|
||||
JERRY_UNUSED (export_name_val);
|
||||
JERRY_UNUSED (value_to_set);
|
||||
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_module_not_supported_p)));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
} /* jerry_native_module_set_export */
|
||||
|
||||
/**
|
||||
* Run enqueued Promise jobs until the first thrown error or until all get executed.
|
||||
*
|
||||
|
||||
@ -81,6 +81,11 @@ const char * const ecma_error_bigint_not_supported_p = "BigInt support is disabl
|
||||
* Error message, if argument is not a module
|
||||
*/
|
||||
const char * const ecma_error_not_module_p = "Argument is not a module";
|
||||
|
||||
/**
|
||||
* Error message, if a native module export is not found
|
||||
*/
|
||||
const char * const ecma_error_unknown_export_p = "Native module export not found";
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
/**
|
||||
* Error message, if Module support is disabled
|
||||
|
||||
@ -53,6 +53,7 @@ extern const char * const ecma_error_bigint_not_supported_p;
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
extern const char * const ecma_error_not_module_p;
|
||||
extern const char * const ecma_error_unknown_export_p;
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
extern const char * const ecma_error_module_not_supported_p;
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
@ -1059,6 +1059,9 @@ typedef struct
|
||||
union
|
||||
{
|
||||
uint16_t formal_params_number; /**< for arguments: formal parameters number */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
uint8_t module_flags; /**< Module flags */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
#if JERRY_ESNEXT
|
||||
uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */
|
||||
uint16_t executable_obj_flags; /**< executable object flags */
|
||||
|
||||
@ -1313,13 +1313,13 @@ ecma_substring_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, /**< ecm
|
||||
while (start_pos--)
|
||||
{
|
||||
ecma_char_t ch;
|
||||
lit_utf8_size_t code_unit_size = lit_read_code_unit_from_utf8 (cesu8_str_p, &ch);
|
||||
lit_utf8_size_t code_unit_size = lit_read_code_unit_from_cesu8 (cesu8_str_p, &ch);
|
||||
|
||||
cesu8_str_p += code_unit_size;
|
||||
if ((cesu8_str_p != cesu8_end_pos) && lit_is_code_point_utf16_high_surrogate (ch))
|
||||
{
|
||||
ecma_char_t next_ch;
|
||||
lit_utf8_size_t next_ch_size = lit_read_code_unit_from_utf8 (cesu8_str_p, &next_ch);
|
||||
lit_utf8_size_t next_ch_size = lit_read_code_unit_from_cesu8 (cesu8_str_p, &next_ch);
|
||||
if (lit_is_code_point_utf16_low_surrogate (next_ch))
|
||||
{
|
||||
JERRY_ASSERT (code_unit_size == next_ch_size);
|
||||
@ -1336,7 +1336,7 @@ ecma_substring_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, /**< ecm
|
||||
while (end_pos--)
|
||||
{
|
||||
ecma_char_t ch;
|
||||
lit_utf8_size_t code_unit_size = lit_read_code_unit_from_utf8 (cesu8_pos, &ch);
|
||||
lit_utf8_size_t code_unit_size = lit_read_code_unit_from_cesu8 (cesu8_pos, &ch);
|
||||
|
||||
if ((size + code_unit_size) > buffer_size)
|
||||
{
|
||||
@ -1346,7 +1346,7 @@ ecma_substring_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, /**< ecm
|
||||
if (((cesu8_pos + code_unit_size) != cesu8_end_pos) && lit_is_code_point_utf16_high_surrogate (ch))
|
||||
{
|
||||
ecma_char_t next_ch;
|
||||
lit_utf8_size_t next_ch_size = lit_read_code_unit_from_utf8 (cesu8_pos + code_unit_size, &next_ch);
|
||||
lit_utf8_size_t next_ch_size = lit_read_code_unit_from_cesu8 (cesu8_pos + code_unit_size, &next_ch);
|
||||
|
||||
if (lit_is_code_point_utf16_low_surrogate (next_ch))
|
||||
{
|
||||
@ -2482,7 +2482,7 @@ ecma_string_trim_front (const lit_utf8_byte_t *start_p, /**< current string's st
|
||||
|
||||
while (start_p < end_p)
|
||||
{
|
||||
lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (start_p, &ch);
|
||||
lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (start_p, &ch);
|
||||
|
||||
if (!lit_char_is_white_space (ch))
|
||||
{
|
||||
@ -2655,7 +2655,7 @@ ecma_string_pad (ecma_value_t original_string_p, /**< Input ecma string */
|
||||
while (remaining > 0)
|
||||
{
|
||||
ecma_char_t ch;
|
||||
lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (temp_start_p, &ch);
|
||||
lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (temp_start_p, &ch);
|
||||
ecma_stringbuilder_append_char (&builder, ch);
|
||||
temp_start_p += read_size;
|
||||
remaining--;
|
||||
|
||||
@ -30,9 +30,11 @@
|
||||
|
||||
/**
|
||||
* Initialize context variables for the root module.
|
||||
*
|
||||
* @return new module
|
||||
*/
|
||||
void
|
||||
ecma_module_initialize_context (void)
|
||||
ecma_module_t *
|
||||
ecma_module_create (void)
|
||||
{
|
||||
JERRY_ASSERT (JERRY_CONTEXT (module_current_p) == NULL);
|
||||
|
||||
@ -41,19 +43,20 @@ ecma_module_initialize_context (void)
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_MODULE;
|
||||
ext_object_p->u.cls.u1.module_state = JERRY_MODULE_STATE_UNLINKED;
|
||||
ext_object_p->u.cls.u2.module_flags = 0;
|
||||
|
||||
ecma_module_t *module_p = (ecma_module_t *) obj_p;
|
||||
|
||||
module_p->scope_p = NULL;
|
||||
module_p->namespace_object_p = NULL;
|
||||
module_p->imports_p = NULL;
|
||||
module_p->local_exports_p = NULL;
|
||||
module_p->indirect_exports_p = NULL;
|
||||
module_p->star_exports_p = NULL;
|
||||
module_p->compiled_code_p = NULL;
|
||||
module_p->scope_p = NULL;
|
||||
module_p->namespace_object_p = NULL;
|
||||
module_p->u.compiled_code_p = NULL;
|
||||
|
||||
JERRY_CONTEXT (module_current_p) = module_p;
|
||||
} /* ecma_module_initialize_context */
|
||||
return module_p;
|
||||
} /* ecma_module_create */
|
||||
|
||||
/**
|
||||
* cleanup context variables for the root module.
|
||||
@ -219,30 +222,6 @@ ecma_module_resolve_export (ecma_module_t *const module_p, /**< base module */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_module_p->header.u.cls.u1.module_state == 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),
|
||||
object_p,
|
||||
current_export_name_p);
|
||||
if (ecma_is_value_found (prop_value))
|
||||
{
|
||||
found = true;
|
||||
found_record.module_p = current_module_p;
|
||||
found_record.name_p = current_export_name_p;
|
||||
ecma_free_value (prop_value);
|
||||
}
|
||||
|
||||
if (ecma_compare_ecma_string_to_magic_id (current_export_name_p, LIT_MAGIC_STRING_DEFAULT))
|
||||
{
|
||||
ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("No default export in native module"));
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_module_resolve_stack_pop (&stack_p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_module_p->local_exports_p != NULL)
|
||||
{
|
||||
/* 15.2.1.16.3 / 4 */
|
||||
@ -398,20 +377,40 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATING;
|
||||
|
||||
ecma_value_t ret_value;
|
||||
ret_value = vm_run_module (module_p);
|
||||
|
||||
if (module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)
|
||||
{
|
||||
ret_value = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
if (module_p->u.callback)
|
||||
{
|
||||
ret_value = module_p->u.callback (ecma_make_object_value (&module_p->header.object));
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_is_value_error_reference (ret_value)))
|
||||
{
|
||||
ecma_raise_error_from_error_reference (ret_value);
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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))
|
||||
{
|
||||
ecma_free_value (ret_value);
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATED;
|
||||
ret_value = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
ecma_bytecode_deref (module_p->compiled_code_p);
|
||||
module_p->compiled_code_p = NULL;
|
||||
if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE))
|
||||
{
|
||||
ecma_bytecode_deref (module_p->u.compiled_code_p);
|
||||
}
|
||||
|
||||
module_p->u.compiled_code_p = NULL;
|
||||
return ret_value;
|
||||
} /* ecma_module_evaluate */
|
||||
|
||||
@ -646,6 +645,8 @@ ecma_module_connect_imports (ecma_module_t *module_p)
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_free_value (result);
|
||||
|
||||
while (import_names_p != NULL)
|
||||
{
|
||||
const bool is_namespace_import = ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p,
|
||||
@ -682,29 +683,11 @@ 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.cls.u1.module_state == JERRY_MODULE_STATE_NATIVE)
|
||||
{
|
||||
ecma_object_t *object_p = record.module_p->namespace_object_p;
|
||||
ecma_value_t prop_value;
|
||||
ecma_property_t *property_p = ecma_find_named_property (record.module_p->scope_p, record.name_p);
|
||||
|
||||
prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p), object_p, record.name_p);
|
||||
JERRY_ASSERT (ecma_is_value_found (prop_value));
|
||||
|
||||
ecma_property_value_t *value_p;
|
||||
value_p = ecma_create_named_data_property (module_p->scope_p,
|
||||
import_names_p->local_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
NULL);
|
||||
value_p->value = ecma_copy_value_if_not_object (prop_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (record.module_p->scope_p, record.name_p);
|
||||
|
||||
ecma_create_named_reference_property (module_p->scope_p,
|
||||
import_names_p->local_name_p,
|
||||
property_p);
|
||||
}
|
||||
ecma_create_named_reference_property (module_p->scope_p,
|
||||
import_names_p->local_name_p,
|
||||
property_p);
|
||||
}
|
||||
|
||||
import_names_p = import_names_p->next_p;
|
||||
@ -1074,21 +1057,22 @@ ecma_module_release_module (ecma_module_t *module_p) /**< module */
|
||||
module_p->namespace_object_p = NULL;
|
||||
#endif /* JERRY_NDEBUG */
|
||||
|
||||
if (state == JERRY_MODULE_STATE_NATIVE)
|
||||
ecma_module_release_module_names (module_p->local_exports_p);
|
||||
|
||||
if (module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_module_release_module_nodes (module_p->imports_p, true);
|
||||
ecma_module_release_module_names (module_p->local_exports_p);
|
||||
ecma_module_release_module_nodes (module_p->indirect_exports_p, false);
|
||||
ecma_module_release_module_nodes (module_p->star_exports_p, false);
|
||||
|
||||
if (module_p->compiled_code_p != NULL)
|
||||
if (module_p->u.compiled_code_p != NULL)
|
||||
{
|
||||
ecma_bytecode_deref (module_p->compiled_code_p);
|
||||
ecma_bytecode_deref (module_p->u.compiled_code_p);
|
||||
#ifndef JERRY_NDEBUG
|
||||
module_p->compiled_code_p = NULL;
|
||||
module_p->u.compiled_code_p = NULL;
|
||||
#endif /* JERRY_NDEBUG */
|
||||
}
|
||||
} /* ecma_module_release_module */
|
||||
|
||||
@ -23,6 +23,14 @@
|
||||
|
||||
#define ECMA_MODULE_MAX_PATH 255u
|
||||
|
||||
/**
|
||||
* Module status flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_MODULE_IS_NATIVE = (1 << 0), /**< native module */
|
||||
} ecma_module_flags_t;
|
||||
|
||||
/**
|
||||
* Imported or exported names, such as "a as b"
|
||||
* Note: See https://www.ecma-international.org/ecma-262/6.0/#table-39
|
||||
@ -47,13 +55,19 @@ typedef struct ecma_module
|
||||
/* Note: state is stored in header.u.class_prop.extra_info */
|
||||
ecma_extended_object_t header; /**< header part */
|
||||
/* TODO(dbatyai): These could be compressed pointers */
|
||||
ecma_object_t *scope_p; /**< lexical lenvironment of the module */
|
||||
ecma_object_t *namespace_object_p; /**< namespace object of the module */
|
||||
struct ecma_module_node *imports_p; /**< import requests of the module */
|
||||
ecma_module_names_t *local_exports_p; /**< local exports of the module */
|
||||
struct ecma_module_node *indirect_exports_p; /**< indirect exports of the module */
|
||||
struct ecma_module_node *star_exports_p; /**< star exports of the module */
|
||||
ecma_compiled_code_t *compiled_code_p; /**< compiled code for the module */
|
||||
ecma_object_t *scope_p; /**< lexical lenvironment of the module */
|
||||
ecma_object_t *namespace_object_p; /**< namespace object of the module */
|
||||
|
||||
/* Code used for evaluating a module */
|
||||
union
|
||||
{
|
||||
ecma_compiled_code_t *compiled_code_p; /**< compiled code for the module */
|
||||
jerry_native_module_evaluate_callback_t callback; /**< callback for evaluating native modules */
|
||||
} u;
|
||||
} ecma_module_t;
|
||||
|
||||
/**
|
||||
@ -114,7 +128,7 @@ ecma_value_t ecma_module_link (ecma_module_t *module_p,
|
||||
void *user_p);
|
||||
ecma_value_t ecma_module_evaluate (ecma_module_t *module_p);
|
||||
|
||||
void ecma_module_initialize_context (void);
|
||||
ecma_module_t *ecma_module_create (void);
|
||||
void ecma_module_cleanup_context (void);
|
||||
ecma_value_t ecma_module_create_namespace_object (ecma_module_t *module_p);
|
||||
|
||||
|
||||
@ -351,7 +351,7 @@ ecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /*
|
||||
|
||||
while (input_char_p < input_end_p)
|
||||
{
|
||||
input_char_p += lit_read_code_unit_from_utf8 (input_char_p, &ch);
|
||||
input_char_p += lit_read_code_unit_from_cesu8 (input_char_p, &ch);
|
||||
|
||||
if (lit_is_code_point_utf16_low_surrogate (ch))
|
||||
{
|
||||
@ -370,7 +370,7 @@ ecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /*
|
||||
}
|
||||
|
||||
ecma_char_t next_ch;
|
||||
lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (input_char_p, &next_ch);
|
||||
lit_utf8_size_t read_size = lit_read_code_unit_from_cesu8 (input_char_p, &next_ch);
|
||||
|
||||
if (lit_is_code_point_utf16_low_surrogate (next_ch))
|
||||
{
|
||||
|
||||
@ -273,6 +273,14 @@ 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);
|
||||
|
||||
jerry_value_t jerry_native_module_create (jerry_native_module_evaluate_callback_t callback,
|
||||
const jerry_value_t * const exports_p, size_t number_of_exports);
|
||||
jerry_value_t jerry_native_module_get_export (const jerry_value_t native_mmodule_val,
|
||||
const jerry_value_t export_name_val);
|
||||
jerry_value_t jerry_native_module_set_export (const jerry_value_t native_mmodule_val,
|
||||
const jerry_value_t export_name_val,
|
||||
const jerry_value_t value_to_set);
|
||||
|
||||
/**
|
||||
* Promise functions.
|
||||
*/
|
||||
|
||||
@ -541,7 +541,6 @@ typedef enum
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -551,6 +550,11 @@ 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 by jerry_module_evaluate to evaluate the native module.
|
||||
*/
|
||||
typedef jerry_value_t (*jerry_native_module_evaluate_callback_t) (const jerry_value_t native_module);
|
||||
|
||||
/**
|
||||
* Proxy related types.
|
||||
*/
|
||||
|
||||
@ -321,7 +321,7 @@ lit_get_utf8_size_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< cesu
|
||||
while (offset < cesu8_buf_size)
|
||||
{
|
||||
ecma_char_t ch;
|
||||
offset += lit_read_code_unit_from_utf8 (cesu8_buf_p + offset, &ch);
|
||||
offset += lit_read_code_unit_from_cesu8 (cesu8_buf_p + offset, &ch);
|
||||
|
||||
if (lit_is_code_point_utf16_low_surrogate (ch) && lit_is_code_point_utf16_high_surrogate (prev_ch))
|
||||
{
|
||||
@ -352,7 +352,7 @@ lit_get_utf8_length_of_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, /**< ce
|
||||
while (offset < cesu8_buf_size)
|
||||
{
|
||||
ecma_char_t ch;
|
||||
offset += lit_read_code_unit_from_utf8 (cesu8_buf_p + offset, &ch);
|
||||
offset += lit_read_code_unit_from_cesu8 (cesu8_buf_p + offset, &ch);
|
||||
|
||||
if (!lit_is_code_point_utf16_low_surrogate (ch) || !lit_is_code_point_utf16_high_surrogate (prev_ch))
|
||||
{
|
||||
@ -423,20 +423,21 @@ lit_read_code_point_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with ch
|
||||
* @return number of bytes occupied by code point in the string
|
||||
*/
|
||||
lit_utf8_size_t
|
||||
lit_read_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */
|
||||
ecma_char_t *code_point) /**< [out] code point */
|
||||
lit_read_code_unit_from_cesu8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */
|
||||
ecma_char_t *code_unit) /**< [out] code unit */
|
||||
{
|
||||
JERRY_ASSERT (buf_p);
|
||||
|
||||
lit_utf8_byte_t c = buf_p[0];
|
||||
if ((c & LIT_UTF8_1_BYTE_MASK) == LIT_UTF8_1_BYTE_MARKER)
|
||||
{
|
||||
*code_point = (ecma_char_t) (c & LIT_UTF8_LAST_7_BITS_MASK);
|
||||
*code_unit = (ecma_char_t) (c & LIT_UTF8_LAST_7_BITS_MASK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lit_code_point_t ret = LIT_UNICODE_CODE_POINT_NULL;
|
||||
lit_utf8_size_t bytes_count;
|
||||
|
||||
if ((c & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER)
|
||||
{
|
||||
bytes_count = 2;
|
||||
@ -456,9 +457,47 @@ lit_read_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer with cha
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ret <= LIT_UTF16_CODE_UNIT_MAX);
|
||||
*code_point = (ecma_char_t) ret;
|
||||
*code_unit = (ecma_char_t) ret;
|
||||
return bytes_count;
|
||||
} /* lit_read_code_unit_from_utf8 */
|
||||
} /* lit_read_code_unit_from_cesu8 */
|
||||
|
||||
/**
|
||||
* Decodes a unicode code point from non-empty cesu-8-encoded buffer
|
||||
*
|
||||
* @return number of bytes occupied by code point in the string
|
||||
*/
|
||||
lit_utf8_size_t
|
||||
lit_read_code_point_from_cesu8 (const lit_utf8_byte_t *buf_p, /**< buffer with characters */
|
||||
const lit_utf8_byte_t *buf_end_p, /**< buffer end */
|
||||
lit_code_point_t *code_point) /**< [out] code point */
|
||||
{
|
||||
ecma_char_t code_unit;
|
||||
lit_utf8_size_t size = lit_read_code_unit_from_cesu8 (buf_p, &code_unit);
|
||||
|
||||
JERRY_ASSERT (buf_p + size <= buf_end_p);
|
||||
|
||||
if (lit_is_code_point_utf16_high_surrogate (code_unit))
|
||||
{
|
||||
buf_p += size;
|
||||
|
||||
if (buf_p < buf_end_p)
|
||||
{
|
||||
ecma_char_t next_code_unit;
|
||||
lit_utf8_size_t next_size = lit_read_code_unit_from_cesu8 (buf_p, &next_code_unit);
|
||||
|
||||
if (lit_is_code_point_utf16_low_surrogate (next_code_unit))
|
||||
{
|
||||
JERRY_ASSERT (buf_p + next_size <= buf_end_p);
|
||||
|
||||
*code_point = lit_convert_surrogate_pair_to_code_point (code_unit, next_code_unit);
|
||||
return size + next_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*code_point = code_unit;
|
||||
return size;
|
||||
} /* lit_read_code_point_from_cesu8 */
|
||||
|
||||
/**
|
||||
* Decodes a unicode code unit from non-empty cesu-8-encoded buffer
|
||||
@ -472,7 +511,7 @@ lit_read_prev_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p, /**< buffer wit
|
||||
JERRY_ASSERT (buf_p);
|
||||
|
||||
lit_utf8_decr (&buf_p);
|
||||
return lit_read_code_unit_from_utf8 (buf_p, code_point);
|
||||
return lit_read_code_unit_from_cesu8 (buf_p, code_point);
|
||||
} /* lit_read_prev_code_unit_from_utf8 */
|
||||
|
||||
/**
|
||||
@ -486,7 +525,7 @@ lit_cesu8_read_next (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with ch
|
||||
JERRY_ASSERT (*buf_p);
|
||||
ecma_char_t ch;
|
||||
|
||||
*buf_p += lit_read_code_unit_from_utf8 (*buf_p, &ch);
|
||||
*buf_p += lit_read_code_unit_from_cesu8 (*buf_p, &ch);
|
||||
|
||||
return ch;
|
||||
} /* lit_cesu8_read_next */
|
||||
@ -503,7 +542,7 @@ lit_cesu8_read_prev (const lit_utf8_byte_t **buf_p) /**< [in,out] buffer with ch
|
||||
ecma_char_t ch;
|
||||
|
||||
lit_utf8_decr (buf_p);
|
||||
lit_read_code_unit_from_utf8 (*buf_p, &ch);
|
||||
lit_read_code_unit_from_cesu8 (*buf_p, &ch);
|
||||
|
||||
return ch;
|
||||
} /* lit_cesu8_read_prev */
|
||||
@ -519,7 +558,7 @@ lit_cesu8_peek_next (const lit_utf8_byte_t *buf_p) /**< [in,out] buffer with cha
|
||||
JERRY_ASSERT (buf_p != NULL);
|
||||
ecma_char_t ch;
|
||||
|
||||
lit_read_code_unit_from_utf8 (buf_p, &ch);
|
||||
lit_read_code_unit_from_cesu8 (buf_p, &ch);
|
||||
|
||||
return ch;
|
||||
} /* lit_cesu8_peek_next */
|
||||
@ -631,7 +670,7 @@ lit_utf8_string_code_unit_at (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 stri
|
||||
do
|
||||
{
|
||||
JERRY_ASSERT (current_p < utf8_buf_p + utf8_buf_size);
|
||||
current_p += lit_read_code_unit_from_utf8 (current_p, &code_unit);
|
||||
current_p += lit_read_code_unit_from_cesu8 (current_p, &code_unit);
|
||||
}
|
||||
while (code_unit_offset--);
|
||||
|
||||
@ -827,7 +866,7 @@ lit_convert_cesu8_string_to_utf8_string (const lit_utf8_byte_t *cesu8_string, /*
|
||||
while (cesu8_pos < cesu8_end_pos)
|
||||
{
|
||||
ecma_char_t ch;
|
||||
lit_utf8_size_t code_unit_size = lit_read_code_unit_from_utf8 (cesu8_pos, &ch);
|
||||
lit_utf8_size_t code_unit_size = lit_read_code_unit_from_cesu8 (cesu8_pos, &ch);
|
||||
|
||||
if (lit_is_code_point_utf16_low_surrogate (ch) && lit_is_code_point_utf16_high_surrogate (prev_ch))
|
||||
{
|
||||
@ -900,8 +939,8 @@ bool lit_compare_utf8_strings_relational (const lit_utf8_byte_t *string1_p, /**<
|
||||
while (string1_pos < string1_end_p && string2_pos < string2_end_p)
|
||||
{
|
||||
ecma_char_t ch1, ch2;
|
||||
string1_pos += lit_read_code_unit_from_utf8 (string1_pos, &ch1);
|
||||
string2_pos += lit_read_code_unit_from_utf8 (string2_pos, &ch2);
|
||||
string1_pos += lit_read_code_unit_from_cesu8 (string1_pos, &ch1);
|
||||
string2_pos += lit_read_code_unit_from_cesu8 (string2_pos, &ch2);
|
||||
|
||||
if (ch1 < ch2)
|
||||
{
|
||||
|
||||
@ -129,8 +129,10 @@ uint8_t lit_utf16_encode_code_point (lit_code_point_t cp, ecma_char_t *cu_p);
|
||||
lit_utf8_size_t lit_read_code_point_from_utf8 (const lit_utf8_byte_t *buf_p, lit_utf8_size_t buf_size,
|
||||
lit_code_point_t *code_point);
|
||||
|
||||
lit_utf8_size_t lit_read_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p,
|
||||
ecma_char_t *code_point);
|
||||
lit_utf8_size_t lit_read_code_unit_from_cesu8 (const lit_utf8_byte_t *buf_p,
|
||||
ecma_char_t *code_unit);
|
||||
lit_utf8_size_t lit_read_code_point_from_cesu8 (const lit_utf8_byte_t *buf_p, const lit_utf8_byte_t *buf_end_p,
|
||||
lit_code_point_t *code_point);
|
||||
|
||||
lit_utf8_size_t lit_read_prev_code_unit_from_utf8 (const lit_utf8_byte_t *buf_p,
|
||||
ecma_char_t *code_point);
|
||||
|
||||
@ -426,7 +426,7 @@ vm_run_module (ecma_module_t *module_p) /**< module to be executed */
|
||||
}
|
||||
|
||||
vm_frame_ctx_shared_t shared;
|
||||
shared.bytecode_header_p = module_p->compiled_code_p;
|
||||
shared.bytecode_header_p = module_p->u.compiled_code_p;
|
||||
shared.status_flags = 0;
|
||||
|
||||
return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p);
|
||||
@ -4933,14 +4933,14 @@ vm_init_module_scope (ecma_module_t *module_p) /**< module without scope */
|
||||
{
|
||||
ecma_object_t *global_object_p;
|
||||
#if JERRY_BUILTIN_REALMS
|
||||
global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->compiled_code_p);
|
||||
global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->u.compiled_code_p);
|
||||
#else /* !JERRY_BUILTIN_REALMS */
|
||||
global_object_p = ecma_builtin_get_global ();
|
||||
#endif /* JERRY_BUILTIN_REALMS */
|
||||
|
||||
ecma_object_t *scope_p = ecma_create_lex_env_class (ecma_get_global_environment (global_object_p),
|
||||
sizeof (ecma_lexical_environment_class_t));
|
||||
const ecma_compiled_code_t *compiled_code_p = module_p->compiled_code_p;
|
||||
const ecma_compiled_code_t *compiled_code_p = module_p->u.compiled_code_p;
|
||||
ecma_value_t *literal_start_p;
|
||||
uint8_t *byte_code_p;
|
||||
uint16_t encoding_limit;
|
||||
|
||||
@ -137,6 +137,93 @@ resolve_callback3 (const jerry_value_t specifier, /**< module specifier */
|
||||
TEST_ASSERT (false);
|
||||
} /* resolve_callback3 */
|
||||
|
||||
static jerry_value_t
|
||||
native_module_evaluate (const jerry_value_t native_module) /**< native module */
|
||||
{
|
||||
++counter;
|
||||
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_EVALUATING);
|
||||
|
||||
jerry_value_t exp_val = jerry_create_string ((const jerry_char_t *) "exp");
|
||||
jerry_value_t other_exp_val = jerry_create_string ((const jerry_char_t *) "other_exp");
|
||||
/* The native module has no such export. */
|
||||
jerry_value_t no_exp_val = jerry_create_string ((const jerry_char_t *) "no_exp");
|
||||
|
||||
jerry_value_t result = jerry_native_module_get_export (native_module, exp_val);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_native_module_get_export (native_module, other_exp_val);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_native_module_get_export (native_module, no_exp_val);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_value_t export = jerry_create_number (3.5);
|
||||
result = jerry_native_module_set_export (native_module, exp_val, export);
|
||||
TEST_ASSERT (jerry_value_is_boolean (result) && jerry_get_boolean_value (result));
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (export);
|
||||
|
||||
export = jerry_create_string ((const jerry_char_t *) "str");
|
||||
result = jerry_native_module_set_export (native_module, other_exp_val, export);
|
||||
TEST_ASSERT (jerry_value_is_boolean (result) && jerry_get_boolean_value (result));
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (export);
|
||||
|
||||
result = jerry_native_module_set_export (native_module, no_exp_val, no_exp_val);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_native_module_get_export (native_module, exp_val);
|
||||
TEST_ASSERT (jerry_value_is_number (result) && jerry_get_number_value (result) == 3.5);
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_native_module_get_export (native_module, other_exp_val);
|
||||
TEST_ASSERT (jerry_value_is_string (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (exp_val);
|
||||
jerry_release_value (other_exp_val);
|
||||
jerry_release_value (no_exp_val);
|
||||
|
||||
if (counter == 4)
|
||||
{
|
||||
++counter;
|
||||
return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Ooops!");
|
||||
}
|
||||
|
||||
return jerry_create_undefined ();
|
||||
} /* native_module_evaluate */
|
||||
|
||||
static jerry_value_t
|
||||
resolve_callback4 (const jerry_value_t specifier, /**< module specifier */
|
||||
const jerry_value_t referrer, /**< parent module */
|
||||
void *user_p) /**< user data */
|
||||
{
|
||||
(void) specifier;
|
||||
(void) referrer;
|
||||
|
||||
++counter;
|
||||
|
||||
jerry_value_t exports[2] =
|
||||
{
|
||||
jerry_create_string ((const jerry_char_t *) "exp"),
|
||||
jerry_create_string ((const jerry_char_t *) "other_exp")
|
||||
};
|
||||
|
||||
jerry_value_t native_module = jerry_native_module_create (native_module_evaluate, exports, 2);
|
||||
TEST_ASSERT (!jerry_value_is_error (native_module));
|
||||
|
||||
jerry_release_value (exports[0]);
|
||||
jerry_release_value (exports[1]);
|
||||
|
||||
*((jerry_value_t *) user_p) = jerry_acquire_value (native_module);
|
||||
return native_module;
|
||||
} /* resolve_callback4 */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -286,6 +373,97 @@ main (void)
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
module = jerry_native_module_create (NULL, &object, 1);
|
||||
TEST_ASSERT (jerry_value_is_error (module));
|
||||
jerry_release_value (module);
|
||||
|
||||
module = jerry_native_module_create (NULL, NULL, 0);
|
||||
TEST_ASSERT (!jerry_value_is_error (module));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_LINKED);
|
||||
|
||||
result = jerry_native_module_get_export (object, number);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
result = jerry_native_module_set_export (module, number, number);
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
|
||||
/* Valid identifier. */
|
||||
jerry_value_t export = jerry_create_string ((const jerry_char_t *) "\xed\xa0\x83\xed\xb2\x80");
|
||||
|
||||
module = jerry_native_module_create (NULL, &export, 1);
|
||||
TEST_ASSERT (!jerry_value_is_error (module));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_LINKED);
|
||||
|
||||
result = jerry_module_evaluate (module);
|
||||
TEST_ASSERT (jerry_value_is_undefined (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
jerry_release_value (module);
|
||||
jerry_release_value (export);
|
||||
|
||||
/* Invalid identifiers. */
|
||||
export = jerry_create_string ((const jerry_char_t *) "a+");
|
||||
module = jerry_native_module_create (NULL, &export, 1);
|
||||
TEST_ASSERT (jerry_value_is_error (module));
|
||||
jerry_release_value (module);
|
||||
jerry_release_value (export);
|
||||
|
||||
export = jerry_create_string ((const jerry_char_t *) "\xed\xa0\x80");
|
||||
module = jerry_native_module_create (NULL, &export, 1);
|
||||
TEST_ASSERT (jerry_value_is_error (module));
|
||||
jerry_release_value (module);
|
||||
jerry_release_value (export);
|
||||
|
||||
counter = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
jerry_char_t source3[] = TEST_STRING_LITERAL (
|
||||
"import {exp, other_exp as other} from 'native.js'\n"
|
||||
"import * as namespace from 'native.js'\n"
|
||||
"if (exp !== 3.5 || other !== 'str') { throw 'Assertion failed!' }\n"
|
||||
"if (namespace.exp !== 3.5 || namespace.other_exp !== 'str') { throw 'Assertion failed!' }\n"
|
||||
);
|
||||
module = jerry_parse (source3, sizeof (source3) - 1, &module_parse_options);
|
||||
TEST_ASSERT (!jerry_value_is_error (module));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_UNLINKED);
|
||||
|
||||
jerry_value_t native_module;
|
||||
|
||||
result = jerry_module_link (module, resolve_callback4, (void *) &native_module);
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
TEST_ASSERT (counter == i * 2 + 1);
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_LINKED);
|
||||
TEST_ASSERT (jerry_module_get_state (native_module) == JERRY_MODULE_STATE_LINKED);
|
||||
|
||||
result = jerry_module_evaluate (module);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
TEST_ASSERT (!jerry_value_is_error (result));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_EVALUATED);
|
||||
TEST_ASSERT (jerry_module_get_state (native_module) == JERRY_MODULE_STATE_EVALUATED);
|
||||
TEST_ASSERT (counter == 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ASSERT (jerry_value_is_error (result));
|
||||
TEST_ASSERT (jerry_module_get_state (module) == JERRY_MODULE_STATE_ERROR);
|
||||
TEST_ASSERT (jerry_module_get_state (native_module) == JERRY_MODULE_STATE_ERROR);
|
||||
TEST_ASSERT (counter == 5);
|
||||
}
|
||||
|
||||
jerry_release_value (result);
|
||||
jerry_release_value (module);
|
||||
jerry_release_value (native_module);
|
||||
}
|
||||
|
||||
jerry_release_value (object);
|
||||
jerry_release_value (number);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user