• 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  * Evaluates an EcmaScript module.
474  *
475  * @return ECMA_VALUE_ERROR - if an error occured
476  *         ECMA_VALUE_EMPTY - otherwise
477  */
478 static ecma_value_t
ecma_module_evaluate(ecma_module_t * module_p)479 ecma_module_evaluate (ecma_module_t *module_p) /**< module */
480 {
481   JERRY_ASSERT (module_p->state >= ECMA_MODULE_STATE_PARSED);
482 
483   if (module_p->state >= ECMA_MODULE_STATE_EVALUATING)
484   {
485     return ECMA_VALUE_EMPTY;
486   }
487 
488   module_p->state = ECMA_MODULE_STATE_EVALUATING;
489   module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment ());
490   module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
491   JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
492 
493   ecma_value_t ret_value;
494   ret_value = vm_run_module (module_p->compiled_code_p,
495                              module_p->scope_p);
496 
497   if (!ECMA_IS_VALUE_ERROR (ret_value))
498   {
499     ecma_free_value (ret_value);
500     ret_value = ECMA_VALUE_EMPTY;
501   }
502 
503   JERRY_CONTEXT (module_top_context_p) = module_p->context_p->parent_p;
504 
505   ecma_bytecode_deref (module_p->compiled_code_p);
506   module_p->state = ECMA_MODULE_STATE_EVALUATED;
507 
508   return ret_value;
509 } /* ecma_module_evaluate */
510 
511 /**
512  * Resolves an export and adds it to the modules namespace object, if the export name is not yet handled.
513  * Note: See 15.2.1.16.2 and 15.2.1.18
514  *
515  * @return ECMA_VALUE_ERROR - if an error occured
516  *         ECMA_VALUE_EMPTY - otherwise
517  */
518 static ecma_value_t
ecma_module_namespace_object_add_export_if_needed(ecma_module_t * module_p,ecma_string_t * export_name_p)519 ecma_module_namespace_object_add_export_if_needed (ecma_module_t *module_p, /**< module */
520                                                    ecma_string_t *export_name_p) /**< export name */
521 {
522   JERRY_ASSERT (module_p->namespace_object_p != NULL);
523   ecma_value_t result = ECMA_VALUE_EMPTY;
524 
525   /* Default exports should not be added to the namespace object. */
526   if (ecma_compare_ecma_string_to_magic_id (export_name_p, LIT_MAGIC_STRING_DEFAULT)
527       || ecma_find_named_property (module_p->namespace_object_p, export_name_p) != NULL)
528   {
529     /* This export name has already been handled. */
530     return result;
531   }
532 
533   ecma_module_record_t record;
534   result = ecma_module_resolve_export (module_p, export_name_p, &record);
535 
536   if (ECMA_IS_VALUE_ERROR (result))
537   {
538     return result;
539   }
540 
541   if (record.module_p == NULL)
542   {
543     /* 15.2.1.18 / 3.d.iv Skip ambiguous names. */
544     return result;
545   }
546 
547   ecma_object_t *ref_base_lex_env_p;
548   ecma_value_t prop_value = ecma_op_get_value_lex_env_base (record.module_p->scope_p,
549                                                             &ref_base_lex_env_p,
550                                                             record.name_p);
551   ecma_property_t *new_property_p;
552   ecma_create_named_data_property (module_p->namespace_object_p,
553                                    export_name_p,
554                                    ECMA_PROPERTY_FIXED,
555                                    &new_property_p);
556 
557   ecma_named_data_property_assign_value (module_p->namespace_object_p,
558                                          ECMA_PROPERTY_VALUE_PTR (new_property_p),
559                                          prop_value);
560 
561   ecma_free_value (prop_value);
562   return result;
563 } /* ecma_module_namespace_object_add_export_if_needed */
564 
565 /**
566  * Creates a namespace object for a module.
567  * Note: See 15.2.1.18
568  *
569  * @return ECMA_VALUE_ERROR - if an error occured
570  *         ECMA_VALUE_EMPTY - otherwise
571  */
572 static ecma_value_t
ecma_module_create_namespace_object(ecma_module_t * module_p)573 ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
574 {
575   ecma_value_t result = ECMA_VALUE_EMPTY;
576   if (module_p->namespace_object_p != NULL)
577   {
578     return result;
579   }
580 
581   JERRY_ASSERT (module_p->state == ECMA_MODULE_STATE_EVALUATED);
582   ecma_module_resolve_set_t *resolve_set_p = NULL;
583   ecma_module_resolve_stack_t *stack_p = NULL;
584 
585   module_p->namespace_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE),
586                                                      0,
587                                                      ECMA_OBJECT_TYPE_GENERAL);
588 
589   ecma_module_resolve_stack_push (&stack_p, module_p, ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR));
590   while (stack_p != NULL)
591   {
592     ecma_module_resolve_stack_t *current_frame_p = stack_p;
593     ecma_module_t *current_module_p = current_frame_p->module_p;
594     ecma_module_context_t *context_p = current_module_p->context_p;
595 
596     ecma_module_resolve_stack_pop (&stack_p);
597 
598     /* 15.2.1.16.2 / 2-3 */
599     if (!ecma_module_resolve_set_insert (&resolve_set_p,
600                                          current_module_p,
601                                          ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR)))
602     {
603       /* Circular import. */
604       continue;
605     }
606 
607     result = ecma_module_evaluate (current_module_p);
608 
609     if (ECMA_IS_VALUE_ERROR (result))
610     {
611       break;
612     }
613 
614     if (context_p->local_exports_p != NULL)
615     {
616       /* 15.2.1.16.2 / 5 */
617       JERRY_ASSERT (context_p->local_exports_p->next_p == NULL);
618       ecma_module_names_t *export_names_p = context_p->local_exports_p->module_names_p;
619       while (export_names_p != NULL && ecma_is_value_empty (result))
620       {
621         result = ecma_module_namespace_object_add_export_if_needed (module_p,
622                                                                     export_names_p->imex_name_p);
623         export_names_p = export_names_p->next_p;
624       }
625     }
626 
627     /* 15.2.1.16.2 / 6 */
628     ecma_module_node_t *indirect_export_p = context_p->indirect_exports_p;
629     while (indirect_export_p != NULL && ecma_is_value_empty (result))
630     {
631       ecma_module_names_t *export_names_p = indirect_export_p->module_names_p;
632       while (export_names_p != NULL && ecma_is_value_empty (result))
633       {
634         result = ecma_module_namespace_object_add_export_if_needed (module_p,
635                                                                     export_names_p->imex_name_p);
636         export_names_p = export_names_p->next_p;
637       }
638       indirect_export_p = indirect_export_p->next_p;
639     }
640 
641     /* 15.2.1.16.2 / 7 */
642     ecma_module_node_t *star_export_p = context_p->star_exports_p;
643     while (star_export_p != NULL && ecma_is_value_empty (result))
644     {
645       JERRY_ASSERT (star_export_p->module_names_p == NULL);
646 
647       /* 15.2.1.16.3/10.c */
648       ecma_module_resolve_stack_push (&stack_p,
649                                       star_export_p->module_request_p,
650                                       ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR));
651 
652       star_export_p = star_export_p->next_p;
653     }
654   }
655 
656   /* Clean up. */
657   ecma_module_resolve_set_cleanup (resolve_set_p);
658   while (stack_p)
659   {
660     ecma_module_resolve_stack_pop (&stack_p);
661   }
662 
663   return result;
664 } /* ecma_module_create_namespace_object */
665 
666 /**
667  * Connects imported values to the current context.
668  *
669  * @return ECMA_VALUE_ERROR - if an error occured
670  *         ECMA_VALUE_EMPTY - otherwise
671  */
672 static ecma_value_t
ecma_module_connect_imports(void)673 ecma_module_connect_imports (void)
674 {
675   ecma_module_context_t *current_context_p = JERRY_CONTEXT (module_top_context_p);
676 
677   ecma_object_t *local_env_p = current_context_p->module_p->scope_p;
678   JERRY_ASSERT (ecma_is_lexical_environment (local_env_p));
679 
680   ecma_module_node_t *import_node_p = current_context_p->imports_p;
681 
682   /* Check that the imported bindings don't exist yet. */
683   while (import_node_p != NULL)
684   {
685     ecma_module_names_t *import_names_p = import_node_p->module_names_p;
686 
687     while (import_names_p != NULL)
688     {
689       ecma_object_t *lex_env_p = local_env_p;
690       ecma_property_t *binding_p = NULL;
691 
692       if (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
693       {
694         binding_p = ecma_find_named_property (lex_env_p, import_names_p->local_name_p);
695 
696         JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
697         lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
698       }
699 
700       if (binding_p != NULL)
701       {
702         return ecma_raise_syntax_error (ECMA_ERR_MSG ("Imported binding shadows local variable."));
703       }
704 
705       ecma_value_t status = ecma_op_has_binding (lex_env_p, import_names_p->local_name_p);
706 
707 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
708       if (ECMA_IS_VALUE_ERROR (status))
709       {
710         return status;
711       }
712 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
713 
714       if (ecma_is_value_true (status))
715       {
716         return ecma_raise_syntax_error (ECMA_ERR_MSG ("Imported binding shadows local variable."));
717       }
718 
719       import_names_p = import_names_p->next_p;
720     }
721 
722     import_node_p = import_node_p->next_p;
723   }
724 
725   import_node_p = current_context_p->imports_p;
726 
727   /* Resolve imports and create local bindings. */
728   while (import_node_p != NULL)
729   {
730     ecma_value_t result = ecma_module_evaluate (import_node_p->module_request_p);
731     if (ECMA_IS_VALUE_ERROR (result))
732     {
733       return result;
734     }
735 
736     ecma_module_names_t *import_names_p = import_node_p->module_names_p;
737     while (import_names_p != NULL)
738     {
739       const bool is_namespace_import = ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p,
740                                                                              LIT_MAGIC_STRING_ASTERIX_CHAR);
741 
742       if (is_namespace_import)
743       {
744         result = ecma_module_create_namespace_object (import_node_p->module_request_p);
745         if (ECMA_IS_VALUE_ERROR (result))
746         {
747           return result;
748         }
749 
750         ecma_op_create_mutable_binding (local_env_p, import_names_p->local_name_p, true /* is_deletable */);
751         ecma_op_set_mutable_binding (local_env_p,
752                                      import_names_p->local_name_p,
753                                      ecma_make_object_value (import_node_p->module_request_p->namespace_object_p),
754                                      false /* is_strict */);
755       }
756       else /* !is_namespace_import */
757       {
758         ecma_module_record_t record;
759         result = ecma_module_resolve_export (import_node_p->module_request_p, import_names_p->imex_name_p, &record);
760 
761         if (ECMA_IS_VALUE_ERROR (result))
762         {
763           return result;
764         }
765 
766         if (record.module_p == NULL)
767         {
768           return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous import request."));
769         }
770 
771         if (record.module_p->state == ECMA_MODULE_STATE_NATIVE)
772         {
773           ecma_object_t *object_p = record.module_p->namespace_object_p;
774           ecma_value_t prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p),
775                                                              object_p,
776                                                              record.name_p);
777           JERRY_ASSERT (ecma_is_value_found (prop_value));
778 
779           ecma_op_create_mutable_binding (local_env_p, import_names_p->local_name_p, true /* is_deletable */);
780           ecma_op_set_mutable_binding (local_env_p,
781                                        import_names_p->local_name_p,
782                                        prop_value,
783                                        false /* is_strict */);
784 
785           ecma_free_value (prop_value);
786         }
787         else
788         {
789           result = ecma_module_evaluate (record.module_p);
790 
791           if (ECMA_IS_VALUE_ERROR (result))
792           {
793             return result;
794           }
795 
796           ecma_object_t *ref_base_lex_env_p;
797           ecma_value_t prop_value = ecma_op_get_value_lex_env_base (record.module_p->scope_p,
798                                                                     &ref_base_lex_env_p,
799                                                                     record.name_p);
800 
801           ecma_op_create_mutable_binding (local_env_p, import_names_p->local_name_p, true /* is_deletable */);
802           ecma_op_set_mutable_binding (local_env_p,
803                                        import_names_p->local_name_p,
804                                        prop_value,
805                                        false /* is_strict */);
806 
807           ecma_free_value (prop_value);
808         }
809       }
810 
811       import_names_p = import_names_p->next_p;
812     }
813 
814     import_node_p = import_node_p->next_p;
815   }
816 
817   return ECMA_VALUE_EMPTY;
818 } /* ecma_module_connect_imports */
819 
820 /**
821  * Initialize the current module by creating the local binding for the imported variables
822  * and verifying indirect exports.
823  *
824  * @return ECMA_VALUE_ERROR - if an error occured
825  *         ECMA_VALUE_EMPTY - otherwise
826  */
827 ecma_value_t
ecma_module_initialize_current(void)828 ecma_module_initialize_current (void)
829 {
830   ecma_value_t ret_value = ecma_module_connect_imports ();
831 
832   if (ecma_is_value_empty (ret_value))
833   {
834     ret_value = ecma_module_check_indirect_exports ();
835   }
836 
837   return ret_value;
838 } /* ecma_module_initialize_current */
839 
840 /**
841  * Parses an EcmaScript module.
842  *
843  * @return ECMA_VALUE_ERROR - if an error occured
844  *         ECMA_VALUE_EMPTY - otherwise
845  */
846 static jerry_value_t
ecma_module_parse(ecma_module_t * module_p)847 ecma_module_parse (ecma_module_t *module_p) /**< module */
848 {
849   if (module_p->state >= ECMA_MODULE_STATE_PARSING)
850   {
851     return ECMA_VALUE_EMPTY;
852   }
853 
854   module_p->state = ECMA_MODULE_STATE_PARSING;
855   module_p->context_p = ecma_module_create_module_context ();
856 
857   lit_utf8_size_t module_path_size = ecma_string_get_size (module_p->path_p);
858   lit_utf8_byte_t *module_path_p = (lit_utf8_byte_t *) jmem_heap_alloc_block (module_path_size + 1);
859 
860   lit_utf8_size_t module_path_utf8_size;
861   module_path_utf8_size = ecma_string_copy_to_utf8_buffer (module_p->path_p,
862                                                            module_path_p,
863                                                            module_path_size);
864   module_path_p[module_path_utf8_size] = LIT_CHAR_NULL;
865 
866   size_t source_size = 0;
867   uint8_t *source_p = jerry_port_read_source ((const char *) module_path_p, &source_size);
868   jmem_heap_free_block (module_path_p, module_path_size + 1);
869 
870   if (source_p == NULL)
871   {
872     return ecma_raise_syntax_error (ECMA_ERR_MSG ("File not found."));
873   }
874 
875   module_p->context_p->module_p = module_p;
876   module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
877   JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
878 
879 #if ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER)
880   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
881   {
882     jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE_NAME,
883                                 JERRY_DEBUGGER_NO_SUBTYPE,
884                                 module_path_p,
885                                 module_path_size - 1);
886   }
887 #endif /* ENABLED (JERRY_DEBUGGER) && ENABLED (JERRY_PARSER) */
888 
889   JERRY_CONTEXT (resource_name) = ecma_make_string_value (module_p->path_p);
890 
891   ecma_compiled_code_t *bytecode_data_p;
892   ecma_value_t ret_value = parser_parse_script (NULL,
893                                                 0,
894                                                 (jerry_char_t *) source_p,
895                                                 source_size,
896                                                 ECMA_PARSE_STRICT_MODE | ECMA_PARSE_MODULE,
897                                                 &bytecode_data_p);
898 
899   JERRY_CONTEXT (module_top_context_p) = module_p->context_p->parent_p;
900 
901   jerry_port_release_source (source_p);
902 
903   if (ECMA_IS_VALUE_ERROR (ret_value))
904   {
905     return ret_value;
906   }
907 
908   ecma_free_value (ret_value);
909 
910   module_p->compiled_code_p = bytecode_data_p;
911   module_p->state = ECMA_MODULE_STATE_PARSED;
912 
913   return ECMA_VALUE_EMPTY;
914 } /* ecma_module_parse */
915 
916 /**
917  * Parses all referenced modules.
918  *
919  * @return ECMA_VALUE_ERROR - if an error occured
920  *         ECMA_VALUE_EMPTY - otherwise
921  */
922 ecma_value_t
ecma_module_parse_modules(void)923 ecma_module_parse_modules (void)
924 {
925   ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
926 
927   while (current_p != NULL)
928   {
929     ecma_value_t ret_value = ecma_module_parse (current_p);
930     if (ECMA_IS_VALUE_ERROR (ret_value))
931     {
932       return ret_value;
933     }
934 
935     JERRY_ASSERT (ecma_is_value_empty (ret_value));
936     current_p = current_p->next_p;
937   }
938 
939   return ECMA_VALUE_EMPTY;
940 } /* ecma_module_parse_modules */
941 
942 /**
943  * Checks if indirect exports in the current context are resolvable.
944  * Note: See 15.2.1.16.4 / 9.
945  *
946  * @return ECMA_VALUE_ERROR - if an error occured
947  *         ECMA_VALUE_EMPTY - otherwise
948  */
949 ecma_value_t
ecma_module_check_indirect_exports(void)950 ecma_module_check_indirect_exports (void)
951 {
952   ecma_module_node_t *indirect_export_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
953   while (indirect_export_p != NULL)
954   {
955     ecma_module_names_t *name_p = indirect_export_p->module_names_p;
956     while (name_p != NULL)
957     {
958       ecma_module_record_t record;
959       ecma_value_t result = ecma_module_resolve_export (indirect_export_p->module_request_p,
960                                                         name_p->local_name_p,
961                                                         &record);
962 
963       if (ECMA_IS_VALUE_ERROR (result))
964       {
965         return result;
966       }
967 
968       if (record.module_p == NULL)
969       {
970         return ecma_raise_syntax_error (ECMA_ERR_MSG ("Ambiguous indirect export request."));
971       }
972 
973       name_p = name_p->next_p;
974     }
975 
976     indirect_export_p = indirect_export_p->next_p;
977   }
978 
979   return ECMA_VALUE_EMPTY;
980 } /* ecma_module_check_indirect_exports */
981 
982 /**
983  * Cleans up a list of module names.
984  */
985 static void
ecma_module_release_module_names(ecma_module_names_t * module_name_p)986 ecma_module_release_module_names (ecma_module_names_t *module_name_p) /**< first module name */
987 {
988   while (module_name_p != NULL)
989   {
990     ecma_module_names_t *next_p = module_name_p->next_p;
991 
992     ecma_deref_ecma_string (module_name_p->imex_name_p);
993     ecma_deref_ecma_string (module_name_p->local_name_p);
994     jmem_heap_free_block (module_name_p, sizeof (ecma_module_names_t));
995 
996     module_name_p = next_p;
997   }
998 } /* ecma_module_release_module_names */
999 
1000 /**
1001  * Cleans up a list of module nodes.
1002  */
1003 void
ecma_module_release_module_nodes(ecma_module_node_t * module_node_p)1004 ecma_module_release_module_nodes (ecma_module_node_t *module_node_p) /**< first module node */
1005 {
1006   while (module_node_p != NULL)
1007   {
1008     ecma_module_node_t *next_p = module_node_p->next_p;
1009 
1010     ecma_module_release_module_names (module_node_p->module_names_p);
1011     jmem_heap_free_block (module_node_p, sizeof (ecma_module_node_t));
1012 
1013     module_node_p = next_p;
1014   }
1015 } /* ecma_module_release_module_nodes */
1016 
1017 /**
1018  * Cleans up a module context.
1019  */
1020 static void
ecma_module_release_module_context(ecma_module_context_t * module_context_p)1021 ecma_module_release_module_context (ecma_module_context_t *module_context_p) /**< modle context */
1022 {
1023   ecma_module_release_module_nodes (module_context_p->imports_p);
1024   ecma_module_release_module_nodes (module_context_p->local_exports_p);
1025   ecma_module_release_module_nodes (module_context_p->indirect_exports_p);
1026   ecma_module_release_module_nodes (module_context_p->star_exports_p);
1027 
1028   jmem_heap_free_block (module_context_p, sizeof (ecma_module_context_t));
1029 } /* ecma_module_release_module_context */
1030 
1031 /**
1032  * Cleans up a module structure.
1033  */
1034 static void
ecma_module_release_module(ecma_module_t * module_p)1035 ecma_module_release_module (ecma_module_t *module_p) /**< module */
1036 {
1037   ecma_deref_ecma_string (module_p->path_p);
1038 
1039   if (module_p->namespace_object_p != NULL)
1040   {
1041     ecma_deref_object (module_p->namespace_object_p);
1042   }
1043 
1044   if (module_p->state == ECMA_MODULE_STATE_NATIVE)
1045   {
1046     goto finished;
1047   }
1048 
1049   if (module_p->state >= ECMA_MODULE_STATE_PARSING)
1050   {
1051     ecma_module_release_module_context (module_p->context_p);
1052   }
1053 
1054   if (module_p->state >= ECMA_MODULE_STATE_EVALUATING
1055       && module_p->scope_p != NULL)
1056   {
1057     ecma_deref_object (module_p->scope_p);
1058   }
1059 
1060   if (module_p->state >= ECMA_MODULE_STATE_PARSED
1061       && module_p->state < ECMA_MODULE_STATE_EVALUATED)
1062   {
1063     ecma_bytecode_deref (module_p->compiled_code_p);
1064   }
1065 
1066 finished:
1067   jmem_heap_free_block (module_p, sizeof (ecma_module_t));
1068 } /* ecma_module_release_module */
1069 
1070 /**
1071  * Cleans up all modules if the current context is the root context.
1072  */
1073 void
ecma_module_cleanup(void)1074 ecma_module_cleanup (void)
1075 {
1076   ecma_module_t *current_p = JERRY_CONTEXT (ecma_modules_p);
1077   while (current_p != NULL)
1078   {
1079     ecma_module_t *next_p = current_p->next_p;
1080     ecma_module_release_module (current_p);
1081     current_p = next_p;
1082   }
1083 
1084   JERRY_CONTEXT (ecma_modules_p) = NULL;
1085   JERRY_CONTEXT (module_top_context_p) = NULL;
1086 } /* ecma_module_cleanup */
1087 
1088 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1089