/**
 * [[GetProperty]] ecma general object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 8.12.2
 *
 * @return pointer to a property - if it exists,
 *         NULL (i.e. ecma-undefined) - otherwise.
 */
ecma_property_t*
ecma_op_general_object_get_property (ecma_object_t *obj_p, /**< the object */
                                     ecma_string_t *property_name_p) /**< property name */
{
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);

  // 1.
  ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, property_name_p);

  // 2.
  if (prop_p != NULL)
  {
    return prop_p;
  }

  // 3.
  ecma_object_t *prototype_p = ecma_get_object_prototype (obj_p);

  // 4., 5.
  if (prototype_p != NULL)
  {
    return ecma_op_object_get_property (prototype_p, property_name_p);
  }
  else
  {
    return NULL;
  }
} /* ecma_op_general_object_get_property */
/**
 * The Object object's 'getPrototypeOf' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.2
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_get_prototype_of (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
                                             ecma_value_t arg) /**< routine's argument */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  /* 1. */
  if (!ecma_is_value_object (arg))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    /* 2. */
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);
    ecma_object_t *prototype_p = ecma_get_object_prototype (obj_p);

    if (prototype_p)
    {
      ret_value = ecma_make_normal_completion_value (ecma_make_object_value (prototype_p));
      ecma_ref_object (prototype_p);
    }
    else
    {
      ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_NULL);
    }
  }

  return ret_value;
} /* ecma_builtin_object_object_get_prototype_of */
示例#3
0
/**
 * Mark objects as visited starting from specified object as root
 */
void
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (ecma_gc_is_object_visited (object_p));

  bool traverse_properties = true;

  if (ecma_is_lexical_environment (object_p))
  {
    ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
    if (lex_env_p != NULL)
    {
      ecma_gc_set_object_visited (lex_env_p, true);
    }

    if (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
    {
      ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
      ecma_gc_set_object_visited (binding_object_p, true);

      traverse_properties = false;
    }
  }
  else
  {
    ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
    if (proto_p != NULL)
    {
      ecma_gc_set_object_visited (proto_p, true);
    }
  }

  if (traverse_properties)
  {
    ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);

    while (prop_iter_p != NULL)
    {
      JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));

      if (prop_iter_p->types[0].type_and_flags != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 0);
      }

      if (prop_iter_p->types[1].type_and_flags != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 1);
      }

      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);
    }
  }
} /* ecma_gc_mark */
示例#4
0
/**
 * Object's isPrototypeOf operation
 *
 * See also:
 *          ECMA-262 v5, 15.2.4.6; 3
 *
 * @return true if the target object is prototype of the base object
 *         false if the target object is not prototype of the base object
 */
bool
ecma_op_object_is_prototype_of (ecma_object_t *base_p, /** < base object */
                                ecma_object_t *target_p) /** < target object */
{
  do
  {
    target_p = ecma_get_object_prototype (target_p);
    if (target_p == NULL)
    {
      return false;
    }
    else if (target_p == base_p)
    {
      return true;
    }
  } while (true);
} /* ecma_op_object_is_prototype_of */
示例#5
0
/**
 * Mark objects as visited starting from specified object as root
 */
