/**
 * Number object creation operation.
 *
 * See also: ECMA-262 v5, 15.7.2.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */
{
  ecma_value_t conv_to_num_completion = ecma_op_to_number (arg);

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

#ifndef CONFIG_DISABLE_NUMBER_BUILTIN
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE);
#else /* CONFIG_DISABLE_NUMBER_BUILTIN */
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
#endif /* !CONFIG_DISABLE_NUMBER_BUILTIN */

  ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
                                                sizeof (ecma_extended_object_t),
                                                ECMA_OBJECT_TYPE_CLASS);

  ecma_deref_object (prototype_obj_p);

  ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
  ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_NUMBER_UL;

  /* Pass reference (no need to free conv_to_num_completion). */
  ext_object_p->u.class_prop.value = conv_to_num_completion;

  return ecma_make_object_value (object_p);
} /* ecma_op_create_number_object */
示例#2
0
/**
 * Number object creation operation.
 *
 * See also: ECMA-262 v5, 15.7.2.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */
{
  ecma_value_t conv_to_num_completion = ecma_op_to_number (arg);

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

#ifndef CONFIG_DISABLE_NUMBER_BUILTIN
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE);
#else /* CONFIG_DISABLE_NUMBER_BUILTIN */
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
#endif /* !CONFIG_DISABLE_NUMBER_BUILTIN */

  ecma_object_t *obj_p = ecma_create_object (prototype_obj_p,
                                             false,
                                             true,
                                             ECMA_OBJECT_TYPE_GENERAL);
  ecma_deref_object (prototype_obj_p);

  ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS);
  ECMA_PROPERTY_VALUE_PTR (class_prop_p)->value = LIT_MAGIC_STRING_NUMBER_UL;

  ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p,
                                                                      ECMA_INTERNAL_PROPERTY_ECMA_VALUE);

  /* Pass reference (no need to free conv_to_num_completion). */
  ecma_set_internal_property_value (prim_value_prop_p, conv_to_num_completion);

  return ecma_make_object_value (obj_p);
} /* ecma_op_create_number_object */
/**
 * Number object creation operation.
 *
 * See also: ECMA-262 v5, 15.7.2.1
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */
{
  ecma_completion_value_t conv_to_num_completion = ecma_op_to_number (arg);

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

  ecma_number_t *prim_value_p = ecma_get_number_from_completion_value (conv_to_num_completion);

#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE);
#else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */
  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
#endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */

  ecma_object_t *obj_p = ecma_create_object (prototype_obj_p,
                                             true,
                                             ECMA_OBJECT_TYPE_GENERAL);
  ecma_deref_object (prototype_obj_p);

  ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS);
  class_prop_p->u.internal_property.value = LIT_MAGIC_STRING_NUMBER_UL;

  ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p,
                                                                      ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE);
  ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_value_p);

  return ecma_make_normal_completion_value (ecma_make_object_value (obj_p));
} /* ecma_op_create_number_object */
/**
 * ArrayBuffer object creation operation.
 *
 * See also: ES2015 24.1.1.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that
                                                                          *   are passed to String constructor */
                                   ecma_length_t arguments_list_len) /**< length of the arguments' list */
{
  JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);

  ecma_number_t length_num = 0;

  if (arguments_list_len > 0)
  {

    if (ecma_is_value_number (arguments_list_p[0]))
    {
      length_num = ecma_get_number_from_value (arguments_list_p[0]);
    }
    else
    {
      ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0]);

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

      length_num = ecma_get_number_from_value (to_number_value);

      ecma_free_value (to_number_value);
    }

    if (ecma_number_is_nan (length_num))
    {
      length_num = 0;
    }

    const uint32_t maximum_size_in_byte = UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1;

    if (length_num <= -1.0 || length_num > (double) maximum_size_in_byte + 0.5)
    {
      return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid ArrayBuffer length."));
    }
  }

  uint32_t length_uint32 = ecma_number_to_uint32 (length_num);

  return ecma_make_object_value (ecma_arraybuffer_new_object (length_uint32));
} /* ecma_op_create_arraybuffer_object */
示例#5
0
/**
 * Handle calling [[Call]] of built-in Number object
 *
 * @return ecma value
 */
ecma_value_t
ecma_builtin_number_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
                                   ecma_length_t arguments_list_len) /**< number of arguments */
{
  JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  if (arguments_list_len == 0)
  {
    ret_value = ecma_make_integer_value (0);
  }
  else
  {
    ret_value = ecma_op_to_number (arguments_list_p[0]);
  }

  return ret_value;
} /* ecma_builtin_number_dispatch_call */
示例#6
0
/**
 * ECMA abstract equality comparison routine.
 *
 * See also: ECMA-262 v5, 11.9.3
 *
 * Note:
 *      This function might raise an exception, so the
 *      returned value must be freed with ecma_free_value.
 *
 * @return true - if values are equal,
 *         false - otherwise
 *         error - in case of any problems
 */
