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 */
39ecma_string_t *
40ecma_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 */
104ecma_module_t *
105ecma_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 */
125static ecma_module_t *
126ecma_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 */
142ecma_module_t *
143ecma_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 */
160ecma_module_t *
161ecma_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 */
175static ecma_module_context_t *
176ecma_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 */
191bool
192ecma_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 */
225void
226ecma_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 */
241void
242ecma_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 */
262void
263ecma_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 */
285static ecma_value_t
286ecma_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 */
478static ecma_value_t
479ecma_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 */
518static ecma_value_t
519ecma_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 */
572static ecma_value_t
573ecma_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 */
672static ecma_value_t
673ecma_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 */
827ecma_value_t
828ecma_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 */
846static jerry_value_t
847ecma_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 */
922ecma_value_t
923ecma_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 */
949ecma_value_t
950ecma_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 */
985static void
986ecma_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 */
1003void
1004ecma_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 */
1020static void
1021ecma_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 */
1034static void
1035ecma_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
1066finished:
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 */
1073void
1074ecma_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