Skip to content

Commit ec11a7b

Browse files
dbatyaifbmrk
andauthored
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
1 parent 6c44109 commit ec11a7b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+231
-127
lines changed

docs/05.PORT-API.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
118118
size_t
119119
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
120120
char *out_buf_p, /**< output buffer */
121-
size_t out_buf_size) /**< size of output buffer */
121+
size_t out_buf_size, /**< size of output buffer */
122+
char *base_file_p) /**< base file path */
122123
{
123124
// normalize in_path_p by expanding relative paths etc.
125+
// if base_file_p is not NULL, in_path_p is relative to that file
124126
// write to out_buf_p the normalized path
125127
// return length of written path
126128
} /* jerry_port_normalize_path */

jerry-core/api/jerry.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
402402
#if ENABLED (JERRY_PARSER)
403403
jerry_assert_api_available ();
404404

405-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
405+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
406406
if (resource_name_length == 0)
407407
{
408408
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
@@ -412,7 +412,7 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
412412
JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p,
413413
(lit_utf8_size_t) resource_name_length);
414414
}
415-
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
415+
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
416416

417417
ecma_compiled_code_t *bytecode_data_p;
418418
ecma_value_t parse_status;
@@ -481,7 +481,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u
481481
ecma_compiled_code_t *bytecode_data_p;
482482
ecma_value_t parse_status;
483483

484-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
484+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
485485
if (resource_name_length == 0)
486486
{
487487
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
@@ -491,7 +491,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u
491491
JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p,
492492
(lit_utf8_size_t) resource_name_length);
493493
}
494-
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
494+
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
495495