ecma_value_t
ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */
                                   ecma_value_t y) /**< second operand */
{
  if (x == y)
  {
    return ECMA_VALUE_TRUE;
  }

  if (ecma_are_values_integer_numbers (x, y))
  {
    /* Note: the (x == y) comparison captures the true case. */
    return ECMA_VALUE_FALSE;
  }

  if (ecma_is_value_number (x))
  {
    if (ecma_is_value_number (y))
    {
      /* 1.c */
      ecma_number_t x_num = ecma_get_number_from_value (x);
      ecma_number_t y_num = ecma_get_number_from_value (y);

      bool is_x_equal_to_y = (x_num == y_num);

#ifndef JERRY_NDEBUG
      bool is_x_equal_to_y_check;

      if (ecma_number_is_nan (x_num)
          || ecma_number_is_nan (y_num))
      {
        is_x_equal_to_y_check = false;
      }
      else if (x_num == y_num
               || (ecma_number_is_zero (x_num)
                   && ecma_number_is_zero (y_num)))
      {
        is_x_equal_to_y_check = true;
      }
      else
      {
        is_x_equal_to_y_check = false;
      }

      JERRY_ASSERT (is_x_equal_to_y == is_x_equal_to_y_check);
#endif /* !JERRY_NDEBUG */

      return ecma_make_boolean_value (is_x_equal_to_y);
    }

    /* Swap values. */
    ecma_value_t tmp = x;
    x = y;
    y = tmp;
  }

  if (ecma_is_value_string (x))
  {
    if (ecma_is_value_string (y))
    {
      /* 1., d. */
      ecma_string_t *x_str_p = ecma_get_string_from_value (x);
      ecma_string_t *y_str_p = ecma_get_string_from_value (y);

      bool is_equal = ecma_compare_ecma_strings (x_str_p, y_str_p);

      return ecma_make_boolean_value (is_equal);
    }

    if (ecma_is_value_number (y))
    {
      /* 4. */
      ecma_value_t x_num_value = ecma_op_to_number (x);

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

      ecma_value_t compare_result = ecma_op_abstract_equality_compare (x_num_value, y);

      ecma_free_value (x_num_value);
      return compare_result;
    }

    /* Swap values. */
    ecma_value_t tmp = x;
    x = y;
    y = tmp;
  }

#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
  if (ecma_is_value_symbol (x))
  {
    return ECMA_VALUE_FALSE;
  }
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */

  if (ecma_is_value_boolean (y))
  {
    if (ecma_is_value_boolean (x))
    {
      /* 1., e. */
      /* Note: the (x == y) comparison captures the true case. */
      return ECMA_VALUE_FALSE;
    }

    /* 7. */
    return ecma_op_abstract_equality_compare (x, ecma_make_integer_value (ecma_is_value_true (y) ? 1 : 0));
  }

  if (ecma_is_value_object (x))
  {
    if (ecma_is_value_string (y)
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
        || ecma_is_value_symbol (y)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
        || ecma_is_value_number (y))
    {
      /* 9. */
      ecma_value_t x_prim_value = ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NO);

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

      ecma_value_t compare_result = ecma_op_abstract_equality_compare (x_prim_value, y);

      ecma_free_value (x_prim_value);
      return compare_result;
    }

    /* 1., f. */
    /* Note: the (x == y) comparison captures the true case. */
    return ECMA_VALUE_FALSE;
  }

  if (ecma_is_value_boolean (x))
  {
    /* 6. */
    return ecma_op_abstract_equality_compare (ecma_make_integer_value (ecma_is_value_true (x) ? 1 : 0), y);
  }

  if (ecma_is_value_undefined (x)
      || ecma_is_value_null (x))
  {
    /* 1. a., b. */
    /* 2., 3. */
    bool is_equal = ecma_is_value_undefined (y) || ecma_is_value_null (y);

    return ecma_make_boolean_value (is_equal);
  }

  return ECMA_VALUE_FALSE;
} /* ecma_op_abstract_equality_compare */
/**
  * Calculate MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)) for Date constructor and UTC
  *
  * See also:
  *          ECMA-262 v5, 15.9.3.1
  *          ECMA-262 v5, 15.9.4.3
  *
  * @return result of MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))
  */
