/**
 * Check if passed string equals to one of magic strings
 * and if equal magic string was found, return it's id in 'out_id_p' argument.
 *
 * @return true - if magic string equal to passed string was found,
 *         false - otherwise.
 */
bool
ecma_is_string_magic (const ecma_string_t *string_p, /**< ecma-string */
                      lit_magic_string_id_t *out_id_p) /**< [out] magic string's id */
{
  if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING)
  {
    JERRY_ASSERT (string_p->u.magic_string_id < LIT_MAGIC_STRING__COUNT);

    *out_id_p = (lit_magic_string_id_t) string_p->u.magic_string_id;

    return true;
  }
  else
  {
    /*
     * Any ecma-string constructor except ecma_concat_ecma_strings
     * should return ecma-string with ECMA_STRING_CONTAINER_MAGIC_STRING
     * container type if new ecma-string's content is equal to one of magic strings.
     */
#ifndef JERRY_NDEBUG
    JERRY_ASSERT (ecma_string_get_length (string_p) > LIT_MAGIC_STRING_LENGTH_LIMIT
                  || !ecma_is_string_magic_longpath (string_p, out_id_p));
#endif /* !JERRY_NDEBUG */

    return false;
  }
} /* ecma_is_string_magic */
/**
 * The String.prototype object's 'charCodeAt' routine
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.5
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_string_prototype_object_char_code_at (ecma_value_t this_arg, /**< this argument */
                                                   ecma_value_t arg) /**< routine's argument */
{
  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 */
  ECMA_OP_TO_NUMBER_TRY_CATCH (index_num,
                               arg,
                               ret_value);

  /* 4 */
  ecma_string_t *original_string_p = ecma_get_string_from_value (to_string_val);
  const ecma_length_t len = ecma_string_get_length (original_string_p);

  ecma_number_t *ret_num_p = ecma_alloc_number ();

  /* 5 */
  // When index_num is NaN, then the first two comparisons are false
  if (index_num < 0 || index_num >= len || (ecma_number_is_nan (index_num) && !len))
  {
    *ret_num_p = ecma_number_make_nan ();
  }
  else
  {
    /* 6 */
    /*
     * String length is currently uit32_t, but index_num may be bigger,
     * ToInteger performs floor, while ToUInt32 performs modulo 2^32,
     * hence after the check 0 <= index_num < len we assume to_uint32 can be used.
     * We assume to_uint32 (NaN) is 0.
     */
    JERRY_ASSERT (ecma_number_is_nan (index_num) || ecma_number_to_uint32 (index_num) == ecma_number_trunc (index_num));

    ecma_char_t new_ecma_char = ecma_string_get_char_at_pos (original_string_p, ecma_number_to_uint32 (index_num));
    *ret_num_p = ecma_uint32_to_number (new_ecma_char);
  }

  ecma_value_t new_value = ecma_make_number_value (ret_num_p);
  ret_value = ecma_make_normal_completion_value (new_value);

  ECMA_OP_TO_NUMBER_FINALIZE (index_num);

  ECMA_FINALIZE (to_string_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_string_prototype_object_char_code_at */
/**
 * Helper function for string indexOf and lastIndexOf functions
 *
 * This function implements string indexOf and lastIndexOf with required checks and conversions.
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.7
 *          ECMA-262 v5, 15.5.4.8
 *
 * Used by:
 *         - The String.prototype.indexOf routine.
 *         - The String.prototype.lastIndexOf routine.
 *
 * @return uint32_t - (last) index of search string
 */
ecma_value_t
ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */
                                                      ecma_value_t arg1, /**< routine's first argument */
                                                      ecma_value_t arg2, /**< routine's second argument */
                                                      bool first_index) /**< routine's third argument */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 1 */
  ECMA_TRY_CATCH (check_coercible_val,
                  ecma_op_check_object_coercible (this_arg),
                  ret_value);

  /* 2 */
  ECMA_TRY_CATCH (to_str_val,
                  ecma_op_to_string (this_arg),
                  ret_value);

  /* 3 */
  ECMA_TRY_CATCH (search_str_val,
                  ecma_op_to_string (arg1),
                  ret_value);

  /* 4 */
  ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num,
                               arg2,
                               ret_value);

  /* 5 (indexOf) -- 6 (lastIndexOf) */
  ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val);
  const ecma_length_t original_len = ecma_string_get_length (original_str_p);

  /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */
  ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, first_index);

  /* 7 (indexOf) -- 8 (lastIndexOf) */
  ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val);

  ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE;

  /* 8 (indexOf) -- 9 (lastIndexOf) */
  ecma_length_t index_of = 0;
  if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, first_index, start, &index_of))
  {
    ret_num = ((ecma_number_t) index_of);
  }

  ret_value = ecma_make_number_value (ret_num);

  ECMA_OP_TO_NUMBER_FINALIZE (pos_num);
  ECMA_FINALIZE (search_str_val);
  ECMA_FINALIZE (to_str_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_helper_string_prototype_object_index_of */
/**
 * ToBoolean operation.
 *
 * See also:
 *          ECMA-262 v5, 9.2
 *
 * @return completion value
 *         Returned value is simple and so need not be freed.
 *         However, ecma_free_completion_value may be called for it, but it is a no-op.
 */
ecma_completion_value_t
ecma_op_to_boolean (ecma_value_t value) /**< ecma-value */
{
  ecma_check_value_type_is_spec_defined (value);

  ecma_simple_value_t ret_value;

  if (ecma_is_value_boolean (value))
  {
    ret_value = (ecma_is_value_true (value) ?
                 ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE);
  }
  else if (ecma_is_value_undefined (value)
           || ecma_is_value_null (value))
  {
    ret_value = ECMA_SIMPLE_VALUE_FALSE;
  }
  else if (ecma_is_value_number (value))
  {
    ecma_number_t *num_p = ecma_get_number_from_value (value);

    if (ecma_number_is_nan (*num_p)
        || ecma_number_is_zero (*num_p))
    {
      ret_value = ECMA_SIMPLE_VALUE_FALSE;
    }
    else
    {
      ret_value = ECMA_SIMPLE_VALUE_TRUE;
    }
  }
  else if (ecma_is_value_string (value))
  {
    ecma_string_t *str_p = ecma_get_string_from_value (value);

    if (ecma_string_get_length (str_p) == 0)
    {
      ret_value = ECMA_SIMPLE_VALUE_FALSE;
    }
    else
    {
      ret_value = ECMA_SIMPLE_VALUE_TRUE;
    }
  }
  else
  {
    JERRY_ASSERT (ecma_is_value_object (value));

    ret_value = ECMA_SIMPLE_VALUE_TRUE;
  }

  return ecma_make_simple_completion_value (ret_value);
} /* ecma_op_to_boolean */
/**
 * The String.prototype object's 'charAt' routine
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.4
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_string_prototype_object_char_at (ecma_value_t this_arg, /**< this argument */
                                              ecma_value_t arg) /**< routine's argument */
{
  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 */
  ECMA_OP_TO_NUMBER_TRY_CATCH (index_num,
                               arg,
                               ret_value);

  /* 4 */
  ecma_string_t *original_string_p = ecma_get_string_from_value (to_string_val);
  const ecma_length_t len = ecma_string_get_length (original_string_p);

  /* 5 */
  if (index_num < 0 || index_num >= len || !len)
  {
    ret_value = ecma_make_normal_completion_value (ecma_make_string_value (
                                                   ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY)));
  }
  else
  {
    /* 6 */
    ecma_char_t new_ecma_char = ecma_string_get_char_at_pos (original_string_p, ecma_number_to_uint32 (index_num));
    ret_value = ecma_make_normal_completion_value (ecma_make_string_value (
                                                   ecma_new_ecma_string_from_code_unit (new_ecma_char)));
  }

  ECMA_OP_TO_NUMBER_FINALIZE (index_num);

  ECMA_FINALIZE (to_string_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_string_prototype_object_char_at */
/**
 * List names of a String object's lazy instantiated properties
 *
 * @return string values collection
 */
void
ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */
                                         bool separate_enumerable, /**< true -  list enumerable properties
                                                                    *           into main collection,
                                                                    *           and non-enumerable to collection of
                                                                    *           'skipped non-enumerable' properties,
                                                                    *   false - list all properties into main
                                                                    *           collection.
                                                                    */
                                         ecma_collection_header_t *main_collection_p, /**< 'main'
                                                                                       *   collection */
                                         ecma_collection_header_t *non_enum_collection_p) /**< skipped
                                                                                           *   'non-enumerable'
                                                                                           *   collection */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS);

  ecma_collection_header_t *for_enumerable_p = main_collection_p;

  ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;

  ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
  JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL);

  ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.class_prop.u.value);

  ecma_length_t length = ecma_string_get_length (prim_value_str_p);

  for (ecma_length_t i = 0; i < length; i++)
  {
    ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i);

    /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */
    ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), 0);

    ecma_deref_ecma_string (name_p);
  }

  ecma_append_to_values_collection (for_non_enumerable_p,
                                    ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH),
                                    0);
} /* ecma_op_string_list_lazy_property_names */
/**
 * List names of a String object's lazy instantiated properties
 *
 * See also:
 *          ecma_op_string_object_get_own_property
 *
 * @return string values collection
 */
