/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ bool is_enumerable, /**< 'enumerable' attribute */ bool is_configurable) /**< 'configurable' attribute */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR; if (is_configurable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_CONFIGURABLE); } if (is_enumerable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_ENUMERABLE); } name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_t *property_p = ecma_create_property (object_p, name_p, type_and_flags); /* * Should be performed after linking the property into object's property list, because the setters assert that. */ ecma_set_named_accessor_property_getter (object_p, property_p, get_p); ecma_set_named_accessor_property_setter (object_p, property_p, set_p); ecma_lcache_invalidate (object_p, name_p, NULL); return property_p; } /* ecma_create_named_accessor_property */
/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to the newly created property value */ ecma_property_value_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ uint8_t prop_attributes, /**< property attributes */ ecma_property_t **out_prop_p) /**< [out] the property is also returned * if this field is non-NULL */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes; ecma_property_value_t value; #ifdef JERRY_CPOINTER_32_BIT ecma_getter_setter_pointers_t *getter_setter_pair_p; getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); ECMA_SET_POINTER (getter_setter_pair_p->getter_p, get_p); ECMA_SET_POINTER (getter_setter_pair_p->setter_p, set_p); ECMA_SET_POINTER (value.getter_setter_pair_cp, getter_setter_pair_p); #else /* !JERRY_CPOINTER_32_BIT */ ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p); ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p); #endif /* JERRY_CPOINTER_32_BIT */ return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); } /* ecma_create_named_accessor_property */
/** * Create named data property with given name, attributes and undefined value * in the specified object. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ bool is_writable, /**< 'Writable' attribute */ bool is_enumerable, /**< 'Enumerable' attribute */ bool is_configurable) /**< 'Configurable' attribute */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDDATA; if (is_configurable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_CONFIGURABLE); } if (is_enumerable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_ENUMERABLE); } if (is_writable) { type_and_flags = (uint8_t) (type_and_flags | ECMA_PROPERTY_FLAG_WRITABLE); } name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_t *property_p = ecma_create_property (object_p, name_p, type_and_flags); ecma_set_named_data_property_value (property_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ecma_lcache_invalidate (object_p, name_p, NULL); return property_p; } /* ecma_create_named_data_property */
/** * Update getter or setter for object literals. */ void opfunc_set_accessor (bool is_getter, /**< is getter accessor */ ecma_value_t object, /**< object value */ ecma_value_t accessor_name, /**< accessor name value */ ecma_value_t accessor) /**< accessor value */ { ecma_object_t *object_p = ecma_get_object_from_value (object); JERRY_ASSERT (ecma_is_value_string (accessor_name) || ecma_is_value_number (accessor_name)); ecma_string_t *accessor_name_p = ecma_get_string_from_value (ecma_op_to_string (accessor_name)); ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p); if (property_p != NULL && ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p)); property_p = NULL; } if (property_p == NULL) { ecma_object_t *getter_func_p = NULL; ecma_object_t *setter_func_p = NULL; if (is_getter) { getter_func_p = ecma_get_object_from_value (accessor); } else { setter_func_p = ecma_get_object_from_value (accessor); } ecma_create_named_accessor_property (object_p, accessor_name_p, getter_func_p, setter_func_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE, NULL); } else if (is_getter) { ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_getter (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), getter_func_p); } else { ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_setter (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), setter_func_p); } ecma_deref_ecma_string (accessor_name_p); } /* opfunc_set_accessor */
/** * [[GetOwnProperty]] 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_own_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); return ecma_find_named_property (obj_p, property_name_p); } /* ecma_op_general_object_get_own_property */
/** * Update getter or setter for object literals. */ void opfunc_set_accessor (bool is_getter, /**< is getter accessor */ ecma_value_t object, /**< object value */ ecma_value_t accessor_name, /**< accessor name value */ ecma_value_t accessor) /**< accessor value */ { ecma_object_t *object_p = ecma_get_object_from_value (object); ecma_string_t *accessor_name_p = ecma_get_string_from_value (accessor_name); ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p); if (property_p != NULL && property_p->type != ECMA_PROPERTY_NAMEDACCESSOR) { ecma_delete_property (object_p, property_p); property_p = NULL; } if (property_p == NULL) { ecma_object_t *getter_func_p = NULL; ecma_object_t *setter_func_p = NULL; if (is_getter) { getter_func_p = ecma_get_object_from_value (accessor); } else { setter_func_p = ecma_get_object_from_value (accessor); } ecma_create_named_accessor_property (object_p, accessor_name_p, getter_func_p, setter_func_p, true, true); } else if (is_getter) { ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_getter (object_p, property_p, getter_func_p); } else { ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_setter (object_p, property_p, setter_func_p); } } /* opfunc_set_accessor */
/** * Resolve value corresponding to reference. * * @return value of the reference */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ ecma_string_t *name_p, /**< identifier's name */ bool is_strict) /**< strict mode */ { JERRY_ASSERT (lex_env_p != NULL); while (lex_env_p != NULL) { if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); if (property_p != NULL) { ecma_value_t prop_value = ecma_get_named_data_property_value (property_p); /* is the binding mutable? */ if (unlikely (!ecma_is_property_writable (property_p) && ecma_is_value_empty (prop_value))) { /* unitialized mutable binding */ if (is_strict) { return ecma_raise_reference_error (ECMA_ERR_MSG ("")); } else { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } return ecma_fast_copy_value (prop_value); } } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND || 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_property_t *property_p = ecma_op_object_get_property (binding_obj_p, name_p); if (property_p != NULL) { return ecma_op_object_get (binding_obj_p, name_p); } } lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } return ecma_raise_reference_error (ECMA_ERR_MSG ("")); } /* ecma_op_resolve_reference_value */
/** * Get named data property in specified object. * * Warning: * the property must exist and be named data property * * @return pointer to the property, if it is found, * NULL - otherwise. */ ecma_property_t * ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property in */ ecma_string_t *name_p) /**< property's name */ { JERRY_ASSERT (obj_p != NULL); JERRY_ASSERT (name_p != NULL); ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); return property_p; } /* ecma_get_named_data_property */
/** * Get named data property or named access property in specified object. * * Warning: * the property must exist * * @return pointer to the property, if it is found, * NULL - otherwise. */ ecma_property_t * ecma_get_named_property (ecma_object_t *obj_p, /**< object to find property in */ ecma_string_t *name_p) /**< property's name */ { JERRY_ASSERT (obj_p != NULL); JERRY_ASSERT (name_p != NULL); ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); JERRY_ASSERT (property_p != NULL); return property_p; } /* ecma_get_named_property */
/** * SetMutableBinding 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_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ ecma_value_t value, /**< argument V */ bool is_strict) /**< argument S */ { 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) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); if (ecma_is_property_writable (*property_p)) { ecma_named_data_property_assign_value (lex_env_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); } else if (is_strict) { return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set.")); } } 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 = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); if (ECMA_IS_VALUE_ERROR (completion)) { return completion; } JERRY_ASSERT (ecma_is_value_boolean (completion)); } return ECMA_VALUE_EMPTY; } /* ecma_op_set_mutable_binding */
/** * DeleteBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Return value is simple and so need not be freed. * However, ecma_free_value may be called for it, but it is a no-op. */ ecma_value_t ecma_op_delete_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p) /**< argument N */ { 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) { ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, name_p); ecma_simple_value_t ret_val; if (prop_p == NULL) { ret_val = ECMA_SIMPLE_VALUE_TRUE; } else { JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA); if (!ecma_is_property_configurable (prop_p)) { ret_val = ECMA_SIMPLE_VALUE_FALSE; } else { ecma_delete_property (lex_env_p, prop_p); ret_val = ECMA_SIMPLE_VALUE_TRUE; } } return ecma_make_simple_value (ret_val); } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); return ecma_op_object_delete (binding_obj_p, name_p, false); } } /* ecma_op_delete_binding */
/** * Create named data property with given name, attributes and undefined value * in the specified object. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ uint8_t prop_attributes) /**< property attributes (See: ecma_property_flags_t) */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDDATA | prop_attributes; name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_value_t value; value.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); return ecma_create_property (object_p, name_p, type_and_flags, value); } /* ecma_create_named_data_property */
/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ uint8_t prop_attributes) /**< property attributes */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes; name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_value_t value; ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p); ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p); return ecma_create_property (object_p, name_p, type_and_flags, value); } /* ecma_create_named_accessor_property */
/** * HasBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return true / false */ bool ecma_op_has_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p) /**< argument N */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); return (property_p != NULL); } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); return (ecma_op_object_get_property (binding_obj_p, name_p) != NULL); } } /* ecma_op_has_binding */
/* * Initializes the source, global, ignoreCase, multiline, and lastIndex properties of RegExp instance. */ void re_initialize_props (ecma_object_t *re_obj_p, /**< RegExp obejct */ ecma_string_t *source_p, /**< source string */ uint8_t flags) /**< flags */ { /* Set source property. ECMA-262 v5, 15.10.7.1 */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *prop_p = ecma_find_named_property (re_obj_p, magic_string_p); if (prop_p == NULL) { prop_p = ecma_create_named_data_property (re_obj_p, magic_string_p, false, false, false); } ecma_deref_ecma_string (magic_string_p); JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA); ecma_named_data_property_assign_value (re_obj_p, prop_p, ecma_make_string_value (source_p)); ecma_simple_value_t prop_value; /* Set global property. ECMA-262 v5, 15.10.7.2 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); prop_p = ecma_find_named_property (re_obj_p, magic_string_p); if (prop_p == NULL) { prop_p = ecma_create_named_data_property (re_obj_p, magic_string_p, false, false, false); } ecma_deref_ecma_string (magic_string_p); prop_value = flags & RE_FLAG_GLOBAL ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE; JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA); ecma_set_named_data_property_value (prop_p, ecma_make_simple_value (prop_value)); /* Set ignoreCase property. ECMA-262 v5, 15.10.7.3 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); prop_p = ecma_find_named_property (re_obj_p, magic_string_p); if (prop_p == NULL) { prop_p = ecma_create_named_data_property (re_obj_p, magic_string_p, false, false, false); } ecma_deref_ecma_string (magic_string_p); prop_value = flags & RE_FLAG_IGNORE_CASE ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE; JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA); ecma_set_named_data_property_value (prop_p, ecma_make_simple_value (prop_value)); /* Set multiline property. ECMA-262 v5, 15.10.7.4 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); prop_p = ecma_find_named_property (re_obj_p, magic_string_p); if (prop_p == NULL) { prop_p = ecma_create_named_data_property (re_obj_p, magic_string_p, false, false, false); } ecma_deref_ecma_string (magic_string_p); prop_value = flags & RE_FLAG_MULTILINE ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE; JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA); ecma_set_named_data_property_value (prop_p, ecma_make_simple_value (prop_value)); /* Set lastIndex property. ECMA-262 v5, 15.10.7.5 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); prop_p = ecma_find_named_property (re_obj_p, magic_string_p); if (prop_p == NULL) { prop_p = ecma_create_named_data_property (re_obj_p, magic_string_p, true, false, false); } ecma_deref_ecma_string (magic_string_p); ecma_number_t *lastindex_num_p = ecma_alloc_number (); *lastindex_num_p = ECMA_NUMBER_ZERO; JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA); ecma_named_data_property_assign_value (re_obj_p, prop_p, ecma_make_number_value (lastindex_num_p)); ecma_dealloc_number (lastindex_num_p); } /* re_initialize_props */
/* * 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 */
/** * [[DefineOwnProperty]] ecma array object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.4.5.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the array 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 */ { if (ecma_string_is_length (property_name_p)) { if (!property_desc_p->is_value_defined) { return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p, is_throw); } 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); uint32_t flags = 0; if (is_throw) { flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW; } /* Only the writable and data properties can be modified. */ if (property_desc_p->is_configurable || property_desc_p->is_enumerable || property_desc_p->is_get_defined || property_desc_p->is_set_defined) { flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT; } if (property_desc_p->is_writable_defined) { flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED; } if (property_desc_p->is_writable) { flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE; } return ecma_op_array_object_set_length (object_p, property_desc_p->value, flags); } uint32_t index = ecma_string_get_array_index (property_name_p); if (index == ECMA_STRING_NOT_ARRAY_INDEX) { return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p, is_throw); } ecma_string_t magic_string_length; ecma_init_ecma_length_string (&magic_string_length); ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); bool update_length = (index >= ecma_get_uint32_from_value (len_prop_value_p->value)); if (update_length && !ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } ecma_value_t completition = ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p, false); JERRY_ASSERT (ecma_is_value_boolean (completition)); if (ecma_is_value_false (completition)) { return ecma_reject (is_throw); } if (update_length) { ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } /* ecma_op_array_object_define_own_property */
/** * Update the length of an array to a new length * * @return ecma value * Returned value must be freed with ecma_free_value */ extern ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ ecma_value_t new_value, /**< new length value */ uint32_t flags) /**< configuration options */ { bool is_throw = (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW); ecma_value_t completion = ecma_op_to_number (new_value); if (ECMA_IS_VALUE_ERROR (completion)) { return completion; } JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion) && ecma_is_value_number (completion)); ecma_number_t new_len_num = ecma_get_number_from_value (completion); ecma_free_value (completion); if (ecma_is_value_object (new_value)) { ecma_value_t compared_num_val = ecma_op_to_number (new_value); if (ECMA_IS_VALUE_ERROR (completion)) { return compared_num_val; } new_len_num = ecma_get_number_from_value (compared_num_val); ecma_free_value (compared_num_val); } uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); if (((ecma_number_t) new_len_uint32) != new_len_num) { return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length.")); } if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT) { return ecma_reject (is_throw); } ecma_string_t magic_string_length; ecma_init_ecma_length_string (&magic_string_length); ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); uint32_t old_len_uint32 = ecma_get_uint32_from_value (len_prop_value_p->value); if (new_len_num == old_len_uint32) { /* Only the writable flag must be updated. */ if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) { if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { ecma_set_property_writable_attr (len_prop_p, false); } else if (!ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else if (!ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } uint32_t current_len_uint32 = new_len_uint32; if (new_len_uint32 < old_len_uint32) { current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32); } ecma_value_assign_uint32 (&len_prop_value_p->value, current_len_uint32); if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) && !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { ecma_set_property_writable_attr (len_prop_p, false); } if (current_len_uint32 == new_len_uint32) { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } return ecma_reject (is_throw); } /* ecma_op_array_object_set_length */
/** * Resolve value corresponding to reference. * * @return value of the reference */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ ecma_string_t *name_p) /**< identifier's name */ { JERRY_ASSERT (lex_env_p != NULL); while (lex_env_p != NULL) { ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p); if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); if (property_p != NULL) { return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); } } else if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND) { ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); #ifndef CONFIG_ECMA_LCACHE_DISABLE ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); if (property_p != NULL) { ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { return ecma_fast_copy_value (prop_value_p->value); } JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_value_p); if (getter_p == NULL) { return ECMA_VALUE_UNDEFINED; } ecma_value_t base_value = ecma_make_object_value (binding_obj_p); return ecma_op_function_call (getter_p, base_value, NULL, 0); } #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ ecma_value_t prop_value = ecma_op_object_find (binding_obj_p, name_p); if (ecma_is_value_found (prop_value)) { return prop_value; } } else { #if ENABLED (JERRY_ES2015_CLASS) JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND); #else /* !ENABLED (JERRY_ES2015_CLASS) */ JERRY_UNREACHABLE (); #endif /* ENABLED (JERRY_ES2015_CLASS) */ } lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } #ifdef JERRY_ENABLE_ERROR_MESSAGES ecma_value_t name_val = ecma_make_string_value (name_p); ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, "% is not defined", name_val); #else /* !JERRY_ENABLE_ERROR_MESSAGES */ ecma_value_t error_value = ecma_raise_reference_error (NULL); #endif /* JERRY_ENABLE_ERROR_MESSAGES */ return error_value; } /* ecma_op_resolve_reference_value */