Rework module parsing and execution (#4462)

This patch disables automatic detection of module code, and instead
requires the user to explicitly specify whether to parse a source
as a module or as a script.

To achieve this the jerry_parse API function now takes a new option
which signals that the source should be parsed as a module.

JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai daniel.batyai@h-lab.eu
This commit is contained in:
Dániel Bátyai 2021-01-18 15:33:43 +01:00 committed by GitHub
parent ef8a6a9f39
commit 0fec9135ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 575 additions and 492 deletions

View File

@ -212,8 +212,10 @@ Option bits for [jerry_parse](#jerry_parse) and
- JERRY_PARSE_NO_OPTS - no options passed
- JERRY_PARSE_STRICT_MODE - enable strict mode
- JERRY_PARSE_MODULE - parse source as an ECMAScript module
*New in version 2.0*.
*Changed in version 2.4: Added `JERRY_PARSE_MODULE`.*
## jerry_gc_mode_t

View File

@ -246,10 +246,6 @@ jerry_cleanup (void)
}
}
#if ENABLED (JERRY_MODULE_SYSTEM)
ecma_module_cleanup ();
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
#if ENABLED (JERRY_BUILTIN_PROMISE)
ecma_free_all_enqueued_jobs ();
#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
@ -456,6 +452,15 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
}
#endif /* ENABLED (JERRY_RESOURCE_NAME) */
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
{
#if ENABLED (JERRY_MODULE_SYSTEM)
ecma_module_initialize_context (ecma_get_string_from_value (resource_name));
#else /* !ENABLED (JERRY_MODULE_SYSTEM) */
return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("Module system has been disabled.")));
#endif /* !ENABLED (JERRY_MODULE_SYSTEM) */
}
ecma_compiled_code_t *bytecode_data_p = parser_parse_script (NULL,
0,
source_p,
@ -465,9 +470,44 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
if (JERRY_UNLIKELY (bytecode_data_p == NULL))
{
#if ENABLED (JERRY_MODULE_SYSTEM)
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
{
ecma_module_cleanup_context ();
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
return ecma_create_error_reference_from_context ();
}
#if ENABLED (JERRY_MODULE_SYSTEM)
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
{
if (ECMA_IS_VALUE_ERROR (ecma_module_parse_referenced_modules ()))
{
ecma_bytecode_deref (bytecode_data_p);
ecma_module_cleanup_context ();
return ecma_create_error_reference_from_context ();
}
ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS);
ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) obj_p;
wrapper_p->u.class_prop.class_id = LIT_MAGIC_STRING_RUNNABLE_UL;
wrapper_p->u.class_prop.extra_info = ECMA_RUNNABLE_FLAGS_MODULE;
ecma_module_t *root_module_p = JERRY_CONTEXT (module_current_p);
root_module_p->compiled_code_p = bytecode_data_p;
ECMA_SET_INTERNAL_VALUE_POINTER (wrapper_p->u.class_prop.u.value, root_module_p);
JERRY_CONTEXT (module_current_p) = NULL;
JERRY_CONTEXT (module_list_p) = NULL;
return ecma_make_object_value (obj_p);
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
ecma_object_t *global_object_p = ecma_builtin_get_global ();
#if ENABLED (JERRY_BUILTIN_REALMS)
@ -475,6 +515,9 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p);
/* TODO(dbatyai): For now Scripts continue to return Function objects due to backwards compatibility. This should be
* changed to also return a Runnable object eventually. */
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
ecma_bytecode_deref (bytecode_data_p);
@ -588,15 +631,35 @@ jerry_run (const jerry_value_t func_val) /**< function to run */
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
}
ecma_object_t *func_obj_p = ecma_get_object_from_value (func_val);
ecma_object_t *obj_p = ecma_get_object_from_value (func_val);
if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION
|| ecma_get_object_is_builtin (func_obj_p))
#if ENABLED (JERRY_MODULE_SYSTEM)
if (ecma_object_class_is (obj_p, LIT_MAGIC_STRING_RUNNABLE_UL))
{
ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) obj_p;
JERRY_ASSERT (wrapper_p->u.class_prop.extra_info == ECMA_RUNNABLE_FLAGS_MODULE);
ecma_module_t *root_module_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_module_t, wrapper_p->u.class_prop.u.value);
#if ENABLED (JERRY_BUILTIN_REALMS)
ecma_object_t *global_object_p = (ecma_object_t *) ecma_op_function_get_realm (root_module_p->compiled_code_p);
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
ecma_object_t *global_object_p = ecma_builtin_get_global ();
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
ecma_create_global_lexical_block (global_object_p);
root_module_p->scope_p = ecma_get_global_scope (global_object_p);
return jerry_return (vm_run_module (root_module_p));
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_FUNCTION
|| ecma_get_object_is_builtin (obj_p))
{
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
}
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p;
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);

View File

