Example #1
0
/**
 * GetBindingValue operation.
 *
 * See also: ECMA-262 v5, 10.2.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */
                           ecma_string_t *name_p, /**< argument N */
                           bool is_strict) /**< argument S */
{
  JERRY_ASSERT (lex_env_p != NULL
                && ecma_is_lexical_environment (lex_env_p));
  JERRY_ASSERT (name_p != NULL);

  if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
  {
    ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p);

    ecma_value_t prop_value = ecma_get_named_data_property_value (property_p);

    /* is the binding mutable? */
    if (!ecma_is_property_writable (property_p)
        && ecma_is_value_empty (prop_value))
    {
      /* unitialized immutable binding */
      if (is_strict)
      {
        return ecma_raise_reference_error ("");
      }
      else
      {
        return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
      }
    }

    return ecma_copy_value (prop_value, true);
  }
  else
  {
    JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND);

    ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);

    if (ecma_op_object_get_property (binding_obj_p, name_p) == NULL)
    {
      if (is_strict)
      {
        return ecma_raise_reference_error ("");
      }
      else
      {
        return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
      }
    }

    return ecma_op_object_get (binding_obj_p, name_p);
  }
} /* ecma_op_get_binding_value */
Example #2
0
/**
 * Process the PromiseResolveThenableJob.
 *
 * See also: ES2015 25.4.2.2
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
static ecma_value_t
ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be operated */
{
  ecma_job_promise_resolve_thenable_t *job_p = (ecma_job_promise_resolve_thenable_t *) obj_p;
  ecma_object_t *promise_p = ecma_get_object_from_value (job_p->promise);
  ecma_string_t str_resolve, str_reject;
  ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION);
  ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION);

  ecma_value_t resolve = ecma_op_object_get (promise_p, &str_resolve);
  ecma_value_t reject = ecma_op_object_get (promise_p, &str_reject);

  ecma_value_t argv[] = { resolve, reject };
  ecma_value_t ret;
  ecma_value_t then_call_result = ecma_op_function_call (ecma_get_object_from_value (job_p->then),
                                                         job_p->thenable,
                                                         argv,
                                                         2);

  ret = then_call_result;

  if (ECMA_IS_VALUE_ERROR (then_call_result))
  {
    ret = ecma_op_function_call (ecma_get_object_from_value (reject),
                                 ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
                                 &then_call_result,
                                 1);

    ecma_free_value (then_call_result);
  }

  ecma_free_value (resolve);
  ecma_free_value (reject);
  ecma_free_promise_resolve_thenable_job (job_p);

  return ret;
} /* ecma_process_promise_resolve_thenable_job */
/**
 * The Object.prototype object's 'toLocaleString' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.4.3
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */
{
  ecma_completion_value_t return_value = ecma_make_empty_completion_value ();
  /* 1. */
  ECMA_TRY_CATCH (obj_val,
                  ecma_op_to_object (this_arg),
                  return_value);

  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
  ecma_string_t *to_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_STRING_UL);

  /* 2. */
  ECMA_TRY_CATCH (to_string_val,
                  ecma_op_object_get (obj_p, to_string_magic_string_p),
                  return_value);

  /* 3. */
  if (!ecma_op_is_callable (to_string_val))
  {
    return_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    /* 4. */
    ecma_object_t *to_string_func_obj_p = ecma_get_object_from_value (to_string_val);
    return_value = ecma_op_function_call (to_string_func_obj_p, this_arg, NULL);
  }
  ECMA_FINALIZE (to_string_val);

  ecma_deref_ecma_string (to_string_magic_string_p);

  ECMA_FINALIZE (obj_val);

  return return_value;
} /* ecma_builtin_object_prototype_object_to_locale_string */
/**
 * The Object.prototype object's 'toLocaleString' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.4.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */
{
  ecma_value_t return_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
  /* 1. */
  ECMA_TRY_CATCH (obj_val,
                  ecma_op_to_object (this_arg),
                  return_value);

  ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
  ecma_string_t *to_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_STRING_UL);

  /* 2. */
  ECMA_TRY_CATCH (to_string_val,
                  ecma_op_object_get (obj_p, to_string_magic_string_p),
                  return_value);

  /* 3. */
  if (!ecma_op_is_callable (to_string_val))
  {
    return_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
  }
  else
  {
    /* 4. */
    ecma_object_t *to_string_func_obj_p = ecma_get_object_from_value (to_string_val);
    return_value = ecma_op_function_call (to_string_func_obj_p, this_arg, NULL, 0);
  }
  ECMA_FINALIZE (to_string_val);

  ecma_deref_ecma_string (to_string_magic_string_p);

  ECMA_FINALIZE (obj_val);

  return return_value;
} /* ecma_builtin_object_prototype_object_to_locale_string */
/**
 * The Function.prototype object's 'apply' routine
 *
 * See also:
 *          ECMA-262 v5, 15.3.4.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */
                                              ecma_value_t arg1, /**< first argument */
                                              ecma_value_t arg2) /**< second argument */
{
  ecma_value_t ret_value = ECMA_VALUE_EMPTY;

  /* 1. */
  if (!ecma_op_is_callable (this_arg))
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function."));
  }
  else
  {
    ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg);

    /* 2. */
    if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2))
    {
      ret_value = ecma_op_function_call (func_obj_p, arg1, NULL, 0);
    }
    else
    {
      /* 3. */
      if (!ecma_is_value_object (arg2))
      {
        ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object."));
      }
      else
      {
        ecma_object_t *obj_p = ecma_get_object_from_value (arg2);

        /* 4. */
        ecma_value_t length_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH);
        if (ECMA_IS_VALUE_ERROR (length_value))
        {
          return length_value;
        }

        ecma_number_t length_number;
        ecma_value_t get_result = ecma_get_number (length_value, &length_number);

        ecma_free_value (length_value);

        if (ECMA_IS_VALUE_ERROR (get_result))
        {
          return get_result;
        }
        JERRY_ASSERT (ecma_is_value_empty (get_result));

        /* 5. */
        const uint32_t length = ecma_number_to_uint32 (length_number);

        if (length >= ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT)
        {
          ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Too many arguments declared for Function.apply()."));
        }
        else
        {
          /* 6. */
          JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t);
          uint32_t index = 0;

          /* 7. */
          for (index = 0; index < length; index++)
          {
            ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index);
            ecma_value_t get_value = ecma_op_object_get (obj_p, curr_idx_str_p);
            ecma_deref_ecma_string (curr_idx_str_p);

            if (ECMA_IS_VALUE_ERROR (get_value))
            {
              ret_value = get_value;
              break;
            }

            arguments_list_p[index] = get_value;
          }

          if (ecma_is_value_empty (ret_value))
          {
            JERRY_ASSERT (index == length);
            ret_value = ecma_op_function_call (func_obj_p,
                                               arg1,
                                               arguments_list_p,
                                               length);
          }

          for (uint32_t remove_index = 0; remove_index < index; remove_index++)
          {
            ecma_free_value (arguments_list_p[remove_index]);
          }

          JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p);
        }
      }
    }
  }

  return ret_value;
} /* ecma_builtin_function_prototype_object_apply */
/**
 * The Function.prototype object's 'apply' routine
 *
 * See also:
 *          ECMA-262 v5, 15.3.4.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */
                                              ecma_value_t arg1, /**< first argument */
                                              ecma_value_t arg2) /**< second argument */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 1. */
  if (!ecma_op_is_callable (this_arg))
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
  }
  else
  {
    ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg);

    /* 2. */
    if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2))
    {
      ret_value = ecma_op_function_call (func_obj_p, arg1, NULL, 0);
    }
    else
    {
      /* 3. */
      if (!ecma_is_value_object (arg2))
      {
        ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
      }
      else
      {
        ecma_object_t *obj_p = ecma_get_object_from_value (arg2);
        ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string ();

        /* 4. */
        ECMA_TRY_CATCH (length_value,
                        ecma_op_object_get (obj_p, length_magic_string_p),
                        ret_value);

        ECMA_OP_TO_NUMBER_TRY_CATCH (length_number,
                                     length_value,
                                     ret_value);

        /* 5. */
        const uint32_t length = ecma_number_to_uint32 (length_number);

        /* 6. */
        JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t);
        uint32_t last_index = 0;

        /* 7. */
        for (uint32_t index = 0;
             index < length && ecma_is_value_empty (ret_value);
             index++)
        {
          ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index);

          ECMA_TRY_CATCH (get_value,
                          ecma_op_object_get (obj_p, curr_idx_str_p),
                          ret_value);

          arguments_list_p[index] = ecma_copy_value (get_value);
          last_index = index + 1;

          ECMA_FINALIZE (get_value);
          ecma_deref_ecma_string (curr_idx_str_p);
        }

        if (ecma_is_value_empty (ret_value))
        {
          JERRY_ASSERT (last_index == length);
          ret_value = ecma_op_function_call (func_obj_p,
                                             arg1,
                                             arguments_list_p,
                                             length);
        }

        for (uint32_t index = 0; index < last_index; index++)
        {
          ecma_free_value (arguments_list_p[index]);
        }

        JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p);

        ECMA_OP_TO_NUMBER_FINALIZE (length_number);
        ECMA_FINALIZE (length_value);
        ecma_deref_ecma_string (length_magic_string_p);
      }
    }
  }

  return ret_value;
} /* ecma_builtin_function_prototype_object_apply */
Example #7
0
/**
 * GetBindingValue operation.
 *
 * See also: ECMA-262 v5, 10.2.1
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
ecma_completion_value_t
ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */
                           ecma_string_t *name_p, /**< argument N */
                           bool is_strict) /**< argument S */
{
  JERRY_ASSERT (lex_env_p != NULL
                && ecma_is_lexical_environment (lex_env_p));
  JERRY_ASSERT (name_p != NULL);

  if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
  {
#ifndef JERRY_NDEBUG
# ifdef CONFIG_ECMA_COMPACT_PROFILE
    bool is_equal = false;

    ecma_string_t *arguments_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS);
    if (ecma_compare_ecma_strings (name_p, arguments_magic_string_p))
    {
      is_equal = true;
    }
    ecma_deref_ecma_string (arguments_magic_string_p);

    JERRY_ASSERT (!is_equal);

    if (is_equal)
    {
      return ecma_make_throw_obj_completion_value (ecma_builtin_get (ECMA_BUILTIN_ID_COMPACT_PROFILE_ERROR));
    }
# endif /* CONFIG_ECMA_COMPACT_PROFILE */
#endif /* !JERRY_NDEBUG */

    ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p);

    ecma_value_t prop_value = ecma_get_named_data_property_value (property_p);

    /* is the binding mutable? */
    if (!ecma_is_property_writable (property_p)
        && ecma_is_value_empty (prop_value))
    {
      /* unitialized immutable binding */
      if (is_strict)
      {
        return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_REFERENCE));
      }
      else
      {
        return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED);
      }
    }

    return ecma_make_normal_completion_value (ecma_copy_value (prop_value, true));
  }
  else
  {
    JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND);

    ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);

    if (ecma_op_object_get_property (binding_obj_p, name_p) == NULL)
    {
      if (is_strict)
      {
        return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_REFERENCE));
      }
      else
      {
        return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED);
      }
    }

    return ecma_op_object_get (binding_obj_p, name_p);
  }
} /* ecma_op_get_binding_value */
/**
 * [[DefaultValue]] ecma general object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 8.12.8
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */
                                      ecma_preferred_type_hint_t hint) /**< hint on preferred result type */
{
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));

  if (hint == ECMA_PREFERRED_TYPE_NO)
  {
    if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL)
    {
      hint = ECMA_PREFERRED_TYPE_STRING;
    }
    else
    {
      hint = ECMA_PREFERRED_TYPE_NUMBER;
    }
  }

  for (uint32_t i = 1; i <= 2; i++)
  {
    lit_magic_string_id_t function_name_magic_string_id;

    if ((i == 1 && hint == ECMA_PREFERRED_TYPE_STRING)
        || (i == 2 && hint == ECMA_PREFERRED_TYPE_NUMBER))
    {
      function_name_magic_string_id = LIT_MAGIC_STRING_TO_STRING_UL;
    }
    else
    {
      function_name_magic_string_id = LIT_MAGIC_STRING_VALUE_OF_UL;
    }

    ecma_string_t *function_name_p = ecma_get_magic_string (function_name_magic_string_id);

    ecma_completion_value_t function_value_get_completion = ecma_op_object_get (obj_p, function_name_p);

    ecma_deref_ecma_string (function_name_p);

    if (!ecma_is_completion_value_normal (function_value_get_completion))
    {
      return function_value_get_completion;
    }

    ecma_completion_value_t call_completion = ecma_make_empty_completion_value ();

    if (ecma_op_is_callable (ecma_get_completion_value_value (function_value_get_completion)))
    {
      ecma_object_t *func_obj_p = ecma_get_object_from_completion_value (function_value_get_completion);

      call_completion = ecma_op_function_call (func_obj_p,
                                               ecma_make_object_value (obj_p),
                                               NULL);
    }

    ecma_free_completion_value (function_value_get_completion);

    if (!ecma_is_completion_value_normal (call_completion))
    {
      return call_completion;
    }

    if (!ecma_is_completion_value_empty (call_completion)
        && !ecma_is_value_object (ecma_get_completion_value_value (call_completion)))
    {
      return call_completion;
    }

    ecma_free_completion_value (call_completion);
  }

  return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
} /* ecma_op_general_object_default_value */
/**
 * Abstract operation Walk defined in 15.12.2
 *
 * See also:
 *          ECMA-262 v5, 15.12.2
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */
                        ecma_object_t *holder_p, /**< holder object */
                        ecma_string_t *name_p) /**< property name */
{
  JERRY_ASSERT (reviver_p);
  JERRY_ASSERT (holder_p);
  JERRY_ASSERT (name_p);

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  ECMA_TRY_CATCH (value_get,
                  ecma_op_object_get (holder_p, name_p),
                  ret_value);

  if (ecma_is_value_object (value_get))
  {
    ecma_object_t *object_p = ecma_get_object_from_value (value_get);

    ecma_collection_header_t *props_p = ecma_op_object_get_property_names (object_p, false, true, false);

    ecma_collection_iterator_t iter;
    ecma_collection_iterator_init (&iter, props_p);

    while (ecma_collection_iterator_next (&iter)
           && ecma_is_value_empty (ret_value))
    {
      ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);

      ECMA_TRY_CATCH (value_walk,
                      ecma_builtin_json_walk (reviver_p,
                                              object_p,
                                              property_name_p),
                      ret_value);

      /*
       * We cannot optimize this function since any members
       * can be changed (deleted) by the reviver function.
       */
      if (ecma_is_value_undefined (value_walk))
      {
        ecma_value_t delete_val = ecma_op_general_object_delete (object_p,
                                                                 property_name_p,
                                                                 false);
        JERRY_ASSERT (ecma_is_value_boolean (delete_val));
      }
      else
      {
        ecma_builtin_json_define_value_property (object_p,
                                                 property_name_p,
                                                 value_walk);
      }

      ECMA_FINALIZE (value_walk);
    }

    ecma_free_values_collection (props_p, true);
  }

  if (ecma_is_value_empty (ret_value))
  {
    ecma_value_t arguments_list[2];

    arguments_list[0] = ecma_make_string_value (name_p);
    arguments_list[1] = value_get;

   /*
    * The completion value can be anything including exceptions.
    */
    ret_value = ecma_op_function_call (reviver_p,
                                       ecma_make_object_value (holder_p),
                                       arguments_list,
                                       2);
  }
  else
  {
    JERRY_ASSERT (ecma_is_value_error (ret_value));
  }

  ECMA_FINALIZE (value_get);

  return ret_value;
} /* ecma_builtin_json_walk */
Example #10
0
/**
 * 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 */
