1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci #include "ecma-alloc.h" 17425bb815Sopenharmony_ci #include "ecma-builtins.h" 18425bb815Sopenharmony_ci #include "ecma-conversion.h" 19425bb815Sopenharmony_ci #include "ecma-exceptions.h" 20425bb815Sopenharmony_ci #include "ecma-gc.h" 21425bb815Sopenharmony_ci #include "ecma-globals.h" 22425bb815Sopenharmony_ci #include "ecma-helpers.h" 23425bb815Sopenharmony_ci #include "ecma-objects.h" 24425bb815Sopenharmony_ci #include "ecma-symbol-object.h" 25425bb815Sopenharmony_ci #include "ecma-literal-storage.h" 26425bb815Sopenharmony_ci #include "ecma-try-catch-macro.h" 27425bb815Sopenharmony_ci #include "jcontext.h" 28425bb815Sopenharmony_ci #include "jrt.h" 29425bb815Sopenharmony_ci 30425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 31425bb815Sopenharmony_ci 32425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL 33425bb815Sopenharmony_ci#include "ecma-builtins-internal.h" 34425bb815Sopenharmony_ci 35425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol.inc.h" 36425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID symbol 37425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h" 38425bb815Sopenharmony_ci 39425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 40425bb815Sopenharmony_ci * @{ 41425bb815Sopenharmony_ci * 42425bb815Sopenharmony_ci * \addtogroup ecmabuiltins 43425bb815Sopenharmony_ci * @{ 44425bb815Sopenharmony_ci * 45425bb815Sopenharmony_ci * \addtogroup symbol ECMA Symbol object built-in 46425bb815Sopenharmony_ci * @{ 47425bb815Sopenharmony_ci */ 48425bb815Sopenharmony_ci 49425bb815Sopenharmony_ci/** 50425bb815Sopenharmony_ci * Handle calling [[Call]] of built-in Symbol object. 51425bb815Sopenharmony_ci * 52425bb815Sopenharmony_ci * @return ecma value 53425bb815Sopenharmony_ci */ 54425bb815Sopenharmony_ciecma_value_t 55425bb815Sopenharmony_ciecma_builtin_symbol_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ 56425bb815Sopenharmony_ci ecma_length_t arguments_list_len) /**< number of arguments */ 57425bb815Sopenharmony_ci{ 58425bb815Sopenharmony_ci JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 59425bb815Sopenharmony_ci 60425bb815Sopenharmony_ci return ecma_op_create_symbol (arguments_list_p, arguments_list_len); 61425bb815Sopenharmony_ci} /* ecma_builtin_symbol_dispatch_call */ 62425bb815Sopenharmony_ci 63425bb815Sopenharmony_ci/** 64425bb815Sopenharmony_ci * Handle calling [[Construct]] of built-in Symbol object. 65425bb815Sopenharmony_ci * 66425bb815Sopenharmony_ci * Symbol constructor is not intended to be used 67425bb815Sopenharmony_ci * with the new operator or to be subclassed. 68425bb815Sopenharmony_ci * 69425bb815Sopenharmony_ci * See also: 70425bb815Sopenharmony_ci * ECMA-262 v6, 19.4.1 71425bb815Sopenharmony_ci * @return ecma value 72425bb815Sopenharmony_ci */ 73425bb815Sopenharmony_ciecma_value_t 74425bb815Sopenharmony_ciecma_builtin_symbol_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ 75425bb815Sopenharmony_ci ecma_length_t arguments_list_len) /**< number of arguments */ 76425bb815Sopenharmony_ci{ 77425bb815Sopenharmony_ci JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 78425bb815Sopenharmony_ci 79425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not a constructor.")); 80425bb815Sopenharmony_ci} /* ecma_builtin_symbol_dispatch_construct */ 81425bb815Sopenharmony_ci 82425bb815Sopenharmony_ci/** 83425bb815Sopenharmony_ci * Helper function for Symbol object's 'for' and `keyFor` 84425bb815Sopenharmony_ci * routines common parts 85425bb815Sopenharmony_ci * 86425bb815Sopenharmony_ci * @return ecma value 87425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 88425bb815Sopenharmony_ci */ 89425bb815Sopenharmony_cistatic ecma_value_t 90425bb815Sopenharmony_ciecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma-string */ 91425bb815Sopenharmony_ci{ 92425bb815Sopenharmony_ci ecma_string_t *string_p; 93425bb815Sopenharmony_ci 94425bb815Sopenharmony_ci bool is_for = ecma_is_value_string (value_to_find); 95425bb815Sopenharmony_ci 96425bb815Sopenharmony_ci if (is_for) 97425bb815Sopenharmony_ci { 98425bb815Sopenharmony_ci string_p = ecma_get_string_from_value (value_to_find); 99425bb815Sopenharmony_ci } 100425bb815Sopenharmony_ci else 101425bb815Sopenharmony_ci { 102425bb815Sopenharmony_ci string_p = ecma_get_symbol_from_value (value_to_find); 103425bb815Sopenharmony_ci } 104425bb815Sopenharmony_ci 105425bb815Sopenharmony_ci jmem_cpointer_t symbol_list_cp = JERRY_CONTEXT (symbol_list_first_cp); 106425bb815Sopenharmony_ci jmem_cpointer_t *empty_cpointer_p = NULL; 107425bb815Sopenharmony_ci 108425bb815Sopenharmony_ci while (symbol_list_cp != JMEM_CP_NULL) 109425bb815Sopenharmony_ci { 110425bb815Sopenharmony_ci ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, 111425bb815Sopenharmony_ci symbol_list_cp); 112425bb815Sopenharmony_ci 113425bb815Sopenharmony_ci for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) 114425bb815Sopenharmony_ci { 115425bb815Sopenharmony_ci if (symbol_list_p->values[i] != JMEM_CP_NULL) 116425bb815Sopenharmony_ci { 117425bb815Sopenharmony_ci ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, 118425bb815Sopenharmony_ci symbol_list_p->values[i]); 119425bb815Sopenharmony_ci 120425bb815Sopenharmony_ci if (is_for) 121425bb815Sopenharmony_ci { 122425bb815Sopenharmony_ci ecma_string_t *symbol_desc_p = ecma_get_symbol_description (value_p); 123425bb815Sopenharmony_ci 124425bb815Sopenharmony_ci if (ecma_compare_ecma_strings (symbol_desc_p, string_p)) 125425bb815Sopenharmony_ci { 126425bb815Sopenharmony_ci /* The current symbol's descriptor matches with the value_to_find, 127425bb815Sopenharmony_ci so the value is no longer needed. */ 128425bb815Sopenharmony_ci ecma_deref_ecma_string (string_p); 129425bb815Sopenharmony_ci return ecma_copy_value (ecma_make_symbol_value (value_p)); 130425bb815Sopenharmony_ci } 131425bb815Sopenharmony_ci } 132425bb815Sopenharmony_ci else 133425bb815Sopenharmony_ci { 134425bb815Sopenharmony_ci if (string_p == value_p) 135425bb815Sopenharmony_ci { 136425bb815Sopenharmony_ci ecma_string_t *symbol_desc_p = ecma_get_symbol_description (string_p); 137425bb815Sopenharmony_ci ecma_ref_ecma_string (symbol_desc_p); 138425bb815Sopenharmony_ci return ecma_make_string_value (symbol_desc_p); 139425bb815Sopenharmony_ci } 140425bb815Sopenharmony_ci } 141425bb815Sopenharmony_ci } 142425bb815Sopenharmony_ci else 143425bb815Sopenharmony_ci { 144425bb815Sopenharmony_ci if (empty_cpointer_p == NULL) 145425bb815Sopenharmony_ci { 146425bb815Sopenharmony_ci empty_cpointer_p = symbol_list_p->values + i; 147425bb815Sopenharmony_ci } 148425bb815Sopenharmony_ci } 149425bb815Sopenharmony_ci } 150425bb815Sopenharmony_ci 151425bb815Sopenharmony_ci symbol_list_cp = symbol_list_p->next_cp; 152425bb815Sopenharmony_ci } 153425bb815Sopenharmony_ci 154425bb815Sopenharmony_ci if (!is_for) 155425bb815Sopenharmony_ci { 156425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 157425bb815Sopenharmony_ci } 158425bb815Sopenharmony_ci 159425bb815Sopenharmony_ci /* There was no matching, sp a new symbol should be added the the global symbol list. The symbol creation requires 160425bb815Sopenharmony_ci an extra reference to the descriptor string, but this reference has already been added. */ 161425bb815Sopenharmony_ci ecma_string_t *new_symbol_p = ecma_new_symbol_from_descriptor_string (value_to_find); 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_ci jmem_cpointer_t result; 164425bb815Sopenharmony_ci JMEM_CP_SET_NON_NULL_POINTER (result, new_symbol_p); 165425bb815Sopenharmony_ci 166425bb815Sopenharmony_ci if (empty_cpointer_p != NULL) 167425bb815Sopenharmony_ci { 168425bb815Sopenharmony_ci *empty_cpointer_p = result; 169425bb815Sopenharmony_ci return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); 170425bb815Sopenharmony_ci } 171425bb815Sopenharmony_ci 172425bb815Sopenharmony_ci ecma_lit_storage_item_t *new_item_p; 173425bb815Sopenharmony_ci new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); 174425bb815Sopenharmony_ci 175425bb815Sopenharmony_ci new_item_p->values[0] = result; 176425bb815Sopenharmony_ci for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) 177425bb815Sopenharmony_ci { 178425bb815Sopenharmony_ci new_item_p->values[i] = JMEM_CP_NULL; 179425bb815Sopenharmony_ci } 180425bb815Sopenharmony_ci 181425bb815Sopenharmony_ci new_item_p->next_cp = JERRY_CONTEXT (symbol_list_first_cp); 182425bb815Sopenharmony_ci JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (symbol_list_first_cp), new_item_p); 183425bb815Sopenharmony_ci 184425bb815Sopenharmony_ci return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); 185425bb815Sopenharmony_ci} /* ecma_builtin_symbol_for_helper */ 186425bb815Sopenharmony_ci 187425bb815Sopenharmony_ci/** 188425bb815Sopenharmony_ci * The Symbol object's 'for' routine 189425bb815Sopenharmony_ci * 190425bb815Sopenharmony_ci * See also: 191425bb815Sopenharmony_ci * ECMA-262 v6, 19.4.2.1 192425bb815Sopenharmony_ci * 193425bb815Sopenharmony_ci * @return ecma value 194425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 195425bb815Sopenharmony_ci */ 196425bb815Sopenharmony_cistatic ecma_value_t 197425bb815Sopenharmony_ciecma_builtin_symbol_for (ecma_value_t this_arg, /**< this argument */ 198425bb815Sopenharmony_ci ecma_value_t key) /**< key string */ 199425bb815Sopenharmony_ci{ 200425bb815Sopenharmony_ci JERRY_UNUSED (this_arg); 201425bb815Sopenharmony_ci ecma_string_t *string_desc_p = ecma_op_to_string (key); 202425bb815Sopenharmony_ci 203425bb815Sopenharmony_ci /* 1. */ 204425bb815Sopenharmony_ci if (JERRY_UNLIKELY (string_desc_p == NULL)) 205425bb815Sopenharmony_ci { 206425bb815Sopenharmony_ci /* 2. */ 207425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 208425bb815Sopenharmony_ci } 209425bb815Sopenharmony_ci 210425bb815Sopenharmony_ci return ecma_builtin_symbol_for_helper (ecma_make_string_value (string_desc_p)); 211425bb815Sopenharmony_ci} /* ecma_builtin_symbol_for */ 212425bb815Sopenharmony_ci 213425bb815Sopenharmony_ci/** 214425bb815Sopenharmony_ci * The Symbol object's 'keyFor' routine 215425bb815Sopenharmony_ci * 216425bb815Sopenharmony_ci * See also: 217425bb815Sopenharmony_ci * ECMA-262 v6, 19.4.2. 218425bb815Sopenharmony_ci * 219425bb815Sopenharmony_ci * @return ecma value 220425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 221425bb815Sopenharmony_ci */ 222425bb815Sopenharmony_cistatic ecma_value_t 223425bb815Sopenharmony_ciecma_builtin_symbol_key_for (ecma_value_t this_arg, /**< this argument */ 224425bb815Sopenharmony_ci ecma_value_t symbol) /**< symbol */ 225425bb815Sopenharmony_ci{ 226425bb815Sopenharmony_ci JERRY_UNUSED (this_arg); 227425bb815Sopenharmony_ci 228425bb815Sopenharmony_ci /* 1. */ 229425bb815Sopenharmony_ci if (!ecma_is_value_symbol (symbol)) 230425bb815Sopenharmony_ci { 231425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("The given argument is not a Symbol.")); 232425bb815Sopenharmony_ci } 233425bb815Sopenharmony_ci 234425bb815Sopenharmony_ci /* 2-4. */ 235425bb815Sopenharmony_ci return ecma_builtin_symbol_for_helper (symbol); 236425bb815Sopenharmony_ci} /* ecma_builtin_symbol_key_for */ 237425bb815Sopenharmony_ci 238425bb815Sopenharmony_ci/** 239425bb815Sopenharmony_ci * @} 240425bb815Sopenharmony_ci * @} 241425bb815Sopenharmony_ci * @} 242425bb815Sopenharmony_ci */ 243425bb815Sopenharmony_ci 244425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 245