Esempio n. 1
0
/**
 * Handle calling [[Construct]] of built-in Number object
 *
 * @return ecma value
 */
ecma_value_t
ecma_builtin_number_dispatch_construct (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);

  if (arguments_list_len == 0)
  {
    ecma_value_t completion = ecma_op_create_number_object (ecma_make_integer_value (0));
    return completion;
  }
  else
  {
    return ecma_op_create_number_object (arguments_list_p[0]);
  }
} /* ecma_builtin_number_dispatch_construct */
Esempio n. 2
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 */
Esempio n. 3
0
/**
 * ToBoolean operation. Cannot throw an exception.
 *
 * See also:
 *          ECMA-262 v5, 9.2
 *
 * @return true if the logical value is true
 *         false otherwise
 */
bool
ecma_op_to_boolean (ecma_value_t value) /**< ecma value */
{
  ecma_check_value_type_is_spec_defined (value);

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

    return ecma_is_value_true (value);
  }

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

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

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

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

    return ecma_string_get_length (str_p) != 0;
  }

  JERRY_ASSERT (ecma_is_value_object (value));

  return true;
} /* ecma_op_to_boolean */
Esempio n. 4
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 */
Esempio n. 5
0
/**
 * ECMA strict equality comparison routine.
 *
 * See also: ECMA-262 v5, 11.9.6
 *
 * @return true - if values are strict equal,
 *         false - otherwise
 */
bool
ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */
                                 ecma_value_t y) /**< second operand */
{
  if (ecma_is_value_direct (x)
      || ecma_is_value_direct (y)
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
      || ecma_is_value_symbol (x)
      || ecma_is_value_symbol (y)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
      || ecma_is_value_object (x)
      || ecma_is_value_object (y))
  {
    JERRY_ASSERT (!ecma_is_value_direct (x)
                  || ecma_is_value_undefined (x)
                  || ecma_is_value_null (x)
                  || ecma_is_value_boolean (x)
                  || ecma_is_value_integer_number (x));

    JERRY_ASSERT (!ecma_is_value_direct (y)
                  || ecma_is_value_undefined (y)
                  || ecma_is_value_null (y)
                  || ecma_is_value_boolean (y)
                  || ecma_is_value_integer_number (y));

    if ((x != ecma_make_integer_value (0) || !ecma_is_value_float_number (y))
        && (y != ecma_make_integer_value (0) || !ecma_is_value_float_number (x)))
    {
      return (x == y);
    }

    /* The +0 === -0 case handled below. */
  }

  JERRY_ASSERT (ecma_is_value_number (x) || ecma_is_value_string (x));
  JERRY_ASSERT (ecma_is_value_number (y) || ecma_is_value_string (y));

  if (ecma_is_value_string (x))
  {
    if (!ecma_is_value_string (y))
    {
      return false;
    }

    ecma_string_t *x_str_p = ecma_get_string_from_value (x);
    ecma_string_t *y_str_p = ecma_get_string_from_value (y);

    return ecma_compare_ecma_strings (x_str_p, y_str_p);
  }

  if (!ecma_is_value_number (y))
  {
    return false;
  }

  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 is_x_equal_to_y;
} /* ecma_op_strict_equality_compare */
Esempio n. 6
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 */
Esempio n. 7
0
/**
 * If the property's name is one of built-in properties of the object
 * that is not instantiated yet, instantiate the property and
 * return pointer to the instantiated property.
 *
 * @return pointer property, if one was instantiated,
 *         NULL - otherwise.
 */
