• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "jcontext.h"
17 #include "jerryscript.h"
18 
19 #include "ecma-exceptions.h"
20 #include "ecma-function-object.h"
21 #include "ecma-gc.h"
22 #include "ecma-globals.h"
23 #include "ecma-helpers.h"
24 #include "ecma-lex-env.h"
25 #include "ecma-module.h"
26 #include "ecma-objects.h"
27 #include "lit-char-helpers.h"
28 #include "vm.h"
29 
30 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
31 
32 /**
33  * Takes a ModuleSpecifier and applies path normalization to it.
34  * It's not checked if the ModuleSpecifier is a valid path or not.
35  * Note: See 15.2.1.17
36  *
37  * @return pointer to ecma_string_t containing the normalized and zero terminated path
38  */
39 ecma_string_t *
ecma_module_create_normalized_path(const uint8_t * char_p,prop_length_t size)40 ecma_module_create_normalized_path (const uint8_t *char_p, /**< module specifier */
41                                     prop_length_t size) /**< size of module specifier */
42 {
43   JERRY_ASSERT (size > 0);
44   ecma_string_t *ret_p = NULL;
45 
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);
49 
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;
56 
57   lit_utf8_byte_t *module_path_p = NULL;
58   lit_utf8_size_t module_path_size = 0;
59 
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)
63   {
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;
74   }
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   if (normalized_size > 0)
83   {
84     /* Convert the normalized path to cesu8. */
85     ret_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (normalized_out_p, (lit_utf8_size_t) (normalized_size));
86   }
87 
88   jmem_heap_free_block (path_p, size + 1u);
89   jmem_heap_free_block (normalized_out_p, ECMA_MODULE_MAX_PATH);
90   if (module_path_p != NULL)
91   {
92     jmem_heap_free_block (module_path_p, module_path_size + 1);
93   }
94 
95   return ret_p;
96 } /* ecma_module_create_normalized_path */
97 
98 /**
99  * Find a module with a specific identifier
100  *
101  * @return pointer to ecma_module_t, if found
102  *         NULL, otherwise
103  */
104 ecma_module_t *
ecma_module_find_module(ecma_string_t * const path_p)105 ecma_module_find_module (ecma_string_t *const path_p) /**< module identifier */
106 {
107   ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
108   while (current_p != NULL)
109   {
110     if (ecma_compare_ecma_strings (path_p, current_p->path_p))
111     {
112       return current_p;
113     }
114     current_p = current_p->next_p;
115   }
116 
117   return current_p;
118 } /* ecma_module_find_module */
119 
120 /**
121  * Create a new module
122  *
123  * @return pointer to created module
124  */
125 static ecma_module_t *
ecma_module_create_module(ecma_string_t * const path_p)126 ecma_module_create_module (ecma_string_t *const path_p) /**< module identifier */
127 {
128   ecma_module_t *module_p = (ecma_module_t *) jmem_heap_alloc_block (sizeof (ecma_module_t));
129   memset (module_p, 0, sizeof (ecma_module_t));
130 
131   module_p->path_p = path_p;
132   module_p->next_p = JERRY_CONTEXT (ecma_modules_p);
133   JERRY_CONTEXT (ecma_modules_p) = module_p;
134   return module_p;
135 } /* ecma_module_create_module */
136 
137 /**
138  * Checks if we already have a module request in the module list.
139  *
140  * @return pointer to found or newly created module structure
141  */
142 ecma_module_t *
ecma_module_find_or_create_module(ecma_string_t * const path_p)143 ecma_module_find_or_create_module (ecma_string_t *const path_p) /**< module path */
144 {
145   ecma_module_t *module_p = ecma_module_find_module (path_p);
146   if (module_p)
147   {
148     ecma_deref_ecma_string (path_p);
149     return module_p;
150   }
151 
152   return ecma_module_create_module (path_p);
153 } /* ecma_module_find_or_create_module */
154 
155 /**
156  * Create a new native module
157  *
158  * @return pointer to created module
159  */
160 ecma_module_t *
ecma_module_create_native_module(ecma_string_t * const path_p,ecma_object_t * const namespace_p)161 ecma_module_create_native_module (ecma_string_t *const path_p, /**< module identifier */
162                                   ecma_object_t *const namespace_p) /**< module namespace */
163 {
164   ecma_module_t *module_p = ecma_module_create_module (path_p);
165   module_p->state = ECMA_MODULE_STATE_NATIVE;
166   module_p->namespace_object_p = namespace_p;
167   return module_p;
168 } /* ecma_module_create_native_module */
169 
170 /**
171  * Creates a module context.
172  *
173  * @return pointer to created module context
174  */
175 static ecma_module_context_t *
ecma_module_create_module_context(void)176 ecma_module_create_module_context (void)
177 {
178   ecma_module_context_t *context_p = (ecma_module_context_t *) jmem_heap_alloc_block (sizeof (ecma_module_context_t));
179   memset (context_p, 0, sizeof (ecma_module_context_t));
180 
181   return context_p;
182 } /* ecma_module_create_module_context */
183 
184 /**
185  *  Inserts a {module, export_name} record into a resolve set.
186  *  Note: See 15.2.1.16.3 - resolveSet and exportStarSet
187  *
188  *  @return true - if the set already contains the record
189  *          false - otherwise
190  */
191 bool
ecma_module_resolve_set_insert(ecma_module_resolve_set_t ** set_p,ecma_module_t * const module_p,ecma_string_t * const export_name_p)192 ecma_module_resolve_set_insert (ecma_module_resolve_set_t **set_p, /**< [in, out] resolve set */
193                                 ecma_module_t * const module_p, /**< module */
194                                 ecma_string_t * const export_name_p) /**< export name */
195 {
196   JERRY_ASSERT (set_p != NULL);
197   ecma_module_resolve_set_t *current_p = *set_p;
198 
199   while (current_p != NULL)
200   {
201     if (current_p->record.module_p == module_p
202         && ecma_compare_ecma_strings (current_p->record.name_p, export_name_p))
203     {
204       return false;
205     }
206 
207     current_p = current_p->next_p;
208   }
209 
210   ecma_module_resolve_set_t *new_p;
211   new_p = (ecma_module_resolve_set_t *) jmem_heap_alloc_block (sizeof (ecma_module_resolve_set_t));
212 
213   new_p->next_p = *set_p;
214   new_p->record.module_p = module_p;
215   ecma_ref_ecma_string (export_name_p);
216   new_p->record.name_p = export_name_p;
217 
218   *set_p = new_p;
219   return true;
220 } /* ecma_module_resolve_set_insert */
221 
222 /**
223  * Cleans up contents of a resolve set.
224  */
225 void
ecma_module_resolve_set_cleanup(ecma_module_resolve_set_t * set_p)226 ecma_module_resolve_set_cleanup (ecma_module_resolve_set_t *set_p) /**< resolve set */
227 {
228   while (set_p != NULL)
229   {
230     ecma_module_resolve_set_t *next_p = set_p->next_p;
231     ecma_deref_ecma_string (set_p->record.name_p);
232     jmem_heap_free_block (set_p, sizeof (ecma_module_resolve_set_t));
233     set_p = next_p;
234   }
235 } /* ecma_module_resolve_set_cleanup */
236 
237 /**
238  * Pushes a new resolve frame on top of a resolve stack and initializes it
239  * to begin resolving the specified exported name in the base module.
240  */
241 void
ecma_module_resolve_stack_push(ecma_module_resolve_stack_t ** stack_p,ecma_module_t * const module_p,ecma_string_t * const export_name_p)242 ecma_module_resolve_stack_push (ecma_module_resolve_stack_t **stack_p, /**< [in, out] resolve stack */
243                                 ecma_module_t * const module_p, /**< base module */
244                                 ecma_string_t * const export_name_p) /**< exported name */
245 {
246   JERRY_ASSERT (stack_p != NULL);
247   ecma_module_resolve_stack_t *new_frame_p;
248   new_frame_p = (ecma_module_resolve_stack_t *) jmem_heap_alloc_block (sizeof (ecma_module_resolve_stack_t));
249 
250   ecma_ref_ecma_string (export_name_p);
251   new_frame_p->export_name_p = export_name_p;
252   new_frame_p->module_p = module_p;
253   new_frame_p->resolving = false;
254 
255   new_frame_p->next_p = *stack_p;
256   *stack_p = new_frame_p;
257 } /* ecma_module_resolve_stack_push */
258 
259 /**
260  * Pops the topmost frame from a resolve stack.
261  */
262 void
ecma_module_resolve_stack_pop(ecma_module_resolve_stack_t ** stack_p)263 ecma_module_resolve_stack_pop (ecma_module_resolve_stack_t **stack_p) /**< [in, out] resolve stack */
264 {
265   JERRY_ASSERT (stack_p != NULL);
266   ecma_module_resolve_stack_t *current_p = *stack_p;
267 
268   if (current_p != NULL)
269   {
270     *stack_p = current_p->next_p;
271     ecma_deref_ecma_string (current_p->export_name_p);
272     jmem_heap_free_block (current_p, sizeof (ecma_module_resolve_stack_t));
273   }
274 } /* ecma_module_resolve_stack_pop */
275 
276 /**
277  * Resolves which module satisfies an export based from a specific module in the import tree.
278  * If no error occurs, out_record_p will contain a {module, local_name} record, which satisfies
279  * the export, or {NULL, NULL} if the export is ambiguous.
280  * Note: See 15.2.1.16.3
281  *
282  * @return ECMA_VALUE_ERROR - if an error occured
283  *         ECMA_VALUE_EMPTY - otherwise
284  */
285 static ecma_value_t
ecma_module_resolve_export(ecma_module_t * const module_p,ecma_string_t * const export_name_p,ecma_module_record_t * out_record_p)286 ecma_module_resolve_export (ecma_module_t * const module_p, /**< base module */
287                             ecma_string_t * const export_name_p, /**< export name */
288                             ecma_module_record_t *out_record_p) /**< [out] found module record */
289 {
290   ecma_module_resolve_set_t *resolve_set_p = NULL;
291   ecma_module_resolve_stack_t *stack_p = NULL;
292 
293   bool found = false;
294   ecma_module_record_t found_record = { NULL, NULL };
295   ecma_value_t ret_value = ECMA_VALUE_EMPTY;
296 
297   ecma_module_resolve_stack_push (&stack_p, module_p, export_name_p);
298 
299   while (stack_p != NULL)
300   {
301     ecma_module_resolve_stack_t *current_frame_p = stack_p;
302 
303     ecma_module_t *current_module_p = current_frame_p->module_p;
304     JERRY_ASSERT (current_module_p->state >= ECMA_MODULE_STATE_PARSED);
305     ecma_module_context_t *context_p = current_module_p->context_p;
306     ecma_string_t *current_export_name_p = current_frame_p->export_name_p;
307 
308     if (!current_frame_p->resolving)
309     {
310       current_frame_p->resolving = true;
311 
312       /* 15.2.1.16.3 / 2-3 */
313       if (!ecma_module_resolve_set_insert (&resolve_set_p, current_module_p, current_export_name_p))
314       {
315         /* This is a circular import request. */
316         ecma_module_resolve_stack_pop (&stack_p);
317         continue;
318       }
319 
320       if (current_module_p->state == ECMA_MODULE_STATE_NATIVE)
321       {
322         ecma_object_t *object_p = current_module_p->namespace_object_p;
323         ecma_value_t prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p),
324                                                            object_p,
325                                                            current_export_name_p);
326         if (ecma_is_value_found (prop_value))
327         {
328           found = true;
329           found_record.module_p = current_module_p;
330           found_record.name_p = current_export_name_p;
331           ecma_free_value (prop_value);
332         }
333 
334         if (ecma_compare_ecma_string_to_magic_id (current_export_name_p, LIT_MAGIC_STRING_DEFAULT))
335         {
336           ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("No default export in native module."));
337           break;
338         }
339 
340         ecma_module_resolve_stack_pop (&stack_p);
341         continue;
342       }
343 
344       if (context_p->local_exports_p != NULL)
345       {
346         /* 15.2.1.16.3 / 4 */
347         JERRY_ASSERT (context_p->local_exports_p->next_p == NULL);
348         ecma_module_names_t *export_names_p = context_p->local_exports_p->module_names_p;
349         while (export_names_p != NULL)
350         {
351           if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p))
352           {
353             if (found)
354             {
355               /* This is an ambigous export. */
356               found_record.module_p = NULL;
357               found_record.name_p = NULL;
358               break;
359             }
360 
361             /* The current module provides a direct binding for this export. */
362             found = true;
363             found_record.module_p = current_module_p;
364             found_record.name_p = export_names_p->local_name_p;
365             break;
366           }
367 
368           export_names_p = export_names_p->next_p;
369         }
370       }
371 
372       if (found)
373       {
374         /* We found a resolution for the current frame, return to the previous. */
375         ecma_module_resolve_stack_pop (&stack_p);
376         continue;
377       }
378 
379       /* 15.2.1.16.3 / 5 */
380       ecma_module_node_t *indirect_export_p = context_p->indirect_exports_p;
381       while (indirect_export_p != NULL)
382       {
383         ecma_module_names_t *export_names_p = indirect_export_p->module_names_p;
384         while (export_names_p != NULL)
385         {
386           if (ecma_compare_ecma_strings (current_export_name_p, export_names_p->imex_name_p))
387           {
388             /* 5.2.1.16.3 / 5.a.iv */
389             ecma_module_resolve_stack_push (&stack_p,
390                                             indirect_export_p->module_request_p,
391                                             export_names_p->local_name_p);
392           }
393 
394           export_names_p = export_names_p->next_p;
395         }
396 
397         indirect_export_p = indirect_export_p->next_p;
398       }
399 
400       /* We need to check whether the newly pushed indirect exports resolve to anything.
401        * Keep current frame in the stack, and continue from the topmost frame. */
402       continue;
403     } /* if (!current_frame_p->resolving) */
404 
405     /* By the time we return to the current frame, the indirect exports will have finished resolving. */
406     if (found)
407     {
408       /* We found at least one export that satisfies the current request.
409        * Pop current frame, and return to the previous. */
410       ecma_module_resolve_stack_pop (&stack_p);
411       continue;
412     }
413 
414     /* 15.2.1.16.3 / 6 */
415     if (ecma_compare_ecma_string_to_magic_id (current_export_name_p, LIT_MAGIC_STRING_DEFAULT))
416     {
417       ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("No explicitly defined default export in module."));
418       break;
419     }
420 
421     /* 15.2.1.16.3 / 7-8 */
422     if (!ecma_module_resolve_set_insert (&resolve_set_p,
423                                          current_module_p,
424                                          ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)))
425     {
426       /* This is a circular import request. */
427       ecma_module_resolve_stack_pop (&stack_p);
428       continue;
429     }
430 
431     /* Pop the current frame, we have nothing else to do here after the star export resolutions are queued. */
432     ecma_module_resolve_stack_pop (&stack_p);
433 
434     /* 15.2.1.16.3 / 10 */
435     ecma_module_node_t *star_export_p = context_p->star_exports_p;
436     while (star_export_p != NULL)
437     {
438       JERRY_ASSERT (star_export_p->module_names_p == NULL);
439 
440       /* 15.2.1.16.3 / 10.c */
441       ecma_module_resolve_stack_push (&stack_p, star_export_p->module_request_p, export_name_p);
442 
443       star_export_p = star_export_p->next_p;
444     }
445   }
446 
447   /* Clean up. */
448   ecma_module_resolve_set_cleanup (resolve_set_p);
449   while (stack_p)
450   {
451     ecma_module_resolve_stack_pop (&stack_p);
452   }
453 
454   if (ECMA_IS_VALUE_ERROR (ret_value))
455   {
456     /* No default export was found */
457     return ret_value;
458   }
459 
460   if (found)
461   {
462     *out_record_p = found_record;
463   }
464   else
465   {
466     ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("Unexported or circular import request."));
467   }
468 
469   return ret_value;
470 } /* ecma_module_resolve_export */
471 
472 /**
473  * Resolves an export and adds it to the modules namespace object, if the export name is not yet handled.
474  * Note: See 15.2.1.16.2 and 15.2.1.18
475  *
476  * @return ECMA_VALUE_ERROR - if an error occured
477  *         ECMA_VALUE_EMPTY - otherwise
478  */
479 static ecma_value_t
ecma_module_namespace_object_add_export_if_needed(ecma_module_t * module_p,ecma_string_t * export_name_p)480 ecma_module_namespace_object_add_export_if_needed (ecma_module_t *module_p, /**< module */
481                                                    ecma_string_t *export_name_p) /**< export name */
482 {
483   JERRY_ASSERT (module_p->namespace_object_p != NULL);
484   ecma_value_t result = ECMA_VALUE_EMPTY;
485 
486   if (ecma_find_named_property (module_p->namespace_object_p, export_name_p) != NULL)
487   {
488     /* This export name has already been handled. */
489     return result;
490   }
491 
492   ecma_module_record_t record;
493   result = ecma_module_resolve_export (module_p, export_name_p, &record);
494 
495   if (ECMA_IS_VALUE_ERROR (result))
496   {
497     return result;
498   }
499 
500   if (record.module_p == NULL)
501   {
502     /* 15.2.1.18 / 3.d.iv Skip ambiguous names. */
503     return result;
504   }
505 
506   ecma_object_t *ref_base_lex_env_p;
507   ecma_value_t prop_value = ecma_op_get_value_lex_env_base (record.module_p->scope_p,
508                                                             &ref_base_lex_env_p,
509                                                             record.name_p);
510   ecma_property_t *new_property_p;
511   ecma_create_named_data_property (module_p->namespace_object_p,
512                                    export_name_p,
513                                    ECMA_PROPERTY_FIXED,
514                                    &new_property_p);
515 
516   ecma_named_data_property_assign_value (module_p->namespace_object_p,
517                                          ECMA_PROPERTY_VALUE_PTR (new_property_p),
518                                          prop_value);
519 
520   ecma_free_value (prop_value);
521   return result;
522 } /* ecma_module_namespace_object_add_export_if_needed */
523 
524 /**
525  * Creates a namespace object for a module.
526  * Note: See 15.2.1.18
527  *
528  * @return ECMA_VALUE_ERROR - if an error occured
529  *         ECMA_VALUE_EMPTY - otherwise
530  */
531 static ecma_value_t
ecma_module_create_namespace_object(ecma_module_t * module_p)532 ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
533 {
534   ecma_value_t result = ECMA_VALUE_EMPTY;
535   if (module_p->namespace_object_p != NULL)
536   {
537     return result;
538   }
539 
540   JERRY_ASSERT (module_p->state == ECMA_MODULE_STATE_EVALUATED);
541   ecma_module_resolve_set_t *resolve_set_p = NULL;
542   ecma_module_resolve_stack_t *stack_p = NULL;
543 
544   module_p->namespace_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE),
545                                                      0,
546                                                      ECMA_OBJECT_TYPE_GENERAL);
547 
548   ecma_module_resolve_stack_push (&stack_p, module_p, ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR));
549   while (stack_p != NULL)
550   {
551     ecma_module_resolve_stack_t *current_frame_p = stack_p;
552     ecma_module_t *current_module_p = current_frame_p->module_p;
553     ecma_module_context_t *context_p = current_module_p->context_p;
554 
555     ecma_module_resolve_stack_pop (&stack_p);
556 
557     /* 15.2.1.16.2 / 2-3 */
558     if (!ecma_module_resolve_set_insert (&resolve_set_p,
559                                          current_module_p,
560                                          ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)))
561     {
562       /* Circular import. */
563       continue;
564     }
565 
566     if (context_p->local_exports_p != NULL)
567     {
568       /* 15.2.1.16.2 / 5 */
569       JERRY_ASSERT (context_p->local_exports_p->next_p == NULL);
570       ecma_module_names_t *export_names_p = context_p->local_exports_p->module_names_p;
571       while (export_names_p != NULL && ecma_is_value_empty (result))
572       {
573         result = ecma_module_namespace_object_add_export_if_needed (module_p,
574                                                                     export_names_p->imex_name_p);
575         export_names_p = export_names_p->next_p;
576       }
577     }
578 
579     /* 15.2.1.16.2 / 6 */
580     ecma_module_node_t *indirect_export_p = context_p->indirect_exports_p;
581     while (indirect_export_p != NULL && ecma_is_value_empty (result))
582     {
583       ecma_module_names_t *export_names_p = indirect_export_p->module_names_p;
584       while (export_names_p != NULL && ecma_is_value_empty (result))
585       {
586         result = ecma_module_namespace_object_add_export_if_needed (module_p,
587                                                                     export_names_p->imex_name_p);
588         export_names_p = export_names_p->next_p;
589       }
590       indirect_export_p = indirect_export_p->next_p;
591     }
592 
593     /* 15.2.1.16.2 / 7 */
594     ecma_module_node_t *star_export_p = context_p->star_exports_p;
595     while (star_export_p != NULL && ecma_is_value_empty (result))
596     {
597       JERRY_ASSERT (star_export_p->module_names_p == NULL);
598 
599       /* 15.2.1.16.3/10.c */
600       ecma_module_resolve_stack_push (&stack_p,
601                                       star_export_p->module_request_p,
602                                       ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR));
603 
604       star_export_p = star_export_p->next_p;
605     }
606   }
607 
608   /* Clean up. */
609   ecma_module_resolve_set_cleanup (resolve_set_p);
610   while (stack_p)
611   {
612     ecma_module_resolve_stack_pop (&stack_p);
613   }
614 
615   return result;
616 } /* ecma_module_create_namespace_object */
617 
618 /**
619  * Evaluates an EcmaScript module.
620  *
621  * @return ECMA_VALUE_ERROR - if an error occured
622  *         ECMA_VALUE_EMPTY - otherwise
623  */
624 static ecma_value_t
ecma_module_evaluate(ecma_module_t * module_p)625 ecma_module_evaluate (ecma_module_t *module_p) /**< module */
626 {
627   JERRY_ASSERT (module_p->state >= ECMA_MODULE_STATE_PARSED);
628 
629   if (module_p->state >= ECMA_MODULE_STATE_EVALUATING)
630   {
631     return ECMA_VALUE_EMPTY;
632   }
633 
634   module_p->state = ECMA_MODULE_STATE_EVALUATING;
635   module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment ());
636   module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
637   JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
638 
639   ecma_value_t ret_value;
640   ret_value = vm_run_module (module_p->compiled_code_p,
641                              module_p->scope_p);
642 
643   if (!ECMA_IS_VALUE_ERROR (ret_value))
644   {
645     jerry_release_value (ret_value);
646     ret_value = ECMA_VALUE_EMPTY;
647   }
648 
649   JERRY_CONTEXT (module_top_context_p) = module_p->context_p->parent_p;
650 
651   ecma_bytecode_deref (module_p->compiled_code_p);
652   module_p->state = ECMA_MODULE_STATE_EVALUATED;
653 
654   return ret_value;
655 } /* ecma_module_evaluate */
656 
657 /**
658  * Connects imported values to the current context.
659  *
660  * @return ECMA_VALUE_ERROR - if an error occured
661  *         ECMA_VALUE_EMPTY - otherwise
662  */
663 static ecma_value_t
ecma_module_connect_imports(void)664 ecma_module_connect_imports (void)
665 {
666   ecma_module_context_t *current_context_p = JERRY_CONTEXT (module_top_context_p);
667 
668   ecma_object_t *local_env_p = current_context_p->module_p->scope_p;
669   JERRY_ASSERT (ecma_is_lexical_environment (local_env_p));
670 
671   ecma_module_node_t *import_node_p = current_context_p->imports_p;
672 
673   /* Check that the imported bindings don't exist yet. */
674   while (import_node_p != NULL)
675   {
676     ecma_module_names_t *import_names_p = import_node_p->module_names_p;
677 
678     while (import_names_p != NULL)
679     {
680       ecma_object_t *lex_env_p = local_env_p;
681       ecma_property_t *binding_p = NULL;
682 
683       if (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
684       {
685         binding_p = ecma_find_named_property (lex_env_p, import_names_p->local_name_p);
686 
687         JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
688         lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
689       }
690 
691       if (binding_p != NULL)
692       {
693         return ecma_raise_syntax_error (ECMA_ERR_MSG ("Imported binding shadows local variable."));
694       }
695 
696       ecma_value_t status = ecma_op_has_binding (lex_env_p, import_names_p->local_name_p);
697 
698 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
699       if (ECMA_IS_VALUE_ERROR (status))
700       {
701         return status;
702       }
703 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
704 
705       if (ecma_is_value_true (status))
706       {
707         return ecma_raise_syntax_error (ECMA_ERR_MSG ("Imported binding shadows local variable."));
708       }
709 
710       import_names_p = import_names_p->next_p;
711     }
712 
713     import_node_p = import_node_p->next_p;
714   }
715 
716   import_node_p = current_context_p->imports_p;
717 
718   /* Resolve imports and create local bindings. */
719   while (import_node_p != NULL)
720   {
721     ecma_value_t result = ecma_module_evaluate (import_node_p->module_request_p);
722     if (ECMA_IS_VALUE_ERROR (result))
723     {
724       return result;
725     }
726 
727     ecma_module_names_t *import_names_p = import_node_p->module_names_p;
728     while (import_names_p != NULL)
729     {
730       const bool is_namespace_import = ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p,
731                                                                              LIT_MAGIC_STRING_ASTERIX_CHAR);
732 
733       if (is_namespace_import)
734       {
735         result = ecma_module_create_namespace_object (import_node_p->module_request_p);
736         if (ECMA_IS_VALUE_ERROR (result))
737         {
738           return result;
739         }
740 
741         ecma_op_create_mutable_binding (local_env_p, import_names_p->local_name_p, true /* is_deletable */);
742         ecma_op_set_mutable_binding (local_env_p,
743                                      import_names_p->local_name_p,
744                                      ecma_make_object_value (import_node_p->module_request_p->namespace_object_p),
745                                      false /* is_strict */);
746       }
747       else /* !is_namespace_import */
748       {
749         ecma_module_record_t record;
750         result = ecma_module_resolve_export (import_node_p->module_request_p, import_names_p->imex_name_p, &record);
751 
752         if (ECMA_IS_VALUE_ERROR (result))
753         {
754           return result;
755         }
756 
757         if (record.module_p == NULL)
758         {
759           return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous import request."));
760         }
761 
762         if (record.module_p->state == ECMA_MODULE_STATE_NATIVE)
763         {
764           ecma_object_t *object_p = record.module_p->namespace_object_p;
765           ecma_value_t prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p),
766                                                              object_p,
767                                                              record.name_p);
768           JERRY_ASSERT (ecma_is_value_found (prop_value));
769 
770           ecma_op_create_mutable_binding (local_env_p, import_names_p->local_name_p, true /* is_deletable */);
771           ecma_op_set_mutable_binding (local_env_p,
772                                        import_names_p->local_name_p,
773                                        prop_value,
774                                        false /* is_strict */);
775 
776           ecma_free_value (prop_value);
777         }
778         else
779         {
780           result = ecma_module_evaluate (record.module_p);
781 
782           if (ECMA_IS_VALUE_ERROR (result))
783           {
784             return result;
785           }
786 
787           ecma_object_t *ref_base_lex_env_p;
788           ecma_value_t prop_value = ecma_op_get_value_lex_env_base (record.module_p->scope_p,
789                                                                     &ref_base_lex_env_p,
790                                                                     record.name_p);
791 
792           ecma_op_create_mutable_binding (local_env_p, import_names_p->local_name_p, true /* is_deletable */);
793           ecma_op_set_mutable_binding (local_env_p,
794                                        import_names_p->local_name_p,
795                                        prop_value,
796                                        false /* is_strict */);
797 
798           ecma_free_value (prop_value);
799         }
800       }
801 
802       import_names_p = import_names_p->next_p;
803     }
804 
805     import_node_p = import_node_p->next_p;
806   }
807 
808   return ECMA_VALUE_EMPTY;
809 } /* ecma_module_connect_imports */
810 
811 /**
812  * Initialize the current module by creating the local binding for the imported variables
813  * and verifying indirect exports.
814  *
815  * @return ECMA_VALUE_ERROR - if an error occured
816  *         ECMA_VALUE_EMPTY - otherwise
817  */
818 ecma_value_t
ecma_module_initialize_current(void)819 ecma_module_initialize_current (void)
820 {
821   ecma_value_t ret_value = ecma_module_connect_imports ();
822 
823   if (ecma_is_value_empty (ret_value))
824   {
825     ret_value = ecma_module_check_indirect_exports ();
826   }
827 
828   return ret_value;
829 } /* ecma_module_initialize_current */
830 
831 /**
832  * Parses an EcmaScript module.
833  *
834  * @return ECMA_VALUE_ERROR - if an error occured
835  *         ECMA_VALUE_EMPTY - otherwise
836  */
837 static jerry_value_t
ecma_module_parse(ecma_module_t * module_p)838 ecma_module_parse (ecma_module_t *module_p) /**< module */
839 {
840   if (module_p->state >= ECMA_MODULE_STATE_PARSING)
841   {
842     return ECMA_VALUE_EMPTY;
843   }
844 
845   module_p->state = ECMA_MODULE_STATE_PARSING;
846   module_p->context_p = ecma_module_create_module_context ();
847 
848   lit_utf8_size_t module_path_size = ecma_string_get_size (module_p->path_p);
849   lit_utf8_byte_t *module_path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (module_path_size + 1);
850 
851   lit_utf8_size_t module_path_utf8_size;
852   module_path_utf8_size = ecma_string_copy_to_utf8_buffer (module_p->path_p,
853                                                            module_path_p,
854                                                            module_path_size);
855   module_path_p[module_path_utf8_size] = LIT_CHAR_NULL;
856 
857   size_t source_size = 0;
858   uint8_t *source_p = jerry_port_read_source ((const char *) module_path_p, &source_size);
859   jmem_heap_free_block (module_path_p, module_path_size + 1);
860 
861   if (source_p == NULL)
862   {
863     return ecma_raise_syntax_error (ECMA_ERR_MSG ("File not found."));
864   }
865 
866   module_p->context_p->module_p = module_p;
867   module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
868   JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
869 
870 #if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
871   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
872   {
873     jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
874                                 JERRY_DEBUGGER_NO_SUBTYPE,
875                                 module_path_p,
876                                 module_path_size - 1);
877   }
878 #endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
879 
880   JERRY_CONTEXT (resource_name) = ecma_make_string_value (module_p->path_p);
881 
882   ecma_compiled_code_t *bytecode_data_p;
883   ecma_value_t ret_value = parser_parse_script (NULL,
884                                                 0,
885                                                 (jerry_char_t *) source_p,
886                                                 source_size,
887                                                 ECMA_PARSE_STRICT_MODE | ECMA_PARSE_MODULE,
888                                                 &bytecode_data_p);
889 
890   JERRY_CONTEXT (module_top_context_p) = module_p->context_p->parent_p;
891 
892   jerry_port_release_source (source_p);
893 
894   if (ECMA_IS_VALUE_ERROR (ret_value))
895   {
896     return ret_value;
897   }
898 
899   ecma_free_value (ret_value);
900 
901   module_p->compiled_code_p = bytecode_data_p;
902   module_p->state = ECMA_MODULE_STATE_PARSED;
903 
904   return ECMA_VALUE_EMPTY;
905 } /* ecma_module_parse */
906 
907 /**
908  * Parses all referenced modules.
909  *
910  * @return ECMA_VALUE_ERROR - if an error occured
911  *         ECMA_VALUE_EMPTY - otherwise
912  */
913 ecma_value_t
ecma_module_parse_modules(void)914 ecma_module_parse_modules (void)
915 {
916   ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
917 
918   while (current_p != NULL)
919   {
920     ecma_value_t ret_value = ecma_module_parse (current_p);
921     if (ECMA_IS_VALUE_ERROR (ret_value))
922     {
923       return ret_value;
924     }
925 
926     JERRY_ASSERT (ecma_is_value_empty (ret_value));
927     current_p = current_p->next_p;
928   }
929 
930   return ECMA_VALUE_EMPTY;
931 } /* ecma_module_parse_modules */
932 
933 /**
934  * Checks if indirect exports in the current context are resolvable.
935  * Note: See 15.2.1.16.4 / 9.
936  *
937  * @return ECMA_VALUE_ERROR - if an error occured
938  *         ECMA_VALUE_EMPTY - otherwise
939  */
940 ecma_value_t
ecma_module_check_indirect_exports(void)941 ecma_module_check_indirect_exports (void)
942 {
943   ecma_module_node_t *indirect_export_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
944   while (indirect_export_p != NULL)
945   {
946     ecma_module_names_t *name_p = indirect_export_p->module_names_p;
947     while (name_p != NULL)
948     {
949       ecma_module_record_t record;
950       ecma_value_t result = ecma_module_resolve_export (indirect_export_p->module_request_p,
951                                                         name_p->local_name_p,
952                                                         &record);
953 
954       if (ECMA_IS_VALUE_ERROR (result))
955       {
956         return result;
957       }
958 
959       if (record.module_p == NULL)
960       {
961         return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous indirect export request."));
962       }
963 
964       name_p = name_p->next_p;
965     }
966 
967     indirect_export_p = indirect_export_p->next_p;
968   }
969 
970   return ECMA_VALUE_EMPTY;
971 } /* ecma_module_check_indirect_exports */
972 
973 /**
974  * Cleans up a list of module names.
975  */
976 static void
ecma_module_release_module_names(ecma_module_names_t * module_name_p)977 ecma_module_release_module_names (ecma_module_names_t *module_name_p) /**< first module name */
978 {
979   while (module_name_p != NULL)
980   {
981     ecma_module_names_t *next_p = module_name_p->next_p;
982 
983     ecma_deref_ecma_string (module_name_p->imex_name_p);
984     ecma_deref_ecma_string (module_name_p->local_name_p);
985     jmem_heap_free_block (module_name_p, sizeof (ecma_module_names_t));
986 
987     module_name_p = next_p;
988   }
989 } /* ecma_module_release_module_names */
990 
991 /**
992  * Cleans up a list of module nodes.
993  */
994 void
ecma_module_release_module_nodes(ecma_module_node_t * module_node_p)995 ecma_module_release_module_nodes (ecma_module_node_t *module_node_p) /**< first module node */
996 {
997   while (module_node_p != NULL)
998   {
999     ecma_module_node_t *next_p = module_node_p->next_p;
1000 
1001     ecma_module_release_module_names (module_node_p->module_names_p);
1002     jmem_heap_free_block (module_node_p, sizeof (ecma_module_node_t));
1003 
1004     module_node_p = next_p;
1005   }
1006 } /* ecma_module_release_module_nodes */
1007 
1008 /**
1009  * Cleans up a module context.
1010  */
1011 static void
ecma_module_release_module_context(ecma_module_context_t * module_context_p)1012 ecma_module_release_module_context (ecma_module_context_t *module_context_p) /**< modle context */
1013 {
1014   ecma_module_release_module_nodes (module_context_p->imports_p);
1015   ecma_module_release_module_nodes (module_context_p->local_exports_p);
1016   ecma_module_release_module_nodes (module_context_p->indirect_exports_p);
1017   ecma_module_release_module_nodes (module_context_p->star_exports_p);
1018 
1019   jmem_heap_free_block (module_context_p, sizeof (ecma_module_context_t));
1020 } /* ecma_module_release_module_context */
1021 
1022 /**
1023  * Cleans up a module structure.
1024  */
1025 static void
ecma_module_release_module(ecma_module_t * module_p)1026 ecma_module_release_module (ecma_module_t *module_p) /**< module */
1027 {
1028   ecma_deref_ecma_string (module_p->path_p);
1029 
1030   if (module_p->namespace_object_p != NULL)
1031   {
1032     ecma_deref_object (module_p->namespace_object_p);
1033   }
1034 
1035   if (module_p->state == ECMA_MODULE_STATE_NATIVE)
1036   {
1037     goto finished;
1038   }
1039 
1040   if (module_p->state >= ECMA_MODULE_STATE_PARSING)
1041   {
1042     ecma_module_release_module_context (module_p->context_p);
1043   }
1044 
1045   if (module_p->state >= ECMA_MODULE_STATE_EVALUATING
1046       && module_p->scope_p != NULL)
1047   {
1048     ecma_deref_object (module_p->scope_p);
1049   }
1050 
1051   if (module_p->state >= ECMA_MODULE_STATE_PARSED
1052       && module_p->state < ECMA_MODULE_STATE_EVALUATED)
1053   {
1054     ecma_bytecode_deref (module_p->compiled_code_p);
1055   }
1056 
1057 finished:
1058   jmem_heap_free_block (module_p, sizeof (ecma_module_t));
1059 } /* ecma_module_release_module */
1060 
1061 /**
1062  * Cleans up all modules if the current context is the root context.
1063  */
1064 void
ecma_module_cleanup(void)1065 ecma_module_cleanup (void)
1066 {
1067   ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
1068   while (current_p != NULL)
1069   {
1070     ecma_module_t *next_p = current_p->next_p;
1071     ecma_module_release_module (current_p);
1072     current_p = next_p;
1073   }
1074 
1075   JERRY_CONTEXT (ecma_modules_p) = NULL;
1076   JERRY_CONTEXT (module_top_context_p) = NULL;
1077 } /* ecma_module_cleanup */
1078 
1079 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1080