496496
if (arg_list_p == NULL)
497497
{

jerry-core/ecma/base/ecma-module.c

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,57 @@ ecma_module_create_normalized_path (const uint8_t *char_p, /**< module specifier
4141
prop_length_t size) /**< size of module specifier */
4242
{
4343
JERRY_ASSERT (size > 0);
44-
ecma_string_t *ret_p;
44+
ecma_string_t *ret_p = NULL;
4545

46-
/* Zero terminate the string. */
47-
uint8_t *temp_p = (uint8_t *) jmem_heap_alloc_block (size + 1u);
48-
memcpy (temp_p, char_p, size);
49-
temp_p[size] = LIT_CHAR_NULL;
46+
/* The module specifier is cesu8 encoded, we need to convert is to utf8, and zero terminate it,
47+
* so that OS level functions can handle it. */
48+
lit_utf8_byte_t *path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (size + 1u);
5049

51-
uint8_t *normalized_p = (uint8_t *) jmem_heap_alloc_block (ECMA_MODULE_MAX_PATH);
52-
size_t new_size = jerry_port_normalize_path ((const char *) temp_p,
53-
(char *) normalized_p,
54-
ECMA_MODULE_MAX_PATH);
50+
lit_utf8_size_t utf8_size;
51+
utf8_size = lit_convert_cesu8_string_to_utf8_string (char_p,
52+
size,
53+
path_p,
54+
size);
55+
path_p[utf8_size] = LIT_CHAR_NULL;
5556

57+
lit_utf8_byte_t *module_path_p = NULL;
58+
lit_utf8_size_t module_path_size = 0;
5659

57-
if (new_size == 0)
60+
/* Check if we have a current module, and use its path as the base path. */
61+
JERRY_ASSERT (JERRY_CONTEXT (module_top_context_p) != NULL);
62+
if (JERRY_CONTEXT (module_top_context_p)->module_p != NULL)
5863
{
59-
/* Failed to normalize path, use original. */
60-
ret_p = ecma_new_ecma_string_from_utf8 (temp_p, (lit_utf8_size_t) (size + 1u));
64+
JERRY_ASSERT (JERRY_CONTEXT (module_top_context_p)->module_p->path_p != NULL);
65+
module_path_size = ecma_string_get_size (JERRY_CONTEXT (module_top_context_p)->module_p->path_p);
66+
module_path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (module_path_size + 1);
67+
68+
lit_utf8_size_t module_utf8_size;
69+
module_utf8_size = ecma_string_copy_to_utf8_buffer (JERRY_CONTEXT (module_top_context_p)->module_p->path_p,
70+
module_path_p,
71+
module_path_size);
72+
73+
module_path_p[module_utf8_size] = LIT_CHAR_NULL;
6174
}
62-
else
75+
76+
lit_utf8_byte_t *normalized_out_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (ECMA_MODULE_MAX_PATH);
77+
size_t normalized_size = jerry_port_normalize_path ((const char *) path_p,
78+
(char *) normalized_out_p,
79+
ECMA_MODULE_MAX_PATH,
80+
(char *) module_path_p);
81+
82+
83+
if (normalized_size > 0)
6384
{
64-
/* Copy the trailing \0 into the string as well, to make it more convenient to use later. */
65-
ret_p = ecma_new_ecma_string_from_utf8 (normalized_p, (lit_utf8_size_t) (new_size + 1u));
85+
/* Convert the normalized path to cesu8. */
86+
ret_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (normalized_out_p, (lit_utf8_size_t) (normalized_size));
6687
}
6788

68-
jmem_heap_free_block (temp_p, size + 1u);
69-
jmem_heap_free_block (normalized_p, ECMA_MODULE_MAX_PATH);
89+
jmem_heap_free_block (path_p, size + 1u);
90+
jmem_heap_free_block (normalized_out_p, ECMA_MODULE_MAX_PATH);
91+
if (module_path_p != NULL)
92+
{
93+
jmem_heap_free_block (module_path_p, module_path_size + 1);
94+
}
7095

7196
return ret_p;
7297
} /* ecma_module_create_normalized_path */
@@ -573,17 +598,7 @@ ecma_module_connect_imports (void)
573598
{
574599
ecma_module_context_t *current_context_p = JERRY_CONTEXT (module_top_context_p);
575600

576-
ecma_object_t *local_env_p;
577-
578-
if (current_context_p->module_p != NULL)
579-
{
580-
local_env_p = current_context_p->module_p->scope_p;
581-
}
582-
else
583-
{
584-
/* This is the root context. */
585-
local_env_p = ecma_get_global_environment ();
586-
}
601+
ecma_object_t *local_env_p = current_context_p->module_p->scope_p;
587602
JERRY_ASSERT (ecma_is_lexical_environment (local_env_p));
588603

589604
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 */
677692
module_p->state = ECMA_MODULE_STATE_PARSING;
678693
module_p->context_p = ecma_module_create_module_context ();
679694

680-
lit_utf8_size_t script_path_size;
681-
uint8_t flags = ECMA_STRING_FLAG_EMPTY;
682-
const lit_utf8_byte_t *script_path_p = ecma_string_get_chars (module_p->path_p,
683-
&script_path_size,
684-
&flags);
695+
lit_utf8_size_t module_path_size = ecma_string_get_size (module_p->path_p);
696+
lit_utf8_byte_t *module_path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (module_path_size + 1);
697+
698+
lit_utf8_size_t module_path_utf8_size;
699+
module_path_utf8_size = ecma_string_copy_to_utf8_buffer (module_p->path_p,
700+
module_path_p,
701+
module_path_size);
702+
module_path_p[module_path_utf8_size] = LIT_CHAR_NULL;
685703

686704
size_t source_size = 0;
687-
uint8_t *source_p = jerry_port_read_source ((const char *) script_path_p, &source_size);
705+
uint8_t *source_p = jerry_port_read_source ((const char *) module_path_p, &source_size);
706+
jmem_heap_free_block (module_path_p, module_path_size + 1);
688707

689708
if (source_p == NULL)
690709
{
@@ -700,15 +719,12 @@ ecma_module_parse (ecma_module_t *module_p) /**< module */
700719
{
701720
jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
702721
JERRY_DEBUGGER_NO_SUBTYPE,
703-
script_path_p,
704-
script_path_size - 1);
722+
module_path_p,
723+
module_path_size - 1);
705724
}
706725
#endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
707726

708-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
709-
JERRY_CONTEXT (resource_name) = ecma_make_string_value (ecma_new_ecma_string_from_utf8 (script_path_p,
710-
script_path_size - 1));
711-
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
727+
JERRY_CONTEXT (resource_name) = ecma_make_string_value (module_p->path_p);
712728

713729
ecma_compiled_code_t *bytecode_data_p;
714730
ecma_value_t ret_value = parser_parse_script (NULL,
@@ -900,7 +916,6 @@ ecma_module_cleanup (void)
900916
current_p = next_p;
901917
}
902918

903-
ecma_module_release_module_context (JERRY_CONTEXT (module_top_context_p));
904919
JERRY_CONTEXT (module_top_context_p) = NULL;
905920
} /* ecma_module_cleanup */
906921

jerry-core/ecma/builtin-objects/ecma-builtin-function.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
#include "js-parser.h"
2525
#include "lit-magic-strings.h"
2626

27-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
27+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2828
#include "jcontext.h"
29-
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
29+
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
3030

3131
#define ECMA_BUILTINS_INTERNAL
3232
#include "ecma-builtins-internal.h"
@@ -159,9 +159,9 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
159159
ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
160160
ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
161161

162-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
162+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
163163
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
164-
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
164+
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
165165

166166
ecma_compiled_code_t *bytecode_data_p = NULL;
167167

jerry-core/include/jerryscript-port.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,16 @@ void jerry_port_release_source (uint8_t *buffer_p);
225225
* @param in_path_p Input path as a zero terminated string.
226226
* @param out_buf_p Pointer to the output buffer where the normalized path should be written.
227227
* @param out_buf_size Size of the output buffer.
228+
* @param base_file_p A file path that 'in_path_p' is relative to, usually the current module file.
229+
* A NULL value represents that 'in_path_p' is relative to the current working directory.
228230
*
229231
* @return length of the string written to the output buffer
230232
* zero, if the buffer was not sufficient or an error occured
231233
*/
232-
size_t jerry_port_normalize_path (const char *in_path_p, char *out_buf_p, size_t out_buf_size);
234+
size_t jerry_port_normalize_path (const char *in_path_p,
235+
char *out_buf_p,
236+
size_t out_buf_size,
237+
char *base_file_p);
233238

234239
/**
235240
* @}

jerry-core/jcontext/jcontext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,9 @@ struct jerry_context_t
190190
uint8_t debugger_max_receive_size; /**< maximum amount of data that can be received */
191191
#endif /* ENABLED (JERRY_DEBUGGER) */
192192

193-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
193+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
194194
ecma_value_t resource_name; /**< resource name (usually a file name) */
195-
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
195+
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
196196

197197
#if ENABLED (JERRY_MEM_STATS)
198198
jmem_heap_stats_t jmem_heap_stats; /**< heap's memory usage statistics */

jerry-core/lit/lit-magic-strings.inc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_DATE_UL, "setUTCDate")
575575
#if ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ES2015_BUILTIN)
576576
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STARTS_WITH, "startsWith")
577577
#endif
578-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
578+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
579579
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RESOURCE_ANON, "<anonymous>")
580580
#endif
581581
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \
@@ -797,7 +797,7 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_CHAR_CODE_AT_UL)
797797
#else
798798
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_ENUMERABLE)
799799
#endif
800-
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES)
800+
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
801801
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (11, LIT_MAGIC_STRING_RESOURCE_ANON)
802802
#elif ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \
803803
|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)

