Resolve module paths relative to the current module (#2976)

The current module implementation resolves module paths relative to the
current working directory, but paths should be resolved relative to the
currently evaluated module/source.

This requires a change in the jerry_port_normalize_path port API
function, so that it also takes the current module path as an argument.
On the engine side, we now also create a module object for the main
script, so that we can properly identify the base path for other
modules.

Co-authored-by: Marko Fabo <mfabo@inf.u-szeged.hu>
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
This commit is contained in:
Dániel Bátyai
2019-07-17 14:44:18 +02:00
committed by GitHub
parent 6c441091b4
commit ec11a7b4e9
47 changed files with 233 additions and 129 deletions
+58 -43
View File
@@ -41,32 +41,57 @@ ecma_module_create_normalized_path (const uint8_t *char_p, /**< module specifier
prop_length_t size) /**< size of module specifier */
{
JERRY_ASSERT (size > 0);
ecma_string_t *ret_p;
ecma_string_t *ret_p = NULL;
/* Zero terminate the string. */
uint8_t *temp_p = (uint8_t *) jmem_heap_alloc_block (size + 1u);
memcpy (temp_p, char_p, size);
temp_p[size] = LIT_CHAR_NULL;
/* The module specifier is cesu8 encoded, we need to convert is to utf8, and zero terminate it,
* so that OS level functions can handle it. */
lit_utf8_byte_t *path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (size + 1u);
uint8_t *normalized_p = (uint8_t *) jmem_heap_alloc_block (ECMA_MODULE_MAX_PATH);
size_t new_size = jerry_port_normalize_path ((const char *) temp_p,
(char *) normalized_p,
ECMA_MODULE_MAX_PATH);
lit_utf8_size_t utf8_size;
utf8_size = lit_convert_cesu8_string_to_utf8_string (char_p,
size,
path_p,
size);
path_p[utf8_size] = LIT_CHAR_NULL;
lit_utf8_byte_t *module_path_p = NULL;
lit_utf8_size_t module_path_size = 0;
if (new_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)
{
/* Failed to normalize path, use original. */
ret_p = ecma_new_ecma_string_from_utf8 (temp_p, (lit_utf8_size_t) (size + 1u));
}
else
{
/* Copy the trailing \0 into the string as well, to make it more convenient to use later. */
ret_p = ecma_new_ecma_string_from_utf8 (normalized_p, (lit_utf8_size_t) (new_size + 1u));
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_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_path_p,
module_path_size);
module_path_p[module_utf8_size] = LIT_CHAR_NULL;
}
jmem_heap_free_block (temp_p, size + 1u);
jmem_heap_free_block (normalized_p, ECMA_MODULE_MAX_PATH);
lit_utf8_byte_t *normalized_out_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (ECMA_MODULE_MAX_PATH);
size_t normalized_size = jerry_port_normalize_path ((const char *) path_p,
(char *) normalized_out_p,
ECMA_MODULE_MAX_PATH,
(char *) module_path_p);
if (normalized_size > 0)
{
/* Convert the normalized path to cesu8. */
ret_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (normalized_out_p, (lit_utf8_size_t) (normalized_size));
}
jmem_heap_free_block (path_p, size + 1u);
jmem_heap_free_block (normalized_out_p, ECMA_MODULE_MAX_PATH);
if (module_path_p != NULL)
{
jmem_heap_free_block (module_path_p, module_path_size + 1);
}
return ret_p;
} /* ecma_module_create_normalized_path */
@@ -573,17 +598,7 @@ ecma_module_connect_imports (void)
{
ecma_module_context_t *current_context_p = JERRY_CONTEXT (module_top_context_p);
ecma_object_t *local_env_p;
if (current_context_p->module_p != NULL)
{
local_env_p = current_context_p->module_p->scope_p;
}
else
{
/* This is the root context. */
local_env_p = ecma_get_global_environment ();
}
ecma_object_t *local_env_p = current_context_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;
@@ -677,14 +692,18 @@ 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 script_path_size;
uint8_t flags = ECMA_STRING_FLAG_EMPTY;
const lit_utf8_byte_t *script_path_p = ecma_string_get_chars (module_p->path_p,
&script_path_size,
&flags);
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);
lit_utf8_size_t module_path_utf8_size;
module_path_utf8_size = ecma_string_copy_to_utf8_buffer (module_p->path_p,
module_path_p,
module_path_size);
module_path_p[module_path_utf8_size] = LIT_CHAR_NULL;
size_t source_size = 0;
uint8_t *source_p = jerry_port_read_source ((const char *) script_path_p, &source_size);
uint8_t *source_p = jerry_port_read_source ((const char *) module_path_p, &source_size);
jmem_heap_free_block (module_path_p, module_path_size + 1);
if (source_p == NULL)
{
@@ -700,15 +719,12 @@ ecma_module_parse (ecma_module_t *module_p) /**< module */
{
jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
JERRY_DEBUGGER_NO_SUBTYPE,
script_path_p,
script_path_size - 1);
module_path_p,
module_path_size - 1);
}
#endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
JERRY_CONTEXT (resource_name) = ecma_make_string_value (ecma_new_ecma_string_from_utf8 (script_path_p,
script_path_size - 1));
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
JERRY_CONTEXT (resource_name) = ecma_make_string_value (module_p->path_p);
ecma_compiled_code_t *bytecode_data_p;
ecma_value_t ret_value = parser_parse_script (NULL,
@@ -900,7 +916,6 @@ ecma_module_cleanup (void)
current_p = next_p;
}
ecma_module_release_module_context (JERRY_CONTEXT (module_top_context_p));
JERRY_CONTEXT (module_top_context_p) = NULL;
} /* ecma_module_cleanup */
@@ -24,9 +24,9 @@
#include "js-parser.h"
#include "lit-magic-strings.h"
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
#include "jcontext.h"
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
@@ -159,9 +159,9 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
ecma_compiled_code_t *bytecode_data_p = NULL;