Example #11
0
/**
 * Abstract operation 'Str' defined in 15.12.3
 *
 * See also:
 *          ECMA-262 v5, 15.12.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_json_str (ecma_string_t *key_p, /**< property key*/
                       ecma_object_t *holder_p, /**< the object*/
                       ecma_json_stringify_context_t *context_p) /**< context*/
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 1. */
  ECMA_TRY_CATCH (value,
                  ecma_op_object_get (holder_p, key_p),
                  ret_value);

  ecma_value_t my_val = ecma_copy_value (value, true);

  /* 2. */
  if (ecma_is_value_object (my_val))
  {
    ecma_object_t *value_obj_p = ecma_get_object_from_value (my_val);
    ecma_string_t *to_json_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_JSON_UL);

    /* 2.a */
    ECMA_TRY_CATCH (toJSON,
                    ecma_op_object_get (value_obj_p, to_json_str_p),
                    ret_value);

    /* 2.b */
    if (ecma_op_is_callable (toJSON))
    {
      ecma_value_t key_value = ecma_make_string_value (key_p);
      ecma_value_t call_args[] = { key_value };
      ecma_object_t *toJSON_obj_p = ecma_get_object_from_value (toJSON);

      ECMA_TRY_CATCH (func_ret_val,
                      ecma_op_function_call (toJSON_obj_p, my_val, call_args, 1),
                      ret_value);

      ecma_free_value (my_val);
      my_val = ecma_copy_value (func_ret_val, true);

      ECMA_FINALIZE (func_ret_val);
    }

    ECMA_FINALIZE (toJSON);

    ecma_deref_ecma_string (to_json_str_p);
  }

  /* 3. */
  if (context_p->replacer_function_p && ecma_is_value_empty (ret_value))
  {
    ecma_value_t holder_value = ecma_make_object_value (holder_p);
    ecma_value_t key_value = ecma_make_string_value (key_p);
    ecma_value_t call_args[] = { key_value, my_val };

    ECMA_TRY_CATCH (func_ret_val,
                    ecma_op_function_call (context_p->replacer_function_p, holder_value, call_args, 2),
                    ret_value);

    ecma_free_value (my_val);
    my_val = ecma_copy_value (func_ret_val, true);

    ECMA_FINALIZE (func_ret_val);
  }

  /* 4. */
  if (ecma_is_value_object (my_val) && ecma_is_value_empty (ret_value))
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (my_val);
    lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p);

    /* 4.a */
    if (class_name == LIT_MAGIC_STRING_NUMBER_UL)
    {
      ECMA_TRY_CATCH (val,
                      ecma_op_to_number (my_val),
                      ret_value);

      ecma_free_value (my_val);
      my_val = ecma_copy_value (val, true);

      ECMA_FINALIZE (val);
    }
    /* 4.b */
    else if (class_name == LIT_MAGIC_STRING_STRING_UL)
    {
      ECMA_TRY_CATCH (val,
                      ecma_op_to_string (my_val),
                      ret_value);

      ecma_free_value (my_val);
      my_val = ecma_copy_value (val, true);

      ECMA_FINALIZE (val);
    }
    /* 4.c */
    else if (class_name == LIT_MAGIC_STRING_BOOLEAN_UL)
    {
      ECMA_TRY_CATCH (val,
                      ecma_op_to_primitive (my_val, ECMA_PREFERRED_TYPE_NO),
                      ret_value);

      ecma_free_value (my_val);
      my_val = ecma_copy_value (val, true);

      ECMA_FINALIZE (val);
    }
  }

  if (ecma_is_value_empty (ret_value))
  {
    /* 5. - 7. */
    if (ecma_is_value_null (my_val) || ecma_is_value_boolean (my_val))
    {
      ret_value = ecma_op_to_string (my_val);
      JERRY_ASSERT (!ecma_is_value_error (ret_value));
    }
    /* 8. */
    else if (ecma_is_value_string (my_val))
    {
      ecma_string_t *value_str_p = ecma_get_string_from_value (my_val);
      ret_value = ecma_builtin_json_quote (value_str_p);
    }
    /* 9. */
    else if (ecma_is_value_number (my_val))
    {
      ecma_number_t num_value_p = *ecma_get_number_from_value (my_val);

      /* 9.a */
      if (!ecma_number_is_nan (num_value_p) && !ecma_number_is_infinity (num_value_p))
      {
        ret_value = ecma_op_to_string (my_val);
        JERRY_ASSERT (!ecma_is_value_error (ret_value));
      }
      else
      {
        /* 9.b */
        ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
        ret_value = ecma_make_string_value (null_str_p);
      }
    }
    /* 10. */
    else if (ecma_is_value_object (my_val) && !ecma_op_is_callable (my_val))
    {
      ecma_object_t *obj_p = ecma_get_object_from_value (my_val);
      lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p);

      /* 10.a */
      if (class_name == LIT_MAGIC_STRING_ARRAY_UL)
      {
        ECMA_TRY_CATCH (val,
                        ecma_builtin_json_array (obj_p, context_p),
                        ret_value);

        ret_value = ecma_copy_value (val, true);

        ECMA_FINALIZE (val);
      }
      /* 10.b */
      else
      {
        ECMA_TRY_CATCH (val,
                        ecma_builtin_json_object (obj_p, context_p),
                        ret_value);

        ret_value = ecma_copy_value (val, true);

        ECMA_FINALIZE (val);
      }
    }
    else
    {
      /* 11. */
      ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
    }
  }

  ecma_free_value (my_val);
  ECMA_FINALIZE (value);

  return ret_value;
} /* ecma_builtin_json_str */
/**
 * The common function for 'reject' and 'resolve'.
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */
                                        ecma_value_t argument, /**< argument for reject or resolve */
                                        bool is_resolve) /**< whether it is for resolve routine */
{
  if (!ecma_is_value_object (this_arg))
  {
    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
  }

  uint8_t builtin_id = ecma_get_object_builtin_id (ecma_get_object_from_value (this_arg));

  if (builtin_id != ECMA_BUILTIN_ID_PROMISE)
  {
    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not the Promise constructor."));
  }

  if (is_resolve
      && ecma_is_value_object (argument)
      && ecma_is_promise (ecma_get_object_from_value (argument)))
  {
    return ecma_copy_value (argument);
  }


  ecma_value_t capability = ecma_promise_new_capability ();

  if (ECMA_IS_VALUE_ERROR (capability))
  {
    return capability;
  }

  ecma_string_t *str;

  if (is_resolve)
  {
    str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
  }
  else
  {
    str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);
  }

  ecma_value_t func = ecma_op_object_get (ecma_get_object_from_value (capability), str);
  ecma_deref_ecma_string (str);

  ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func),
                                                 ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
                                                 &argument,
                                                 1);

  ecma_free_value (func);

  if (ECMA_IS_VALUE_ERROR (call_ret))
  {
    return call_ret;
  }

  ecma_free_value (call_ret);

  ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
  ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise);
  ecma_deref_ecma_string (str_promise);
  ecma_free_value (capability);

  return promise_new;
} /* ecma_builtin_promise_reject_or_resolve */
/**
 * Runtime Semantics: PerformPromiseRace.
 *
 * See also:
 *         ES2015 25.4.4.3.1
 *
 * @return ecma value of the new promise.
 *         Returned value must be freed with ecma_free_value.
 */
