/** * 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 */
/** * 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 */