/**
 * The Object object's 'isSealed' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.11
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_is_sealed (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
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);

    bool is_sealed;

    // 3.
    if (ecma_get_object_extensible (obj_p))
    {
      is_sealed = false;
    }
    else
    {
      /* the value can be updated in the loop below */
      is_sealed = true;

      // 2.
      ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);

      ecma_collection_iterator_t iter;
      ecma_collection_iterator_init (&iter, props_p);

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

        // 2.a
        ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);

        // 2.b
        if (ecma_is_property_configurable (property_p))
        {
          is_sealed = false;
          break;
        }
      }

      ecma_free_values_collection (props_p, true);
    }

    // 4.
    ret_value = ecma_make_simple_completion_value (is_sealed
                                                   ? ECMA_SIMPLE_VALUE_TRUE
                                                   : ECMA_SIMPLE_VALUE_FALSE);
  }

  return ret_value;
} /* ecma_builtin_object_object_is_sealed */
Example #2
0
/**
 * CreateMutableBinding operation.
 *
 * See also: ECMA-262 v5, 10.2.1
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */
                                ecma_string_t *name_p, /**< argument N */
                                bool is_deletable) /**< argument D */
{
  JERRY_ASSERT (lex_env_p != NULL
                && ecma_is_lexical_environment (lex_env_p));
  JERRY_ASSERT (name_p != NULL);

  if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
  {
    uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE;

    if (is_deletable)
    {
      prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_CONFIGURABLE);
    }

    ecma_create_named_data_property (lex_env_p,
                                     name_p,
                                     prop_attributes,
                                     NULL);
  }
  else
  {
    JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);

    ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);

    ecma_value_t completion;
    if (!ecma_get_object_extensible (binding_obj_p))
    {
      return ECMA_VALUE_EMPTY;
    }

    completion = ecma_builtin_helper_def_prop (binding_obj_p,
                                               name_p,
                                               ECMA_VALUE_UNDEFINED,
                                               is_deletable ? ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE
                                                            : ECMA_PROPERTY_ENUMERABLE_WRITABLE,
                                               true); /* Failure handling */

    if (ECMA_IS_VALUE_ERROR (completion))
    {
      return completion;
    }
    else
    {
      JERRY_ASSERT (ecma_is_value_boolean (completion));
    }
  }

  return ECMA_VALUE_EMPTY;
} /* ecma_op_create_mutable_binding */
/**
 * The Object object's 'isExtensible' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.13
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_is_extensible (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 ();

  if (!ecma_is_value_object (arg))
  {
    ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
  }
  else
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);

    bool extensible = ecma_get_object_extensible (obj_p);

    ret_value = ecma_make_simple_completion_value (extensible
                                                   ? ECMA_SIMPLE_VALUE_TRUE
                                                   : ECMA_SIMPLE_VALUE_FALSE);
  }

  return ret_value;
} /* ecma_builtin_object_object_is_extensible */
/**
 * [[DefineOwnProperty]] ecma general object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 8.12.9
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value
 */
