/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ bool is_enumerable, /**< 'enumerable' attribute */ bool is_configurable) /**< 'configurable' attribute */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR; if (is_configurable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_CONFIGURABLE); } if (is_enumerable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_ENUMERABLE); } name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_t *property_p = ecma_create_property (object_p, name_p, type_and_flags); /* * Should be performed after linking the property into object's property list, because the setters assert that. */ ecma_set_named_accessor_property_getter (object_p, property_p, get_p); ecma_set_named_accessor_property_setter (object_p, property_p, set_p); ecma_lcache_invalidate (object_p, name_p, NULL); return property_p; } /* ecma_create_named_accessor_property */
/** * The String.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.5.4.2 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ { if (ecma_is_value_string (this_arg)) { return ecma_make_normal_completion_value (ecma_copy_value (this_arg, true)); } else if (ecma_is_value_object (this_arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_STRING_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ecma_string_t *prim_value_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prim_value_prop_p->u.internal_property.value); prim_value_str_p = ecma_copy_or_ref_ecma_string (prim_value_str_p); return ecma_make_normal_completion_value (ecma_make_string_value (prim_value_str_p)); } } return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } /* ecma_builtin_string_prototype_object_to_string */
/** * Create named data property with given name, attributes and undefined value * in the specified object. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ bool is_writable, /**< 'Writable' attribute */ bool is_enumerable, /**< 'Enumerable' attribute */ bool is_configurable) /**< 'Configurable' attribute */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDDATA; if (is_configurable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_CONFIGURABLE); } if (is_enumerable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_ENUMERABLE); } if (is_writable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_WRITABLE); } name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_t *property_p = ecma_create_property (object_p, name_p, type_and_flags); ecma_set_named_data_property_value (property_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ecma_lcache_invalidate (object_p, name_p, NULL); return property_p; } /* ecma_create_named_data_property */
/** * ToString operation. * * See also: * ECMA-262 v5, 9.8 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_to_string (ecma_value_t value) /**< ecma-value */ { ecma_check_value_type_is_spec_defined (value); if (unlikely (ecma_is_value_object (value))) { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ECMA_TRY_CATCH (prim_value, ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING), ret_value); ret_value = ecma_op_to_string (prim_value); ECMA_FINALIZE (prim_value); return ret_value; } else { ecma_string_t *res_p = NULL; if (ecma_is_value_string (value)) { res_p = ecma_get_string_from_value (value); res_p = ecma_copy_or_ref_ecma_string (res_p); } else if (ecma_is_value_number (value)) { ecma_number_t *num_p = ecma_get_number_from_value (value); res_p = ecma_new_ecma_string_from_number (*num_p); } else if (ecma_is_value_undefined (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); } else if (ecma_is_value_null (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); if (ecma_is_value_true (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); } else { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); } } return ecma_make_normal_completion_value (ecma_make_string_value (res_p)); } } /* ecma_op_to_string */
/** * The String.prototype object's 'concat' routine * * See also: * ECMA-262 v5, 15.5.4.6 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_concat (ecma_value_t this_arg, /**< this argument */ const ecma_value_t* argument_list_p, /**< arguments list */ ecma_length_t arguments_number) /**< number of arguments */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ // No copy performed /* 4 */ ecma_string_t *string_to_return = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (to_string_val)); /* 5 */ for (uint32_t arg_index = 0; arg_index < arguments_number && ecma_is_completion_value_empty (ret_value); ++arg_index) { /* 5a */ /* 5b */ ecma_string_t *string_temp = string_to_return; ECMA_TRY_CATCH (get_arg_string, ecma_op_to_string (argument_list_p[arg_index]), ret_value); string_to_return = ecma_concat_ecma_strings (string_to_return, ecma_get_string_from_value (get_arg_string)); ecma_deref_ecma_string (string_temp); ECMA_FINALIZE (get_arg_string); } /* 6 */ if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_normal_completion_value (ecma_make_string_value (string_to_return)); } else { ecma_deref_ecma_string (string_to_return); } ECMA_FINALIZE (to_string_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_concat */
/** * Copy ecma value. * * Note: * Operation algorithm. * switch (valuetype) * case simple: * simply return the value as it was passed; * case number: * copy the number * and return new ecma value * pointing to copy of the number; * case string: * increase reference counter of the string * and return the value as it was passed. * case object; * increase reference counter of the object if do_ref_if_object is true * and return the value as it was passed. * * @return See note. */ ecma_value_t ecma_copy_value (ecma_value_t value, /**< ecma value */ bool do_ref_if_object) /**< if the value is object value, increment reference counter of the object */ { ecma_value_t value_copy = 0; switch (ecma_get_value_type_field (value)) { case ECMA_TYPE_SIMPLE: { value_copy = value; break; } case ECMA_TYPE_NUMBER: { ecma_number_t *num_p = ecma_get_number_from_value (value); ecma_number_t *number_copy_p = ecma_alloc_number (); *number_copy_p = *num_p; value_copy = ecma_make_number_value (number_copy_p); break; } case ECMA_TYPE_STRING: { ecma_string_t *string_p = ecma_get_string_from_value (value); string_p = ecma_copy_or_ref_ecma_string (string_p); value_copy = ecma_make_string_value (string_p); break; } case ECMA_TYPE_OBJECT: { ecma_object_t *obj_p = ecma_get_object_from_value (value); if (do_ref_if_object) { ecma_ref_object (obj_p); } value_copy = value; break; } } return value_copy; } /* ecma_copy_value */
/** * Create named data property with given name, attributes and undefined value * in the specified object. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ uint8_t prop_attributes) /**< property attributes (See: ecma_property_flags_t) */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDDATA | prop_attributes; name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_value_t value; value.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); return ecma_create_property (object_p, name_p, type_and_flags, value); } /* ecma_create_named_data_property */
/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ uint8_t prop_attributes) /**< property attributes */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes; name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_value_t value; ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p); ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p); return ecma_create_property (object_p, name_p, type_and_flags, value); } /* ecma_create_named_accessor_property */
/** * Handle calling [[Construct]] of built-in RegExp object * * @return completion-value */ ecma_completion_value_t ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< number of arguments */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_value_t pattern_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ecma_value_t flags_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); if (arguments_list_len > 0) { /* pattern string or RegExp object */ pattern_value = arguments_list_p[0]; if (arguments_list_len > 1) { flags_value = arguments_list_p[1]; } } if (ecma_is_value_object (pattern_value) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_value)) == LIT_MAGIC_STRING_REGEXP_UL) { if (ecma_is_value_undefined (flags_value)) { ret_value = ecma_make_normal_completion_value (ecma_copy_value (pattern_value, true)); } else { ret_value = ecma_raise_type_error ("Invalid argument of RegExp call."); } } else { ecma_string_t *pattern_string_p = NULL; ecma_string_t *flags_string_p = NULL; if (!ecma_is_value_undefined (pattern_value)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_value), ret_value); if (ecma_string_get_length (ecma_get_string_from_value (regexp_str_value)) == 0) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (regexp_str_value)); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } if (ecma_is_completion_value_empty (ret_value) && !ecma_is_value_undefined (flags_value)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_value), ret_value); flags_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (flags_str_value)); ECMA_FINALIZE (flags_str_value); } if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_op_create_regexp_object (pattern_string_p, flags_string_p); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } if (flags_string_p != NULL) { ecma_deref_ecma_string (flags_string_p); } } return ret_value; } /* ecma_builtin_regexp_dispatch_construct */
/** * Insert an entry into LCache */ void ecma_lcache_insert (ecma_object_t *object_p, /**< object */ ecma_string_t *prop_name_p, /**< property's name */ ecma_property_t *prop_p) /**< pointer to associated property or NULL * (NULL indicates that the object doesn't have property * with the name specified) */ { JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (prop_name_p != NULL); #ifndef CONFIG_ECMA_LCACHE_DISABLE prop_name_p = ecma_copy_or_ref_ecma_string (prop_name_p); lit_string_hash_t hash_key = ecma_string_hash (prop_name_p); if (prop_p != NULL) { if (unlikely (ecma_is_property_lcached (prop_p))) { int32_t entry_index; for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++) { if (ecma_lcache_hash_table[hash_key][entry_index].object_cp != ECMA_NULL_POINTER && ecma_lcache_hash_table[hash_key][entry_index].prop_p == prop_p) { #ifndef JERRY_NDEBUG ecma_object_t *obj_in_entry_p; obj_in_entry_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, ecma_lcache_hash_table[hash_key][entry_index].object_cp); JERRY_ASSERT (obj_in_entry_p == object_p); #endif /* !JERRY_NDEBUG */ break; } } JERRY_ASSERT (entry_index != ECMA_LCACHE_HASH_ROW_LENGTH); ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][entry_index]); } JERRY_ASSERT (!ecma_is_property_lcached (prop_p)); ecma_set_property_lcached (prop_p, true); } int32_t entry_index; for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++) { if (ecma_lcache_hash_table[hash_key][entry_index].object_cp == ECMA_NULL_POINTER) { break; } } if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH) { /* No empty entry was found, invalidating the whole row */ for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++) { ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][i]); } entry_index = 0; } ecma_ref_object (object_p); ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].object_cp, object_p); ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_name_cp, prop_name_p); ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_p = prop_p; #else /* CONFIG_ECMA_LCACHE_DISABLE */ (void) prop_p; #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ } /* ecma_lcache_insert */
/** * The RegExp.prototype object's 'compile' routine * * See also: * ECMA-262 v5, B.2.5.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument */ ecma_value_t pattern_arg, /**< pattern or RegExp object */ ecma_value_t flags_arg) /**< flags */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (this_obj_p) != LIT_MAGIC_STRING_REGEXP_UL) { /* Compile can only be called on RegExp objects. */ ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_string_t *pattern_string_p = NULL; uint16_t flags = 0; if (ecma_is_value_object (pattern_arg) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_arg)) == LIT_MAGIC_STRING_REGEXP_UL) { if (!ecma_is_value_undefined (flags_arg)) { ret_value = ecma_raise_type_error ("Invalid argument of RegExp compile."); } else { /* Compile from existing RegExp pbject. */ ecma_object_t *target_p = ecma_get_object_from_value (pattern_arg); /* Get source. */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *prop_p = ecma_get_named_data_property (target_p, magic_string_p); pattern_string_p = ecma_get_string_from_value (ecma_get_named_data_property_value (prop_p)); ecma_deref_ecma_string (magic_string_p); /* Get flags. */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); prop_p = ecma_get_named_data_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_GLOBAL; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); prop_p = ecma_get_named_data_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_IGNORE_CASE; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); prop_p = ecma_get_named_data_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_MULTILINE; } ecma_deref_ecma_string (magic_string_p); /* Get bytecode property. */ ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* FIXME: "We currently have to re-compile the bytecode, because * we can't copy it without knowing its length." */ re_compiled_code_t *new_bc_p = NULL; ecma_completion_value_t bc_comp = re_compile_bytecode (&new_bc_p, pattern_string_p, flags); /* Should always succeed, since we're compiling from a source that has been compiled previously. */ JERRY_ASSERT (ecma_is_completion_value_empty (bc_comp)); re_compiled_code_t *old_bc_p = ECMA_GET_POINTER (re_compiled_code_t, bc_prop_p->u.internal_property.value); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_POINTER (bc_prop_p->u.internal_property.value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_normal_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); } } else { /* Get source string. */ if (!ecma_is_value_undefined (pattern_arg)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_arg), ret_value); if (ecma_string_get_length (ecma_get_string_from_value (regexp_str_value)) == 0) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (regexp_str_value)); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } /* Parse flags. */ if (ecma_is_completion_value_empty (ret_value) && !ecma_is_value_undefined (flags_arg)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_arg), ret_value); ECMA_TRY_CATCH (flags_dummy, re_parse_regexp_flags (ecma_get_string_from_value (flags_str_value), &flags), ret_value); ECMA_FINALIZE (flags_dummy); ECMA_FINALIZE (flags_str_value); } if (ecma_is_completion_value_empty (ret_value)) { ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Try to compile bytecode from new source. */ re_compiled_code_t *new_bc_p = NULL; ECMA_TRY_CATCH (bc_dummy, re_compile_bytecode (&new_bc_p, pattern_string_p, flags), ret_value); re_compiled_code_t *old_bc_p = ECMA_GET_POINTER (re_compiled_code_t, bc_prop_p->u.internal_property.value); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_POINTER (bc_prop_p->u.internal_property.value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_normal_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ECMA_FINALIZE (bc_dummy); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } } } return ret_value; } /* ecma_builtin_regexp_prototype_compile */
/** * The RegExp.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.10.6.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_regexp_prototype_to_string (ecma_value_t this_arg) /**< this argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (!ecma_is_value_object (this_arg) || ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_REGEXP_UL) { ret_value = ecma_raise_type_error ("Incomplete RegExp type"); } else { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); /* Get RegExp source from the source property */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *source_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); ecma_string_t *src_sep_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_SLASH_CHAR); ecma_string_t *source_str_p = ecma_get_string_from_value (source_prop_p->u.named_data_property.value); ecma_string_t *output_str_p = ecma_concat_ecma_strings (src_sep_str_p, ecma_copy_or_ref_ecma_string (source_str_p)); ecma_deref_ecma_string (source_str_p); ecma_string_t *concat_p = ecma_concat_ecma_strings (output_str_p, src_sep_str_p); ecma_deref_ecma_string (src_sep_str_p); ecma_deref_ecma_string (output_str_p); output_str_p = concat_p; /* Check the global flag */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); ecma_property_t *global_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); if (ecma_is_value_true (global_prop_p->u.named_data_property.value)) { ecma_string_t *g_flag_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_G_CHAR); concat_p = ecma_concat_ecma_strings (output_str_p, g_flag_str_p); ecma_deref_ecma_string (output_str_p); ecma_deref_ecma_string (g_flag_str_p); output_str_p = concat_p; } /* Check the ignoreCase flag */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); ecma_property_t *ignorecase_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); if (ecma_is_value_true (ignorecase_prop_p->u.named_data_property.value)) { ecma_string_t *ic_flag_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_I_CHAR); concat_p = ecma_concat_ecma_strings (output_str_p, ic_flag_str_p); ecma_deref_ecma_string (output_str_p); ecma_deref_ecma_string (ic_flag_str_p); output_str_p = concat_p; } /* Check the global flag */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); ecma_property_t *multiline_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); if (ecma_is_value_true (multiline_prop_p->u.named_data_property.value)) { ecma_string_t *m_flag_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_M_CHAR); concat_p = ecma_concat_ecma_strings (output_str_p, m_flag_str_p); ecma_deref_ecma_string (output_str_p); ecma_deref_ecma_string (m_flag_str_p); output_str_p = concat_p; } ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p)); ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_regexp_prototype_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 */
/** * ToString operation. * * See also: * ECMA-262 v5, 9.8 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_string (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (unlikely (ecma_is_value_object (value))) { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (prim_value, ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING), ret_value); ret_value = ecma_op_to_string (prim_value); ECMA_FINALIZE (prim_value); return ret_value; } else { ecma_string_t *res_p = NULL; if (ecma_is_value_string (value)) { res_p = ecma_get_string_from_value (value); res_p = ecma_copy_or_ref_ecma_string (res_p); } else if (ecma_is_value_integer_number (value)) { ecma_integer_value_t num = ecma_get_integer_from_value (value); if (num < 0) { res_p = ecma_new_ecma_string_from_number ((ecma_number_t) num); } else { res_p = ecma_new_ecma_string_from_uint32 ((uint32_t) num); } } else if (ecma_is_value_float_number (value)) { ecma_number_t num = ecma_get_float_from_value (value); res_p = ecma_new_ecma_string_from_number (num); } else if (ecma_is_value_undefined (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); } else if (ecma_is_value_null (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); if (ecma_is_value_true (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); } else { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); } } return ecma_make_string_value (res_p); } } /* ecma_op_to_string */
/** * The Error.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.11.4.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_error_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // 2. if (!ecma_is_value_object (this_arg)) { 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 (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_completion_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_normal_completion_value (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_completion_value_normal (name_to_str_completion))) { ret_value = ecma_copy_completion_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_completion_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_normal_completion_value (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_completion_value_normal (msg_to_str_completion))) { ret_value = ecma_copy_completion_value (msg_to_str_completion); } else { ecma_string_t *name_string_p = ecma_get_string_from_completion_value (name_to_str_completion); ecma_string_t *msg_string_p = ecma_get_string_from_completion_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 size = (ecma_string_get_size (name_string_p) + ecma_string_get_size (msg_string_p) + lit_get_magic_string_size (LIT_MAGIC_STRING_COLON_CHAR) + lit_get_magic_string_size (LIT_MAGIC_STRING_SPACE_CHAR)); const ssize_t buffer_size = (ssize_t) size; ssize_t buffer_size_left = buffer_size; MEM_DEFINE_LOCAL_ARRAY (ret_str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *ret_str_buffer_p = ret_str_buffer; ssize_t bytes = ecma_string_to_utf8_string (name_string_p, ret_str_buffer_p, buffer_size_left); JERRY_ASSERT (bytes >= 0 && buffer_size_left - bytes >= 0); buffer_size_left -= bytes; ret_str_buffer_p = ret_str_buffer + buffer_size - buffer_size_left; ret_str_buffer_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_COLON_CHAR, ret_str_buffer_p, buffer_size_left); buffer_size_left = buffer_size - (ret_str_buffer_p - ret_str_buffer); JERRY_ASSERT (buffer_size_left >= 0); ret_str_buffer_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_SPACE_CHAR, ret_str_buffer_p, buffer_size_left); buffer_size_left = buffer_size - (ret_str_buffer_p - ret_str_buffer); JERRY_ASSERT (buffer_size_left >= 0); bytes = ecma_string_to_utf8_string (msg_string_p, ret_str_buffer_p, buffer_size_left); JERRY_ASSERT (bytes >= 0 && buffer_size_left - bytes >= 0); buffer_size_left -= bytes; JERRY_ASSERT (buffer_size_left >= 0); ret_str_p = ecma_new_ecma_string_from_utf8 (ret_str_buffer, (jerry_api_size_t) (buffer_size - buffer_size_left)); MEM_FINALIZE_LOCAL_ARRAY (ret_str_buffer); } ret_value = ecma_make_normal_completion_value (ecma_make_string_value (ret_str_p)); } ecma_free_completion_value (msg_to_str_completion); ECMA_FINALIZE (msg_get_ret_value); ecma_deref_ecma_string (message_magic_string_p); } ecma_free_completion_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 */
/** * Abstract operation 'Quote' 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_quote (ecma_string_t *string_p) /**< string that should be quoted*/ { /* 1. */ ecma_string_t *quote_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR); ecma_string_t *product_str_p = ecma_copy_or_ref_ecma_string (quote_str_p); ecma_string_t *tmp_str_p; ecma_length_t string_size = ecma_string_get_size (string_p); MEM_DEFINE_LOCAL_ARRAY (string_buff, string_size, lit_utf8_byte_t); ssize_t bytes_copied = ecma_string_to_utf8_string (string_p, string_buff, (ssize_t) string_size); JERRY_ASSERT (bytes_copied > 0 || !string_size); lit_utf8_byte_t *str_p = string_buff; const lit_utf8_byte_t *str_end_p = str_p + string_size; while (str_p < str_end_p) { ecma_char_t current_char = lit_utf8_read_next (&str_p); /* 2.a */ if (current_char == LIT_CHAR_BACKSLASH || current_char == LIT_CHAR_DOUBLE_QUOTE) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.a.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.a.ii */ ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char); tmp_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (current_char_str_p); product_str_p = tmp_str_p; } /* 2.b */ else if (current_char == LIT_CHAR_BS || current_char == LIT_CHAR_FF || current_char == LIT_CHAR_LF || current_char == LIT_CHAR_CR || current_char == LIT_CHAR_TAB) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.b.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.b.ii */ lit_utf8_byte_t abbrev = LIT_CHAR_SP; switch (current_char) { case LIT_CHAR_BS: { abbrev = LIT_CHAR_LOWERCASE_B; break; } case LIT_CHAR_FF: { abbrev = LIT_CHAR_LOWERCASE_F; break; } case LIT_CHAR_LF: { abbrev = LIT_CHAR_LOWERCASE_N; break; } case LIT_CHAR_CR: { abbrev = LIT_CHAR_LOWERCASE_R; break; } case LIT_CHAR_TAB: { abbrev = LIT_CHAR_LOWERCASE_T; break; } } /* 2.b.iii */ ecma_string_t *abbrev_str_p = ecma_new_ecma_string_from_utf8 (&abbrev, 1); tmp_str_p = ecma_concat_ecma_strings (product_str_p, abbrev_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (abbrev_str_p); product_str_p = tmp_str_p; } /* 2.c */ else if (current_char < LIT_CHAR_SP) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.c.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.c.ii */ lit_utf8_byte_t u_ch = LIT_CHAR_LOWERCASE_U; ecma_string_t *u_ch_str_p = ecma_new_ecma_string_from_utf8 (&u_ch, 1); tmp_str_p = ecma_concat_ecma_strings (product_str_p, u_ch_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (u_ch_str_p); product_str_p = tmp_str_p; /* 2.c.iii */ ecma_string_t *hex_str_p = ecma_builtin_helper_json_create_hex_digit_ecma_string ((uint8_t) current_char); /* 2.c.iv */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, hex_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (hex_str_p); product_str_p = tmp_str_p; } /* 2.d */ else { ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char); tmp_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (current_char_str_p); product_str_p = tmp_str_p; } } MEM_FINALIZE_LOCAL_ARRAY (string_buff); /* 3. */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, quote_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (quote_str_p); product_str_p = tmp_str_p; /* 4. */ return ecma_make_string_value (product_str_p); } /* ecma_builtin_json_quote */
/** * [[GetOwnProperty]] ecma String object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.5.5.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_property_t * ecma_op_string_object_get_own_property (ecma_object_t *obj_p, /**< a String object */ ecma_string_t *property_name_p) /**< property name */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING); // 1. ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); // 2. if (prop_p != NULL) { return prop_p; } // 3., 5. uint32_t uint32_index; ecma_string_t *new_prop_name_p; if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) { uint32_index = property_name_p->u.uint32_number; new_prop_name_p = ecma_copy_or_ref_ecma_string (property_name_p); } else { ecma_number_t index = ecma_string_to_number (property_name_p); uint32_index = ecma_number_to_uint32 (index); ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (uint32_index); bool are_equal = ecma_compare_ecma_strings (to_str_p, property_name_p); if (!are_equal) { ecma_deref_ecma_string (to_str_p); return NULL; } else { new_prop_name_p = to_str_p; } } // 4. ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ecma_string_t *prim_value_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, ECMA_PROPERTY_VALUE_PTR (prim_value_prop_p)->value); // 6. ecma_length_t length = ecma_string_get_length (prim_value_str_p); ecma_property_t *new_prop_p; if (uint32_index >= (uint32_t) length) { // 7. new_prop_p = NULL; } else { // 8. ecma_char_t c = ecma_string_get_char_at_pos (prim_value_str_p, uint32_index); // 9. ecma_string_t *new_prop_str_value_p = ecma_new_ecma_string_from_code_unit (c); new_prop_p = ecma_create_named_data_property (obj_p, new_prop_name_p, false, true, false); ecma_set_named_data_property_value (new_prop_p, ecma_make_string_value (new_prop_str_value_p)); } ecma_deref_ecma_string (new_prop_name_p); return new_prop_p; } /* ecma_op_string_object_get_own_property */
/** * 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 */