/** * PutValue operation part (object base). * * See also: ECMA-262 v5, 8.7.2, section 4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_put_value_object_base (ecma_reference_t ref, /**< ECMA-reference */ ecma_value_t value) /**< ECMA-value */ { const ecma_value_t base = ref.base; const bool is_unresolvable_reference = ecma_is_value_undefined (base); const bool has_primitive_base = (ecma_is_value_boolean (base) || ecma_is_value_number (base) || ecma_is_value_string (base)); const bool has_object_base = (ecma_is_value_object (base) && !(ecma_is_lexical_environment (ecma_get_object_from_value (base)))); const bool is_property_reference = has_primitive_base || has_object_base; JERRY_ASSERT (!is_unresolvable_reference); JERRY_ASSERT (is_property_reference); // 4.a if (!has_primitive_base) { // 4.b case 1 ecma_object_t *obj_p = ecma_get_object_from_value (base); JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (put_ret_value, ecma_op_object_put (obj_p, ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp), value, ref.is_strict), ret_value); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_FINALIZE (put_ret_value); return ret_value; } else { // 4.b case 2 ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // sub_1. ECMA_TRY_CATCH (obj_base, ecma_op_to_object (base), ret_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_base); JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); ecma_string_t *referenced_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp); // sub_2. if (!ecma_op_object_can_put (obj_p, referenced_name_p)) { ret_value = ecma_reject_put (ref.is_strict); } else { // sub_3. ecma_property_t *own_prop_p = ecma_op_object_get_own_property (obj_p, referenced_name_p); // sub_5. ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, referenced_name_p); // sub_4., sub_7 if ((own_prop_p != NULL && (own_prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDDATA)) || (prop_p == NULL) || !(prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDACCESSOR)) { ret_value = ecma_reject_put (ref.is_strict); } else { // sub_6. JERRY_ASSERT (prop_p != NULL && (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDACCESSOR)); ecma_object_t *setter_p = ecma_get_named_accessor_property_setter (prop_p); JERRY_ASSERT (setter_p != NULL); ECMA_TRY_CATCH (call_ret, ecma_op_function_call (setter_p, base, &value, 1), ret_value); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_FINALIZE (call_ret); } } ECMA_FINALIZE (obj_base); return ret_value; } } /* ecma_op_put_value_object_base */
/** * [[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 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_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); // 1. if (!ecma_op_object_can_put (obj_p, property_name_p)) { if (is_throw) { // a. return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { // b. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE); } } // 2. ecma_property_t *own_desc_p = ecma_op_object_get_own_property (obj_p, property_name_p); // 3. if (own_desc_p != NULL && own_desc_p->type == ECMA_PROPERTY_NAMEDDATA) { // a. ecma_property_descriptor_t value_desc = ecma_make_empty_property_descriptor (); { value_desc.is_value_defined = true; value_desc.value = value; } // b., c. return ecma_op_object_define_own_property (obj_p, property_name_p, &value_desc, is_throw); } // 4. ecma_property_t *desc_p = ecma_op_object_get_property (obj_p, property_name_p); // 5. if (desc_p != NULL && desc_p->type == ECMA_PROPERTY_NAMEDACCESSOR) { // a. ecma_object_t *setter_p = ecma_get_named_accessor_property_setter (desc_p); JERRY_ASSERT (setter_p != NULL); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ECMA_TRY_CATCH (call_ret, ecma_op_function_call_array_args (setter_p, ecma_make_object_value (obj_p), &value, 1), ret_value); ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); ECMA_FINALIZE (call_ret); return ret_value; } else { // 6.a., 6.b. return ecma_builtin_helper_def_prop (obj_p, property_name_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ is_throw); /* Failure handling */ } JERRY_UNREACHABLE (); } /* ecma_op_general_object_put */