void
ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */
                                         bool separate_enumerable, /**< true -  list enumerable properties
                                                                    *           into main collection,
                                                                    *           and non-enumerable to collection of
                                                                    *           'skipped non-enumerable' properties,
                                                                    *   false - list all properties into main
                                                                    *           collection.
                                                                    */
                                         ecma_collection_header_t *main_collection_p, /**< 'main'
                                                                                       *   collection */
                                         ecma_collection_header_t *non_enum_collection_p) /**< skipped
                                                                                           *   'non-enumerable'
                                                                                           *   collection
                                                                                                        */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING);

  ecma_collection_header_t *for_enumerable_p = main_collection_p;

  ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? main_collection_p : non_enum_collection_p;
  JERRY_UNUSED (for_non_enumerable_p);

  ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p,
                                                                   ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
  ecma_string_t *prim_value_str_p;
  prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p));

  ecma_length_t length = ecma_string_get_length (prim_value_str_p);

  for (ecma_length_t i = 0; i < length; i++)
  {
    ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i);

    /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */
    ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), true);

    ecma_deref_ecma_string (name_p);
  }
} /* ecma_op_string_list_lazy_property_names */
Beispiel #8
0
/**
 * ToBoolean operation. Cannot throw an exception.
 *
 * See also:
 *          ECMA-262 v5, 9.2
 *
 * @return true if the logical value is true
 *         false otherwise
 */