static ecma_completion_value_t
ecma_date_construct_helper (const ecma_value_t *args, /**< arguments passed to the Date constructor */
                            ecma_length_t args_len) /**< number of arguments */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
  ecma_number_t *prim_value_p = ecma_alloc_number ();
  *prim_value_p = ecma_number_make_nan ();

  ECMA_TRY_CATCH (year_value, ecma_op_to_number (args[0]), ret_value);
  ECMA_TRY_CATCH (month_value, ecma_op_to_number (args[1]), ret_value);

  ecma_number_t year = *ecma_get_number_from_value (year_value);
  ecma_number_t month = *ecma_get_number_from_value (month_value);
  ecma_number_t date = ECMA_NUMBER_ONE;
  ecma_number_t hours = ECMA_NUMBER_ZERO;
  ecma_number_t minutes = ECMA_NUMBER_ZERO;
  ecma_number_t seconds = ECMA_NUMBER_ZERO;
  ecma_number_t milliseconds = ECMA_NUMBER_ZERO;

  /* 3. */
  if (args_len >= 3 && ecma_is_completion_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (date_value, ecma_op_to_number (args[2]), ret_value);
    date = *ecma_get_number_from_value (date_value);
    ECMA_FINALIZE (date_value);
  }

  /* 4. */
  if (args_len >= 4 && ecma_is_completion_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (hours_value, ecma_op_to_number (args[3]), ret_value);
    hours = *ecma_get_number_from_value (hours_value);
    ECMA_FINALIZE (hours_value);
  }

  /* 5. */
  if (args_len >= 5 && ecma_is_completion_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (minutes_value, ecma_op_to_number (args[4]), ret_value);
    minutes = *ecma_get_number_from_value (minutes_value);
    ECMA_FINALIZE (minutes_value);
  }

  /* 6. */
  if (args_len >= 6 && ecma_is_completion_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (seconds_value, ecma_op_to_number (args[5]), ret_value);
    seconds = *ecma_get_number_from_value (seconds_value);
    ECMA_FINALIZE (seconds_value);
  }

  /* 7. */
  if (args_len >= 7 && ecma_is_completion_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (milliseconds_value, ecma_op_to_number (args[6]), ret_value);
    milliseconds = *ecma_get_number_from_value (milliseconds_value);
    ECMA_FINALIZE (milliseconds_value);
  }

  if (ecma_is_completion_value_empty (ret_value))
  {
    if (!ecma_number_is_nan (year) && !ecma_number_is_infinity (year))
    {
      /* 8. */
      int32_t y = ecma_number_to_int32 (year);

      if (y >= 0 && y <= 99)
      {
        year = (ecma_number_t) (1900 + y);
      }
      else
      {
        year = (ecma_number_t) y;
      }
    }

    *prim_value_p = ecma_date_make_date (ecma_date_make_day (year,
                                                             month,
                                                             date),
                                         ecma_date_make_time (hours,
                                                              minutes,
                                                              seconds,
                                                              milliseconds));
  }

  ECMA_FINALIZE (month_value);
  ECMA_FINALIZE (year_value);

  if (ecma_is_completion_value_empty (ret_value))
  {
    ret_value = ecma_make_normal_completion_value (ecma_make_number_value (prim_value_p));
  }
  else
  {
    ecma_dealloc_number (prim_value_p);
  }

  return ret_value;
} /* ecma_date_construct_helper */
示例#8
0
/**
  * Calculate MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)) for Date constructor and UTC
  *
  * See also:
  *          ECMA-262 v5, 15.9.3.1
  *          ECMA-262 v5, 15.9.4.3
  *
  * @return result of MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))
  */