@ -1630,6 +1630,20 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
break;
}
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_MODULE_SYSTEM)
case LIT_MAGIC_STRING_RUNNABLE_UL:
{
ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) object_p;
JERRY_ASSERT (wrapper_p->u.class_prop.extra_info == ECMA_RUNNABLE_FLAGS_MODULE);
ecma_module_t *root_module_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_module_t,
wrapper_p->u.class_prop.u.value);
ecma_bytecode_deref (root_module_p->compiled_code_p);
ecma_module_cleanup (root_module_p);
break;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
default:
{
/* The undefined id represents an uninitialized class. */

View File

@ -1059,6 +1059,14 @@ typedef struct
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
#if ENABLED (JERRY_ESNEXT)
/**
* Flags for runnable objects.
*/
typedef enum
{
ECMA_RUNNABLE_FLAGS_EMPTY = (0), /**< empty flags */
ECMA_RUNNABLE_FLAGS_MODULE = (1 << 0) /**< runnable is a module */
} ecma_runnable_flags_t;
/**
* Description of arrow function objects.

View File

@ -37,8 +37,9 @@
* @return pointer to ecma_string_t containing the normalized and zero terminated path
*/
ecma_string_t *
ecma_module_create_normalized_path (const uint8_t *char_p, /**< module specifier */
prop_length_t size) /**< size of module specifier */
ecma_module_create_normalized_path (const lit_utf8_byte_t *char_p, /**< module path specifier */
lit_utf8_size_t size, /**< size of module specifier */
ecma_string_t *const base_path_p) /**< base path for the module specifier */
{
JERRY_ASSERT (size > 0);
ecma_string_t *ret_p = NULL;
@ -57,16 +58,13 @@ ecma_module_create_normalized_path (const uint8_t *char_p, /**< module specifier
lit_utf8_byte_t *module_path_p = NULL;
lit_utf8_size_t module_path_size = 0;
/* Check if we have a current module, and use its path as the base path. */
JERRY_ASSERT (JERRY_CONTEXT (module_top_context_p) != NULL);
if (JERRY_CONTEXT (module_top_context_p)->module_p != NULL)
if (base_path_p != NULL)
{
JERRY_ASSERT (JERRY_CONTEXT (module_top_context_p)->module_p->path_p != NULL);
module_path_size = ecma_string_get_size (JERRY_CONTEXT (module_top_context_p)->module_p->path_p);
module_path_size = ecma_string_get_size (base_path_p);
module_path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (module_path_size + 1);
lit_utf8_size_t module_utf8_size;
module_utf8_size = ecma_string_copy_to_utf8_buffer (JERRY_CONTEXT (module_top_context_p)->module_p->path_p,
module_utf8_size = ecma_string_copy_to_utf8_buffer (base_path_p,
module_path_p,
module_path_size);
@ -96,26 +94,39 @@ ecma_module_create_normalized_path (const uint8_t *char_p, /**< module specifier
} /* ecma_module_create_normalized_path */
/**
* Find a module with a specific identifier
* Push a new module into the module list. New modules are inserted after the head module, this way in the end the
* root module remains the first in the list.
*/
static void
ecma_module_list_push (ecma_module_t *module_p)
{
ecma_module_t *head_p = JERRY_CONTEXT (module_list_p);
module_p->next_p = head_p->next_p;
head_p->next_p = module_p;
} /* ecma_module_list_push */
/**
* Lookup a module with a specific identifier.
*
* @return pointer to ecma_module_t, if found
* NULL, otherwise
*/
ecma_module_t *
ecma_module_find_module (ecma_string_t *const path_p) /**< module identifier */
static ecma_module_t *
ecma_module_list_lookup (ecma_string_t *const path_p) /**< module identifier */
{
ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
ecma_module_t *current_p = JERRY_CONTEXT (module_list_p);
while (current_p != NULL)
{
if (ecma_compare_ecma_strings (path_p, current_p->path_p))
{
return current_p;
}
current_p = current_p->next_p;
}
return current_p;
} /* ecma_module_find_module */
return NULL;
} /* ecma_module_list_lookup */
/**
* Create a new module
@ -129,8 +140,7 @@ ecma_module_create_module (ecma_string_t *const path_p) /**< module identifier *
memset (module_p, 0, sizeof (ecma_module_t));
module_p->path_p = path_p;
module_p->next_p = JERRY_CONTEXT (ecma_modules_p);
JERRY_CONTEXT (ecma_modules_p) = module_p;
ecma_module_list_push (module_p);
return module_p;
} /* ecma_module_create_module */
@ -140,9 +150,10 @@ ecma_module_create_module (ecma_string_t *const path_p) /**< module identifier *
* @return pointer to found or newly created module structure
*/
ecma_module_t *
ecma_module_find_or_create_module (ecma_string_t *const path_p) /**< module path */
ecma_module_find_module (ecma_string_t *const path_p) /**< module path */
{
ecma_module_t *module_p = ecma_module_find_module (path_p);
ecma_module_t *module_p = ecma_module_list_lookup (path_p);
if (module_p)
{
ecma_deref_ecma_string (path_p);
@ -150,7 +161,7 @@ ecma_module_find_or_create_module (ecma_string_t *const path_p) /**< module path
}
return ecma_module_create_module (path_p);
} /* ecma_module_find_or_create_module */
} /* ecma_module_find_module */
/**
* Create a new native module
@ -158,28 +169,83 @@ ecma_module_find_or_create_module (ecma_string_t *const path_p) /**< module path
* @return pointer to created module
*/
ecma_module_t *
ecma_module_create_native_module (ecma_string_t *const path_p, /**< module identifier */
ecma_object_t *const namespace_p) /**< module namespace */
ecma_module_find_native_module (ecma_string_t *const path_p)
{
ecma_module_t *module_p = ecma_module_create_module (path_p);
module_p->state = ECMA_MODULE_STATE_NATIVE;
module_p->namespace_object_p = namespace_p;
return module_p;
} /* ecma_module_create_native_module */
ecma_module_t *module_p = ecma_module_list_lookup (path_p);
if (module_p != NULL)
{
return module_p;
}
ecma_value_t native = jerry_port_get_native_module (ecma_make_string_value (path_p));
if (!ecma_is_value_undefined (native))
{
JERRY_ASSERT (ecma_is_value_object (native));
module_p = ecma_module_create_module (path_p);
module_p->state = ECMA_MODULE_STATE_NATIVE;
module_p->namespace_object_p = ecma_get_object_from_value (native);
return module_p;
}
return NULL;
} /* ecma_module_find_native_module */
/**
* Creates a module context.
*
* @return pointer to created module context
* Initialize context variables for the root module.
*/
static ecma_module_context_t *
ecma_module_create_module_context (void)
void
ecma_module_initialize_context (ecma_string_t *root_path_p) /**< root module */
{
ecma_module_context_t *context_p = (ecma_module_context_t *) jmem_heap_alloc_block (sizeof (ecma_module_context_t));
memset (context_p, 0, sizeof (ecma_module_context_t));
JERRY_ASSERT (JERRY_CONTEXT (module_current_p) == NULL);
JERRY_ASSERT (JERRY_CONTEXT (module_list_p) == NULL);
return context_p;
} /* ecma_module_create_module_context */
lit_utf8_size_t path_str_size;
uint8_t flags = ECMA_STRING_FLAG_EMPTY;
const lit_utf8_byte_t *path_str_chars_p = ecma_string_get_chars (root_path_p,
&path_str_size,
NULL,
NULL,
&flags);
ecma_string_t *path_p = ecma_module_create_normalized_path (path_str_chars_p,
path_str_size,
NULL);
if (path_p == NULL)
{
ecma_ref_ecma_string (root_path_p);
path_p = root_path_p;
}
ecma_module_t *module_p = (ecma_module_t *) jmem_heap_alloc_block (sizeof (ecma_module_t));
memset (module_p, 0, sizeof (ecma_module_t));
module_p->path_p = path_p;
/* Root modules are handled differently then the rest of the referenced modules, as the scope and compiled code
* are handled separately. */
module_p->state = ECMA_MODULE_STATE_ROOT;
JERRY_CONTEXT (module_current_p) = module_p;
JERRY_CONTEXT (module_list_p) = module_p;
} /* ecma_module_initialize_context */
/**
* cleanup context variables for the root module.
*/
void
ecma_module_cleanup_context (void)
{
ecma_module_cleanup (JERRY_CONTEXT (module_current_p));
#ifndef JERRY_NDEBUG
JERRY_CONTEXT (module_current_p) = NULL;
JERRY_CONTEXT (module_list_p) = NULL;
#endif /* JERRY_NDEBUG */
} /* ecma_module_cleanup_context */
/**
* Inserts a {module, export_name} record into a resolve set.
@ -190,8 +256,8 @@ ecma_module_create_module_context (void)
*/
bool
ecma_module_resolve_set_insert (ecma_module_resolve_set_t **set_p, /**< [in, out] resolve set */
ecma_module_t * const module_p, /**< module */
ecma_string_t * const export_name_p) /**< export name */
ecma_module_t *const module_p, /**< module */
ecma_string_t *const export_name_p) /**< export name */
{
JERRY_ASSERT (set_p != NULL);
ecma_module_resolve_set_t *current_p = *set_p;
@ -283,8 +349,8 @@ ecma_module_resolve_stack_pop (ecma_module_resolve_stack_t **stack_p) /**< [in,
* ECMA_VALUE_EMPTY - otherwise
*/
static ecma_value_t
ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
ecma_string_t * const export_name_p, /**< export name */
ecma_module_resolve_export (ecma_module_t *const module_p, /**< base module */
ecma_string_t *const export_name_p, /**< export name */
ecma_module_record_t *out_record_p) /**< [out] found module record */
{
ecma_module_resolve_set_t *resolve_set_p = NULL;
@ -302,7 +368,6 @@ ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
ecma_module_t *current_module_p = current_frame_p->module_p;
JERRY_ASSERT (current_module_p->state >= ECMA_MODULE_STATE_PARSED);
ecma_module_context_t *context_p = current_module_p->context_p;
ecma_string_t *current_export_name_p = current_frame_p->export_name_p;
if (!current_frame_p->resolving)
@ -341,11 +406,11 @@ ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
continue;
}
if (context_p->local_exports_p != NULL)
if (current_module_p->local_exports_p != NULL)
{
/* 15.2.1.16.3 / 4 */
JERRY_ASSERT (context_p->local_exports_p->next_p == NULL);
ecma_module_names_t *export_names_p = context_p->local_exports_p->module_names_p;
JERRY_ASSERT (current_module_p->local_exports_p->next_p == NULL);
ecma_module_names_t *export_names_p = current_module_p->local_exports_p->module_names_p;
while (export_names_p != NULL)
{
if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p))
@ -377,7 +442,7 @@ ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
}
/* 15.2.1.16.3 / 5 */
ecma_module_node_t *indirect_export_p = context_p->indirect_exports_p;
ecma_module_node_t *indirect_export_p = current_module_p->indirect_exports_p;
while (indirect_export_p != NULL)
{
ecma_module_names_t *export_names_p = indirect_export_p->module_names_p;
@ -389,6 +454,7 @@ ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
ecma_module_resolve_stack_push (&stack_p,
indirect_export_p->module_request_p,
export_names_p->local_name_p);
break;
}
export_names_p = export_names_p->next_p;
@ -432,7 +498,7 @@ ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
ecma_module_resolve_stack_pop (&stack_p);
/* 15.2.1.16.3 / 10 */
ecma_module_node_t *star_export_p = context_p->star_exports_p;
ecma_module_node_t *star_export_p = current_module_p->star_exports_p;
while (star_export_p != NULL)
{
JERRY_ASSERT (star_export_p->module_names_p == NULL);
@ -493,12 +559,9 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
module_p->state = ECMA_MODULE_STATE_EVALUATING;
module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p));
module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
ecma_value_t ret_value;
ret_value = vm_run_module (module_p->compiled_code_p,
module_p->scope_p);
ret_value = vm_run_module (module_p);
if (!ECMA_IS_VALUE_ERROR (ret_value))
{
@ -506,10 +569,11 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
ret_value = ECMA_VALUE_EMPTY;
}
JERRY_CONTEXT (module_top_context_p) = module_p->context_p->parent_p;
ecma_bytecode_deref (module_p->compiled_code_p);
module_p->state = ECMA_MODULE_STATE_EVALUATED;
ecma_bytecode_deref (module_p->compiled_code_p);
#ifndef JERRY_NDEBUG
module_p->compiled_code_p = NULL;
#endif /* JERRY_NDEBUG */
return ret_value;
} /* ecma_module_evaluate */
@ -597,7 +661,6 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
{
ecma_module_resolve_stack_t *current_frame_p = stack_p;
ecma_module_t *current_module_p = current_frame_p->module_p;
ecma_module_context_t *context_p = current_module_p->context_p;
ecma_module_resolve_stack_pop (&stack_p);
@ -617,11 +680,11 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
break;
}
if (context_p->local_exports_p != NULL)
if (current_module_p->local_exports_p != NULL)
{
/* 15.2.1.16.2 / 5 */
JERRY_ASSERT (context_p->local_exports_p->next_p == NULL);
ecma_module_names_t *export_names_p = context_p->local_exports_p->module_names_p;
JERRY_ASSERT (current_module_p->local_exports_p->next_p == NULL);
ecma_module_names_t *export_names_p = current_module_p->local_exports_p->module_names_p;
while (export_names_p != NULL && ecma_is_value_empty (result))
{
result = ecma_module_namespace_object_add_export_if_needed (module_p,
@ -631,7 +694,7 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
}
/* 15.2.1.16.2 / 6 */
ecma_module_node_t *indirect_export_p = context_p->indirect_exports_p;
ecma_module_node_t *indirect_export_p = current_module_p->indirect_exports_p;
while (indirect_export_p != NULL && ecma_is_value_empty (result))
{
ecma_module_names_t *export_names_p = indirect_export_p->module_names_p;
@ -645,7 +708,7 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
}
/* 15.2.1.16.2 / 7 */
ecma_module_node_t *star_export_p = context_p->star_exports_p;
ecma_module_node_t *star_export_p = current_module_p->star_exports_p;
while (star_export_p != NULL && ecma_is_value_empty (result))
{
JERRY_ASSERT (star_export_p->module_names_p == NULL);
@ -670,20 +733,18 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
} /* ecma_module_create_namespace_object */
/**
* Connects imported values to the current context.
* Connects imported values to the current module scope.
*
* @return ECMA_VALUE_ERROR - if an error occured
* ECMA_VALUE_EMPTY - otherwise
*/
static ecma_value_t
ecma_module_connect_imports (void)
ecma_module_connect_imports (ecma_module_t *module_p)
{
ecma_module_context_t *current_context_p = JERRY_CONTEXT (module_top_context_p);
ecma_object_t *local_env_p = current_context_p->module_p->scope_p;
ecma_object_t *local_env_p = module_p->scope_p;
JERRY_ASSERT (ecma_is_lexical_environment (local_env_p));
ecma_module_node_t *import_node_p = current_context_p->imports_p;
ecma_module_node_t *import_node_p = module_p->imports_p;
/* Check that the imported bindings don't exist yet. */
while (import_node_p != NULL)
@ -728,7 +789,7 @@ ecma_module_connect_imports (void)
import_node_p = import_node_p->next_p;
}
import_node_p = current_context_p->imports_p;
import_node_p = module_p->imports_p;
/* Resolve imports and create local bindings. */
while (import_node_p != NULL)
@ -823,6 +884,48 @@ ecma_module_connect_imports (void)
return ECMA_VALUE_EMPTY;
} /* ecma_module_connect_imports */
/**
* Checks if indirect exports in the current context are resolvable.
* Note: See 15.2.1.16.4 / 9.
*
* @return ECMA_VALUE_ERROR - if an error occured
* ECMA_VALUE_EMPTY - otherwise
*/
static ecma_value_t
ecma_module_check_indirect_exports (ecma_module_t *module_p)
{
ecma_module_node_t *indirect_export_p = module_p->indirect_exports_p;
while (indirect_export_p != NULL)
{
ecma_module_names_t *name_p = indirect_export_p->module_names_p;
while (name_p != NULL)
{
ecma_module_record_t record;
ecma_value_t result = ecma_module_resolve_export (indirect_export_p->module_request_p,
name_p->local_name_p,
&record);
if (ECMA_IS_VALUE_ERROR (result))
{
return result;
}
JERRY_ASSERT (ecma_is_value_empty (result));
if (record.module_p == NULL)
{
return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous indirect export request."));
}
name_p = name_p->next_p;
}
indirect_export_p = indirect_export_p->next_p;
}
return ECMA_VALUE_EMPTY;
} /* ecma_module_check_indirect_exports */
/**
* Initialize the current module by creating the local binding for the imported variables
* and verifying indirect exports.
@ -831,17 +934,42 @@ ecma_module_connect_imports (void)
* ECMA_VALUE_EMPTY - otherwise
*/
ecma_value_t
ecma_module_initialize_current (void)
ecma_module_initialize (ecma_module_t *module_p) /**< module */
{
ecma_value_t ret_value = ecma_module_connect_imports ();
ecma_value_t ret_value = ecma_module_connect_imports (module_p);
if (ecma_is_value_empty (ret_value))
{
ret_value = ecma_module_check_indirect_exports ();
ret_value = ecma_module_check_indirect_exports (module_p);
}
return ret_value;
} /* ecma_module_initialize_current */
} /* ecma_module_initialize */
static ecma_value_t ecma_module_parse (ecma_module_t *module_p);
/**
* Parses all referenced modules.
*
* @return ECMA_VALUE_ERROR - if an error occured
* ECMA_VALUE_EMPTY - otherwise
*/
ecma_value_t
ecma_module_parse_referenced_modules (void)
{
ecma_module_t *current_p = JERRY_CONTEXT (module_list_p);
while (current_p != NULL)
{
if (ECMA_IS_VALUE_ERROR (ecma_module_parse (current_p)))
{
return ECMA_VALUE_ERROR;
}
current_p = current_p->next_p;
}
return ECMA_VALUE_EMPTY;
} /* ecma_module_parse_referenced_modules */
/**
* Parses an EcmaScript module.
@ -849,7 +977,7 @@ ecma_module_initialize_current (void)
* @return ECMA_VALUE_ERROR - if an error occured
* ECMA_VALUE_EMPTY - otherwise
*/
static jerry_value_t
static ecma_value_t
ecma_module_parse (ecma_module_t *module_p) /**< module */
{
if (module_p->state >= ECMA_MODULE_STATE_PARSING)
@ -858,7 +986,6 @@ ecma_module_parse (ecma_module_t *module_p) /**< module */
}
module_p->state = ECMA_MODULE_STATE_PARSING;
module_p->context_p = ecma_module_create_module_context ();
lit_utf8_size_t module_path_size = ecma_string_get_size (module_p->path_p);
lit_utf8_byte_t *module_path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (module_path_size + 1);
@ -878,9 +1005,8 @@ ecma_module_parse (ecma_module_t *module_p) /**< module */
return ecma_raise_syntax_error (ECMA_ERR_MSG ("File not found."));
}
module_p->context_p->module_p = module_p;
module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
ecma_module_t *prev_module_p = JERRY_CONTEXT (module_current_p);
JERRY_CONTEXT (module_current_p) = module_p;
#if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
@ -899,8 +1025,7 @@ ecma_module_parse (ecma_module_t *module_p) /**< module */
ecma_make_string_value (module_p->path_p),
ECMA_PARSE_STRICT_MODE | ECMA_PARSE_MODULE);
JERRY_CONTEXT (module_top_context_p) = module_p->context_p->parent_p;
JERRY_CONTEXT (module_current_p) = prev_module_p;
jerry_port_release_source (source_p);
if (JERRY_UNLIKELY (bytecode_p == NULL))
@ -908,78 +1033,18 @@ ecma_module_parse (ecma_module_t *module_p) /**< module */
return ECMA_VALUE_ERROR;
}
if (ECMA_IS_VALUE_ERROR (ecma_module_parse_referenced_modules ()))
{
ecma_bytecode_deref (bytecode_p);
return ECMA_VALUE_ERROR;
}
module_p->compiled_code_p = bytecode_p;
module_p->state = ECMA_MODULE_STATE_PARSED;
return ECMA_VALUE_EMPTY;
} /* ecma_module_parse */
/**
* Parses all referenced modules.
*
* @return ECMA_VALUE_ERROR - if an error occured
* ECMA_VALUE_EMPTY - otherwise
*/
ecma_value_t
ecma_module_parse_modules (void)
{
ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
while (current_p != NULL)
{
ecma_value_t ret_value = ecma_module_parse (current_p);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ret_value;
}
JERRY_ASSERT (ecma_is_value_empty (ret_value));
current_p = current_p->next_p;
}
return ECMA_VALUE_EMPTY;
} /* ecma_module_parse_modules */
/**
* Checks if indirect exports in the current context are resolvable.
* Note: See 15.2.1.16.4 / 9.
*
* @return ECMA_VALUE_ERROR - if an error occured
* ECMA_VALUE_EMPTY - otherwise
*/
ecma_value_t
ecma_module_check_indirect_exports (void)
{
ecma_module_node_t *indirect_export_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
while (indirect_export_p != NULL)
{
ecma_module_names_t *name_p = indirect_export_p->module_names_p;
while (name_p != NULL)
{
ecma_module_record_t record;
ecma_value_t result = ecma_module_resolve_export (indirect_export_p->module_request_p,
name_p->local_name_p,
&record);
if (ECMA_IS_VALUE_ERROR (result))
{
return result;
}
if (record.module_p == NULL)
{
return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous indirect export request."));
}
name_p = name_p->next_p;
}
indirect_export_p = indirect_export_p->next_p;
}
return ECMA_VALUE_EMPTY;
} /* ecma_module_check_indirect_exports */
/**
* Cleans up a list of module names.
*/
@ -1016,52 +1081,60 @@ ecma_module_release_module_nodes (ecma_module_node_t *module_node_p) /**< first
} /* ecma_module_release_module_nodes */
/**
* Cleans up a module context.
*/
static void
ecma_module_release_module_context (ecma_module_context_t *module_context_p) /**< modle context */
{
ecma_module_release_module_nodes (module_context_p->imports_p);
ecma_module_release_module_nodes (module_context_p->local_exports_p);
ecma_module_release_module_nodes (module_context_p->indirect_exports_p);
ecma_module_release_module_nodes (module_context_p->star_exports_p);
jmem_heap_free_block (module_context_p, sizeof (ecma_module_context_t));
} /* ecma_module_release_module_context */
/**
* Cleans up a module structure.
* Cleans up and releases a module structure including all referenced modules.
*/
static void
ecma_module_release_module (ecma_module_t *module_p) /**< module */
{
ecma_module_state_t state = module_p->state;
ecma_deref_ecma_string (module_p->path_p);
#ifndef JERRY_NDEBUG
module_p->path_p = NULL;
#endif /* JERRY_NDEBUG */
if (module_p->namespace_object_p != NULL)
{
/* The module structure keeps a strong reference to the namespace object, which will require an extra GC call. */
JERRY_CONTEXT (ecma_gc_new_objects)++;
ecma_deref_object (module_p->namespace_object_p);
#ifndef JERRY_NDEBUG
module_p->namespace_object_p = NULL;
#endif /* JERRY_NDEBUG */
}
if (module_p->state == ECMA_MODULE_STATE_NATIVE)
if (state == ECMA_MODULE_STATE_NATIVE)
{
goto finished;
}
if (module_p->state >= ECMA_MODULE_STATE_PARSING)
if (state >= ECMA_MODULE_STATE_PARSING)
{
ecma_module_release_module_context (module_p->context_p);
ecma_module_release_module_nodes (module_p->imports_p);
ecma_module_release_module_nodes (module_p->local_exports_p);
ecma_module_release_module_nodes (module_p->indirect_exports_p);
ecma_module_release_module_nodes (module_p->star_exports_p);
}
if (module_p->state >= ECMA_MODULE_STATE_EVALUATING
&& module_p->scope_p != NULL)
if (state == ECMA_MODULE_STATE_ROOT)
{
goto finished;
}
if (state >= ECMA_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)++;
ecma_deref_object (module_p->scope_p);
}
if (module_p->state >= ECMA_MODULE_STATE_PARSED
&& module_p->state < ECMA_MODULE_STATE_EVALUATED)
if (state >= ECMA_MODULE_STATE_PARSED
&& state < ECMA_MODULE_STATE_EVALUATED)
{
ecma_bytecode_deref (module_p->compiled_code_p);
#ifndef JERRY_NDEBUG
module_p->compiled_code_p = NULL;
#endif /* JERRY_NDEBUG */
}
finished:
@ -1069,21 +1142,16 @@ finished:
} /* ecma_module_release_module */
/**
* Cleans up all modules if the current context is the root context.
* Cleans up and releases a module list.
*/
void
ecma_module_cleanup (void)
ecma_module_cleanup (ecma_module_t *head_p) /**< module */
{
ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
while (current_p != NULL)
while (head_p != NULL)
{
ecma_module_t *next_p = current_p->next_p;
ecma_module_release_module (current_p);
current_p = next_p;
ecma_module_t *next_p = head_p->next_p;
ecma_module_release_module (head_p);
head_p = next_p;
}
JERRY_CONTEXT (ecma_modules_p) = NULL;
JERRY_CONTEXT (module_top_context_p) = NULL;
} /* ecma_module_cleanup */
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