inline static ecma_value_t
ecma_builtin_promise_do_race (ecma_value_t array, /**< the array for race */
                              ecma_value_t capability, /**< PromiseCapability record */
                              ecma_value_t ctor) /**< the caller of Promise.race */
{
  JERRY_ASSERT (ecma_is_value_object (capability)
                && ecma_is_value_object (array)
                && ecma_is_value_object (ctor));
  JERRY_ASSERT (ecma_get_object_builtin_id (ecma_get_object_from_value (ctor)) == ECMA_BUILTIN_ID_PROMISE);
  JERRY_ASSERT (ecma_get_object_type (ecma_get_object_from_value (array)) == ECMA_OBJECT_TYPE_ARRAY);

  ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
  ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();
  ecma_object_t *array_p = ecma_get_object_from_value (array);
  ecma_value_t len_value = ecma_op_object_get (array_p, magic_string_length_p);
  ecma_deref_ecma_string (magic_string_length_p);
  ecma_length_t len = (ecma_length_t) ecma_get_integer_from_value (len_value);
  ecma_fast_free_value (len_value);

  ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE);
  ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
  ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);

  ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability),
                                             str_resolve);
  ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability),
                                            str_reject);

  for (ecma_length_t index = 0; index <= len; index++)
  {
    /* b-d. */
    if (index == len)
    {
      ret = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise);
      break;
    }

    /* e. */
    ecma_string_t *str_index = ecma_new_ecma_string_from_uint32 (index);
    ecma_value_t array_item = ecma_op_object_get (array_p, str_index);
    ecma_deref_ecma_string (str_index);

    /* h. */
    ecma_value_t next_promise = ecma_builtin_promise_resolve (ctor, array_item);
    ecma_free_value (array_item);

    /* i. */
    if (ECMA_IS_VALUE_ERROR (next_promise))
    {
      ret = next_promise;
      break;
    }

    /* j. */
    ecma_value_t then_result = ecma_promise_then (next_promise, resolve, reject);
    ecma_free_value (next_promise);

    /* k. */
    if (ECMA_IS_VALUE_ERROR (then_result))
    {
      ret = then_result;
      break;
    }

    ecma_free_value (then_result);
  }

  ecma_free_value (reject);
  ecma_free_value (resolve);
  ecma_deref_ecma_string (str_promise);
  ecma_deref_ecma_string (str_resolve);
  ecma_deref_ecma_string (str_reject);

  JERRY_ASSERT (!ecma_is_value_empty (ret));

  return ret;
} /* ecma_builtin_promise_do_race */
 * @return ecma value of undefined.
 */
