Esempio n. 1
0
/**
 * Handle calling [[Construct]] of built-in object
 *
 * @return ecma value
 */
ecma_value_t
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */
                                 const ecma_value_t *arguments_list_p, /**< arguments list */
                                 ecma_length_t arguments_list_len) /**< arguments list length */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
  JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p,
                                                                    ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
  ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

  JERRY_ASSERT (ecma_builtin_is (obj_p, builtin_id));

  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
  switch (builtin_id)
  {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
    case builtin_id: \
      { \
        if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \
        { \
          ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_construct (arguments_list_p, \
                                                                              arguments_list_len); \
        } \
        break; \
      }
#include "ecma-builtins.inc.h"

    case ECMA_BUILTIN_ID__COUNT:
    {
      JERRY_UNREACHABLE ();
    }

    default:
    {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
      JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
      JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
    }
  }

  JERRY_ASSERT (!ecma_is_value_empty (ret_value));

  return ret_value;
} /* ecma_builtin_dispatch_construct */
Esempio n. 2
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_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p,
                                                                    ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
  ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

  JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));

  switch (builtin_id)
  {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
    case builtin_id: \
    { \
      return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \
                                                                              string_p); \
    }
#include "ecma-builtins.inc.h"

    case ECMA_BUILTIN_ID__COUNT:
    {
      JERRY_UNREACHABLE ();
    }

    default:
    {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
      JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
      JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
    }
  }

  JERRY_UNREACHABLE ();
} /* ecma_builtin_try_to_instantiate_property */
Esempio n. 3
0
/**
 * Get [[Class]] string of specified object
 *
 * @return class name magic string
 */
lit_magic_string_id_t
ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
{
  ecma_object_type_t type = ecma_get_object_type (obj_p);

  switch (type)
  {
    case ECMA_OBJECT_TYPE_ARRAY:
    {
      return LIT_MAGIC_STRING_ARRAY_UL;
    }
    case ECMA_OBJECT_TYPE_STRING:
    {
      return LIT_MAGIC_STRING_STRING_UL;
    }
    case ECMA_OBJECT_TYPE_ARGUMENTS:
    {
      return LIT_MAGIC_STRING_ARGUMENTS_UL;
    }
    case ECMA_OBJECT_TYPE_FUNCTION:
    case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
    case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
    case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION:
    {
      return LIT_MAGIC_STRING_FUNCTION_UL;
    }
    default:
    {
      JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL);

      if (ecma_get_object_is_builtin (obj_p))
      {
        ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p,
                                                                          ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
        ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

        switch (builtin_id)
        {
          case ECMA_BUILTIN_ID_OBJECT_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_OBJECT_UL;
          }
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN
          case ECMA_BUILTIN_ID_STRING_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_STRING_UL;
          }
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN
          case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_BOOLEAN_UL;
          }
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN
          case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_NUMBER_UL;
          }
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN
          case ECMA_BUILTIN_ID_MATH:
          {
            return LIT_MAGIC_STRING_MATH_UL;
          }
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_MATH_BUILTIN */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_JSON_BUILTIN
          case ECMA_BUILTIN_ID_JSON:
          {
            return LIT_MAGIC_STRING_JSON_U;
          }
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_JSON_BUILTIN */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS
          case ECMA_BUILTIN_ID_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE:
          case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_ERROR_UL;
          }
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN
          case ECMA_BUILTIN_ID_DATE_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_DATE_UL;
          }
#endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN
          case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE:
          {
            return LIT_MAGIC_STRING_REGEXP_UL;
          }
#endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */
          default:
          {
            JERRY_ASSERT (ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_GLOBAL));

            return LIT_MAGIC_STRING_OBJECT_UL;
          }
        }
      }
      else
      {
        ecma_property_t *class_name_prop_p = ecma_find_internal_property (obj_p,
                                                                          ECMA_INTERNAL_PROPERTY_CLASS);

        if (class_name_prop_p == NULL)
        {
          return LIT_MAGIC_STRING_OBJECT_UL;
        }
        else
        {
          return (lit_magic_string_id_t) class_name_prop_p->u.internal_property.value;
        }
      }
    }
  }
} /* ecma_object_get_class_name */
Esempio n. 4
0
/**
 * Handle calling [[Call]] of built-in object
 *
 * @return ecma value
 */
