Use array based storage in container objects (#3600)
Currently, collections use object based solutions for storing elements and iterating on them. If an element is deleted and re-inserted, the storage position is the same as before so the iteration order is wrong. This patch replaces the object based storage with an array based solution that helps to store and iterate elements as expected. JerryScript-DCO-1.0-Signed-off-by: Roland Takacs rtakacs@inf.u-szeged.hu
This commit is contained in:
@@ -35,6 +35,325 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a new internal buffer.
|
||||
*
|
||||
* Note:
|
||||
* The first element of the collection tracks the size of the buffer.
|
||||
* ECMA_VALUE_EMPTY values are not calculated into the size.
|
||||
*
|
||||
* @return pointer to the internal buffer
|
||||
*/
|
||||
static inline ecma_collection_t *
|
||||
ecma_op_create_internal_buffer (void)
|
||||
{
|
||||
ecma_collection_t *collection_p = ecma_new_collection ();
|
||||
ecma_collection_push_back (collection_p, (ecma_value_t) 0);
|
||||
|
||||
return collection_p;
|
||||
} /* ecma_op_create_internal_buffer */
|
||||
|
||||
/**
|
||||
* Append values to the internal buffer.
|
||||
*/
|
||||
static void
|
||||
ecma_op_internal_buffer_append (ecma_collection_t *container_p, /**< internal container pointer */
|
||||
ecma_value_t key_arg, /**< key argument */
|
||||
ecma_value_t value_arg, /**< value argument */
|
||||
lit_magic_string_id_t lit_id) /**< class id */
|
||||
{
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
|
||||
ecma_collection_push_back (container_p, ecma_copy_value_if_not_object (key_arg));
|
||||
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL)
|
||||
{
|
||||
ecma_collection_push_back (container_p, ecma_copy_value_if_not_object (value_arg));
|
||||
}
|
||||
|
||||
ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) + 1);
|
||||
} /* ecma_op_internal_buffer_append */
|
||||
|
||||
/**
|
||||
* Update the value of a given entry.
|
||||
*/
|
||||
static inline void
|
||||
ecma_op_internal_buffer_update (ecma_value_t *entry_p, /**< entry pointer */
|
||||
ecma_value_t value_arg, /**< value argument */
|
||||
lit_magic_string_id_t lit_id) /**< class id */
|
||||
{
|
||||
JERRY_ASSERT (entry_p != NULL);
|
||||
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL)
|
||||
{
|
||||
ecma_free_value_if_not_object (((ecma_container_pair_t *) entry_p)->value);
|
||||
|
||||
((ecma_container_pair_t *) entry_p)->value = ecma_copy_value_if_not_object (value_arg);
|
||||
}
|
||||
} /* ecma_op_internal_buffer_update */
|
||||
|
||||
/**
|
||||
* Delete element from the internal buffer.
|
||||
*/
|
||||
static void
|
||||
ecma_op_internal_buffer_delete (ecma_collection_t *container_p, /**< internal container pointer */
|
||||
ecma_container_pair_t *entry_p, /**< entry pointer */
|
||||
lit_magic_string_id_t lit_id) /**< class id */
|
||||
{
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
JERRY_ASSERT (entry_p != NULL);
|
||||
|
||||
ecma_free_value_if_not_object (entry_p->key);
|
||||
entry_p->key = ECMA_VALUE_EMPTY;
|
||||
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL)
|
||||
{
|
||||
ecma_free_value_if_not_object (entry_p->value);
|
||||
entry_p->value = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
ECMA_CONTAINER_SET_SIZE (container_p, ECMA_CONTAINER_GET_SIZE (container_p) - 1);
|
||||
} /* ecma_op_internal_buffer_delete */
|
||||
|
||||
/**
|
||||
* Find an entry in the collection.
|
||||
*
|
||||
* @return pointer to the appropriate entry.
|
||||
*/
|
||||
static ecma_value_t *
|
||||
ecma_op_internal_buffer_find (ecma_collection_t *container_p, /**< internal container pointer */
|
||||
ecma_value_t key_arg, /**< key argument */
|
||||
lit_magic_string_id_t lit_id) /**< class id */
|
||||
{
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
|
||||
uint8_t entry_size = ecma_op_container_entry_size (lit_id);
|
||||
uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p);
|
||||
ecma_value_t *start_p = ECMA_CONTAINER_START (container_p);
|
||||
|
||||
for (uint32_t i = 0; i < entry_count; i += entry_size)
|
||||
{
|
||||
ecma_value_t *entry_p = start_p + i;
|
||||
|
||||
if (ecma_op_same_value_zero (*entry_p, key_arg))
|
||||
{
|
||||
return entry_p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* ecma_op_internal_buffer_find */
|
||||
|
||||
/**
|
||||
* Get the value that belongs to the key.
|
||||
*
|
||||
* Note: in case of Set containers, the values are the same as the keys.
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_op_container_get_value (ecma_value_t *entry_p, /**< entry (key) pointer */
|
||||
lit_magic_string_id_t lit_id) /**< class id */
|
||||
{
|
||||
JERRY_ASSERT (entry_p != NULL);
|
||||
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL)
|
||||
{
|
||||
return ((ecma_container_pair_t *) entry_p)->value;
|
||||
}
|
||||
|
||||
return *entry_p;
|
||||
} /* ecma_op_container_get_value */
|
||||
|
||||
/**
|
||||
* Get the size (in ecma_value_t) of the stored entries.
|
||||
*
|
||||
* @return size of the entries.
|
||||
*/
|
||||
uint8_t
|
||||
ecma_op_container_entry_size (lit_magic_string_id_t lit_id) /**< class id */
|
||||
{
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_MAP_UL)
|
||||
{
|
||||
return ECMA_CONTAINER_PAIR_SIZE;
|
||||
}
|
||||
|
||||
return ECMA_CONTAINER_VALUE_SIZE;
|
||||
} /* ecma_op_container_entry_size */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
|
||||
/**
|
||||
* Release the entries in the WeakSet container.
|
||||
*/
|
||||
static void
|
||||
ecma_op_container_free_weakset_entries (ecma_object_t *object_p, /**< object pointer */
|
||||
ecma_collection_t *container_p) /** internal buffer pointer */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
|
||||
uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p);
|
||||
ecma_value_t *start_p = ECMA_CONTAINER_START (container_p);
|
||||
|
||||
for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE)
|
||||
{
|
||||
ecma_value_t *entry_p = start_p + i;
|
||||
|
||||
if (ecma_is_value_empty (*entry_p))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_op_container_unref_weak (ecma_get_object_from_value (*entry_p), ecma_make_object_value (object_p));
|
||||
ecma_op_container_remove_weak_entry (object_p, *entry_p);
|
||||
|
||||
*entry_p = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
} /* ecma_op_container_free_weakset_entries */
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
|
||||
/**
|
||||
* Release the entries in the WeakMap container.
|
||||
*/
|
||||
static void
|
||||
ecma_op_container_free_weakmap_entries (ecma_object_t *object_p, /**< object pointer */
|
||||
ecma_collection_t *container_p) /**< internal buffer pointer */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
|
||||
uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p);
|
||||
ecma_value_t *start_p = ECMA_CONTAINER_START (container_p);
|
||||
|
||||
for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE)
|
||||
{
|
||||
ecma_container_pair_t *entry_p = (ecma_container_pair_t *)(start_p + i);
|
||||
|
||||
if (ecma_is_value_empty (entry_p->key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_op_container_unref_weak (ecma_get_object_from_value (entry_p->key), ecma_make_object_value (object_p));
|
||||
ecma_op_container_remove_weak_entry (object_p, entry_p->key);
|
||||
|
||||
ecma_free_value_if_not_object (entry_p->value);
|
||||
|
||||
entry_p->key = ECMA_VALUE_EMPTY;
|
||||
entry_p->value = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
} /* ecma_op_container_free_weakmap_entries */
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_SET)
|
||||
/**
|
||||
* Release the entries in the Set container.
|
||||
*/
|
||||
static void
|
||||
ecma_op_container_free_set_entries (ecma_collection_t *container_p)
|
||||
{
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
|
||||
uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p);
|
||||
ecma_value_t *start_p = ECMA_CONTAINER_START (container_p);
|
||||
|
||||
for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_VALUE_SIZE)
|
||||
{
|
||||
ecma_value_t *entry_p = start_p + i;
|
||||
|
||||
if (ecma_is_value_empty (*entry_p))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_free_value_if_not_object (*entry_p);
|
||||
*entry_p = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
} /* ecma_op_container_free_set_entries */
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
/**
|
||||
* Release the entries in the Map container.
|
||||
*/
|
||||
static void
|
||||
ecma_op_container_free_map_entries (ecma_collection_t *container_p)
|
||||
{
|
||||
JERRY_ASSERT (container_p != NULL);
|
||||
|
||||
uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p);
|
||||
ecma_value_t *start_p = ECMA_CONTAINER_START (container_p);
|
||||
|
||||
for (uint32_t i = 0; i < entry_count; i += ECMA_CONTAINER_PAIR_SIZE)
|
||||
{
|
||||
ecma_container_pair_t *entry_p = (ecma_container_pair_t *)(start_p + i);
|
||||
|
||||
if (ecma_is_value_empty (entry_p->key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_free_value_if_not_object (entry_p->key);
|
||||
ecma_free_value_if_not_object (entry_p->value);
|
||||
|
||||
entry_p->key = ECMA_VALUE_EMPTY;
|
||||
entry_p->value = ECMA_VALUE_EMPTY;
|
||||
}
|
||||
} /* ecma_op_container_free_map_entries */
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
|
||||
/**
|
||||
* Release the internal buffer and the stored entries.
|
||||
*/
|
||||
void
|
||||
ecma_op_container_free_entries (ecma_object_t *object_p) /**< collection object pointer */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p;
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
switch (map_object_p->u.class_prop.class_id)
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
|
||||
case LIT_MAGIC_STRING_WEAKSET_UL:
|
||||
{
|
||||
ecma_op_container_free_weakset_entries (object_p, container_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP)
|
||||
case LIT_MAGIC_STRING_WEAKMAP_UL:
|
||||
{
|
||||
ecma_op_container_free_weakmap_entries (object_p, container_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_SET)
|
||||
case LIT_MAGIC_STRING_SET_UL:
|
||||
{
|
||||
ecma_op_container_free_set_entries (container_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SET) */
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
case LIT_MAGIC_STRING_MAP_UL:
|
||||
{
|
||||
ecma_op_container_free_map_entries (container_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ECMA_CONTAINER_SET_SIZE (container_p, 0);
|
||||
} /* ecma_op_container_free_entries */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in Map/Set like objects
|
||||
*
|
||||
@@ -52,29 +371,22 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
|
||||
|| lit_id == LIT_MAGIC_STRING_WEAKMAP_UL
|
||||
|| lit_id == LIT_MAGIC_STRING_WEAKSET_UL);
|
||||
|
||||
ecma_object_t *internal_object_p = ecma_create_object (NULL,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *container_p = (ecma_extended_object_t *) internal_object_p;
|
||||
container_p->u.class_prop.class_id = LIT_INTERNAL_MAGIC_STRING_CONTAINER;
|
||||
container_p->u.class_prop.extra_info = ECMA_CONTAINER_FLAGS_EMPTY;
|
||||
container_p->u.class_prop.u.length = 0;
|
||||
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL)
|
||||
{
|
||||
container_p->u.class_prop.extra_info |= ECMA_CONTAINER_FLAGS_WEAK;
|
||||
}
|
||||
ecma_collection_t *container_p = ecma_op_create_internal_buffer ();
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (proto_id),
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *map_obj_p = (ecma_extended_object_t *) object_p;
|
||||
map_obj_p->u.class_prop.extra_info = ECMA_CONTAINER_FLAGS_EMPTY;
|
||||
map_obj_p->u.class_prop.class_id = (uint16_t) lit_id;
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (map_obj_p->u.class_prop.u.value, container_p);
|
||||
|
||||
ecma_deref_object (internal_object_p);
|
||||
if (lit_id == LIT_MAGIC_STRING_WEAKMAP_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL)
|
||||
{
|
||||
map_obj_p->u.class_prop.extra_info |= ECMA_CONTAINER_FLAGS_WEAK;
|
||||
}
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (map_obj_p->u.class_prop.u.value, container_p);
|
||||
|
||||
ecma_value_t set_value = ecma_make_object_value (object_p);
|
||||
ecma_value_t result = set_value;
|
||||
@@ -261,37 +573,6 @@ ecma_op_container_get_object (ecma_value_t this_arg, /**< this argument */
|
||||
return NULL;
|
||||
} /* ecma_op_container_get_object */
|
||||
|
||||
/**
|
||||
* Creates a property key for the internal object from the given argument
|
||||
*
|
||||
* Note:
|
||||
* This operation does not increase the reference counter of strings and symbols
|
||||
*
|
||||
* @return property key
|
||||
*/
|
||||
static ecma_string_t *
|
||||
ecma_op_container_to_key (ecma_value_t key_arg) /**< key argument */
|
||||
{
|
||||
if (ecma_is_value_prop_name (key_arg))
|
||||
{
|
||||
ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key_arg);
|
||||
ecma_ref_ecma_string (prop_name_p);
|
||||
return prop_name_p;
|
||||
}
|
||||
|
||||
if (ecma_is_value_integer_number (key_arg))
|
||||
{
|
||||
ecma_integer_value_t integer = ecma_get_integer_from_value (key_arg);
|
||||
|
||||
if (JERRY_LIKELY (integer > 0 && integer <= ECMA_DIRECT_STRING_MAX_IMM))
|
||||
{
|
||||
return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_ECMA_INTEGER, (uintptr_t) integer);
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_new_map_key_string (key_arg);
|
||||
} /* ecma_op_container_to_key */
|
||||
|
||||
/**
|
||||
* Returns with the size of the Map/Set object.
|
||||
*
|
||||
@@ -308,9 +589,10 @@ ecma_op_container_size (ecma_value_t this_arg, /**< this argument */
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_extended_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
return ecma_make_uint32_value (container_p->u.class_prop.u.length);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
return ecma_make_uint32_value (ECMA_CONTAINER_GET_SIZE (container_p));
|
||||
} /* ecma_op_container_size */
|
||||
|
||||
/**
|
||||
@@ -338,26 +620,22 @@ ecma_op_container_get (ecma_value_t this_arg, /**< this argument */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) */
|
||||
|
||||
ecma_extended_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_extended_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
if (container_p->u.class_prop.u.length == 0)
|
||||
if (ECMA_CONTAINER_GET_SIZE (container_p) == 0)
|
||||
{
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_op_container_to_key (key_arg);
|
||||
ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id);
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property ((ecma_object_t *) container_p, prop_name_p);
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
|
||||
if (property_p == NULL || ecma_is_value_empty (ECMA_PROPERTY_VALUE_PTR (property_p)->value))
|
||||
if (entry_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
return ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
|
||||
return ecma_copy_value (((ecma_container_pair_t *) entry_p)->value);
|
||||
} /* ecma_op_container_get */
|
||||
|
||||
/**
|
||||
@@ -378,30 +656,25 @@ ecma_op_container_has (ecma_value_t this_arg, /**< this argument */
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_extended_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
|
||||
if ((container_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0
|
||||
if ((map_object_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0
|
||||
&& !ecma_is_value_object (key_arg))
|
||||
{
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
|
||||
|
||||
if (container_p->u.class_prop.u.length == 0)
|
||||
if (ECMA_CONTAINER_GET_SIZE (container_p) == 0)
|
||||
{
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_op_container_to_key (key_arg);
|
||||
ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id);
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property ((ecma_object_t *) container_p, prop_name_p);
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
|
||||
return ecma_make_boolean_value (property_p != NULL
|
||||
&& !ecma_is_value_empty (ECMA_PROPERTY_VALUE_PTR (property_p)->value));
|
||||
return ecma_make_boolean_value (entry_p != NULL);
|
||||
} /* ecma_op_container_has */
|
||||
|
||||
/**
|
||||
@@ -467,52 +740,36 @@ ecma_op_container_set (ecma_value_t this_arg, /**< this argument */
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_extended_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
|
||||
if ((container_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0
|
||||
if ((map_object_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0
|
||||
&& !ecma_is_value_object (key_arg))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Key must be an object"));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_op_container_to_key (key_arg);
|
||||
ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id);
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property ((ecma_object_t *) container_p, prop_name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
if (entry_p == NULL)
|
||||
{
|
||||
ecma_property_value_t *value_p = ecma_create_named_data_property ((ecma_object_t *) container_p,
|
||||
prop_name_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
value_p->value = ecma_copy_value_if_not_object (value_arg);
|
||||
container_p->u.class_prop.u.length++;
|
||||
ecma_op_internal_buffer_append (container_p, key_arg, value_arg, lit_id);
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
|
||||
if ((container_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0)
|
||||
if ((map_object_p->u.class_prop.extra_info & ECMA_CONTAINER_FLAGS_WEAK) != 0)
|
||||
{
|
||||
ecma_object_t *key_p = ecma_get_object_from_value (key_arg);
|
||||
ecma_op_container_set_weak (key_p, container_p);
|
||||
ecma_op_container_set_weak (key_p, map_object_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKMAP) || ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ecma_is_value_empty (ECMA_PROPERTY_VALUE_PTR (property_p)->value))
|
||||
{
|
||||
container_p->u.class_prop.u.length++;
|
||||
}
|
||||
|
||||
ecma_named_data_property_assign_value ((ecma_object_t *) container_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
value_arg);
|
||||
ecma_op_internal_buffer_update (entry_p, value_arg, lit_id);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
ecma_ref_object ((ecma_object_t *) map_object_p);
|
||||
return this_arg;
|
||||
} /* ecma_op_container_set */
|
||||
@@ -544,59 +801,28 @@ ecma_op_container_foreach (ecma_value_t this_arg, /**< this argument */
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (predicate));
|
||||
ecma_object_t *func_object_p = ecma_get_object_from_value (predicate);
|
||||
|
||||
ecma_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
ecma_collection_t *props_p = ecma_op_object_get_property_names (container_p, ECMA_LIST_NO_OPTS);
|
||||
|
||||
ecma_value_t *buffer_p = props_p->buffer_p;
|
||||
|
||||
ecma_value_t ret_value = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
ecma_ref_object (container_p);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
for (uint32_t i = 0; i < props_p->item_count; i++)
|
||||
uint8_t entry_size = ecma_op_container_entry_size (lit_id);
|
||||
|
||||
for (uint32_t i = 0; i < ECMA_CONTAINER_ENTRY_COUNT (container_p); i += entry_size)
|
||||
{
|
||||
ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[i]);
|
||||
ecma_property_t *property_p = ecma_find_named_property (container_p, prop_name_p);
|
||||
JERRY_ASSERT (property_p != NULL);
|
||||
ecma_value_t *entry_p = ECMA_CONTAINER_START (container_p) + i;
|
||||
|
||||
if (ecma_is_value_empty (ECMA_PROPERTY_VALUE_PTR (property_p)->value))
|
||||
if (ecma_is_value_empty (*entry_p))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_value_t value = ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
|
||||
ecma_value_t key_arg;
|
||||
|
||||
if (lit_id == LIT_MAGIC_STRING_SET_UL)
|
||||
{
|
||||
key_arg = value;
|
||||
}
|
||||
else if (ecma_prop_name_is_map_key (prop_name_p))
|
||||
{
|
||||
key_arg = ((ecma_extended_string_t *) prop_name_p)->u.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ECMA_IS_DIRECT_STRING (prop_name_p)
|
||||
&& ECMA_GET_DIRECT_STRING_TYPE (prop_name_p) == ECMA_DIRECT_STRING_ECMA_INTEGER)
|
||||
{
|
||||
key_arg = ecma_make_uint32_value ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
key_arg = buffer_p[i];
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t call_args[] = { value, key_arg, this_arg };
|
||||
ecma_value_t key_arg = *entry_p;
|
||||
ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id);
|
||||
|
||||
ecma_value_t call_args[] = { value_arg, key_arg, this_arg };
|
||||
ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3);
|
||||
|
||||
ecma_free_value (value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (call_value))
|
||||
{
|
||||
ret_value = call_value;
|
||||
@@ -606,9 +832,6 @@ ecma_op_container_foreach (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_free_value (call_value);
|
||||
}
|
||||
|
||||
ecma_deref_object (container_p);
|
||||
ecma_collection_free (props_p);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_container_foreach */
|
||||
|
||||
@@ -629,18 +852,7 @@ ecma_op_container_clear (ecma_value_t this_arg, /**< this argument */
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_object_t *internal_object_p = ecma_create_object (NULL,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *container_p = (ecma_extended_object_t *) internal_object_p;
|
||||
container_p->u.class_prop.class_id = LIT_INTERNAL_MAGIC_STRING_CONTAINER;
|
||||
container_p->u.class_prop.extra_info = ECMA_CONTAINER_FLAGS_EMPTY;
|
||||
container_p->u.class_prop.u.length = 0;
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (map_object_p->u.class_prop.u.value, internal_object_p);
|
||||
|
||||
ecma_deref_object (internal_object_p);
|
||||
ecma_op_container_free_entries ((ecma_object_t *) map_object_p);
|
||||
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
} /* ecma_op_container_clear */
|
||||
@@ -663,25 +875,17 @@ ecma_op_container_delete (ecma_value_t this_arg, /**< this argument */
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_extended_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_op_container_to_key (key_arg);
|
||||
ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id);
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property ((ecma_object_t *) container_p, prop_name_p);
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
|
||||
if (property_p == NULL || ecma_is_value_empty (ECMA_PROPERTY_VALUE_PTR (property_p)->value))
|
||||
if (entry_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
|
||||
ecma_named_data_property_assign_value ((ecma_object_t *) container_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
ECMA_VALUE_EMPTY);
|
||||
container_p->u.class_prop.u.length--;
|
||||
|
||||
ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id);
|
||||
return ECMA_VALUE_TRUE;
|
||||
} /* ecma_op_container_delete */
|
||||
|
||||
@@ -708,28 +912,21 @@ ecma_op_container_delete_weak (ecma_value_t this_arg, /**< this argument */
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_extended_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_op_container_to_key (key_arg);
|
||||
ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, lit_id);
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property ((ecma_object_t *) container_p, prop_name_p);
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
if (entry_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
|
||||
ecma_delete_property ((ecma_object_t *) container_p, ECMA_PROPERTY_VALUE_PTR (property_p));
|
||||
ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, lit_id);
|
||||
|
||||
ecma_object_t *internal_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_object_t *key_object_p = ecma_get_object_from_value (key_arg);
|
||||
ecma_op_container_unref_weak (key_object_p, ecma_make_object_value (internal_obj_p));
|
||||
ecma_op_container_unref_weak (key_object_p, ecma_make_object_value ((ecma_object_t *) map_object_p));
|
||||
|
||||
container_p->u.class_prop.u.length--;
|
||||
return ECMA_VALUE_TRUE;
|
||||
} /* ecma_op_container_delete_weak */
|
||||
|
||||
@@ -764,18 +961,19 @@ ecma_op_container_unref_weak (ecma_object_t *object_p, /**< this argument */
|
||||
* Helper function to remove a key/value pair from a weak container object
|
||||
*/
|
||||
void
|
||||
ecma_op_container_remove_weak_entry (ecma_object_t *container_p, /**< internal container object */
|
||||
ecma_op_container_remove_weak_entry (ecma_object_t *object_p, /**< internal container object */
|
||||
ecma_value_t key_arg) /**< key */
|
||||
{
|
||||
ecma_string_t *prop_name_p = ecma_new_map_key_string (key_arg);
|
||||
ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (container_p, prop_name_p);
|
||||
JERRY_ASSERT (property_p != NULL);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
ecma_value_t *entry_p = ecma_op_internal_buffer_find (container_p, key_arg, map_object_p->u.class_prop.class_id);
|
||||
|
||||
ecma_delete_property (container_p, ECMA_PROPERTY_VALUE_PTR (property_p));
|
||||
((ecma_extended_object_t *) container_p)->u.class_prop.u.length--;
|
||||
JERRY_ASSERT (entry_p != NULL);
|
||||
|
||||
ecma_op_internal_buffer_delete (container_p, (ecma_container_pair_t *) entry_p, map_object_p->u.class_prop.class_id);
|
||||
} /* ecma_op_container_remove_weak_entry */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
@@ -814,6 +1012,60 @@ ecma_op_container_create_iterator (ecma_value_t this_arg, /**< this argument */
|
||||
type);
|
||||
} /* ecma_op_container_create_iterator */
|
||||
|
||||
/**
|
||||
* Get the index of the iterator object.
|
||||
*
|
||||
* @return index of the iterator.
|
||||
*/
|
||||
static uint32_t
|
||||
ecma_op_iterator_get_index (ecma_object_t *iter_obj_p) /**< iterator object pointer */
|
||||
{
|
||||
uint32_t index = ((ecma_extended_object_t *) iter_obj_p)->u.pseudo_array.u1.iterator_index;
|
||||
|
||||
if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT))
|
||||
{
|
||||
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX);
|
||||
ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p);
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
return (uint32_t) (ecma_get_number_from_value (value_p->value));
|
||||
}
|
||||
|
||||
return index;
|
||||
} /* ecma_op_iterator_get_index */
|
||||
|
||||
/**
|
||||
* Set the index of the iterator object.
|
||||
*/
|
||||
static void
|
||||
ecma_op_iterator_set_index (ecma_object_t *iter_obj_p, /**< iterator object pointer */
|
||||
uint32_t index) /* iterator index to set */
|
||||
{
|
||||
if (JERRY_UNLIKELY (index >= ECMA_ITERATOR_INDEX_LIMIT))
|
||||
{
|
||||
/* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]]
|
||||
property is stored as an internal property */
|
||||
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX);
|
||||
ecma_property_t *property_p = ecma_find_named_property (iter_obj_p, prop_name_p);
|
||||
ecma_property_value_t *value_p;
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
value_p = ecma_create_named_data_property (iter_obj_p, prop_name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p);
|
||||
value_p->value = ecma_make_uint32_value (index);
|
||||
}
|
||||
else
|
||||
{
|
||||
value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
value_p->value = ecma_make_uint32_value (index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
((ecma_extended_object_t *) iter_obj_p)->u.pseudo_array.u1.iterator_index = (uint16_t) index;
|
||||
}
|
||||
} /* ecma_op_iterator_set_index */
|
||||
|
||||
/**
|
||||
* The %{Set, Map}IteratorPrototype% object's 'next' routine
|
||||
*
|
||||
@@ -853,97 +1105,44 @@ ecma_op_container_iterator_next (ecma_value_t this_val, /**< this argument */
|
||||
}
|
||||
|
||||
ecma_extended_object_t *map_object_p = (ecma_extended_object_t *) (ecma_get_object_from_value (iterated_value));
|
||||
lit_magic_string_id_t lit_id = map_object_p->u.class_prop.class_id;
|
||||
|
||||
ecma_object_t *internal_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
ecma_collection_t *props_p = ecma_op_object_get_property_names (internal_obj_p, ECMA_LIST_NO_OPTS);
|
||||
ecma_collection_t *container_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
map_object_p->u.class_prop.u.value);
|
||||
uint32_t entry_count = ECMA_CONTAINER_ENTRY_COUNT (container_p);
|
||||
uint32_t index = ecma_op_iterator_get_index (obj_p);
|
||||
|
||||
uint32_t length = props_p->item_count;
|
||||
uint32_t index = ext_obj_p->u.pseudo_array.u1.iterator_index;
|
||||
|
||||
if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT))
|
||||
{
|
||||
/* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]]
|
||||
property is stored as an internal property */
|
||||
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX);
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (obj_p, prop_name_p);
|
||||
ecma_property_value_t *value_p;
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
value_p = ecma_create_named_data_property (obj_p, prop_name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p);
|
||||
value_p->value = ecma_make_uint32_value (index);
|
||||
}
|
||||
else
|
||||
{
|
||||
value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
index = (uint32_t) (ecma_get_number_from_value (value_p->value) + 1);
|
||||
value_p->value = ecma_make_uint32_value (index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_obj_p->u.pseudo_array.u1.iterator_index++;
|
||||
}
|
||||
|
||||
if (index >= length)
|
||||
if (index == entry_count)
|
||||
{
|
||||
ext_obj_p->u.pseudo_array.u2.iterated_value = ECMA_VALUE_EMPTY;
|
||||
ecma_collection_free (props_p);
|
||||
|
||||
return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
|
||||
}
|
||||
|
||||
uint8_t entry_size = ecma_op_container_entry_size (lit_id);
|
||||
uint8_t iterator_kind = ext_obj_p->u.pseudo_array.extra_info;
|
||||
|
||||
ecma_value_t *buffer_p = props_p->buffer_p;
|
||||
|
||||
ecma_value_t *start_p = ECMA_CONTAINER_START (container_p);
|
||||
ecma_value_t ret_value = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
for (uint32_t i = 0; i < props_p->item_count; i++)
|
||||
for (uint32_t i = index; i < entry_count; i += entry_size)
|
||||
{
|
||||
if (index > 0)
|
||||
{
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
ecma_value_t *entry_p = start_p + i;
|
||||
|
||||
ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[i]);
|
||||
ecma_property_t *property_p = ecma_find_named_property (internal_obj_p, prop_name_p);
|
||||
JERRY_ASSERT (property_p != NULL);
|
||||
|
||||
if (ecma_is_value_empty (ECMA_PROPERTY_VALUE_PTR (property_p)->value))
|
||||
if (ecma_is_value_empty (*entry_p))
|
||||
{
|
||||
if (i == props_p->item_count - 1)
|
||||
if (i == (entry_count - entry_size))
|
||||
{
|
||||
ret_value = ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_value_t value = ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
|
||||
ecma_value_t key_arg;
|
||||
ecma_op_iterator_set_index (obj_p, i + entry_size);
|
||||
|
||||
if (iterator_type == ECMA_PSEUDO_SET_ITERATOR)
|
||||
{
|
||||
key_arg = value;
|
||||
}
|
||||
else if (ecma_prop_name_is_map_key (prop_name_p))
|
||||
{
|
||||
key_arg = ((ecma_extended_string_t *) prop_name_p)->u.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ECMA_IS_DIRECT_STRING (prop_name_p)
|
||||
&& ECMA_GET_DIRECT_STRING_TYPE (prop_name_p) == ECMA_DIRECT_STRING_ECMA_INTEGER)
|
||||
{
|
||||
key_arg = ecma_make_uint32_value ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
key_arg = buffer_p[i];
|
||||
}
|
||||
}
|
||||
ecma_value_t key_arg = *entry_p;
|
||||
ecma_value_t value_arg = ecma_op_container_get_value (entry_p, lit_id);
|
||||
|
||||
if (iterator_kind == ECMA_ITERATOR_KEYS)
|
||||
{
|
||||
@@ -951,25 +1150,22 @@ ecma_op_container_iterator_next (ecma_value_t this_val, /**< this argument */
|
||||
}
|
||||
else if (iterator_kind == ECMA_ITERATOR_VALUES)
|
||||
{
|
||||
ret_value = ecma_create_iter_result_object (value, ECMA_VALUE_FALSE);
|
||||
ret_value = ecma_create_iter_result_object (value_arg, ECMA_VALUE_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (iterator_kind == ECMA_ITERATOR_KEYS_VALUES);
|
||||
|
||||
ecma_value_t entry_array_value;
|
||||
entry_array_value = ecma_create_array_from_iter_element (value, key_arg);
|
||||
entry_array_value = ecma_create_array_from_iter_element (value_arg, key_arg);
|
||||
|
||||
ret_value = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE);
|
||||
ecma_free_value (entry_array_value);
|
||||
}
|
||||
|
||||
ecma_free_value (value);
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_collection_free (props_p);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_container_iterator_next */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user