static ecma_value_t
ecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function itself */
                                  const ecma_value_t this, /**< this_arg of the function */
                                  const ecma_value_t argv[], /**< argument list */
                                  const ecma_length_t argc) /**< argument number */
{
  JERRY_UNUSED (this);
  JERRY_UNUSED (argc);

  ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
  /* 1. */
  ecma_object_t *function_p = ecma_get_object_from_value (function);
  ecma_string_t *str_already_called = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_ALREADY_CALLED);
  ecma_value_t already_called =  ecma_op_object_get (function_p, str_already_called);

  JERRY_ASSERT (ecma_is_value_boolean (already_called));

  /* 2. */
  if (ecma_is_value_true (already_called))
  {
    ecma_fast_free_value (already_called);
    ecma_deref_ecma_string (str_already_called);

    return ret;
  }

  /* 3. */
  ecma_op_object_put (function_p,
                      str_already_called,
Example #15
0
/**
 * ToPropertyDescriptor operation.
 *
 * See also:
 *          ECMA-262 v5, 8.10.5
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */
                                ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor
                                                                                  if return value is normal
                                                                                  empty completion value */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  // 1.
  if (!ecma_is_value_object (obj_value))
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
  }
  else
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);

    // 2.
    ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();

    // 3.
    ecma_string_t *enumerable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE);

    if (ecma_op_object_get_property (obj_p, enumerable_magic_string_p) != NULL)
    {
      ECMA_TRY_CATCH (enumerable_prop_value,
                      ecma_op_object_get (obj_p, enumerable_magic_string_p),
                      ret_value);

      prop_desc.is_enumerable_defined = true;
      prop_desc.is_enumerable = ecma_op_to_boolean (enumerable_prop_value);

      ECMA_FINALIZE (enumerable_prop_value);
    }

    ecma_deref_ecma_string (enumerable_magic_string_p);

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 4.
      ecma_string_t *configurable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE);

      if (ecma_op_object_get_property (obj_p, configurable_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (configurable_prop_value,
                        ecma_op_object_get (obj_p, configurable_magic_string_p),
                        ret_value);

        prop_desc.is_configurable_defined = true;
        prop_desc.is_configurable = ecma_op_to_boolean (configurable_prop_value);

        ECMA_FINALIZE (configurable_prop_value);
      }

      ecma_deref_ecma_string (configurable_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 5.
      ecma_string_t *value_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUE);

      if (ecma_op_object_get_property (obj_p, value_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (value_prop_value,
                        ecma_op_object_get (obj_p, value_magic_string_p),
                        ret_value);

        prop_desc.is_value_defined = true;
        prop_desc.value = ecma_copy_value (value_prop_value);

        ECMA_FINALIZE (value_prop_value);
      }

      ecma_deref_ecma_string (value_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 6.
      ecma_string_t *writable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE);

      if (ecma_op_object_get_property (obj_p, writable_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (writable_prop_value,
                        ecma_op_object_get (obj_p, writable_magic_string_p),
                        ret_value);

        prop_desc.is_writable_defined = true;
        prop_desc.is_writable = ecma_op_to_boolean (writable_prop_value);

        ECMA_FINALIZE (writable_prop_value);
      }

      ecma_deref_ecma_string (writable_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 7.
      ecma_string_t *get_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GET);

      if (ecma_op_object_get_property (obj_p, get_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (get_prop_value,
                        ecma_op_object_get (obj_p, get_magic_string_p),
                        ret_value);

        if (!ecma_op_is_callable (get_prop_value)
            && !ecma_is_value_undefined (get_prop_value))
        {
          ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
        }
        else
        {
          prop_desc.is_get_defined = true;

          if (ecma_is_value_undefined (get_prop_value))
          {
            prop_desc.get_p = NULL;
          }
          else
          {
            JERRY_ASSERT (ecma_is_value_object (get_prop_value));

            ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value);
            ecma_ref_object (get_p);

            prop_desc.get_p = get_p;
          }
        }

        ECMA_FINALIZE (get_prop_value);
      }

      ecma_deref_ecma_string (get_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 8.

      ecma_string_t *set_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SET);

      if (ecma_op_object_get_property (obj_p, set_magic_string_p) != NULL)
      {
        ECMA_TRY_CATCH (set_prop_value,
                        ecma_op_object_get (obj_p, set_magic_string_p),
                        ret_value);

        if (!ecma_op_is_callable (set_prop_value)
            && !ecma_is_value_undefined (set_prop_value))
        {
          ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
        }
        else
        {
          prop_desc.is_set_defined = true;

          if (ecma_is_value_undefined (set_prop_value))
          {
            prop_desc.set_p = NULL;
          }
          else
          {
            JERRY_ASSERT (ecma_is_value_object (set_prop_value));

            ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value);
            ecma_ref_object (set_p);

            prop_desc.set_p = set_p;
          }
        }

        ECMA_FINALIZE (set_prop_value);
      }

      ecma_deref_ecma_string (set_magic_string_p);
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));

      // 9.
      if (prop_desc.is_get_defined
          || prop_desc.is_set_defined)
      {
        if (prop_desc.is_value_defined
            || prop_desc.is_writable_defined)
        {
          ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
        }
      }
    }

    if (!ecma_is_value_error (ret_value))
    {
      JERRY_ASSERT (ecma_is_value_empty (ret_value));
    }
    else
    {
      ecma_free_property_descriptor (&prop_desc);
    }

    *out_prop_desc_p = prop_desc;
  }

  return ret_value;
} /* ecma_op_to_property_descriptor */
Example #16
0
/**
 * The processor for PromiseReactionJob.
 *
 * See also: ES2015 25.4.2.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
static ecma_value_t
ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */
{
  ecma_job_promise_reaction_t *job_p = (ecma_job_promise_reaction_t *) obj_p;
  ecma_object_t *reaction_p = ecma_get_object_from_value (job_p->reaction);

  ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY);
  ecma_string_t *str_handler = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_HANDLER);
  ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE);
  ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT);

  /* 2. */
  ecma_value_t capability = ecma_op_object_get (reaction_p, str_capability);
  /* 3. */
  ecma_value_t handler = ecma_op_object_get (reaction_p, str_handler);

  JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler));

  ecma_value_t handler_result;

  if (ecma_is_value_boolean (handler))
  {
    /* 4-5. True indicates "identity" and false indicates "thrower" */
    handler_result = ecma_copy_value (job_p->argument);
  }
  else
  {
    /* 6. */
    handler_result = ecma_op_function_call (ecma_get_object_from_value (handler),
                                            ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
                                            &(job_p->argument),
                                            1);
  }

  ecma_value_t status;

  if (ecma_is_value_false (handler) || ECMA_IS_VALUE_ERROR (handler_result))
  {
    if (ECMA_IS_VALUE_ERROR (handler_result))
    {
      handler_result = ecma_get_value_from_error_value (handler_result);
    }

    /* 7. */
    ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject);

    JERRY_ASSERT (ecma_op_is_callable (reject));

    status = ecma_op_function_call (ecma_get_object_from_value (reject),
                                    ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
                                    &handler_result,
                                    1);
    ecma_free_value (reject);
  }
  else
  {
    /* 8. */
    ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve);

    JERRY_ASSERT (ecma_op_is_callable (resolve));

    status = ecma_op_function_call (ecma_get_object_from_value (resolve),
                                    ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
                                    &handler_result,
                                    1);
    ecma_free_value (resolve);
  }

  ecma_free_value (handler_result);
  ecma_free_value (handler);
  ecma_free_value (capability);
  ecma_deref_ecma_string (str_capability);
  ecma_deref_ecma_string (str_handler);
  ecma_deref_ecma_string (str_resolve);
  ecma_deref_ecma_string (str_reject);
  ecma_free_promise_reaction_job (job_p);

  return status;
} /* ecma_process_promise_reaction_job */
Example #17
0
/**
 * 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 */