ecma_value_t
ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */
                            ecma_value_t this_arg_value, /**< 'this' argument value */
                            const ecma_value_t *arguments_list_p, /**< arguments list */
                            ecma_length_t arguments_list_len) /**< arguments list length */
{
  JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
  {
    ecma_property_t *desc_prop_p = ecma_get_internal_property (obj_p,
                                                               ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC);
    uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value;

    uint64_t built_in_id_field = jrt_extract_bit_field (builtin_routine_desc,
                                                        ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS,
                                                        ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH);
    JERRY_ASSERT (built_in_id_field < ECMA_BUILTIN_ID__COUNT);

    uint64_t routine_id_field = jrt_extract_bit_field (builtin_routine_desc,
                                                       ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS,
                                                       ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH);
    JERRY_ASSERT ((uint16_t) routine_id_field == routine_id_field);

    ecma_builtin_id_t built_in_id = (ecma_builtin_id_t) built_in_id_field;
    uint16_t routine_id = (uint16_t) routine_id_field;

    ret_value =  ecma_builtin_dispatch_routine (built_in_id,
                                                routine_id,
                                                this_arg_value,
                                                arguments_list_p,
                                                arguments_list_len);
  }
  else
  {
    JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);

    ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p,
                                                                      ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
    ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

    JERRY_ASSERT (ecma_builtin_is (obj_p, builtin_id));

    switch (builtin_id)
    {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
      case builtin_id: \
      { \
        if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \
        { \
          ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_call (arguments_list_p, \
                                                                         arguments_list_len); \
        } \
        break; \
      }
#include "ecma-builtins.inc.h"

      case ECMA_BUILTIN_ID__COUNT:
      {
        JERRY_UNREACHABLE ();
      }

      default:
      {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
        JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
        JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
      }
    }
  }

  JERRY_ASSERT (!ecma_is_value_empty (ret_value));

  return ret_value;
} /* ecma_builtin_dispatch_call */
Esempio n. 5
0
/**
 * List names of a built-in object's lazy instantiated properties
 *
 * See also:
 *          ecma_builtin_try_to_instantiate_property
 */
void
ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */
                                       bool separate_enumerable, /**< true -  list enumerable properties into
                                                                  *           main collection, and non-enumerable
                                                                  *           to collection of 'skipped non-enumerable'
                                                                  *           properties,
                                                                  *   false - list all properties into main collection.
                                                                  */
                                       ecma_collection_header_t *main_collection_p, /**< 'main' collection */
                                       ecma_collection_header_t *non_enum_collection_p) /**< skipped 'non-enumerable'
                                                                                         *   collection */
{
  const ecma_object_type_t type = ecma_get_object_type (object_p);

  if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
  {
    ecma_collection_header_t *for_enumerable_p = main_collection_p;
    (void) for_enumerable_p;

    ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;

    /* 'length' property is non-enumerable (ECMA-262 v5, 15) */
    ecma_string_t *name_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
    ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
    ecma_deref_ecma_string (name_p);
  }
  else
  {
    ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p,
                                                                      ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
    ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

    JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));

    switch (builtin_id)
    {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
      case builtin_id: \
                       { \
                         ecma_builtin_ ## lowercase_name ## _list_lazy_property_names (object_p, \
                                                                                       separate_enumerable, \
                                                                                       main_collection_p, \
                                                                                       non_enum_collection_p); \
                         return; \
                       }