bool
ecma_op_to_boolean (ecma_value_t value) /**< ecma value */
{
  ecma_check_value_type_is_spec_defined (value);

  if (ecma_is_value_simple (value))
  {
    JERRY_ASSERT (ecma_is_value_boolean (value)
                  || ecma_is_value_undefined (value)
                  || ecma_is_value_null (value));

    return ecma_is_value_true (value);
  }

  if (ecma_is_value_integer_number (value))
  {
    return (value != ecma_make_integer_value (0));
  }

  if (ecma_is_value_float_number (value))
  {
    ecma_number_t num = ecma_get_float_from_value (value);

    return (!ecma_number_is_nan (num) && !ecma_number_is_zero (num));
  }

  if (ecma_is_value_string (value))
  {
    ecma_string_t *str_p = ecma_get_string_from_value (value);

    return ecma_string_get_length (str_p) != 0;
  }

  JERRY_ASSERT (ecma_is_value_object (value));

  return true;
} /* ecma_op_to_boolean */
/**
 * Convert decimal value to 4 digit hexadecimal string value.
 *
 * See also:
 *          ECMA-262 v5, 15.12.3
 *
 * Used by:
 *         - ecma_builtin_json_quote step 2.c.iii
 *
 * @return pointer to ecma-string
 *         Returned value must be freed with ecma_deref_ecma_string.
 */
ecma_string_t *
ecma_builtin_helper_json_create_hex_digit_ecma_string (uint8_t value) /**< value in decimal*/
{
  /* 2.c.iii */
  ecma_string_t *hex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);

  JMEM_DEFINE_LOCAL_ARRAY (hex_buff, 4, lit_utf8_byte_t);

  for (uint32_t i = 0; i < 4; i++)
  {
    uint8_t remainder = value % 16;
    lit_utf8_byte_t ch = ' ';

    if (remainder < 10)
    {
      ch = (lit_utf8_byte_t) (LIT_CHAR_0 + remainder);
    }
    else
    {
      uint8_t a = (uint8_t) (remainder - 10);
      ch = (lit_utf8_byte_t) (LIT_CHAR_LOWERCASE_A + a);
    }

    hex_buff[3 - i] = ch;

    value = value / 16;
  }

  ecma_deref_ecma_string (hex_str_p);
  hex_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) hex_buff, 4);

  JMEM_FINALIZE_LOCAL_ARRAY (hex_buff);

  JERRY_ASSERT (ecma_string_get_length (hex_str_p));

  return hex_str_p;
} /* ecma_builtin_helper_json_create_hex_digit_ecma_string */
/**
 * Get character from specified position in the ecma-string.
 *
 * @return character value
 */
