Skip to content

Commit 77c2602

Browse files
authored
Implement import.meta object (#4766)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent 386ec44 commit 77c2602

27 files changed

+528
-93
lines changed

docs/02.API-REFERENCE.md

+104-4
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,31 @@ typedef void (*jerry_module_state_changed_callback_t) (jerry_module_state_t new_
952952
**See also**
953953
- [jerry_module_set_state_changed_callback](#jerry_module_set_state_changed_callback)
954954

955+
## jerry_module_import_meta_callback_t
956+
957+
**Summary**
958+
959+
Callback which is called when an import.meta expression of a module is evaluated the first time.
960+
The object returned by import.meta is passed as the `meta_object` argument to the callback, and
961+
the callback can set the initial status of the object (e.g. add properties or set prototype).
962+
963+
**Prototype**
964+
965+
```c
966+
typedef void (*jerry_module_import_meta_callback_t) (const jerry_value_t module,
967+
const jerry_value_t meta_object,
968+
void *user_p);
969+
```
970+
971+
- `module` - module whose import.meta object is requested.
972+
- `meta_object` - import.meta object created for the module.
973+
- `user_p` - pointer passed to [jerry_module_set_import_meta_callback](#jerry_module_set_import_meta_callback).
974+
975+
*New in version [[NEXT_RELEASE]]*.
976+
977+
**See also**
978+
- [jerry_module_set_import_meta_callback](#jerry_module_set_import_meta_callback)
979+
955980
## jerry_native_module_evaluate_callback_t
956981

957982
**Summary**
@@ -4996,13 +5021,12 @@ Sets a callback which is called after a module state is changed to linked, evalu
49965021
**Prototype**
49975022

49985023
```c
4999-
void
5000-
jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t callback,
5001-
void *user_p)
5024+
void jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t callback,
5025+
void *user_p);
50025026
```
50035027

50045028
- `callback` - callback, which is called after the state change.
5005-
- `module_val` - pointer passed to the callback function.
5029+
- `user_p` - pointer passed to the callback function.
50065030

50075031
*New in version [[NEXT_RELEASE]]*.
50085032

@@ -5060,6 +5084,82 @@ main (void)
50605084
- [jerry_module_state_t](#jerry_module_state_t)
50615085
- [jerry_module_state_changed_callback_t](#jerry_module_state_changed_callback_t)
50625086

5087+
## jerry_module_set_import_meta_callback
5088+
5089+
**Summary**
5090+
5091+
Sets a callback which is called when an import.meta expression of a module is evaluated the first time.
5092+
5093+
*Notes*:
5094+
- This API depends on a build option (`JERRY_MODULE_SYSTEM`) and can be checked
5095+
in runtime with the `JERRY_FEATURE_MODULE` feature enum value,
5096+
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
5097+
5098+
**Prototype**
5099+
5100+
```c
5101+
void jerry_module_set_import_meta_callback (jerry_module_import_meta_callback_t callback,
5102+
void *user_p);
5103+
```
5104+
5105+
- `callback` - callback, which is called when an import.meta
5106+
expression of a module is evaluated the first time
5107+
- `user_p` - pointer passed to the callback function.
5108+
5109+
*New in version [[NEXT_RELEASE]]*.
5110+
5111+
**Example**
5112+
5113+
[doctest]: # (test="compile")
5114+
5115+
```c
5116+
#include <jerryscript.h>
5117+
#include <stdio.h>
5118+
5119+
static void
5120+
module_import_meta_callback (const jerry_value_t module, /**< module */
5121+
const jerry_value_t meta_object, /**< import.meta object */
5122+
void *user_p) /**< user pointer */
5123+
{
5124+
(void) user_p;
5125+
5126+
/* Create a property for the meta object */
5127+
jerry_value_t property_name_value = jerry_create_string ((const jerry_char_t *) "prop");
5128+
jerry_value_t property_value = jerry_create_string ((const jerry_char_t *) "prop");
5129+
jerry_value_t result_value = jerry_set_property (meta_object, property_name_value, property_value);
5130+
jerry_release_value (result_value);
5131+
jerry_release_value (property_value);
5132+
jerry_release_value (property_name_value);
5133+
} /* module_import_meta_callback */
5134+
5135+
int
5136+
main (void)
5137+
{
5138+
jerry_init (JERRY_INIT_EMPTY);
5139+
5140+
const jerry_char_t script[] = "import.meta";
5141+
5142+
jerry_module_set_import_meta_callback (module_import_meta_callback, NULL);
5143+
5144+
jerry_parse_options_t parse_options;
5145+
parse_options.options = JERRY_PARSE_MODULE;
5146+
5147+
jerry_value_t module_value = jerry_parse (script, sizeof (script) - 1, &parse_options);
5148+
5149+
jerry_release_value (jerry_module_link (module_value, NULL, NULL));
5150+
jerry_release_value (jerry_module_evaluate (module_value));
5151+
5152+
jerry_release_value (module_value);
5153+
5154+
jerry_cleanup ();
5155+
return 0;
5156+
}
5157+
```
5158+
5159+
**See also**
5160+
5161+
- [jerry_module_import_meta_callback_t](#jerry_module_import_meta_callback_t)
5162+
50635163
## jerry_module_get_number_of_requests
50645164

50655165
**Summary**

jerry-core/api/jerry.c

+19-1
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,24 @@ jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t c
740740
#endif /* JERRY_MODULE_SYSTEM */
741741
} /* jerry_module_set_state_changed_callback */
742742

743+
/**
744+
* Sets a callback which is called when an import.meta expression of a module is evaluated the first time.
745+
*/
746+
void
747+
jerry_module_set_import_meta_callback (jerry_module_import_meta_callback_t callback, /**< callback */
748+
void *user_p) /**< pointer passed to the callback */
749+
{
750+
jerry_assert_api_available ();
751+
752+
#if JERRY_MODULE_SYSTEM
753+
JERRY_CONTEXT (module_import_meta_callback_p) = callback;
754+
JERRY_CONTEXT (module_import_meta_callback_user_p) = user_p;
755+
#else /* !JERRY_MODULE_SYSTEM */
756+
JERRY_UNUSED (callback);
757+
JERRY_UNUSED (user_p);
758+
#endif /* JERRY_MODULE_SYSTEM */
759+
} /* jerry_module_set_import_meta_callback */
760+
743761
/**
744762
* Returns the number of import/export requests of a module
745763
*
@@ -5489,7 +5507,7 @@ jerry_get_user_value (const jerry_value_t value) /**< jerry api value */
54895507
ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value;
54905508
cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
54915509

5492-
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_GENERIC)
5510+
if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE))
54935511
{
54945512
return ECMA_VALUE_UNDEFINED;
54955513
}

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -428,14 +428,24 @@ ecma_gc_mark_compiled_code (const ecma_compiled_code_t *compiled_code_p) /**< co
428428
ecma_value_t script_value = ((cbc_uint8_arguments_t *) compiled_code_p)->script_value;
429429
cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
430430

431-
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_USER_OBJECT)
431+
if (script_p->refs_and_type & CBC_SCRIPT_USER_VALUE_IS_OBJECT)
432432
{
433433
ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p);
434434

435435
JERRY_ASSERT (ecma_is_value_object (user_value));
436436
ecma_gc_set_object_visited (ecma_get_object_from_value (user_value));
437437
}
438438

439+
#if JERRY_MODULE_SYSTEM
440+
if (script_p->refs_and_type & CBC_SCRIPT_HAS_IMPORT_META)
441+
{
442+
ecma_value_t import_meta = CBC_SCRIPT_GET_IMPORT_META (script_p, script_p->refs_and_type);
443+
444+
JERRY_ASSERT (ecma_is_value_object (import_meta));
445+
ecma_gc_set_object_visited (ecma_get_object_from_value (import_meta));
446+
}
447+
#endif /* JERRY_MODULE_SYSTEM */
448+
439449
#if JERRY_BUILTIN_REALMS
440450
ecma_gc_set_object_visited (script_p->realm_p);
441451
#endif /* JERRY_BUILTIN_REALMS */

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,11 @@ typedef enum
130130
#if JERRY_ESNEXT
131131
ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 16), /**< the parser is in pre-scanning mode */
132132
#endif /* JERRY_ESNEXT */
133+
#if JERRY_MODULE_SYSTEM
134+
ECMA_PARSE_INTERNAL_HAS_IMPORT_META = (1u << 17), /**< module has import.meta expression */
135+
#endif /* JERRY_MODULE_SYSTEM */
133136
#if JERRY_FUNCTION_TO_STRING
134-
ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 17), /**< source has 4 byte marker */
137+
ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 18), /**< source has 4 byte marker */
135138
#endif /* JERRY_FUNCTION_TO_STRING */
136139
#ifndef JERRY_NDEBUG
137140
/**

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

+13-5
Original file line numberDiff line numberDiff line change
@@ -1485,14 +1485,13 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
14851485
if (script_p->refs_and_type < CBC_SCRIPT_REF_ONE)
14861486
{
14871487
size_t script_size = sizeof (cbc_script_t);
1488+
uint32_t type = script_p->refs_and_type;
14881489

1489-
uint32_t type = CBC_SCRIPT_GET_TYPE (script_p);
1490-
1491-
if (type != CBC_SCRIPT_GENERIC)
1490+
if (type & CBC_SCRIPT_HAS_USER_VALUE)
14921491
{
14931492
script_size += sizeof (ecma_value_t);
14941493

1495-
if (type == CBC_SCRIPT_USER_VALUE)
1494+
if (!(type & CBC_SCRIPT_USER_VALUE_IS_OBJECT))
14961495
{
14971496
ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p);
14981497

@@ -1505,10 +1504,19 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
15051504
ecma_deref_ecma_string (ecma_get_string_from_value (script_p->resource_name));
15061505
#endif /* JERRY_RESOURCE_NAME */
15071506

1507+
#if JERRY_MODULE_SYSTEM
1508+
if (type & CBC_SCRIPT_HAS_IMPORT_META)
1509+
{
1510+
JERRY_ASSERT (ecma_is_value_object (CBC_SCRIPT_GET_IMPORT_META (script_p, type)));
1511+
1512+
script_size += sizeof (ecma_value_t);
1513+
}
1514+
#endif /* JERRY_MODULE_SYSTEM */
1515+
15081516
#if JERRY_FUNCTION_TO_STRING
15091517
ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_code));
15101518