void
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
    JERRY_ASSERT (object_p != NULL);
    JERRY_ASSERT (ecma_gc_is_object_visited (object_p));

    bool traverse_properties = true;

    if (ecma_is_lexical_environment (object_p))
    {
        ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
        if (lex_env_p != NULL)
        {
            ecma_gc_set_object_visited (lex_env_p, true);
        }

        if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
        {
            ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
            ecma_gc_set_object_visited (binding_object_p, true);

            traverse_properties = false;
        }
    }
    else
    {
        ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
        if (proto_p != NULL)
        {
            ecma_gc_set_object_visited (proto_p, true);
        }
    }

    if (traverse_properties)
    {
        for (ecma_property_t *property_p = ecma_get_property_list (object_p), *next_property_p;
                property_p != NULL;
                property_p = next_property_p)
        {
            next_property_p = ECMA_GET_POINTER (ecma_property_t,
                                                property_p->next_property_p);

            switch ((ecma_property_type_t) property_p->type)
            {
            case ECMA_PROPERTY_NAMEDDATA:
            {
                ecma_value_t value = ecma_get_named_data_property_value (property_p);

                if (ecma_is_value_object (value))
                {
                    ecma_object_t *value_obj_p = ecma_get_object_from_value (value);

                    ecma_gc_set_object_visited (value_obj_p, true);
                }

                break;
            }

            case ECMA_PROPERTY_NAMEDACCESSOR:
            {
                ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p);
                ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_p);

                if (getter_obj_p != NULL)
                {
                    ecma_gc_set_object_visited (getter_obj_p, true);
                }

                if (setter_obj_p != NULL)
                {
                    ecma_gc_set_object_visited (setter_obj_p, true);
                }

                break;
            }

            case ECMA_PROPERTY_INTERNAL:
            {
                ecma_internal_property_id_t property_id = (ecma_internal_property_id_t) property_p->u.internal_property.type;
                uint32_t property_value = property_p->u.internal_property.value;

                switch (property_id)
                {
                case ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */
                case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */
                {
                    JERRY_UNIMPLEMENTED ("Indexed array storage is not implemented yet.");
                }

                case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t
                                                    (see above in the routine) */
                case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t
                                                     (see above in the routine) */
                case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
                                             * but number of the real internal property types */
                {
                    JERRY_UNREACHABLE ();
                }

                case ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS: /* a collection of strings */
                case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */
                case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */
                case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */
                case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
                case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */
                case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */
                case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
                case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
                case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
                case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
                case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */
                case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
                case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */
                case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
                case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE:
                case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION:
                case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS:
                case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS:
                {
                    break;
                }

                case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
                case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
                {
                    ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, property_value);

                    ecma_gc_set_object_visited (obj_p, true);

                    break;
                }
                }

                break;
            }
            }
        }
    }
} /* ecma_gc_mark */
示例#6
0
/**
 * Mark objects as visited starting from specified object as root
 */
void
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (ecma_gc_is_object_visited (object_p));

  bool traverse_properties = true;

  if (ecma_is_lexical_environment (object_p))
  {
    ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
    if (lex_env_p != NULL)
    {
      ecma_gc_set_object_visited (lex_env_p, true);
    }

    if (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
    {
      ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
      ecma_gc_set_object_visited (binding_object_p, true);

      traverse_properties = false;
    }
  }
  else
  {
    ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
    if (proto_p != NULL)
    {
      ecma_gc_set_object_visited (proto_p, true);
    }

    if (!ecma_get_object_is_builtin (object_p)
        && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
    {
      ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;

      ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
                                                                ext_func_p->u.function.scope_cp);

      ecma_gc_set_object_visited (scope_p, true);
    }
  }

  if (traverse_properties)
  {
    ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);

    if (prop_iter_p != NULL
        && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP)
    {
      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);
    }

    while (prop_iter_p != NULL)
    {
      JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));

      if (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 0);
      }

      if (prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 1);
      }

      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);
    }
  }
} /* ecma_gc_mark */
示例#7
0
/**
 * Enumerate properties and construct collection with their
 * names for further iteration in for-in opcode handler.
 *
 * See also:
 *          ECMA-262 v5, 12.6.4
 *
 * @return header of constructed strings collection (should be freed with ecma_free_values_collection),
 *         or NULL - if there are no properties to enumerate in for-in.
 */