ecma_char_t
ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */
                             ecma_length_t index) /**< index of character */
{
  JERRY_ASSERT (index < ecma_string_get_length (string_p));

  lit_utf8_size_t buffer_size;
  bool is_ascii;
  const lit_utf8_byte_t *chars_p = ecma_string_raw_chars (string_p, &buffer_size, &is_ascii);

  if (chars_p != NULL)
  {
    if (is_ascii)
    {
      return chars_p[index];
    }

    return lit_utf8_string_code_unit_at (chars_p, buffer_size, index);
  }

  ecma_char_t ch;

  JMEM_DEFINE_LOCAL_ARRAY (utf8_str_p, buffer_size, lit_utf8_byte_t);

  ecma_string_to_utf8_bytes (string_p, utf8_str_p, buffer_size);

  JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC);
  /* Both above must be ascii strings. */
  JERRY_ASSERT (is_ascii);

  ch = utf8_str_p[index];

  JMEM_FINALIZE_LOCAL_ARRAY (utf8_str_p);

  return ch;
} /* ecma_string_get_char_at_pos */
Beispiel #11
0
int
main (int __attr_unused___ argc,
      char __attr_unused___ **argv)
{
  TEST_INIT ();

  jmem_init ();
  lit_init ();
  ecma_init ();

  lit_utf8_byte_t cesu8_string[max_bytes_in_string];
  ecma_char_t code_units[max_code_units_in_string];
  const lit_utf8_byte_t *saved_positions[max_code_units_in_string];

  for (int i = 0; i < test_iters; i++)
  {
    lit_utf8_size_t cesu8_string_size = (i == 0) ? 0 : (lit_utf8_size_t) (rand () % max_bytes_in_string);
    ecma_length_t length = generate_cesu8_string (cesu8_string, cesu8_string_size);

    ecma_string_t *char_collection_string_p = ecma_new_ecma_string_from_utf8 (cesu8_string, cesu8_string_size);
    ecma_length_t char_collection_len = ecma_string_get_length (char_collection_string_p);
    JERRY_ASSERT (char_collection_len == length);
    ecma_deref_ecma_string (char_collection_string_p);

    JERRY_ASSERT (lit_utf8_string_length (cesu8_string, cesu8_string_size) == length);

    const lit_utf8_byte_t *curr_p = cesu8_string;
    const lit_utf8_byte_t *end_p = cesu8_string + cesu8_string_size;

    ecma_length_t calculated_length = 0;
    ecma_length_t code_units_count = 0;

    while (curr_p < end_p)
    {
      code_units[code_units_count] = lit_utf8_peek_next (curr_p);
      saved_positions[code_units_count] = curr_p;
      code_units_count++;
      calculated_length++;

      lit_utf8_incr (&curr_p);
    }

    JERRY_ASSERT (length == calculated_length);

    if (code_units_count > 0)
    {
      for (int j = 0; j < test_subiters; j++)
      {
        ecma_length_t index = (ecma_length_t) rand () % code_units_count;
        curr_p = saved_positions[index];
        JERRY_ASSERT (lit_utf8_peek_next (curr_p) == code_units[index]);
      }
    }

    curr_p = (lit_utf8_byte_t *) end_p;
    while (curr_p > cesu8_string)
    {
      JERRY_ASSERT (code_units_count > 0);
      calculated_length--;
      JERRY_ASSERT (code_units[calculated_length] == lit_utf8_peek_prev (curr_p));
      lit_utf8_decr (&curr_p);
    }

    JERRY_ASSERT (calculated_length == 0);

    while (curr_p < end_p)
    {
      ecma_char_t code_unit = lit_utf8_read_next (&curr_p);
      JERRY_ASSERT (code_unit == code_units[calculated_length]);
      calculated_length++;
    }

    JERRY_ASSERT (length == calculated_length);

    while (curr_p > cesu8_string)
    {
      JERRY_ASSERT (code_units_count > 0);
      calculated_length--;
      JERRY_ASSERT (code_units[calculated_length] == lit_utf8_read_prev (&curr_p));
    }

    JERRY_ASSERT (calculated_length == 0);
  }

  /* Overlong-encoded code point */
  lit_utf8_byte_t invalid_cesu8_string_1[] = {0xC0, 0x82};
  JERRY_ASSERT (!lit_is_cesu8_string_valid (invalid_cesu8_string_1, sizeof (invalid_cesu8_string_1)));

  /* Overlong-encoded code point */
  lit_utf8_byte_t invalid_cesu8_string_2[] = {0xE0, 0x80, 0x81};
  JERRY_ASSERT (!lit_is_cesu8_string_valid (invalid_cesu8_string_2, sizeof (invalid_cesu8_string_2)));

  /* Pair of surrogates: 0xD901 0xDFF0 which encode Unicode character 0x507F0 */
  lit_utf8_byte_t invalid_cesu8_string_3[] = {0xED, 0xA4, 0x81, 0xED, 0xBF, 0xB0};
  JERRY_ASSERT (lit_is_cesu8_string_valid (invalid_cesu8_string_3, sizeof (invalid_cesu8_string_3)));

  /* Isolated high surrogate 0xD901 */
  lit_utf8_byte_t valid_utf8_string_1[] = {0xED, 0xA4, 0x81};
  JERRY_ASSERT (lit_is_cesu8_string_valid (valid_utf8_string_1, sizeof (valid_utf8_string_1)));

  lit_utf8_byte_t res_buf[3];
  lit_utf8_size_t res_size;

  res_size = lit_code_unit_to_utf8 (0x73, res_buf);
  JERRY_ASSERT (res_size == 1);
  JERRY_ASSERT (res_buf[0] == 0x73);

  res_size = lit_code_unit_to_utf8 (0x41A, res_buf);
  JERRY_ASSERT (res_size == 2);
  JERRY_ASSERT (res_buf[0] == 0xD0);
  JERRY_ASSERT (res_buf[1] == 0x9A);

  res_size = lit_code_unit_to_utf8 (0xD7FF, res_buf);
  JERRY_ASSERT (res_size == 3);
  JERRY_ASSERT (res_buf[0] == 0xED);
  JERRY_ASSERT (res_buf[1] == 0x9F);
  JERRY_ASSERT (res_buf[2] == 0xBF);

  ecma_finalize ();
  lit_finalize ();
  jmem_finalize (true);

  return 0;
} /* main */
/**
 * 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 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 */
/**
 * Helper function for finding index of a search string
 *
 * This function clamps the given index to the [0, length] range.
 * If the index is negative, 0 value is used.
 * If the index is greater than the length of the string, the normalized index will be the length of the string.
 * NaN is mapped to zero or length depending on the nan_to_zero parameter.
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.7,8,11
 *
 * Used by:
 *         - The ecma_builtin_helper_string_prototype_object_index_of helper routine.
 *         - The ecma_builtin_string_prototype_object_replace_match helper routine.
 *
 * @return uint32_t - the normalized value of the index
 */
