Use ecma-collection in JSON.

The simple list data structure has been replaced with ecma-collection in the JSON object.

JerryScript-DCO-1.0-Signed-off-by: Roland Takacs rtakacs.u-szeged@partner.samsung.com
This commit is contained in:
Roland Takacs
2015-08-06 15:41:17 +02:00
parent a19dd0523e
commit ff580ca33e
3 changed files with 153 additions and 256 deletions
@@ -26,173 +26,72 @@
#include "ecma-builtin-helpers.h" #include "ecma-builtin-helpers.h"
#include "lit-char-helpers.h" #include "lit-char-helpers.h"
#define LIST_BLOCK_SIZE 256UL
/** /**
* Allocate memory for elements. * Check the object value existance in the collection.
* *
* @return pointer to current position of the allocated memory. * Used by:
*/ * - ecma_builtin_json_object step 1
void ** * - ecma_builtin_json_array step 1
realloc_list (list_ctx_t *ctx_p) /**< list context */
{
size_t old_block_size = static_cast<size_t> (ctx_p->block_end_p - ctx_p->block_start_p);
size_t new_block_size = old_block_size + LIST_BLOCK_SIZE;
size_t current_ptr_offset = static_cast<size_t> (ctx_p->current_p - ctx_p->block_start_p);
void **new_block_start_p = (void **) mem_heap_alloc_block (new_block_size, MEM_HEAP_ALLOC_SHORT_TERM);
if (ctx_p->current_p)
{
memcpy (new_block_start_p, ctx_p->block_start_p, static_cast<size_t> (current_ptr_offset));
mem_heap_free_block (ctx_p->block_start_p);
}
ctx_p->block_start_p = new_block_start_p;
ctx_p->block_end_p = new_block_start_p + new_block_size;
ctx_p->current_p = new_block_start_p + current_ptr_offset;
return ctx_p->current_p;
} /* realloc_list */
/**
* Append element to the list.
*/
void
list_append (list_ctx_t *ctx_p, /**< list context */
void *element_p) /**< element that should be stored */
{
void **current_p = ctx_p->current_p;
if (current_p + 1 > ctx_p->block_end_p)
{
current_p = realloc_list (ctx_p);
}
*current_p = element_p;
ctx_p->current_p++;
} /* list_append */
/**
* Check the element existance in the list.
* *
* @return true if the list already has the value. * @return true, if the object is already in the collection.
*/ */
bool bool
list_has_element (list_ctx_t *ctx_p, /**< list context */ ecma_has_object_value_in_collection (ecma_collection_header_t *collection_p, /**< collection */
void *element_p) /**< element that should be checked */ ecma_value_t object_value) /**< object value */
{ {
for (void **current_p = ctx_p->block_start_p; JERRY_ASSERT (ecma_is_value_object (object_value));
current_p < ctx_p->current_p;
current_p++) ecma_object_t *obj_p = ecma_get_object_from_value (object_value);
ecma_collection_iterator_t iterator;
ecma_collection_iterator_init (&iterator, collection_p);
while (ecma_collection_iterator_next (&iterator))
{ {
if (*current_p == element_p) ecma_value_t value = *iterator.current_value_p;
ecma_object_t *current_p = ecma_get_object_from_value (value);
if (current_p == obj_p)
{ {
return true; return true;
} }
} }
return false; return false;
} /* list_has_element */ } /* ecma_has_object_value_in_collection */
/** /**
* Check the element existance in the list for ecma strings. * Check the string value existance in the collection.
* *
* @return true if the list already has the value. * Used by:
* - ecma_builtin_json_stringify step 4.b.ii.5
*
* @return true, if the string is already in the collection.
*/ */
bool bool
list_has_ecma_string_element (list_ctx_t *ctx_p, /**< list context */ ecma_has_string_value_in_collection (ecma_collection_header_t *collection_p, /**< collection */
ecma_string_t *string_p) /**< element that should be checked */ ecma_value_t string_value) /**< string value */
{ {
for (void **current_p = ctx_p->block_start_p; JERRY_ASSERT (ecma_is_value_string (string_value));
current_p < ctx_p->current_p;
current_p++) ecma_string_t *string_p = ecma_get_string_from_value (string_value);
ecma_collection_iterator_t iterator;
ecma_collection_iterator_init (&iterator, collection_p);
while (ecma_collection_iterator_next (&iterator))
{ {
if (ecma_compare_ecma_strings ((ecma_string_t *) *current_p, string_p)) ecma_value_t value = *iterator.current_value_p;
ecma_string_t *current_p = ecma_get_string_from_value (value);
if (ecma_compare_ecma_strings (current_p, string_p))
{ {
return true; return true;
} }
} }
return false; return false;
} /* list_has_element */ } /* ecma_has_string_value_in_collection*/
/**
* Check the state of the list allocation.
*
* @return true if the list is already allocated.
*/
static bool
list_is_allocated (list_ctx_t *ctx_p) /**< list context */
{
return ctx_p->block_start_p < ctx_p->block_end_p;
} /* list_is_allocated */
/**
* Check if the list is empty.
*
* @return true if the list is empty.
*/
bool
list_is_empty (list_ctx_t *ctx_p)
{
return ctx_p->block_start_p == ctx_p->current_p;
} /* list_is_empty */
/**
* Set the current memory position to the previous element.
*/
void
list_remove_last_element (list_ctx_t *ctx_p) /**< list context */
{
if (list_is_empty (ctx_p))
{
return;
}
*ctx_p->current_p = NULL;
ctx_p->current_p--;
} /* list_remove_last_element */
/**
* Free the allocated list.
*/
void
free_list (list_ctx_t *ctx_p) /**< list context */
{
if (!list_is_allocated (ctx_p))
{
return;
}
mem_heap_free_block (ctx_p->block_start_p);
ctx_p->block_start_p = NULL;
ctx_p->block_end_p = NULL;
ctx_p->current_p = NULL;
} /* free_list */
/**
* Free the stored ecma string elements and the list.
*/
void
free_list_with_ecma_string_content (list_ctx_t *ctx_p) /**< list context */
{
if (!list_is_allocated (ctx_p))
{
return;
}
for (void **current_p = ctx_p->block_start_p;
current_p < ctx_p->current_p;
current_p++)
{
ecma_deref_ecma_string ((ecma_string_t *) *current_p);
}
free_list (ctx_p);
} /* free_list_with_ecma_string_content */
/** /**
* Common function to concatenate key-value pairs into an ecma-string. * Common function to concatenate key-value pairs into an ecma-string.
@@ -208,21 +107,27 @@ free_list_with_ecma_string_content (list_ctx_t *ctx_p) /**< list context */
* Returned value must be freed with ecma_deref_ecma_string. * Returned value must be freed with ecma_deref_ecma_string.
*/ */
ecma_string_t * ecma_string_t *
ecma_builtin_helper_json_create_separated_properties (list_ctx_t *partial_p, /**< list of key-value pairs*/ ecma_builtin_helper_json_create_separated_properties (ecma_collection_header_t *partial_p, /**< key-value pairs*/
ecma_string_t *separator_p) /**< separator*/ ecma_string_t *separator_p) /**< separator*/
{ {
ecma_string_t *properties_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_string_t *properties_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
ecma_string_t *tmp_str_p; ecma_string_t *tmp_str_p;
ecma_collection_iterator_t iterator;
ecma_collection_iterator_init (&iterator, partial_p);
uint32_t index = 0; uint32_t index = 0;
for (void **current_p = partial_p->block_start_p; while (ecma_collection_iterator_next (&iterator))
current_p < partial_p->current_p;
current_p++, index++)
{ {
ecma_value_t name_value = *iterator.current_value_p;
ecma_string_t *current_p = ecma_get_string_from_value (name_value);
if (index == 0) if (index == 0)
{ {
tmp_str_p = ecma_concat_ecma_strings (properties_str_p, (ecma_string_t *) *current_p); index++;
tmp_str_p = ecma_concat_ecma_strings (properties_str_p, current_p);
ecma_deref_ecma_string (properties_str_p); ecma_deref_ecma_string (properties_str_p);
properties_str_p = tmp_str_p; properties_str_p = tmp_str_p;
continue; continue;
@@ -232,7 +137,7 @@ ecma_builtin_helper_json_create_separated_properties (list_ctx_t *partial_p, /**
ecma_deref_ecma_string (properties_str_p); ecma_deref_ecma_string (properties_str_p);
properties_str_p = tmp_str_p; properties_str_p = tmp_str_p;
tmp_str_p = ecma_concat_ecma_strings (properties_str_p, (ecma_string_t *) *current_p); tmp_str_p = ecma_concat_ecma_strings (properties_str_p, current_p);
ecma_deref_ecma_string (properties_str_p); ecma_deref_ecma_string (properties_str_p);
properties_str_p = tmp_str_p; properties_str_p = tmp_str_p;
} }
@@ -257,8 +162,8 @@ ecma_completion_value_t
ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/ ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/
ecma_string_t *right_bracket_p, /**< right bracket*/ ecma_string_t *right_bracket_p, /**< right bracket*/
ecma_string_t *stepback_p, /**< stepback*/ ecma_string_t *stepback_p, /**< stepback*/
list_ctx_t *partial_p, /**< list of key-value pairs*/ ecma_collection_header_t *partial_p, /**< key-value pairs*/
stringify_context_t *context_p) /**< context*/ ecma_json_stringify_context_t *context_p) /**< context*/
{ {
/* 10.b */ /* 10.b */
ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR);
@@ -326,7 +231,7 @@ ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p, /
ecma_completion_value_t ecma_completion_value_t
ecma_builtin_helper_json_create_non_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/ ecma_builtin_helper_json_create_non_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/
ecma_string_t *right_bracket_p, /**< right bracket*/ ecma_string_t *right_bracket_p, /**< right bracket*/
list_ctx_t *partial_p) /**< list of key-value pairs*/ ecma_collection_header_t *partial_p) /**< key-value pairs*/
{ {
/* 10.a */ /* 10.a */
ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR);
@@ -130,45 +130,48 @@ extern ecma_completion_value_t ecma_date_get_primitive_value (ecma_value_t this_
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */ #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */
typedef struct
{
void **block_start_p;
void **block_end_p;
void **current_p;
} list_ctx_t;
typedef struct
{
list_ctx_t property_list;
list_ctx_t occurence_stack;
ecma_string_t *indent_str_p;
ecma_string_t *gap_str_p;
ecma_object_t *replacer_function_p;
} stringify_context_t;
/* ecma-builtin-helper-json.cpp */ /* ecma-builtin-helper-json.cpp */
extern void **realloc_list (list_ctx_t *ctx);
extern void list_append (list_ctx_t *ctx, void *element);
extern void free_list (list_ctx_t *ctx);
extern bool list_has_element (list_ctx_t *ctx, void *element);
extern bool list_has_ecma_string_element (list_ctx_t *ctx, ecma_string_t *string_p);
extern bool list_is_empty (list_ctx_t *ctx);
extern void list_remove_last_element (list_ctx_t *ctx);
extern void free_list_with_ecma_string_content (list_ctx_t *ctx);
extern ecma_string_t *ecma_builtin_helper_json_create_separated_properties (list_ctx_t *partial_p, /**
ecma_string_t *separator_p); * Context for JSON.stringify()
extern ecma_completion_value_t ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p, */
ecma_string_t *right_bracket_p, typedef struct
ecma_string_t *stepback_p, {
list_ctx_t *partial_p, /** Collection for property keys. */
stringify_context_t *context_p); ecma_collection_header_t *property_list_p;
extern ecma_completion_value_t ecma_builtin_helper_json_create_non_formatted_json (ecma_string_t *left_bracket_p,
ecma_string_t *right_bracket_p, /** Collection for traversing objects. */
list_ctx_t *partial_p); ecma_collection_header_t *occurence_stack_p;
/** The actual indentation text. */
ecma_string_t *indent_str_p;
/** The indentation text. */
ecma_string_t *gap_str_p;
/** The replacer function. */
ecma_object_t *replacer_function_p;
} ecma_json_stringify_context_t;
extern bool ecma_has_object_value_in_collection (ecma_collection_header_t *collection_p, ecma_value_t object_value);
extern bool ecma_has_string_value_in_collection (ecma_collection_header_t *collection_p, ecma_value_t string_value);
extern ecma_string_t *ecma_builtin_helper_json_create_hex_digit_ecma_string (uint8_t value); extern ecma_string_t *ecma_builtin_helper_json_create_hex_digit_ecma_string (uint8_t value);
extern ecma_string_t *
ecma_builtin_helper_json_create_separated_properties (ecma_collection_header_t *partial_p,
ecma_string_t *separator_p);
extern ecma_completion_value_t
ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p,
ecma_string_t *right_bracket_p,
ecma_string_t *stepback_p,
ecma_collection_header_t *partial_p,
ecma_json_stringify_context_t *context_p);
extern ecma_completion_value_t
ecma_builtin_helper_json_create_non_formatted_json (ecma_string_t *left_bracket_p,
ecma_string_t *right_bracket_p,
ecma_collection_header_t *partial_p);
/** /**
* @} * @}
* @} * @}
@@ -892,13 +892,13 @@ ecma_builtin_json_parse (ecma_value_t this_arg __attr_unused___, /**< 'this' arg
} /* ecma_builtin_json_parse */ } /* ecma_builtin_json_parse */
static ecma_completion_value_t static ecma_completion_value_t
ecma_builtin_json_str (ecma_string_t *key_p, ecma_object_t *holder_p, stringify_context_t *context_p); ecma_builtin_json_str (ecma_string_t *key_p, ecma_object_t *holder_p, ecma_json_stringify_context_t *context_p);
static ecma_completion_value_t static ecma_completion_value_t
ecma_builtin_json_object (ecma_object_t *obj_p, stringify_context_t *context_p); ecma_builtin_json_object (ecma_object_t *obj_p, ecma_json_stringify_context_t *context_p);
static ecma_completion_value_t static ecma_completion_value_t
ecma_builtin_json_array (ecma_object_t *obj_p, stringify_context_t *context_p); ecma_builtin_json_array (ecma_object_t *obj_p, ecma_json_stringify_context_t *context_p);
/** /**
* The JSON object's 'stringify' routine * The JSON object's 'stringify' routine
@@ -917,20 +917,16 @@ ecma_builtin_json_stringify (ecma_value_t this_arg __attr_unused___, /**< 'this'
{ {
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
stringify_context_t context; ecma_json_stringify_context_t context;
/* 1. */ /* 1. */
context.occurence_stack.block_start_p = NULL; context.occurence_stack_p = ecma_new_values_collection (NULL, 0, false);
context.occurence_stack.block_end_p = NULL;
context.occurence_stack.current_p = NULL;
/* 2. */ /* 2. */
context.indent_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); context.indent_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
/* 3. */ /* 3. */
context.property_list.block_start_p = NULL; context.property_list_p = ecma_new_values_collection (NULL, 0, false);
context.property_list.block_end_p = NULL;
context.property_list.current_p = NULL;
context.replacer_function_p = NULL; context.replacer_function_p = NULL;
@@ -1011,15 +1007,10 @@ ecma_builtin_json_stringify (ecma_value_t this_arg __attr_unused___, /**< 'this'
/* 4.b.ii.5 */ /* 4.b.ii.5 */
if (!ecma_is_value_undefined (item)) if (!ecma_is_value_undefined (item))
{ {
ecma_string_t *item_str_p = ecma_get_string_from_value (item); if (!ecma_has_string_value_in_collection (context.property_list_p, item))
if (!list_has_ecma_string_element (&context.property_list, item_str_p))
{ {
list_append (&context.property_list, item_str_p); ecma_append_to_values_collection (context.property_list_p, item, true);
} ecma_deref_ecma_string (ecma_get_string_from_value (item));
else
{
ecma_deref_ecma_string (item_str_p);
} }
} }
@@ -1154,8 +1145,8 @@ ecma_builtin_json_stringify (ecma_value_t this_arg __attr_unused___, /**< 'this'
ecma_deref_ecma_string (context.indent_str_p); ecma_deref_ecma_string (context.indent_str_p);
ecma_deref_ecma_string (context.gap_str_p); ecma_deref_ecma_string (context.gap_str_p);
free_list_with_ecma_string_content (&context.property_list); ecma_free_values_collection (context.property_list_p, true);
free_list (&context.occurence_stack); ecma_free_values_collection (context.occurence_stack_p, true);
return ret_value; return ret_value;
} /* ecma_builtin_json_stringify */ } /* ecma_builtin_json_stringify */
@@ -1332,7 +1323,7 @@ ecma_builtin_json_quote (ecma_string_t *string_p) /**< string that should be quo
static ecma_completion_value_t static ecma_completion_value_t
ecma_builtin_json_str (ecma_string_t *key_p, /**< property key*/ ecma_builtin_json_str (ecma_string_t *key_p, /**< property key*/
ecma_object_t *holder_p, /**< the object*/ ecma_object_t *holder_p, /**< the object*/
stringify_context_t *context_p) /**< context*/ ecma_json_stringify_context_t *context_p) /**< context*/
{ {
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
@@ -1522,10 +1513,12 @@ ecma_builtin_json_str (ecma_string_t *key_p, /**< property key*/
*/ */
static ecma_completion_value_t static ecma_completion_value_t
ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
stringify_context_t *context_p) /**< context*/ ecma_json_stringify_context_t *context_p) /**< context*/
{ {
ecma_value_t obj_value = ecma_make_object_value (obj_p);
/* 1. */ /* 1. */
if (list_has_element (&context_p->occurence_stack, obj_p)) if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value))
{ {
return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
} }
@@ -1533,7 +1526,7 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
/* 2. */ /* 2. */
list_append (&context_p->occurence_stack, obj_p); ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true);
/* 3. */ /* 3. */
ecma_string_t *stepback_p = context_p->indent_str_p; ecma_string_t *stepback_p = context_p->indent_str_p;
@@ -1541,21 +1534,18 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
/* 4. */ /* 4. */
context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p);
list_ctx_t property_keys; ecma_collection_header_t *property_keys_p;
{
property_keys.block_start_p = NULL;
property_keys.block_end_p = NULL;
property_keys.current_p = NULL;
}
/* 5. */ /* 5. */
if (!list_is_empty (&context_p->property_list)) if (context_p->property_list_p->unit_number > 0)
{ {
property_keys = context_p->property_list; property_keys_p = context_p->property_list_p;
} }
/* 6. */ /* 6. */
else else
{ {
property_keys_p = ecma_new_values_collection (NULL, 0, true);
for (ecma_property_t *property_p = ecma_get_property_list (obj_p); for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
property_p != NULL; property_p != NULL;
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p)) property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
@@ -1563,31 +1553,30 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_enumerable (property_p)) if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_enumerable (property_p))
{ {
ecma_string_t *prop_key = ECMA_GET_NON_NULL_POINTER (ecma_string_t, ecma_string_t *prop_key = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
property_p->u.named_data_property.name_p); property_p->u.named_data_property.name_p);
JERRY_ASSERT (prop_key != NULL); JERRY_ASSERT (prop_key != NULL);
list_append (&property_keys, ecma_copy_or_ref_ecma_string (prop_key)); ecma_append_to_values_collection (property_keys_p, ecma_make_string_value (prop_key), true);
} }
} }
} }
/* 7. */ /* 7. */
list_ctx_t partial; ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true);
{
partial.block_start_p = NULL;
partial.block_end_p = NULL;
partial.current_p = NULL;
}
/* 8. */ /* 8. */
for (void **key_p = property_keys.block_start_p; ecma_collection_iterator_t iterator;
key_p < property_keys.current_p && ecma_is_completion_value_empty (ret_value); ecma_collection_iterator_init (&iterator, property_keys_p);
key_p++)
while (ecma_collection_iterator_next (&iterator) && ecma_is_completion_value_empty (ret_value))
{ {
ecma_value_t value = *iterator.current_value_p;
ecma_string_t *key_p = ecma_get_string_from_value (value);
/* 8.a */ /* 8.a */
ECMA_TRY_CATCH (str_val, ECMA_TRY_CATCH (str_val,
ecma_builtin_json_str ((ecma_string_t *) *key_p, obj_p, context_p), ecma_builtin_json_str (key_p, obj_p, context_p),
ret_value); ret_value);
/* 8.b */ /* 8.b */
@@ -1598,7 +1587,7 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
ecma_string_t *tmp_str_p; ecma_string_t *tmp_str_p;
/* 8.b.i */ /* 8.b.i */
ecma_completion_value_t str_comp_val = ecma_builtin_json_quote ((ecma_string_t *) *key_p); ecma_completion_value_t str_comp_val = ecma_builtin_json_quote (key_p);
JERRY_ASSERT (ecma_is_completion_value_normal (str_comp_val)); JERRY_ASSERT (ecma_is_completion_value_normal (str_comp_val));
ecma_string_t *member_str_p = ecma_get_string_from_value (str_comp_val); ecma_string_t *member_str_p = ecma_get_string_from_value (str_comp_val);
@@ -1628,26 +1617,28 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
member_str_p = tmp_str_p; member_str_p = tmp_str_p;
/* 8.b.v */ /* 8.b.v */
list_append (&partial, member_str_p); ecma_value_t member_value = ecma_make_string_value (member_str_p);
ecma_append_to_values_collection (partial_p, member_value, true);
ecma_deref_ecma_string (member_str_p);
} }
ECMA_FINALIZE (str_val); ECMA_FINALIZE (str_val);
} }
if (list_is_empty (&context_p->property_list)) if (context_p->property_list_p->unit_number == 0)
{ {
free_list_with_ecma_string_content (&property_keys); ecma_free_values_collection (property_keys_p, true);
} }
if (!ecma_is_completion_value_empty (ret_value)) if (!ecma_is_completion_value_empty (ret_value))
{ {
free_list_with_ecma_string_content (&partial); ecma_free_values_collection (partial_p, true);
ecma_deref_ecma_string (stepback_p); ecma_deref_ecma_string (stepback_p);
return ret_value; return ret_value;
} }
/* 9. */ /* 9. */
if (list_is_empty (&partial)) if (partial_p->unit_number == 0)
{ {
ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR); ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR);
ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR); ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR);
@@ -1671,7 +1662,7 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_brace_str_p, ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_brace_str_p,
right_brace_str_p, right_brace_str_p,
&partial); partial_p);
ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (left_brace_str_p);
ecma_deref_ecma_string (right_brace_str_p); ecma_deref_ecma_string (right_brace_str_p);
@@ -1685,7 +1676,7 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
ret_value = ecma_builtin_helper_json_create_formatted_json (left_brace_str_p, ret_value = ecma_builtin_helper_json_create_formatted_json (left_brace_str_p,
right_brace_str_p, right_brace_str_p,
stepback_p, stepback_p,
&partial, partial_p,
context_p); context_p);
ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (left_brace_str_p);
@@ -1693,10 +1684,10 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
} }
} }
free_list_with_ecma_string_content (&partial); ecma_free_values_collection (partial_p, true);
/* 11. */ /* 11. */
list_remove_last_element (&context_p->occurence_stack); ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p, true);
/* 12. */ /* 12. */
ecma_deref_ecma_string (context_p->indent_str_p); ecma_deref_ecma_string (context_p->indent_str_p);
@@ -1717,10 +1708,12 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
*/ */
static ecma_completion_value_t static ecma_completion_value_t
ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
stringify_context_t *context_p) /**< context*/ ecma_json_stringify_context_t *context_p) /**< context*/
{ {
ecma_value_t obj_value = ecma_make_object_value (obj_p);
/* 1. */ /* 1. */
if (list_has_element (&context_p->occurence_stack, obj_p)) if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value))
{ {
return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
} }
@@ -1728,7 +1721,7 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
/* 2. */ /* 2. */
list_append (&context_p->occurence_stack, obj_p); ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true);
/* 3. */ /* 3. */
ecma_string_t *stepback_p = context_p->indent_str_p; ecma_string_t *stepback_p = context_p->indent_str_p;
@@ -1737,12 +1730,7 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p);
/* 5. */ /* 5. */
list_ctx_t partial; ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true);
{
partial.block_start_p = NULL;
partial.block_end_p = NULL;
partial.current_p = NULL;
}
ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
@@ -1773,13 +1761,14 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
/* 8.b */ /* 8.b */
if (ecma_is_value_undefined (str_val)) if (ecma_is_value_undefined (str_val))
{ {
list_append (&partial, ecma_get_magic_string (LIT_MAGIC_STRING_NULL)); ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
ecma_append_to_values_collection (partial_p, ecma_make_string_value (null_str_p), true);
ecma_deref_ecma_string (null_str_p);
} }
/* 8.c */ /* 8.c */
else else
{ {
ecma_string_t *str_val_p = ecma_get_string_from_value (str_val); ecma_append_to_values_collection (partial_p, str_val, true);
list_append (&partial, ecma_copy_or_ref_ecma_string (str_val_p));
} }
ECMA_FINALIZE (str_val); ECMA_FINALIZE (str_val);
@@ -1789,7 +1778,7 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
if (ecma_is_completion_value_empty (ret_value)) if (ecma_is_completion_value_empty (ret_value))
{ {
/* 9. */ /* 9. */
if (list_is_empty (&partial)) if (partial_p->unit_number == 0)
{ {
ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR);
ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR);
@@ -1812,7 +1801,7 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_square_str_p, ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_square_str_p,
right_square_str_p, right_square_str_p,
&partial); partial_p);
ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (left_square_str_p);
ecma_deref_ecma_string (right_square_str_p); ecma_deref_ecma_string (right_square_str_p);
@@ -1826,7 +1815,7 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
ret_value = ecma_builtin_helper_json_create_formatted_json (left_square_str_p, ret_value = ecma_builtin_helper_json_create_formatted_json (left_square_str_p,
right_square_str_p, right_square_str_p,
stepback_p, stepback_p,
&partial, partial_p,
context_p); context_p);
ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (left_square_str_p);
@@ -1839,10 +1828,10 @@ ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
ECMA_FINALIZE (array_length); ECMA_FINALIZE (array_length);
ecma_deref_ecma_string (length_str_p); ecma_deref_ecma_string (length_str_p);
free_list_with_ecma_string_content (&partial); ecma_free_values_collection (partial_p, true);
/* 11. */ /* 11. */
list_remove_last_element (&context_p->occurence_stack); ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p, true);
/* 12. */ /* 12. */
ecma_deref_ecma_string (context_p->indent_str_p); ecma_deref_ecma_string (context_p->indent_str_p);