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