ecma_property_t *
ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */
                                          ecma_string_t *string_p) /**< property's name */
{
  JERRY_ASSERT (ecma_get_object_is_builtin (object_p));

  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;

  if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION
      && ecma_builtin_function_is_routine (object_p))
  {
    if (ecma_string_is_length (string_p))
    {
      /*
       * Lazy instantiation of 'length' property
       *
       * Note:
       *      We don't need to mark that the property was already lazy instantiated,
       *      as it is non-configurable and so can't be deleted
       */

      ecma_property_t *len_prop_p = ecma_create_named_data_property (object_p,
                                                                     string_p,
                                                                     ECMA_PROPERTY_FIXED);

      ecma_set_named_data_property_value (len_prop_p,
                                          ecma_make_integer_value (ext_obj_p->u.built_in.length));

      JERRY_ASSERT (!ecma_is_property_configurable (len_prop_p));
      return len_prop_p;
    }

    return NULL;
  }

  lit_magic_string_id_t magic_string_id;

  if (!ecma_is_string_magic (string_p, &magic_string_id))
  {
    return NULL;
  }

  ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) ext_obj_p->u.built_in.id;

  JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
  JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));

  const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id];

  const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p;

  while (curr_property_p->magic_string_id != magic_string_id)
  {
    if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT)
    {
      return NULL;
    }
    curr_property_p++;
  }

  uint32_t index = (uint32_t) (curr_property_p - property_list_p);

  JERRY_ASSERT (index < 64);

  if (likely (index < 32))
  {
    uint32_t bit_for_index = (uint32_t) 1u << index;

    if (ext_obj_p->u.built_in.instantiated_bitset & bit_for_index)
    {
      /* This property was instantiated before. */
      return NULL;
    }

    ext_obj_p->u.built_in.instantiated_bitset |= bit_for_index;
  }
  else
  {
    uint32_t bit_for_index = (uint32_t) 1u << (index - 32);
    ecma_value_t *mask_prop_p = ecma_find_internal_property (object_p,
                                                             ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63);

    uint32_t instantiated_bitset;

    if (mask_prop_p == NULL)
    {
      mask_prop_p = ecma_create_internal_property (object_p, ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63);
      instantiated_bitset = 0;
    }
    else
    {
      instantiated_bitset = *mask_prop_p;

      if (instantiated_bitset & bit_for_index)
      {
        /* This property was instantiated before. */
        return NULL;
      }
    }

    *mask_prop_p = (instantiated_bitset | bit_for_index);
  }

  ecma_value_t value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  switch (curr_property_p->type)
  {
    case ECMA_BUILTIN_PROPERTY_SIMPLE:
    {
      value = ecma_make_simple_value (curr_property_p->value);
      break;
    }
    case ECMA_BUILTIN_PROPERTY_NUMBER:
    {
      ecma_number_t num = 0.0;

      if (curr_property_p->value < ECMA_BUILTIN_NUMBER_MAX)
      {
        num = curr_property_p->value;
      }
      else if (curr_property_p->value < ECMA_BUILTIN_NUMBER_NAN)
      {
        static const ecma_number_t builtin_number_list[] =
        {
          ECMA_NUMBER_MAX_VALUE,
          ECMA_NUMBER_MIN_VALUE,
          ECMA_NUMBER_E,
          ECMA_NUMBER_PI,
          ECMA_NUMBER_LN10,
          ECMA_NUMBER_LN2,
          ECMA_NUMBER_LOG2E,
          ECMA_NUMBER_LOG10E,
          ECMA_NUMBER_SQRT2,
          ECMA_NUMBER_SQRT_1_2
        };

        num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX];
      }
      else
      {
        switch (curr_property_p->value)
        {
          case ECMA_BUILTIN_NUMBER_NAN:
          {
            num = ecma_number_make_nan ();
            break;
          }
          case ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY:
          {
            num = ecma_number_make_infinity (false);
            break;
          }
          case ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY:
          {
            num = ecma_number_make_infinity (true);
            break;
          }
          default:
          {
            JERRY_UNREACHABLE ();
            break;
          }
        }
      }

      value = ecma_make_number_value (num);
      break;
    }
    case ECMA_BUILTIN_PROPERTY_STRING:
    {
      value = ecma_make_string_value (ecma_get_magic_string (curr_property_p->value));
      break;
    }
    case ECMA_BUILTIN_PROPERTY_OBJECT:
    {
      value = ecma_make_object_value (ecma_builtin_get (curr_property_p->value));
      break;
    }
    case ECMA_BUILTIN_PROPERTY_ROUTINE:
    {
      ecma_object_t *func_obj_p;
      func_obj_p = ecma_builtin_make_function_object_for_routine (builtin_id,
                                                                  ECMA_GET_ROUTINE_ID (curr_property_p->value),
                                                                  ECMA_GET_ROUTINE_LENGTH (curr_property_p->value));
      value = ecma_make_object_value (func_obj_p);
      break;
    }
    default:
    {
      JERRY_UNREACHABLE ();
      return NULL;
    }
  }

  ecma_property_t *prop_p = ecma_create_named_data_property (object_p,
                                                             string_p,
                                                             curr_property_p->attributes);

  ecma_set_named_data_property_value (prop_p, value);

  /* Reference count of objects must be decreased. */
  if (ecma_is_value_object (value))
  {
    ecma_free_value (value);
  }

  return prop_p;
} /* ecma_builtin_try_to_instantiate_property */
Esempio n. 8
0
/**
 * Initialize specified built-in object.
 *
 * @return pointer to the object
 */
static ecma_object_t *
ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */
                          ecma_object_t *prototype_obj_p, /**< prototype object */
                          ecma_object_type_t obj_type, /**< object's type */
                          bool is_extensible) /**< value of object's [[Extensible]] property */
{
  ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, true, is_extensible, obj_type);

  /*
   * [[Class]] property of built-in object is not stored explicitly.
   *
   * See also: ecma_object_get_class_name
   */

  ecma_set_object_is_builtin (obj_p);

  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
  ext_obj_p->u.built_in.id = obj_builtin_id;
  ext_obj_p->u.built_in.routine_id = obj_builtin_id;
  ext_obj_p->u.built_in.instantiated_bitset = 0;

  /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */
  switch (obj_builtin_id)
  {
#ifndef CONFIG_DISABLE_ARRAY_BUILTIN
    case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE:
    {
      ecma_string_t *length_str_p = ecma_new_ecma_length_string ();

      ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p,
                                                                        length_str_p,
                                                                        ECMA_PROPERTY_FLAG_WRITABLE);

      ecma_set_named_data_property_value (length_prop_p, ecma_make_integer_value (0));

      ecma_deref_ecma_string (length_str_p);
      break;
    }
