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:
@@ -298,6 +298,9 @@ ECMA_ERROR_DEF (ECMA_ERR_MODULE_MUST_BE_IN_LINKED_STATE, "Module must be in link
|
||||
ECMA_ERROR_DEF (ECMA_ERR_UNKNOWN_EXPORT, "Native module export not found")
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PASSED_ARGUMENT_IS_NOT_A_REALM, "Passed argument is not a realm")
|
||||
#if JERRY_ESNEXT
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE, "Private method is not writable")
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_BIGINT || JERRY_BUILTIN_NUMBER
|
||||
ECMA_ERROR_DEF (ECMA_ERR_RADIX_IS_OUT_OF_RANGE, "Radix must be between 2 and 36")
|
||||
#endif /* JERRY_BUILTIN_BIGINT \
|
||||
@@ -548,6 +551,9 @@ ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT, "Value received
|
||||
#if JERRY_BUILTIN_BOOLEAN
|
||||
ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_BOOLEAN_OBJECT, "Argument 'this' is not a Boolean object")
|
||||
#endif /* JERRY_BUILTIN_BOOLEAN */
|
||||
#if JERRY_ESNEXT
|
||||
ECMA_ERROR_DEF (ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE, "Cannot declare same private field twice")
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_FLOAT32_ARRAY_REQUIRES_NEW, "Constructor Float32Array requires 'new'")
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
@@ -608,6 +614,8 @@ ECMA_ERROR_DEF (ECMA_ERR_CANNOT_CONVERT_TO_OBJECT, "Cannot convert undefined or
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PRECISION_DIGITS_MUST_BE_BETWEEN_IN_RANGE, "Precision digits must be between 1 and 100")
|
||||
#endif /* JERRY_BUILTIN_NUMBER */
|
||||
#if JERRY_ESNEXT
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER, "Private field was defined without a getter")
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER, "Private field was defined without a setter")
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PROPERTY_NAME_IS_NEITHER_SYMBOL_NOR_STRING, "Property name is neither Symbol nor string")
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_BIGINT
|
||||
@@ -818,8 +826,20 @@ ECMA_ERROR_DEF (ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED,
|
||||
"Target object is non-extensible and trap returned different prototype")
|
||||
ECMA_ERROR_DEF (ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET,
|
||||
"Trap returned truish for adding property to the non-extensible target")
|
||||
#endif /* JERRY_BUILTIN_PROXY */
|
||||
#if JERRY_ESNEXT
|
||||
ECMA_ERROR_DEF (ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT,
|
||||
"Cannot read private member to an object whose class did not declare it")
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_PROXY
|
||||
ECMA_ERROR_DEF (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE,
|
||||
"Given property is a non-configurable data property on the proxy target")
|
||||
#endif /* JERRY_BUILTIN_PROXY */
|
||||
#if JERRY_ESNEXT
|
||||
ECMA_ERROR_DEF (ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT,
|
||||
"Cannot write private member to an object whose class did not declare it")
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_PROXY
|
||||
ECMA_ERROR_DEF (ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE,
|
||||
"Trap returned falsish for property but the proxy target is not extensible")
|
||||
ECMA_ERROR_DEF (ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER,
|
||||
|
||||
@@ -323,4 +323,10 @@ ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR = "Proxy target is not a constructor"
|
||||
ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED = "Maximum call stack size exceeded"
|
||||
ECMA_ERR_INVALID_SNAPSHOT_FORMAT = "Invalid snapshot format"
|
||||
ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES = "Invalid snapshot version or unsupported features present"
|
||||
ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT = "Receiver must be an object"
|
||||
ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT = "Receiver must be an object"
|
||||
ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE = "Cannot declare same private field twice"
|
||||
ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot write private member to an object whose class did not declare it"
|
||||
ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE = "Private method is not writable"
|
||||
ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_SETTER = "Private field was defined without a setter"
|
||||
ECMA_ERR_CANNOT_READ_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot read private member to an object whose class did not declare it"
|
||||
ECMA_ERR_PRIVATE_FIELD_WAS_DEFINED_WITHOUT_A_GETTER = "Private field was defined without a getter"
|
||||
|
||||
@@ -328,6 +328,27 @@ ecma_gc_mark_properties (ecma_object_t *object_p, /**< object */
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (environment_record_p->function_object));
|
||||
break;
|
||||
}
|
||||
case LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS:
|
||||
{
|
||||
ecma_value_t *compact_collection_p;
|
||||
compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, property_pair_p->values[index].value);
|
||||
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (compact_collection_p);
|
||||
ecma_value_t *current_p = compact_collection_p + 1;
|
||||
|
||||
while (end_p - current_p >= ECMA_PRIVATE_ELEMENT_LIST_SIZE)
|
||||
{
|
||||
current_p++; /* skip the type */
|
||||
current_p++; /* skip the name */
|
||||
ecma_value_t value = *current_p++;
|
||||
|
||||
if (!ecma_is_value_undefined (value))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (value));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_CONTAINER
|
||||
case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS:
|
||||
@@ -816,8 +837,12 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)
|
||||
{
|
||||
ecma_gc_mark_properties (object_p, true);
|
||||
ecma_gc_set_object_visited (((ecma_lexical_environment_class_t *) object_p)->module_p);
|
||||
if (ECMA_LEX_ENV_CLASS_IS_MODULE (object_p))
|
||||
{
|
||||
ecma_gc_mark_properties (object_p, true);
|
||||
}
|
||||
|
||||
ecma_gc_set_object_visited (((ecma_lexical_environment_class_t *) object_p)->object_p);
|
||||
return;
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
@@ -1591,6 +1616,26 @@ ecma_gc_free_property (ecma_object_t *object_p, /**< object */
|
||||
ecma_compact_collection_free (compact_collection_p);
|
||||
break;
|
||||
}
|
||||
case LIT_INTERNAL_MAGIC_STRING_CLASS_PRIVATE_ELEMENTS:
|
||||
{
|
||||
ecma_value_t *compact_collection_p;
|
||||
compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value);
|
||||
|
||||
ecma_value_t *end_p = ecma_compact_collection_end (compact_collection_p);
|
||||
ecma_value_t *current_p = compact_collection_p + 1;
|
||||
|
||||
JERRY_ASSERT ((end_p - current_p) % ECMA_PRIVATE_ELEMENT_LIST_SIZE == 0);
|
||||
|
||||
while (current_p < end_p)
|
||||
{
|
||||
current_p++; /* skip the type */
|
||||
ecma_deref_ecma_string (ecma_get_prop_name_from_value (*current_p++));
|
||||
current_p++; /* skip the value */
|
||||
}
|
||||
|
||||
ecma_compact_collection_destroy (compact_collection_p);
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER
|
||||
case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS:
|
||||
@@ -1684,7 +1729,11 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA))
|
||||
{
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES);
|
||||
if (ECMA_LEX_ENV_CLASS_IS_MODULE (object_p))
|
||||
{
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES);
|
||||
}
|
||||
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_lexical_environment_class_t));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1184,16 +1184,32 @@ typedef struct
|
||||
ecma_built_in_props_t built_in; /**< built-in object part */
|
||||
} ecma_extended_built_in_object_t;
|
||||
|
||||
/**
|
||||
* Type of lexical environment with class
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_LEX_ENV_CLASS_TYPE_MODULE, /**< module object reference */
|
||||
ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV, /**< class constructor object reference */
|
||||
} ecma_lexical_environment_class_type_t;
|
||||
|
||||
/**
|
||||
* Description of lexical environment with class
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_object_t lexical_env; /**< lexical environment header */
|
||||
|
||||
ecma_object_t *module_p; /**< module reference */
|
||||
uint32_t type; /**< element of ecma_lexical_environment_class_type_t */
|
||||
ecma_object_t *object_p; /**< object reference */
|
||||
} ecma_lexical_environment_class_t;
|
||||
|
||||
/**
|
||||
* Check whether the given lexical class environment is a module
|
||||
*/
|
||||
#define ECMA_LEX_ENV_CLASS_IS_MODULE(lex_env_p) \
|
||||
(((lex_env_p)->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) \
|
||||
&& ((ecma_lexical_environment_class_t *) (lex_env_p))->type == ECMA_LEX_ENV_CLASS_TYPE_MODULE)
|
||||
|
||||
/**
|
||||
* Description of native functions
|
||||
*/
|
||||
@@ -1892,6 +1908,13 @@ typedef struct
|
||||
} u;
|
||||
} ecma_extended_string_t;
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
/**
|
||||
* Required number of ecma values in a compact collection to represent PrivateElement
|
||||
*/
|
||||
#define ECMA_PRIVATE_ELEMENT_LIST_SIZE 3
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
/**
|
||||
* String builder header
|
||||
*/
|
||||
@@ -2248,24 +2271,23 @@ typedef struct
|
||||
} ecma_dataview_object_t;
|
||||
#endif /* JERRY_BUILTIN_DATAVIEW */
|
||||
|
||||
/**
|
||||
* Flag for indicating whether the symbol is a well known symbol
|
||||
*
|
||||
* See also: 6.1.5.1
|
||||
*/
|
||||
#define ECMA_GLOBAL_SYMBOL_FLAG 0x01
|
||||
|
||||
/**
|
||||
* Bitshift index for indicating whether the symbol is a well known symbol
|
||||
*
|
||||
* See also: 6.1.5.1
|
||||
*/
|
||||
#define ECMA_GLOBAL_SYMBOL_SHIFT 1
|
||||
typedef enum
|
||||
{
|
||||
ECMA_SYMBOL_FLAG_NONE = 0, /**< no options */
|
||||
ECMA_SYMBOL_FLAG_GLOBAL = (1 << 0), /**< symbol is a well known symbol, See also: 6.1.5.1 */
|
||||
ECMA_SYMBOL_FLAG_PRIVATE_KEY = (1 << 1), /**< symbol is a private field */
|
||||
ECMA_SYMBOL_FLAG_PRIVATE_INSTANCE_METHOD = (1 << 2), /**< symbol is a private method or accessor */
|
||||
} ecma_symbol_flags_t;
|
||||
|
||||
/**
|
||||
* Bitshift index for the symbol hash property
|
||||
*/
|
||||
#define ECMA_SYMBOL_HASH_SHIFT 2
|
||||
#define ECMA_SYMBOL_FLAGS_SHIFT 3
|
||||
|
||||
/**
|
||||
* Bitmask for symbol hash flags
|
||||
*/
|
||||
#define ECMA_SYMBOL_FLAGS_MASK ((1 << ECMA_SYMBOL_FLAGS_SHIFT) - 1)
|
||||
|
||||
#if (JERRY_STACK_LIMIT != 0)
|
||||
/**
|
||||
@@ -2481,6 +2503,28 @@ typedef struct
|
||||
ecma_extended_object_t header; /**< header part */
|
||||
ecma_value_t sync_next_method; /**< IteratorRecord [[NextMethod]] internal slot */
|
||||
} ecma_async_from_sync_iterator_object_t;
|
||||
|
||||
/**
|
||||
* Private method kind
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_PRIVATE_FIELD = 0, /**< private field */
|
||||
ECMA_PRIVATE_METHOD, /**< private method */
|
||||
ECMA_PRIVATE_GETTER, /**< private setter */
|
||||
ECMA_PRIVATE_SETTER, /**< private getter */
|
||||
} ecma_private_property_kind_t;
|
||||
|
||||
/**
|
||||
* Private static property flag
|
||||
*/
|
||||
#define ECMA_PRIVATE_PROPERTY_STATIC_FLAG (1 << 2)
|
||||
|
||||
/*
|
||||
* Get private property kind from a descriptor
|
||||
*/
|
||||
#define ECMA_PRIVATE_PROPERTY_KIND(prop) ((prop) & ((ECMA_PRIVATE_PROPERTY_STATIC_FLAG - 1)))
|
||||
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
/**
|
||||
|
||||
@@ -417,6 +417,31 @@ ecma_compact_collection_free (ecma_value_t *compact_collection_p) /**< compact c
|
||||
jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t));
|
||||
} /* ecma_compact_collection_free */
|
||||
|
||||
/**
|
||||
* Get the end of a compact collection
|
||||
*
|
||||
* @return pointer to the compact collection end
|
||||
*/
|
||||
ecma_value_t *
|
||||
ecma_compact_collection_end (ecma_value_t *compact_collection_p) /**< compact collection */
|
||||
{
|
||||
ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p);
|
||||
ecma_value_t unused_items = ECMA_COMPACT_COLLECTION_GET_UNUSED_ITEM_COUNT (compact_collection_p);
|
||||
|
||||
return compact_collection_p + size - unused_items;
|
||||
} /* ecma_compact_collection_end */
|
||||
|
||||
/**
|
||||
* Destroy a compact collection
|
||||
*/
|
||||
void
|
||||
ecma_compact_collection_destroy (ecma_value_t *compact_collection_p) /**< compact collection */
|
||||
{
|
||||
ecma_value_t size = ECMA_COMPACT_COLLECTION_GET_SIZE (compact_collection_p);
|
||||
|
||||
jmem_heap_free_block (compact_collection_p, size * sizeof (ecma_value_t));
|
||||
} /* ecma_compact_collection_destroy */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -221,8 +221,7 @@ ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc) /**< ecma-stri
|
||||
ecma_extended_string_t *symbol_p = ecma_alloc_extended_string ();
|
||||
symbol_p->header.refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_SYMBOL;
|
||||
symbol_p->u.symbol_descriptor = string_desc;
|
||||
symbol_p->header.u.hash = (lit_string_hash_t) (((uintptr_t) symbol_p) >> ECMA_SYMBOL_HASH_SHIFT);
|
||||
JERRY_ASSERT ((symbol_p->header.u.hash & ECMA_GLOBAL_SYMBOL_FLAG) == 0);
|
||||
symbol_p->header.u.hash = (lit_string_hash_t) (((uintptr_t) symbol_p) & (uintptr_t) ~ECMA_SYMBOL_FLAGS_MASK);
|
||||
|
||||
return (ecma_string_t *) symbol_p;
|
||||
} /* ecma_new_symbol_from_descriptor_string */
|
||||
|
||||
@@ -306,7 +306,7 @@ ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-boun
|
||||
#if JERRY_ESNEXT
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
|
||||
|| (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) == 0));
|
||||
&& !ECMA_LEX_ENV_CLASS_IS_MODULE (object_p)));
|
||||
#else /* !JERRY_ESNEXT */
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
#endif /* JERRY_ESNEXT */
|
||||
@@ -593,7 +593,7 @@ ecma_create_named_reference_property (ecma_object_t *object_p, /**< object */
|
||||
JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
|
||||
JERRY_ASSERT ((ecma_is_lexical_environment (object_p)
|
||||
&& ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA))
|
||||
&& ECMA_LEX_ENV_CLASS_IS_MODULE (object_p))
|
||||
|| ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE));
|
||||
|
||||
uint8_t type_and_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE;
|
||||
|
||||
@@ -434,6 +434,8 @@ ecma_value_t *ecma_new_compact_collection (void);
|
||||
ecma_value_t *ecma_compact_collection_push_back (ecma_value_t *compact_collection_p, ecma_value_t value);
|
||||
ecma_value_t *ecma_compact_collection_shrink (ecma_value_t *compact_collection_p);
|
||||
void ecma_compact_collection_free (ecma_value_t *compact_collection_p);
|
||||
ecma_value_t *ecma_compact_collection_end (ecma_value_t *compact_collection_p);
|
||||
void ecma_compact_collection_destroy (ecma_value_t *compact_collection_p);
|
||||
|
||||
/* ecma-helpers.c */
|
||||
ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type);
|
||||
|
||||
Reference in New Issue
Block a user