View File

@ -16,11 +16,11 @@
#ifndef ECMA_MODULE_H
#define ECMA_MODULE_H
#if ENABLED (JERRY_MODULE_SYSTEM)
#include "common.h"
#include "ecma-globals.h"
#if ENABLED (JERRY_MODULE_SYSTEM)
#define ECMA_MODULE_MAX_PATH 255u
/**
@ -35,31 +35,6 @@ typedef struct ecma_module_names
ecma_string_t *local_name_p; /**< Local name of the item */
} ecma_module_names_t;
typedef struct ecma_module ecma_module_t;
/**
* Module node to store imports / exports.
*/
typedef struct ecma_module_node
{
struct ecma_module_node *next_p; /**< next linked list node */
ecma_module_names_t *module_names_p; /**< names of the requested import/export node */
ecma_module_t *module_request_p; /**< module structure of the requested module */
} ecma_module_node_t;
/**
* Module context containing all import and export nodes.
*/
typedef struct ecma_module_context
{
struct ecma_module_context *parent_p; /**< parent context */
ecma_module_node_t *imports_p; /**< import item of the current context */
ecma_module_node_t *local_exports_p; /**< export item of the current context */
ecma_module_node_t *indirect_exports_p; /**< export item of the current context */
ecma_module_node_t *star_exports_p; /**< export item of the current context */
ecma_module_t *module_p; /**< module request */
} ecma_module_context_t;
/**
* An enum identifing the current state of the module
*/
@ -71,21 +46,36 @@ typedef enum
ECMA_MODULE_STATE_EVALUATING = 3, /**< module is currently being evaluated */
ECMA_MODULE_STATE_EVALUATED = 4, /**< module has been evaluated */
ECMA_MODULE_STATE_NATIVE = 5, /**< module is native */
ECMA_MODULE_STATE_ROOT = 6, /**< module is a root module */
} ecma_module_state_t;
/**
* Module structure storing an instance of a module
*/
struct ecma_module
typedef struct ecma_module
{
struct ecma_module *next_p; /**< next linked list node */
ecma_module_state_t state; /**< state of the mode */
ecma_string_t *path_p; /**< path of the module */
ecma_module_context_t *context_p; /**< module context of the module */
ecma_compiled_code_t *compiled_code_p; /**< compiled code of the module */
ecma_object_t *scope_p; /**< lexica lenvironment of the module */
ecma_object_t *namespace_object_p; /**< namespace import object of the module */
};
/* TODO(dbatyai): These could be compressed pointers */
struct ecma_module *next_p; /**< next module in the list */
struct ecma_module_node *imports_p; /**< import requests of the module */
struct ecma_module_node *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_string_t *path_p; /**< path 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 */
ecma_module_state_t state; /**< evaluation state of the module */
} ecma_module_t;
/**
* Module node to store imports / exports.
*/
typedef struct ecma_module_node
{
struct ecma_module_node *next_p; /**< next linked list node */
ecma_module_names_t *module_names_p; /**< names of the requested import/export node */
ecma_module_t *module_request_p; /**< module structure of the requested module */
} ecma_module_node_t;
/**
* A record that can be used to store {module, identifier} pairs
@ -126,19 +116,21 @@ void ecma_module_resolve_stack_push (ecma_module_resolve_stack_t **stack_p,
ecma_string_t *const export_name_p);
void ecma_module_resolve_stack_pop (ecma_module_resolve_stack_t **stack_p);
ecma_string_t *ecma_module_create_normalized_path (const uint8_t *char_p,
prop_length_t size);
ecma_module_t *ecma_module_find_module (ecma_string_t *const path_p);
ecma_module_t *ecma_module_create_native_module (ecma_string_t *const path_p,
ecma_object_t *const namespace_p);
ecma_module_t *ecma_module_find_or_create_module (ecma_string_t *const path_p);
ecma_string_t *ecma_module_create_normalized_path (const lit_utf8_byte_t *char_p,
lit_utf8_size_t size,
ecma_string_t *const base_path_p);
ecma_value_t ecma_module_initialize_current (void);
ecma_value_t ecma_module_parse_modules (void);
ecma_value_t ecma_module_check_indirect_exports (void);
ecma_module_t *ecma_module_find_module (ecma_string_t *const path_p);
ecma_module_t *ecma_module_find_native_module (ecma_string_t *const path_p);
ecma_value_t ecma_module_parse_referenced_modules (void);
ecma_value_t ecma_module_initialize (ecma_module_t *module_p);
void ecma_module_initialize_context (ecma_string_t *root_path_p);
void ecma_module_cleanup_context (void);
void ecma_module_release_module_nodes (ecma_module_node_t *module_node_p);
void ecma_module_cleanup (void);
void ecma_module_cleanup (ecma_module_t *head_p);
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
#endif /* !ECMA_MODULE_H */

