/** * List names of a Function object's lazy instantiated properties, * adding them to corresponding string collections * * See also: * ecma_op_function_try_lazy_instantiate_property */ void ecma_op_function_list_lazy_property_names (bool separate_enumerable, /**< true - list enumerable properties into * main collection and non-enumerable * to collection of 'skipped * non-enumerable' properties, * false - list all properties into main * collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' * collection */ { ecma_collection_header_t *for_enumerable_p = main_collection_p; JERRY_UNUSED (for_enumerable_p); ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; ecma_string_t *name_p; /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */ name_p = ecma_new_ecma_length_string (); ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ name_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE); ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } /* ecma_op_function_list_lazy_property_names */
/** * List names of a String object's lazy instantiated properties * * @return string values collection */ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ bool separate_enumerable, /**< true - list enumerable properties * into main collection, * and non-enumerable to collection of * 'skipped non-enumerable' properties, * false - list all properties into main * collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' * collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS); ecma_collection_header_t *for_enumerable_p = main_collection_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL); ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.class_prop.u.value); ecma_length_t length = ecma_string_get_length (prim_value_str_p); for (ecma_length_t i = 0; i < length; i++) { ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), 0); ecma_deref_ecma_string (name_p); } ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH), 0); } /* ecma_op_string_list_lazy_property_names */
/** * Allocate a collection of ecma-strings. * * @return pointer to the collection's header */ ecma_collection_header_t * ecma_new_strings_collection (ecma_string_t *string_ptrs_buffer[], /**< pointers to ecma-strings */ ecma_length_t strings_number) /**< number of ecma-strings */ { JERRY_ASSERT (string_ptrs_buffer != NULL || strings_number == 0); ecma_collection_header_t *new_collection_p; new_collection_p = ecma_new_values_collection (NULL, 0, false); for (ecma_length_t string_index = 0; string_index < strings_number; string_index++) { ecma_append_to_values_collection (new_collection_p, ecma_make_string_value (string_ptrs_buffer[string_index]), false); } return new_collection_p; } /* ecma_new_strings_collection */
/** * List names of a String object's lazy instantiated properties * * See also: * ecma_op_string_object_get_own_property * * @return string values collection */ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ bool separate_enumerable, /**< true - list enumerable properties * into main collection, * and non-enumerable to collection of * 'skipped non-enumerable' properties, * false - list all properties into main * collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' * collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING); ecma_collection_header_t *for_enumerable_p = main_collection_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? main_collection_p : non_enum_collection_p; JERRY_UNUSED (for_non_enumerable_p); ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_string_t *prim_value_str_p; prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p)); ecma_length_t length = ecma_string_get_length (prim_value_str_p); for (ecma_length_t i = 0; i < length; i++) { ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } } /* ecma_op_string_list_lazy_property_names */
/** * List names of a built-in object's lazy instantiated properties * * See also: * ecma_builtin_try_to_instantiate_property */ void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ bool separate_enumerable, /**< true - list enumerable properties into * main collection, and non-enumerable * to collection of 'skipped non-enumerable' * properties, * false - list all properties into main collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped 'non-enumerable' * collection */ { const ecma_object_type_t type = ecma_get_object_type (object_p); if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { ecma_collection_header_t *for_enumerable_p = main_collection_p; (void) for_enumerable_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; /* 'length' property is non-enumerable (ECMA-262 v5, 15) */ ecma_string_t *name_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } else { ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ ecma_builtin_ ## lowercase_name ## _list_lazy_property_names (object_p, \ separate_enumerable, \ main_collection_p, \ non_enum_collection_p); \ return; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { #ifdef CONFIG_ECMA_COMPACT_PROFILE JERRY_UNREACHABLE (); #else /* CONFIG_ECMA_COMPACT_PROFILE */ JERRY_UNIMPLEMENTED ("The built-in is not implemented."); #endif /* !CONFIG_ECMA_COMPACT_PROFILE */ } } JERRY_UNREACHABLE (); } } /* ecma_builtin_list_lazy_property_names */
/** * List names of a built-in object's lazy instantiated properties * * See also: * ecma_builtin_try_to_instantiate_property */ void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ bool separate_enumerable, /**< true - list enumerable properties into * main collection, and non-enumerable * to collection of 'skipped non-enumerable' * properties, * false - list all properties into main collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION && ecma_builtin_function_is_routine (object_p)) { ecma_collection_header_t *for_enumerable_p = main_collection_p; JERRY_UNUSED (for_enumerable_p); ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; /* 'length' property is non-enumerable (ECMA-262 v5, 15) */ ecma_string_t *name_p = ecma_new_ecma_length_string (); ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } else { ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id; JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; ecma_length_t index = 0; uint32_t instantiated_bitset = ext_obj_p->u.built_in.instantiated_bitset; ecma_collection_header_t *for_non_enumerable_p = (separate_enumerable ? non_enum_collection_p : main_collection_p); while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) { JERRY_ASSERT (index < 64); if (index == 32) { ecma_value_t *mask_prop_p = ecma_find_internal_property (object_p, ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63); if (mask_prop_p == NULL) { instantiated_bitset = 0; } else { instantiated_bitset = *mask_prop_p; } } uint32_t bit_for_index; if (index >= 32) { bit_for_index = (uint32_t) 1u << (index - 32); } else { bit_for_index = (uint32_t) 1u << index; } bool was_instantiated = false; if (instantiated_bitset & bit_for_index) { was_instantiated = true; } ecma_string_t *name_p = ecma_get_magic_string (curr_property_p->magic_string_id); if (!was_instantiated || ecma_op_object_has_own_property (object_p, name_p)) { ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true); } ecma_deref_ecma_string (name_p); curr_property_p++; index++; } } } /* ecma_builtin_list_lazy_property_names */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 4. */ ECMA_TRY_CATCH (length_value, ecma_op_object_get (obj_p, length_magic_string_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, length_value, ret_value); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); /* 6. */ ecma_collection_header_t *arg_collection_p = ecma_new_values_collection (NULL, 0, true); /* 7. */ for (uint32_t index = 0; index < length && ecma_is_completion_value_empty (ret_value); index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value); ecma_append_to_values_collection (arg_collection_p, get_value, true); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (curr_idx_str_p); } JERRY_ASSERT (arg_collection_p->unit_number == length || !ecma_is_completion_value_empty (ret_value)); if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_op_function_call (func_obj_p, arg1, arg_collection_p); } ecma_free_values_collection (arg_collection_p, true); ECMA_OP_TO_NUMBER_FINALIZE (length_number); ECMA_FINALIZE (length_value); ecma_deref_ecma_string (length_magic_string_p); } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * The JSON object's 'stringify' routine * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_stringify (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< value */ ecma_value_t arg2, /**< replacer */ ecma_value_t arg3) /**< space */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_json_stringify_context_t context; /* 1. */ context.occurence_stack_p = ecma_new_values_collection (NULL, 0, false); /* 2. */ context.indent_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); /* 3. */ context.property_list_p = ecma_new_values_collection (NULL, 0, false); context.replacer_function_p = NULL; /* 4. */ if (ecma_is_value_object (arg2)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); /* 4.a */ if (ecma_op_is_callable (arg2)) { context.replacer_function_p = obj_p; } /* 4.b */ else if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL) { ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ECMA_TRY_CATCH (array_length, ecma_op_object_get (obj_p, length_str_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, array_length, ret_value); uint32_t array_length = ecma_number_to_uint32 (array_length_num); uint32_t index = 0; /* 4.b.ii */ while ((index < array_length) && ecma_is_value_empty (ret_value)) { ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (value, ecma_op_object_get (obj_p, index_str_p), ret_value); /* 4.b.ii.1 */ ecma_value_t item = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); /* 4.b.ii.2 */ if (ecma_is_value_string (value)) { item = ecma_copy_value (value, true); } /* 4.b.ii.3 */ else if (ecma_is_value_number (value)) { ECMA_TRY_CATCH (str_val, ecma_op_to_string (value), ret_value); item = ecma_copy_value (str_val, true); ECMA_FINALIZE (str_val); } /* 4.b.ii.4 */ else if (ecma_is_value_object (value)) { ecma_object_t *obj_val_p = ecma_get_object_from_value (value); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_val_p); /* 4.b.ii.4.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL || class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (value), ret_value); item = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } /* 4.b.ii.5 */ if (!ecma_is_value_undefined (item)) { if (!ecma_has_string_value_in_collection (context.property_list_p, item)) { ecma_append_to_values_collection (context.property_list_p, item, true); ecma_deref_ecma_string (ecma_get_string_from_value (item)); } else { ecma_free_value (item); } } ECMA_FINALIZE (value); ecma_deref_ecma_string (index_str_p); index++; } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); ECMA_FINALIZE (array_length); ecma_deref_ecma_string (length_str_p); } } if (ecma_is_value_empty (ret_value)) { ecma_value_t space = ecma_copy_value (arg3, true); /* 5. */ if (ecma_is_value_object (arg3)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg3); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 5.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL) { ECMA_TRY_CATCH (val, ecma_op_to_number (arg3), ret_value); ecma_free_value (space); space = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 5.b */ else if (class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (arg3), ret_value); ecma_free_value (space); space = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } if (ecma_is_value_empty (ret_value)) { /* 6. */ if (ecma_is_value_number (space)) { ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, arg3, ret_value); /* 6.a */ int32_t num_of_spaces = ecma_number_to_int32 (array_length_num); int32_t space = (num_of_spaces > 10) ? 10 : num_of_spaces; /* 6.b */ if (space < 1) { context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } else { MEM_DEFINE_LOCAL_ARRAY (space_buff, space, char); for (int32_t i = 0; i < space; i++) { space_buff[i] = LIT_CHAR_SP; } context.gap_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) space_buff, (lit_utf8_size_t) space); MEM_FINALIZE_LOCAL_ARRAY (space_buff); } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); } /* 7. */ else if (ecma_is_value_string (space)) { ecma_string_t *space_str_p = ecma_get_string_from_value (space); ecma_length_t num_of_chars = ecma_string_get_length (space_str_p); if (num_of_chars < 10) { context.gap_str_p = ecma_copy_or_ref_ecma_string (space_str_p); } else { context.gap_str_p = ecma_string_substr (space_str_p, 0, 10); } } /* 8. */ else { context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } } ecma_free_value (space); if (ecma_is_value_empty (ret_value)) { /* 9. */ ecma_object_t *obj_wrapper_p = ecma_op_create_object_object_noarg (); ecma_string_t *empty_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); /* 10. */ ecma_value_t put_comp_val = ecma_op_object_put (obj_wrapper_p, empty_str_p, arg1, false); JERRY_ASSERT (ecma_is_value_true (put_comp_val)); ecma_free_value (put_comp_val); /* 11. */ ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (empty_str_p, obj_wrapper_p, &context), ret_value); ret_value = ecma_copy_value (str_val, true); ECMA_FINALIZE (str_val); ecma_deref_object (obj_wrapper_p); ecma_deref_ecma_string (empty_str_p); } ecma_deref_ecma_string (context.gap_str_p); } ecma_deref_ecma_string (context.indent_str_p); ecma_free_values_collection (context.property_list_p, true); ecma_free_values_collection (context.occurence_stack_p, true); return ret_value; } /* ecma_builtin_json_stringify */
/** * Abstract operation 'JA' defined in 15.12.3 * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t obj_value = ecma_make_object_value (obj_p); /* 1. */ if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value)) { return ecma_raise_type_error (""); } ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true); /* 3. */ ecma_string_t *stepback_p = context_p->indent_str_p; /* 4. */ context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); /* 5. */ ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true); ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 6. */ ECMA_TRY_CATCH (array_length, ecma_op_object_get (obj_p, length_str_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, array_length, ret_value); uint32_t array_length = ecma_number_to_uint32 (array_length_num); /* 7. - 8. */ for (uint32_t index = 0; index < array_length && ecma_is_value_empty (ret_value); index++) { /* 8.a */ ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (index_str_p, obj_p, context_p), ret_value); /* 8.b */ if (ecma_is_value_undefined (str_val)) { 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 */ else { ecma_append_to_values_collection (partial_p, str_val, true); } ECMA_FINALIZE (str_val); ecma_deref_ecma_string (index_str_p); } if (ecma_is_value_empty (ret_value)) { /* 9. */ 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 *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_square_str_p, right_square_str_p); ret_value = ecma_make_string_value (final_str_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } /* 10. */ else { bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); /* 10.a */ if (is_gap_empty) { 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); ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_square_str_p, right_square_str_p, partial_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } /* 10.b */ else { 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); ret_value = ecma_builtin_helper_json_create_formatted_json (left_square_str_p, right_square_str_p, stepback_p, partial_p, context_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } } } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); ECMA_FINALIZE (array_length); ecma_deref_ecma_string (length_str_p); ecma_free_values_collection (partial_p, true); /* 11. */ ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p); /* 12. */ ecma_deref_ecma_string (context_p->indent_str_p); context_p->indent_str_p = stepback_p; /* 13. */ return ret_value; } /* ecma_builtin_json_array */
/** * Abstract operation 'JO' defined in 15.12.3 * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t obj_value = ecma_make_object_value (obj_p); /* 1. */ if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value)) { return ecma_raise_type_error (""); } ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true); /* 3. */ ecma_string_t *stepback_p = context_p->indent_str_p; /* 4. */ context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); ecma_collection_header_t *property_keys_p; /* 5. */ if (context_p->property_list_p->unit_number > 0) { property_keys_p = context_p->property_list_p; } /* 6. */ else { property_keys_p = ecma_new_values_collection (NULL, 0, true); ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, true, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); JERRY_ASSERT (ecma_is_property_enumerable (property_p)); if (property_p->type == ECMA_PROPERTY_NAMEDDATA) { ecma_append_to_values_collection (property_keys_p, *iter.current_value_p, true); } } ecma_free_values_collection (props_p, true); } /* 7. */ ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true); /* 8. */ ecma_collection_iterator_t iterator; ecma_collection_iterator_init (&iterator, property_keys_p); while (ecma_collection_iterator_next (&iterator) && ecma_is_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 */ ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (key_p, obj_p, context_p), ret_value); /* 8.b */ if (!ecma_is_value_undefined (str_val)) { ecma_string_t *colon_p = ecma_get_magic_string (LIT_MAGIC_STRING_COLON_CHAR); ecma_string_t *value_str_p = ecma_get_string_from_value (str_val); ecma_string_t *tmp_str_p; /* 8.b.i */ ecma_value_t str_comp_val = ecma_builtin_json_quote (key_p); JERRY_ASSERT (!ecma_is_value_error (str_comp_val)); ecma_string_t *member_str_p = ecma_get_string_from_value (str_comp_val); /* 8.b.ii */ tmp_str_p = ecma_concat_ecma_strings (member_str_p, colon_p); ecma_free_value (str_comp_val); ecma_deref_ecma_string (colon_p); member_str_p = tmp_str_p; /* 8.b.iii */ bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); if (!is_gap_empty) { ecma_string_t *space_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_SPACE_CHAR); tmp_str_p = ecma_concat_ecma_strings (member_str_p, space_str_p); ecma_deref_ecma_string (member_str_p); ecma_deref_ecma_string (space_str_p); member_str_p = tmp_str_p; } /* 8.b.iv */ tmp_str_p = ecma_concat_ecma_strings (member_str_p, value_str_p); ecma_deref_ecma_string (member_str_p); member_str_p = tmp_str_p; /* 8.b.v */ 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); } if (context_p->property_list_p->unit_number == 0) { ecma_free_values_collection (property_keys_p, true); } if (!ecma_is_value_empty (ret_value)) { ecma_free_values_collection (partial_p, true); ecma_deref_ecma_string (stepback_p); return ret_value; } /* 9. */ 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 *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR); ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_brace_str_p, right_brace_str_p); ret_value = ecma_make_string_value (final_str_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); } /* 10. */ else { bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); /* 10.a */ if (is_gap_empty) { 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); ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_brace_str_p, right_brace_str_p, partial_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); } /* 10.b */ else { 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); ret_value = ecma_builtin_helper_json_create_formatted_json (left_brace_str_p, right_brace_str_p, stepback_p, partial_p, context_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); } } ecma_free_values_collection (partial_p, true); /* 11. */ ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p); /* 12. */ ecma_deref_ecma_string (context_p->indent_str_p); context_p->indent_str_p = stepback_p; /* 13. */ return ret_value; } /* ecma_builtin_json_object */