static ecma_value_t
ecma_date_construct_helper (const ecma_value_t *args, /**< arguments passed to the Date constructor */
                            ecma_length_t args_len) /**< number of arguments */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
  ecma_number_t prim_value = ecma_number_make_nan ();

  ECMA_TRY_CATCH (year_value, ecma_op_to_number (args[0]), ret_value);
  ECMA_TRY_CATCH (month_value, ecma_op_to_number (args[1]), ret_value);

  ecma_number_t year = ecma_get_number_from_value (year_value);
  ecma_number_t month = ecma_get_number_from_value (month_value);
  ecma_number_t date = ECMA_NUMBER_ONE;
  ecma_number_t hours = ECMA_NUMBER_ZERO;
  ecma_number_t minutes = ECMA_NUMBER_ZERO;
  ecma_number_t seconds = ECMA_NUMBER_ZERO;
  ecma_number_t milliseconds = ECMA_NUMBER_ZERO;

  /* 3. */
  if (args_len >= 3 && ecma_is_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (date_value, ecma_op_to_number (args[2]), ret_value);
    date = ecma_get_number_from_value (date_value);
    ECMA_FINALIZE (date_value);
  }

  /* 4. */
  if (args_len >= 4 && ecma_is_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (hours_value, ecma_op_to_number (args[3]), ret_value);
    hours = ecma_get_number_from_value (hours_value);
    ECMA_FINALIZE (hours_value);
  }

  /* 5. */
  if (args_len >= 5 && ecma_is_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (minutes_value, ecma_op_to_number (args[4]), ret_value);
    minutes = ecma_get_number_from_value (minutes_value);
    ECMA_FINALIZE (minutes_value);
  }

  /* 6. */
  if (args_len >= 6 && ecma_is_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (seconds_value, ecma_op_to_number (args[5]), ret_value);
    seconds = ecma_get_number_from_value (seconds_value);
    ECMA_FINALIZE (seconds_value);
  }

  /* 7. */
  if (args_len >= 7 && ecma_is_value_empty (ret_value))
  {
    ECMA_TRY_CATCH (milliseconds_value, ecma_op_to_number (args[6]), ret_value);
    milliseconds = ecma_get_number_from_value (milliseconds_value);
    ECMA_FINALIZE (milliseconds_value);
  }

  if (ecma_is_value_empty (ret_value))
  {
    if (!ecma_number_is_nan (year))
    {
      /* 8. */
      ecma_number_t y = ecma_number_trunc (year);

      if (y >= 0 && y <= 99)
      {
        year = 1900 + y;
      }
    }

    prim_value = ecma_date_make_date (ecma_date_make_day (year,
                                                          month,
                                                          date),
                                      ecma_date_make_time (hours,
                                                           minutes,
                                                           seconds,
                                                           milliseconds));
  }

  ECMA_FINALIZE (month_value);
  ECMA_FINALIZE (year_value);

  if (ecma_is_value_empty (ret_value))
  {
    ret_value = ecma_make_number_value (prim_value);
  }

  return ret_value;
} /* ecma_date_construct_helper */
示例#9
0
/**
 * Update the length of an array to a new length
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
extern ecma_value_t
ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */
                                 ecma_value_t new_value, /**< new length value */
                                 uint32_t flags) /**< configuration options */
{
  bool is_throw = (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW);

  ecma_value_t completion = ecma_op_to_number (new_value);

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

  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion)
                && ecma_is_value_number (completion));

  ecma_number_t new_len_num = ecma_get_number_from_value (completion);

  ecma_free_value (completion);

  if (ecma_is_value_object (new_value))
  {
    ecma_value_t compared_num_val = ecma_op_to_number (new_value);

    if (ECMA_IS_VALUE_ERROR (completion))
    {
      return compared_num_val;
    }

    new_len_num = ecma_get_number_from_value (compared_num_val);
    ecma_free_value (compared_num_val);
  }

  uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num);

  if (((ecma_number_t) new_len_uint32) != new_len_num)
  {
    return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length."));
  }

  if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT)
  {
    return ecma_reject (is_throw);
  }

  ecma_string_t magic_string_length;
  ecma_init_ecma_length_string (&magic_string_length);

  ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length);
  JERRY_ASSERT (len_prop_p != NULL
                && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);

  ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p);
  uint32_t old_len_uint32 = ecma_get_uint32_from_value (len_prop_value_p->value);

  if (new_len_num == old_len_uint32)
  {
    /* Only the writable flag must be updated. */
    if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED)
    {
      if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE))
      {
        ecma_set_property_writable_attr (len_prop_p, false);
      }
      else if (!ecma_is_property_writable (*len_prop_p))
      {
        return ecma_reject (is_throw);
      }
    }
    return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
  }
  else if (!ecma_is_property_writable (*len_prop_p))
  {
    return ecma_reject (is_throw);
  }

  uint32_t current_len_uint32 = new_len_uint32;

  if (new_len_uint32 < old_len_uint32)
  {
    current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32);
  }

  ecma_value_assign_uint32 (&len_prop_value_p->value, current_len_uint32);

  if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED)
      && !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE))
  {
    ecma_set_property_writable_attr (len_prop_p, false);
  }

  if (current_len_uint32 == new_len_uint32)
  {
    return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
  }
  return ecma_reject (is_throw);
} /* ecma_op_array_object_set_length */
示例#10
0
/**
 * ToNumber operation.
 *
 * See also:
 *          ECMA-262 v5, 9.3
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_to_number (ecma_value_t value) /**< ecma value */
{
  ecma_check_value_type_is_spec_defined (value);

  if (ecma_is_value_integer_number (value))
  {
    return value;
  }
  else if (ecma_is_value_float_number (value))
  {
    return ecma_copy_value (value);
  }
  else if (ecma_is_value_string (value))
  {
    ecma_string_t *str_p = ecma_get_string_from_value (value);
    return ecma_make_number_value (ecma_string_to_number (str_p));
  }
  else if (ecma_is_value_object (value))
  {
    ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

    ECMA_TRY_CATCH (primitive_value,
                    ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NUMBER),
                    ret_value);

    ret_value = ecma_op_to_number (primitive_value);

    ECMA_FINALIZE (primitive_value);

    return ret_value;
  }
  else
  {
    int16_t num = 0;

    if (ecma_is_value_undefined (value))
    {
      return ecma_make_nan_value ();
    }
    else if (ecma_is_value_null (value))
    {
      num = 0;
    }
    else
    {
      JERRY_ASSERT (ecma_is_value_boolean (value));

      if (ecma_is_value_true (value))
      {
        num = 1;
      }
      else
      {
        num = 0;
      }
    }

    return ecma_make_integer_value (num);
  }
} /* ecma_op_to_number */
/**
 * 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 */