View File

@ -115,7 +115,8 @@ typedef enum
typedef enum
{
JERRY_PARSE_NO_OPTS = 0, /**< no options passed */
JERRY_PARSE_STRICT_MODE = (1 << 0) /**< enable strict mode */
JERRY_PARSE_STRICT_MODE = (1 << 0), /**< enable strict mode */
JERRY_PARSE_MODULE = (1 << 1) /**< parse source as an ECMAScript module */
} jerry_parse_opts_t;
/**

View File

@ -150,8 +150,8 @@ struct jerry_context_t
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_MODULE_SYSTEM)
ecma_module_t *ecma_modules_p; /**< list of referenced modules */
ecma_module_context_t *module_top_context_p; /**< top (current) module parser context */
ecma_module_t *module_list_p; /**< current module context */
ecma_module_t *module_current_p; /**< current module context */
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */

View File

@ -16,14 +16,16 @@
#include "config.h"
#include "ecma-helpers.h"
#include "lit-char-helpers.h"
#include "lit-unicode-ranges.inc.h"
#include "lit-unicode-ranges-sup.inc.h"
#include "lit-strings.h"
#include "lit-unicode-ranges.inc.h"
#if ENABLED (JERRY_ESNEXT)
#include "lit-unicode-ranges-sup.inc.h"
#endif /* ENABLED (JERRY_ESNEXT) */
#if ENABLED (JERRY_UNICODE_CASE_CONVERSION)
#include "lit-unicode-conversions.inc.h"
#include "lit-unicode-conversions-sup.inc.h"
#if ENABLED (JERRY_ESNEXT)
#include "lit-unicode-conversions-sup.inc.h"
#include "lit-unicode-folding.inc.h"
#endif /* ENABLED (JERRY_ESNEXT) */
#endif /* ENABLED (JERRY_UNICODE_CASE_CONVERSION) */

View File

@ -549,6 +549,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DATAVIEW_UL, "DataView")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_UL, "Function")
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INFINITY_UL, "Infinity")
#if ENABLED (JERRY_MODULE_SYSTEM)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RUNNABLE_UL, "Runnable")
#endif
#if ENABLED (JERRY_BUILTIN_ERRORS)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_URI_ERROR_UL, "URIError")
#endif

View File

@ -214,6 +214,7 @@ LIT_MAGIC_STRING_VALUE_OF_UL = "valueOf"
LIT_MAGIC_STRING_WEAKMAP_UL = "WeakMap"
LIT_MAGIC_STRING_WEAKSET_UL = "WeakSet"
LIT_MAGIC_STRING_EPSILON_U = "EPSILON"
LIT_MAGIC_STRING_RUNNABLE_UL = "Runnable"
LIT_MAGIC_STRING_DATAVIEW_UL = "DataView"
LIT_MAGIC_STRING_FUNCTION_UL = "Function"
LIT_MAGIC_STRING_INFINITY_UL = "Infinity"