jerry-core/parser/js/js-parser-internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ extern const lexer_lit_location_t lexer_default_literal;
572572
void parser_module_add_export_node_to_context (parser_context_t *context_p);
573573
void parser_module_add_import_node_to_context (parser_context_t *context_p);
574574
void parser_module_check_request_place (parser_context_t *context_p);
575-
void parser_module_context_init (parser_context_t *context_p);
575+
void parser_module_context_init (void);
576576
void parser_module_handle_module_specifier (parser_context_t *context_p);
577577
void parser_module_handle_requests (parser_context_t *context_p);
578578
void parser_module_parse_export_clause (parser_context_t *context_p);

jerry-core/parser/js/js-parser-module.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,45 @@ parser_module_add_names_to_node (parser_context_t *context_p, /**< parser contex
259259
* Create module context if needed.
260260
*/
261261
void
262-
parser_module_context_init (parser_context_t *context_p) /**< parser context */
262+
parser_module_context_init (void)
263263
{
264264
if (JERRY_CONTEXT (module_top_context_p) == NULL)
265265
{
266266
ecma_module_context_t *module_context_p;
267-
module_context_p = (ecma_module_context_t *) parser_malloc (context_p,
268-
sizeof (ecma_module_context_t));
269-
267+
module_context_p = (ecma_module_context_t *) jmem_heap_alloc_block (sizeof (ecma_module_context_t));
270268
memset (module_context_p, 0, sizeof (ecma_module_context_t));
271269
JERRY_CONTEXT (module_top_context_p) = module_context_p;
270+
271+
ecma_string_t *path_str_p = ecma_get_string_from_value (JERRY_CONTEXT (resource_name));
272+
273+
lit_utf8_size_t path_str_size;
274+
uint8_t flags = ECMA_STRING_FLAG_EMPTY;
275+
276+
const lit_utf8_byte_t *path_str_chars_p = ecma_string_get_chars (path_str_p,
277+
&path_str_size,
278+
&flags);
279+
280+
ecma_string_t *path_p = ecma_module_create_normalized_path (path_str_chars_p,
281+
(prop_length_t) path_str_size);
282+
283+
if (path_p == NULL)
284+
{
285+
path_p = path_str_p;
286+
}
287+
288+
ecma_module_t *module_p = ecma_module_find_or_create_module (path_p);
289+
290+
if (path_p != path_str_p)
291+
{
292+
ecma_deref_ecma_string (path_p);
293+
}
294+
295+
module_p->state = ECMA_MODULE_STATE_EVALUATED;
296+
module_p->scope_p = ecma_get_global_environment ();
297+
ecma_ref_object (module_p->scope_p);
298+
299+
module_p->context_p = module_context_p;
300+
module_context_p->module_p = module_p;
272301
}
273302
} /* parser_module_context_init */
274303

@@ -518,6 +547,11 @@ parser_module_handle_module_specifier (parser_context_t *context_p) /**< parser
518547
ecma_string_t *path_p = ecma_module_create_normalized_path (context_p->lit_object.literal_p->u.char_p,
519548
context_p->lit_object.literal_p->prop.length);
520549

550+
if (path_p == NULL)
551+
{
552+
parser_raise_error (context_p, PARSER_ERR_FILE_NOT_FOUND);
553+
}
554+
521555
ecma_module_t *module_p = ecma_module_find_or_create_module (path_p);
522556
ecma_deref_ecma_string (path_p);
523557

jerry-core/parser/js/js-parser-statm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ parser_parse_import_statement (parser_context_t *context_p) /**< parser context
18431843
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_IMPORT);
18441844

18451845
parser_module_check_request_place (context_p);
1846-
parser_module_context_init (context_p);
1846+
parser_module_context_init ();
18471847

18481848
ecma_module_node_t module_node;
18491849
memset (&module_node, 0, sizeof (ecma_module_node_t));
@@ -1964,7 +1964,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
19641964
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_EXPORT);
19651965

19661966
parser_module_check_request_place (context_p);
1967-
parser_module_context_init (context_p);
1967+
parser_module_context_init ();
19681968

19691969
ecma_module_node_t module_node;
19701970
memset (&module_node, 0, sizeof (ecma_module_node_t));

0 commit comments

Comments
 (0)