static ecma_collection_header_t *
vm_helper_for_in_enumerate_properties_names (ecma_object_t *obj_p) /**< starting object - result of ToObject
                                                                    *   conversion (ECMA-262 v5, 12.6.4, step 4) */
{
  const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE;
  uint32_t names_hashes_bitmap[(1u << LIT_STRING_HASH_BITS) / bitmap_row_size];

  memset (names_hashes_bitmap, 0, sizeof (names_hashes_bitmap));

  ecma_length_t all_properties_count = 0;

  /* First pass: counting properties */
  for (ecma_object_t *prototype_chain_iter_p = obj_p;
       prototype_chain_iter_p != NULL;
       prototype_chain_iter_p = ecma_get_object_prototype (prototype_chain_iter_p))
  {
    for (ecma_property_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
         prop_iter_p != NULL;
         prop_iter_p = ECMA_GET_POINTER (ecma_property_t, prop_iter_p->next_property_p))
    {
      if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA
          || prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
      {
        all_properties_count++;
      }
      else
      {
        JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_INTERNAL);
      }
    }
  }

  if (all_properties_count == 0)
  {
    return NULL;
  }

  ecma_collection_header_t *ret_p = NULL;

  /* Second pass: collecting properties names */
  MEM_DEFINE_LOCAL_ARRAY (names_p, all_properties_count, ecma_string_t*);

  ecma_length_t enumerated_properties_count = 0;
  ecma_length_t non_enumerated_properties_count = 0;

  for (ecma_object_t *prototype_chain_iter_p = obj_p;
       prototype_chain_iter_p != NULL;
       prototype_chain_iter_p = ecma_get_object_prototype (prototype_chain_iter_p))
  {
    for (ecma_property_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
         prop_iter_p != NULL;
         prop_iter_p = ECMA_GET_POINTER (ecma_property_t, prop_iter_p->next_property_p))
    {
      if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA
          || prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
      {
        bool is_enumerated;

        ecma_string_t *prop_name_p;

        if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA)
        {
          prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_data_property.name_p);
        }
        else
        {
          prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_accessor_property.name_p);
        }

        lit_string_hash_t hash = prop_name_p->hash;
        uint32_t bitmap_row = hash / bitmap_row_size;
        uint32_t bitmap_column = hash % bitmap_row_size;

        if (ecma_is_property_enumerable (prop_iter_p))
        {
          if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
          {
            /* no name with the hash occured during the iteration session */
            is_enumerated = true;
          }
          else
          {
            /* name with same hash already occured */
            bool is_equal_found = false;

            for (uint32_t index = 0;
                 !is_equal_found && index < enumerated_properties_count;
                 index++)
            {
              if (ecma_compare_ecma_strings (prop_name_p,
                                             names_p[index]))
              {
                is_equal_found = true;
              }
            }

            for (uint32_t index = 0;
                 !is_equal_found && index < non_enumerated_properties_count;
                 index++)
            {
              if (ecma_compare_ecma_strings (prop_name_p,
                                             names_p[all_properties_count - index - 1]))
              {
                is_equal_found = true;
              }
            }

            is_enumerated = !is_equal_found;
          }
        }
        else
        {
          is_enumerated = false;
        }

        names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);

        if (is_enumerated)
        {
          names_p[enumerated_properties_count++] = prop_name_p;
        }
        else
        {
          names_p[all_properties_count - non_enumerated_properties_count++ - 1] = prop_name_p;
        }

        JERRY_ASSERT (enumerated_properties_count + non_enumerated_properties_count <= all_properties_count);
      }
      else
      {
        JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_INTERNAL);
      }
    }
  }

  if (enumerated_properties_count != 0)
  {
    ret_p = ecma_new_strings_collection (names_p, enumerated_properties_count);
  }

  MEM_FINALIZE_LOCAL_ARRAY (names_p);

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

  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

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

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

    ecma_object_t *v_obj_p = ecma_get_object_from_value (value);

    ecma_string_t *prototype_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);

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

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

      do
      {
        v_obj_p = ecma_get_object_prototype (v_obj_p);

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

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

          break;
        }
      } while (true);
    }

    ECMA_FINALIZE (prototype_obj_value);

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

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

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

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

  return ret_value;
} /* ecma_op_function_has_instance */
示例#9
0
/*
 * Converts an standard error into a string.
 *
 * @return standard error string
 */
static ecma_string_t *
jerry_debugger_exception_object_to_string (ecma_value_t exception_obj_value) /**< exception object */
{
  ecma_object_t *object_p = ecma_get_object_from_value (exception_obj_value);

  ecma_object_t *prototype_p = ecma_get_object_prototype (object_p);

  if (prototype_p == NULL
      || ecma_get_object_type (prototype_p) != ECMA_OBJECT_TYPE_GENERAL
      || !ecma_get_object_is_builtin (prototype_p))
  {
    return NULL;
  }

  lit_magic_string_id_t string_id;

  switch (((ecma_extended_object_t *) prototype_p)->u.built_in.id)
  {
#ifndef CONFIG_DISABLE_ERROR_BUILTINS
    case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_EVAL_ERROR_UL;
      break;
    }
    case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_RANGE_ERROR_UL;
      break;
    }
    case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_REFERENCE_ERROR_UL;
      break;
    }
    case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_SYNTAX_ERROR_UL;
      break;
    }
    case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_TYPE_ERROR_UL;
      break;
    }
    case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_URI_ERROR_UL;
      break;
    }
