mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
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:
parent
ef8a6a9f39
commit
0fec9135ec
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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) */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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) */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
#ifndef JS_LEXER_H
|
||||
#define JS_LEXER_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
/** \addtogroup parser Parser
|
||||
* @{
|
||||
*
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) */
|
||||
|
||||
@ -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:
|
||||
{
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -38,6 +38,7 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
SOURCE_SNAPSHOT,
|
||||
SOURCE_MODULE,
|
||||
SOURCE_SCRIPT,
|
||||
} main_source_type_t;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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"};
|
||||
@ -23,4 +23,4 @@ export default class {
|
||||
}
|
||||
}
|
||||
|
||||
export * from "module-export-02.js"
|
||||
export * from "module-export-02.mjs"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -13,5 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from "./module-export-04.js";
|
||||
export * from "./module-export-04.mjs";
|
||||
export let c = 5;
|
||||
@ -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");
|
||||
@ -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")
|
||||
@ -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);
|
||||
@ -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";
|
||||
@ -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)
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
*/
|
||||
|
||||
// File does not exist.
|
||||
import b from "module-exports.js"
|
||||
import b from "module-exports.mjs"
|
||||
@ -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";
|
||||
@ -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";
|
||||
@ -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";
|
||||
16
tests/jerry/fail/module-004.mjs
Normal file
16
tests/jerry/fail/module-004.mjs
Normal 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";
|
||||
@ -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";
|
||||
@ -14,4 +14,4 @@
|
||||
*/
|
||||
|
||||
/* Module requests must always be evaluated. */
|
||||
import "./module-sideeffect.js"
|
||||
import "./module-sideeffect.mjs"
|
||||
@ -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";
|
||||
@ -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";
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
@ -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";');
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -14,4 +14,4 @@
|
||||
*/
|
||||
|
||||
/* Can't have circular imports/exports. */
|
||||
export { b } from "./module-027.js"
|
||||
export { b } from "./module-027.mjs"
|
||||
@ -14,4 +14,4 @@
|
||||
*/
|
||||
|
||||
/* Can't have circular imports/exports. */
|
||||
export { b } from "./module-026.js"
|
||||
export { b } from "./module-026.mjs"
|
||||
@ -14,4 +14,4 @@
|
||||
*/
|
||||
|
||||
/* Ambiguous import */
|
||||
import { x } from "../es.next/module-export-05.js"
|
||||
import { x } from "../es.next/module-export-05.mjs"
|
||||
@ -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";')
|
||||
@ -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"
|
||||
@ -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";
|
||||
@ -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";
|
||||
@ -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 {};
|
||||
@ -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() {}
|
||||
@ -13,4 +13,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import "./module-export-001.js"
|
||||
import "./module-await-001.mjs"
|
||||
@ -13,4 +13,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import "./module-await-001.js"
|
||||
import "./module-await-001.mjs"
|
||||
@ -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";
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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':
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user