View File

@ -16,6 +16,8 @@
#ifndef JS_LEXER_H
#define JS_LEXER_H
#include "ecma-globals.h"
/** \addtogroup parser Parser
* @{
*

View File

@ -860,8 +860,8 @@ void parser_free_jumps (parser_stack_iterator_t iterator);
*/
extern const lexer_lit_location_t lexer_default_literal;
void parser_module_add_export_node_to_context (parser_context_t *context_p);
void parser_module_add_import_node_to_context (parser_context_t *context_p);
void parser_module_finalize_export_node (parser_context_t *context_p);
void parser_module_finalize_import_node (parser_context_t *context_p);
void parser_module_check_request_place (parser_context_t *context_p);
void parser_module_context_init (parser_context_t *context_p);
void parser_module_handle_module_specifier (parser_context_t *context_p);

View File

@ -55,7 +55,7 @@ parser_module_check_duplicate_import (parser_context_t *context_p, /**< parser c
module_names_p = module_names_p->next_p;
}
ecma_module_node_t *module_node_p = JERRY_CONTEXT (module_top_context_p)->imports_p;
ecma_module_node_t *module_node_p = JERRY_CONTEXT (module_current_p)->imports_p;
while (module_node_p != NULL)
{
module_names_p = module_node_p->module_names_p;
@ -124,7 +124,7 @@ parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser c
current_names_p = current_names_p->next_p;
}
ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_top_context_p)->local_exports_p;
ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_current_p)->local_exports_p;
if (export_node_p != NULL)
{
JERRY_ASSERT (export_node_p->next_p == NULL);
@ -141,7 +141,7 @@ parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser c
}
}
export_node_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
export_node_p = JERRY_CONTEXT (module_current_p)->indirect_exports_p;
while (export_node_p != NULL)
{
ecma_module_names_t *name_p = export_node_p->module_names_p;
@ -167,7 +167,7 @@ parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser c
* Add export node to parser context.
*/
void
parser_module_add_export_node_to_context (parser_context_t *context_p) /**< parser context */
parser_module_finalize_export_node (parser_context_t *context_p) /**< parser context */
{
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
context_p->module_current_node_p = NULL;
@ -180,17 +180,17 @@ parser_module_add_export_node_to_context (parser_context_t *context_p) /**< pars
if (!module_node_p->module_names_p)
{
/* If there are no names in the node, then it's a star export. */
export_list_p = &(JERRY_CONTEXT (module_top_context_p)->star_exports_p);
export_list_p = &(JERRY_CONTEXT (module_current_p)->star_exports_p);
}
else
{
export_list_p = &(JERRY_CONTEXT (module_top_context_p)->indirect_exports_p);
export_list_p = &(JERRY_CONTEXT (module_current_p)->indirect_exports_p);
}
}
else
{
/* If there is no module request, then it's a local export. */
export_list_p = &(JERRY_CONTEXT (module_top_context_p)->local_exports_p);
export_list_p = &(JERRY_CONTEXT (module_current_p)->local_exports_p);
}
/* Check if we have a node with the same module request, append to it if we do. */
@ -213,7 +213,7 @@ parser_module_add_export_node_to_context (parser_context_t *context_p) /**< pars
module_node_p->module_names_p = NULL;
}
ecma_module_release_module_nodes (module_node_p);
jmem_heap_free_block (module_node_p, sizeof (ecma_module_node_t));
return;
}
@ -222,22 +222,22 @@ parser_module_add_export_node_to_context (parser_context_t *context_p) /**< pars
module_node_p->next_p = *export_list_p;
*export_list_p = module_node_p;
} /* parser_module_add_export_node_to_context */
} /* parser_module_finalize_export_node */
/**
* Add import node to parser context.
*/
void
parser_module_add_import_node_to_context (parser_context_t *context_p) /**< parser context */
parser_module_finalize_import_node (parser_context_t *context_p) /**< parser context */
{
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
context_p->module_current_node_p = NULL;
ecma_module_node_t *stored_imports = JERRY_CONTEXT (module_top_context_p)->imports_p;
ecma_module_node_t *stored_imports_p = JERRY_CONTEXT (module_current_p)->imports_p;
/* Check if we have a node with the same module request, append to it if we do. */
while (stored_imports != NULL)
while (stored_imports_p != NULL)
{
if (stored_imports->module_request_p == module_node_p->module_request_p)
if (stored_imports_p->module_request_p == module_node_p->module_request_p)
{
ecma_module_names_t *module_names_p = module_node_p->module_names_p;
@ -248,21 +248,21 @@ parser_module_add_import_node_to_context (parser_context_t *context_p) /**< pars
module_names_p = module_names_p->next_p;
}
module_names_p->next_p = stored_imports->module_names_p;
stored_imports->module_names_p = module_node_p->module_names_p;
module_names_p->next_p = stored_imports_p->module_names_p;
stored_imports_p->module_names_p = module_node_p->module_names_p;
module_node_p->module_names_p = NULL;
}
ecma_module_release_module_nodes (module_node_p);
jmem_heap_free_block (module_node_p, sizeof (ecma_module_node_t));
return;
}
stored_imports = stored_imports->next_p;
stored_imports_p = stored_imports_p->next_p;
}
module_node_p->next_p = JERRY_CONTEXT (module_top_context_p)->imports_p;
JERRY_CONTEXT (module_top_context_p)->imports_p = module_node_p;
} /* parser_module_add_import_node_to_context */
module_node_p->next_p = JERRY_CONTEXT (module_current_p)->imports_p;
JERRY_CONTEXT (module_current_p)->imports_p = module_node_p;
} /* parser_module_finalize_import_node */
/**
* Add module names to current module node.
@ -289,50 +289,6 @@ parser_module_add_names_to_node (parser_context_t *context_p, /**< parser contex
new_names_p->local_name_p = local_name_p;
} /* parser_module_add_names_to_node */
/**
* Create module context if needed.
*/
void
parser_module_context_init (parser_context_t *context_p)
{
if (JERRY_CONTEXT (module_top_context_p) == NULL)
{
ecma_module_context_t *module_context_p;
module_context_p = (ecma_module_context_t *) jmem_heap_alloc_block (sizeof (ecma_module_context_t));
memset (module_context_p, 0, sizeof (ecma_module_context_t));
JERRY_CONTEXT (module_top_context_p) = module_context_p;
ecma_string_t *path_str_p = ecma_get_string_from_value (context_p->resource_name);
lit_utf8_size_t path_str_size;
uint8_t flags = ECMA_STRING_FLAG_EMPTY;
const lit_utf8_byte_t *path_str_chars_p = ecma_string_get_chars (path_str_p,
&path_str_size,
NULL,
NULL,
&flags);
ecma_string_t *path_p = ecma_module_create_normalized_path (path_str_chars_p,
(prop_length_t) path_str_size);
if (path_p == NULL)
{
ecma_ref_ecma_string (path_str_p);
path_p = path_str_p;
}
ecma_module_t *module_p = ecma_module_find_or_create_module (path_p);
module_p->state = ECMA_MODULE_STATE_EVALUATED;
/* The lexical scope of the root module does not exist yet. */
module_p->scope_p = NULL;
module_p->context_p = module_context_p;
module_context_p->module_p = module_p;
}
} /* parser_module_context_init */
/**
* Create a permanent import/export node from a template node.
* @return - the copy of the template if the second parameter is not NULL.
@ -567,7 +523,8 @@ parser_module_check_request_place (parser_context_t *context_p) /**< parser cont
if (context_p->last_context_p != NULL
|| context_p->stack_top_uint8 != 0
|| (context_p->status_flags & PARSER_IS_FUNCTION)
|| (context_p->global_status_flags & ECMA_PARSE_EVAL))
|| (context_p->global_status_flags & ECMA_PARSE_EVAL)
|| (context_p->global_status_flags & ECMA_PARSE_MODULE) == 0)
{
parser_raise_error (context_p, PARSER_ERR_MODULE_UNEXPECTED);
}
@ -592,34 +549,25 @@ parser_module_handle_module_specifier (parser_context_t *context_p) /**< parser
ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
context_p->lit_object.literal_p->prop.length);
ecma_module_t *module_p = ecma_module_find_module (name_p);
ecma_module_t *module_p = ecma_module_find_native_module (name_p);
if (module_p)
{
ecma_deref_ecma_string (name_p);
goto module_found;
}
ecma_value_t native = jerry_port_get_native_module (ecma_make_string_value (name_p));
if (!ecma_is_value_undefined (native))
{
JERRY_ASSERT (ecma_is_value_object (native));
ecma_object_t *module_object_p = ecma_get_object_from_value (native);
module_p = ecma_module_create_native_module (name_p, module_object_p);
goto module_found;
}
ecma_deref_ecma_string (name_p);
ecma_string_t *path_p = ecma_module_create_normalized_path (context_p->lit_object.literal_p->u.char_p,
context_p->lit_object.literal_p->prop.length);
context_p->lit_object.literal_p->prop.length,
JERRY_CONTEXT (module_current_p)->path_p);
if (path_p == NULL)
{
parser_raise_error (context_p, PARSER_ERR_FILE_NOT_FOUND);
}
module_p = ecma_module_find_or_create_module (path_p);
module_p = ecma_module_find_module (path_p);
module_found:
module_node_p->module_request_p = module_p;

View File

@ -2427,7 +2427,6 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_IMPORT);
parser_module_check_request_place (context_p);
parser_module_context_init (context_p);
context_p->module_current_node_p = parser_module_create_module_node (context_p);
@ -2529,7 +2528,7 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context
}
parser_module_handle_module_specifier (context_p);
parser_module_add_import_node_to_context (context_p);
parser_module_finalize_import_node (context_p);
context_p->module_current_node_p = NULL;
} /* parser_parse_import_statement */
@ -2543,7 +2542,6 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXPORT);
parser_module_check_request_place (context_p);
parser_module_context_init (context_p);
context_p->module_current_node_p = parser_module_create_module_node (context_p);
@ -2656,7 +2654,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
}
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC | PARSER_MODULE_STORE_IDENT);
parser_module_add_export_node_to_context (context_p);
parser_module_finalize_export_node (context_p);
context_p->module_current_node_p = NULL;
} /* parser_parse_export_statement */
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */

