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#include "jcontext.h" 16425bb815Sopenharmony_ci#include "ecma-alloc.h" 17425bb815Sopenharmony_ci#include "ecma-array-object.h" 18425bb815Sopenharmony_ci#include "ecma-builtins.h" 19425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h" 20425bb815Sopenharmony_ci#include "ecma-exceptions.h" 21425bb815Sopenharmony_ci#include "ecma-function-object.h" 22425bb815Sopenharmony_ci#include "ecma-gc.h" 23425bb815Sopenharmony_ci#include "ecma-helpers.h" 24425bb815Sopenharmony_ci#include "ecma-iterator-object.h" 25425bb815Sopenharmony_ci#include "ecma-container-object.h" 26425bb815Sopenharmony_ci#include "ecma-property-hashmap.h" 27425bb815Sopenharmony_ci#include "ecma-objects.h" 28425bb815Sopenharmony_ci 29425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 32425bb815Sopenharmony_ci * @{ 33425bb815Sopenharmony_ci * 34425bb815Sopenharmony_ci * \addtogroup \addtogroup ecmamaphelpers ECMA builtin Map/Set helper functions 35425bb815Sopenharmony_ci * @{ 36425bb815Sopenharmony_ci */ 37425bb815Sopenharmony_ci 38425bb815Sopenharmony_ci/** 39425bb815Sopenharmony_ci * Create a new internal buffer. 40425bb815Sopenharmony_ci * 41425bb815Sopenharmony_ci * Note: 42425bb815Sopenharmony_ci * The first element of the collection tracks the size of the buffer. 43425bb815Sopenharmony_ci * ECMA_VALUE_EMPTY values are not calculated into the size. 44425bb815Sopenharmony_ci * 45425bb815Sopenharmony_ci * @return pointer to the internal buffer 46425bb815Sopenharmony_ci */ 47425bb815Sopenharmony_cistatic inline ecma_collection_t * 48425bb815Sopenharmony_ciecma_op_create_internal_buffer (void) 49425bb815Sopenharmony_ci{ 50425bb815Sopenharmony_ci ecma_collection_t *collection_p = ecma_new_collection (); 51425bb815Sopenharmony_ci ecma_collection_push_back (collection_p, (ecma_value_t) 0); 52425bb815Sopenharmony_ci 53425bb815Sopenharmony_ci return collection_p; 54425bb815Sopenharmony_ci} /* ecma_op_create_internal_buffer */ 55425bb815Sopenharmony_ci 56425bb815Sopenharmony_ci/** 57425bb815Sopenharmony_ci * Append values to the internal buffer. 58425bb815Sopenharmony_ci */ 59425bb815Sopenharmony_cistatic void 60425bb815Sopenharmony_ciecma_op_internal_buffer_append (ecma_collection_t *container_p, /**< internal container pointer */ 61425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 62425bb815Sopenharmony_ci ecma_value_t value_arg, /**< value argument */ 63425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< class id */ 64425bb815Sopenharmony_ci{ 65425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 66425bb815Sopenharmony_ci 67425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) 68425bb815Sopenharmony_ci { 69425bb815Sopenharmony_ci ecma_value_t values[] = { ecma_copy_value_if_not_object (key_arg), ecma_copy_value_if_not_object (value_arg) }; 70425bb815Sopenharmony_ci ecma_collection_append (container_p, values, 2); 71425bb815Sopenharmony_ci } 72425bb815Sopenharmony_ci else 73425bb815Sopenharmony_ci { 74425bb815Sopenharmony_ci ecma_collection_push_back (container_p, ecma_copy_value_if_not_object (key_arg)); 75425bb815Sopenharmony_ci } 76425bb815Sopenharmony_ci 77425bb815Sopenharmony_ci ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) + 1); 78425bb815Sopenharmony_ci} /* ecma_op_internal_buffer_append */ 79425bb815Sopenharmony_ci 80425bb815Sopenharmony_ci/** 81425bb815Sopenharmony_ci * Update the value of a given entry. 82425bb815Sopenharmony_ci */ 83425bb815Sopenharmony_cistatic inline void 84425bb815Sopenharmony_ciecma_op_internal_buffer_update (ecma_value_t *entry_p, /**< entry pointer */ 85425bb815Sopenharmony_ci ecma_value_t value_arg, /**< value argument */ 86425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< class id */ 87425bb815Sopenharmony_ci{ 88425bb815Sopenharmony_ci JERRY_ASSERT (entry_p != NULL); 89425bb815Sopenharmony_ci 90425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) 91425bb815Sopenharmony_ci { 92425bb815Sopenharmony_ci ecma_free_value_if_not_object (((ecma_container_pair_t *) entry_p)->value); 93425bb815Sopenharmony_ci 94425bb815Sopenharmony_ci ((ecma_container_pair_t *) entry_p)->value = ecma_copy_value_if_not_object (value_arg); 95425bb815Sopenharmony_ci } 96425bb815Sopenharmony_ci} /* ecma_op_internal_buffer_update */ 97425bb815Sopenharmony_ci 98425bb815Sopenharmony_ci/** 99425bb815Sopenharmony_ci * Delete element from the internal buffer. 100425bb815Sopenharmony_ci */ 101425bb815Sopenharmony_cistatic void 102425bb815Sopenharmony_ciecma_op_internal_buffer_delete (ecma_collection_t *container_p, /**< internal container pointer */ 103425bb815Sopenharmony_ci ecma_container_pair_t *entry_p, /**< entry pointer */ 104425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< class id */ 105425bb815Sopenharmony_ci{ 106425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 107425bb815Sopenharmony_ci JERRY_ASSERT (entry_p != NULL); 108425bb815Sopenharmony_ci 109425bb815Sopenharmony_ci ecma_free_value_if_not_object (entry_p->key); 110425bb815Sopenharmony_ci entry_p->key = ECMA_VALUE_EMPTY; 111425bb815Sopenharmony_ci 112425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) 113425bb815Sopenharmony_ci { 114425bb815Sopenharmony_ci ecma_free_value_if_not_object (entry_p->value); 115425bb815Sopenharmony_ci entry_p->value = ECMA_VALUE_EMPTY; 116425bb815Sopenharmony_ci } 117425bb815Sopenharmony_ci 118425bb815Sopenharmony_ci ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) - 1); 119425bb815Sopenharmony_ci} /* ecma_op_internal_buffer_delete */ 120425bb815Sopenharmony_ci 121425bb815Sopenharmony_ci/** 122425bb815Sopenharmony_ci * Find an entry in the collection. 123425bb815Sopenharmony_ci * 124425bb815Sopenharmony_ci * @return pointer to the appropriate entry. 125425bb815Sopenharmony_ci */ 126425bb815Sopenharmony_cistatic ecma_value_t * 127425bb815Sopenharmony_ciecma_op_internal_buffer_find (ecma_collection_t *container_p, /**< internal container pointer */ 128425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 129425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< class id */ 130425bb815Sopenharmony_ci{ 131425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 132425bb815Sopenharmony_ci 133425bb815Sopenharmony_ci uint8_t entry_size = ecma_op_container_entry_size (lit_id); 134425bb815Sopenharmony_ci uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); 135425bb815Sopenharmony_ci ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); 136425bb815Sopenharmony_ci 137425bb815Sopenharmony_ci for (uint32_t i = 0; i < entry_count; i += entry_size) 138425bb815Sopenharmony_ci { 139425bb815Sopenharmony_ci ecma_value_t *entry_p = start_p + i; 140425bb815Sopenharmony_ci 141425bb815Sopenharmony_ci if (ecma_op_same_value_zero (*entry_p, key_arg)) 142425bb815Sopenharmony_ci { 143425bb815Sopenharmony_ci return entry_p; 144425bb815Sopenharmony_ci } 145425bb815Sopenharmony_ci } 146425bb815Sopenharmony_ci 147425bb815Sopenharmony_ci return NULL; 148425bb815Sopenharmony_ci} /* ecma_op_internal_buffer_find */ 149425bb815Sopenharmony_ci 150425bb815Sopenharmony_ci/** 151425bb815Sopenharmony_ci * Get the value that belongs to the key. 152425bb815Sopenharmony_ci * 153425bb815Sopenharmony_ci * Note: in case of Set containers, the values are the same as the keys. 154425bb815Sopenharmony_ci * 155425bb815Sopenharmony_ci * @return ecma value 156425bb815Sopenharmony_ci */ 157425bb815Sopenharmony_cistatic ecma_value_t 158425bb815Sopenharmony_ciecma_op_container_get_value (ecma_value_t *entry_p, /**< entry (key) pointer */ 159425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< class id */ 160425bb815Sopenharmony_ci{ 161425bb815Sopenharmony_ci JERRY_ASSERT (entry_p != NULL); 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) 164425bb815Sopenharmony_ci { 165425bb815Sopenharmony_ci return ((ecma_container_pair_t *) entry_p)->value; 166425bb815Sopenharmony_ci } 167425bb815Sopenharmony_ci 168425bb815Sopenharmony_ci return *entry_p; 169425bb815Sopenharmony_ci} /* ecma_op_container_get_value */ 170425bb815Sopenharmony_ci 171425bb815Sopenharmony_ci/** 172425bb815Sopenharmony_ci * Get the size (in ecma_value_t) of the stored entries. 173425bb815Sopenharmony_ci * 174425bb815Sopenharmony_ci * @return size of the entries. 175425bb815Sopenharmony_ci */ 176425bb815Sopenharmony_ciuint8_t 177425bb815Sopenharmony_ciecma_op_container_entry_size (lit_magic_string_id_t lit_id) /**< class id */ 178425bb815Sopenharmony_ci{ 179425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL) 180425bb815Sopenharmony_ci { 181425bb815Sopenharmony_ci return ECMA_CONTAINER_PAIR_SIZE; 182425bb815Sopenharmony_ci } 183425bb815Sopenharmony_ci 184425bb815Sopenharmony_ci return ECMA_CONTAINER_VALUE_SIZE; 185425bb815Sopenharmony_ci} /* ecma_op_container_entry_size */ 186425bb815Sopenharmony_ci 187425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) 188425bb815Sopenharmony_ci/** 189425bb815Sopenharmony_ci * Release the entries in the WeakSet container. 190425bb815Sopenharmony_ci */ 191425bb815Sopenharmony_cistatic void 192425bb815Sopenharmony_ciecma_op_container_free_weakset_entries (ecma_object_t *object_p, /**< object pointer */ 193425bb815Sopenharmony_ci ecma_collection_t *container_p) /** internal buffer pointer */ 194425bb815Sopenharmony_ci{ 195425bb815Sopenharmony_ci JERRY_ASSERT (object_p != NULL); 196425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 197425bb815Sopenharmony_ci 198425bb815Sopenharmony_ci uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); 199425bb815Sopenharmony_ci ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); 200425bb815Sopenharmony_ci 201425bb815Sopenharmony_ci for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) 202425bb815Sopenharmony_ci { 203425bb815Sopenharmony_ci ecma_value_t *entry_p = start_p + i; 204425bb815Sopenharmony_ci 205425bb815Sopenharmony_ci if (ecma_is_value_empty (*entry_p)) 206425bb815Sopenharmony_ci { 207425bb815Sopenharmony_ci continue; 208425bb815Sopenharmony_ci } 209425bb815Sopenharmony_ci 210425bb815Sopenharmony_ci ecma_op_container_unref_weak (ecma_get_object_from_value (*entry_p), ecma_make_object_value (object_p)); 211425bb815Sopenharmony_ci ecma_op_container_remove_weak_entry (object_p, *entry_p); 212425bb815Sopenharmony_ci 213425bb815Sopenharmony_ci *entry_p = ECMA_VALUE_EMPTY; 214425bb815Sopenharmony_ci } 215425bb815Sopenharmony_ci} /* ecma_op_container_free_weakset_entries */ 216425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */ 217425bb815Sopenharmony_ci 218425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) 219425bb815Sopenharmony_ci/** 220425bb815Sopenharmony_ci * Release the entries in the WeakMap container. 221425bb815Sopenharmony_ci */ 222425bb815Sopenharmony_cistatic void 223425bb815Sopenharmony_ciecma_op_container_free_weakmap_entries (ecma_object_t *object_p, /**< object pointer */ 224425bb815Sopenharmony_ci ecma_collection_t *container_p) /**< internal buffer pointer */ 225425bb815Sopenharmony_ci{ 226425bb815Sopenharmony_ci JERRY_ASSERT (object_p != NULL); 227425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 228425bb815Sopenharmony_ci 229425bb815Sopenharmony_ci uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); 230425bb815Sopenharmony_ci ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); 231425bb815Sopenharmony_ci 232425bb815Sopenharmony_ci for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) 233425bb815Sopenharmony_ci { 234425bb815Sopenharmony_ci ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); 235425bb815Sopenharmony_ci 236425bb815Sopenharmony_ci if (ecma_is_value_empty (entry_p->key)) 237425bb815Sopenharmony_ci { 238425bb815Sopenharmony_ci continue; 239425bb815Sopenharmony_ci } 240425bb815Sopenharmony_ci 241425bb815Sopenharmony_ci ecma_op_container_unref_weak (ecma_get_object_from_value (entry_p->key), ecma_make_object_value (object_p)); 242425bb815Sopenharmony_ci ecma_op_container_remove_weak_entry (object_p, entry_p->key); 243425bb815Sopenharmony_ci 244425bb815Sopenharmony_ci ecma_free_value_if_not_object (entry_p->value); 245425bb815Sopenharmony_ci 246425bb815Sopenharmony_ci entry_p->key = ECMA_VALUE_EMPTY; 247425bb815Sopenharmony_ci entry_p->value = ECMA_VALUE_EMPTY; 248425bb815Sopenharmony_ci } 249425bb815Sopenharmony_ci} /* ecma_op_container_free_weakmap_entries */ 250425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */ 251425bb815Sopenharmony_ci 252425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_SET) 253425bb815Sopenharmony_ci/** 254425bb815Sopenharmony_ci * Release the entries in the Set container. 255425bb815Sopenharmony_ci */ 256425bb815Sopenharmony_cistatic void 257425bb815Sopenharmony_ciecma_op_container_free_set_entries (ecma_collection_t *container_p) 258425bb815Sopenharmony_ci{ 259425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 260425bb815Sopenharmony_ci 261425bb815Sopenharmony_ci uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); 262425bb815Sopenharmony_ci ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); 263425bb815Sopenharmony_ci 264425bb815Sopenharmony_ci for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE) 265425bb815Sopenharmony_ci { 266425bb815Sopenharmony_ci ecma_value_t *entry_p = start_p + i; 267425bb815Sopenharmony_ci 268425bb815Sopenharmony_ci if (ecma_is_value_empty (*entry_p)) 269425bb815Sopenharmony_ci { 270425bb815Sopenharmony_ci continue; 271425bb815Sopenharmony_ci } 272425bb815Sopenharmony_ci 273425bb815Sopenharmony_ci ecma_free_value_if_not_object (*entry_p); 274425bb815Sopenharmony_ci *entry_p = ECMA_VALUE_EMPTY; 275425bb815Sopenharmony_ci } 276425bb815Sopenharmony_ci} /* ecma_op_container_free_set_entries */ 277425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */ 278425bb815Sopenharmony_ci 279425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_MAP) 280425bb815Sopenharmony_ci/** 281425bb815Sopenharmony_ci * Release the entries in the Map container. 282425bb815Sopenharmony_ci */ 283425bb815Sopenharmony_cistatic void 284425bb815Sopenharmony_ciecma_op_container_free_map_entries (ecma_collection_t *container_p) 285425bb815Sopenharmony_ci{ 286425bb815Sopenharmony_ci JERRY_ASSERT (container_p != NULL); 287425bb815Sopenharmony_ci 288425bb815Sopenharmony_ci uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); 289425bb815Sopenharmony_ci ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); 290425bb815Sopenharmony_ci 291425bb815Sopenharmony_ci for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE) 292425bb815Sopenharmony_ci { 293425bb815Sopenharmony_ci ecma_container_pair_t *entry_p = (ecma_container_pair_t *) (start_p + i); 294425bb815Sopenharmony_ci 295425bb815Sopenharmony_ci if (ecma_is_value_empty (entry_p->key)) 296425bb815Sopenharmony_ci { 297425bb815Sopenharmony_ci continue; 298425bb815Sopenharmony_ci } 299425bb815Sopenharmony_ci 300425bb815Sopenharmony_ci ecma_free_value_if_not_object (entry_p->key); 301425bb815Sopenharmony_ci ecma_free_value_if_not_object (entry_p->value); 302425bb815Sopenharmony_ci 303425bb815Sopenharmony_ci entry_p->key = ECMA_VALUE_EMPTY; 304425bb815Sopenharmony_ci entry_p->value = ECMA_VALUE_EMPTY; 305425bb815Sopenharmony_ci } 306425bb815Sopenharmony_ci} /* ecma_op_container_free_map_entries */ 307425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */ 308425bb815Sopenharmony_ci 309425bb815Sopenharmony_ci/** 310425bb815Sopenharmony_ci * Release the internal buffer and the stored entries. 311425bb815Sopenharmony_ci */ 312425bb815Sopenharmony_civoid 313425bb815Sopenharmony_ciecma_op_container_free_entries (ecma_object_t *object_p) /**< collection object pointer */ 314425bb815Sopenharmony_ci{ 315425bb815Sopenharmony_ci JERRY_ASSERT (object_p != NULL); 316425bb815Sopenharmony_ci 317425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; 318425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 319425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 320425bb815Sopenharmony_ci 321425bb815Sopenharmony_ci switch (map_object_p->u.class_prop.class_id) 322425bb815Sopenharmony_ci { 323425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) 324425bb815Sopenharmony_ci case LIT_MAGIC_STRING_WEAKSET_UL: 325425bb815Sopenharmony_ci { 326425bb815Sopenharmony_ci ecma_op_container_free_weakset_entries (object_p, container_p); 327425bb815Sopenharmony_ci break; 328425bb815Sopenharmony_ci } 329425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */ 330425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) 331425bb815Sopenharmony_ci case LIT_MAGIC_STRING_WEAKMAP_UL: 332425bb815Sopenharmony_ci { 333425bb815Sopenharmony_ci ecma_op_container_free_weakmap_entries (object_p, container_p); 334425bb815Sopenharmony_ci break; 335425bb815Sopenharmony_ci } 336425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */ 337425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_SET) 338425bb815Sopenharmony_ci case LIT_MAGIC_STRING_SET_UL: 339425bb815Sopenharmony_ci { 340425bb815Sopenharmony_ci ecma_op_container_free_set_entries (container_p); 341425bb815Sopenharmony_ci break; 342425bb815Sopenharmony_ci } 343425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */ 344425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_MAP) 345425bb815Sopenharmony_ci case LIT_MAGIC_STRING_MAP_UL: 346425bb815Sopenharmony_ci { 347425bb815Sopenharmony_ci ecma_op_container_free_map_entries (container_p); 348425bb815Sopenharmony_ci break; 349425bb815Sopenharmony_ci } 350425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */ 351425bb815Sopenharmony_ci default: 352425bb815Sopenharmony_ci { 353425bb815Sopenharmony_ci break; 354425bb815Sopenharmony_ci } 355425bb815Sopenharmony_ci } 356425bb815Sopenharmony_ci 357425bb815Sopenharmony_ci ECMA_CONTAINER_SET_SIZE (container_p, 0); 358425bb815Sopenharmony_ci} /* ecma_op_container_free_entries */ 359425bb815Sopenharmony_ci 360425bb815Sopenharmony_ci/** 361425bb815Sopenharmony_ci * Handle calling [[Construct]] of built-in Map/Set like objects 362425bb815Sopenharmony_ci * 363425bb815Sopenharmony_ci * @return ecma value 364425bb815Sopenharmony_ci */ 365425bb815Sopenharmony_ciecma_value_t 366425bb815Sopenharmony_ciecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments list */ 367425bb815Sopenharmony_ci ecma_length_t arguments_list_len, /**< number of arguments */ 368425bb815Sopenharmony_ci lit_magic_string_id_t lit_id, /**< internal class id */ 369425bb815Sopenharmony_ci ecma_builtin_id_t proto_id) /**< prototype builtin id */ 370425bb815Sopenharmony_ci{ 371425bb815Sopenharmony_ci JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); 372425bb815Sopenharmony_ci JERRY_ASSERT (lit_id == LIT_MAGIC_STRING_MAP_UL 373425bb815Sopenharmony_ci || lit_id == LIT_MAGIC_STRING_SET_UL 374425bb815Sopenharmony_ci || lit_id == LIT_MAGIC_STRING_WEAKMAP_UL 375425bb815Sopenharmony_ci || lit_id == LIT_MAGIC_STRING_WEAKSET_UL); 376425bb815Sopenharmony_ci JERRY_ASSERT (JERRY_CONTEXT (current_new_target) != NULL); 377425bb815Sopenharmony_ci 378425bb815Sopenharmony_ci ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target), proto_id); 379425bb815Sopenharmony_ci 380425bb815Sopenharmony_ci if (JERRY_UNLIKELY (proto_p == NULL)) 381425bb815Sopenharmony_ci { 382425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 383425bb815Sopenharmony_ci } 384425bb815Sopenharmony_ci 385425bb815Sopenharmony_ci ecma_collection_t *container_p = ecma_op_create_internal_buffer (); 386425bb815Sopenharmony_ci ecma_object_t *object_p = ecma_create_object (proto_p, 387425bb815Sopenharmony_ci sizeof (ecma_extended_object_t), 388425bb815Sopenharmony_ci ECMA_OBJECT_TYPE_CLASS); 389425bb815Sopenharmony_ci ecma_deref_object (proto_p); 390425bb815Sopenharmony_ci ecma_extended_object_t *map_obj_p = (ecma_extended_object_t *) object_p; 391425bb815Sopenharmony_ci map_obj_p->u.class_prop.extra_info = ECMA_CONTAINER_FLAGS_EMPTY; 392425bb815Sopenharmony_ci map_obj_p->u.class_prop.class_id = (uint16_t) lit_id; 393425bb815Sopenharmony_ci 394425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL) 395425bb815Sopenharmony_ci { 396425bb815Sopenharmony_ci map_obj_p->u.class_prop.extra_info |= ECMA_CONTAINER_FLAGS_WEAK; 397425bb815Sopenharmony_ci } 398425bb815Sopenharmony_ci 399425bb815Sopenharmony_ci ECMA_SET_INTERNAL_VALUE_POINTER (map_obj_p->u.class_prop.u.value, container_p); 400425bb815Sopenharmony_ci 401425bb815Sopenharmony_ci ecma_value_t set_value = ecma_make_object_value (object_p); 402425bb815Sopenharmony_ci ecma_value_t result = set_value; 403425bb815Sopenharmony_ci 404425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 405425bb815Sopenharmony_ci if (arguments_list_len == 0) 406425bb815Sopenharmony_ci { 407425bb815Sopenharmony_ci return result; 408425bb815Sopenharmony_ci } 409425bb815Sopenharmony_ci 410425bb815Sopenharmony_ci ecma_value_t iterable = arguments_list_p[0]; 411425bb815Sopenharmony_ci 412425bb815Sopenharmony_ci if (ecma_is_value_undefined (iterable) || ecma_is_value_null (iterable)) 413425bb815Sopenharmony_ci { 414425bb815Sopenharmony_ci return result; 415425bb815Sopenharmony_ci } 416425bb815Sopenharmony_ci 417425bb815Sopenharmony_ci lit_magic_string_id_t adder_string_id; 418425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_MAP_UL || lit_id == LIT_MAGIC_STRING_WEAKMAP_UL) 419425bb815Sopenharmony_ci { 420425bb815Sopenharmony_ci adder_string_id = LIT_MAGIC_STRING_SET; 421425bb815Sopenharmony_ci } 422425bb815Sopenharmony_ci else 423425bb815Sopenharmony_ci { 424425bb815Sopenharmony_ci adder_string_id = LIT_MAGIC_STRING_ADD; 425425bb815Sopenharmony_ci } 426425bb815Sopenharmony_ci 427425bb815Sopenharmony_ci result = ecma_op_object_get_by_magic_id (object_p, adder_string_id); 428425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 429425bb815Sopenharmony_ci { 430425bb815Sopenharmony_ci goto cleanup_object; 431425bb815Sopenharmony_ci } 432425bb815Sopenharmony_ci 433425bb815Sopenharmony_ci if (!ecma_op_is_callable (result)) 434425bb815Sopenharmony_ci { 435425bb815Sopenharmony_ci ecma_free_value (result); 436425bb815Sopenharmony_ci result = ecma_raise_type_error (ECMA_ERR_MSG ("add/set function is not callable.")); 437425bb815Sopenharmony_ci goto cleanup_object; 438425bb815Sopenharmony_ci } 439425bb815Sopenharmony_ci 440425bb815Sopenharmony_ci ecma_object_t *adder_func_p = ecma_get_object_from_value (result); 441425bb815Sopenharmony_ci 442425bb815Sopenharmony_ci result = ecma_op_get_iterator (iterable, ECMA_VALUE_EMPTY); 443425bb815Sopenharmony_ci 444425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 445425bb815Sopenharmony_ci { 446425bb815Sopenharmony_ci goto cleanup_adder; 447425bb815Sopenharmony_ci } 448425bb815Sopenharmony_ci 449425bb815Sopenharmony_ci const ecma_value_t iter = result; 450425bb815Sopenharmony_ci 451425bb815Sopenharmony_ci while (true) 452425bb815Sopenharmony_ci { 453425bb815Sopenharmony_ci result = ecma_op_iterator_step (iter); 454425bb815Sopenharmony_ci 455425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 456425bb815Sopenharmony_ci { 457425bb815Sopenharmony_ci goto cleanup_iter; 458425bb815Sopenharmony_ci } 459425bb815Sopenharmony_ci 460425bb815Sopenharmony_ci if (ecma_is_value_false (result)) 461425bb815Sopenharmony_ci { 462425bb815Sopenharmony_ci break; 463425bb815Sopenharmony_ci } 464425bb815Sopenharmony_ci 465425bb815Sopenharmony_ci const ecma_value_t next = result; 466425bb815Sopenharmony_ci result = ecma_op_iterator_value (next); 467425bb815Sopenharmony_ci ecma_free_value (next); 468425bb815Sopenharmony_ci 469425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 470425bb815Sopenharmony_ci { 471425bb815Sopenharmony_ci goto cleanup_iter; 472425bb815Sopenharmony_ci } 473425bb815Sopenharmony_ci 474425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_SET_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL) 475425bb815Sopenharmony_ci { 476425bb815Sopenharmony_ci const ecma_value_t value = result; 477425bb815Sopenharmony_ci 478425bb815Sopenharmony_ci ecma_value_t arguments[] = { value }; 479425bb815Sopenharmony_ci result = ecma_op_function_call (adder_func_p, set_value, arguments, 1); 480425bb815Sopenharmony_ci 481425bb815Sopenharmony_ci ecma_free_value (value); 482425bb815Sopenharmony_ci } 483425bb815Sopenharmony_ci else 484425bb815Sopenharmony_ci { 485425bb815Sopenharmony_ci if (!ecma_is_value_object (result)) 486425bb815Sopenharmony_ci { 487425bb815Sopenharmony_ci ecma_free_value (result); 488425bb815Sopenharmony_ci ecma_raise_type_error (ECMA_ERR_MSG ("Iterator value is not an object.")); 489425bb815Sopenharmony_ci result = ecma_op_iterator_close (iter); 490425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result)); 491425bb815Sopenharmony_ci goto cleanup_iter; 492425bb815Sopenharmony_ci } 493425bb815Sopenharmony_ci 494425bb815Sopenharmony_ci ecma_object_t *next_object_p = ecma_get_object_from_value (result); 495425bb815Sopenharmony_ci 496425bb815Sopenharmony_ci result = ecma_op_object_get_by_uint32_index (next_object_p, 0); 497425bb815Sopenharmony_ci 498425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 499425bb815Sopenharmony_ci { 500425bb815Sopenharmony_ci ecma_deref_object (next_object_p); 501425bb815Sopenharmony_ci ecma_op_iterator_close (iter); 502425bb815Sopenharmony_ci goto cleanup_iter; 503425bb815Sopenharmony_ci } 504425bb815Sopenharmony_ci 505425bb815Sopenharmony_ci const ecma_value_t key = result; 506425bb815Sopenharmony_ci 507425bb815Sopenharmony_ci result = ecma_op_object_get_by_uint32_index (next_object_p, 1); 508425bb815Sopenharmony_ci 509425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 510425bb815Sopenharmony_ci { 511425bb815Sopenharmony_ci ecma_deref_object (next_object_p); 512425bb815Sopenharmony_ci ecma_free_value (key); 513425bb815Sopenharmony_ci ecma_op_iterator_close (iter); 514425bb815Sopenharmony_ci goto cleanup_iter; 515425bb815Sopenharmony_ci } 516425bb815Sopenharmony_ci 517425bb815Sopenharmony_ci const ecma_value_t value = result; 518425bb815Sopenharmony_ci ecma_value_t arguments[] = { key, value }; 519425bb815Sopenharmony_ci result = ecma_op_function_call (adder_func_p, set_value, arguments, 2); 520425bb815Sopenharmony_ci 521425bb815Sopenharmony_ci ecma_free_value (key); 522425bb815Sopenharmony_ci ecma_free_value (value); 523425bb815Sopenharmony_ci ecma_deref_object (next_object_p); 524425bb815Sopenharmony_ci } 525425bb815Sopenharmony_ci 526425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 527425bb815Sopenharmony_ci { 528425bb815Sopenharmony_ci ecma_op_iterator_close (iter); 529425bb815Sopenharmony_ci goto cleanup_iter; 530425bb815Sopenharmony_ci } 531425bb815Sopenharmony_ci 532425bb815Sopenharmony_ci ecma_free_value (result); 533425bb815Sopenharmony_ci } 534425bb815Sopenharmony_ci 535425bb815Sopenharmony_ci ecma_free_value (iter); 536425bb815Sopenharmony_ci ecma_deref_object (adder_func_p); 537425bb815Sopenharmony_ci return ecma_make_object_value (object_p); 538425bb815Sopenharmony_ci 539425bb815Sopenharmony_cicleanup_iter: 540425bb815Sopenharmony_ci ecma_free_value (iter); 541425bb815Sopenharmony_cicleanup_adder: 542425bb815Sopenharmony_ci ecma_deref_object (adder_func_p); 543425bb815Sopenharmony_cicleanup_object: 544425bb815Sopenharmony_ci ecma_deref_object (object_p); 545425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 546425bb815Sopenharmony_ci 547425bb815Sopenharmony_ci return result; 548425bb815Sopenharmony_ci} /* ecma_op_container_create */ 549425bb815Sopenharmony_ci 550425bb815Sopenharmony_ci/** 551425bb815Sopenharmony_ci * Get Map/Set object pointer 552425bb815Sopenharmony_ci * 553425bb815Sopenharmony_ci * Note: 554425bb815Sopenharmony_ci * If the function returns with NULL, the error object has 555425bb815Sopenharmony_ci * already set, and the caller must return with ECMA_VALUE_ERROR 556425bb815Sopenharmony_ci * 557425bb815Sopenharmony_ci * @return pointer to the Map/Set if this_arg is a valid Map/Set object 558425bb815Sopenharmony_ci * NULL otherwise 559425bb815Sopenharmony_ci */ 560425bb815Sopenharmony_cistatic ecma_extended_object_t * 561425bb815Sopenharmony_ciecma_op_container_get_object (ecma_value_t this_arg, /**< this argument */ 562425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 563425bb815Sopenharmony_ci{ 564425bb815Sopenharmony_ci if (ecma_is_value_object (this_arg)) 565425bb815Sopenharmony_ci { 566425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) ecma_get_object_from_value (this_arg); 567425bb815Sopenharmony_ci 568425bb815Sopenharmony_ci if (ecma_get_object_type ((ecma_object_t *) map_object_p) == ECMA_OBJECT_TYPE_CLASS 569425bb815Sopenharmony_ci && map_object_p->u.class_prop.class_id == lit_id) 570425bb815Sopenharmony_ci { 571425bb815Sopenharmony_ci return map_object_p; 572425bb815Sopenharmony_ci } 573425bb815Sopenharmony_ci } 574425bb815Sopenharmony_ci 575425bb815Sopenharmony_ci#if ENABLED (JERRY_ERROR_MESSAGES) 576425bb815Sopenharmony_ci ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE, 577425bb815Sopenharmony_ci "Expected a % object.", 578425bb815Sopenharmony_ci ecma_make_string_value (ecma_get_magic_string (lit_id))); 579425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ERROR_MESSAGES) */ 580425bb815Sopenharmony_ci ecma_raise_type_error (NULL); 581425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ERROR_MESSAGES) */ 582425bb815Sopenharmony_ci 583425bb815Sopenharmony_ci return NULL; 584425bb815Sopenharmony_ci} /* ecma_op_container_get_object */ 585425bb815Sopenharmony_ci 586425bb815Sopenharmony_ci/** 587425bb815Sopenharmony_ci * Returns with the size of the Map/Set object. 588425bb815Sopenharmony_ci * 589425bb815Sopenharmony_ci * @return size of the Map/Set object as ecma-value. 590425bb815Sopenharmony_ci */ 591425bb815Sopenharmony_ciecma_value_t 592425bb815Sopenharmony_ciecma_op_container_size (ecma_value_t this_arg, /**< this argument */ 593425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 594425bb815Sopenharmony_ci{ 595425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 596425bb815Sopenharmony_ci 597425bb815Sopenharmony_ci if (map_object_p == NULL) 598425bb815Sopenharmony_ci { 599425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 600425bb815Sopenharmony_ci } 601425bb815Sopenharmony_ci 602425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 603425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 604425bb815Sopenharmony_ci 605425bb815Sopenharmony_ci return ecma_make_uint32_value (ECMA_CONTAINER_GET_SIZE (container_p)); 606425bb815Sopenharmony_ci} /* ecma_op_container_size */ 607425bb815Sopenharmony_ci 608425bb815Sopenharmony_ci/** 609425bb815Sopenharmony_ci * The generic Map/WeakMap prototype object's 'get' routine 610425bb815Sopenharmony_ci * 611425bb815Sopenharmony_ci * @return ecma value 612425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 613425bb815Sopenharmony_ci */ 614425bb815Sopenharmony_ciecma_value_t 615425bb815Sopenharmony_ciecma_op_container_get (ecma_value_t this_arg, /**< this argument */ 616425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 617425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 618425bb815Sopenharmony_ci{ 619425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 620425bb815Sopenharmony_ci 621425bb815Sopenharmony_ci if (map_object_p == NULL) 622425bb815Sopenharmony_ci { 623425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 624425bb815Sopenharmony_ci } 625425bb815Sopenharmony_ci 626425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) 627425bb815Sopenharmony_ci if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL && !ecma_is_value_object (key_arg)) 628425bb815Sopenharmony_ci { 629425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 630425bb815Sopenharmony_ci } 631425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */ 632425bb815Sopenharmony_ci 633425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 634425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 635425bb815Sopenharmony_ci 636425bb815Sopenharmony_ci if (ECMA_CONTAINER_GET_SIZE (container_p) == 0) 637425bb815Sopenharmony_ci { 638425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 639425bb815Sopenharmony_ci } 640425bb815Sopenharmony_ci 641425bb815Sopenharmony_ci ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); 642425bb815Sopenharmony_ci 643425bb815Sopenharmony_ci if (entry_p == NULL) 644425bb815Sopenharmony_ci { 645425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 646425bb815Sopenharmony_ci } 647425bb815Sopenharmony_ci 648425bb815Sopenharmony_ci return ecma_copy_value (((ecma_container_pair_t *) entry_p)->value); 649425bb815Sopenharmony_ci} /* ecma_op_container_get */ 650425bb815Sopenharmony_ci 651425bb815Sopenharmony_ci/** 652425bb815Sopenharmony_ci * The generic Map/Set prototype object's 'has' routine 653425bb815Sopenharmony_ci * 654425bb815Sopenharmony_ci * @return ecma value 655425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 656425bb815Sopenharmony_ci */ 657425bb815Sopenharmony_ciecma_value_t 658425bb815Sopenharmony_ciecma_op_container_has (ecma_value_t this_arg, /**< this argument */ 659425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 660425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 661425bb815Sopenharmony_ci{ 662425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 663425bb815Sopenharmony_ci 664425bb815Sopenharmony_ci if (map_object_p == NULL) 665425bb815Sopenharmony_ci { 666425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 667425bb815Sopenharmony_ci } 668425bb815Sopenharmony_ci 669425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 670425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 671425bb815Sopenharmony_ci 672425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) 673425bb815Sopenharmony_ci if ((map_object_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0 674425bb815Sopenharmony_ci && !ecma_is_value_object (key_arg)) 675425bb815Sopenharmony_ci { 676425bb815Sopenharmony_ci return ECMA_VALUE_FALSE; 677425bb815Sopenharmony_ci } 678425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */ 679425bb815Sopenharmony_ci 680425bb815Sopenharmony_ci if (ECMA_CONTAINER_GET_SIZE (container_p) == 0) 681425bb815Sopenharmony_ci { 682425bb815Sopenharmony_ci return ECMA_VALUE_FALSE; 683425bb815Sopenharmony_ci } 684425bb815Sopenharmony_ci 685425bb815Sopenharmony_ci ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); 686425bb815Sopenharmony_ci 687425bb815Sopenharmony_ci return ecma_make_boolean_value (entry_p != NULL); 688425bb815Sopenharmony_ci} /* ecma_op_container_has */ 689425bb815Sopenharmony_ci 690425bb815Sopenharmony_ci/** 691425bb815Sopenharmony_ci * Set a weak reference from a container to a key object 692425bb815Sopenharmony_ci */ 693425bb815Sopenharmony_cistatic void 694425bb815Sopenharmony_ciecma_op_container_set_weak (ecma_object_t *const key_p, /**< key object */ 695425bb815Sopenharmony_ci ecma_extended_object_t *const container_p) /**< container */ 696425bb815Sopenharmony_ci{ 697425bb815Sopenharmony_ci if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (key_p))) 698425bb815Sopenharmony_ci { 699425bb815Sopenharmony_ci ecma_fast_array_convert_to_normal (key_p); 700425bb815Sopenharmony_ci } 701425bb815Sopenharmony_ci 702425bb815Sopenharmony_ci ecma_string_t *weak_refs_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_WEAK_REFS); 703425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (key_p, weak_refs_string_p); 704425bb815Sopenharmony_ci ecma_collection_t *refs_p; 705425bb815Sopenharmony_ci 706425bb815Sopenharmony_ci if (property_p == NULL) 707425bb815Sopenharmony_ci { 708425bb815Sopenharmony_ci ecma_property_value_t *value_p = ecma_create_named_data_property (key_p, 709425bb815Sopenharmony_ci weak_refs_string_p, 710425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_WRITABLE, 711425bb815Sopenharmony_ci &property_p); 712425bb815Sopenharmony_ci ECMA_CONVERT_DATA_PROPERTY_TO_INTERNAL_PROPERTY (property_p); 713425bb815Sopenharmony_ci refs_p = ecma_new_collection (); 714425bb815Sopenharmony_ci ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, refs_p); 715425bb815Sopenharmony_ci } 716425bb815Sopenharmony_ci else 717425bb815Sopenharmony_ci { 718425bb815Sopenharmony_ci refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, (ECMA_PROPERTY_VALUE_PTR (property_p)->value)); 719425bb815Sopenharmony_ci } 720425bb815Sopenharmony_ci 721425bb815Sopenharmony_ci const ecma_value_t container_value = ecma_make_object_value ((ecma_object_t *) container_p); 722425bb815Sopenharmony_ci for (uint32_t i = 0; i < refs_p->item_count; i++) 723425bb815Sopenharmony_ci { 724425bb815Sopenharmony_ci if (ecma_is_value_empty (refs_p->buffer_p[i])) 725425bb815Sopenharmony_ci { 726425bb815Sopenharmony_ci refs_p->buffer_p[i] = container_value; 727425bb815Sopenharmony_ci return; 728425bb815Sopenharmony_ci } 729425bb815Sopenharmony_ci } 730425bb815Sopenharmony_ci 731425bb815Sopenharmony_ci ecma_collection_push_back (refs_p, container_value); 732425bb815Sopenharmony_ci} /* ecma_op_container_set_weak */ 733425bb815Sopenharmony_ci 734425bb815Sopenharmony_ci/** 735425bb815Sopenharmony_ci * Helper method for the Map.prototype.set and Set.prototype.add methods to swap the sign of the given value if needed 736425bb815Sopenharmony_ci * 737425bb815Sopenharmony_ci * See also: 738425bb815Sopenharmony_ci * ECMA-262 v6, 23.2.3.1 step 6 739425bb815Sopenharmony_ci * ECMA-262 v6, 23.1.3.9 step 6 740425bb815Sopenharmony_ci * 741425bb815Sopenharmony_ci * @return ecma value 742425bb815Sopenharmony_ci */ 743425bb815Sopenharmony_cistatic ecma_value_t 744425bb815Sopenharmony_ciecma_op_container_set_noramlize_zero (ecma_value_t this_arg) /*< this arg */ 745425bb815Sopenharmony_ci{ 746425bb815Sopenharmony_ci if (ecma_is_value_number (this_arg)) 747425bb815Sopenharmony_ci { 748425bb815Sopenharmony_ci ecma_number_t number_value = ecma_get_number_from_value (this_arg); 749425bb815Sopenharmony_ci 750425bb815Sopenharmony_ci if (JERRY_UNLIKELY (ecma_number_is_zero (number_value) && ecma_number_is_negative (number_value))) 751425bb815Sopenharmony_ci { 752425bb815Sopenharmony_ci return ecma_make_integer_value (0); 753425bb815Sopenharmony_ci } 754425bb815Sopenharmony_ci } 755425bb815Sopenharmony_ci 756425bb815Sopenharmony_ci return this_arg; 757425bb815Sopenharmony_ci} /* ecma_op_container_set_noramlize_zero */ 758425bb815Sopenharmony_ci 759425bb815Sopenharmony_ci/** 760425bb815Sopenharmony_ci * The generic Map prototype object's 'set' and Set prototype object's 'add' routine 761425bb815Sopenharmony_ci * 762425bb815Sopenharmony_ci * @return ecma value 763425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 764425bb815Sopenharmony_ci */ 765425bb815Sopenharmony_ciecma_value_t 766425bb815Sopenharmony_ciecma_op_container_set (ecma_value_t this_arg, /**< this argument */ 767425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 768425bb815Sopenharmony_ci ecma_value_t value_arg, /**< value argument */ 769425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 770425bb815Sopenharmony_ci{ 771425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 772425bb815Sopenharmony_ci 773425bb815Sopenharmony_ci if (map_object_p == NULL) 774425bb815Sopenharmony_ci { 775425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 776425bb815Sopenharmony_ci } 777425bb815Sopenharmony_ci 778425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 779425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 780425bb815Sopenharmony_ci 781425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) 782425bb815Sopenharmony_ci if ((map_object_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0 783425bb815Sopenharmony_ci && !ecma_is_value_object (key_arg)) 784425bb815Sopenharmony_ci { 785425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Key must be an object")); 786425bb815Sopenharmony_ci } 787425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */ 788425bb815Sopenharmony_ci 789425bb815Sopenharmony_ci ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); 790425bb815Sopenharmony_ci 791425bb815Sopenharmony_ci if (entry_p == NULL) 792425bb815Sopenharmony_ci { 793425bb815Sopenharmony_ci ecma_op_internal_buffer_append (container_p, 794425bb815Sopenharmony_ci ecma_op_container_set_noramlize_zero (key_arg), 795425bb815Sopenharmony_ci value_arg, 796425bb815Sopenharmony_ci lit_id); 797425bb815Sopenharmony_ci 798425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) 799425bb815Sopenharmony_ci if ((map_object_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0) 800425bb815Sopenharmony_ci { 801425bb815Sopenharmony_ci ecma_object_t *key_p = ecma_get_object_from_value (key_arg); 802425bb815Sopenharmony_ci ecma_op_container_set_weak (key_p, map_object_p); 803425bb815Sopenharmony_ci } 804425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */ 805425bb815Sopenharmony_ci } 806425bb815Sopenharmony_ci else 807425bb815Sopenharmony_ci { 808425bb815Sopenharmony_ci ecma_op_internal_buffer_update (entry_p, ecma_op_container_set_noramlize_zero (value_arg), lit_id); 809425bb815Sopenharmony_ci } 810425bb815Sopenharmony_ci 811425bb815Sopenharmony_ci ecma_ref_object ((ecma_object_t *) map_object_p); 812425bb815Sopenharmony_ci return this_arg; 813425bb815Sopenharmony_ci} /* ecma_op_container_set */ 814425bb815Sopenharmony_ci 815425bb815Sopenharmony_ci/** 816425bb815Sopenharmony_ci * The generic Map/Set prototype object's 'forEach' routine 817425bb815Sopenharmony_ci * 818425bb815Sopenharmony_ci * @return ecma value 819425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 820425bb815Sopenharmony_ci */ 821425bb815Sopenharmony_ciecma_value_t 822425bb815Sopenharmony_ciecma_op_container_foreach (ecma_value_t this_arg, /**< this argument */ 823425bb815Sopenharmony_ci ecma_value_t predicate, /**< callback function */ 824425bb815Sopenharmony_ci ecma_value_t predicate_this_arg, /**< this argument for 825425bb815Sopenharmony_ci * invoke predicate */ 826425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 827425bb815Sopenharmony_ci{ 828425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 829425bb815Sopenharmony_ci 830425bb815Sopenharmony_ci if (map_object_p == NULL) 831425bb815Sopenharmony_ci { 832425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 833425bb815Sopenharmony_ci } 834425bb815Sopenharmony_ci 835425bb815Sopenharmony_ci if (!ecma_op_is_callable (predicate)) 836425bb815Sopenharmony_ci { 837425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); 838425bb815Sopenharmony_ci } 839425bb815Sopenharmony_ci 840425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_object (predicate)); 841425bb815Sopenharmony_ci ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); 842425bb815Sopenharmony_ci ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; 843425bb815Sopenharmony_ci 844425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 845425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 846425bb815Sopenharmony_ci 847425bb815Sopenharmony_ci uint8_t entry_size = ecma_op_container_entry_size (lit_id); 848425bb815Sopenharmony_ci 849425bb815Sopenharmony_ci for (uint32_t i = 0; i < ECMA_CONTAINER_ENTRY_COUNT (container_p); i += entry_size) 850425bb815Sopenharmony_ci { 851425bb815Sopenharmony_ci ecma_value_t *entry_p = ECMA_CONTAINER_START (container_p) + i; 852425bb815Sopenharmony_ci 853425bb815Sopenharmony_ci if (ecma_is_value_empty (*entry_p)) 854425bb815Sopenharmony_ci { 855425bb815Sopenharmony_ci continue; 856425bb815Sopenharmony_ci } 857425bb815Sopenharmony_ci 858425bb815Sopenharmony_ci ecma_value_t key_arg = *entry_p; 859425bb815Sopenharmony_ci ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id); 860425bb815Sopenharmony_ci 861425bb815Sopenharmony_ci ecma_value_t call_args[] = { value_arg, key_arg, this_arg }; 862425bb815Sopenharmony_ci ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); 863425bb815Sopenharmony_ci 864425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (call_value)) 865425bb815Sopenharmony_ci { 866425bb815Sopenharmony_ci ret_value = call_value; 867425bb815Sopenharmony_ci break; 868425bb815Sopenharmony_ci } 869425bb815Sopenharmony_ci 870425bb815Sopenharmony_ci ecma_free_value (call_value); 871425bb815Sopenharmony_ci } 872425bb815Sopenharmony_ci 873425bb815Sopenharmony_ci return ret_value; 874425bb815Sopenharmony_ci} /* ecma_op_container_foreach */ 875425bb815Sopenharmony_ci 876425bb815Sopenharmony_ci/** 877425bb815Sopenharmony_ci * The Map/Set prototype object's 'clear' routine 878425bb815Sopenharmony_ci * 879425bb815Sopenharmony_ci * @return ecma value 880425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 881425bb815Sopenharmony_ci */ 882425bb815Sopenharmony_ciecma_value_t 883425bb815Sopenharmony_ciecma_op_container_clear (ecma_value_t this_arg, /**< this argument */ 884425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 885425bb815Sopenharmony_ci{ 886425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 887425bb815Sopenharmony_ci 888425bb815Sopenharmony_ci if (map_object_p == NULL) 889425bb815Sopenharmony_ci { 890425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 891425bb815Sopenharmony_ci } 892425bb815Sopenharmony_ci 893425bb815Sopenharmony_ci ecma_op_container_free_entries ((ecma_object_t *) map_object_p); 894425bb815Sopenharmony_ci 895425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 896425bb815Sopenharmony_ci} /* ecma_op_container_clear */ 897425bb815Sopenharmony_ci 898425bb815Sopenharmony_ci/** 899425bb815Sopenharmony_ci * The generic Map/Set prototype object's 'delete' routine 900425bb815Sopenharmony_ci * 901425bb815Sopenharmony_ci * @return ecma value 902425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 903425bb815Sopenharmony_ci */ 904425bb815Sopenharmony_ciecma_value_t 905425bb815Sopenharmony_ciecma_op_container_delete (ecma_value_t this_arg, /**< this argument */ 906425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 907425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 908425bb815Sopenharmony_ci{ 909425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 910425bb815Sopenharmony_ci 911425bb815Sopenharmony_ci if (map_object_p == NULL) 912425bb815Sopenharmony_ci { 913425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 914425bb815Sopenharmony_ci } 915425bb815Sopenharmony_ci 916425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 917425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 918425bb815Sopenharmony_ci 919425bb815Sopenharmony_ci ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); 920425bb815Sopenharmony_ci 921425bb815Sopenharmony_ci if (entry_p == NULL) 922425bb815Sopenharmony_ci { 923425bb815Sopenharmony_ci return ECMA_VALUE_FALSE; 924425bb815Sopenharmony_ci } 925425bb815Sopenharmony_ci 926425bb815Sopenharmony_ci ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id); 927425bb815Sopenharmony_ci return ECMA_VALUE_TRUE; 928425bb815Sopenharmony_ci} /* ecma_op_container_delete */ 929425bb815Sopenharmony_ci 930425bb815Sopenharmony_ci/** 931425bb815Sopenharmony_ci * The generic WeakMap/WeakSet prototype object's 'delete' routine 932425bb815Sopenharmony_ci * 933425bb815Sopenharmony_ci * @return ecma value 934425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 935425bb815Sopenharmony_ci */ 936425bb815Sopenharmony_ciecma_value_t 937425bb815Sopenharmony_ciecma_op_container_delete_weak (ecma_value_t this_arg, /**< this argument */ 938425bb815Sopenharmony_ci ecma_value_t key_arg, /**< key argument */ 939425bb815Sopenharmony_ci lit_magic_string_id_t lit_id) /**< internal class id */ 940425bb815Sopenharmony_ci{ 941425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 942425bb815Sopenharmony_ci 943425bb815Sopenharmony_ci if (map_object_p == NULL) 944425bb815Sopenharmony_ci { 945425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 946425bb815Sopenharmony_ci } 947425bb815Sopenharmony_ci 948425bb815Sopenharmony_ci if (!ecma_is_value_object (key_arg)) 949425bb815Sopenharmony_ci { 950425bb815Sopenharmony_ci return ECMA_VALUE_FALSE; 951425bb815Sopenharmony_ci } 952425bb815Sopenharmony_ci 953425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 954425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 955425bb815Sopenharmony_ci 956425bb815Sopenharmony_ci ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id); 957425bb815Sopenharmony_ci 958425bb815Sopenharmony_ci if (entry_p == NULL) 959425bb815Sopenharmony_ci { 960425bb815Sopenharmony_ci return ECMA_VALUE_FALSE; 961425bb815Sopenharmony_ci } 962425bb815Sopenharmony_ci 963425bb815Sopenharmony_ci ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id); 964425bb815Sopenharmony_ci 965425bb815Sopenharmony_ci ecma_object_t *key_object_p = ecma_get_object_from_value (key_arg); 966425bb815Sopenharmony_ci ecma_op_container_unref_weak (key_object_p, ecma_make_object_value ((ecma_object_t *) map_object_p)); 967425bb815Sopenharmony_ci 968425bb815Sopenharmony_ci return ECMA_VALUE_TRUE; 969425bb815Sopenharmony_ci} /* ecma_op_container_delete_weak */ 970425bb815Sopenharmony_ci 971425bb815Sopenharmony_ci/** 972425bb815Sopenharmony_ci * Helper function to remove a weak reference to an object. 973425bb815Sopenharmony_ci * 974425bb815Sopenharmony_ci * @return ecma value 975425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 976425bb815Sopenharmony_ci */ 977425bb815Sopenharmony_civoid 978425bb815Sopenharmony_ciecma_op_container_unref_weak (ecma_object_t *object_p, /**< this argument */ 979425bb815Sopenharmony_ci ecma_value_t ref_holder) /**< key argument */ 980425bb815Sopenharmony_ci{ 981425bb815Sopenharmony_ci ecma_string_t *weak_refs_string_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_WEAK_REFS); 982425bb815Sopenharmony_ci 983425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (object_p, weak_refs_string_p); 984425bb815Sopenharmony_ci JERRY_ASSERT (property_p != NULL); 985425bb815Sopenharmony_ci 986425bb815Sopenharmony_ci ecma_collection_t *refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 987425bb815Sopenharmony_ci ECMA_PROPERTY_VALUE_PTR (property_p)->value); 988425bb815Sopenharmony_ci for (uint32_t i = 0; i < refs_p->item_count; i++) 989425bb815Sopenharmony_ci { 990425bb815Sopenharmony_ci if (refs_p->buffer_p[i] == ref_holder) 991425bb815Sopenharmony_ci { 992425bb815Sopenharmony_ci refs_p->buffer_p[i] = ECMA_VALUE_EMPTY; 993425bb815Sopenharmony_ci break; 994425bb815Sopenharmony_ci } 995425bb815Sopenharmony_ci } 996425bb815Sopenharmony_ci} /* ecma_op_container_unref_weak */ 997425bb815Sopenharmony_ci 998425bb815Sopenharmony_ci/** 999425bb815Sopenharmony_ci * Helper function to remove a key/value pair from a weak container object 1000425bb815Sopenharmony_ci */ 1001425bb815Sopenharmony_civoid 1002425bb815Sopenharmony_ciecma_op_container_remove_weak_entry (ecma_object_t *object_p, /**< internal container object */ 1003425bb815Sopenharmony_ci ecma_value_t key_arg) /**< key */ 1004425bb815Sopenharmony_ci{ 1005425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p; 1006425bb815Sopenharmony_ci 1007425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 1008425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 1009425bb815Sopenharmony_ci 1010425bb815Sopenharmony_ci ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, map_object_p->u.class_prop.class_id); 1011425bb815Sopenharmony_ci 1012425bb815Sopenharmony_ci JERRY_ASSERT (entry_p != NULL); 1013425bb815Sopenharmony_ci 1014425bb815Sopenharmony_ci ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, map_object_p->u.class_prop.class_id); 1015425bb815Sopenharmony_ci} /* ecma_op_container_remove_weak_entry */ 1016425bb815Sopenharmony_ci 1017425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 1018425bb815Sopenharmony_ci 1019425bb815Sopenharmony_ci/** 1020425bb815Sopenharmony_ci * The Create{Set, Map}Iterator Abstract operation 1021425bb815Sopenharmony_ci * 1022425bb815Sopenharmony_ci * See also: 1023425bb815Sopenharmony_ci * ECMA-262 v6, 23.1.5.1 1024425bb815Sopenharmony_ci * ECMA-262 v6, 23.2.5.1 1025425bb815Sopenharmony_ci * 1026425bb815Sopenharmony_ci * Note: 1027425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 1028425bb815Sopenharmony_ci * 1029425bb815Sopenharmony_ci * @return Map/Set iterator object, if success 1030425bb815Sopenharmony_ci * error - otherwise 1031425bb815Sopenharmony_ci */ 1032425bb815Sopenharmony_ciecma_value_t 1033425bb815Sopenharmony_ciecma_op_container_create_iterator (ecma_value_t this_arg, /**< this argument */ 1034425bb815Sopenharmony_ci uint8_t type, /**< any combination of 1035425bb815Sopenharmony_ci * ecma_iterator_type_t bits */ 1036425bb815Sopenharmony_ci lit_magic_string_id_t lit_id, /**< internal class id */ 1037425bb815Sopenharmony_ci ecma_builtin_id_t proto_id, /**< prototype builtin id */ 1038425bb815Sopenharmony_ci ecma_pseudo_array_type_t iterator_type) /**< type of the iterator */ 1039425bb815Sopenharmony_ci{ 1040425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = ecma_op_container_get_object (this_arg, lit_id); 1041425bb815Sopenharmony_ci 1042425bb815Sopenharmony_ci if (map_object_p == NULL) 1043425bb815Sopenharmony_ci { 1044425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 1045425bb815Sopenharmony_ci } 1046425bb815Sopenharmony_ci 1047425bb815Sopenharmony_ci return ecma_op_create_iterator_object (this_arg, 1048425bb815Sopenharmony_ci ecma_builtin_get (proto_id), 1049425bb815Sopenharmony_ci (uint8_t) iterator_type, 1050425bb815Sopenharmony_ci type); 1051425bb815Sopenharmony_ci} /* ecma_op_container_create_iterator */ 1052425bb815Sopenharmony_ci 1053425bb815Sopenharmony_ci/** 1054425bb815Sopenharmony_ci * Get the index of the iterator object. 1055425bb815Sopenharmony_ci * 1056425bb815Sopenharmony_ci * @return index of the iterator. 1057425bb815Sopenharmony_ci */ 1058425bb815Sopenharmony_cistatic uint32_t 1059425bb815Sopenharmony_ciecma_op_iterator_get_index (ecma_object_t *iter_obj_p) /**< iterator object pointer */ 1060425bb815Sopenharmony_ci{ 1061425bb815Sopenharmony_ci uint32_t index = ((ecma_extended_object_t *) iter_obj_p)->u.pseudo_array.u1.iterator_index; 1062425bb815Sopenharmony_ci 1063425bb815Sopenharmony_ci if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT)) 1064425bb815Sopenharmony_ci { 1065425bb815Sopenharmony_ci ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); 1066425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p); 1067425bb815Sopenharmony_ci ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 1068425bb815Sopenharmony_ci 1069425bb815Sopenharmony_ci return (uint32_t) (ecma_get_number_from_value (value_p->value)); 1070425bb815Sopenharmony_ci } 1071425bb815Sopenharmony_ci 1072425bb815Sopenharmony_ci return index; 1073425bb815Sopenharmony_ci} /* ecma_op_iterator_get_index */ 1074425bb815Sopenharmony_ci 1075425bb815Sopenharmony_ci/** 1076425bb815Sopenharmony_ci * Set the index of the iterator object. 1077425bb815Sopenharmony_ci */ 1078425bb815Sopenharmony_cistatic void 1079425bb815Sopenharmony_ciecma_op_iterator_set_index (ecma_object_t *iter_obj_p, /**< iterator object pointer */ 1080425bb815Sopenharmony_ci uint32_t index) /* iterator index to set */ 1081425bb815Sopenharmony_ci{ 1082425bb815Sopenharmony_ci if (JERRY_UNLIKELY (index >= ECMA_ITERATOR_INDEX_LIMIT)) 1083425bb815Sopenharmony_ci { 1084425bb815Sopenharmony_ci /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] 1085425bb815Sopenharmony_ci property is stored as an internal property */ 1086425bb815Sopenharmony_ci ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); 1087425bb815Sopenharmony_ci ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p); 1088425bb815Sopenharmony_ci ecma_property_value_t *value_p; 1089425bb815Sopenharmony_ci 1090425bb815Sopenharmony_ci if (property_p == NULL) 1091425bb815Sopenharmony_ci { 1092425bb815Sopenharmony_ci value_p = ecma_create_named_data_property (iter_obj_p, prop_name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p); 1093425bb815Sopenharmony_ci value_p->value = ecma_make_uint32_value (index); 1094425bb815Sopenharmony_ci } 1095425bb815Sopenharmony_ci else 1096425bb815Sopenharmony_ci { 1097425bb815Sopenharmony_ci value_p = ECMA_PROPERTY_VALUE_PTR (property_p); 1098425bb815Sopenharmony_ci value_p->value = ecma_make_uint32_value (index); 1099425bb815Sopenharmony_ci } 1100425bb815Sopenharmony_ci } 1101425bb815Sopenharmony_ci else 1102425bb815Sopenharmony_ci { 1103425bb815Sopenharmony_ci ((ecma_extended_object_t *) iter_obj_p)->u.pseudo_array.u1.iterator_index = (uint16_t) index; 1104425bb815Sopenharmony_ci } 1105425bb815Sopenharmony_ci} /* ecma_op_iterator_set_index */ 1106425bb815Sopenharmony_ci 1107425bb815Sopenharmony_ci/** 1108425bb815Sopenharmony_ci * The %{Set, Map}IteratorPrototype% object's 'next' routine 1109425bb815Sopenharmony_ci * 1110425bb815Sopenharmony_ci * See also: 1111425bb815Sopenharmony_ci * ECMA-262 v6, 23.1.5.2.1 1112425bb815Sopenharmony_ci * ECMA-262 v6, 23.2.5.2.1 1113425bb815Sopenharmony_ci * 1114425bb815Sopenharmony_ci * Note: 1115425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 1116425bb815Sopenharmony_ci * 1117425bb815Sopenharmony_ci * @return iterator result object, if success 1118425bb815Sopenharmony_ci * error - otherwise 1119425bb815Sopenharmony_ci */ 1120425bb815Sopenharmony_ciecma_value_t 1121425bb815Sopenharmony_ciecma_op_container_iterator_next (ecma_value_t this_val, /**< this argument */ 1122425bb815Sopenharmony_ci ecma_pseudo_array_type_t iterator_type) /**< type of the iterator */ 1123425bb815Sopenharmony_ci{ 1124425bb815Sopenharmony_ci if (!ecma_is_value_object (this_val)) 1125425bb815Sopenharmony_ci { 1126425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an object.")); 1127425bb815Sopenharmony_ci } 1128425bb815Sopenharmony_ci 1129425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (this_val); 1130425bb815Sopenharmony_ci ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; 1131425bb815Sopenharmony_ci 1132425bb815Sopenharmony_ci if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_PSEUDO_ARRAY 1133425bb815Sopenharmony_ci || ext_obj_p->u.pseudo_array.type != iterator_type) 1134425bb815Sopenharmony_ci { 1135425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an iterator.")); 1136425bb815Sopenharmony_ci } 1137425bb815Sopenharmony_ci 1138425bb815Sopenharmony_ci ecma_value_t iterated_value = ext_obj_p->u.pseudo_array.u2.iterated_value; 1139425bb815Sopenharmony_ci 1140425bb815Sopenharmony_ci if (ecma_is_value_empty (iterated_value)) 1141425bb815Sopenharmony_ci { 1142425bb815Sopenharmony_ci return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); 1143425bb815Sopenharmony_ci } 1144425bb815Sopenharmony_ci 1145425bb815Sopenharmony_ci ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) (ecma_get_object_from_value (iterated_value)); 1146425bb815Sopenharmony_ci lit_magic_string_id_t lit_id = map_object_p->u.class_prop.class_id; 1147425bb815Sopenharmony_ci 1148425bb815Sopenharmony_ci ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, 1149425bb815Sopenharmony_ci map_object_p->u.class_prop.u.value); 1150425bb815Sopenharmony_ci uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p); 1151425bb815Sopenharmony_ci uint32_t index = ecma_op_iterator_get_index (obj_p); 1152425bb815Sopenharmony_ci 1153425bb815Sopenharmony_ci if (index == entry_count) 1154425bb815Sopenharmony_ci { 1155425bb815Sopenharmony_ci ext_obj_p->u.pseudo_array.u2.iterated_value = ECMA_VALUE_EMPTY; 1156425bb815Sopenharmony_ci 1157425bb815Sopenharmony_ci return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); 1158425bb815Sopenharmony_ci } 1159425bb815Sopenharmony_ci 1160425bb815Sopenharmony_ci uint8_t entry_size = ecma_op_container_entry_size (lit_id); 1161425bb815Sopenharmony_ci uint8_t iterator_kind = ext_obj_p->u.pseudo_array.extra_info; 1162425bb815Sopenharmony_ci ecma_value_t *start_p = ECMA_CONTAINER_START (container_p); 1163425bb815Sopenharmony_ci ecma_value_t ret_value = ECMA_VALUE_UNDEFINED; 1164425bb815Sopenharmony_ci 1165425bb815Sopenharmony_ci for (uint32_t i = index; i < entry_count; i += entry_size) 1166425bb815Sopenharmony_ci { 1167425bb815Sopenharmony_ci ecma_value_t *entry_p = start_p + i; 1168425bb815Sopenharmony_ci 1169425bb815Sopenharmony_ci if (ecma_is_value_empty (*entry_p)) 1170425bb815Sopenharmony_ci { 1171425bb815Sopenharmony_ci if (i == (entry_count - entry_size)) 1172425bb815Sopenharmony_ci { 1173425bb815Sopenharmony_ci ret_value = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); 1174425bb815Sopenharmony_ci break; 1175425bb815Sopenharmony_ci } 1176425bb815Sopenharmony_ci 1177425bb815Sopenharmony_ci continue; 1178425bb815Sopenharmony_ci } 1179425bb815Sopenharmony_ci 1180425bb815Sopenharmony_ci ecma_op_iterator_set_index (obj_p, i + entry_size); 1181425bb815Sopenharmony_ci 1182425bb815Sopenharmony_ci ecma_value_t key_arg = *entry_p; 1183425bb815Sopenharmony_ci ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id); 1184425bb815Sopenharmony_ci 1185425bb815Sopenharmony_ci if (iterator_kind == ECMA_ITERATOR_KEYS) 1186425bb815Sopenharmony_ci { 1187425bb815Sopenharmony_ci ret_value = ecma_create_iter_result_object (key_arg, ECMA_VALUE_FALSE); 1188425bb815Sopenharmony_ci } 1189425bb815Sopenharmony_ci else if (iterator_kind == ECMA_ITERATOR_VALUES) 1190425bb815Sopenharmony_ci { 1191425bb815Sopenharmony_ci ret_value = ecma_create_iter_result_object (value_arg, ECMA_VALUE_FALSE); 1192425bb815Sopenharmony_ci } 1193425bb815Sopenharmony_ci else 1194425bb815Sopenharmony_ci { 1195425bb815Sopenharmony_ci JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_KEYS_VALUES); 1196425bb815Sopenharmony_ci 1197425bb815Sopenharmony_ci ecma_value_t entry_array_value; 1198425bb815Sopenharmony_ci entry_array_value = ecma_create_array_from_iter_element (value_arg, key_arg); 1199425bb815Sopenharmony_ci 1200425bb815Sopenharmony_ci ret_value = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE); 1201425bb815Sopenharmony_ci ecma_free_value (entry_array_value); 1202425bb815Sopenharmony_ci } 1203425bb815Sopenharmony_ci 1204425bb815Sopenharmony_ci break; 1205425bb815Sopenharmony_ci } 1206425bb815Sopenharmony_ci 1207425bb815Sopenharmony_ci return ret_value; 1208425bb815Sopenharmony_ci} /* ecma_op_container_iterator_next */ 1209425bb815Sopenharmony_ci 1210425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 1211425bb815Sopenharmony_ci 1212425bb815Sopenharmony_ci/** 1213425bb815Sopenharmony_ci * @} 1214425bb815Sopenharmony_ci * @} 1215425bb815Sopenharmony_ci */ 1216425bb815Sopenharmony_ci 1217425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */ 1218