Support native modules (#4649)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2021-04-13 16:26:38 +02:00
committed by GitHub
parent 05a4e45ece
commit 7b6743403f
15 changed files with 770 additions and 100 deletions
+5
View File
@@ -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
+1
View File
@@ -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 */
+3
View File
@@ -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 */
+6 -6
View File
@@ -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--;
+47 -63
View File
@@ -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 */
+18 -4
View File
@@ -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))
{