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