#endif /* !CONFIG_DISABLE_ARRAY_BUILTIN */

#ifndef CONFIG_DISABLE_STRING_BUILTIN
    case ECMA_BUILTIN_ID_STRING_PROTOTYPE:
    {
      ecma_string_t *prim_prop_str_value_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);

      ecma_value_t *prim_value_p = ecma_create_internal_property (obj_p,
                                                                  ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
      *prim_value_p = ecma_make_string_value (prim_prop_str_value_p);
      break;
    }
#endif /* !CONFIG_DISABLE_STRING_BUILTIN */

#ifndef CONFIG_DISABLE_NUMBER_BUILTIN
    case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE:
    {
      ecma_value_t *prim_value_p = ecma_create_internal_property (obj_p,
                                                                  ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
      *prim_value_p = ecma_make_integer_value (0);
      break;
    }
#endif /* !CONFIG_DISABLE_NUMBER_BUILTIN */

#ifndef CONFIG_DISABLE_BOOLEAN_BUILTIN
    case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE:
    {
      ecma_value_t *prim_value_p = ecma_create_internal_property (obj_p,
                                                                  ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
      *prim_value_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
      break;
    }
#endif /* !CONFIG_DISABLE_BOOLEAN_BUILTIN */

#ifndef CONFIG_DISABLE_DATE_BUILTIN
    case ECMA_BUILTIN_ID_DATE_PROTOTYPE:
    {
      ecma_number_t *prim_prop_num_value_p = ecma_alloc_number ();
      *prim_prop_num_value_p = ecma_number_make_nan ();

      ecma_value_t *prim_value_p = ecma_create_internal_property (obj_p,
                                                                  ECMA_INTERNAL_PROPERTY_DATE_FLOAT);
      ECMA_SET_INTERNAL_VALUE_POINTER (*prim_value_p, prim_prop_num_value_p);
      break;
    }
#endif /* !CONFIG_DISABLE_DATE_BUILTIN */

#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
    case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE:
    {
      ecma_value_t *bytecode_prop_p = ecma_create_internal_property (obj_p,
                                                                     ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE);
      *bytecode_prop_p = ECMA_NULL_POINTER;
      break;
    }
#endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */
    default:
    {
      break;
    }
  }

  return obj_p;
} /* ecma_builtin_init_object */
/**
 * 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_VALUE_EMPTY;

  /* 2. */
  if (!ecma_op_is_callable (this_arg))
  {
    ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function."));
  }
  else
  {
    /* 4. 11. 18. */
    ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);

    ecma_length_t args_length = arguments_number;
    ecma_object_t *function_p;
    ecma_extended_object_t *ext_function_p;

    if (arguments_number == 0
        || (arguments_number == 1 && !ecma_is_value_integer_number (arguments_list_p[0])))
    {
      args_length = 1;

      function_p = ecma_create_object (prototype_obj_p,
                                       sizeof (ecma_extended_object_t),
                                       ECMA_OBJECT_TYPE_BOUND_FUNCTION);

      /* 8. */
      ext_function_p = (ecma_extended_object_t *) function_p;
      ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg);
      ECMA_SET_INTERNAL_VALUE_POINTER (ext_function_p->u.bound_function.target_function,
                                       this_arg_obj_p);

      ext_function_p->u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED;

      if (arguments_number != 0)
      {
        ext_function_p->u.bound_function.args_len_or_this = ecma_copy_value_if_not_object (arguments_list_p[0]);
      }
    }
    else
    {
      JERRY_ASSERT (arguments_number > 0);

      size_t obj_size = sizeof (ecma_extended_object_t) + (args_length * sizeof (ecma_value_t));

      function_p = ecma_create_object (prototype_obj_p,
                                       obj_size,
                                       ECMA_OBJECT_TYPE_BOUND_FUNCTION);

      /* 8. */
      ext_function_p = (ecma_extended_object_t *) function_p;
      ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg);
      ECMA_SET_INTERNAL_VALUE_POINTER (ext_function_p->u.bound_function.target_function,
                                       this_arg_obj_p);

      /* NOTE: This solution provides temporary false data about the object's size
         but prevents GC from freeing it until it's not fully initialized. */
      ext_function_p->u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED;
      ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);

      for (ecma_length_t i = 0; i < arguments_number; i++)
      {
        *args_p++ = ecma_copy_value_if_not_object (arguments_list_p[i]);
      }

      ecma_value_t args_len_or_this = ecma_make_integer_value ((ecma_integer_value_t) args_length);
      ext_function_p->u.bound_function.args_len_or_this = args_len_or_this;
    }

    ecma_deref_object (prototype_obj_p);

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

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

  return ret_value;
} /* ecma_builtin_function_prototype_object_bind */