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:
+586
-12
@@ -894,6 +894,115 @@ opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context *
|
||||
return result;
|
||||
} /* opfunc_async_create_and_await */
|
||||
|
||||
/**
|
||||
* PrivateMethodOrAccessorAdd abstact operation.
|
||||
*
|
||||
* See also: ECMAScript v12, 7.3.29.
|
||||
*
|
||||
* @return ECMA_VALUE_ERROR - initialization fails
|
||||
* ECMA_VALUE_UNDEFINED - otherwise
|
||||
*/
|
||||
static ecma_value_t
|
||||
opfunc_private_method_or_accessor_add (ecma_object_t *class_object_p, /**< the function itself */
|
||||
ecma_object_t *this_obj_p, /**< this object */
|
||||
uint32_t static_flag)
|
||||
{
|
||||
ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS);
|
||||
ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
|
||||
ecma_value_t *current_p = collection_p + 1;
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (collection_p);
|
||||
|
||||
while (current_p < end_p)
|
||||
{
|
||||
uint32_t prop_desc = *current_p++;
|
||||
ecma_private_property_kind_t kind = ECMA_PRIVATE_PROPERTY_KIND (prop_desc);
|
||||
|
||||
if ((prop_desc & ECMA_PRIVATE_PROPERTY_STATIC_FLAG) != static_flag || kind == ECMA_PRIVATE_FIELD)
|
||||
{
|
||||
current_p += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_get_symbol_from_value (*current_p++);
|
||||
ecma_value_t method = *current_p++;
|
||||
|
||||
JERRY_ASSERT (prop_name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD);
|
||||
|
||||
prop_p = ecma_find_named_property (this_obj_p, prop_name_p);
|
||||
ecma_object_t *method_p = ecma_get_object_from_value (method);
|
||||
|
||||
if (kind == ECMA_PRIVATE_METHOD)
|
||||
{
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE);
|
||||
}
|
||||
|
||||
ecma_property_value_t *prop_value_p =
|
||||
ecma_create_named_data_property (this_obj_p, prop_name_p, ECMA_PROPERTY_FIXED, NULL);
|
||||
prop_value_p->value = method;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
ecma_object_t *getter_p = (kind == ECMA_PRIVATE_GETTER) ? method_p : NULL;
|
||||
ecma_object_t *setter_p = (kind == ECMA_PRIVATE_SETTER) ? method_p : NULL;
|
||||
ecma_create_named_accessor_property (this_obj_p, prop_name_p, getter_p, setter_p, ECMA_PROPERTY_FIXED, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_property_value_t *accessor_objs_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
|
||||
ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p);
|
||||
|
||||
if (kind == ECMA_PRIVATE_GETTER)
|
||||
{
|
||||
ECMA_SET_POINTER (get_set_pair_p->getter_cp, method_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (kind == ECMA_PRIVATE_SETTER);
|
||||
ECMA_SET_POINTER (get_set_pair_p->setter_cp, method_p);
|
||||
}
|
||||
}
|
||||
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
} /* opfunc_private_method_or_accessor_add */
|
||||
|
||||
/**
|
||||
* DefineField abstract operation.
|
||||
*
|
||||
* See also: ECMAScript v12, 7.3.32.
|
||||
*
|
||||
* @return ECMA_VALUE_ERROR - operation fails
|
||||
* ECMA_VALUE_{TRUE/FALSE} - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_define_field (ecma_value_t base, ecma_value_t property, ecma_value_t value)
|
||||
{
|
||||
ecma_string_t *property_key_p = ecma_op_to_property_key (property);
|
||||
|
||||
JERRY_ASSERT (property_key_p != NULL);
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (base);
|
||||
ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor ();
|
||||
desc.value = value;
|
||||
desc.flags = (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE
|
||||
| JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED
|
||||
| JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_SHOULD_THROW);
|
||||
|
||||
ecma_value_t result = ecma_op_object_define_own_property (obj_p, property_key_p, &desc);
|
||||
ecma_deref_ecma_string (property_key_p);
|
||||
|
||||
return result;
|
||||
} /* opfunc_define_field */
|
||||
|
||||
/**
|
||||
* Initialize class fields.
|
||||
*
|
||||
@@ -905,6 +1014,14 @@ opfunc_init_class_fields (ecma_object_t *class_object_p, /**< the function itsel
|
||||
ecma_value_t this_val) /**< this_arg of the function */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_object (this_val));
|
||||
ecma_object_t *this_obj_p = ecma_get_object_from_value (this_val);
|
||||
|
||||
ecma_value_t result = opfunc_private_method_or_accessor_add (class_object_p, this_obj_p, 0);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT);
|
||||
ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p);
|
||||
@@ -938,7 +1055,7 @@ opfunc_init_class_fields (ecma_object_t *class_object_p, /**< the function itsel
|
||||
ecma_object_t *scope_p =
|
||||
ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_function_p->u.function.scope_cp);
|
||||
|
||||
ecma_value_t result = vm_run (&shared_class_fields.header, this_val, scope_p);
|
||||
result = vm_run (&shared_class_fields.header, this_val, scope_p);
|
||||
|
||||
JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED);
|
||||
return result;
|
||||
@@ -1097,6 +1214,407 @@ opfunc_set_home_object (ecma_object_t *func_p, /**< function object */
|
||||
}
|
||||
} /* opfunc_set_home_object */
|
||||
|
||||
/**
|
||||
* Make private key from descriptor
|
||||
*/
|
||||
ecma_string_t *
|
||||
opfunc_make_private_key (ecma_value_t descriptor) /**< descriptor */
|
||||
{
|
||||
ecma_string_t *private_key_p = ecma_new_symbol_from_descriptor_string (descriptor);
|
||||
private_key_p->u.hash |= ECMA_SYMBOL_FLAG_PRIVATE_KEY;
|
||||
|
||||
return (ecma_string_t *) private_key_p;
|
||||
} /* opfunc_make_private_key */
|
||||
|
||||
/**
|
||||
* Find a private property in the private elements internal property given the key
|
||||
*/
|
||||
static ecma_property_t *
|
||||
opfunc_find_private_key (ecma_object_t *class_object_p, /**< class environment */
|
||||
ecma_object_t *obj_p, /**< object */
|
||||
ecma_string_t *search_key_p, /**< key */
|
||||
ecma_string_t **out_private_key_p) /**< [out] private key */
|
||||
{
|
||||
ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS);
|
||||
ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
|
||||
ecma_value_t *current_p = collection_p + 1;
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (collection_p);
|
||||
|
||||
while (current_p < end_p)
|
||||
{
|
||||
current_p++; /* skip kind */
|
||||
ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++);
|
||||
current_p++; /* skip value */
|
||||
|
||||
JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p));
|
||||
|
||||
ecma_string_t *private_key_desc_p =
|
||||
ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor);
|
||||
|
||||
if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p))
|
||||
{
|
||||
prop_p = ecma_find_named_property (obj_p, private_key_p);
|
||||
|
||||
if (out_private_key_p)
|
||||
{
|
||||
*out_private_key_p = private_key_p;
|
||||
}
|
||||
|
||||
return prop_p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* opfunc_find_private_key */
|
||||
|
||||
/**
|
||||
* PrivateElementFind abstact operation
|
||||
*
|
||||
* See also: ECMAScript v12, 7.3.27
|
||||
*
|
||||
* @return - ECMA_VALUE_ERROR - if the operation fails
|
||||
* ECMA_VALUE_EMPTY - otherwise
|
||||
*/
|
||||
static ecma_property_t *
|
||||
opfunc_find_private_element (ecma_object_t *obj_p, /**< object */
|
||||
ecma_string_t *key_p, /**< key */
|
||||
ecma_string_t **private_key_p, /**< [out] private key */
|
||||
bool allow_heritage)
|
||||
{
|
||||
JERRY_ASSERT (private_key_p != NULL);
|
||||
JERRY_ASSERT (*private_key_p == NULL);
|
||||
ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;
|
||||
|
||||
while (true)
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p != NULL);
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) != 0
|
||||
&& !ECMA_LEX_ENV_CLASS_IS_MODULE (lex_env_p))
|
||||
{
|
||||
ecma_object_t *class_object_p = ((ecma_lexical_environment_class_t *) lex_env_p)->object_p;
|
||||
|
||||
ecma_property_t *prop_p = opfunc_find_private_key (class_object_p, obj_p, key_p, private_key_p);
|
||||
|
||||
if (prop_p || *private_key_p != NULL)
|
||||
{
|
||||
/* Found non shadowed property */
|
||||
return prop_p;
|
||||
}
|
||||
|
||||
if (!allow_heritage)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* opfunc_find_private_element */
|
||||
|
||||
/**
|
||||
* In expression runtime evaluation in case of private identifiers
|
||||
*
|
||||
* See also: ECMAScript v12, 13.10.1
|
||||
*
|
||||
* @return - ECMA_VALUE_ERROR - if the operation fails
|
||||
* ECMA_VALUE_TRUE - if the property was found in the base object
|
||||
* ECMA_VALUE_FALSE - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_private_in (ecma_value_t base, ecma_value_t property)
|
||||
{
|
||||
if (!ecma_is_value_object (base))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT);
|
||||
}
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (base);
|
||||
ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (property);
|
||||
ecma_string_t *private_key_p = NULL;
|
||||
|
||||
ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, false);
|
||||
|
||||
return ecma_make_boolean_value (prop_p != NULL);
|
||||
} /* opfunc_private_in */
|
||||
|
||||
/**
|
||||
* PrivateFieldAdd abstact operation
|
||||
*
|
||||
* See also: ECMAScript v12, 7.3.28
|
||||
*
|
||||
* @return - ECMA_VALUE_ERROR - if the operation fails
|
||||
* ECMA_VALUE_EMPTY - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_private_field_add (ecma_value_t base, /**< base object */
|
||||
ecma_value_t property, /**< property name */
|
||||
ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (base);
|
||||
ecma_string_t *prop_name_p = ecma_get_string_from_value (property);
|
||||
ecma_string_t *private_key_p = NULL;
|
||||
|
||||
ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, false);
|
||||
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE);
|
||||
}
|
||||
|
||||
ecma_property_value_t *value_p =
|
||||
ecma_create_named_data_property (obj_p, private_key_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL);
|
||||
|
||||
value_p->value = ecma_copy_value_if_not_object (value);
|
||||
|
||||
return ECMA_VALUE_EMPTY;
|
||||
} /* opfunc_private_field_add */
|
||||
|
||||
/**
|
||||
* PrivateSet abstact operation
|
||||
*
|
||||
* See also: ECMAScript v12, 7.3.31
|
||||
*
|
||||
* @return - ECMA_VALUE_ERROR - if the operation fails
|
||||
* ECMA_VALUE_EMPTY - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_private_set (ecma_value_t base, /**< this object */
|
||||
ecma_value_t property, /**< property name */
|
||||
ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (base);
|
||||
ecma_string_t *prop_name_p = ecma_get_string_from_value (property);
|
||||
ecma_string_t *private_key_p = NULL;
|
||||
|
||||
ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, true);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT);
|
||||
}
|
||||
|
||||
if (*prop_p & ECMA_PROPERTY_FLAG_DATA)
|
||||
{
|
||||
JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p));
|
||||
|
||||
if (private_key_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE);
|
||||
}
|
||||
|
||||
ecma_value_assign_value (&ECMA_PROPERTY_VALUE_PTR (prop_p)->value, value);
|
||||
return ecma_copy_value (value);
|
||||
}
|
||||
|
||||
ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_p));
|
||||
|
||||
if (get_set_pair_p->setter_cp == JMEM_CP_NULL)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER);
|
||||
}
|
||||
|
||||
ecma_object_t *setter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp);
|
||||
|
||||
return ecma_op_function_call (setter_p, base, &value, 1);
|
||||
} /* opfunc_private_set */
|
||||
|
||||
/**
|
||||
* PrivateGet abstact operation
|
||||
*
|
||||
* See also: ECMAScript v12, 7.3.30
|
||||
*
|
||||
* @return - ECMA_VALUE_ERROR - if the operation fails
|
||||
* private property value - otherwise
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_private_get (ecma_value_t base, /**< this object */
|
||||
ecma_value_t property) /**< property name */
|
||||
{
|
||||
ecma_value_t base_obj = ecma_op_to_object (base);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (base_obj))
|
||||
{
|
||||
return base_obj;
|
||||
}
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (base_obj);
|
||||
ecma_string_t *prop_name_p = ecma_get_string_from_value (property);
|
||||
ecma_string_t *private_key_p = NULL;
|
||||
|
||||
ecma_property_t *prop_p = opfunc_find_private_element (obj_p, prop_name_p, &private_key_p, true);
|
||||
|
||||
ecma_value_t result;
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
result = ecma_raise_type_error (ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT);
|
||||
}
|
||||
else if (*prop_p & ECMA_PROPERTY_FLAG_DATA)
|
||||
{
|
||||
result = ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_p));
|
||||
|
||||
if (get_set_pair_p->getter_cp == JMEM_CP_NULL)
|
||||
{
|
||||
result = ecma_raise_type_error (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp);
|
||||
result = ecma_op_function_call (getter_p, base, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_deref_object (obj_p);
|
||||
|
||||
return result;
|
||||
} /* opfunc_private_get */
|
||||
|
||||
/**
|
||||
* Find the private property in the object who's private key descriptor matches the given key
|
||||
*/
|
||||
static ecma_string_t *
|
||||
opfunc_create_private_key (ecma_value_t *collection_p, /**< TODO */
|
||||
ecma_value_t search_key, /**< key */
|
||||
ecma_private_property_kind_t search_kind)
|
||||
{
|
||||
if (search_kind < ECMA_PRIVATE_GETTER)
|
||||
{
|
||||
return opfunc_make_private_key (search_key);
|
||||
}
|
||||
|
||||
ecma_string_t *search_key_p = ecma_get_string_from_value (search_key);
|
||||
|
||||
ecma_value_t *current_p = collection_p + 1;
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (collection_p);
|
||||
|
||||
while (current_p < end_p)
|
||||
{
|
||||
ecma_private_property_kind_t kind = ECMA_PRIVATE_PROPERTY_KIND (*current_p++);
|
||||
ecma_string_t *private_key_p = ecma_get_prop_name_from_value (*current_p++);
|
||||
current_p++; /* skip value */
|
||||
|
||||
if (kind < ECMA_PRIVATE_GETTER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_prop_name_is_symbol (private_key_p));
|
||||
|
||||
ecma_string_t *private_key_desc_p =
|
||||
ecma_get_string_from_value (((ecma_extended_string_t *) private_key_p)->u.symbol_descriptor);
|
||||
|
||||
if (ecma_compare_ecma_strings (private_key_desc_p, search_key_p))
|
||||
{
|
||||
ecma_deref_ecma_string (search_key_p);
|
||||
ecma_ref_ecma_string (private_key_p);
|
||||
return private_key_p;
|
||||
}
|
||||
}
|
||||
|
||||
return opfunc_make_private_key (search_key);
|
||||
} /* opfunc_create_private_key */
|
||||
|
||||
/**
|
||||
* Collect private members for PrivateMethodOrAccessorAdd and PrivateFieldAdd abstract operations
|
||||
*/
|
||||
void
|
||||
opfunc_collect_private_properties (ecma_value_t constructor, ecma_value_t prop_name, ecma_value_t value, uint8_t opcode)
|
||||
{
|
||||
ecma_private_property_kind_t kind = ECMA_PRIVATE_FIELD;
|
||||
bool is_static = false;
|
||||
|
||||
if (opcode >= CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD)
|
||||
{
|
||||
opcode = (uint8_t) (opcode - PARSER_STATIC_PRIVATE_TO_PRIVATE_OFFSET);
|
||||
is_static = true;
|
||||
}
|
||||
|
||||
if (opcode == CBC_EXT_COLLECT_PRIVATE_METHOD)
|
||||
{
|
||||
prop_name ^= value;
|
||||
value ^= prop_name;
|
||||
prop_name ^= value;
|
||||
kind = ECMA_PRIVATE_METHOD;
|
||||
}
|
||||
else if (opcode == CBC_EXT_COLLECT_PRIVATE_GETTER)
|
||||
{
|
||||
kind = ECMA_PRIVATE_GETTER;
|
||||
}
|
||||
else if (opcode == CBC_EXT_COLLECT_PRIVATE_SETTER)
|
||||
{
|
||||
kind = ECMA_PRIVATE_SETTER;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (constructor));
|
||||
JERRY_ASSERT (ecma_is_value_string (prop_name));
|
||||
JERRY_ASSERT (ecma_is_value_object (value) || ecma_is_value_undefined (value));
|
||||
|
||||
ecma_object_t *constructor_p = ecma_get_object_from_value (constructor);
|
||||
ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS);
|
||||
ecma_property_t *prop_p = ecma_find_named_property (constructor_p, internal_string_p);
|
||||
ecma_value_t *collection_p;
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
collection_p = ecma_new_compact_collection ();
|
||||
ECMA_CREATE_INTERNAL_PROPERTY (constructor_p, internal_string_p, prop_p, prop_value_p);
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, collection_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
|
||||
collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, prop_value_p->value);
|
||||
}
|
||||
|
||||
ecma_string_t *key_p = opfunc_create_private_key (collection_p, prop_name, kind);
|
||||
|
||||
if (kind != ECMA_PRIVATE_FIELD)
|
||||
{
|
||||
key_p->u.hash |= ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD;
|
||||
}
|
||||
|
||||
if (is_static)
|
||||
{
|
||||
kind |= ECMA_PRIVATE_PROPERTY_STATIC_FLAG;
|
||||
}
|
||||
|
||||
collection_p = ecma_compact_collection_push_back (collection_p, (ecma_value_t) kind);
|
||||
collection_p = ecma_compact_collection_push_back (collection_p, ecma_make_symbol_value (key_p));
|
||||
collection_p = ecma_compact_collection_push_back (collection_p, value);
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (collection_p);
|
||||
ecma_value_t *current_p = collection_p + 1;
|
||||
|
||||
JERRY_ASSERT ((end_p - current_p) % ECMA_PRIVATE_ELEMENT_LIST_SIZE == 0);
|
||||
#endif /* !defined (JERRY_NDEBUG) */
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (prop_value_p->value, collection_p);
|
||||
|
||||
ecma_free_value (value);
|
||||
} /* opfunc_collect_private_properties */
|
||||
|
||||
/**
|
||||
* ClassDefinitionEvaluation environment initialization part
|
||||
*
|
||||
@@ -1222,18 +1740,13 @@ opfunc_init_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
|
||||
if (ecma_get_object_type (ctor_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
ecma_object_t *proto_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0);
|
||||
ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, proto_p);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp, proto_env_p, 0);
|
||||
opfunc_bind_class_environment (frame_ctx_p->lex_env_p, proto_p, ctor_p, ctor_p);
|
||||
|
||||
/* 15. set F’s [[ConstructorKind]] internal slot to "derived". */
|
||||
if (heritage_present)
|
||||
{
|
||||
ECMA_SET_THIRD_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp);
|
||||
}
|
||||
|
||||
ecma_deref_object (proto_env_p);
|
||||
}
|
||||
|
||||
stack_top_p[-2] = stack_top_p[-1];
|
||||
@@ -1242,6 +1755,34 @@ opfunc_init_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
return ECMA_VALUE_EMPTY;
|
||||
} /* opfunc_init_class */
|
||||
|
||||
/**
|
||||
* Creates a new class lexical environment and binds the bound object and the class's object
|
||||
*
|
||||
* @return newly created class lexical environment - if func_obj_p is not present
|
||||
* NULL - otherwise, also the environment is set as the func_obj_p's scope
|
||||
*/
|
||||
ecma_object_t *
|
||||
opfunc_bind_class_environment (ecma_object_t *lex_env_p, /**< lexical environment */
|
||||
ecma_object_t *home_object_p, /**< bound object */
|
||||
ecma_object_t *ctor_p, /**< constructor object */
|
||||
ecma_object_t *func_obj_p) /**< function object */
|
||||
{
|
||||
ecma_object_t *proto_env_p = ecma_create_lex_env_class (lex_env_p, sizeof (ecma_lexical_environment_class_t));
|
||||
ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, home_object_p);
|
||||
((ecma_lexical_environment_class_t *) proto_env_p)->object_p = ctor_p;
|
||||
((ecma_lexical_environment_class_t *) proto_env_p)->type = ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV;
|
||||
|
||||
if (func_obj_p)
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
|
||||
ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp, proto_env_p, 0);
|
||||
ecma_deref_object (proto_env_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return proto_env_p;
|
||||
} /* opfunc_bind_class_environment */
|
||||
|
||||
/**
|
||||
* Set [[Enumerable]] and [[HomeObject]] attributes for all class method
|
||||
*/
|
||||
@@ -1277,7 +1818,7 @@ opfunc_set_class_attributes (ecma_object_t *obj_p, /**< object */
|
||||
{
|
||||
JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_DELETED
|
||||
|| (ECMA_PROPERTY_IS_INTERNAL (property)
|
||||
&& property_pair_p->names_cp[index] == LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED));
|
||||
&& LIT_INTERNAL_MAGIC_STRING_IGNORED (property_pair_p->names_cp[index])));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1311,6 +1852,37 @@ opfunc_set_class_attributes (ecma_object_t *obj_p, /**< object */
|
||||
}
|
||||
} /* opfunc_set_class_attributes */
|
||||
|
||||
/**
|
||||
* Set [[HomeObject]] attributes for all class private elements
|
||||
*/
|
||||
static void
|
||||
opfunc_set_private_instance_method_attributes (ecma_object_t *class_object_p, /**< class constructor */
|
||||
ecma_object_t *parent_env_p) /**< parent environment */
|
||||
{
|
||||
ecma_string_t *internal_string_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS);
|
||||
ecma_property_t *prop_p = ecma_find_named_property (class_object_p, internal_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_value_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
|
||||
ecma_value_t *current_p = collection_p + 1;
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (collection_p);
|
||||
|
||||
while (current_p < end_p)
|
||||
{
|
||||
current_p += 2; /* skip kind, name */
|
||||
ecma_value_t value = *current_p++;
|
||||
|
||||
if (!ecma_is_value_undefined (value))
|
||||
{
|
||||
opfunc_set_home_object (ecma_get_object_from_value (value), parent_env_p);
|
||||
}
|
||||
}
|
||||
} /* opfunc_set_private_instance_method_attributes */
|
||||
|
||||
/**
|
||||
* Pop the current lexical environment referenced by the frame context
|
||||
*/
|
||||
@@ -1346,13 +1918,12 @@ opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
ecma_op_initialize_binding (class_env_p, ecma_get_string_from_value (class_name), stack_top_p[-2]);
|
||||
}
|
||||
|
||||
ecma_object_t *ctor_env_p = ecma_create_lex_env_class (class_env_p, 0);
|
||||
ECMA_SET_NON_NULL_POINTER (ctor_env_p->u1.bound_object_cp, ctor_p);
|
||||
ecma_object_t *proto_env_p = ecma_create_lex_env_class (class_env_p, 0);
|
||||
ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, proto_p);
|
||||
ecma_object_t *ctor_env_p = opfunc_bind_class_environment (class_env_p, ctor_p, ctor_p, NULL);
|
||||
ecma_object_t *proto_env_p = opfunc_bind_class_environment (class_env_p, proto_p, ctor_p, NULL);
|
||||
|
||||
opfunc_set_class_attributes (ctor_p, ctor_env_p);
|
||||
opfunc_set_class_attributes (proto_p, proto_env_p);
|
||||
opfunc_set_private_instance_method_attributes (ctor_p, proto_env_p);
|
||||
|
||||
ecma_deref_object (proto_env_p);
|
||||
ecma_deref_object (ctor_env_p);
|
||||
@@ -1367,6 +1938,9 @@ opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
opfunc_pop_lexical_environment (frame_ctx_p);
|
||||
}
|
||||
|
||||
ecma_value_t result = opfunc_private_method_or_accessor_add (ctor_p, ctor_p, ECMA_PRIVATE_PROPERTY_STATIC_FLAG);
|
||||
JERRY_ASSERT (ecma_is_value_undefined (result));
|
||||
|
||||
stack_top_p[-3] = stack_top_p[-2];
|
||||
*vm_stack_top_p -= 2;
|
||||
} /* opfunc_finalize_class */
|
||||
|
||||
@@ -132,10 +132,32 @@ ecma_value_t opfunc_create_implicit_class_constructor (uint8_t opcode, const ecm
|
||||
|
||||
void opfunc_set_home_object (ecma_object_t *func_p, ecma_object_t *parent_env_p);
|
||||
|
||||
ecma_value_t opfunc_define_field (ecma_value_t base, ecma_value_t property, ecma_value_t value);
|
||||
|
||||
ecma_string_t *opfunc_make_private_key (ecma_value_t descriptor);
|
||||
|
||||
ecma_value_t opfunc_private_in (ecma_value_t base, ecma_value_t property);
|
||||
|
||||
ecma_value_t opfunc_private_field_add (ecma_value_t base, ecma_value_t property, ecma_value_t value);
|
||||
|
||||
ecma_value_t opfunc_private_set (ecma_value_t base, ecma_value_t property, ecma_value_t value);
|
||||
|
||||
ecma_value_t opfunc_private_get (ecma_value_t base, ecma_value_t property);
|
||||
|
||||
void opfunc_collect_private_properties (ecma_value_t constructor,
|
||||
ecma_value_t prop_name,
|
||||
ecma_value_t method,
|
||||
uint8_t opcode);
|
||||
|
||||
void opfunc_push_class_environment (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top, ecma_value_t class_name);
|
||||
|
||||
ecma_value_t opfunc_init_class (vm_frame_ctx_t *frame_context_p, ecma_value_t *stack_top_p);
|
||||
|
||||
ecma_object_t *opfunc_bind_class_environment (ecma_object_t *lex_env_p,
|
||||
ecma_object_t *home_object_p,
|
||||
ecma_object_t *ctor_p,
|
||||
ecma_object_t *func_obj_p);
|
||||
|
||||
void opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p);
|
||||
|
||||
void opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_p, ecma_value_t class_name);
|
||||
|
||||
+140
-13
@@ -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);
|
||||
|
||||
@@ -237,6 +237,13 @@ typedef enum
|
||||
VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
#if JERRY_ESNEXT
|
||||
VM_OC_DEFINE_FIELD, /**< define class field */
|
||||
VM_OC_PRIVATE_PROP_REFERENCE, /**< reference to class private method */
|
||||
VM_OC_ASSIGN_PRIVATE, /**< assign to private field */
|
||||
VM_OC_PRIVATE_FIELD_ADD, /**< add private field */
|
||||
VM_OC_PRIVATE_PROP_GET, /**< get private field */
|
||||
VM_OC_PRIVATE_IN, /**< 'in' opcode handler for private identifiers */
|
||||
VM_OC_COLLECT_PRIVATE_PROPERTY, /**< collect private properties */
|
||||
VM_OC_CHECK_VAR, /**< check redeclared vars in the global scope */
|
||||
VM_OC_CHECK_LET, /**< check redeclared lets in the global scope */
|
||||
VM_OC_ASSIGN_LET_CONST, /**< assign values to let/const declarations */
|
||||
@@ -324,6 +331,13 @@ typedef enum
|
||||
VM_OC_BREAKPOINT_DISABLED = VM_OC_NONE, /**< disabled breakpoint for debugger is unused */
|
||||
#endif /* !JERRY_DEBUGGER */
|
||||
#if !JERRY_ESNEXT
|
||||
VM_OC_DEFINE_FIELD = VM_OC_NONE, /**< define class field */
|
||||
VM_OC_PRIVATE_PROP_REFERENCE = VM_OC_NONE, /* reference to class private method */
|
||||
VM_OC_ASSIGN_PRIVATE = VM_OC_NONE, /**< assign to private field */
|
||||
VM_OC_PRIVATE_FIELD_ADD = VM_OC_NONE, /**< add private field */
|
||||
VM_OC_PRIVATE_PROP_GET = VM_OC_NONE, /**< get private field */
|
||||
VM_OC_PRIVATE_IN = VM_OC_NONE, /**< 'in' opcode handler for private identifiers */
|
||||
VM_OC_COLLECT_PRIVATE_PROPERTY = VM_OC_NONE, /**< collect private properties */
|
||||
VM_OC_EXT_VAR_EVAL = VM_OC_NONE, /**< variable and function evaluation for
|
||||
* functions with separate argument context */
|
||||
VM_OC_CHECK_VAR = VM_OC_NONE, /**< check redeclared vars in the global scope */
|
||||
|
||||
Reference in New Issue
Block a user