bool
ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /**< index */
                                       ecma_string_t *search_str_p, /**< string's length */
                                       bool first_index, /**< whether search for first (t) or last (f) index */
                                       ecma_length_t start_pos, /**< start position */
                                       ecma_length_t *ret_index_p) /**< position found in original string */
{
  bool match_found = false;
  const ecma_length_t original_len = ecma_string_get_length (original_str_p);
  const ecma_length_t search_len = ecma_string_get_length (search_str_p);

  if (search_len <= original_len)
  {
    if (!search_len)
    {
      match_found = true;
      *ret_index_p = first_index ? 0 : original_len;
    }
    else
    {
      /* create utf8 string from original string and advance to position */
      ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size);

      ecma_length_t index = start_pos;

      const lit_utf8_byte_t *original_str_curr_p = original_str_utf8_p;
      for (ecma_length_t idx = 0; idx < index; idx++)
      {
        lit_utf8_incr (&original_str_curr_p);
      }

      /* create utf8 string from search string */
      ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size);

      const lit_utf8_byte_t *search_str_curr_p = search_str_utf8_p;

      /* iterate original string and try to match at each position */
      bool searching = true;
      ecma_char_t first_char = lit_utf8_read_next (&search_str_curr_p);
      while (searching)
      {
        /* match as long as possible */
        ecma_length_t match_len = 0;
        const lit_utf8_byte_t *stored_original_str_curr_p = original_str_curr_p;

        if (match_len < search_len &&
            index + match_len < original_len &&
            lit_utf8_read_next (&original_str_curr_p) == first_char)
        {
          const lit_utf8_byte_t *nested_search_str_curr_p = search_str_curr_p;
          match_len++;

          while (match_len < search_len &&
                 index + match_len < original_len &&
                 lit_utf8_read_next (&original_str_curr_p) == lit_utf8_read_next (&nested_search_str_curr_p))
          {
            match_len++;
          }
        }

        /* check for match */
        if (match_len == search_len)
        {
          match_found = true;
          *ret_index_p = index;

          break;
        }
        else
        {
          /* inc/dec index and update iterators and search condition */
          original_str_curr_p = stored_original_str_curr_p;

          if (first_index)
          {
            if ((searching = (index <= original_len - search_len)))
            {
              lit_utf8_incr (&original_str_curr_p);
              index++;
            }
          }
          else
          {
            if ((searching = (index > 0)))
            {
              lit_utf8_decr (&original_str_curr_p);
              index--;
            }
          }
        }
      }

      ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size);
      ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size);
    }
  }

  return match_found;
} /* ecma_builtin_helper_string_find_index */
/**
 * 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 */
/**
 * 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 */
/**
 * The String.prototype object's 'substring' routine
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.15
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_string_prototype_object_substring (ecma_value_t this_arg, /**< this argument */
                                                ecma_value_t arg1, /**< routine's first argument */
                                                ecma_value_t arg2) /**< routine's second argument */
{
  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 */
  ecma_string_t *original_string_p = ecma_get_string_from_value (to_string_val);

  const ecma_length_t len = ecma_string_get_length (original_string_p);

  /* 4, 6 */
  ECMA_OP_TO_NUMBER_TRY_CATCH (start_num,
                               arg1,
                               ret_value);

  ecma_length_t start = 0, end = len;

  start = ecma_builtin_helper_string_index_normalize (start_num, len);

  /* 5, 7 */
  if (ecma_is_value_undefined (arg2))
  {
    end = len;
  }
  else
  {
    ECMA_OP_TO_NUMBER_TRY_CATCH (end_num,
                                 arg2,
                                 ret_value);

    end = ecma_builtin_helper_string_index_normalize (end_num, len);

    ECMA_OP_TO_NUMBER_FINALIZE (end_num);
  }

  if (ecma_is_completion_value_empty (ret_value))
  {
    JERRY_ASSERT (start <= len && end <= len);

    /* 8 */
    uint32_t from = start < end ? start : end;

    /* 9 */
    uint32_t to = start > end ? start : end;

    /* 10 */
    ecma_string_t *new_str_p = ecma_string_substr (original_string_p, from, to);
    ret_value = ecma_make_normal_completion_value (ecma_make_string_value (new_str_p));
  }

  ECMA_OP_TO_NUMBER_FINALIZE (start_num);

  ECMA_FINALIZE (to_string_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_string_prototype_object_substring */
/**
 * Abstract operation 'JA' defined in 15.12.3
 *
 * See also:
 *          ECMA-262 v5, 15.12.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_json_array (ecma_object_t *obj_p, /**< the array object*/
                         ecma_json_stringify_context_t *context_p) /**< context*/
{
  ecma_value_t obj_value = ecma_make_object_value (obj_p);

  /* 1. */
  if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value))
  {
    return ecma_raise_type_error ("");
  }

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 2. */
  ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true);

  /* 3. */
  ecma_string_t *stepback_p = context_p->indent_str_p;

  /* 4. */
  context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p);

  /* 5. */
  ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true);

  ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);

  /* 6. */
  ECMA_TRY_CATCH (array_length,
                  ecma_op_object_get (obj_p, length_str_p),
                  ret_value);

  ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num,
                               array_length,
                               ret_value);

  uint32_t array_length = ecma_number_to_uint32 (array_length_num);

  /* 7. - 8. */
  for (uint32_t index = 0;
       index < array_length && ecma_is_value_empty (ret_value);
       index++)
  {

    /* 8.a */
    ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);

    ECMA_TRY_CATCH (str_val,
                    ecma_builtin_json_str (index_str_p, obj_p, context_p),
                    ret_value);

    /* 8.b */
    if (ecma_is_value_undefined (str_val))
    {
      ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
      ecma_append_to_values_collection (partial_p, ecma_make_string_value (null_str_p), true);
      ecma_deref_ecma_string (null_str_p);
    }
    /* 8.c */
    else
    {
      ecma_append_to_values_collection (partial_p, str_val, true);
    }

    ECMA_FINALIZE (str_val);
    ecma_deref_ecma_string (index_str_p);
  }

  if (ecma_is_value_empty (ret_value))
  {
    /* 9. */
    if (partial_p->unit_number == 0)
    {
      ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR);
      ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR);

      ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_square_str_p, right_square_str_p);
      ret_value = ecma_make_string_value (final_str_p);

      ecma_deref_ecma_string (left_square_str_p);
      ecma_deref_ecma_string (right_square_str_p);
    }
    /* 10. */
    else
    {
      bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0);
      /* 10.a */
      if (is_gap_empty)
      {
        ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR);
        ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR);

        ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_square_str_p,
                                                                        right_square_str_p,
                                                                        partial_p);

        ecma_deref_ecma_string (left_square_str_p);
        ecma_deref_ecma_string (right_square_str_p);
      }
      /* 10.b */
      else
      {
        ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR);
        ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR);

        ret_value = ecma_builtin_helper_json_create_formatted_json (left_square_str_p,
                                                                    right_square_str_p,
                                                                    stepback_p,
                                                                    partial_p,
                                                                    context_p);

        ecma_deref_ecma_string (left_square_str_p);
        ecma_deref_ecma_string (right_square_str_p);
      }
    }
  }

  ECMA_OP_TO_NUMBER_FINALIZE (array_length_num);
  ECMA_FINALIZE (array_length);

  ecma_deref_ecma_string (length_str_p);
  ecma_free_values_collection (partial_p, true);

  /* 11. */
  ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p);

  /* 12. */
  ecma_deref_ecma_string (context_p->indent_str_p);
  context_p->indent_str_p = stepback_p;

  /* 13. */
  return ret_value;
} /* ecma_builtin_json_array */
/**
 * 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_DISABLE_STRING_BUILTIN
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE);
#else /* CONFIG_DISABLE_STRING_BUILTIN */
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
#endif /* !CONFIG_DISABLE_STRING_BUILTIN */

  ecma_object_t *obj_p = ecma_create_object (prototype_obj_p,
                                             false,
                                             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_ECMA_VALUE);
  ecma_set_internal_property_value (prim_value_prop_p, ecma_make_string_value (prim_prop_str_value_p));

  // 15.5.5.1
  ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string ();
  ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p,
                                                                    length_magic_string_p,
                                                                    ECMA_PROPERTY_FIXED);

  ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_value));
  ecma_deref_ecma_string (length_magic_string_p);

  return ecma_make_object_value (obj_p);
} /* ecma_op_create_string_object */
/**
 * [[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 = property_name_p;
    ecma_ref_ecma_string (new_prop_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_ECMA_VALUE);
  ecma_string_t *prim_value_str_p;
  prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p));

  // 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,
                                                  ECMA_PROPERTY_FLAG_ENUMERABLE);

    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 */