#endif /* !CONFIG_DISABLE_ERROR_BUILTINS */
    case ECMA_BUILTIN_ID_ERROR_PROTOTYPE:
    {
      string_id = LIT_MAGIC_STRING_ERROR_UL;
      break;
    }
    default:
    {
      return NULL;
    }
  }

  lit_utf8_size_t size = lit_get_magic_string_size (string_id);
  JERRY_ASSERT (size <= 14);

  lit_utf8_byte_t data[16];
  memcpy (data, lit_get_magic_string_utf8 (string_id), size);

  ecma_property_t *property_p;
  property_p = ecma_find_named_property (ecma_get_object_from_value (exception_obj_value),
                                         ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE));

  if (property_p == NULL
      || ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
  {
    return ecma_new_ecma_string_from_utf8 (data, size);
  }

  ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);

  if (!ecma_is_value_string (prop_value_p->value))
  {
    return ecma_new_ecma_string_from_utf8 (data, size);
  }

  data[size] = LIT_CHAR_COLON;
  data[size + 1] = LIT_CHAR_SP;

  return ecma_concat_ecma_strings (ecma_new_ecma_string_from_utf8 (data, size + 2),
                                   ecma_get_string_from_value (prop_value_p->value));
} /* jerry_debugger_exception_object_to_string */
示例#10
0
/**
 * [[CanPut]] ecma general object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 8.12.4
 *
 * @return true - if [[Put]] with the given property name can be performed;
 *         false - otherwise.
 */
bool
ecma_op_general_object_can_put (ecma_object_t *obj_p, /**< the object */
                                ecma_string_t *property_name_p) /**< property name */
{
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);

  // 1.
  ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, property_name_p);

  // 2.
  if (prop_p != NULL)
  {
    // a.
    if (prop_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
    {
      ecma_object_t *setter_p = ecma_get_named_accessor_property_setter (prop_p);

      // i.
      if (setter_p == NULL)
      {
        return false;
      }

      // ii.
      return true;
    }
    else
    {
      // b.

      JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA);

      return ecma_is_property_writable (prop_p);
    }
  }

  // 3.
  ecma_object_t *proto_p = ecma_get_object_prototype (obj_p);

  // 4.
  if (proto_p == NULL)
  {
    return ecma_get_object_extensible (obj_p);
  }

  // 5.
  ecma_property_t *inherited_p = ecma_op_object_get_property (proto_p, property_name_p);

  // 6.
  if (inherited_p == NULL)
  {
    return ecma_get_object_extensible (obj_p);
  }

  // 7.
  if (inherited_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
  {
    ecma_object_t *setter_p = ecma_get_named_accessor_property_setter (inherited_p);

    // a.
    if (setter_p == NULL)
    {
      return false;
    }

    // b.
    return true;
  }
  else
  {
    // 8.
    JERRY_ASSERT (inherited_p->type == ECMA_PROPERTY_NAMEDDATA);

    // a.
    if (!ecma_get_object_extensible (obj_p))
    {
      return false;
    }
    else
    {
      // b.
      return ecma_is_property_writable (inherited_p);
    }
  }

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

  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

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

    ecma_object_t* v_obj_p = ecma_get_object_from_value (value);

    ecma_string_t *prototype_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);

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

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

      do
      {
        v_obj_p = ecma_get_object_prototype (v_obj_p);

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

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

          break;
        }
      } while (true);
    }

    ECMA_FINALIZE (prototype_obj_value);

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

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

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

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

  return ret_value;
} /* ecma_op_function_has_instance */
示例#12
0
/**
 * [[Put]] ecma general object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 8.12.5
 *          Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4
 *
 * @return ecma value
 *         The returned value must be freed with ecma_free_value.
 *
 *         Returns with ECMA_SIMPLE_VALUE_TRUE if the operation is
 *         successful. Otherwise it returns with an error object
 *         or ECMA_SIMPLE_VALUE_FALSE.
 *
 *         Note: even if is_throw is false, the setter can throw an
 *         error, and this function returns with that error.
 */
