Implement the Symbol builtin object (#2601)
This patch contains the base functionalities that the new builtin object requires.
Currently unavailable:
- print (Symbol('foo')) - this features requires the refactor of the print handler function
- Several global symbol based builtin routines (follow up patch)
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
committed by
Robert Sipka
parent
08c7183ef8
commit
7e3d688e5b
@@ -125,6 +125,13 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
if (ecma_is_value_symbol (x))
|
||||
{
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
if (ecma_is_value_boolean (y))
|
||||
{
|
||||
if (ecma_is_value_boolean (x))
|
||||
@@ -141,6 +148,9 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */
|
||||
if (ecma_is_value_object (x))
|
||||
{
|
||||
if (ecma_is_value_string (y)
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
|| ecma_is_value_symbol (y)
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|| ecma_is_value_number (y))
|
||||
{
|
||||
/* 9. */
|
||||
@@ -195,6 +205,10 @@ ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */
|
||||
{
|
||||
if (ecma_is_value_direct (x)
|
||||
|| ecma_is_value_direct (y)
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
|| ecma_is_value_symbol (x)
|
||||
|| ecma_is_value_symbol (y)
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|| ecma_is_value_object (x)
|
||||
|| ecma_is_value_object (y))
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "ecma-string-object.h"
|
||||
#include "ecma-symbol-object.h"
|
||||
#include "ecma-try-catch-macro.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
|
||||
@@ -224,7 +225,7 @@ ecma_op_to_boolean (ecma_value_t value) /**< ecma value */
|
||||
return !ecma_string_is_empty (str_p);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (value));
|
||||
JERRY_ASSERT (ecma_is_value_object (value) || ECMA_ASSERT_VALUE_IS_SYMBOL (value));
|
||||
|
||||
return true;
|
||||
} /* ecma_op_to_boolean */
|
||||
@@ -258,6 +259,12 @@ ecma_op_to_number (ecma_value_t value) /**< ecma value */
|
||||
ecma_string_t *str_p = ecma_get_string_from_value (value);
|
||||
return ecma_make_number_value (ecma_string_to_number (str_p));
|
||||
}
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number."));
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
if (ecma_is_value_object (value))
|
||||
{
|
||||
@@ -359,6 +366,85 @@ ecma_get_number (ecma_value_t value, /**< ecma value*/
|
||||
return ECMA_VALUE_EMPTY;
|
||||
} /* ecma_get_number */
|
||||
|
||||
/**
|
||||
* ToString operation helper function.
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 9.8
|
||||
*
|
||||
* @return NULL - if the conversion fails
|
||||
* ecma-string - otherwise
|
||||
*/
|
||||
static ecma_string_t *
|
||||
ecma_to_op_string_helper (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
ecma_check_value_type_is_spec_defined (value);
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_is_value_object (value)))
|
||||
{
|
||||
ecma_value_t prim_value = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (prim_value))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_string_t *ret_string_p = ecma_to_op_string_helper (prim_value);
|
||||
|
||||
ecma_free_value (prim_value);
|
||||
|
||||
return ret_string_p;
|
||||
}
|
||||
|
||||
if (ecma_is_value_string (value))
|
||||
{
|
||||
ecma_string_t *res_p = ecma_get_string_from_value (value);
|
||||
ecma_ref_ecma_string (res_p);
|
||||
return res_p;
|
||||
}
|
||||
else if (ecma_is_value_integer_number (value))
|
||||
{
|
||||
ecma_integer_value_t num = ecma_get_integer_from_value (value);
|
||||
|
||||
if (num < 0)
|
||||
{
|
||||
return ecma_new_ecma_string_from_number ((ecma_number_t) num);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ecma_new_ecma_string_from_uint32 ((uint32_t) num);
|
||||
}
|
||||
}
|
||||
else if (ecma_is_value_float_number (value))
|
||||
{
|
||||
ecma_number_t num = ecma_get_float_from_value (value);
|
||||
return ecma_new_ecma_string_from_number (num);
|
||||
}
|
||||
else if (ecma_is_value_undefined (value))
|
||||
{
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED);
|
||||
}
|
||||
else if (ecma_is_value_null (value))
|
||||
{
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
|
||||
}
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
else if (ecma_is_value_symbol (value))
|
||||
{
|
||||
ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a string."));
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
JERRY_ASSERT (ecma_is_value_boolean (value));
|
||||
|
||||
if (ecma_is_value_true (value))
|
||||
{
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_TRUE);
|
||||
}
|
||||
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_FALSE);
|
||||
} /* ecma_to_op_string_helper */
|
||||
|
||||
/**
|
||||
* ToString operation.
|
||||
*
|
||||
@@ -373,73 +459,40 @@ ecma_op_to_string (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
ecma_check_value_type_is_spec_defined (value);
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_is_value_object (value)))
|
||||
ecma_string_t *string_p = ecma_to_op_string_helper (value);
|
||||
|
||||
if (JERRY_UNLIKELY (string_p == NULL))
|
||||
{
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
ECMA_TRY_CATCH (prim_value,
|
||||
ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING),
|
||||
ret_value);
|
||||
|
||||
ret_value = ecma_op_to_string (prim_value);
|
||||
|
||||
ECMA_FINALIZE (prim_value);
|
||||
|
||||
return ret_value;
|
||||
/* Note: At this point the error has already been thrown. */
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_string_t *res_p = NULL;
|
||||
|
||||
if (ecma_is_value_string (value))
|
||||
{
|
||||
res_p = ecma_get_string_from_value (value);
|
||||
ecma_ref_ecma_string (res_p);
|
||||
}
|
||||
else if (ecma_is_value_integer_number (value))
|
||||
{
|
||||
ecma_integer_value_t num = ecma_get_integer_from_value (value);
|
||||
|
||||
if (num < 0)
|
||||
{
|
||||
res_p = ecma_new_ecma_string_from_number ((ecma_number_t) num);
|
||||
}
|
||||
else
|
||||
{
|
||||
res_p = ecma_new_ecma_string_from_uint32 ((uint32_t) num);
|
||||
}
|
||||
}
|
||||
else if (ecma_is_value_float_number (value))
|
||||
{
|
||||
ecma_number_t num = ecma_get_float_from_value (value);
|
||||
res_p = ecma_new_ecma_string_from_number (num);
|
||||
}
|
||||
else if (ecma_is_value_undefined (value))
|
||||
{
|
||||
res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED);
|
||||
}
|
||||
else if (ecma_is_value_null (value))
|
||||
{
|
||||
res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (value));
|
||||
|
||||
if (ecma_is_value_true (value))
|
||||
{
|
||||
res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_make_string_value (res_p);
|
||||
}
|
||||
return ecma_make_string_value (string_p);
|
||||
} /* ecma_op_to_string */
|
||||
|
||||
/**
|
||||
* ToPropertyName operation.
|
||||
*
|
||||
* @return NULL - if the conversion fails
|
||||
* ecma-string - otherwise
|
||||
*/
|
||||
ecma_string_t *
|
||||
ecma_op_to_prop_name (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
ecma_check_value_type_is_spec_defined (value);
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
ecma_string_t *symbol_p = ecma_get_symbol_from_value (value);
|
||||
ecma_ref_ecma_string (symbol_p);
|
||||
return symbol_p;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
return ecma_to_op_string_helper (value);
|
||||
} /* ecma_op_to_prop_name */
|
||||
|
||||
/**
|
||||
* ToObject operation.
|
||||
*
|
||||
@@ -466,6 +519,12 @@ ecma_op_to_object (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return ecma_copy_value (value);
|
||||
}
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
else if (ecma_is_value_symbol (value))
|
||||
{
|
||||
return ecma_op_create_symbol_object (value);
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
else
|
||||
{
|
||||
if (ecma_is_value_undefined (value)
|
||||
|
||||
@@ -44,6 +44,7 @@ bool ecma_op_to_boolean (ecma_value_t value);
|
||||
ecma_value_t ecma_op_to_number (ecma_value_t value);
|
||||
ecma_value_t ecma_get_number (ecma_value_t value, ecma_number_t *number_p);
|
||||
ecma_value_t ecma_op_to_string (ecma_value_t value);
|
||||
ecma_string_t *ecma_op_to_prop_name (ecma_value_t value);
|
||||
ecma_value_t ecma_op_to_object (ecma_value_t value);
|
||||
|
||||
ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p);
|
||||
|
||||
@@ -96,6 +96,7 @@ ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (base_value)
|
||||
|| ecma_is_value_number (base_value)
|
||||
|| ECMA_ASSERT_VALUE_IS_SYMBOL (base_value)
|
||||
|| ecma_is_value_string (base_value));
|
||||
|
||||
ecma_value_t object_base = ecma_op_to_object (base_value);
|
||||
|
||||
@@ -1350,6 +1350,9 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
const bool is_enumerable_only = (const bool) (opts & ECMA_LIST_ENUMERABLE);
|
||||
const bool is_array_indices_only = (const bool) (opts & ECMA_LIST_ARRAY_INDICES);
|
||||
const bool is_with_prototype_chain = (const bool) (opts & ECMA_LIST_PROTOTYPE);
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
const bool is_symbols_only = (const bool) (opts & ECMA_LIST_SYMBOLS);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE;
|
||||
const size_t names_hashes_bitmap_size = ECMA_OBJECT_HASH_BITMAP_SIZE / bitmap_row_size;
|
||||
@@ -1367,82 +1370,90 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
ecma_collection_header_t *prop_names_p = ecma_new_values_collection ();
|
||||
|
||||
if (obj_is_builtin)
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
if (JERRY_LIKELY (!is_symbols_only))
|
||||
{
|
||||
ecma_builtin_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
if (obj_is_builtin)
|
||||
{
|
||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||
ecma_builtin_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
if (ecma_is_typedarray (ecma_make_object_value (obj_p)))
|
||||
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
|
||||
{
|
||||
ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p);
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
if (ecma_is_typedarray (ecma_make_object_value (obj_p)))
|
||||
{
|
||||
ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p);
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
break;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
|
||||
case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
{
|
||||
ecma_op_function_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
|
||||
{
|
||||
ecma_op_external_function_list_lazy_property_names (is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
ecma_op_bound_function_list_lazy_property_names (is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_CLASS:
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
|
||||
case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
{
|
||||
ecma_op_string_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
ecma_op_function_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
|
||||
{
|
||||
ecma_op_external_function_list_lazy_property_names (is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
ecma_op_bound_function_list_lazy_property_names (is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_CLASS:
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_ARRAY:
|
||||
{
|
||||
ecma_op_array_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL);
|
||||
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL)
|
||||
{
|
||||
ecma_op_string_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_ARRAY:
|
||||
{
|
||||
ecma_op_array_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
ecma_value_t *ecma_value_p = ecma_collection_iterator_init (prop_names_p);
|
||||
|
||||
@@ -1453,6 +1464,12 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
while (ecma_value_p != NULL)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p);
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
/* Symbols are never lazy listed */
|
||||
JERRY_ASSERT (!ecma_prop_name_is_symbol (name_p));
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
|
||||
|
||||
uint8_t hash = (uint8_t) ecma_string_hash (name_p);
|
||||
@@ -1498,6 +1515,19 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p)))
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
/* If is_symbols_only is false and prop_name is symbol
|
||||
we should skip the current property e.g. for-in.
|
||||
|
||||
Also if is_symbols_only is true and prop_name is not symbol
|
||||
we should skip the current property e.g. Object.getOwnPropertySymbols. */
|
||||
if (JERRY_UNLIKELY (is_symbols_only != ecma_prop_name_is_symbol (name_p)))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
continue;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
uint8_t hash = (uint8_t) ecma_string_hash (name_p);
|
||||
uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
|
||||
uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size);
|
||||
@@ -1510,7 +1540,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
while (ecma_value_p != NULL)
|
||||
{
|
||||
ecma_string_t *current_name_p = ecma_get_string_from_value (*ecma_value_p);
|
||||
ecma_string_t *current_name_p = ecma_get_prop_name_from_value (*ecma_value_p);
|
||||
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, current_name_p))
|
||||
@@ -1526,7 +1556,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
own_names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
||||
|
||||
ecma_append_to_values_collection (prop_names_p,
|
||||
ecma_make_string_value (name_p),
|
||||
ecma_make_prop_name_value (name_p),
|
||||
0);
|
||||
}
|
||||
}
|
||||
@@ -1535,7 +1565,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (*property_p));
|
||||
|
||||
ecma_append_to_values_collection (skipped_non_enumerable_p,
|
||||
ecma_make_string_value (name_p),
|
||||
ecma_make_prop_name_value (name_p),
|
||||
0);
|
||||
}
|
||||
|
||||
@@ -1551,7 +1581,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
while (ecma_value_p != NULL)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p);
|
||||
ecma_string_t *name_p = ecma_get_prop_name_from_value (*ecma_value_p);
|
||||
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
|
||||
|
||||
uint32_t index = ecma_string_get_array_index (name_p);
|
||||
@@ -1580,7 +1610,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
while (ecma_value_p != NULL)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p);
|
||||
ecma_string_t *name_p = ecma_get_prop_name_from_value (*ecma_value_p);
|
||||
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
|
||||
|
||||
uint32_t index = ecma_string_get_array_index (name_p);
|
||||
@@ -1670,7 +1700,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
while (ecma_value_p != NULL)
|
||||
{
|
||||
ecma_string_t *current_name_p = ecma_get_string_from_value (*ecma_value_p);
|
||||
ecma_string_t *current_name_p = ecma_get_prop_name_from_value (*ecma_value_p);
|
||||
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, current_name_p))
|
||||
@@ -1687,7 +1717,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
while (ecma_value_p != NULL)
|
||||
{
|
||||
ecma_string_t *current_name_p = ecma_get_string_from_value (*ecma_value_p);
|
||||
ecma_string_t *current_name_p = ecma_get_prop_name_from_value (*ecma_value_p);
|
||||
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, current_name_p))
|
||||
@@ -1702,7 +1732,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
{
|
||||
JERRY_ASSERT ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) != 0);
|
||||
|
||||
ecma_append_to_values_collection (ret_p, ecma_make_string_value (names_p[i]), 0);
|
||||
ecma_append_to_values_collection (ret_p, ecma_make_prop_name_value (names_p[i]), 0);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "ecma-symbol-object.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmasymbolobject ECMA Symbol object related routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Symbol creation operation.
|
||||
*
|
||||
* See also: ECMA-262 v6, 6.1.5.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_symbol (const ecma_value_t *arguments_list_p, /**< list of arguments */
|
||||
ecma_length_t arguments_list_len) /**< length of the arguments' list */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
ecma_value_t string_desc;
|
||||
|
||||
/* 1-3. */
|
||||
if (arguments_list_len == 0)
|
||||
{
|
||||
string_desc = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_desc = ecma_op_to_string (arguments_list_p[0]);
|
||||
|
||||
/* 4. */
|
||||
if (ECMA_IS_VALUE_ERROR (string_desc))
|
||||
{
|
||||
return string_desc;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_string (string_desc));
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
return ecma_make_symbol_value (ecma_new_symbol_from_descriptor_string (string_desc));
|
||||
} /* ecma_op_create_symbol */
|
||||
|
||||
/**
|
||||
* Symbol object creation operation.
|
||||
*
|
||||
* See also: ECMA-262 v6, 19.4.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_symbol_object (const ecma_value_t value) /**< symbol value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_symbol (value));
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE);
|
||||
#else /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_SYMBOL_UL;
|
||||
ext_object_p->u.class_prop.u.value = ecma_copy_value (value);
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_symbol_object */
|
||||
|
||||
/**
|
||||
* Get the symbol descriptor ecma-string from an ecma-symbol
|
||||
*
|
||||
* @return pointer to ecma-string descriptor
|
||||
*/
|
||||
ecma_string_t *
|
||||
ecma_get_symbol_description (ecma_string_t *symbol_p) /**< ecma-symbol */
|
||||
{
|
||||
JERRY_ASSERT (symbol_p != NULL);
|
||||
JERRY_ASSERT (ecma_prop_name_is_symbol (symbol_p));
|
||||
|
||||
return ecma_get_string_from_value (symbol_p->u.symbol_descriptor);
|
||||
} /* ecma_get_symbol_description */
|
||||
|
||||
/**
|
||||
* Get the descriptive string of the Symbol.
|
||||
*
|
||||
* See also: ECMA-262 v6, 19.4.3.2.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_get_symbol_descriptive_string (ecma_value_t symbol_value) /**< symbol to stringify */
|
||||
{
|
||||
/* 1. */
|
||||
JERRY_ASSERT (ecma_is_value_symbol (symbol_value));
|
||||
|
||||
/* 2 - 3. */
|
||||
ecma_string_t *symbol_p = ecma_get_symbol_from_value (symbol_value);
|
||||
ecma_string_t *string_desc_p = ecma_get_symbol_description (symbol_p);
|
||||
|
||||
/* 5. */
|
||||
ecma_string_t *concat_p = ecma_concat_ecma_strings (ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_LEFT_PAREN_UL),
|
||||
string_desc_p);
|
||||
|
||||
ecma_string_t *final_str_p = ecma_append_magic_string_to_string (concat_p, LIT_MAGIC_STRING_RIGHT_PAREN);
|
||||
|
||||
return ecma_make_string_value (final_str_p);
|
||||
} /* ecma_get_symbol_descriptive_string */
|
||||
|
||||
/**
|
||||
* Helper for Symbol.prototype.{toString, valueOf} routines
|
||||
*
|
||||
* See also: 19.4.3.2, 19.4.3.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_symbol_to_string_helper (ecma_value_t this_arg, /**< this argument value */
|
||||
bool is_to_string) /**< true - perform the 'toString' routine steps
|
||||
* false - perform the 'valueOf' routine steps */
|
||||
{
|
||||
if (ecma_is_value_symbol (this_arg))
|
||||
{
|
||||
return is_to_string ? ecma_get_symbol_descriptive_string (this_arg) : ecma_copy_value (this_arg);
|
||||
}
|
||||
|
||||
if (ecma_is_value_object (this_arg))
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
|
||||
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_SYMBOL_UL)
|
||||
{
|
||||
return (is_to_string ? ecma_get_symbol_descriptive_string (ext_object_p->u.class_prop.u.value)
|
||||
: ecma_copy_value (ext_object_p->u.class_prop.u.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is must be a Symbol."));
|
||||
} /* ecma_symbol_to_string_helper */
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_SYMBOL_H
|
||||
#define ECMA_SYMBOL_H
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN
|
||||
#include "ecma-globals.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmasymbolobject ECMA Symbol object related routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_create_symbol (const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_create_symbol_object (const ecma_value_t value);
|
||||
|
||||
bool
|
||||
ecma_prop_name_is_symbol (ecma_string_t *string_p);
|
||||
|
||||
ecma_string_t *
|
||||
ecma_get_symbol_description (ecma_string_t *symbol_p);
|
||||
|
||||
ecma_value_t
|
||||
ecma_symbol_to_string_helper (ecma_value_t this_arg, bool is_to_string);
|
||||
|
||||
ecma_value_t
|
||||
ecma_get_symbol_descriptive_string (ecma_value_t symbol_value);
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_SYMBOL_H */
|
||||
Reference in New Issue
Block a user