From 60bbd731e53a8cf48ccc0bc8af77f19600cb6028 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Tue, 19 Feb 2019 07:45:50 +0100 Subject: [PATCH] Add new symbol related API functions. (#2741) New functions: - ecma_create_symbol - ecma_value_is_symbol - jerry_get_symbol_descriptive_string Also improve the jerryx_handler_print to be able to print symbol values via using the jerry_get_symbol_descriptive_string API function for symbol values. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- docs/02.API-REFERENCE.md | 158 +++++++++++++++++++++ jerry-core/api/jerry.c | 113 +++++++++++++-- jerry-core/include/jerryscript-core.h | 9 ++ jerry-ext/handler/handler-print.c | 11 +- tests/unit-core/test-api-value-type.c | 13 ++ tests/unit-core/test-symbol.c | 197 ++++++++++++++++++++++++++ 6 files changed, 486 insertions(+), 15 deletions(-) create mode 100644 tests/unit-core/test-symbol.c diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index 28b9bda6f..2a8d2bc3c 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -24,6 +24,7 @@ Enum that contains JerryScript API value types: - JERRY_TYPE_OBJECT - object type - JERRY_TYPE_FUNCTION - function type - JERRY_TYPE_ERROR - error/abort type + - JERRY_TYPE_SYMBOL - symbol type ## jerry_error_t @@ -61,6 +62,7 @@ Possible compile time enabled feature types: - JERRY_FEATURE_REGEXP - RegExp support - JERRY_FEATURE_LINE_INFO - line info available - JERRY_FEATURE_LOGGING - logging + - JERRY_FEATURE_SYMBOL - symbol support ## jerry_regexp_flags_t @@ -1567,6 +1569,57 @@ jerry_value_is_string (const jerry_value_t value) - [jerry_release_value](#jerry_release_value) +## jerry_value_is_symbol + +**Summary** + +Returns whether the given `jerry_value_t` is a symbol value. + +**Prototype** + +```c +bool +jerry_value_is_symbol (const jerry_value_t value) +``` + +- `value` - API value +- return value + - true, if the given `jerry_value_t` is a symbol + - false, otherwise + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t string_value = jerry_create_string ((const jerry_char_t *) "Symbol description string"); + jerry_value_t symbol_value = jerry_create_symbol (string_value); + + jerry_release_value (string_value); + + if (jerry_value_is_symbol (symbol_value)) + { + // usage of symbol_value + } + + jerry_release_value (symbol_value); + + jerry_cleanup (); +} +``` + +**See also** + +- [jerry_release_value](#jerry_release_value) + + ## jerry_value_is_typedarray **Summary** @@ -2821,6 +2874,59 @@ jerry_resolve_or_reject_promise (jerry_value_t promise, - [jerry_release_value](#jerry_release_value) - [jerry_value_is_error](#jerry_value_is_error) +# Functions for symbols + +These APIs all depend on the ES2015-subset profile. + +## jerry_get_symbol_descriptive_string + +**Summary** + +Call the SymbolDescriptiveString ecma builtin operation on the API value. + +*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it +is no longer needed. + +**Prototype** + +```c +jerry_value_t +jerry_get_symbol_descriptive_string (const jerry_value_t value); +``` + +- `value` - symbol value +- return value + - string value containing the symbol's descriptive string - if success + - thrown error, otherwise + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t string_value = jerry_create_string ((const jerry_char_t *) "foo"); + jerry_value_t symbol_value = jerry_create_symbol (string_value); + + jerry_release_value (string_value); + + jerry_value_t symbol_desc_string = jerry_get_symbol_descriptive_string (symbol_value); + + // usage of symbol_desc_string + + jerry_release_value (symbol_desc_string); + jerry_release_value (symbol_value); + + jerry_cleanup (); +} +``` + # Acquire and release API values @@ -3546,6 +3652,58 @@ jerry_create_string_sz (const jerry_char_t *str_p, - [jerry_create_string_from_utf8](#jerry_create_string_from_utf8) +## jerry_create_symbol + +**Summary** + +Create symbol from an API value. + +*Note*: The given argument is converted to string. This operation can throw an error. + +**Prototype** + +```c +jerry_value_t +jerry_create_symbol (const jerry_value_t value) +``` + +- `value` - API value +- return value + - value of the created symbol, if success + - thrown error, otherwise + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t string_value = jerry_create_string ((const jerry_char_t *) "Symbol description string"); + jerry_value_t symbol_value = jerry_create_symbol (string_value); + + // The description value is no longer needed + jerry_release_value (string_value); + + // usage of symbol_value + + jerry_release_value (symbol_value); + + jerry_cleanup (); +} +``` + +**See also** + +- [jerry_value_is_symbol](#jerry_value_is_symbol) +- [jerry_release_value](#jerry_release_value) + + ## jerry_create_regexp **Summary** diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 2e3f21f6c..7b646ece9 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -34,6 +34,7 @@ #include "ecma-objects-general.h" #include "ecma-regexp-object.h" #include "ecma-promise-object.h" +#include "ecma-symbol-object.h" #include "ecma-typedarray-object.h" #include "opcodes.h" #include "jcontext.h" @@ -770,6 +771,25 @@ jerry_value_is_string (const jerry_value_t value) /**< api value */ return ecma_is_value_string (value); } /* jerry_value_is_string */ +/** + * Check if the specified value is symbol. + * + * @return true - if the specified value is symbol, + * false - otherwise + */ +bool +jerry_value_is_symbol (const jerry_value_t value) /**< api value */ +{ + jerry_assert_api_available (); + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + return ecma_is_value_symbol (value); +#else /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + JERRY_UNUSED (value); + return false; +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +} /* jerry_value_is_symbol */ + /** * Check if the specified value is undefined. * @@ -821,6 +841,12 @@ jerry_value_get_type (const jerry_value_t value) /**< input value to check */ { return JERRY_TYPE_STRING; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + case LIT_MAGIC_STRING_SYMBOL: + { + return JERRY_TYPE_SYMBOL; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ case LIT_MAGIC_STRING_FUNCTION: { return JERRY_TYPE_FUNCTION; @@ -885,6 +911,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check * #ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN || feature == JERRY_FEATURE_PROMISE #endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + || feature == JERRY_FEATURE_SYMBOL +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ #ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN || feature == JERRY_FEATURE_TYPEDARRAY #endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ @@ -1557,6 +1586,33 @@ jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */ return ecma_make_string_value (ecma_str_p); } /* jerry_create_string_sz */ +/** + * Create symbol from an api value + * + * Note: + * The given argument is converted to string. This operation can throw an error. + * returned value must be freed with jerry_release_value when it is no longer needed. + * + * @return value of the created symbol, if success + * thrown error, otherwise + */ +jerry_value_t +jerry_create_symbol (const jerry_value_t value) /**< api value */ +{ + jerry_assert_api_available (); + + if (ecma_is_value_error_reference (value)) + { + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); + } + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + return jerry_return (ecma_op_create_symbol (&value, 1)); +#else /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported."))); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +} /* jerry_create_symbol */ + /** * Calculates the size of the given pattern and creates a RegExp object. * @@ -1873,13 +1929,13 @@ jerry_has_property (const jerry_value_t obj_val, /**< object value */ jerry_assert_api_available (); if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return ECMA_VALUE_FALSE; } bool has_property = ecma_op_object_has_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + ecma_get_prop_name_from_value (prop_name_val)); return ecma_make_boolean_value (has_property); } /* jerry_has_property */ @@ -1897,13 +1953,13 @@ jerry_has_own_property (const jerry_value_t obj_val, /**< object value */ jerry_assert_api_available (); if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return ECMA_VALUE_FALSE; } bool has_property = ecma_op_object_has_own_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + ecma_get_prop_name_from_value (prop_name_val)); return ecma_make_boolean_value (has_property); } /* jerry_has_own_property */ @@ -1921,13 +1977,13 @@ jerry_delete_property (const jerry_value_t obj_val, /**< object value */ jerry_assert_api_available (); if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return false; } ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + ecma_get_prop_name_from_value (prop_name_val), false); return ecma_is_value_true (ret_value); } /* jerry_delete_property */ @@ -1974,13 +2030,13 @@ jerry_get_property (const jerry_value_t obj_val, /**< object value */ jerry_assert_api_available (); if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } jerry_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + ecma_get_prop_name_from_value (prop_name_val)); return jerry_return (ret_value); } /* jerry_get_property */ @@ -2029,13 +2085,13 @@ jerry_set_property (const jerry_value_t obj_val, /**< object value */ if (ecma_is_value_error_reference (value_to_set) || !ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } return jerry_return (ecma_op_object_put (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + ecma_get_prop_name_from_value (prop_name_val), value_to_set, true)); } /* jerry_set_property */ @@ -2109,7 +2165,7 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ jerry_assert_api_available (); if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } @@ -2189,7 +2245,7 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ } return ecma_op_object_define_own_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + ecma_get_prop_name_from_value (prop_name_val), &prop_desc, true); } /* jerry_define_own_property */ @@ -2208,7 +2264,7 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val jerry_assert_api_available (); if (!ecma_is_value_object (obj_val) - || !ecma_is_value_string (prop_name_val)) + || !ecma_is_value_prop_name (prop_name_val)) { return false; } @@ -2216,7 +2272,7 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val ecma_property_descriptor_t prop_desc; if (!ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val), + ecma_get_prop_name_from_value (prop_name_val), &prop_desc)) { return false; @@ -2715,6 +2771,35 @@ jerry_resolve_or_reject_promise (jerry_value_t promise, /**< the promise value * #endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */ } /* jerry_resolve_or_reject_promise */ +/** + * Call the SymbolDescriptiveString ecma builtin operation on the symbol value. + * + * Note: + * returned value must be freed with jerry_release_value, when it is no longer needed. + * + * @return string value containing the symbol's descriptive string - if success + * thrown error - otherwise + */ +jerry_value_t +jerry_get_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol value */ +{ + jerry_assert_api_available (); + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (!ecma_is_value_symbol (symbol)) + { + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); + } + + /* Note: This operation cannot throw an error */ + return ecma_get_symbol_descriptive_string (symbol); +#else /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + JERRY_UNUSED (symbol); + + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not supported."))); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +} /** jerry_get_symbol_descriptive_string */ + /** * Validate UTF-8 string * diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 91b910b3f..2bec6dd94 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -92,6 +92,7 @@ typedef enum JERRY_FEATURE_REGEXP, /**< Regexp support */ JERRY_FEATURE_LINE_INFO, /**< line info available */ JERRY_FEATURE_LOGGING, /**< logging */ + JERRY_FEATURE_SYMBOL, /**< symbol support */ JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */ } jerry_feature_t; @@ -368,6 +369,7 @@ bool jerry_value_is_null (const jerry_value_t value); bool jerry_value_is_object (const jerry_value_t value); bool jerry_value_is_promise (const jerry_value_t value); bool jerry_value_is_string (const jerry_value_t value); +bool jerry_value_is_symbol (const jerry_value_t value); bool jerry_value_is_undefined (const jerry_value_t value); /** @@ -384,6 +386,7 @@ typedef enum JERRY_TYPE_OBJECT, /**< object type */ JERRY_TYPE_FUNCTION, /**< function type */ JERRY_TYPE_ERROR, /**< error/abort type */ + JERRY_TYPE_SYMBOL, /**< symbol type */ } jerry_type_t; jerry_type_t jerry_value_get_type (const jerry_value_t value); @@ -485,6 +488,7 @@ jerry_value_t jerry_create_string_from_utf8 (const jerry_char_t *str_p); jerry_value_t jerry_create_string_sz_from_utf8 (const jerry_char_t *str_p, jerry_size_t str_size); jerry_value_t jerry_create_string (const jerry_char_t *str_p); jerry_value_t jerry_create_string_sz (const jerry_char_t *str_p, jerry_size_t str_size); +jerry_value_t jerry_create_symbol (const jerry_value_t value); jerry_value_t jerry_create_undefined (void); /** @@ -542,6 +546,11 @@ bool jerry_foreach_object_property (const jerry_value_t obj_val, jerry_object_pr */ jerry_value_t jerry_resolve_or_reject_promise (jerry_value_t promise, jerry_value_t argument, bool is_resolve); +/** + * Symbol functions. + */ +jerry_value_t jerry_get_symbol_descriptive_string (const jerry_value_t symbol); + /** * Input validator functions. */ diff --git a/jerry-ext/handler/handler-print.c b/jerry-ext/handler/handler-print.c index d1cdd306c..1175b17b4 100644 --- a/jerry-ext/handler/handler-print.c +++ b/jerry-ext/handler/handler-print.c @@ -50,7 +50,16 @@ jerryx_handler_print (const jerry_value_t func_obj_val, /**< function object */ for (jerry_length_t arg_index = 0; arg_index < args_cnt; arg_index++) { - jerry_value_t str_val = jerry_value_to_string (args_p[arg_index]); + jerry_value_t str_val; + + if (jerry_value_is_symbol (args_p[arg_index])) + { + str_val = jerry_get_symbol_descriptive_string (args_p[arg_index]); + } + else + { + str_val = jerry_value_to_string (args_p[arg_index]); + } if (jerry_value_is_error (str_val)) { diff --git a/tests/unit-core/test-api-value-type.c b/tests/unit-core/test-api-value-type.c index 8a85be97e..f85e02b7d 100644 --- a/tests/unit-core/test-api-value-type.c +++ b/tests/unit-core/test-api-value-type.c @@ -86,6 +86,19 @@ main (void) jerry_release_value (entries[idx].value); } + if (jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL)) + { + jerry_value_t symbol_desc_value = jerry_create_string ((jerry_char_t *) "foo"); + jerry_value_t symbol_value = jerry_create_symbol (symbol_desc_value); + jerry_type_t type_info = jerry_value_get_type (symbol_value); + + TEST_ASSERT (type_info != JERRY_TYPE_NONE); + TEST_ASSERT (type_info == JERRY_TYPE_SYMBOL); + + jerry_release_value (symbol_value); + jerry_release_value (symbol_desc_value); + } + jerry_cleanup (); return 0; diff --git a/tests/unit-core/test-symbol.c b/tests/unit-core/test-symbol.c new file mode 100644 index 000000000..e73e4c3ae --- /dev/null +++ b/tests/unit-core/test-symbol.c @@ -0,0 +1,197 @@ +/* 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 "jerryscript.h" +#include "jerryscript-port.h" +#include "jerryscript-port-default.h" +#include "test-common.h" + +/* foo string */ +#define STRING_FOO ((const jerry_char_t *) "foo") + +/* bar string */ +#define STRING_BAR ((const jerry_char_t *) "bar") + +/* Symbol(bar) desciptive string */ +#define SYMBOL_DESCIPTIVE_STRING_BAR "Symbol(bar)" + +int +main (void) +{ + if (!jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL)) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Symbol support is disabled!\n"); + return 0; + } + + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t object = jerry_create_object (); + + /* Test for that each symbol is unique independently from their descriptor strings */ + jerry_value_t symbol_desc_1 = jerry_create_string (STRING_FOO); + jerry_value_t symbol_desc_2 = jerry_create_string (STRING_FOO); + + jerry_value_t symbol_1 = jerry_create_symbol (symbol_desc_1); + TEST_ASSERT (!jerry_value_is_error (symbol_1)); + TEST_ASSERT (jerry_value_is_symbol (symbol_1)); + + jerry_value_t symbol_2 = jerry_create_symbol (symbol_desc_2); + TEST_ASSERT (!jerry_value_is_error (symbol_2)); + TEST_ASSERT (jerry_value_is_symbol (symbol_2)); + + /* The descriptor strings are no longer needed */ + jerry_release_value (symbol_desc_1); + jerry_release_value (symbol_desc_2); + + jerry_value_t value_1 = jerry_create_number (1); + jerry_value_t value_2 = jerry_create_number (2); + + jerry_value_t result_val = jerry_set_property (object, symbol_1, value_1); + TEST_ASSERT (jerry_value_is_boolean (result_val)); + TEST_ASSERT (jerry_get_boolean_value (jerry_has_property (object, symbol_1))); + TEST_ASSERT (jerry_get_boolean_value (jerry_has_own_property (object, symbol_1))); + + result_val = jerry_set_property (object, symbol_2, value_2); + TEST_ASSERT (jerry_value_is_boolean (result_val)); + TEST_ASSERT (jerry_get_boolean_value (jerry_has_property (object, symbol_2))); + TEST_ASSERT (jerry_get_boolean_value (jerry_has_own_property (object, symbol_2))); + + jerry_value_t get_value_1 = jerry_get_property (object, symbol_1); + TEST_ASSERT (jerry_get_number_value (get_value_1) == jerry_get_number_value (value_1)); + jerry_release_value (get_value_1); + + jerry_value_t get_value_2 = jerry_get_property (object, symbol_2); + TEST_ASSERT (jerry_get_number_value (get_value_2) == jerry_get_number_value (value_2)); + jerry_release_value (get_value_2); + + /* Test delete / has_{own}_property */ + TEST_ASSERT (jerry_delete_property (object, symbol_1)); + TEST_ASSERT (!jerry_get_boolean_value (jerry_has_property (object, symbol_1))); + TEST_ASSERT (!jerry_get_boolean_value (jerry_has_own_property (object, symbol_1))); + + jerry_release_value (value_1); + jerry_release_value (symbol_1); + + /* Test {get, define}_own_property_descriptor */ + jerry_property_descriptor_t prop_desc; + TEST_ASSERT (jerry_get_own_property_descriptor (object, symbol_2, &prop_desc)); + TEST_ASSERT (prop_desc.is_value_defined == true); + TEST_ASSERT (value_2 == prop_desc.value); + TEST_ASSERT (jerry_get_number_value (value_2) == jerry_get_number_value (prop_desc.value)); + TEST_ASSERT (prop_desc.is_writable == true); + TEST_ASSERT (prop_desc.is_enumerable == true); + TEST_ASSERT (prop_desc.is_configurable == true); + TEST_ASSERT (prop_desc.is_get_defined == false); + TEST_ASSERT (jerry_value_is_undefined (prop_desc.getter)); + TEST_ASSERT (prop_desc.is_set_defined == false); + TEST_ASSERT (jerry_value_is_undefined (prop_desc.setter)); + jerry_free_property_descriptor_fields (&prop_desc); + + /* Modify the descriptor fields */ + jerry_init_property_descriptor_fields (&prop_desc); + jerry_value_t value_3 = jerry_create_string (STRING_BAR); + + prop_desc.is_value_defined = true; + prop_desc.value = jerry_acquire_value (value_3); + prop_desc.is_writable_defined = true; + prop_desc.is_writable = false; + prop_desc.is_enumerable_defined = true; + prop_desc.is_enumerable = false; + prop_desc.is_configurable_defined = true; + prop_desc.is_configurable = false; + TEST_ASSERT (jerry_get_boolean_value (jerry_define_own_property (object, symbol_2, &prop_desc))); + jerry_free_property_descriptor_fields (&prop_desc); + + /* Check the modified fields */ + TEST_ASSERT (jerry_get_own_property_descriptor (object, symbol_2, &prop_desc)); + TEST_ASSERT (prop_desc.is_value_defined == true); + TEST_ASSERT (value_3 == prop_desc.value); + TEST_ASSERT (jerry_value_is_string (prop_desc.value)); + TEST_ASSERT (prop_desc.is_writable_defined == true); + TEST_ASSERT (prop_desc.is_writable == false); + TEST_ASSERT (prop_desc.is_enumerable_defined == true); + TEST_ASSERT (prop_desc.is_enumerable == false); + TEST_ASSERT (prop_desc.is_configurable_defined == true); + TEST_ASSERT (prop_desc.is_configurable == false); + TEST_ASSERT (prop_desc.is_get_defined == false); + TEST_ASSERT (jerry_value_is_undefined (prop_desc.getter)); + TEST_ASSERT (prop_desc.is_set_defined == false); + TEST_ASSERT (jerry_value_is_undefined (prop_desc.setter)); + jerry_free_property_descriptor_fields (&prop_desc); + + jerry_release_value (value_3); + jerry_release_value (value_2); + jerry_release_value (symbol_2); + jerry_release_value (object); + + /* Test creating symbol with a symbol description */ + jerry_value_t empty_symbol_desc = jerry_create_string ((const jerry_char_t *) ""); + + jerry_value_t empty_symbol = jerry_create_symbol (empty_symbol_desc); + TEST_ASSERT (!jerry_value_is_error (empty_symbol)); + TEST_ASSERT (jerry_value_is_symbol (empty_symbol)); + + jerry_release_value (empty_symbol_desc); + + jerry_value_t symbol_symbol = jerry_create_symbol (empty_symbol); + TEST_ASSERT (!jerry_value_is_symbol (symbol_symbol)); + TEST_ASSERT (jerry_value_is_error (symbol_symbol)); + + jerry_value_t error_obj = jerry_get_value_from_error (symbol_symbol, true); + + TEST_ASSERT (jerry_get_error_type (error_obj) == JERRY_ERROR_TYPE); + + jerry_release_value (error_obj); + jerry_release_value (empty_symbol); + + /* Test symbol to string operation with symbol argument */ + jerry_value_t bar_symbol_desc = jerry_create_string (STRING_BAR); + + jerry_value_t bar_symbol = jerry_create_symbol (bar_symbol_desc); + TEST_ASSERT (!jerry_value_is_error (bar_symbol)); + TEST_ASSERT (jerry_value_is_symbol (bar_symbol)); + + jerry_release_value (bar_symbol_desc); + + jerry_value_t bar_symbol_string = jerry_get_symbol_descriptive_string (bar_symbol); + TEST_ASSERT (jerry_value_is_string (bar_symbol_string)); + + jerry_size_t bar_symbol_string_size = jerry_get_string_size (bar_symbol_string); + TEST_ASSERT (bar_symbol_string_size == (sizeof (SYMBOL_DESCIPTIVE_STRING_BAR) - 1)); + jerry_char_t str_buff[bar_symbol_string_size]; + + jerry_string_to_char_buffer (bar_symbol_string, str_buff, bar_symbol_string_size); + TEST_ASSERT (memcmp (str_buff, SYMBOL_DESCIPTIVE_STRING_BAR, sizeof (SYMBOL_DESCIPTIVE_STRING_BAR) - 1) == 0); + + jerry_release_value (bar_symbol_string); + jerry_release_value (bar_symbol); + + /* Test symbol to string operation with non-symbol argument */ + jerry_value_t null_value = jerry_create_null (); + jerry_value_t to_string_value = jerry_get_symbol_descriptive_string (null_value); + TEST_ASSERT (jerry_value_is_error (to_string_value)); + + error_obj = jerry_get_value_from_error (to_string_value, true); + + TEST_ASSERT (jerry_get_error_type (error_obj) == JERRY_ERROR_TYPE); + + jerry_release_value (error_obj); + jerry_release_value (null_value); + + jerry_cleanup (); + + return 0; +} /* main */