Implement ECMAScript 2022 private class methods and fields (#4831)

Co-authored-by: Robert Fancsik robert.fancsik@h-lab.eu
Co-authored-by: Martin Negyokru mnegyokru@inf.u-szeged.hu
JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
Szilagyi Adam
2021-11-26 12:24:59 +01:00
committed by GitHub
parent 841e21a970
commit 70e275e92f
35 changed files with 2196 additions and 4341 deletions
+140 -13
View File
@@ -597,6 +597,9 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (ecma_is_value_object (completion_value))
{
ecma_op_bind_this_value (environment_record_p, completion_value);
frame_ctx_p->this_binding = completion_value;
ecma_value_t fields_value = opfunc_init_class_fields (vm_get_class_function (frame_ctx_p), completion_value);
if (ECMA_IS_VALUE_ERROR (fields_value))
@@ -617,9 +620,6 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}
else
{
ecma_op_bind_this_value (environment_record_p, completion_value);
frame_ctx_p->this_binding = completion_value;
frame_ctx_p->byte_code_p = byte_code_p;
uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode];
@@ -1652,7 +1652,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
JERRY_ASSERT (literal_index >= register_end);
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE
|| (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
&& (frame_ctx_p->lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)));
&& ECMA_LEX_ENV_CLASS_IS_MODULE (frame_ctx_p->lex_env_p)));
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
ecma_property_t *property_p = ecma_find_named_property (frame_ctx_p->lex_env_p, name_p);
@@ -1822,6 +1822,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
memmove (stack_top_p - 3, stack_top_p - 4, 3 * sizeof (ecma_value_t));
stack_top_p[-4] = left_value;
ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]);
ecma_object_t *initializer_func_p = ecma_get_object_from_value (left_value);
opfunc_bind_class_environment (frame_ctx_p->lex_env_p, class_object_p, class_object_p, initializer_func_p);
if (!push_computed)
{
continue;
@@ -1998,6 +2002,100 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = opfunc_create_implicit_class_constructor (opcode, frame_ctx_p->shared_p->bytecode_header_p);
continue;
}
case VM_OC_DEFINE_FIELD:
{
result = opfunc_define_field (frame_ctx_p->this_binding, right_value, left_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
goto free_both_values;
}
case VM_OC_ASSIGN_PRIVATE:
{
result = opfunc_private_set (stack_top_p[-3], stack_top_p[-2], stack_top_p[-1]);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
ecma_free_value (stack_top_p[-3]);
ecma_free_value (stack_top_p[-2]);
ecma_free_value (stack_top_p[-1]);
stack_top_p -= 3;
if (opcode_data & VM_OC_PUT_STACK)
{
*stack_top_p++ = result;
}
else if (opcode_data & VM_OC_PUT_BLOCK)
{
ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0));
VM_GET_REGISTERS (frame_ctx_p)[0] = result;
}
else
{
ecma_free_value (result);
}
goto free_both_values;
}
case VM_OC_PRIVATE_FIELD_ADD:
{
result = opfunc_private_field_add (frame_ctx_p->this_binding, right_value, left_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
goto free_both_values;
}
case VM_OC_PRIVATE_PROP_GET:
{
result = opfunc_private_get (left_value, right_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_PRIVATE_PROP_REFERENCE:
{
result = opfunc_private_get (stack_top_p[-1], left_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
*stack_top_p++ = left_value;
*stack_top_p++ = result;
continue;
}
case VM_OC_PRIVATE_IN:
{
result = opfunc_private_in (left_value, right_value);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_COLLECT_PRIVATE_PROPERTY:
{
opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, opcode);
continue;
}
case VM_OC_INIT_CLASS:
{
result = opfunc_init_class (frame_ctx_p, stack_top_p);
@@ -2025,14 +2123,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
case VM_OC_SET_FIELD_INIT:
{
ecma_string_t *property_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT);
ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[-2]);
ecma_object_t *proto_object_p = ecma_get_object_from_value (stack_top_p[-1]);
ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]);
ecma_object_t *initializer_func_p = ecma_get_object_from_value (left_value);
opfunc_bind_class_environment (frame_ctx_p->lex_env_p, proto_object_p, class_object_p, initializer_func_p);
ecma_property_value_t *property_value_p =
ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_FIXED, NULL);
ecma_create_named_data_property (class_object_p, property_name_p, ECMA_PROPERTY_FIXED, NULL);
property_value_p->value = left_value;
property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED);
ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);
ecma_property_t *property_p = ecma_find_named_property (class_object_p, property_name_p);
if (property_p != NULL)
{
@@ -2074,17 +2176,41 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
ecma_integer_value_t next_index = ecma_get_integer_from_value (stack_top_p[-2]) + 1;
stack_top_p[-2] = ecma_make_integer_value (next_index);
stack_top_p++;
JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS);
ecma_value_t *computed_class_fields_p = VM_GET_COMPUTED_CLASS_FIELDS (frame_ctx_p);
JERRY_ASSERT ((ecma_value_t) next_index < ECMA_COMPACT_COLLECTION_GET_SIZE (computed_class_fields_p));
ecma_value_t prop_name = computed_class_fields_p[next_index];
result = stack_top_p[-2];
stack_top_p[-1] = ecma_copy_value (computed_class_fields_p[next_index]);
stack_top_p[-2] = ecma_copy_value (frame_ctx_p->this_binding);
break;
if (opcode == CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC)
{
ecma_object_t *func_obj_p = ecma_get_object_from_value (result);
JERRY_ASSERT (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) == NULL);
ecma_property_value_t *value_p;
value_p = ecma_create_named_data_property (func_obj_p,
ecma_get_magic_string (LIT_MAGIC_STRING_NAME),
ECMA_PROPERTY_FLAG_CONFIGURABLE,
NULL);
if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
{
ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp);
}
value_p->value = ecma_copy_value (prop_name);
}
result = opfunc_define_field (frame_ctx_p->this_binding, prop_name, stack_top_p[-1]);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
ecma_free_value (*(--stack_top_p));
continue;
}
case VM_OC_PUSH_SUPER_CONSTRUCTOR:
{
@@ -4884,7 +5010,8 @@ vm_init_module_scope (ecma_module_t *module_p) /**< module without scope */
uint16_t encoding_limit;
uint16_t encoding_delta;
((ecma_lexical_environment_class_t *) scope_p)->module_p = (ecma_object_t *) module_p;
((ecma_lexical_environment_class_t *) scope_p)->object_p = (ecma_object_t *) module_p;
((ecma_lexical_environment_class_t *) scope_p)->type = ECMA_LEX_ENV_CLASS_TYPE_MODULE;
module_p->scope_p = scope_p;
ecma_deref_object (scope_p);