ecma_value_t
ecma_op_general_object_put (ecma_object_t *obj_p, /**< the object */
                            ecma_string_t *property_name_p, /**< property name */
                            ecma_value_t value, /**< ecma value */
                            bool is_throw) /**< flag that controls failure handling */
{
  JERRY_ASSERT (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);

  ecma_object_t *setter_p = NULL;

  ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, property_name_p);

  if (prop_p != NULL)
  {
    if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
    {
      if (ecma_is_property_writable (prop_p))
      {
        const ecma_object_type_t type = ecma_get_object_type (obj_p);

        if (type == ECMA_OBJECT_TYPE_ARGUMENTS
            || (type == ECMA_OBJECT_TYPE_ARRAY && ecma_op_general_object_property_name_is_length (property_name_p)))
        {
          /* These cases cannot be optimized. */
          ecma_property_descriptor_t value_desc = ecma_make_empty_property_descriptor ();

          value_desc.is_value_defined = true;
          value_desc.value = value;

          return ecma_op_object_define_own_property (obj_p,
                                                     property_name_p,
                                                     &value_desc,
                                                     is_throw);
        }

        /* There is no need for special casing arrays here because changing the
         * value of an existing property never changes the length of an array. */
        ecma_named_data_property_assign_value (obj_p, prop_p, value);
        return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
      }
    }
    else
    {
      JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

      setter_p = ecma_get_named_accessor_property_setter (prop_p);
    }
  }
  else
  {
    ecma_object_t *proto_p = ecma_get_object_prototype (obj_p);
    bool create_new_property = true;

    if (proto_p != NULL)
    {
      ecma_property_t *inherited_prop_p = ecma_op_object_get_property (proto_p, property_name_p);

      if (inherited_prop_p != NULL)
      {
        if (ECMA_PROPERTY_GET_TYPE (inherited_prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
        {
          setter_p = ecma_get_named_accessor_property_setter (inherited_prop_p);
          create_new_property = false;
        }
        else
        {
          create_new_property = ecma_is_property_writable (inherited_prop_p);
        }
      }
    }

    if (create_new_property
        && ecma_get_object_extensible (obj_p))
    {
      const ecma_object_type_t type = ecma_get_object_type (obj_p);

      if (type == ECMA_OBJECT_TYPE_ARGUMENTS)
      {
        return ecma_builtin_helper_def_prop (obj_p,
                                             property_name_p,
                                             value,
                                             true, /* Writable */
                                             true, /* Enumerable */
                                             true, /* Configurable */
                                             is_throw); /* Failure handling */
      }

      uint32_t index;

      if (type == ECMA_OBJECT_TYPE_ARRAY
          && ecma_string_get_array_index (property_name_p, &index))
      {
        /* Since the length of an array is a non-configurable named data
         * property, the prop_p must be a non-NULL pointer for all arrays. */

        JERRY_ASSERT (!ecma_op_general_object_property_name_is_length (property_name_p));

        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);
        ecma_deref_ecma_string (magic_string_length_p);

        JERRY_ASSERT (len_prop_p != NULL
                      && ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);

        uint32_t old_len = ecma_get_uint32_from_value (ecma_get_named_data_property_value (len_prop_p));

        if (index < UINT32_MAX
            && index >= old_len)
        {
          if (!ecma_is_property_writable (len_prop_p))
          {
            return ecma_reject (is_throw);
          }

          ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p);
          ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1);
        }
      }

      ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p,
                                                                     property_name_p,
                                                                     true, /* Writable */
                                                                     true, /* Enumerable */
                                                                     true); /* Configurable */

      JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (new_prop_p)));
      ecma_set_named_data_property_value (new_prop_p, ecma_copy_value_if_not_object (value));
      return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
    }
  }

  if (setter_p == NULL)
  {
    return ecma_reject (is_throw);
  }

  ecma_value_t ret_value = ecma_op_function_call (setter_p,
                                                  ecma_make_object_value (obj_p),
                                                  &value,
                                                  1);

  if (!ecma_is_value_error (ret_value))
  {
    ecma_fast_free_value (ret_value);
    ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  return ret_value;
} /* ecma_op_general_object_put */