示例#12
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 */
示例#13
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 */
示例#14
0
/**
 * ToNumber operation.
 *
 * See also:
 *          ECMA-262 v5, 9.3
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_to_number (ecma_value_t value) /**< ecma-value */
{
  ecma_check_value_type_is_spec_defined (value);

  if (ecma_is_value_number (value))
  {
    return ecma_make_normal_completion_value (ecma_copy_value (value, true));
  }
  else if (ecma_is_value_string (value))
  {
    ecma_string_t *str_p = ecma_get_string_from_value (value);

    ecma_number_t *num_p = ecma_alloc_number ();
    *num_p = ecma_string_to_number (str_p);

    return ecma_make_normal_completion_value (ecma_make_number_value (num_p));
  }
  else if (ecma_is_value_object (value))
  {
    ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

    ECMA_TRY_CATCH (primitive_value,
                    ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NUMBER),
                    ret_value);

    ret_value = ecma_op_to_number (primitive_value);

    ECMA_FINALIZE (primitive_value);

    return ret_value;
  }
  else
  {
    ecma_number_t *num_p = ecma_alloc_number ();

    if (ecma_is_value_undefined (value))
    {
      *num_p = ecma_number_make_nan ();
    }
    else if (ecma_is_value_null (value))
    {
      *num_p = ECMA_NUMBER_ZERO;
    }
    else
    {
      JERRY_ASSERT (ecma_is_value_boolean (value));

      if (ecma_is_value_true (value))
      {
        *num_p = ECMA_NUMBER_ONE;
      }
      else
      {
        *num_p = ECMA_NUMBER_ZERO;
      }
    }

    return ecma_make_normal_completion_value (ecma_make_number_value (num_p));
  }
} /* ecma_op_to_number */
/**
 * Dispatch set date functions
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_date_prototype_dispatch_set (uint16_t builtin_routine_id, /**< built-in wide routine
                                                                        *   identifier */
                                          ecma_extended_object_t *ext_object_p, /**< date extended object */
                                          ecma_number_t date_num, /**< date converted to number */
                                          const ecma_value_t arguments_list[], /**< list of arguments
                                                                                *   passed to routine */
                                          ecma_length_t arguments_number) /**< length of arguments' list */
{
  ecma_number_t converted_number[4];
  ecma_length_t conversions = 0;

  /* If the first argument is not specified, it is always converted to NaN. */
  converted_number[0] = ecma_number_make_nan ();

  switch (builtin_routine_id)
  {
#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
    case ECMA_DATE_PROTOTYPE_SET_YEAR:
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
    case ECMA_DATE_PROTOTYPE_SET_DATE:
    case ECMA_DATE_PROTOTYPE_SET_UTC_DATE:
    case ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS:
    case ECMA_DATE_PROTOTYPE_SET_MILLISECONDS:
    {
      conversions = 1;
      break;
    }
    case ECMA_DATE_PROTOTYPE_SET_MONTH:
    case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH:
    case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS:
    case ECMA_DATE_PROTOTYPE_SET_SECONDS:
    {
      conversions = 2;
      break;
    }
    case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR:
    case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR:
    case ECMA_DATE_PROTOTYPE_SET_MINUTES:
    case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES:
    {
      conversions = 3;
      break;
    }
    default:
    {
      JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_HOURS
                    || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_HOURS);
      conversions = 4;
      break;
    }
  }

  if (conversions > arguments_number)
  {
    conversions = arguments_number;
  }

  for (ecma_length_t i = 0; i < conversions; i++)
  {
    ecma_value_t value = ecma_op_to_number (arguments_list[i]);

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

    converted_number[i] = ecma_get_number_from_value (value);
    ecma_free_value (value);
  }

  ecma_number_t day_part;
  ecma_number_t time_part;

  if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_DATE)
  {
    if (ecma_number_is_nan (date_num))
    {
      if (ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE (builtin_routine_id))
      {
        date_num = ECMA_NUMBER_ZERO;
      }
      else
      {
        return ecma_make_number_value (date_num);
      }
    }

    time_part = ecma_date_time_within_day (date_num);

    ecma_number_t year = ecma_date_year_from_time (date_num);
    ecma_number_t month = ecma_date_month_from_time (date_num);
    ecma_number_t day = ecma_date_date_from_time (date_num);

    switch (builtin_routine_id)
    {
      case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR:
      case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR:
      {
        year = converted_number[0];
        if (conversions >= 2)
        {
          month = converted_number[1];
        }
        if (conversions >= 3)
        {
          day = converted_number[2];
        }
        break;
      }
#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
      case ECMA_DATE_PROTOTYPE_SET_YEAR:
      {
        year = converted_number[0];
        if (year >= 0 && year <= 99)
        {
          year += 1900;
        }
        break;
      }
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
      case ECMA_DATE_PROTOTYPE_SET_MONTH:
      case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH:
      {
        month = converted_number[0];
        if (conversions >= 2)
        {
          day = converted_number[1];
        }
        break;
      }
      default:
      {
        JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_DATE
                      || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_DATE);
        day = converted_number[0];
        break;
      }
    }

    day_part = ecma_date_make_day (year, month, day);

