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:
Robert Fancsik
2019-01-16 10:09:23 +01:00
committed by Robert Sipka
parent 08c7183ef8
commit 7e3d688e5b
43 changed files with 1896 additions and 212 deletions
@@ -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))
{
+122 -63
View File
@@ -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);
+102 -72
View File
@@ -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 */