ecma_completion_value_t
ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the 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 (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);

  const bool is_property_desc_generic_descriptor = (!property_desc_p->is_value_defined
                                                    && !property_desc_p->is_writable_defined
                                                    && !property_desc_p->is_get_defined
                                                    && !property_desc_p->is_set_defined);
  const bool is_property_desc_data_descriptor = (property_desc_p->is_value_defined
                                                 || property_desc_p->is_writable_defined);
  const bool is_property_desc_accessor_descriptor = (property_desc_p->is_get_defined
                                                     || property_desc_p->is_set_defined);

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

  // 2.
  bool extensible = ecma_get_object_extensible (obj_p);

  if (current_p == NULL)
  {
    // 3.
    if (!extensible)
    {
      return ecma_reject (is_throw);
    }

    // 4.

    // a.
    if (is_property_desc_generic_descriptor
        || is_property_desc_data_descriptor)
    {
      ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p,
                                                                     property_name_p,
                                                                     property_desc_p->is_writable,
                                                                     property_desc_p->is_enumerable,
                                                                     property_desc_p->is_configurable);

      ecma_named_data_property_assign_value (obj_p, new_prop_p, property_desc_p->value);
    }
    else
    {
      // b.
      JERRY_ASSERT (is_property_desc_accessor_descriptor);

      ecma_create_named_accessor_property (obj_p,
                                           property_name_p,
                                           property_desc_p->get_p,
                                           property_desc_p->set_p,
                                           property_desc_p->is_enumerable,
                                           property_desc_p->is_configurable);

    }

    return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  // 5.
  if (is_property_desc_generic_descriptor
      && !property_desc_p->is_enumerable_defined
      && !property_desc_p->is_configurable_defined)
  {
    return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  // 6.
  const bool is_current_data_descriptor = (current_p->type == ECMA_PROPERTY_NAMEDDATA);
  const bool is_current_accessor_descriptor = (current_p->type == ECMA_PROPERTY_NAMEDACCESSOR);

  JERRY_ASSERT (is_current_data_descriptor || is_current_accessor_descriptor);

  bool is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = true;
  if (property_desc_p->is_value_defined)
  {
    if (!is_current_data_descriptor
        || !ecma_op_same_value (property_desc_p->value,
                                ecma_get_named_data_property_value (current_p)))
    {
      is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = false;
    }
  }

  if (property_desc_p->is_writable_defined)
  {
    if (!is_current_data_descriptor
        || property_desc_p->is_writable != ecma_is_property_writable (current_p))
    {
      is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = false;
    }
  }

  if (property_desc_p->is_get_defined)
  {
    if (!is_current_accessor_descriptor
        || property_desc_p->get_p != ecma_get_named_accessor_property_getter (current_p))
    {
      is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = false;
    }
  }

  if (property_desc_p->is_set_defined)
  {
    if (!is_current_accessor_descriptor
        || property_desc_p->set_p != ecma_get_named_accessor_property_setter (current_p))
    {
      is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = false;
    }
  }

  if (property_desc_p->is_enumerable_defined)
  {
    if (property_desc_p->is_enumerable != ecma_is_property_enumerable (current_p))
    {
      is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = false;
    }
  }

  if (property_desc_p->is_configurable_defined)
  {
    if (property_desc_p->is_configurable != ecma_is_property_configurable (current_p))
    {
      is_every_field_in_desc_also_occurs_in_current_desc_with_same_value = false;
    }
  }

  if (is_every_field_in_desc_also_occurs_in_current_desc_with_same_value)
  {
    return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  // 7.
  if (!ecma_is_property_configurable (current_p))
  {
    if (property_desc_p->is_configurable
        || (property_desc_p->is_enumerable_defined
            && property_desc_p->is_enumerable != ecma_is_property_enumerable (current_p)))
    {
      // a., b.
      return ecma_reject (is_throw);
    }
  }

  // 8.
  if (is_property_desc_generic_descriptor)
  {
    // no action required
  }
  else if (is_property_desc_data_descriptor != is_current_data_descriptor)
  {
    // 9.
    if (!ecma_is_property_configurable (current_p))
    {
      // a.
      return ecma_reject (is_throw);
    }

    bool was_enumerable = ecma_is_property_enumerable (current_p);
    bool was_configurable = ecma_is_property_configurable (current_p);

    ecma_delete_property (obj_p, current_p);

    if (is_current_data_descriptor)
    {
      // b.

      current_p = ecma_create_named_accessor_property (obj_p,
                                                       property_name_p,
                                                       NULL,
                                                       NULL,
                                                       was_enumerable,
                                                       was_configurable);
    }
    else
    {
      // c.

      current_p = ecma_create_named_data_property (obj_p,
                                                   property_name_p,
                                                   false,
                                                   was_enumerable,
                                                   was_configurable);
    }
  }
  else if (is_property_desc_data_descriptor && is_current_data_descriptor)
  {
    // 10.
    if (!ecma_is_property_configurable (current_p))
    {
      // a.
      if (!ecma_is_property_writable (current_p))
      {
        // i.
        if (property_desc_p->is_writable)
        {
          return ecma_reject (is_throw);
        }

        // ii.
        if (property_desc_p->is_value_defined
            && !ecma_op_same_value (property_desc_p->value,
                                    ecma_get_named_data_property_value (current_p)))
        {
          return ecma_reject (is_throw);
        }
      }
    }
  }
  else
  {
    JERRY_ASSERT (is_property_desc_accessor_descriptor && is_current_accessor_descriptor);

    // 11.

    if (!ecma_is_property_configurable (current_p))
    {
      // a.

      if ((property_desc_p->is_get_defined
           && property_desc_p->get_p != ecma_get_named_accessor_property_getter (current_p))
          || (property_desc_p->is_set_defined
              && property_desc_p->set_p != ecma_get_named_accessor_property_setter (current_p)))
      {
        // i., ii.
        return ecma_reject (is_throw);
      }
    }
  }

  // 12.
  if (property_desc_p->is_value_defined)
  {
    JERRY_ASSERT (current_p->type == ECMA_PROPERTY_NAMEDDATA);

    ecma_named_data_property_assign_value (obj_p, current_p, property_desc_p->value);
  }

  if (property_desc_p->is_writable_defined)
  {
    JERRY_ASSERT (current_p->type == ECMA_PROPERTY_NAMEDDATA);

    ecma_set_property_writable_attr (current_p, property_desc_p->is_writable);
  }

  if (property_desc_p->is_get_defined)
  {
    JERRY_ASSERT (current_p->type == ECMA_PROPERTY_NAMEDACCESSOR);

    ecma_set_named_accessor_property_getter (obj_p, current_p, property_desc_p->get_p);
  }

  if (property_desc_p->is_set_defined)
  {
    JERRY_ASSERT (current_p->type == ECMA_PROPERTY_NAMEDACCESSOR);

    ecma_set_named_accessor_property_setter (obj_p, current_p, property_desc_p->set_p);
  }

  if (property_desc_p->is_enumerable_defined)
  {
    ecma_set_property_enumerable_attr (current_p, property_desc_p->is_enumerable);
  }

  if (property_desc_p->is_configurable_defined)
  {
    ecma_set_property_configurable_attr (current_p, property_desc_p->is_configurable);
  }

  return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE);
} /* ecma_op_general_object_define_own_property */
/**
 * [[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 */
