/** * Get the value from an error ecma value * * @return ecma value */ ecma_value_t __attr_pure___ ecma_get_value_from_error_value (ecma_value_t value) /**< ecma value */ { JERRY_ASSERT (ecma_is_value_error (value)); value = (ecma_value_t) (value & ~(1u << ECMA_VALUE_ERROR_POS)); JERRY_ASSERT (!ecma_is_value_error (value)); return value; } /* ecma_get_value_from_error_value */
/** * Number object creation operation. * * See also: ECMA-262 v5, 15.7.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ { ecma_value_t conv_to_num_completion = ecma_op_to_number (arg); if (ecma_is_value_error (conv_to_num_completion)) { return conv_to_num_completion; } ecma_number_t *prim_value_p = ecma_get_number_from_value (conv_to_num_completion); #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); class_prop_p->u.internal_property.value = LIT_MAGIC_STRING_NUMBER_UL; ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_value_p); return ecma_make_object_value (obj_p); } /* ecma_op_create_number_object */
/** * Error value constructor */ ecma_value_t __attr_const___ ecma_make_error_value (ecma_value_t value) /**< original ecma value */ { /* Error values cannot be converted. */ JERRY_ASSERT (!ecma_is_value_error (value)); return value | (1u << ECMA_VALUE_ERROR_POS); } /* ecma_make_error_value */
/** * SetMutableBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ ecma_value_t value, /**< argument V */ bool is_strict) /**< argument S */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (name_p != NULL); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p); if (ecma_is_property_writable (property_p)) { ecma_named_data_property_assign_value (lex_env_p, property_p, value); } else if (is_strict) { return ecma_raise_type_error (""); } } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); if (ecma_is_value_error (completion)) { return completion; } else { JERRY_ASSERT (ecma_is_value_boolean (completion)); } } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); } /* ecma_op_set_mutable_binding */
/** * The Object.keys and Object.getOwnPropertyNames routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return ecma value - Array of property names. * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ bool only_enumerable_properties) /**< list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ecma_is_value_error (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); uint32_t index = 0; ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, only_enumerable_properties, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter)) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, *iter.current_value_p, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); index++; } ecma_free_values_collection (props_p, true); return new_array; } /* ecma_builtin_helper_object_get_properties */
/** * CreateMutableBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ bool is_deletable) /**< argument D */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (name_p != NULL); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_create_named_data_property (lex_env_p, name_p, true, false, is_deletable); } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_value_t completion; completion = ecma_builtin_helper_def_prop (binding_obj_p, name_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), true, /* Writable */ true, /* Enumerable */ is_deletable, /* Configurable */ true); /* Failure handling */ if (ecma_is_value_error (completion)) { return completion; } else { JERRY_ASSERT (ecma_is_value_boolean (completion)); } } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); } /* ecma_op_create_mutable_binding */
/** * Get value of function's argument mapped to index of Arguments object. * * Note: * The procedure emulates execution of function described by MakeArgGetter * * @return ecma value * Returned value must be freed with ecma_free_value */ static ecma_value_t ecma_arguments_get_mapped_arg_value (ecma_object_t *map_p, /**< [[ParametersMap]] object */ ecma_property_t *arg_name_prop_p) /**< property of [[ParametersMap]] corresponding to index and value equal to mapped argument's name */ { ecma_property_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_object_t *lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, scope_prop_p->u.internal_property.value); JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); ecma_value_t arg_name_prop_value = ecma_get_named_data_property_value (arg_name_prop_p); ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name_prop_value); ecma_value_t completion = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); JERRY_ASSERT (!ecma_is_value_error (completion)); return completion; } /* ecma_arguments_get_mapped_arg_value */
/** * String object creation operation. * * See also: ECMA-262 v5, 15.5.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_string_t *prim_prop_str_value_p; ecma_number_t length_value; if (arguments_list_len == 0) { prim_prop_str_value_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY); length_value = ECMA_NUMBER_ZERO; } else { ecma_value_t to_str_arg_value = ecma_op_to_string (arguments_list_p[0]); if (ecma_is_value_error (to_str_arg_value)) { return to_str_arg_value; } else { JERRY_ASSERT (!ecma_is_value_error (to_str_arg_value)); JERRY_ASSERT (ecma_is_value_string (to_str_arg_value)); prim_prop_str_value_p = ecma_get_string_from_value (to_str_arg_value); ecma_length_t string_len = ecma_string_get_length (prim_prop_str_value_p); length_value = ((ecma_number_t) (uint32_t) string_len); } } #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_STRING); ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_STRING type. * * See also: ecma_object_get_class_name */ ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prim_value_prop_p)->value, prim_prop_str_value_p); // 15.5.5.1 ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, length_magic_string_p, false, false, false); ecma_number_t *length_prop_value_p = ecma_alloc_number (); *length_prop_value_p = length_value; ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_prop_value_p)); ecma_deref_ecma_string (length_magic_string_p); return ecma_make_object_value (obj_p); } /* ecma_op_create_string_object */
/** * [[Put]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.5 * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 * * @return ecma value * The returned value must be freed with ecma_free_value. * * Returns with ECMA_SIMPLE_VALUE_TRUE if the operation is * successful. Otherwise it returns with an error object * or ECMA_SIMPLE_VALUE_FALSE. * * Note: even if is_throw is false, the setter can throw an * error, and this function returns with that error. */ ecma_value_t ecma_op_general_object_put (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ ecma_value_t value, /**< ecma value */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); ecma_object_t *setter_p = NULL; ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, property_name_p); if (prop_p != NULL) { if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { if (ecma_is_property_writable (prop_p)) { const ecma_object_type_t type = ecma_get_object_type (obj_p); if (type == ECMA_OBJECT_TYPE_ARGUMENTS || (type == ECMA_OBJECT_TYPE_ARRAY && ecma_op_general_object_property_name_is_length (property_name_p))) { /* These cases cannot be optimized. */ ecma_property_descriptor_t value_desc = ecma_make_empty_property_descriptor (); value_desc.is_value_defined = true; value_desc.value = value; return ecma_op_object_define_own_property (obj_p, property_name_p, &value_desc, is_throw); } /* There is no need for special casing arrays here because changing the * value of an existing property never changes the length of an array. */ ecma_named_data_property_assign_value (obj_p, prop_p, value); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } else { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); setter_p = ecma_get_named_accessor_property_setter (prop_p); } } else { ecma_object_t *proto_p = ecma_get_object_prototype (obj_p); bool create_new_property = true; if (proto_p != NULL) { ecma_property_t *inherited_prop_p = ecma_op_object_get_property (proto_p, property_name_p); if (inherited_prop_p != NULL) { if (ECMA_PROPERTY_GET_TYPE (inherited_prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { setter_p = ecma_get_named_accessor_property_setter (inherited_prop_p); create_new_property = false; } else { create_new_property = ecma_is_property_writable (inherited_prop_p); } } } if (create_new_property && ecma_get_object_extensible (obj_p)) { const ecma_object_type_t type = ecma_get_object_type (obj_p); if (type == ECMA_OBJECT_TYPE_ARGUMENTS) { return ecma_builtin_helper_def_prop (obj_p, property_name_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ is_throw); /* Failure handling */ } uint32_t index; if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_string_get_array_index (property_name_p, &index)) { /* Since the length of an array is a non-configurable named data * property, the prop_p must be a non-NULL pointer for all arrays. */ JERRY_ASSERT (!ecma_op_general_object_property_name_is_length (property_name_p)); ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); uint32_t old_len = ecma_get_uint32_from_value (ecma_get_named_data_property_value (len_prop_p)); if (index < UINT32_MAX && index >= old_len) { if (!ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); } } ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p, property_name_p, true, /* Writable */ true, /* Enumerable */ true); /* Configurable */ JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (new_prop_p))); ecma_set_named_data_property_value (new_prop_p, ecma_copy_value_if_not_object (value)); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } if (setter_p == NULL) { return ecma_reject (is_throw); } ecma_value_t ret_value = ecma_op_function_call (setter_p, ecma_make_object_value (obj_p), &value, 1); if (!ecma_is_value_error (ret_value)) { ecma_fast_free_value (ret_value); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_op_general_object_put */
/** * Abstract operation 'Str' 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_str (ecma_string_t *key_p, /**< property key*/ ecma_object_t *holder_p, /**< the object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (value, ecma_op_object_get (holder_p, key_p), ret_value); ecma_value_t my_val = ecma_copy_value (value, true); /* 2. */ if (ecma_is_value_object (my_val)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (my_val); ecma_string_t *to_json_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_JSON_UL); /* 2.a */ ECMA_TRY_CATCH (toJSON, ecma_op_object_get (value_obj_p, to_json_str_p), ret_value); /* 2.b */ if (ecma_op_is_callable (toJSON)) { ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value }; ecma_object_t *toJSON_obj_p = ecma_get_object_from_value (toJSON); ECMA_TRY_CATCH (func_ret_val, ecma_op_function_call (toJSON_obj_p, my_val, call_args, 1), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (func_ret_val, true); ECMA_FINALIZE (func_ret_val); } ECMA_FINALIZE (toJSON); ecma_deref_ecma_string (to_json_str_p); } /* 3. */ if (context_p->replacer_function_p && ecma_is_value_empty (ret_value)) { ecma_value_t holder_value = ecma_make_object_value (holder_p); ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value, my_val }; ECMA_TRY_CATCH (func_ret_val, ecma_op_function_call (context_p->replacer_function_p, holder_value, call_args, 2), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (func_ret_val, true); ECMA_FINALIZE (func_ret_val); } /* 4. */ if (ecma_is_value_object (my_val) && ecma_is_value_empty (ret_value)) { ecma_object_t *obj_p = ecma_get_object_from_value (my_val); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 4.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL) { ECMA_TRY_CATCH (val, ecma_op_to_number (my_val), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 4.b */ else if (class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (my_val), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 4.c */ else if (class_name == LIT_MAGIC_STRING_BOOLEAN_UL) { ECMA_TRY_CATCH (val, ecma_op_to_primitive (my_val, ECMA_PREFERRED_TYPE_NO), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } if (ecma_is_value_empty (ret_value)) { /* 5. - 7. */ if (ecma_is_value_null (my_val) || ecma_is_value_boolean (my_val)) { ret_value = ecma_op_to_string (my_val); JERRY_ASSERT (!ecma_is_value_error (ret_value)); } /* 8. */ else if (ecma_is_value_string (my_val)) { ecma_string_t *value_str_p = ecma_get_string_from_value (my_val); ret_value = ecma_builtin_json_quote (value_str_p); } /* 9. */ else if (ecma_is_value_number (my_val)) { ecma_number_t num_value_p = *ecma_get_number_from_value (my_val); /* 9.a */ if (!ecma_number_is_nan (num_value_p) && !ecma_number_is_infinity (num_value_p)) { ret_value = ecma_op_to_string (my_val); JERRY_ASSERT (!ecma_is_value_error (ret_value)); } else { /* 9.b */ ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); ret_value = ecma_make_string_value (null_str_p); } } /* 10. */ else if (ecma_is_value_object (my_val) && !ecma_op_is_callable (my_val)) { ecma_object_t *obj_p = ecma_get_object_from_value (my_val); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 10.a */ if (class_name == LIT_MAGIC_STRING_ARRAY_UL) { ECMA_TRY_CATCH (val, ecma_builtin_json_array (obj_p, context_p), ret_value); ret_value = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 10.b */ else { ECMA_TRY_CATCH (val, ecma_builtin_json_object (obj_p, context_p), ret_value); ret_value = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } else { /* 11. */ ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } ecma_free_value (my_val); ECMA_FINALIZE (value); return ret_value; } /* ecma_builtin_json_str */
ecma_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ { lit_magic_string_id_t type_string; if (ecma_is_value_undefined (this_arg)) { type_string = LIT_MAGIC_STRING_UNDEFINED_UL; } else if (ecma_is_value_null (this_arg)) { type_string = LIT_MAGIC_STRING_NULL_UL; } else { ecma_value_t obj_this = ecma_op_to_object (this_arg); if (ecma_is_value_error (obj_this)) { return obj_this; } JERRY_ASSERT (ecma_is_value_object (obj_this)); ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); type_string = ecma_object_get_class_name (obj_p); ecma_free_value (obj_this); } ecma_string_t *ret_string_p; /* Building string "[object #type#]" where type is 'Undefined', 'Null' or one of possible object's classes. The string with null character is maximum 19 characters long. */ const lit_utf8_size_t buffer_size = 19; JMEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *buffer_ptr = str_buffer; const lit_magic_string_id_t magic_string_ids[] = { LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, LIT_MAGIC_STRING_OBJECT, LIT_MAGIC_STRING_SPACE_CHAR, type_string, LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR }; for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) { buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); } ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); return ecma_make_string_value (ret_string_p); } /* ecma_builtin_helper_object_to_string */
/** * The Error.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.11.4.4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_error_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // 2. if (!ecma_is_value_object (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); ecma_string_t *name_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAME); ECMA_TRY_CATCH (name_get_ret_value, ecma_op_object_get (obj_p, name_magic_string_p), ret_value); ecma_value_t name_to_str_completion; if (ecma_is_value_undefined (name_get_ret_value)) { ecma_string_t *error_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ERROR_UL); name_to_str_completion = ecma_make_string_value (error_magic_string_p); } else { name_to_str_completion = ecma_op_to_string (name_get_ret_value); } if (unlikely (ecma_is_value_error (name_to_str_completion))) { ret_value = ecma_copy_value (name_to_str_completion); } else { ecma_string_t *message_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE); ECMA_TRY_CATCH (msg_get_ret_value, ecma_op_object_get (obj_p, message_magic_string_p), ret_value); ecma_value_t msg_to_str_completion; if (ecma_is_value_undefined (msg_get_ret_value)) { ecma_string_t *empty_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); msg_to_str_completion = ecma_make_string_value (empty_magic_string_p); } else { msg_to_str_completion = ecma_op_to_string (msg_get_ret_value); } if (unlikely (ecma_is_value_error (msg_to_str_completion))) { ret_value = ecma_copy_value (msg_to_str_completion); } else { ecma_string_t *name_string_p = ecma_get_string_from_value (name_to_str_completion); ecma_string_t *msg_string_p = ecma_get_string_from_value (msg_to_str_completion); ecma_string_t *ret_str_p; if (ecma_string_get_length (name_string_p) == 0) { ret_str_p = ecma_copy_or_ref_ecma_string (msg_string_p); } else if (ecma_string_get_length (msg_string_p) == 0) { ret_str_p = ecma_copy_or_ref_ecma_string (name_string_p); } else { const lit_utf8_size_t name_size = ecma_string_get_size (name_string_p); const lit_utf8_size_t msg_size = ecma_string_get_size (msg_string_p); const lit_utf8_size_t colon_size = lit_get_magic_string_size (LIT_MAGIC_STRING_COLON_CHAR); const lit_utf8_size_t space_size = lit_get_magic_string_size (LIT_MAGIC_STRING_SPACE_CHAR); const lit_utf8_size_t size = name_size + msg_size + colon_size + space_size; JMEM_DEFINE_LOCAL_ARRAY (ret_str_buffer, size, lit_utf8_byte_t); lit_utf8_byte_t *ret_str_buffer_p = ret_str_buffer; lit_utf8_size_t bytes = ecma_string_to_utf8_string (name_string_p, ret_str_buffer_p, name_size); JERRY_ASSERT (bytes == name_size); ret_str_buffer_p = ret_str_buffer_p + bytes; JERRY_ASSERT (ret_str_buffer_p <= ret_str_buffer + size); ret_str_buffer_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_COLON_CHAR, ret_str_buffer_p, colon_size); JERRY_ASSERT (ret_str_buffer_p <= ret_str_buffer + size); ret_str_buffer_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_SPACE_CHAR, ret_str_buffer_p, space_size); JERRY_ASSERT (ret_str_buffer_p <= ret_str_buffer + size); bytes = ecma_string_to_utf8_string (msg_string_p, ret_str_buffer_p, msg_size); JERRY_ASSERT (bytes == msg_size); ret_str_buffer_p = ret_str_buffer_p + bytes; JERRY_ASSERT (ret_str_buffer_p == ret_str_buffer + size); ret_str_p = ecma_new_ecma_string_from_utf8 (ret_str_buffer, size); JMEM_FINALIZE_LOCAL_ARRAY (ret_str_buffer); } ret_value = ecma_make_string_value (ret_str_p); } ecma_free_value (msg_to_str_completion); ECMA_FINALIZE (msg_get_ret_value); ecma_deref_ecma_string (message_magic_string_p); } ecma_free_value (name_to_str_completion); ECMA_FINALIZE (name_get_ret_value); ecma_deref_ecma_string (name_magic_string_p); } return ret_value; } /* ecma_builtin_error_prototype_object_to_string */
/** * [[DefineOwnProperty]] ecma array object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.4.5.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */ ecma_string_t *property_name_p, /**< property name */ const ecma_property_descriptor_t *property_desc_p, /**< property descriptor */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); // 1. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA); // 2. ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); ecma_number_t *num_p = ecma_get_number_from_value (old_len_value); uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p); // 3. bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_property_name_equal_length) { // a. if (!property_desc_p->is_value_defined) { // i. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } ecma_number_t new_len_num; // c. ecma_value_t completion = ecma_op_to_number (property_desc_p->value); if (ecma_is_value_error (completion)) { return completion; } JERRY_ASSERT (!ecma_is_value_error (completion) && ecma_is_value_number (completion)); new_len_num = *ecma_get_number_from_value (completion); ecma_free_value (completion); uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); // d. if (ecma_uint32_to_number (new_len_uint32) != new_len_num) { return ecma_raise_range_error (""); } else { // b., e. ecma_number_t *new_len_num_p = ecma_alloc_number (); *new_len_num_p = new_len_num; ecma_property_descriptor_t new_len_property_desc = *property_desc_p; new_len_property_desc.value = ecma_make_number_value (new_len_num_p); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // f. if (new_len_uint32 >= old_len_uint32) { // i. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ret_value = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); } else { // g. if (!ecma_is_property_writable (len_prop_p)) { ret_value = ecma_reject (is_throw); } else { // h. bool new_writable; if (!new_len_property_desc.is_writable_defined || new_len_property_desc.is_writable) { new_writable = true; } else { // ii. new_writable = false; // iii. new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = true; } // j. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); /* Handling normal false and throw values */ if (!ecma_is_value_true (succeeded)) { JERRY_ASSERT (ecma_is_value_false (succeeded) || ecma_is_value_error (succeeded)); // k. ret_value = succeeded; } else { // l JERRY_ASSERT (new_len_uint32 < old_len_uint32); /* * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated */ bool is_reduce_succeeded = true; ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, true, false, false); ecma_length_t array_index_props_num = array_index_props_p->unit_number; MEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, array_index_props_p); uint32_t array_index_values_pos = 0; while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); uint32_t index; bool is_index = ecma_string_get_array_index (property_name_p, &index); JERRY_ASSERT (is_index); JERRY_ASSERT (index < old_len_uint32); array_index_values_p[array_index_values_pos++] = index; } JERRY_ASSERT (array_index_values_pos == array_index_props_num); while (array_index_values_pos != 0 && array_index_values_p[--array_index_values_pos] >= new_len_uint32) { uint32_t index = array_index_values_p[array_index_values_pos]; // ii. ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t delete_succeeded = ecma_op_object_delete (obj_p, index_string_p, false); ecma_deref_ecma_string (index_string_p); if (ecma_is_value_false (delete_succeeded)) { // iii. new_len_uint32 = (index + 1u); ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value); // 1. *new_len_num_p = ecma_uint32_to_number (index + 1u); // 2. if (!new_writable) { new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = false; } // 3. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_value_t completion = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_value_boolean (completion)); is_reduce_succeeded = false; break; } } MEM_FINALIZE_LOCAL_ARRAY (array_index_values_p); ecma_free_values_collection (array_index_props_p, true); if (!is_reduce_succeeded) { ret_value = ecma_reject (is_throw); } else { // m. if (!new_writable) { ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); prop_desc_not_writable.is_writable_defined = true; prop_desc_not_writable.is_writable = false; ecma_value_t completion_set_not_writable; magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &prop_desc_not_writable, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_value_true (completion_set_not_writable)); } ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } } } ecma_dealloc_number (new_len_num_p); return ret_value; } JERRY_UNREACHABLE (); } else { // 4.a. uint32_t index; if (!ecma_string_get_array_index (property_name_p, &index)) { // 5. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } // 4. // b. if (index >= old_len_uint32 && !ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } // c. ecma_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, false); // d. JERRY_ASSERT (ecma_is_value_boolean (succeeded)); if (ecma_is_value_false (succeeded)) { return ecma_reject (is_throw); } // e. if (index >= old_len_uint32) { // i., ii. ecma_number_t *num_p = ecma_alloc_number (); *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE); ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p)); ecma_dealloc_number (num_p); } // f. return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } JERRY_UNREACHABLE (); } /* ecma_op_array_object_define_own_property */
/** * ToPropertyDescriptor operation. * * See also: * ECMA-262 v5, 8.10.5 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor if return value is normal empty completion value */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // 1. if (!ecma_is_value_object (obj_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); // 2. ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); // 3. ecma_string_t *enumerable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE); if (ecma_op_object_get_property (obj_p, enumerable_magic_string_p) != NULL) { ECMA_TRY_CATCH (enumerable_prop_value, ecma_op_object_get (obj_p, enumerable_magic_string_p), ret_value); prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = ecma_op_to_boolean (enumerable_prop_value); ECMA_FINALIZE (enumerable_prop_value); } ecma_deref_ecma_string (enumerable_magic_string_p); if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 4. ecma_string_t *configurable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE); if (ecma_op_object_get_property (obj_p, configurable_magic_string_p) != NULL) { ECMA_TRY_CATCH (configurable_prop_value, ecma_op_object_get (obj_p, configurable_magic_string_p), ret_value); prop_desc.is_configurable_defined = true; prop_desc.is_configurable = ecma_op_to_boolean (configurable_prop_value); ECMA_FINALIZE (configurable_prop_value); } ecma_deref_ecma_string (configurable_magic_string_p); } if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 5. ecma_string_t *value_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUE); if (ecma_op_object_get_property (obj_p, value_magic_string_p) != NULL) { ECMA_TRY_CATCH (value_prop_value, ecma_op_object_get (obj_p, value_magic_string_p), ret_value); prop_desc.is_value_defined = true; prop_desc.value = ecma_copy_value (value_prop_value); ECMA_FINALIZE (value_prop_value); } ecma_deref_ecma_string (value_magic_string_p); } if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 6. ecma_string_t *writable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE); if (ecma_op_object_get_property (obj_p, writable_magic_string_p) != NULL) { ECMA_TRY_CATCH (writable_prop_value, ecma_op_object_get (obj_p, writable_magic_string_p), ret_value); prop_desc.is_writable_defined = true; prop_desc.is_writable = ecma_op_to_boolean (writable_prop_value); ECMA_FINALIZE (writable_prop_value); } ecma_deref_ecma_string (writable_magic_string_p); } if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 7. ecma_string_t *get_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GET); if (ecma_op_object_get_property (obj_p, get_magic_string_p) != NULL) { ECMA_TRY_CATCH (get_prop_value, ecma_op_object_get (obj_p, get_magic_string_p), ret_value); if (!ecma_op_is_callable (get_prop_value) && !ecma_is_value_undefined (get_prop_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { prop_desc.is_get_defined = true; if (ecma_is_value_undefined (get_prop_value)) { prop_desc.get_p = NULL; } else { JERRY_ASSERT (ecma_is_value_object (get_prop_value)); ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value); ecma_ref_object (get_p); prop_desc.get_p = get_p; } } ECMA_FINALIZE (get_prop_value); } ecma_deref_ecma_string (get_magic_string_p); } if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 8. ecma_string_t *set_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SET); if (ecma_op_object_get_property (obj_p, set_magic_string_p) != NULL) { ECMA_TRY_CATCH (set_prop_value, ecma_op_object_get (obj_p, set_magic_string_p), ret_value); if (!ecma_op_is_callable (set_prop_value) && !ecma_is_value_undefined (set_prop_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { prop_desc.is_set_defined = true; if (ecma_is_value_undefined (set_prop_value)) { prop_desc.set_p = NULL; } else { JERRY_ASSERT (ecma_is_value_object (set_prop_value)); ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value); ecma_ref_object (set_p); prop_desc.set_p = set_p; } } ECMA_FINALIZE (set_prop_value); } ecma_deref_ecma_string (set_magic_string_p); } if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 9. if (prop_desc.is_get_defined || prop_desc.is_set_defined) { if (prop_desc.is_value_defined || prop_desc.is_writable_defined) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } } } if (!ecma_is_value_error (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); } else { ecma_free_property_descriptor (&prop_desc); } *out_prop_desc_p = prop_desc; } return ret_value; } /* ecma_op_to_property_descriptor */
/** * 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 */
/** * [[DefaultValue]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.8 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); if (hint == ECMA_PREFERRED_TYPE_NO) { if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL) { hint = ECMA_PREFERRED_TYPE_STRING; } else { hint = ECMA_PREFERRED_TYPE_NUMBER; } } for (uint32_t i = 1; i <= 2; i++) { lit_magic_string_id_t function_name_magic_string_id; if ((i == 1 && hint == ECMA_PREFERRED_TYPE_STRING) || (i == 2 && hint == ECMA_PREFERRED_TYPE_NUMBER)) { function_name_magic_string_id = LIT_MAGIC_STRING_TO_STRING_UL; } else { function_name_magic_string_id = LIT_MAGIC_STRING_VALUE_OF_UL; } ecma_string_t *function_name_p = ecma_get_magic_string (function_name_magic_string_id); ecma_value_t function_value_get_completion = ecma_op_object_get (obj_p, function_name_p); ecma_deref_ecma_string (function_name_p); if (ecma_is_value_error (function_value_get_completion)) { return function_value_get_completion; } ecma_value_t call_completion = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (ecma_op_is_callable (function_value_get_completion)) { ecma_object_t *func_obj_p = ecma_get_object_from_value (function_value_get_completion); call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL, 0); } ecma_free_value (function_value_get_completion); if (ecma_is_value_error (call_completion) || (!ecma_is_value_empty (call_completion) && !ecma_is_value_object (call_completion))) { return call_completion; } ecma_free_value (call_completion); } return ecma_raise_type_error (ECMA_ERR_MSG ("")); } /* ecma_op_general_object_default_value */
/** * Abstract operation Walk defined in 15.12.2 * * See also: * ECMA-262 v5, 15.12.2 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */ ecma_object_t *holder_p, /**< holder object */ ecma_string_t *name_p) /**< property name */ { JERRY_ASSERT (reviver_p); JERRY_ASSERT (holder_p); JERRY_ASSERT (name_p); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (value_get, ecma_op_object_get (holder_p, name_p), ret_value); if (ecma_is_value_object (value_get)) { ecma_object_t *object_p = ecma_get_object_from_value (value_get); ecma_collection_header_t *props_p = ecma_op_object_get_property_names (object_p, false, true, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter) && ecma_is_value_empty (ret_value)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); ECMA_TRY_CATCH (value_walk, ecma_builtin_json_walk (reviver_p, object_p, property_name_p), ret_value); /* * We cannot optimize this function since any members * can be changed (deleted) by the reviver function. */ if (ecma_is_value_undefined (value_walk)) { ecma_value_t delete_val = ecma_op_general_object_delete (object_p, property_name_p, false); JERRY_ASSERT (ecma_is_value_boolean (delete_val)); } else { ecma_builtin_json_define_value_property (object_p, property_name_p, value_walk); } ECMA_FINALIZE (value_walk); } ecma_free_values_collection (props_p, true); } if (ecma_is_value_empty (ret_value)) { ecma_value_t arguments_list[2]; arguments_list[0] = ecma_make_string_value (name_p); arguments_list[1] = value_get; /* * The completion value can be anything including exceptions. */ ret_value = ecma_op_function_call (reviver_p, ecma_make_object_value (holder_p), arguments_list, 2); } else { JERRY_ASSERT (ecma_is_value_error (ret_value)); } ECMA_FINALIZE (value_get); return ret_value; } /* ecma_builtin_json_walk */
/** * Parse next value. * * The function fills the fields of the ecma_json_token_t * argument and advances the string pointer. * * @return ecma_value with the property value */ static ecma_value_t ecma_builtin_json_parse_value (ecma_json_token_t *token_p) /**< token argument */ { ecma_builtin_json_parse_next_token (token_p); switch (token_p->type) { case number_token: { ecma_number_t *number_p = ecma_alloc_number (); *number_p = token_p->u.number; return ecma_make_number_value (number_p); } case string_token: { ecma_string_t *string_p = ecma_new_ecma_string_from_utf8 (token_p->u.string.start_p, token_p->u.string.size); return ecma_make_string_value (string_p); } case null_token: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); } case true_token: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } case false_token: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } case left_brace_token: { bool parse_comma = false; ecma_object_t *object_p = ecma_op_create_object_object_noarg (); while (true) { ecma_builtin_json_parse_next_token (token_p); if (token_p->type == right_brace_token) { return ecma_make_object_value (object_p); } if (parse_comma) { if (token_p->type != comma_token) { break; } ecma_builtin_json_parse_next_token (token_p); } if (token_p->type != string_token) { break; } lit_utf8_byte_t *string_start_p = token_p->u.string.start_p; lit_utf8_size_t string_size = token_p->u.string.size; ecma_builtin_json_parse_next_token (token_p); if (token_p->type != colon_token) { break; } ecma_value_t value = ecma_builtin_json_parse_value (token_p); if (ecma_is_value_undefined (value)) { break; } ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (string_start_p, string_size); ecma_builtin_json_define_value_property (object_p, name_p, value); ecma_deref_ecma_string (name_p); ecma_free_value (value); parse_comma = true; } /* * Parse error occured. */ ecma_deref_object (object_p); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } case left_square_token: { bool parse_comma = false; uint32_t length = 0; ecma_value_t array_construction = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ecma_is_value_error (array_construction)); ecma_object_t *array_p = ecma_get_object_from_value (array_construction); while (true) { if (ecma_builtin_json_check_right_square_token (token_p)) { return ecma_make_object_value (array_p); } if (parse_comma) { ecma_builtin_json_parse_next_token (token_p); if (token_p->type != comma_token) { break; } } ecma_value_t value = ecma_builtin_json_parse_value (token_p); if (ecma_is_value_undefined (value)) { break; } ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (length); ecma_value_t completion = ecma_builtin_helper_def_prop (array_p, index_str_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_str_p); ecma_free_value (value); length++; parse_comma = true; } /* * Parse error occured. */ ecma_deref_object (array_p); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } default: { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } } /* ecma_builtin_json_parse_value */