/**
 * The Object object's 'defineProperties' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.7
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unused___, /**< '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.
  if (!ecma_is_value_object (arg1))
  {
    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 (arg1);

    // 2.
    ECMA_TRY_CATCH (props,
                    ecma_op_to_object (arg2),
                    ret_value);

    ecma_object_t *props_p = ecma_get_object_from_value (props);
    // 3.
    ecma_collection_header_t *prop_names_p = ecma_op_object_get_property_names (props_p, false, true, false);
    uint32_t property_number = prop_names_p->unit_number;

    ecma_collection_iterator_t iter;
    ecma_collection_iterator_init (&iter, prop_names_p);

    // 4.
    MEM_DEFINE_LOCAL_ARRAY (property_descriptors, property_number, ecma_property_descriptor_t);

    uint32_t property_descriptor_number = 0;

    while (ecma_collection_iterator_next (&iter)
           && ecma_is_completion_value_empty (ret_value))
    {
      // 5.a
      ECMA_TRY_CATCH (desc_obj,
                      ecma_op_object_get (props_p, ecma_get_string_from_value (*iter.current_value_p)),
                      ret_value);

      // 5.b
      ECMA_TRY_CATCH (conv_result,
                      ecma_op_to_property_descriptor (desc_obj,
                                                      &property_descriptors[property_descriptor_number]),
                      ret_value);

      property_descriptor_number++;

      ECMA_FINALIZE (conv_result);
      ECMA_FINALIZE (desc_obj);
    }

    // 6.
    ecma_collection_iterator_init (&iter, prop_names_p);
    for (uint32_t index = 0;
         index < property_number && ecma_is_completion_value_empty (ret_value);
         index++)
    {
      bool is_next = ecma_collection_iterator_next (&iter);
      JERRY_ASSERT (is_next);

      ECMA_TRY_CATCH (define_own_prop_ret,
                      ecma_op_object_define_own_property (obj_p,
                                                          ecma_get_string_from_value (*iter.current_value_p),
                                                          &property_descriptors[index],
                                                          true),
                      ret_value);

      ECMA_FINALIZE (define_own_prop_ret);
    }

    // Clean up
    for (uint32_t index = 0;
         index < property_descriptor_number;
         index++)
    {
      ecma_free_property_descriptor (&property_descriptors[index]);
    }

    MEM_FINALIZE_LOCAL_ARRAY (property_descriptors);

    ecma_free_values_collection (prop_names_p, true);

    // 7.
    if (ecma_is_completion_value_empty (ret_value))
    {
      ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg1, true));
    }

    ECMA_FINALIZE (props);
  }

  return ret_value;
} /* ecma_builtin_object_object_define_properties */
 * @return ecma value of undefined.
 */
static ecma_value_t
ecma_promise_reject_handler (const ecma_value_t function, /**< the function itself */
                             const ecma_value_t this, /**< this_arg of the function */
                             const ecma_value_t argv[], /**< argument list */
                             const ecma_length_t argc) /**< argument number */
{
  JERRY_UNUSED (this);

  ecma_string_t *str_promise_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE);
  ecma_string_t *str_already_resolved_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED);

  ecma_object_t *function_p = ecma_get_object_from_value (function);
  /* 2. */
  ecma_value_t promise = ecma_op_object_get (function_p, str_promise_p);
  /* 1. */
  JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise)));
  /* 3. */
  ecma_value_t already_resolved = ecma_op_object_get (function_p, str_already_resolved_p);

  /* 4. */
  if (ecma_get_already_resolved_bool_value (already_resolved))
  {
    ecma_free_value (promise);
    ecma_free_value (already_resolved);
    return ECMA_VALUE_UNDEFINED;
  }

  /* 5. */
  ecma_set_already_resolved_value (already_resolved, true);
/**
 * 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 */