1511-
if (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)
1519+
if (type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)
15121520
{
15131521
ecma_deref_ecma_string (ecma_get_string_from_value (CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, type)));
15141522
script_size += sizeof (ecma_value_t);

jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ ecma_builtin_function_prototype_object_to_string (ecma_object_t *func_obj_p) /**
133133
JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS);
134134
#endif /* JERRY_SNAPSHOT_EXEC */
135135

136-
source_code = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, CBC_SCRIPT_GET_TYPE (script_p));
136+
source_code = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type);
137137
}
138138

139139
ecma_string_t *result_string_p;
@@ -179,7 +179,7 @@ ecma_builtin_function_prototype_object_to_string (ecma_object_t *func_obj_p) /**
179179
#endif /* JERRY_ESNEXT */
180180

181181
ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (ecma_get_magic_string (header_id));
182-
ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, CBC_SCRIPT_GET_TYPE (script_p));
182+
ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, script_p->refs_and_type);
183183

184184
ecma_stringbuilder_append (&builder, ecma_get_string_from_value (function_arguments));
185185
ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n) {\n", 5);

jerry-core/include/jerryscript-core.h

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ jerry_value_t jerry_module_link (const jerry_value_t module_val,
274274
jerry_value_t jerry_module_evaluate (const jerry_value_t module_val);
275275
jerry_module_state_t jerry_module_get_state (const jerry_value_t module_val);
276276
void jerry_module_set_state_changed_callback (jerry_module_state_changed_callback_t callback, void *user_p);
277+
void jerry_module_set_import_meta_callback (jerry_module_import_meta_callback_t callback, void *user_p);
277278
size_t jerry_module_get_number_of_requests (const jerry_value_t module_val);
278279
jerry_value_t jerry_module_get_request (const jerry_value_t module_val, size_t request_index);
279280
jerry_value_t jerry_module_get_namespace (const jerry_value_t module_val);

jerry-core/include/jerryscript-snapshot.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern "C"
3030
/**
3131
* Jerry snapshot format version.
3232
*/
33-
#define JERRY_SNAPSHOT_VERSION (68u)
33+
#define JERRY_SNAPSHOT_VERSION (69u)
3434

3535
/**
3636
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.

jerry-core/include/jerryscript-types.h

+6
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,12 @@ typedef jerry_value_t (*jerry_module_import_callback_t) (const jerry_value_t spe
588588
typedef void (*jerry_module_state_changed_callback_t) (jerry_module_state_t new_state, const jerry_value_t module,
589589
const jerry_value_t value, void *user_p);
590590

591+
/**
592+
* Callback which is called when an import.meta expression of a module is evaluated the first time.
593+
*/
594+
typedef void (*jerry_module_import_meta_callback_t) (const jerry_value_t module,
595+
const jerry_value_t meta_object, void *user_p);
596+
591597
/**
592598
* Callback which is called by jerry_module_evaluate to evaluate the native module.
593599
*/

jerry-core/jcontext/jcontext.h

+4
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ struct jerry_context_t
152152
jerry_module_state_changed_callback_t module_state_changed_callback_p; /**< callback which is called after the
153153
* state of a module is changed */
154154
void *module_state_changed_callback_user_p; /**< user pointer for module_state_changed_callback_p */
155+
jerry_module_import_meta_callback_t module_import_meta_callback_p; /**< callback which is called when an
156+
* import.meta expression of a module
157+
* is evaluated the first time */
158+
void *module_import_meta_callback_user_p; /**< user pointer for module_import_meta_callback_p */
155159
jerry_module_import_callback_t module_import_callback_p; /**< callback for dynamic module import */
156160
void *module_import_callback_user_p; /**< user pointer for module_import_callback_p */
157161
#endif /* JERRY_MODULE_SYSTEM */

jerry-core/parser/js/byte-code.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ JERRY_STATIC_ASSERT (offsetof (cbc_uint8_arguments_t, script_value) == offsetof
3131
*/
3232
JERRY_STATIC_ASSERT (CBC_END == 238,
3333
number_of_cbc_opcodes_changed);
34-
JERRY_STATIC_ASSERT (CBC_EXT_END == 147,
34+
JERRY_STATIC_ASSERT (CBC_EXT_END == 148,
3535
number_of_cbc_ext_opcodes_changed);
3636

3737
#if JERRY_PARSER || JERRY_PARSER_DUMP_BYTE_CODE

jerry-core/parser/js/byte-code.h

+20-18
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@
600600
VM_OC_PUSH_REST_OBJECT) \
601601
CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0, \
602602
VM_OC_MODULE_IMPORT) \
603+
CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1, \
604+
VM_OC_MODULE_IMPORT_META) \
603605
CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, \
604606
VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
605607
CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0, \
@@ -998,42 +1000,36 @@ typedef enum
9981000
*/
9991001
typedef enum
10001002
{
1001-
CBC_SCRIPT_GENERIC, /**< script without user specific data */
1002-
CBC_SCRIPT_USER_OBJECT, /**< script with a user object */
1003-
CBC_SCRIPT_USER_VALUE, /**< script with a non-object user value */
1003+
CBC_SCRIPT_HAS_USER_VALUE = (1 << 0), /**< script has user value */
1004+
CBC_SCRIPT_USER_VALUE_IS_OBJECT = (1 << 1), /**< user value is object */
1005+
CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS = (1 << 2), /**< script is a function with arguments source code */
1006+
CBC_SCRIPT_HAS_IMPORT_META = (1 << 3), /**< script is a module with import.meta object */
10041007
} cbc_script_type;
10051008

1006-
/**
1007-
* Script is a function with arguments source code.
1008-
*/
1009-
#define CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS 0x4
1010-
10111009
/**
10121010
* Value for increasing or decreasing the script reference counter.
10131011
*/
1014-
#define CBC_SCRIPT_REF_ONE 0x8
1012+
#define CBC_SCRIPT_REF_ONE 0x10
10151013

10161014
/**
10171015
* Maximum value of script reference counter.
10181016
*/
10191017
#define CBC_SCRIPT_REF_MAX (UINT32_MAX - CBC_SCRIPT_REF_ONE + 1)
10201018

1021-
/**
1022-
* Get the type of a script.
1023-
*/
1024-
#define CBC_SCRIPT_GET_TYPE(script_p) ((script_p)->refs_and_type & 0x3)
1025-
10261019
/**
10271020
* Sets the type of a script using the user_value.
10281021
*/
10291022
#define CBC_SCRIPT_SET_TYPE(script_p, user_value, ref_count) \
10301023
do \
10311024
{ \
1032-
(script_p)->refs_and_type = ((ref_count) | CBC_SCRIPT_GENERIC); \
1025+
(script_p)->refs_and_type = (ref_count); \
10331026
if ((user_value) != ECMA_VALUE_EMPTY) \
10341027
{ \
1035-
(script_p)->refs_and_type = (ecma_is_value_object (user_value) ? ((ref_count) | CBC_SCRIPT_USER_OBJECT) \
1036-
: ((ref_count) | CBC_SCRIPT_USER_VALUE)); \
1028+
(script_p)->refs_and_type |= CBC_SCRIPT_HAS_USER_VALUE; \
1029+
if (ecma_is_value_object (user_value)) \
1030+
{ \
1031+
(script_p)->refs_and_type |= CBC_SCRIPT_USER_VALUE_IS_OBJECT; \
1032+
} \
10371033
} \
10381034
} \
10391035
while (false)
@@ -1073,7 +1069,13 @@ typedef struct
10731069
* Get function arguments.
10741070
*/
10751071
#define CBC_SCRIPT_GET_FUNCTION_ARGUMENTS(script_p, type) \
1076-
(CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[(type) != CBC_SCRIPT_GENERIC ? 1 : 0])
1072+
(CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) & CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0])
1073+
1074+
/**
1075+
* Get import.meta object.
1076+
*/
1077+
#define CBC_SCRIPT_GET_IMPORT_META(script_p, type) \
1078+
(CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) & CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0])
10771079

10781080
#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,
10791081

jerry-core/parser/js/js-lexer.c

+3
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ static const keyword_string_t keywords_with_length_4[] =
491491
LEXER_KEYWORD ("else", LEXER_KEYW_ELSE),
492492
LEXER_KEYWORD ("enum", LEXER_KEYW_ENUM),
493493
LEXER_KEYWORD ("eval", LEXER_KEYW_EVAL),
494+
#if JERRY_MODULE_SYSTEM
495+
LEXER_KEYWORD ("meta", LEXER_KEYW_META),
496+
#endif /* JERRY_MODULE_SYSTEM */
494497
LEXER_KEYWORD ("null", LEXER_LIT_NULL),
495498
LEXER_KEYWORD ("this", LEXER_KEYW_THIS),
496499
LEXER_KEYWORD ("true", LEXER_LIT_TRUE),

0 commit comments

Comments
 (0)