1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "ecma-alloc.h" 17 #include "ecma-builtins.h" 18 #include "ecma-conversion.h" 19 #include "ecma-exceptions.h" 20 #include "ecma-gc.h" 21 #include "ecma-globals.h" 22 #include "ecma-helpers.h" 23 #include "ecma-objects.h" 24 #include "ecma-symbol-object.h" 25 #include "ecma-literal-storage.h" 26 #include "ecma-try-catch-macro.h" 27 #include "jcontext.h" 28 #include "jrt.h" 29 30#if ENABLED (JERRY_ES2015) 31 32#define ECMA_BUILTINS_INTERNAL 33#include "ecma-builtins-internal.h" 34 35#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol.inc.h" 36#define BUILTIN_UNDERSCORED_ID symbol 37#include "ecma-builtin-internal-routines-template.inc.h" 38 39/** \addtogroup ecma ECMA 40 * @{ 41 * 42 * \addtogroup ecmabuiltins 43 * @{ 44 * 45 * \addtogroup symbol ECMA Symbol object built-in 46 * @{ 47 */ 48 49/** 50 * Handle calling [[Call]] of built-in Symbol object. 51 * 52 * @return ecma value 53 */ 54ecma_value_t 55ecma_builtin_symbol_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ 56 ecma_length_t arguments_list_len) /**< number of arguments */ 57{ 58 JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 59 60 return ecma_op_create_symbol (arguments_list_p, arguments_list_len); 61} /* ecma_builtin_symbol_dispatch_call */ 62 63/** 64 * Handle calling [[Construct]] of built-in Symbol object. 65 * 66 * Symbol constructor is not intended to be used 67 * with the new operator or to be subclassed. 68 * 69 * See also: 70 * ECMA-262 v6, 19.4.1 71 * @return ecma value 72 */ 73ecma_value_t 74ecma_builtin_symbol_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ 75 ecma_length_t arguments_list_len) /**< number of arguments */ 76{ 77 JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 78 79 return ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not a constructor.")); 80} /* ecma_builtin_symbol_dispatch_construct */ 81 82/** 83 * Helper function for Symbol object's 'for' and `keyFor` 84 * routines common parts 85 * 86 * @return ecma value 87 * Returned value must be freed with ecma_free_value. 88 */ 89static ecma_value_t 90ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma-string */ 91{ 92 ecma_string_t *string_p; 93 94 bool is_for = ecma_is_value_string (value_to_find); 95 96 if (is_for) 97 { 98 string_p = ecma_get_string_from_value (value_to_find); 99 } 100 else 101 { 102 string_p = ecma_get_symbol_from_value (value_to_find); 103 } 104 105 jmem_cpointer_t symbol_list_cp = JERRY_CONTEXT (symbol_list_first_cp); 106 jmem_cpointer_t *empty_cpointer_p = NULL; 107 108 while (symbol_list_cp != JMEM_CP_NULL) 109 { 110 ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, 111 symbol_list_cp); 112 113 for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) 114 { 115 if (symbol_list_p->values[i] != JMEM_CP_NULL) 116 { 117 ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, 118 symbol_list_p->values[i]); 119 120 if (is_for) 121 { 122 ecma_string_t *symbol_desc_p = ecma_get_symbol_description (value_p); 123 124 if (ecma_compare_ecma_strings (symbol_desc_p, string_p)) 125 { 126 /* The current symbol's descriptor matches with the value_to_find, 127 so the value is no longer needed. */ 128 ecma_deref_ecma_string (string_p); 129 return ecma_copy_value (ecma_make_symbol_value (value_p)); 130 } 131 } 132 else 133 { 134 if (string_p == value_p) 135 { 136 ecma_string_t *symbol_desc_p = ecma_get_symbol_description (string_p); 137 ecma_ref_ecma_string (symbol_desc_p); 138 return ecma_make_string_value (symbol_desc_p); 139 } 140 } 141 } 142 else 143 { 144 if (empty_cpointer_p == NULL) 145 { 146 empty_cpointer_p = symbol_list_p->values + i; 147 } 148 } 149 } 150 151 symbol_list_cp = symbol_list_p->next_cp; 152 } 153 154 if (!is_for) 155 { 156 return ECMA_VALUE_UNDEFINED; 157 } 158 159 /* There was no matching, sp a new symbol should be added the the global symbol list. The symbol creation requires 160 an extra reference to the descriptor string, but this reference has already been added. */ 161 ecma_string_t *new_symbol_p = ecma_new_symbol_from_descriptor_string (value_to_find); 162 163 jmem_cpointer_t result; 164 JMEM_CP_SET_NON_NULL_POINTER (result, new_symbol_p); 165 166 if (empty_cpointer_p != NULL) 167 { 168 *empty_cpointer_p = result; 169 return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); 170 } 171 172 ecma_lit_storage_item_t *new_item_p; 173 new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); 174 175 new_item_p->values[0] = result; 176 for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) 177 { 178 new_item_p->values[i] = JMEM_CP_NULL; 179 } 180 181 new_item_p->next_cp = JERRY_CONTEXT (symbol_list_first_cp); 182 JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (symbol_list_first_cp), new_item_p); 183 184 return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); 185} /* ecma_builtin_symbol_for_helper */ 186 187/** 188 * The Symbol object's 'for' routine 189 * 190 * See also: 191 * ECMA-262 v6, 19.4.2.1 192 * 193 * @return ecma value 194 * Returned value must be freed with ecma_free_value. 195 */ 196static ecma_value_t 197ecma_builtin_symbol_for (ecma_value_t this_arg, /**< this argument */ 198 ecma_value_t key) /**< key string */ 199{ 200 JERRY_UNUSED (this_arg); 201 ecma_string_t *string_desc_p = ecma_op_to_string (key); 202 203 /* 1. */ 204 if (JERRY_UNLIKELY (string_desc_p == NULL)) 205 { 206 /* 2. */ 207 return ECMA_VALUE_ERROR; 208 } 209 210 return ecma_builtin_symbol_for_helper (ecma_make_string_value (string_desc_p)); 211} /* ecma_builtin_symbol_for */ 212 213/** 214 * The Symbol object's 'keyFor' routine 215 * 216 * See also: 217 * ECMA-262 v6, 19.4.2. 218 * 219 * @return ecma value 220 * Returned value must be freed with ecma_free_value. 221 */ 222static ecma_value_t 223ecma_builtin_symbol_key_for (ecma_value_t this_arg, /**< this argument */ 224 ecma_value_t symbol) /**< symbol */ 225{ 226 JERRY_UNUSED (this_arg); 227 228 /* 1. */ 229 if (!ecma_is_value_symbol (symbol)) 230 { 231 return ecma_raise_type_error (ECMA_ERR_MSG ("The given argument is not a Symbol.")); 232 } 233 234 /* 2-4. */ 235 return ecma_builtin_symbol_for_helper (symbol); 236} /* ecma_builtin_symbol_key_for */ 237 238/** 239 * @} 240 * @} 241 * @} 242 */ 243 244#endif /* ENABLED (JERRY_ES2015) */ 245