/**
 * The String.prototype object's 'match' routine
 *
 * See also:
 *          ECMA-262 v5, 15.5.4.10
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_string_prototype_object_match (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 (this_check_coercible_value,
                  ecma_op_check_object_coercible (this_arg),
                  ret_value);

  /* 2. */
  ECMA_TRY_CATCH (this_to_string_value,
                  ecma_op_to_string (this_arg),
                  ret_value);

  ecma_value_t regexp_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
  /* 3. */
  if (ecma_is_value_object (arg)
      && ecma_object_get_class_name (ecma_get_object_from_value (arg)) == LIT_MAGIC_STRING_REGEXP_UL)
  {
    regexp_value = ecma_copy_value (arg, true);
  }
  else
  {
    /* 4. */
    ecma_value_t regexp_arguments[1] = { arg };
    ECMA_TRY_CATCH (new_regexp_value,
                    ecma_builtin_regexp_dispatch_construct (regexp_arguments, 1),
                    ret_value);

    regexp_value = ecma_copy_value (new_regexp_value, true);

    ECMA_FINALIZE (new_regexp_value);
  }

  if (ecma_is_completion_value_empty (ret_value))
  {
    JERRY_ASSERT (!ecma_is_value_empty (regexp_value));
    ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_value);
    ecma_string_t *global_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL);

    /* 5. */
    ECMA_TRY_CATCH (global_value,
                    ecma_op_object_get (regexp_obj_p, global_string_p),
                    ret_value);

    JERRY_ASSERT (ecma_is_value_boolean (global_value));

    ecma_value_t exec_arguments[1] = { this_to_string_value };

    if (!ecma_is_value_true (global_value))
    {
      /* 7. */
      ret_value = ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC,
                                                                  regexp_value,
                                                                  exec_arguments,
                                                                  1);
    }
    else
    {
      /* 8.a. */
      ecma_number_t *zero_number_p = ecma_alloc_number ();
      *zero_number_p = 0;

      ecma_string_t *index_zero_string_p = ecma_new_ecma_string_from_uint32 (0);

      ecma_string_t *last_index_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);

      ECMA_TRY_CATCH (put_value,
                      ecma_op_object_put (regexp_obj_p,
                                          last_index_string_p,
                                          ecma_make_number_value (zero_number_p),
                                          true),
                      ret_value);

      /* 8.b. */
      ECMA_TRY_CATCH (new_array_value,
                      ecma_op_create_array_object (NULL, 0, false),
                      ret_value);

      ecma_object_t *new_array_obj_p = ecma_get_object_from_value (new_array_value);

      /* 8.c. */
      ecma_number_t previous_last_index = 0;
      /* 8.d. */
      uint32_t n = 0;
      /* 8.e. */
      bool last_match = true;

      //ecma_completion_value_t exec_result = ecma_make_empty_completion_value ();

      /* 8.f. */
      while (last_match && ecma_is_completion_value_empty (ret_value))
      {
        /* 8.f.i. */
        ECMA_TRY_CATCH (exec_value,
                        ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC,
                                                                        regexp_value,
                                                                        exec_arguments,
                                                                        1),
                        ret_value);

        if (ecma_is_value_null (exec_value))
        {
          /* 8.f.ii. */
          last_match = false;
        }
        else
        {
          /* 8.f.iii. */
          ECMA_TRY_CATCH (this_index_value,
                          ecma_op_object_get (regexp_obj_p, last_index_string_p),
                          ret_value);

          ECMA_TRY_CATCH (this_index_number,
                          ecma_op_to_number (this_index_value),
                          ret_value);

          ecma_number_t this_index = *ecma_get_number_from_value (this_index_number);

          /* 8.f.iii.2. */
          if (this_index == previous_last_index)
          {
            ecma_number_t *new_last_index_p = ecma_alloc_number ();
            *new_last_index_p = this_index + 1;
            /* 8.f.iii.2.a. */
            ECMA_TRY_CATCH (index_put_value,
                            ecma_op_object_put (regexp_obj_p,
                                                last_index_string_p,
                                                ecma_make_number_value (new_last_index_p),
                                                true),
                            ret_value);

            /* 8.f.iii.2.b. */
            previous_last_index = this_index + 1;

            ECMA_FINALIZE (index_put_value);

            ecma_dealloc_number (new_last_index_p);
          }
          else
          {
            /* 8.f.iii.3. */
            previous_last_index = this_index;
          }

          if (ecma_is_completion_value_empty (ret_value))
          {
            /* 8.f.iii.4. */
            JERRY_ASSERT (ecma_is_value_object (exec_value));
            ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value);

            ECMA_TRY_CATCH (match_string_value,
                            ecma_op_object_get (exec_obj_p, index_zero_string_p),
                            ret_value);

            /* 8.f.iii.5. */
            ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
            {
              prop_desc.is_value_defined = true;
              prop_desc.value = match_string_value;

              prop_desc.is_writable_defined = true;
              prop_desc.is_writable = true;

              prop_desc.is_enumerable_defined = true;
              prop_desc.is_enumerable = true;

              prop_desc.is_configurable_defined = true;
              prop_desc.is_configurable = true;
            }

            ecma_string_t *current_index_str_p = ecma_new_ecma_string_from_uint32 (n);

            ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_obj_p,
                                                                                     current_index_str_p,
                                                                                     &prop_desc,
                                                                                     false);
            JERRY_ASSERT (ecma_is_completion_value_normal_true (completion));

            ecma_deref_ecma_string (current_index_str_p);

            /* 8.f.iii.6. */
            n++;

            ECMA_FINALIZE (match_string_value);
          }

          ECMA_FINALIZE (this_index_number);

          ECMA_FINALIZE (this_index_value);
        }

        ECMA_FINALIZE (exec_value);
      }

      if (ecma_is_completion_value_empty (ret_value))
      {
        if (n == 0)
        {
          /* 8.g. */
          ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_NULL);
        }
        else
        {
          /* 8.h. */
          ret_value = ecma_make_normal_completion_value (ecma_copy_value (new_array_value, true));
        }
      }

      ECMA_FINALIZE (new_array_value);

      ECMA_FINALIZE (put_value);

      ecma_deref_ecma_string (last_index_string_p);
      ecma_deref_ecma_string (index_zero_string_p);
      ecma_dealloc_number (zero_number_p);
    }

    ECMA_FINALIZE (global_value);

    ecma_deref_ecma_string (global_string_p);

    ecma_free_value (regexp_value, true);
  }

  ECMA_FINALIZE (this_to_string_value);

  ECMA_FINALIZE (this_check_coercible_value);

  return ret_value;
} /* ecma_builtin_string_prototype_object_match */
Example #22
0
/**
 * [[Call]] implementation for Function objects,
 * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION)
 * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION),
 * and for built-in Function objects
 * from section 15 (ECMA_OBJECT_TYPE_FUNCTION).
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object */
                               ecma_value_t value) /**< argument 'V' */
{
  JERRY_ASSERT (func_obj_p != NULL
                && !ecma_is_lexical_environment (func_obj_p));

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
  {
    if (ecma_get_object_is_builtin (func_obj_p)
        && ecma_builtin_function_is_routine (func_obj_p))
    {
      return ecma_raise_type_error (ECMA_ERR_MSG ("Function parameter cannot be built-in a function."));
    }

    if (!ecma_is_value_object (value))
    {
      return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
    }

    ecma_object_t *v_obj_p = ecma_get_object_from_value (value);

    ecma_string_t *prototype_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);

    ECMA_TRY_CATCH (prototype_obj_value,
                    ecma_op_object_get (func_obj_p, prototype_magic_string_p),
                    ret_value);

    if (!ecma_is_value_object (prototype_obj_value))
    {
      ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected an object."));
    }
    else
    {
      ecma_object_t *prototype_obj_p = ecma_get_object_from_value (prototype_obj_value);
      JERRY_ASSERT (prototype_obj_p != NULL);

      do
      {
        v_obj_p = ecma_get_object_prototype (v_obj_p);

        if (v_obj_p == NULL)
        {
          ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);

          break;
        }
        else if (v_obj_p == prototype_obj_p)
        {
          ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);

          break;
        }
      } while (true);
    }

    ECMA_FINALIZE (prototype_obj_value);

    ecma_deref_ecma_string (prototype_magic_string_p);
  }
  else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected a function."));
  }
  else
  {
    JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);

    /* 1. */
    ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;

    ecma_object_t *target_func_obj_p;
    target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
                                                         ext_function_p->u.bound_function.target_function);

    /* 3. */
    ret_value = ecma_op_object_has_instance (target_func_obj_p, value);
  }

  return ret_value;
} /* ecma_op_function_has_instance */
/**
 * [[Call]] implementation for Function objects,
 * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION)
 * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION),
 * and for built-in Function objects
 * from section 15 (ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION).
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object */
                               ecma_value_t value) /**< argument 'V' */
{
  JERRY_ASSERT (func_obj_p != NULL
                && !ecma_is_lexical_environment (func_obj_p));

  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
  {
    if (!ecma_is_value_object (value))
    {
      return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE);
    }

    ecma_object_t* v_obj_p = ecma_get_object_from_value (value);

    ecma_string_t *prototype_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);

    ECMA_TRY_CATCH (prototype_obj_value,
                    ecma_op_object_get (func_obj_p, prototype_magic_string_p),
                    ret_value);

    if (!ecma_is_value_object (prototype_obj_value))
    {
      ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
    }
    else
    {
      ecma_object_t *prototype_obj_p = ecma_get_object_from_value (prototype_obj_value);
      JERRY_ASSERT (prototype_obj_p != NULL);

      do
      {
        v_obj_p = ecma_get_object_prototype (v_obj_p);

        if (v_obj_p == NULL)
        {
          ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE);

          break;
        }
        else if (v_obj_p == prototype_obj_p)
        {
          ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);

          break;
        }
      } while (true);
    }

    ECMA_FINALIZE (prototype_obj_value);

    ecma_deref_ecma_string (prototype_magic_string_p);
  }
  else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);

    /* 1. */
    ecma_property_t *target_function_prop_p;
    target_function_prop_p = ecma_get_internal_property (func_obj_p,
                                                         ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);

    ecma_object_t *target_func_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
                                                                  target_function_prop_p->u.internal_property.value);

    /* 3. */
    ret_value = ecma_op_object_has_instance (target_func_obj_p, value);
  }

  return ret_value;
} /* ecma_op_function_has_instance */
/**
 * GetValue operation part (object base).
 *
 * See also: ECMA-262 v5, 8.7.1, section 4
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_op_get_value_object_base (ecma_reference_t ref) /**< ECMA-reference */
{
  const ecma_value_t base = ref.base;
  const bool is_unresolvable_reference = ecma_is_value_undefined (base);
  const bool has_primitive_base = (ecma_is_value_boolean (base)
                                   || ecma_is_value_number (base)
                                   || ecma_is_value_string (base));
  const bool has_object_base = (ecma_is_value_object (base)
                                && !(ecma_is_lexical_environment (ecma_get_object_from_value (base))));
  const bool is_property_reference = has_primitive_base || has_object_base;

  JERRY_ASSERT (!is_unresolvable_reference);
  JERRY_ASSERT (is_property_reference);

  ecma_string_t *referenced_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
                                                                ref.referenced_name_cp);

  // 4.a
  if (!has_primitive_base)
  {
    // 4.b case 1

    ecma_object_t *obj_p = ecma_get_object_from_value (base);
    JERRY_ASSERT (obj_p != NULL
                  && !ecma_is_lexical_environment (obj_p));

    return ecma_op_object_get (obj_p, referenced_name_p);
  }
  else
  {
    // 4.b case 2
    ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

    // 1.
    ECMA_TRY_CATCH (obj_base, ecma_op_to_object (base), ret_value);

    ecma_object_t *obj_p = ecma_get_object_from_value (obj_base);
    JERRY_ASSERT (obj_p != NULL
                  && !ecma_is_lexical_environment (obj_p));


    // 2.
    ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, referenced_name_p);

    if (prop_p == NULL)
    {
      // 3.
      ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
    }
    else if (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDDATA)
    {
      // 4.
      ret_value = ecma_copy_value (ecma_get_named_data_property_value (prop_p), true);
    }
    else
    {
      // 5.
      JERRY_ASSERT (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDACCESSOR);

      ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (prop_p);

      // 6.
      if (obj_p == NULL)
      {
        ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
      }
      else
      {
        // 7.
        ret_value = ecma_op_function_call (obj_p, base, NULL, 0);
      }
    }

    ECMA_FINALIZE (obj_base);

    return ret_value;
  }
} /* ecma_op_get_value_object_base */
/**
 * The Function.prototype object's 'apply' routine
 *
 * See also:
 *          ECMA-262 v5, 15.3.4.3
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */
                                              ecma_value_t arg1, /**< first argument */
                                              ecma_value_t arg2) /**< second argument */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  /* 1. */
  if (!ecma_op_is_callable (this_arg))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg);

    /* 2. */
    if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2))
    {
      ret_value = ecma_op_function_call (func_obj_p, arg1, NULL);
    }
    else
    {
      /* 3. */
      if (!ecma_is_value_object (arg2))
      {
        ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
      }
      else
      {
        ecma_object_t *obj_p = ecma_get_object_from_value (arg2);
        ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);

        /* 4. */
        ECMA_TRY_CATCH (length_value,
                        ecma_op_object_get (obj_p, length_magic_string_p),
                        ret_value);

        ECMA_OP_TO_NUMBER_TRY_CATCH (length_number,
                                     length_value,
                                     ret_value);

        /* 5. */
        const uint32_t length = ecma_number_to_uint32 (length_number);

        /* 6. */
        ecma_collection_header_t *arg_collection_p = ecma_new_values_collection (NULL, 0, true);

        /* 7. */
        for (uint32_t index = 0; index < length && ecma_is_completion_value_empty (ret_value); index++)
        {
          ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index);

          ECMA_TRY_CATCH (get_value,
                          ecma_op_object_get (obj_p, curr_idx_str_p),
                          ret_value);

          ecma_append_to_values_collection (arg_collection_p, get_value, true);

          ECMA_FINALIZE (get_value);
          ecma_deref_ecma_string (curr_idx_str_p);
        }

        JERRY_ASSERT (arg_collection_p->unit_number == length || !ecma_is_completion_value_empty (ret_value));

        if (ecma_is_completion_value_empty (ret_value))
        {
          ret_value = ecma_op_function_call (func_obj_p,
                                             arg1,
                                             arg_collection_p);
        }

        ecma_free_values_collection (arg_collection_p, true);

        ECMA_OP_TO_NUMBER_FINALIZE (length_number);
        ECMA_FINALIZE (length_value);
        ecma_deref_ecma_string (length_magic_string_p);
      }
    }
  }

  return ret_value;
} /* ecma_builtin_function_prototype_object_apply */
/**
 * The Function.prototype object's 'bind' routine
 *
 * See also:
 *          ECMA-262 v5, 15.3.4.5
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this argument */
                                             const ecma_value_t *arguments_list_p, /**< list of arguments */
                                             ecma_length_t arguments_number) /**< number of arguments */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 2. */
  if (!ecma_op_is_callable (this_arg))
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
  }
  else
  {
    /* 4. 11. 18. */
    ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
    ecma_object_t *function_p = ecma_create_object (prototype_obj_p,
                                                    false,
                                                    true,
                                                    ECMA_OBJECT_TYPE_BOUND_FUNCTION);

    ecma_deref_object (prototype_obj_p);

    /* 7. */
    ecma_value_t *target_function_prop_p;
    target_function_prop_p = ecma_create_internal_property (function_p,
                                                            ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);

    ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg);
    ECMA_SET_INTERNAL_VALUE_POINTER (*target_function_prop_p, this_arg_obj_p);

    /* 8. */
    ecma_value_t *bound_this_prop_p;
    bound_this_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS);
    const ecma_length_t arg_count = arguments_number;

    if (arg_count > 0)
    {
      *bound_this_prop_p = ecma_copy_value_if_not_object (arguments_list_p[0]);
    }
    else
    {
      *bound_this_prop_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
    }

    if (arg_count > 1)
    {
      ecma_collection_header_t *bound_args_collection_p;
      bound_args_collection_p = ecma_new_values_collection (&arguments_list_p[1], arg_count - 1, false);

      ecma_value_t *bound_args_prop_p;
      bound_args_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS);
      ECMA_SET_INTERNAL_VALUE_POINTER (*bound_args_prop_p, bound_args_collection_p);
    }

    /*
     * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type.
     *
     * See also: ecma_object_get_class_name
     */

    /* 16. */
    ecma_number_t length = ECMA_NUMBER_ZERO;
    ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();

    /* 15. */
    if (ecma_object_get_class_name (this_arg_obj_p) == LIT_MAGIC_STRING_FUNCTION_UL)
    {
      ecma_value_t get_len_value = ecma_op_object_get (this_arg_obj_p, magic_string_length_p);
      JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value));
      JERRY_ASSERT (ecma_is_value_number (get_len_value));

      const ecma_length_t bound_arg_count = arg_count > 1 ? arg_count - 1 : 0;

      /* 15.a */
      length = ecma_get_number_from_value (get_len_value) - ((ecma_number_t) bound_arg_count);
      ecma_free_value (get_len_value);

      /* 15.b */
      if (ecma_number_is_negative (length))
      {
        length = ECMA_NUMBER_ZERO;
      }
    }

    /* 17. */
    ecma_value_t completion = ecma_builtin_helper_def_prop (function_p,
                                                            magic_string_length_p,
                                                            ecma_make_number_value (length),
                                                            false, /* Writable */
                                                            false, /* Enumerable */
                                                            false, /* Configurable */
                                                            false); /* Failure handling */

    JERRY_ASSERT (ecma_is_value_boolean (completion));

    ecma_deref_ecma_string (magic_string_length_p);

    /* 19-21. */
    ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);

    ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
    {
      prop_desc.is_enumerable_defined = true;
      prop_desc.is_enumerable = false;

      prop_desc.is_configurable_defined = true;
      prop_desc.is_configurable = false;

      prop_desc.is_get_defined = true;
      prop_desc.get_p = thrower_p;

      prop_desc.is_set_defined = true;
      prop_desc.set_p = thrower_p;
    }

    ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER);
    completion = ecma_op_object_define_own_property (function_p,
                                                     magic_string_caller_p,
                                                     &prop_desc,
                                                     false);

    JERRY_ASSERT (ecma_is_value_boolean (completion));

    ecma_deref_ecma_string (magic_string_caller_p);

    ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS);
    completion = ecma_op_object_define_own_property (function_p,
                                                     magic_string_arguments_p,
                                                     &prop_desc,
                                                     false);

    JERRY_ASSERT (ecma_is_value_boolean (completion));

    ecma_deref_ecma_string (magic_string_arguments_p);
    ecma_deref_object (thrower_p);

    /* 22. */
    ret_value = ecma_make_object_value (function_p);
  }

  return ret_value;
} /* ecma_builtin_function_prototype_object_bind */
/**
 * 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 */