/**
 * Returns with the raw byte array of the string, if it is available.
 *
 * @return byte array start - if the byte array of a string is available
 *         NULL - otherwise
 */
const lit_utf8_byte_t *
ecma_string_raw_chars (const ecma_string_t *string_p, /**< ecma-string */
                       lit_utf8_size_t *size_p, /**< [out] size of the ecma string */
                       bool *is_ascii_p) /**< [out] true, if the string is an ascii
                                          *               character sequence (size == length)
                                          *         false, otherwise */
{
  ecma_length_t length;
  lit_utf8_size_t size;
  const lit_utf8_byte_t *result_p;

  switch (ECMA_STRING_GET_CONTAINER (string_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      size = string_p->u.utf8_string.size;
      length = string_p->u.utf8_string.length;
      result_p = (const lit_utf8_byte_t *) (string_p + 1);
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      size = (lit_utf8_size_t) ecma_string_get_number_in_desc_size (string_p->u.uint32_number);

      /* All numbers must be ascii strings. */
      JERRY_ASSERT (ecma_string_get_length (string_p) == size);

      length = size;
      result_p = NULL;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      size = lit_get_magic_string_size (string_p->u.magic_string_id);

      length = size;
      result_p = lit_get_magic_string_utf8 (string_p->u.magic_string_id);

      /* All magic strings must be ascii strings. */
      JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size));
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      size = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id);
      length = size;

      result_p = lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id);

      /* All extended magic strings must be ascii strings. */
      JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size));
      break;
    }
  }

  *size_p = size;
  *is_ascii_p = (length == size);
  return result_p;
} /* ecma_string_raw_chars */
/**
 * Create a substring from an ecma string
 *
 * @return a newly consturcted ecma string with its value initialized to a copy of a substring of the first argument
 */