/**
 * The Object object's 'isFrozen' routine
 *
 * See also:
 *          ECMA-262 v5, 15.2.3.12
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_object_object_is_frozen (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
  {
    ecma_object_t *obj_p = ecma_get_object_from_value (arg);

    bool is_frozen;

    // 3.
    if (ecma_get_object_extensible (obj_p))
    {
      is_frozen = false;
    }
    else
    {
      is_frozen = true;

      // 2.
      ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);

      ecma_collection_iterator_t iter;
      ecma_collection_iterator_init (&iter, props_p);

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

        // 2.a
        ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);

        JERRY_ASSERT (property_p->type == ECMA_PROPERTY_NAMEDDATA || property_p->type == ECMA_PROPERTY_NAMEDACCESSOR);

        // 2.b
        if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_writable (property_p))
        {
          is_frozen = false;
          break;
        }

        // 2.c
        if (ecma_is_property_configurable (property_p))
        {
          is_frozen = false;
          break;
        }
      }

      ecma_free_values_collection (props_p, true);
    }

    // 4.
    ret_value = ecma_make_simple_completion_value (is_frozen
                                                   ? ECMA_SIMPLE_VALUE_TRUE
                                                   : ECMA_SIMPLE_VALUE_FALSE);
  }

  return ret_value;
} /* ecma_builtin_object_object_is_frozen */
/**
 * [[DefineOwnProperty]] ecma general object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 8.12.9
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_value_t
ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the 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 (obj_p != NULL
                && !ecma_is_lexical_environment (obj_p));
  JERRY_ASSERT (property_name_p != NULL);

  ecma_property_types_t property_desc_type = ECMA_PROPERTY_TYPE_GENERIC;

  if (property_desc_p->is_value_defined
      || property_desc_p->is_writable_defined)
  {
    /* A property descriptor cannot be both named data and named accessor. */
    JERRY_ASSERT (!property_desc_p->is_get_defined
                  && !property_desc_p->is_set_defined);
    property_desc_type = ECMA_PROPERTY_TYPE_NAMEDDATA;
  }
  else if (property_desc_p->is_get_defined
           || property_desc_p->is_set_defined)
  {
    property_desc_type = ECMA_PROPERTY_TYPE_NAMEDACCESSOR;
  }

  /* These three asserts ensures that a new property is created with the appropriate default flags.
   * E.g. if is_configurable_defined is false, the newly created property must be non-configurable. */
  JERRY_ASSERT (property_desc_p->is_configurable_defined || !property_desc_p->is_configurable);
  JERRY_ASSERT (property_desc_p->is_enumerable_defined || !property_desc_p->is_enumerable);
  JERRY_ASSERT (property_desc_p->is_writable_defined || !property_desc_p->is_writable);

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

  if (current_p == NULL)
  {
    // 3.
    if (!ecma_get_object_extensible (obj_p))
    {
      // 2.
      return ecma_reject (is_throw);
    }

    // 4.

    if (property_desc_type != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
    {
      // a.

      JERRY_ASSERT (property_desc_type == ECMA_PROPERTY_TYPE_GENERIC
                    || property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA);

      ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p,
                                                                     property_name_p,
                                                                     property_desc_p->is_writable,
                                                                     property_desc_p->is_enumerable,
                                                                     property_desc_p->is_configurable);


      JERRY_ASSERT (property_desc_p->is_value_defined
                    || ecma_is_value_undefined (property_desc_p->value));

      ecma_named_data_property_assign_value (obj_p, new_prop_p, property_desc_p->value);
    }
    else
    {
      // b.

      ecma_create_named_accessor_property (obj_p,
                                           property_name_p,
                                           property_desc_p->get_p,
                                           property_desc_p->set_p,
                                           property_desc_p->is_enumerable,
                                           property_desc_p->is_configurable);
    }

    return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
  }

  // 6.
  ecma_property_types_t current_property_type = ECMA_PROPERTY_GET_TYPE (current_p);
  const bool is_current_configurable = ecma_is_property_configurable (current_p);

  JERRY_ASSERT (current_property_type == ECMA_PROPERTY_TYPE_NAMEDDATA
                || current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

  // 7. a., b.
  if (!is_current_configurable
      && (property_desc_p->is_configurable
          || (property_desc_p->is_enumerable_defined
              && (property_desc_p->is_enumerable != ecma_is_property_enumerable (current_p)))))
  {
    return ecma_reject (is_throw);
  }

  // 8.
  if (property_desc_type == ECMA_PROPERTY_TYPE_GENERIC)
  {
    /* No action required. */
  }
  else if (likely (property_desc_type == current_property_type))
  {
    /* If property is configurable, there is no need for checks. */
    if (unlikely (!is_current_configurable))
    {
      if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA)
      {
        // 10. a. i. & ii.
        if (!ecma_is_property_writable (current_p)
            && (property_desc_p->is_writable
                || (property_desc_p->is_value_defined
                    && !ecma_op_same_value (property_desc_p->value,
                                            ecma_get_named_data_property_value (current_p)))))
        {
          return ecma_reject (is_throw);
        }
      }
      else
      {
        // 11.

        // a.
        if ((property_desc_p->is_get_defined
             && property_desc_p->get_p != ecma_get_named_accessor_property_getter (current_p))
            || (property_desc_p->is_set_defined
                && property_desc_p->set_p != ecma_get_named_accessor_property_setter (current_p)))
        {
          // i., ii.
          return ecma_reject (is_throw);
        }
      }
    }
  }
  else
  {
    // 9.
    if (!is_current_configurable)
    {
      // a.
      return ecma_reject (is_throw);
    }

    /* The following implementation can be optimized by directly overwriting
     * the fields of current_p if this code path is performance critical. */

    bool was_enumerable = ecma_is_property_enumerable (current_p);

    ecma_delete_property (obj_p, current_p);

    if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
    {
      // b.

      current_p = ecma_create_named_accessor_property (obj_p,
                                                       property_name_p,
                                                       NULL,
                                                       NULL,
                                                       was_enumerable,
                                                       true);
    }
    else
    {
      // c.

      current_p = ecma_create_named_data_property (obj_p,
                                                   property_name_p,
                                                   false,
                                                   was_enumerable,
                                                   true);
    }
  }

  // 12.
  if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA)
  {
    JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (current_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);

    if (property_desc_p->is_value_defined)
    {
      ecma_named_data_property_assign_value (obj_p, current_p, property_desc_p->value);
    }

    if (property_desc_p->is_writable_defined)
    {
      ecma_set_property_writable_attr (current_p, property_desc_p->is_writable);
    }
  }
  else if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
  {
    JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (current_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

    if (property_desc_p->is_get_defined)
    {
      ecma_set_named_accessor_property_getter (obj_p, current_p, property_desc_p->get_p);
    }

    if (property_desc_p->is_set_defined)
    {
      ecma_set_named_accessor_property_setter (obj_p, current_p, property_desc_p->set_p);
    }
  }

  if (property_desc_p->is_enumerable_defined)
  {
    ecma_set_property_enumerable_attr (current_p, property_desc_p->is_enumerable);
  }

  if (property_desc_p->is_configurable_defined)
  {
    ecma_set_property_configurable_attr (current_p, property_desc_p->is_configurable);
  }

  return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
} /* ecma_op_general_object_define_own_property */
/**
 * [[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 */