/**
 * Helper function for concatenating an ecma_value_t to an Array.
 *
 * See also:
 *          ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c
 *
 * Used by:
 *         - The Array.prototype.concat routine.
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
ecma_completion_value_t
ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */
                                        uint32_t *length_p, /**< in-out: array's length */
                                        ecma_value_t value) /**< value to concat */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  /* 5.b */
  if (ecma_is_value_object (value)
      && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL))
  {
    ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
    /* 5.b.ii */
    ECMA_TRY_CATCH (arg_len_value,
                    ecma_op_object_get (ecma_get_object_from_value (value),
                                        magic_string_length_p),
                    ret_value);
    ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value);

    uint32_t arg_len = ecma_number_to_uint32 (arg_len_number);

    /* 5.b.iii */
    for (uint32_t array_index = 0;
         array_index < arg_len && ecma_is_completion_value_empty (ret_value);
         array_index++)
    {
      ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index);

      /* 5.b.iii.2 */
      if (ecma_op_object_get_property (ecma_get_object_from_value (value),
                                       array_index_string_p) != NULL)
      {
        ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index);

        /* 5.b.iii.3.a */
        ECMA_TRY_CATCH (get_value,
                        ecma_op_object_get (ecma_get_object_from_value (value),
                                            array_index_string_p),
                        ret_value);

        ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
        {
          prop_desc.is_value_defined = true;
          prop_desc.value = get_value;

          prop_desc.is_writable_defined = true;
          prop_desc.is_writable = true;

          prop_desc.is_enumerable_defined = true;
          prop_desc.is_enumerable = true;

          prop_desc.is_configurable_defined = true;
          prop_desc.is_configurable = true;
        }

        /* 5.b.iii.3.b */
        /* This will always be a simple value since 'is_throw' is false, so no need to free. */
        ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p,
                                                                               new_array_index_string_p,
                                                                               &prop_desc,
                                                                               false);
        JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));

        ECMA_FINALIZE (get_value);
        ecma_deref_ecma_string (new_array_index_string_p);
      }

      ecma_deref_ecma_string (array_index_string_p);
    }

    *length_p += arg_len;

    ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number);
    ECMA_FINALIZE (arg_len_value);
    ecma_deref_ecma_string (magic_string_length_p);
  }
  else
  {
    ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++);

    ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
    {
      prop_desc.is_value_defined = true;
      prop_desc.value = value;

      prop_desc.is_writable_defined = true;
      prop_desc.is_writable = true;

      prop_desc.is_enumerable_defined = true;
      prop_desc.is_enumerable = true;

      prop_desc.is_configurable_defined = true;
      prop_desc.is_configurable = true;
    }

    /* 5.c.i */
    /* This will always be a simple value since 'is_throw' is false, so no need to free. */
    ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p,
                                                                           new_array_index_string_p,
                                                                           &prop_desc,
                                                                           false);
    JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));

    ecma_deref_ecma_string (new_array_index_string_p);
  }

  if (ecma_is_completion_value_empty (ret_value))
  {
    ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  return ret_value;
} /* ecma_builtin_helper_array_concat_value */
/**
 * Helper function for concatenating an ecma_value_t to an Array.
 *
 * See also:
 *          ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c
 *
 * Used by:
 *         - The Array.prototype.concat routine.
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
ecma_value_t
ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */
                                        uint32_t *length_p, /**< [in,out] array's length */
                                        ecma_value_t value) /**< value to concat */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 5.b */
  if (ecma_is_value_object (value)
      && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL))
  {
    ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();
    /* 5.b.ii */
    ECMA_TRY_CATCH (arg_len_value,
                    ecma_op_object_get (ecma_get_object_from_value (value),
                                        magic_string_length_p),
                    ret_value);
    ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value);

    uint32_t arg_len = ecma_number_to_uint32 (arg_len_number);

    /* 5.b.iii */
    for (uint32_t array_index = 0;
         array_index < arg_len && ecma_is_value_empty (ret_value);
         array_index++)
    {
      ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index);

      /* 5.b.iii.2 */
      if (ecma_op_object_get_property (ecma_get_object_from_value (value),
                                       array_index_string_p) != NULL)
      {
        ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index);

        /* 5.b.iii.3.a */
        ECMA_TRY_CATCH (get_value,
                        ecma_op_object_get (ecma_get_object_from_value (value),
                                            array_index_string_p),
                        ret_value);

        /* 5.b.iii.3.b */
        /* This will always be a simple value since 'is_throw' is false, so no need to free. */
        ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p,
                                                              new_array_index_string_p,
                                                              get_value,
                                                              true, /* Writable */
                                                              true, /* Enumerable */
                                                              true, /* Configurable */
                                                              false); /* Failure handling */

        JERRY_ASSERT (ecma_is_value_true (put_comp));

        ECMA_FINALIZE (get_value);
        ecma_deref_ecma_string (new_array_index_string_p);
      }

      ecma_deref_ecma_string (array_index_string_p);
    }

    *length_p += arg_len;

    ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number);
    ECMA_FINALIZE (arg_len_value);
    ecma_deref_ecma_string (magic_string_length_p);
  }
  else
  {
    ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++);

    /* 5.c.i */
    /* This will always be a simple value since 'is_throw' is false, so no need to free. */
    ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p,
                                                          new_array_index_string_p,
                                                          value,
                                                          true, /* Writable */
                                                          true, /* Enumerable */
                                                          true, /* Configurable */
                                                          false); /* Failure handling */

    JERRY_ASSERT (ecma_is_value_true (put_comp));

    ecma_deref_ecma_string (new_array_index_string_p);
  }

  if (ecma_is_value_empty (ret_value))
  {
    ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  return ret_value;
} /* ecma_builtin_helper_array_concat_value */