View File

@ -1396,7 +1396,7 @@ parser_error_to_string (parser_error_t error) /**< error code */
}
case PARSER_ERR_MODULE_UNEXPECTED:
{
return "Import and export statements must be in the global context.";
return "Unexpected import or export statement.";
}
case PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED:
{

View File

@ -1811,6 +1811,15 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
context.status_flags = parse_opts & PARSER_STRICT_MODE_MASK;
context.global_status_flags = parse_opts;
#if ENABLED (JERRY_MODULE_SYSTEM)
if (context.global_status_flags & ECMA_PARSE_MODULE)
{
context.status_flags |= PARSER_IS_STRICT;
}
context.module_current_node_p = NULL;
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
if (arg_list_p != NULL)
{
context.status_flags |= PARSER_IS_FUNCTION;
@ -1934,15 +1943,6 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
context.breakpoint_info_count = 0;
#endif /* ENABLED (JERRY_DEBUGGER) */
#if ENABLED (JERRY_MODULE_SYSTEM)
if (context.global_status_flags & ECMA_PARSE_MODULE)
{
context.status_flags |= PARSER_IS_STRICT;
}
context.module_current_node_p = NULL;
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
JERRY_ASSERT (context.next_scanner_info_p->source_p == context.source_p);
JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
@ -2859,12 +2859,6 @@ parser_parse_script (const uint8_t *arg_list_p, /**< function argument list */
resource_name,
line_str_val,
col_str_val);
#if ENABLED (JERRY_MODULE_SYSTEM)
if (JERRY_CONTEXT (module_top_context_p) != NULL)
{
ecma_module_cleanup ();
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
ecma_free_value (col_str_val);
ecma_free_value (line_str_val);
@ -2881,16 +2875,6 @@ parser_parse_script (const uint8_t *arg_list_p, /**< function argument list */
return NULL;
}
#if ENABLED (JERRY_MODULE_SYSTEM)
if (JERRY_CONTEXT (module_top_context_p) != NULL && ECMA_IS_VALUE_ERROR (ecma_module_parse_modules ()))
{
ecma_bytecode_deref (bytecode_p);
ecma_module_cleanup ();
return NULL;
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
#if ENABLED (JERRY_DEBUGGER)
if ((JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
== (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))

View File

@ -1649,8 +1649,6 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
context_p->global_status_flags |= ECMA_PARSE_MODULE;
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
lexer_next_token (context_p);
@ -1801,8 +1799,6 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
context_p->global_status_flags |= ECMA_PARSE_MODULE;
lexer_next_token (context_p);
if (context_p->token.type == LEXER_KEYW_DEFAULT)

View File

@ -272,10 +272,9 @@ static const uint16_t vm_decode_table[] JERRY_ATTR_CONST_DATA =
* @return ecma value
*/
ecma_value_t
vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode to run */
ecma_object_t *lex_env_p) /**< pointer to the specified lexenv to run in */
vm_run_module (ecma_module_t *module_p) /**< module to be executed */
{
const ecma_value_t module_init_result = ecma_module_initialize_current ();
const ecma_value_t module_init_result = ecma_module_initialize (module_p);
if (ECMA_IS_VALUE_ERROR (module_init_result))
{
@ -283,10 +282,10 @@ vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode
}
vm_frame_ctx_shared_t shared;
shared.bytecode_header_p = bytecode_p;
shared.bytecode_header_p = module_p->compiled_code_p;
shared.status_flags = 0;
return vm_run (&shared, ECMA_VALUE_UNDEFINED, lex_env_p);
return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p);
} /* vm_run_module */
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
@ -316,27 +315,6 @@ vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode
ecma_object_t *const global_scope_p = ecma_get_global_scope (global_obj_p);
#if ENABLED (JERRY_MODULE_SYSTEM)
if (JERRY_CONTEXT (module_top_context_p) != NULL)
{
JERRY_ASSERT (JERRY_CONTEXT (module_top_context_p)->parent_p == NULL);
ecma_module_t *module_p = JERRY_CONTEXT (module_top_context_p)->module_p;
JERRY_ASSERT (module_p->scope_p == NULL);
ecma_ref_object (global_scope_p);
module_p->scope_p = global_scope_p;
const ecma_value_t module_init_result = ecma_module_initialize_current ();
JERRY_CONTEXT (module_top_context_p) = NULL;
if (ECMA_IS_VALUE_ERROR (module_init_result))
{
ecma_module_cleanup ();
return module_init_result;
}
}
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
vm_frame_ctx_shared_t shared;
shared.bytecode_header_p = bytecode_p;
shared.status_flags = 0;

View File

@ -17,6 +17,7 @@
#define VM_H
#include "ecma-globals.h"
#include "ecma-module.h"
#include "jrt.h"
#include "vm-defines.h"
@ -481,7 +482,7 @@ ecma_value_t vm_run_global (const ecma_compiled_code_t *bytecode_p);
ecma_value_t vm_run_eval (ecma_compiled_code_t *bytecode_data_p, uint32_t parse_opts);
#if ENABLED (JERRY_MODULE_SYSTEM)
ecma_value_t vm_run_module (const ecma_compiled_code_t *bytecode_p, ecma_object_t *lex_env_p);
ecma_value_t vm_run_module (ecma_module_t *module_p);
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
ecma_value_t vm_run (vm_frame_ctx_shared_t *shared_p, ecma_value_t this_binding_value, ecma_object_t *lex_env_p);

View File

@ -44,6 +44,7 @@ typedef enum
OPT_DEBUGGER_WAIT_SOURCE,
OPT_EXEC_SNAP,
OPT_EXEC_SNAP_FUNC,
OPT_MODULE,
OPT_LOG_LEVEL,
OPT_NO_PROMPT,
OPT_CALL_ON_EXIT,
@ -85,6 +86,8 @@ static const cli_opt_t main_opts[] =
.help = "execute input snapshot file(s)"),
CLI_OPT_DEF (.id = OPT_EXEC_SNAP_FUNC, .longopt = "exec-snapshot-func", .meta = "FILE NUM",
.help = "execute specific function from input snapshot file(s)"),
CLI_OPT_DEF (.id = OPT_MODULE, .opt = "m", .longopt = "module", .meta = "FILE",
.help = "execute module file"),
CLI_OPT_DEF (.id = OPT_LOG_LEVEL, .longopt = "log-level", .meta = "NUM",
.help = "set log level (0-3)"),
CLI_OPT_DEF (.id = OPT_NO_PROMPT, .longopt = "no-prompt",
@ -307,6 +310,19 @@ main_parse_args (int argc, /**< argc */
break;
}
case OPT_MODULE:
{
const uint32_t path_index = cli_consume_path (&cli_state);
main_source_t *source_p = arguments_p->sources_p + arguments_p->source_count;
arguments_p->source_count++;
source_p->type = SOURCE_MODULE;
source_p->path_index = path_index;
source_p->snapshot_index = 0;
break;
}
case OPT_LOG_LEVEL:
{
long int log_level = cli_consume_int (&cli_state);

View File

@ -38,6 +38,7 @@ typedef enum
typedef enum
{
SOURCE_SNAPSHOT,
SOURCE_MODULE,
SOURCE_SCRIPT,
} main_source_type_t;

View File

@ -86,6 +86,8 @@ restart:
goto exit;
}
uint32_t parse_opts = JERRY_PARSE_NO_OPTS;
switch (source_file_p->type)
{
case SOURCE_SNAPSHOT:
@ -98,9 +100,15 @@ restart:
jerry_port_release_source (source_p);
break;
}
case SOURCE_MODULE:
{
parse_opts = JERRY_PARSE_MODULE;
/* FALLTHRU */
}
default:
{
assert (source_file_p->type == SOURCE_SCRIPT);
assert (source_file_p->type == SOURCE_SCRIPT
|| source_file_p->type == SOURCE_MODULE);
if (!jerry_is_valid_utf8_string ((jerry_char_t *) source_p, (jerry_size_t) source_size))
{
@ -113,7 +121,7 @@ restart:
strlen (file_path_p),
source_p,
source_size,
JERRY_PARSE_NO_OPTS);
parse_opts);
jerry_port_release_source (source_p);

View File

@ -13,8 +13,8 @@
* limitations under the License.
*/
export {} from "module-export-01.js";
export {aa,} from "module-export-01.js";
export {bb as b_, cc as c_} from "module-export-01.js";
export * from "module-export-01.js";
export {} from "module-export-01.mjs";
export {aa,} from "module-export-01.mjs";
export {bb as b_, cc as c_} from "module-export-01.mjs";
export * from "module-export-01.mjs";
export default function () {return "default"};

View File

@ -23,4 +23,4 @@ export default class {
}
}
export * from "module-export-02.js"
export * from "module-export-02.mjs"

View File

@ -13,6 +13,6 @@
* limitations under the License.
*/
export * from "module-export-01.js";
export * from "module-export-04.js";
export * from "module-export-01.mjs";
export * from "module-export-04.mjs";
export default a = "str"

View File

@ -14,6 +14,6 @@
*/
export {}
export {} from "module-export-01.js";
export {} from "module-export-01.mjs";
export {};
export {} from "module-export-04.js"
export {} from "module-export-04.mjs"

View File

@ -13,5 +13,5 @@
* limitations under the License.
*/
export * from "./module-export-04.js";
export * from "./module-export-04.mjs";
export let c = 5;

View File

@ -13,13 +13,13 @@
* limitations under the License.
*/
import "./module-export-01.js";
import def from "module-export-01.js";
import {} from "module-export-01.js";
import {aa as a,} from "module-export-01.js";
import {bb as b, cc as c} from "module-export-01.js";
import {x} from "module-export-01.js";
import * as mod from "module-export-01.js";
import "./module-export-01.mjs";
import def from "module-export-01.mjs";
import {} from "module-export-01.mjs";
import {aa as a,} from "module-export-01.mjs";
import {bb as b, cc as c} from "module-export-01.mjs";
import {x} from "module-export-01.mjs";
import * as mod from "module-export-01.mjs";
assert (def === "default");
assert (a === "a");

View File

@ -13,8 +13,8 @@
* limitations under the License.
*/
import def, * as mod from "module-export-02.js";
import {b_, c_,} from "module-export-02.js";
import def, * as mod from "module-export-02.mjs";
import {b_, c_,} from "module-export-02.mjs";
assert (def() === "default")
assert (mod.aa === "a")

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
import incrementer, {aa, c_, x,} from "module-export-03.js"
import incrementer, {aa, c_, x,} from "module-export-03.mjs"
var i = new incrementer(3);
assert(i.incr() === 4);
assert(i.incr() === 5);

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
import "module-import-01.js";
import "module-export-05.js";
import "module-export-06.js";
import "module-export-07.js";
import "module-import-01.mjs";
import "module-export-05.mjs";
import "module-export-06.mjs";
import "module-export-07.mjs";

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
import * as f from "./module-export-08.js";
import * as f from "./module-export-08.mjs";
assert (f.c === 5)
assert (f.x === 41)

View File

@ -22,6 +22,6 @@ getNamePromise(collector).then(() => { collector["end"] = resourceName(); });
function __checkAsync() {
assert(collector["start"].endsWith("module-resource-name-export.mjs"));
assert(collector["middle"].endsWith("module-resource-name-export.mjs"));
assert(collector["end"].endsWith("module-resource-name.js"));
assert(collector["end"].endsWith("module-resource-name.mjs"));
assert(Object.keys(collector).length === 3);
}

View File

@ -16,7 +16,7 @@
/* Import/export statements must be in the global scope. */
var eval = eval.bind();
try {
eval('import { c } from "tests/jerry/es.next/module-export-01.js";');
eval('import { c } from "tests/jerry/es.next/module-export-01.mjs";');
assert (false);
} catch (e) {
assert (e instanceof SyntaxError);

View File

@ -14,4 +14,4 @@
*/
// File does not exist.
import b from "module-exports.js"
import b from "module-exports.mjs"

View File

@ -13,4 +13,4 @@
* limitations under the License.
*/
import { , as b } from "../es.next/module-export-01.js";
import { , as b } from "../es.next/module-export-01.mjs";

View File

@ -13,4 +13,4 @@
* limitations under the License.
*/
import , as b from "../es.next/module-export-01.js";
import , as b from "../es.next/module-export-01.mjs";

View File

@ -1,16 +0,0 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { b as , } from "../es.next/module-export-01.js";

View File

@ -0,0 +1,16 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { b as , } from "../es.next/module-export-01.mjs";

View File

@ -14,4 +14,4 @@
*/
/* Named imports must be in a NamedImports block. */
import b as , from "../es.next/module-export-01.js";
import b as , from "../es.next/module-export-01.mjs";

View File

@ -14,4 +14,4 @@
*/
/* Module requests must always be evaluated. */
import "./module-sideeffect.js"
import "./module-sideeffect.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Can't have duplicate local bindings */
import { c as a, d as a } from "../es.next/module-export-01.js";
import { c as a, d as a } from "../es.next/module-export-01.mjs";

View File

@ -15,5 +15,5 @@
/* Import/export statements must be in the global scope. */
if (true) {
import { c } from "../es.next/module-export-01.js";
import { c } from "../es.next/module-export-01.mjs";
}

View File

@ -15,5 +15,5 @@
/* Import/export statements must be in the global scope. */
function someFunction() {
import { c } from "../es.next/module-export-01.js";
import { c } from "../es.next/module-export-01.mjs";
}

View File

@ -14,4 +14,4 @@
*/
/* Import/export statements must be in the global scope. */
eval ('import { c } from "../es.next/module-export-01.js";');
eval ('import { c } from "../es.next/module-export-01.mjs";');

View File

@ -14,4 +14,4 @@
*/
/* NamedImports must always be followed by a FromClause. */
import { b }, from "../es.next/module-export-01.js"
import { b }, from "../es.next/module-export-01.mjs"

View File

@ -14,4 +14,4 @@
*/
/* An import statement can have either a NameSpaceImport or NamedIpmorts */
import * as mod, { b } from "../es.next/module-export-01.js"
import * as mod, { b } from "../es.next/module-export-01.mjs"

View File

@ -14,4 +14,4 @@
*/
/* '*' is not valid inside NamedImports. */
import { *, d } from "../es.next/module-imported-01.js"
import { *, d } from "../es.next/module-imported-01.mjs"

View File

@ -14,5 +14,5 @@
*/
/* Can't have duplicated local bindings. */
import { b } from "../es.next/module-export-01.js"
import { b } from "../es.next/module-export-02.js"
import { b } from "../es.next/module-export-01.mjs"
import { b } from "../es.next/module-export-02.mjs"

View File

@ -14,4 +14,4 @@
*/
/* FromClause must follow an ImportClause. */
import from "../es.next/module-export-02.js"
import from "../es.next/module-export-02.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Namespace imports must have a local name. */
import * from "../es.next/module-export-01.js"
import * from "../es.next/module-export-01.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Star exports can't have an export name. */
export * as star from "../es.next/module-export-01.js"
export * as star from "../es.next/module-export-01.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Indirect exports must be checked if they are resolvable. */
export { l } from "../es.next/module-export-01.js"
export { l } from "../es.next/module-export-01.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Can't have circular imports/exports. */
export { b } from "./module-027.js"
export { b } from "./module-027.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Can't have circular imports/exports. */
export { b } from "./module-026.js"
export { b } from "./module-026.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Ambiguous import */
import { x } from "../es.next/module-export-05.js"
import { x } from "../es.next/module-export-05.mjs"

View File

@ -14,4 +14,4 @@
*/
/* Import/export statements must be in the global scope. */
Function('','import { c } from "../es.next/module-export-01.js";')
Function('','import { c } from "../es.next/module-export-01.mjs";')

View File

@ -14,4 +14,4 @@
*/
/* No default export found. */
import def from "../es.next/module-export-06.js"
import def from "../es.next/module-export-06.mjs"

View File

@ -14,4 +14,4 @@
*/
let a;
import { a } from "../es.next/module-export-fail-test.js";
import { a } from "../es.next/module-export-fail-test.mjs";

View File

@ -14,4 +14,4 @@
*/
var a;
import { a } from "../es.next/module-export-fail-test.js";
import { a } from "../es.next/module-export-fail-test.mjs";

View File

@ -13,5 +13,5 @@
* limitations under the License.
*/
import { a } from "../es.next/module-export-fail-test.js";
import { a } from "../es.next/module-export-fail-test.mjs";
class a {};

View File

@ -13,5 +13,5 @@
* limitations under the License.
*/
import { a } from "../es.next/module-export-fail-test.js";
import { a } from "../es.next/module-export-fail-test.mjs";
function a() {}

View File

@ -13,4 +13,4 @@
* limitations under the License.
*/
import "./module-export-001.js"
import "./module-await-001.mjs"

View File

@ -13,4 +13,4 @@
* limitations under the License.
*/
import "./module-await-001.js"
import "./module-await-001.mjs"

View File

@ -12,5 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.
export {} from "dummy.js";
export {} from "../es.next/module-export-04.js";
export {} from "dummy.mjs";
export {} from "../es.next/module-export-04.mjs";

View File

@ -328,8 +328,6 @@
<test id="language/expressions/call/eval-spread.js"><reason></reason></test>
<test id="language/expressions/class/accessor-name-inst/literal-numeric-leading-decimal.js"><reason></reason></test>
<test id="language/expressions/class/accessor-name-static/literal-numeric-leading-decimal.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-await-escaped-module.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-await-module.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-let-escaped.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-let.js"><reason></reason></test>
<test id="language/expressions/class/class-name-ident-static-escaped.js"><reason></reason></test>
@ -414,7 +412,6 @@
<test id="language/expressions/yield/star-return-is-null.js"><reason></reason></test>
<test id="language/expressions/yield/star-throw-is-null.js"><reason></reason></test>
<test id="language/global-code/decl-lex-configurable-global.js"><reason></reason></test>
<test id="language/global-code/export.js"><reason></reason></test>
<test id="language/identifiers/part-unicode-10.0.0-escaped.js"><reason></reason></test>
<test id="language/identifiers/part-unicode-10.0.0.js"><reason></reason></test>
<test id="language/identifiers/part-unicode-11.0.0-escaped.js"><reason></reason></test>
@ -457,7 +454,6 @@
<test id="language/identifiers/start-unicode-9.0.0.js"><reason></reason></test>
<test id="language/literals/regexp/unicode-escape-nls-err.js"><reason></reason></test>
<test id="language/literals/string/legacy-octal-escape-sequence-prologue-strict.js"><reason></reason></test>
<test id="language/module-code/early-strict-mode.js"><reason></reason></test>
<test id="language/module-code/eval-export-cls-semi.js"><reason></reason></test>
<test id="language/module-code/eval-export-dflt-cls-anon-semi.js"><reason></reason></test>
<test id="language/module-code/eval-export-dflt-cls-anon.js"><reason></reason></test>
@ -487,7 +483,6 @@
<test id="language/module-code/eval-rqstd-once.js"><reason></reason></test>
<test id="language/module-code/eval-rqstd-order.js"><reason></reason></test>
<test id="language/module-code/eval-self-once.js"><reason></reason></test>
<test id="language/module-code/eval-this.js"><reason></reason></test>
<test id="language/module-code/export-star-as-dflt.js"><reason></reason></test>
<test id="language/module-code/instn-iee-bndng-cls.js"><reason></reason></test>
<test id="language/module-code/instn-iee-bndng-const.js"><reason></reason></test>
@ -498,13 +493,6 @@
<test id="language/module-code/instn-iee-iee-cycle.js"><reason></reason></test>
<test id="language/module-code/instn-iee-star-cycle.js"><reason></reason></test>
<test id="language/module-code/instn-iee-trlng-comma.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-export-fun.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-export-gen.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-export-var.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-for.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-fun.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-gen.js"><reason></reason></test>
<test id="language/module-code/instn-local-bndng-var.js"><reason></reason></test>
<test id="language/module-code/instn-named-bndng-cls.js"><reason></reason></test>
<test id="language/module-code/instn-named-bndng-const.js"><reason></reason></test>
<test id="language/module-code/instn-named-bndng-dflt-cls.js"><reason></reason></test>
@ -576,13 +564,9 @@
<test id="language/module-code/namespace/internals/set.js"><reason></reason></test>
<test id="language/module-code/parse-err-hoist-lex-fun.js"><reason></reason></test>
<test id="language/module-code/parse-err-hoist-lex-gen.js"><reason></reason></test>
<test id="language/module-code/parse-err-yield.js"><reason></reason></test>
<test id="language/reserved-words/await-module.js"><reason></reason></test>
<test id="language/statements/async-function/let-newline-await-in-async-function.js"><reason></reason></test>
<test id="language/statements/class/accessor-name-inst/literal-numeric-leading-decimal.js"><reason></reason></test>
<test id="language/statements/class/accessor-name-static/literal-numeric-leading-decimal.js"><reason></reason></test>
<test id="language/statements/class/class-name-ident-await-escaped-module.js"><reason></reason></test>
<test id="language/statements/class/class-name-ident-await-module.js"><reason></reason></test>
<test id="language/statements/class/class-name-ident-let-escaped.js"><reason></reason></test>
<test id="language/statements/class/class-name-ident-let.js"><reason></reason></test>
<test id="language/statements/class/class-name-ident-static-escaped.js"><reason></reason></test>
@ -699,8 +683,6 @@
<test id="language/statements/labeled/decl-gen.js"><reason></reason></test>
<test id="language/statements/labeled/let-block-with-newline.js"><reason></reason></test>
<test id="language/statements/labeled/let-identifier-with-newline.js"><reason></reason></test>
<test id="language/statements/labeled/value-await-module-escaped.js"><reason></reason></test>
<test id="language/statements/labeled/value-await-module.js"><reason></reason></test>
<test id="language/statements/let/dstr/ary-init-iter-no-close.js"><reason></reason></test>
<test id="language/statements/let/syntax/let-newline-yield-in-generator-function.js"><reason></reason></test>
<test id="language/statements/switch/cptn-a-abrupt-empty.js"><reason></reason></test>
@ -5242,7 +5224,6 @@
<test id="language/module-code/top-level-await/module-import-unwrapped.js"><reason></reason></test>
<test id="language/module-code/top-level-await/module-self-import-async-resolution-ticks.js"><reason></reason></test>
<test id="language/module-code/top-level-await/module-sync-import-async-resolution-ticks.js"><reason></reason></test>
<test id="language/module-code/top-level-await/no-operand.js"><reason></reason></test>
<test id="language/module-code/top-level-await/syntax/await-expr-dyn-import.js"><reason></reason></test>
<test id="language/module-code/top-level-await/syntax/block-await-expr-array-literal.js"><reason></reason></test>
<test id="language/module-code/top-level-await/syntax/block-await-expr-func-expression.js"><reason></reason></test>

View File

@ -54,7 +54,9 @@ def get_tests(test_dir, test_list, skip_list):
if test_dir:
tests = []
for root, _, files in os.walk(test_dir):
tests.extend([os.path.join(root, test_file) for test_file in files if test_file.endswith('.js')])
for test_file in files:
if test_file.endswith('.js') or test_file.endswith('.mjs'):
tests.extend([os.path.join(root, test_file)])
if test_list:
dirname = os.path.dirname(test_list)
@ -136,7 +138,12 @@ def run_normal_tests(args, tests):
tested += 1
test_path = os.path.relpath(test)
is_expected_to_fail = os.path.join(os.path.sep, 'fail', '') in test
(returncode, stdout) = execute_test_command(test_cmd + [test])
test_argument = []
if test.endswith('.mjs'):
test_argument.extend(['-m'])
(returncode, stdout) = execute_test_command(test_cmd + test_argument + [test])
if (returncode == 0 and not is_expected_to_fail) or (returncode == 1 and is_expected_to_fail):
passed += 1

View File

@ -367,6 +367,8 @@ def build_options():
help="Command to print from console")
result.add_option("--list-includes", default=False, action="store_true",
help="List includes required by tests")
result.add_option("--module-flag", default="-m",
help="List includes required by tests")
return result
@ -481,7 +483,7 @@ class TestResult(object):
class TestCase(object):
def __init__(self, suite, name, full_path, strict_mode, command_template):
def __init__(self, suite, name, full_path, strict_mode, command_template, module_flag):
self.suite = suite
self.name = name
self.full_path = full_path
@ -495,6 +497,7 @@ class TestCase(object):
test_record.pop("commentary", None) # do not throw if missing
self.test_record = test_record
self.command_template = command_template
self.module_flag = module_flag
self.validate()
@ -543,6 +546,9 @@ class TestCase(object):
def is_async_test(self):
return 'async' in self.test_record or '$DONE' in self.test
def is_module(self):
return 'module' in self.test_record
def get_include_list(self):
if self.test_record.get('includes'):
return self.test_record['includes']
@ -618,9 +624,16 @@ class TestCase(object):
def run_test_in(self, tmp):
tmp.write(self.get_source())
tmp.close()
if self.is_module():
arg = self.module_flag + ' ' + tmp.name
else:
arg = tmp.name
command = TestCase.instantiate_template(self.command_template, {
'path': tmp.name
'path': arg
})
(code, out, err) = TestCase.execute(command)
return TestResult(code, out, err, self)
@ -695,15 +708,16 @@ def percent_format(partial, total):
class TestSuite(object):
def __init__(self, root, strict_only, non_strict_only, unmarked_default, print_handle, exclude_list_path):
self.test_root = path.join(root, 'test')
self.lib_root = path.join(root, 'harness')
self.strict_only = strict_only
self.non_strict_only = non_strict_only
self.unmarked_default = unmarked_default
self.print_handle = print_handle
def __init__(self, options):
self.test_root = path.join(options.tests, 'test')
self.lib_root = path.join(options.tests, 'harness')
self.strict_only = options.strict_only
self.non_strict_only = options.non_strict_only
self.unmarked_default = options.unmarked_default
self.print_handle = options.print_handle
self.include_cache = {}
self.exclude_list_path = exclude_list_path
self.exclude_list_path = options.exclude_list
self.module_flag = options.module_flag
self.logf = None
def _load_excludes(self):
@ -772,12 +786,12 @@ class TestSuite(object):
print('Excluded: ' + rel_path)
else:
if not self.non_strict_only:
strict_case = TestCase(self, name, full_path, True, command_template)
strict_case = TestCase(self, name, full_path, True, command_template, self.module_flag)
if not strict_case.is_no_strict():
if strict_case.is_only_strict() or self.unmarked_default in ['both', 'strict']:
cases.append(strict_case)
if not self.strict_only:
non_strict_case = TestCase(self, name, full_path, False, command_template)
non_strict_case = TestCase(self, name, full_path, False, command_template, self.module_flag)
if not non_strict_case.is_only_strict():
if non_strict_case.is_no_strict() or self.unmarked_default in ['both', 'non_strict']:
cases.append(non_strict_case)
@ -901,12 +915,7 @@ def main():
(options, args) = parser.parse_args()
validate_options(options)
test_suite = TestSuite(options.tests,
options.strict_only,
options.non_strict_only,
options.unmarked_default,
options.print_handle,
options.exclude_list)
test_suite = TestSuite(options)
test_suite.validate()
if options.loglevel == 'debug':