#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
    if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_YEAR)
    {
      builtin_routine_id = ECMA_DATE_PROTOTYPE_SET_UTC_YEAR;

      if (ecma_number_is_nan (converted_number[0]))
      {
        day_part = 0;
        time_part = converted_number[0];
      }
    }
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
  }
  else
  {
    if (ecma_number_is_nan (date_num))
    {
      return ecma_make_number_value (date_num);
    }

    day_part = ecma_date_day (date_num);

    ecma_number_t hour = ecma_date_hour_from_time (date_num);
    ecma_number_t min = ecma_date_min_from_time (date_num);
    ecma_number_t sec = ecma_date_sec_from_time (date_num);
    ecma_number_t ms = ecma_date_ms_from_time (date_num);

    switch (builtin_routine_id)
    {
      case ECMA_DATE_PROTOTYPE_SET_HOURS:
      case ECMA_DATE_PROTOTYPE_SET_UTC_HOURS:
      {
        hour = converted_number[0];
        if (conversions >= 2)
        {
          min = converted_number[1];
        }
        if (conversions >= 3)
        {
          sec = converted_number[2];
        }
        if (conversions >= 4)
        {
          ms = converted_number[3];
        }
        break;
      }
      case ECMA_DATE_PROTOTYPE_SET_MINUTES:
      case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES:
      {
        min = converted_number[0];
        if (conversions >= 2)
        {
          sec = converted_number[1];
        }
        if (conversions >= 3)
        {
          ms = converted_number[2];
        }
        break;
      }
      case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS:
      case ECMA_DATE_PROTOTYPE_SET_SECONDS:
      {
        sec = converted_number[0];
        if (conversions >= 2)
        {
          ms = converted_number[1];
        }
        break;
      }
      default:
      {
        JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS
                      || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_MILLISECONDS);
        ms = converted_number[0];
        break;
      }
    }

    time_part = ecma_date_make_time (hour, min, sec, ms);
  }

  bool is_utc = BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id);

  ecma_number_t full_date = ecma_date_make_date (day_part, time_part);

  if (!is_utc)
  {
    full_date = ecma_date_utc (full_date);
  }

  full_date = ecma_date_time_clip (full_date);

  *ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, ext_object_p->u.class_prop.u.value) = full_date;

  return ecma_make_number_value (full_date);
} /* ecma_builtin_date_prototype_dispatch_set */
示例#16
0
/**
 * [[DefineOwnProperty]] ecma array object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 15.4.5.1
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */
                                          ecma_string_t *property_name_p, /**< property name */
                                          const ecma_property_descriptor_t *property_desc_p, /**< property descriptor */
                                          bool is_throw) /**< flag that controls failure handling */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY);


  // 1.
  ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
  ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p);
  JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA);

  // 2.
  ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p);

  ecma_number_t *num_p = ecma_get_number_from_value (old_len_value);
  uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p);

  // 3.
  bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p,
                                                                  magic_string_length_p);

  ecma_deref_ecma_string (magic_string_length_p);

  if (is_property_name_equal_length)
  {
    // a.
    if (!property_desc_p->is_value_defined)
    {
      // i.
      return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw);
    }

    ecma_number_t new_len_num;

    // c.
    ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value);
    if (ecma_is_completion_value_throw (completion))
    {
      return completion;
    }

    JERRY_ASSERT (ecma_is_completion_value_normal (completion)
                  && ecma_is_value_number (ecma_get_completion_value_value (completion)));

    new_len_num = *ecma_get_number_from_completion_value (completion);

    ecma_free_completion_value (completion);

    uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num);

    // d.
    if (ecma_uint32_to_number (new_len_uint32) != new_len_num)
    {
      return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE));
    }
    else
    {
      // b., e.
      ecma_number_t *new_len_num_p = ecma_alloc_number ();
      *new_len_num_p = new_len_num;

      ecma_property_descriptor_t new_len_property_desc = *property_desc_p;
      new_len_property_desc.value = ecma_make_number_value (new_len_num_p);

      ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

      // f.
      if (new_len_uint32 >= old_len_uint32)
      {
        // i.
        magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
        ret_value = ecma_op_general_object_define_own_property (obj_p,
                                                                magic_string_length_p,
                                                                &new_len_property_desc,
                                                                is_throw);
        ecma_deref_ecma_string (magic_string_length_p);
      }
      else
      {
        // g.
        if (!ecma_is_property_writable (len_prop_p))
        {
          ret_value = ecma_reject (is_throw);
        }
        else
        {
          // h.
          bool new_writable;
          if (!new_len_property_desc.is_writable_defined
              || new_len_property_desc.is_writable)
          {
            new_writable = true;
          }
          else
          {
            // ii.
            new_writable = false;

            // iii.
            new_len_property_desc.is_writable_defined = true;
            new_len_property_desc.is_writable = true;
          }

          // j.
          magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
          ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p,
                                                                                          magic_string_length_p,
                                                                                          &new_len_property_desc,
                                                                                          is_throw);
          ecma_deref_ecma_string (magic_string_length_p);

          /* Handling normal false and throw values */
          if (!ecma_is_completion_value_normal_true (succeeded))
          {
            JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded)
                          || ecma_is_completion_value_throw (succeeded));

            // k.
            ret_value = succeeded;
          }
          else
          {
            // l
            JERRY_ASSERT (new_len_uint32 < old_len_uint32);

            /*
             * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated
             */
            bool is_reduce_succeeded = true;

            ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p,
                                                                                               true,
                                                                                               false,
                                                                                               false);

            ecma_length_t array_index_props_num = array_index_props_p->unit_number;

            MEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t);

            ecma_collection_iterator_t iter;
            ecma_collection_iterator_init (&iter, array_index_props_p);

            uint32_t array_index_values_pos = 0;

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

              uint32_t index;
              bool is_index = ecma_string_get_array_index (property_name_p, &index);
              JERRY_ASSERT (is_index);
              JERRY_ASSERT (index < old_len_uint32);

              array_index_values_p[array_index_values_pos++] = index;
            }

            JERRY_ASSERT (array_index_values_pos == array_index_props_num);

            while (array_index_values_pos != 0
                   && array_index_values_p[--array_index_values_pos] >= new_len_uint32)
            {
              uint32_t index = array_index_values_p[array_index_values_pos];

              // ii.
              ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
              ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p,
                                                                                index_string_p,
                                                                                false);
              ecma_deref_ecma_string (index_string_p);

              if (ecma_is_completion_value_normal_false (delete_succeeded))
              {
                // iii.
                new_len_uint32 = (index + 1u);

                ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value);

                // 1.
                *new_len_num_p = ecma_uint32_to_number (index + 1u);

                // 2.
                if (!new_writable)
                {
                  new_len_property_desc.is_writable_defined = true;
                  new_len_property_desc.is_writable = false;
                }

                // 3.
                ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p,
                                                                                                 magic_string_length_p,
                                                                                                 &new_len_property_desc,
                                                                                                 false);
                ecma_deref_ecma_string (magic_string_length_p);

                JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
                              || ecma_is_completion_value_normal_false (completion));

                is_reduce_succeeded = false;

                break;
              }
            }

            MEM_FINALIZE_LOCAL_ARRAY (array_index_values_p);

            ecma_free_values_collection (array_index_props_p, true);

            if (!is_reduce_succeeded)
            {
              ret_value = ecma_reject (is_throw);
            }
            else
            {
              // m.
              if (!new_writable)
              {
                ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor ();

                prop_desc_not_writable.is_writable_defined = true;
                prop_desc_not_writable.is_writable = false;

                ecma_completion_value_t completion_set_not_writable;
                magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p,
                                                                                          magic_string_length_p,
                                                                                          &prop_desc_not_writable,
                                                                                          false);
                ecma_deref_ecma_string (magic_string_length_p);
                JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable));
              }

              ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
            }
          }
        }
      }

      ecma_dealloc_number (new_len_num_p);

      return ret_value;
    }

    JERRY_UNREACHABLE ();
  }
  else
  {
    // 4.a.
    uint32_t index;

    if (!ecma_string_get_array_index (property_name_p, &index))
    {
      // 5.
      return ecma_op_general_object_define_own_property (obj_p,
                                                         property_name_p,
                                                         property_desc_p,
                                                         is_throw);
    }

    // 4.

    // b.
    if (index >= old_len_uint32
        && !ecma_is_property_writable (len_prop_p))
    {
      return ecma_reject (is_throw);
    }

    // c.
    ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p,
                                                                                    property_name_p,
                                                                                    property_desc_p,
                                                                                    false);
    // d.
    JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded)
                  || ecma_is_completion_value_normal_false (succeeded));

    if (ecma_is_completion_value_normal_false (succeeded))
    {
      return ecma_reject (is_throw);
    }

    // e.
    if (index >= old_len_uint32)
    {
      // i., ii.
      ecma_number_t *num_p = ecma_alloc_number ();
      *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE);

      ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p));

      ecma_dealloc_number (num_p);
    }

    // f.
    return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  JERRY_UNREACHABLE ();
} /* ecma_op_array_object_define_own_property */
示例#17
0
/**
 * [[DefineOwnProperty]] ecma array object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 15.4.5.1
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */
        ecma_string_t *property_name_p, /**< property name */
        const ecma_property_descriptor_t* property_desc_p, /**< property descriptor */
        bool is_throw) /**< flag that controls failure handling */
{
    JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY);


    // 1.
    ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
    ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p);
    JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA);

    // 2.
    ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p);

    ecma_number_t *num_p = ecma_get_number_from_value (old_len_value);
    uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p);

    // 3.
    bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p,
                                         magic_string_length_p);

    ecma_deref_ecma_string (magic_string_length_p);

    if (is_property_name_equal_length)
    {
        // a.
        if (!property_desc_p->is_value_defined)
        {
            // i.
            return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw);
        }

        ecma_number_t new_len_num;

        // c.
        ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value);
        if (ecma_is_completion_value_throw (completion))
        {
            return completion;
        }

        JERRY_ASSERT (ecma_is_completion_value_normal (completion)
                      && ecma_is_value_number (ecma_get_completion_value_value (completion)));

        new_len_num = *ecma_get_number_from_completion_value (completion);

        ecma_free_completion_value (completion);

        uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num);

        // d.
        if (ecma_uint32_to_number (new_len_uint32) != new_len_num)
        {
            return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE));
        }
        else
        {
            // b., e.
            ecma_number_t *new_len_num_p = ecma_alloc_number ();
            *new_len_num_p = new_len_num;

            ecma_property_descriptor_t new_len_property_desc = *property_desc_p;
            new_len_property_desc.value = ecma_make_number_value (new_len_num_p);

            ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

            // f.
            if (new_len_uint32 >= old_len_uint32)
            {
                // i.
                magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                ret_value = ecma_op_general_object_define_own_property (obj_p,
                            magic_string_length_p,
                            &new_len_property_desc,
                            is_throw);
                ecma_deref_ecma_string (magic_string_length_p);
            }
            else
            {
                // g.
                if (!ecma_is_property_writable (len_prop_p))
                {
                    ret_value = ecma_reject (is_throw);
                }
                else
                {
                    // h.
                    bool new_writable;
                    if (!new_len_property_desc.is_writable_defined
                            || new_len_property_desc.is_writable)
                    {
                        new_writable = true;
                    }
                    else
                    {
                        // ii.
                        new_writable = false;

                        // iii.
                        new_len_property_desc.is_writable_defined = true;
                        new_len_property_desc.is_writable = true;
                    }

                    // j.
                    magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                    ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p,
                                                        magic_string_length_p,
                                                        &new_len_property_desc,
                                                        is_throw);
                    ecma_deref_ecma_string (magic_string_length_p);

                    /* Handling normal false and throw values */
                    if (!ecma_is_completion_value_normal_true (succeeded))
                    {
                        JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded)
                                      || ecma_is_completion_value_throw (succeeded));

                        // k.
                        ret_value = succeeded;
                    }
                    else
                    {
                        // l
                        JERRY_ASSERT (new_len_uint32 < old_len_uint32);

                        bool reduce_succeeded = true;

                        while (new_len_uint32 < old_len_uint32)
                        {
                            // i
                            old_len_uint32--;

                            // ii
                            ecma_string_t *old_length_string_p = ecma_new_ecma_string_from_uint32 (old_len_uint32);
                            ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p,
                                    old_length_string_p,
                                    false);
                            ecma_deref_ecma_string (old_length_string_p);

                            // iii
                            if (ecma_is_completion_value_normal_false (delete_succeeded))
                            {
                                JERRY_ASSERT (ecma_is_value_number (new_len_property_desc.value));

                                ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value);

                                // 1.
                                *new_len_num_p = ecma_uint32_to_number (old_len_uint32 + 1);

                                // 2.
                                if (!new_writable)
                                {
                                    new_len_property_desc.is_writable_defined = true;
                                    new_len_property_desc.is_writable = false;
                                }

                                // 3.
                                ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                                ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p,
                                                                     magic_string_length_p,
                                                                     &new_len_property_desc,
                                                                     false);
                                ecma_deref_ecma_string (magic_string_length_p);

                                JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
                                              || ecma_is_completion_value_normal_false (completion));

                                reduce_succeeded = false;

                                break;
                            }
                        }

                        if (!reduce_succeeded)
                        {
                            ret_value = ecma_reject (is_throw);
                        }
                        else
                        {
                            // m.
                            if (!new_writable)
                            {
                                ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor ();

                                prop_desc_not_writable.is_writable_defined = true;
                                prop_desc_not_writable.is_writable = false;

                                ecma_completion_value_t completion_set_not_writable;
                                magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
                                completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p,
                                                              magic_string_length_p,
                                                              &prop_desc_not_writable,
                                                              false);
                                ecma_deref_ecma_string (magic_string_length_p);
                                JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable));
                            }

                            ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
                        }
                    }
                }
            }

            ecma_dealloc_number (new_len_num_p);

            return ret_value;
        }

        JERRY_UNREACHABLE ();
    }
    else
    {
        // 4.a.
        uint32_t index;

        if (!ecma_string_get_array_index (property_name_p, &index))
        {
            // 5.
            return ecma_op_general_object_define_own_property (obj_p,
                    property_name_p,
                    property_desc_p,
                    is_throw);
        }

        // 4.

        // b.
        if (index >= old_len_uint32
                && !ecma_is_property_writable (len_prop_p))
        {
            return ecma_reject (is_throw);
        }

        // c.
        ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p,
                                            property_name_p,
                                            property_desc_p,
                                            false);
        // d.
        JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded)
                      || ecma_is_completion_value_normal_false (succeeded));

        if (ecma_is_completion_value_normal_false (succeeded))
        {
            return ecma_reject (is_throw);
        }

        // e.
        if (index >= old_len_uint32)
        {
            // i., ii.
            ecma_number_t *num_p = ecma_alloc_number ();
            *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE);

            ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p));

            ecma_dealloc_number (num_p);
        }

        // f.
        return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
    }

    JERRY_UNREACHABLE ();
} /* ecma_op_array_object_define_own_property */