Skip to content

Commit 0fec913

Browse files
author
Dániel Bátyai
authored
Rework module parsing and execution (#4462)
This patch disables automatic detection of module code, and instead requires the user to explicitly specify whether to parse a source as a module or as a script. To achieve this the jerry_parse API function now takes a new option which signals that the source should be parsed as a module. JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai [email protected]
1 parent ef8a6a9 commit 0fec913

File tree

85 files changed

+573
-490
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+573
-490
lines changed

docs/02.API-REFERENCE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,10 @@ Option bits for [jerry_parse](#jerry_parse) and
212212

213213
- JERRY_PARSE_NO_OPTS - no options passed
214214
- JERRY_PARSE_STRICT_MODE - enable strict mode
215+
- JERRY_PARSE_MODULE - parse source as an ECMAScript module
215216

216217
*New in version 2.0*.
218+
*Changed in version 2.4: Added `JERRY_PARSE_MODULE`.*
217219

218220
## jerry_gc_mode_t
219221

jerry-core/api/jerry.c

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,6 @@ jerry_cleanup (void)
246246
}
247247
}
248248

249-
#if ENABLED (JERRY_MODULE_SYSTEM)
250-
ecma_module_cleanup ();
251-
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
252-
253249
#if ENABLED (JERRY_BUILTIN_PROMISE)
254250
ecma_free_all_enqueued_jobs ();
255251
#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
@@ -456,6 +452,15 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
456452
}
457453
#endif /* ENABLED (JERRY_RESOURCE_NAME) */
458454

455+
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
456+
{
457+
#if ENABLED (JERRY_MODULE_SYSTEM)
458+
ecma_module_initialize_context (ecma_get_string_from_value (resource_name));
459+
#else /* !ENABLED (JERRY_MODULE_SYSTEM) */
460+
return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("Module system has been disabled.")));
461+
#endif /* !ENABLED (JERRY_MODULE_SYSTEM) */
462+
}
463+
459464
ecma_compiled_code_t *bytecode_data_p = parser_parse_script (NULL,
460465
0,
461466
source_p,
@@ -465,16 +470,54 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
465470

466471
if (JERRY_UNLIKELY (bytecode_data_p == NULL))
467472
{
473+
#if ENABLED (JERRY_MODULE_SYSTEM)
474+
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
475+
{
476+
ecma_module_cleanup_context ();
477+
}
478+
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
479+
468480
return ecma_create_error_reference_from_context ();
469481
}
470482

483+
#if ENABLED (JERRY_MODULE_SYSTEM)
484+
if ((parse_opts & JERRY_PARSE_MODULE) != 0)
485+
{
486+
if (ECMA_IS_VALUE_ERROR (ecma_module_parse_referenced_modules ()))
487+
{
488+
ecma_bytecode_deref (bytecode_data_p);
489+
ecma_module_cleanup_context ();
490+
491+
return ecma_create_error_reference_from_context ();
492+
}
493+
494+
ecma_object_t *obj_p = ecma_create_object (NULL, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS);
495+
496+
ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) obj_p;
497+
wrapper_p->u.class_prop.class_id = LIT_MAGIC_STRING_RUNNABLE_UL;
498+
wrapper_p->u.class_prop.extra_info = ECMA_RUNNABLE_FLAGS_MODULE;
499+
500+
ecma_module_t *root_module_p = JERRY_CONTEXT (module_current_p);
501+
root_module_p->compiled_code_p = bytecode_data_p;
502+
503+
ECMA_SET_INTERNAL_VALUE_POINTER (wrapper_p->u.class_prop.u.value, root_module_p);
504+
JERRY_CONTEXT (module_current_p) = NULL;
505+
JERRY_CONTEXT (module_list_p) = NULL;
506+
507+
return ecma_make_object_value (obj_p);
508+
}
509+
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
510+
471511
ecma_object_t *global_object_p = ecma_builtin_get_global ();
472512