ecma_string_t *
ecma_string_substr (const ecma_string_t *string_p, /**< pointer to an ecma string */
                    ecma_length_t start_pos, /**< start position, should be less or equal than string length */
                    ecma_length_t end_pos) /**< end position, should be less or equal than string length */
{
#ifndef JERRY_NDEBUG
  const ecma_length_t string_length = ecma_string_get_length (string_p);
  JERRY_ASSERT (start_pos <= string_length);
  JERRY_ASSERT (end_pos <= string_length);
#endif /* !JERRY_NDEBUG */

  if (start_pos < end_pos)
  {
    lit_utf8_size_t buffer_size;
    bool is_ascii;
    const lit_utf8_byte_t *start_p = ecma_string_raw_chars (string_p, &buffer_size, &is_ascii);

    end_pos -= start_pos;

    if (start_p != NULL)
    {
      if (is_ascii)
      {
        return ecma_new_ecma_string_from_utf8 (start_p + start_pos,
                                               (lit_utf8_size_t) end_pos);
      }

      while (start_pos--)
      {
        start_p += lit_get_unicode_char_size_by_utf8_first_byte (*start_p);
      }

      const lit_utf8_byte_t *end_p = start_p;
      while (end_pos--)
      {
        end_p += lit_get_unicode_char_size_by_utf8_first_byte (*end_p);
      }

      return ecma_new_ecma_string_from_utf8 (start_p, (lit_utf8_size_t) (end_p - start_p));
    }

    /**
     * I. Dump original string to plain buffer
     */
    ecma_string_t *ecma_string_p;

    JMEM_DEFINE_LOCAL_ARRAY (utf8_str_p, buffer_size, lit_utf8_byte_t);

    ecma_string_to_utf8_bytes (string_p, utf8_str_p, buffer_size);

    /**
     * II. Extract substring
     */
    start_p = utf8_str_p;

    if (is_ascii)
    {
      ecma_string_p = ecma_new_ecma_string_from_utf8 (start_p + start_pos,
                                                      (lit_utf8_size_t) end_pos);
    }
    else
    {
      while (start_pos--)
      {
        start_p += lit_get_unicode_char_size_by_utf8_first_byte (*start_p);
      }

      const lit_utf8_byte_t *end_p = start_p;
      while (end_pos--)
      {
        end_p += lit_get_unicode_char_size_by_utf8_first_byte (*end_p);
      }

      ecma_string_p = ecma_new_ecma_string_from_utf8 (start_p, (lit_utf8_size_t) (end_p - start_p));
    }

    JMEM_FINALIZE_LOCAL_ARRAY (utf8_str_p);

    return ecma_string_p;
  }
  else
  {
    return ecma_new_ecma_string_from_utf8 (NULL, 0);
  }

  JERRY_UNREACHABLE ();
} /* ecma_string_substr */
/**
 * The String.prototype object's 'indexOf' routine
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.7
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */
                                               ecma_value_t arg1, /**< routine's first argument */
                                               ecma_value_t arg2) /**< routine's second argument */
{
  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_str_val,
                  ecma_op_to_string (this_arg),
                  ret_value);

  /* 3 */
  ECMA_TRY_CATCH (search_str_val,
                  ecma_op_to_string (arg1),
                  ret_value);

  /* 4 */
  ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num,
                               arg2,
                               ret_value);

  /* 5 */
  ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val);
  const ecma_length_t original_len = ecma_string_get_length (original_str_p);
  const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p);

  /* 4b, 6 */
  ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len);

  /* 7 */
  ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val);
  const ecma_length_t search_len = ecma_string_get_length (search_str_p);
  const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p);

  ecma_number_t *ret_num_p = ecma_alloc_number ();
  *ret_num_p = ecma_int32_to_number (-1);

  /* 8 */
  if (search_len <= original_len)
  {
    if (!search_len)
    {
      *ret_num_p = ecma_uint32_to_number (0);
    }
    else
    {
      /* create utf8 string from original string and advance to start position */
      MEM_DEFINE_LOCAL_ARRAY (original_str_utf8_p,
                              original_size,
                              lit_utf8_byte_t);

      ecma_string_to_utf8_string (original_str_p,
                                  original_str_utf8_p,
                                  (ssize_t) (original_size));

      lit_utf8_iterator_t original_it = lit_utf8_iterator_create (original_str_utf8_p, original_size);

      ecma_length_t index = start;
      lit_utf8_iterator_advance (&original_it, index);

      /* create utf8 string from search string */
      MEM_DEFINE_LOCAL_ARRAY (search_str_utf8_p,
                              search_size,
                              lit_utf8_byte_t);

      ecma_string_to_utf8_string (search_str_p,
                                  search_str_utf8_p,
                                  (ssize_t) (search_size));

      lit_utf8_iterator_t search_it = lit_utf8_iterator_create (search_str_utf8_p, search_size);

      /* iterate original string and try to match at each position */
      bool found = false;

      while (!found && index <= original_len - search_len)
      {
        ecma_length_t match_len = 0;
        lit_utf8_iterator_pos_t stored_original_pos = lit_utf8_iterator_get_pos (&original_it);

        while (match_len < search_len &&
               lit_utf8_iterator_read_next (&original_it) == lit_utf8_iterator_read_next (&search_it))
        {
          match_len++;
        }

        /* Check for match */
        if (match_len == search_len)
        {
          *ret_num_p = ecma_uint32_to_number (index);
          found = true;
        }
        else
        {
          /* reset iterators */
          lit_utf8_iterator_seek_bos (&search_it);
          lit_utf8_iterator_seek (&original_it, stored_original_pos);
          lit_utf8_iterator_incr (&original_it);
        }
        index++;
      }

      MEM_FINALIZE_LOCAL_ARRAY (search_str_utf8_p);
      MEM_FINALIZE_LOCAL_ARRAY (original_str_utf8_p);
    }
  }

  ecma_value_t new_value = ecma_make_number_value (ret_num_p);
  ret_value = ecma_make_normal_completion_value (new_value);

  ECMA_OP_TO_NUMBER_FINALIZE (pos_num);
  ECMA_FINALIZE (search_str_val);
  ECMA_FINALIZE (to_str_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_string_prototype_object_index_of */
/**
 * The String.prototype object's 'slice' routine
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.13
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_string_prototype_object_slice (ecma_value_t this_arg, /**< this argument */
                                            ecma_value_t arg1, /**< routine's first argument */
                                            ecma_value_t arg2) /**< routine's second argument */
{
  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. */
  ecma_string_t *get_string_val = ecma_get_string_from_value (to_string_val);

  const ecma_length_t len = ecma_string_get_length (get_string_val);

  /* 4. */
  ecma_length_t start = 0, end = len;

  ECMA_OP_TO_NUMBER_TRY_CATCH (start_num,
                               arg1,
                               ret_value);

  start = ecma_builtin_helper_array_index_normalize (start_num, len);

  /* 5. 7. */
  if (ecma_is_value_undefined (arg2))
  {
    end = len;
  }
  else
  {
    ECMA_OP_TO_NUMBER_TRY_CATCH (end_num,
                                 arg2,
                                 ret_value);

    end = ecma_builtin_helper_array_index_normalize (end_num, len);

    ECMA_OP_TO_NUMBER_FINALIZE (end_num);
  }

  ECMA_OP_TO_NUMBER_FINALIZE (start_num);

  JERRY_ASSERT (start <= len && end <= len);

  if (ecma_is_completion_value_empty (ret_value))
  {
    /* 8-9. */
    ecma_string_t *new_str_p = ecma_string_substr (get_string_val, start, end);
    ret_value = ecma_make_normal_completion_value (ecma_make_string_value (new_str_p));
  }

  ECMA_FINALIZE (to_string_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_string_prototype_object_slice */
/*
 * Helper function for string indexOf and lastIndexOf functions
 *
 * This function implements string indexOf and lastIndexOf with required checks and conversions.
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.7
 *          ECMA-262 v5, 15.5.4.8
 *
 * Used by:
 *         - The String.prototype.indexOf routine.
 *         - The String.prototype.lastIndexOf routine.
 *
 * @return uint32_t - (last)index of search string
 */
ecma_completion_value_t
ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */
                                                      ecma_value_t arg1, /**< routine's first argument */
                                                      ecma_value_t arg2, /**< routine's second argument */
                                                      bool firstIndex) /**< routine's third argument */
{
  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_str_val,
                  ecma_op_to_string (this_arg),
                  ret_value);

  /* 3 */
  ECMA_TRY_CATCH (search_str_val,
                  ecma_op_to_string (arg1),
                  ret_value);

  /* 4 */
  ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num,
                               arg2,
                               ret_value);

  /* 6 */
  ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val);
  const ecma_length_t original_len = ecma_string_get_length (original_str_p);
  const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p);

  /* 4b, 5, 7 */
  ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, firstIndex);

  /* 8 */
  ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val);
  const ecma_length_t search_len = ecma_string_get_length (search_str_p);
  const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p);

  ecma_number_t *ret_num_p = ecma_alloc_number ();
  *ret_num_p = ecma_int32_to_number (-1);

  /* 9 */
  if (search_len <= original_len)
  {
    if (!search_len)
    {
      *ret_num_p = ecma_uint32_to_number (firstIndex ? 0 : original_len);
    }
    else
    {
      /* create utf8 string from original string and advance to position */
      MEM_DEFINE_LOCAL_ARRAY (original_str_utf8_p,
                              original_size,
                              lit_utf8_byte_t);

      ecma_string_to_utf8_string (original_str_p,
                                  original_str_utf8_p,
                                  (ssize_t) (original_size));

      lit_utf8_iterator_t original_it = lit_utf8_iterator_create (original_str_utf8_p, original_size);

      ecma_length_t index = start;
      lit_utf8_iterator_advance (&original_it, index);

      /* create utf8 string from search string */
      MEM_DEFINE_LOCAL_ARRAY (search_str_utf8_p,
                              search_size,
                              lit_utf8_byte_t);

      ecma_string_to_utf8_string (search_str_p,
                                  search_str_utf8_p,
                                  (ssize_t) (search_size));

      lit_utf8_iterator_t search_it = lit_utf8_iterator_create (search_str_utf8_p, search_size);

      /* iterate original string and try to match at each position */
      bool searching = true;

      while (searching)
      {
        /* match as long as possible */
        ecma_length_t match_len = 0;
        lit_utf8_iterator_t stored_original_it = original_it;

        while (match_len < search_len &&
               index + match_len < original_len &&
               lit_utf8_iterator_read_next (&original_it) == lit_utf8_iterator_read_next (&search_it))
        {
          match_len++;
        }

        /* check for match */
        if (match_len == search_len)
        {
          *ret_num_p = ecma_uint32_to_number (index);
          break;
        }
        else
        {
          /* inc/dec index and update iterators and search condition */
          lit_utf8_iterator_seek_bos (&search_it);
          original_it = stored_original_it;

          if (firstIndex)
          {
            if ((searching = (index <= original_len - search_len)))
            {
              lit_utf8_iterator_incr (&original_it);
              index++;
            }
          }
          else
          {
            if ((searching = (index > 0)))
            {
              lit_utf8_iterator_decr (&original_it);
              index--;
            }
          }
        }
      }

      MEM_FINALIZE_LOCAL_ARRAY (search_str_utf8_p);
      MEM_FINALIZE_LOCAL_ARRAY (original_str_utf8_p);
    }
  }

  ecma_value_t new_value = ecma_make_number_value (ret_num_p);
  ret_value = ecma_make_normal_completion_value (new_value);

  ECMA_OP_TO_NUMBER_FINALIZE (pos_num);
  ECMA_FINALIZE (search_str_val);
  ECMA_FINALIZE (to_str_val);
  ECMA_FINALIZE (check_coercible_val);

  return ret_value;
} /* ecma_builtin_helper_string_index_normalize */
/**
 * 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 */