#include "ecma-builtins.inc.h"

      case ECMA_BUILTIN_ID__COUNT:
      {
        JERRY_UNREACHABLE ();
      }

      default:
      {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
        JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
        JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
      }
    }

    JERRY_UNREACHABLE ();
  }
} /* ecma_builtin_list_lazy_property_names */
Esempio n. 6
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));

  const ecma_object_type_t type = ecma_get_object_type (object_p);

  if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
  {
    ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);

    bool is_length_property = ecma_compare_ecma_strings (string_p, magic_string_length_p);

    ecma_deref_ecma_string (magic_string_length_p);

    if (is_length_property)
    {
      /*
       * 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 *desc_prop_p = ecma_get_internal_property (object_p,
                                                               ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC);
      uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value;

      JERRY_STATIC_ASSERT (sizeof (uint8_t) * JERRY_BITSINBYTE == ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH,
                           bits_in_uint8_t_must_be_equal_to_ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);
      uint8_t length_prop_value = (uint8_t) jrt_extract_bit_field (builtin_routine_desc,
                                                                   ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_POS,
                                                                   ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);

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


      ecma_number_t *len_p = ecma_alloc_number ();
      *len_p = length_prop_value;

      ecma_set_named_data_property_value (len_prop_p, ecma_make_number_value (len_p));

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

    return NULL;
  }
  else
  {
    ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p,
                                                                      ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
    ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

    JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));

    switch (builtin_id)
    {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
      case builtin_id: \
      { \
        return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \
                                                                                string_p); \
      }
#include "ecma-builtins.inc.h"

      case ECMA_BUILTIN_ID__COUNT:
      {
        JERRY_UNREACHABLE ();
      }

      default:
      {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
        JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
        JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
      }
    }

    JERRY_UNREACHABLE ();
  }
} /* ecma_builtin_try_to_instantiate_property */
Esempio n. 7
0
/**
 * List names of a built-in object's lazy instantiated properties
 *
 * See also:
 *          ecma_builtin_try_to_instantiate_property
 */
void
ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */
                                       bool separate_enumerable, /**< true -  list enumerable properties into
                                                                  *           main collection, and non-enumerable
                                                                  *           to collection of 'skipped non-enumerable'
                                                                  *           properties,
                                                                  *   false - list all properties into main collection.
                                                                  */
                                       ecma_collection_header_t *main_collection_p, /**< 'main' collection */
                                       ecma_collection_header_t *non_enum_collection_p) /**< skipped 'non-enumerable'
                                                                                         *   collection */
{
  JERRY_ASSERT (ecma_get_object_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))
  {
    ecma_collection_header_t *for_enumerable_p = main_collection_p;
    JERRY_UNUSED (for_enumerable_p);

    ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;

    /* 'length' property is non-enumerable (ECMA-262 v5, 15) */
    ecma_string_t *name_p = ecma_new_ecma_length_string ();
    ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
    ecma_deref_ecma_string (name_p);
  }
  else
  {
    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 *curr_property_p = ecma_builtin_property_list_references[builtin_id];

    ecma_length_t index = 0;
    uint32_t instantiated_bitset = ext_obj_p->u.built_in.instantiated_bitset;

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

    while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
    {
      JERRY_ASSERT (index < 64);

      if (index == 32)
      {
        ecma_value_t *mask_prop_p = ecma_find_internal_property (object_p,
                                                                 ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63);

        if (mask_prop_p == NULL)
        {
          instantiated_bitset = 0;
        }
        else
        {
          instantiated_bitset = *mask_prop_p;
        }
      }

      uint32_t bit_for_index;
      if (index >= 32)
      {
        bit_for_index = (uint32_t) 1u << (index - 32);
      }
      else
      {
        bit_for_index = (uint32_t) 1u << index;
      }

      bool was_instantiated = false;

      if (instantiated_bitset & bit_for_index)
      {
        was_instantiated = true;
      }

      ecma_string_t *name_p = ecma_get_magic_string (curr_property_p->magic_string_id);

      if (!was_instantiated || ecma_op_object_has_own_property (object_p, name_p))
      {
        ecma_append_to_values_collection (for_non_enumerable_p,
                                          ecma_make_string_value (name_p),
                                          true);
      }

      ecma_deref_ecma_string (name_p);

      curr_property_p++;
      index++;
    }
  }
} /* ecma_builtin_list_lazy_property_names */
Esempio n. 8
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. 9
0
/**
 * Handle calling [[Construct]] of built-in object
 *
 * @return completion-value
 */
ecma_completion_value_t
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */
                                 ecma_collection_header_t* arg_collection_p) /**< arguments collection */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
  JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));

  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  const ecma_length_t arguments_list_len = arg_collection_p != NULL ? arg_collection_p->unit_number : 0;
  MEM_DEFINE_LOCAL_ARRAY (arguments_list_p, arguments_list_len, ecma_value_t);

  ecma_collection_iterator_t arg_collection_iter;
  ecma_collection_iterator_init (&arg_collection_iter,
                                 arg_collection_p);

  for (ecma_length_t arg_index = 0;
       ecma_collection_iterator_next (&arg_collection_iter);
       arg_index++)
  {
    arguments_list_p[arg_index] = *arg_collection_iter.current_value_p;
  }

  ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_p,
                                                                    ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
  ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

  JERRY_ASSERT (ecma_builtin_is (obj_p, builtin_id));

  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
  switch (builtin_id)
  {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
    case builtin_id: \
      { \
        if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \
        { \
          ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_construct (arguments_list_p, \
                                                                              arguments_list_len); \
        } \
        break; \
      }
#include "ecma-builtins.inc.h"

    case ECMA_BUILTIN_ID__COUNT:
    {
      JERRY_UNREACHABLE ();
    }

    default:
    {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
      JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
      JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
    }
  }

  MEM_FINALIZE_LOCAL_ARRAY (arguments_list_p);

  JERRY_ASSERT (!ecma_is_completion_value_empty (ret_value));

  return ret_value;
} /* ecma_builtin_dispatch_construct */