473513
#if ENABLED (JERRY_BUILTIN_REALMS)
474514
JERRY_ASSERT (global_object_p == (ecma_object_t *) ecma_op_function_get_realm (bytecode_data_p));
475515
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
476516

477517
ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p);
518+
519+
/* TODO(dbatyai): For now Scripts continue to return Function objects due to backwards compatibility. This should be
520+
* changed to also return a Runnable object eventually. */
478521
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
479522
ecma_bytecode_deref (bytecode_data_p);
480523

@@ -588,15 +631,35 @@ jerry_run (const jerry_value_t func_val) /**< function to run */
588631
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
589632
}
590633

591-
ecma_object_t *func_obj_p = ecma_get_object_from_value (func_val);
634+
ecma_object_t *obj_p = ecma_get_object_from_value (func_val);
635+
636+
#if ENABLED (JERRY_MODULE_SYSTEM)
637+
if (ecma_object_class_is (obj_p, LIT_MAGIC_STRING_RUNNABLE_UL))
638+
{
639+
ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) obj_p;
640+
JERRY_ASSERT (wrapper_p->u.class_prop.extra_info == ECMA_RUNNABLE_FLAGS_MODULE);
641+
ecma_module_t *root_module_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_module_t, wrapper_p->u.class_prop.u.value);
642+
643+
#if ENABLED (JERRY_BUILTIN_REALMS)
644+
ecma_object_t *global_object_p = (ecma_object_t *) ecma_op_function_get_realm (root_module_p->compiled_code_p);
645+
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
646+
ecma_object_t *global_object_p = ecma_builtin_get_global ();
647+
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
648+
649+
ecma_create_global_lexical_block (global_object_p);
650+
root_module_p->scope_p = ecma_get_global_scope (global_object_p);
651+
652+
return jerry_return (vm_run_module (root_module_p));
653+
}
654+
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
592655

593-
if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION
594-
|| ecma_get_object_is_builtin (func_obj_p))
656+
if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_FUNCTION
657+
|| ecma_get_object_is_builtin (obj_p))
595658
{
596659
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
597660
}
598661

599-
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
662+
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p;
600663

601664
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
602665

jerry-core/ecma/base/ecma-gc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,20 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
16301630
break;
16311631
}
16321632
#endif /* ENABLED (JERRY_ESNEXT) */
1633+
#if ENABLED (JERRY_MODULE_SYSTEM)
1634+
case LIT_MAGIC_STRING_RUNNABLE_UL:
1635+
{
1636+
ecma_extended_object_t *wrapper_p = (ecma_extended_object_t *) object_p;
1637+
1638+
JERRY_ASSERT (wrapper_p->u.class_prop.extra_info == ECMA_RUNNABLE_FLAGS_MODULE);
1639+
ecma_module_t *root_module_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_module_t,
1640+
wrapper_p->u.class_prop.u.value);
1641+
1642+
ecma_bytecode_deref (root_module_p->compiled_code_p);
1643+
ecma_module_cleanup (root_module_p);
1644+
break;
1645+
}
1646+
#endif /* ENABLED (JERRY_MODULE_SYSTEM) */
16331647
default:
16341648
{
16351649
/* The undefined id represents an uninitialized class. */

jerry-core/ecma/base/ecma-globals.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,14 @@ typedef struct
10591059
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
10601060

10611061
#if ENABLED (JERRY_ESNEXT)
1062+
/**
1063+
* Flags for runnable objects.
1064+
*/
1065+
typedef enum
1066+
{
1067+
ECMA_RUNNABLE_FLAGS_EMPTY = (0), /**< empty flags */
1068+
ECMA_RUNNABLE_FLAGS_MODULE = (1 << 0) /**< runnable is a module */
1069+
} ecma_runnable_flags_t;
10621070

10631071
/**
10641072
* Description of arrow function objects.

0 commit comments

Comments
 (0)