/** * Get value of external pointer stored in the object's property with specified identifier * * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. * * @return true - if property exists and it's value is returned through out_pointer_p, * false - otherwise (value returned through out_pointer_p is NULL). */ bool ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */ ecma_internal_property_id_t id, /**< identifier of internal property * to get value from */ ecma_external_pointer_t *out_pointer_p) /**< [out] value of the external pointer */ { JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id); if (prop_p == NULL) { *out_pointer_p = (ecma_external_pointer_t) NULL; return false; } if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { *out_pointer_p = ECMA_PROPERTY_VALUE_PTR (prop_p)->value; } else { ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); *out_pointer_p = *handler_p; } return true; } /* ecma_get_external_pointer_value */
/** * 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 */
/** * Free property values and change their type to deleted. */ void ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to */ jmem_cpointer_t name_cp, /**< name of the property or ECMA_NULL_POINTER */ ecma_property_t *property_p) /**< property */ { JERRY_ASSERT (object_p != NULL && property_p != NULL); switch (ECMA_PROPERTY_GET_TYPE (*property_p)) { case ECMA_PROPERTY_TYPE_NAMEDDATA: { if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING) { if (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE || name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER) { ecma_free_native_pointer (property_p); break; } } ecma_free_value_if_not_object (ECMA_PROPERTY_VALUE_PTR (property_p)->value); break; } case ECMA_PROPERTY_TYPE_NAMEDACCESSOR: { #ifdef JERRY_CPOINTER_32_BIT ecma_getter_setter_pointers_t *getter_setter_pair_p; getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t, ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp); jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); #endif /* JERRY_CPOINTER_32_BIT */ break; } default: { JERRY_UNREACHABLE (); return; } } if (ecma_is_property_lcached (property_p)) { ecma_lcache_invalidate (object_p, name_cp, property_p); } if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_PROPERTY_NAME_TYPE_STRING) { ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp); ecma_deref_ecma_string (prop_name_p); } *property_p = ECMA_PROPERTY_TYPE_DELETED; } /* ecma_free_property */
/** * Create internal property with specified identifier and store external pointer in the property. * * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. * * @return true - if property was just created with specified value, * false - otherwise, if property existed before the call, it's value was updated. */ bool ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */ ecma_internal_property_id_t id, /**< identifier of internal * property to create */ ecma_external_pointer_t ptr_value) /**< value to store in the property */ { JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); bool is_new; ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id); if (prop_p == NULL) { prop_p = ecma_create_internal_property (obj_p, id); is_new = true; } else { is_new = false; } JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (ECMA_PROPERTY_VALUE_PTR (prop_p)->value), size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { ECMA_PROPERTY_VALUE_PTR (prop_p)->value = (uint32_t) ptr_value; } else { ecma_external_pointer_t *handler_p; if (is_new) { handler_p = ecma_alloc_external_pointer (); ECMA_SET_NON_NULL_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->value, handler_p); } else { handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); } *handler_p = ptr_value; } return is_new; } /* ecma_create_external_pointer_property */
/** * Create a property in an object and link it into * the object's properties' linked-list (at start of the list). * * @return pointer to newly created property */ static ecma_property_t * ecma_create_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *name_p, /**< property name */ uint8_t type_and_flags) /**< type and flags, see ecma_property_info_t */ { JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (object_p->property_list_or_bound_object_cp != ECMA_NULL_POINTER) { /* If the first entry is free (deleted), we simply use its value. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, object_p->property_list_or_bound_object_cp); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); if (first_property_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED) { first_property_p->types[0].type_and_flags = type_and_flags; ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; ECMA_SET_POINTER (first_property_pair_p->names_cp[0], name_p); ecma_property_t *property_p = first_property_p->types + 0; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); return property_p; } } /* Otherwise we create a new property pair and use its second value. */ ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); /* Just copy the previous value (no need to decompress, compress). */ first_property_pair_p->header.next_property_cp = object_p->property_list_or_bound_object_cp; first_property_pair_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_DELETED; first_property_pair_p->header.types[1].type_and_flags = type_and_flags; first_property_pair_p->names_cp[0] = ECMA_NULL_POINTER; ECMA_SET_POINTER (first_property_pair_p->names_cp[1], name_p); ecma_set_property_list (object_p, &first_property_pair_p->header); ecma_property_t *property_p = first_property_pair_p->header.types + 1; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); return property_p; } /* ecma_create_property */
/** * [[Get]] ecma Arguments object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 10.6 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_arguments_object_get (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { // 1. ecma_property_t *map_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (map_prop_p)->value); // 2. ecma_property_t *mapped_prop_p = ecma_op_object_get_own_property (map_p, property_name_p); // 3. if (mapped_prop_p == NULL) { /* We don't check for 'caller' (item 3.b) here, because the 'caller' property is defined as non-configurable and it's get/set are set to [[ThrowTypeError]] object */ return ecma_op_general_object_get (obj_p, property_name_p); } else { // 4. return ecma_arguments_get_mapped_arg_value (map_p, mapped_prop_p); } } /* ecma_op_arguments_object_get */
/** * Get value field of an internal property * * @return ecma value */ inline ecma_value_t __attr_always_inline___ ecma_get_internal_property_value (const ecma_property_t *prop_p) /**< property */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_INTERNAL); return ECMA_PROPERTY_VALUE_PTR (prop_p)->value; } /* ecma_get_internal_property_value */
/** * Get value field of named data property * * @return ecma value */ inline ecma_value_t __attr_always_inline___ ecma_get_named_data_property_value (const ecma_property_t *prop_p) /**< property */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); return ECMA_PROPERTY_VALUE_PTR (prop_p)->value; } /* ecma_get_named_data_property_value */
/** * [[GetOwnProperty]] ecma Arguments object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 10.6 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_property_t * ecma_op_arguments_object_get_own_property (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { // 1. ecma_property_t *desc_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); // 2. if (desc_p == NULL) { return desc_p; } // 3. ecma_property_t *map_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (map_prop_p)->value); // 4. ecma_property_t *mapped_prop_p = ecma_op_object_get_own_property (map_p, property_name_p); // 5. if (mapped_prop_p != NULL) { // a. ecma_value_t completion = ecma_arguments_get_mapped_arg_value (map_p, mapped_prop_p); ecma_named_data_property_assign_value (obj_p, desc_p, completion); ecma_free_value (completion); } // 6. return desc_p; } /* ecma_op_arguments_object_get_own_property */
/** * Number object creation operation. * * See also: ECMA-262 v5, 15.7.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ { ecma_value_t conv_to_num_completion = ecma_op_to_number (arg); if (ECMA_IS_VALUE_ERROR (conv_to_num_completion)) { return conv_to_num_completion; } #ifndef CONFIG_DISABLE_NUMBER_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE); #else /* CONFIG_DISABLE_NUMBER_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_NUMBER_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); ECMA_PROPERTY_VALUE_PTR (class_prop_p)->value = LIT_MAGIC_STRING_NUMBER_UL; ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); /* Pass reference (no need to free conv_to_num_completion). */ ecma_set_internal_property_value (prim_value_prop_p, conv_to_num_completion); return ecma_make_object_value (obj_p); } /* ecma_op_create_number_object */
/** * Boolean object creation operation. * * See also: ECMA-262 v5, 15.6.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_boolean_object (ecma_value_t arg) /**< argument passed to the Boolean constructor */ { bool boolean_value = ecma_op_to_boolean (arg); #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE); #else /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); ECMA_PROPERTY_VALUE_PTR (class_prop_p)->value = LIT_MAGIC_STRING_BOOLEAN_UL; ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_value_t prim_value = ecma_make_simple_value (boolean_value ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_set_internal_property_value (prim_value_prop_p, prim_value); return ecma_make_object_value (obj_p); } /* ecma_op_create_boolean_object */
/** * Get setter of named accessor property * * @return pointer to object - setter of the property */ ecma_object_t * ecma_get_named_accessor_property_setter (const ecma_property_t *prop_p) /**< named accessor property */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); return ECMA_GET_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p); } /* ecma_get_named_accessor_property_setter */
/** * Set value field of named data property */ inline void __attr_always_inline___ ecma_set_internal_property_value (ecma_property_t *prop_p, /**< property */ ecma_value_t value) /**< value to set */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_INTERNAL); ECMA_PROPERTY_VALUE_PTR (prop_p)->value = value; } /* ecma_set_internal_property_value */
/** * Set value field of named data property */ inline void __attr_always_inline___ ecma_set_named_data_property_value (ecma_property_t *prop_p, /**< property */ ecma_value_t value) /**< value to set */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); ECMA_PROPERTY_VALUE_PTR (prop_p)->value = value; } /* ecma_set_named_data_property_value */
/** * Set setter of named accessor property */ void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the property's container */ ecma_property_t *prop_p, /**< named accessor property */ ecma_object_t *setter_p) /**< setter object */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); ecma_assert_object_contains_the_property (object_p, prop_p); ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p, setter_p); } /* ecma_set_named_accessor_property_setter */
/** * Assign value to named data property * * Note: * value previously stored in the property is freed */ void ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */ ecma_property_t *prop_p, /**< property */ ecma_value_t value) /**< value to assign */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); ecma_assert_object_contains_the_property (obj_p, prop_p); ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p); ecma_value_assign_value (&prop_value_p->value, value); } /* ecma_named_data_property_assign_value */
/** * 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_value_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 ECMA_PROPERTY_VALUE_PTR (property_p); } /* ecma_get_named_data_property */
/** * Create internal property in an object and link it into * the object's properties' linked-list (at start of the list). * * @return pointer to newly created property */ ecma_property_t * ecma_create_internal_property (ecma_object_t *object_p, /**< the object */ ecma_internal_property_id_t property_id) /**< internal property identifier */ { JERRY_ASSERT (ecma_find_internal_property (object_p, property_id) == NULL); uint8_t id_byte = (uint8_t) (property_id << ECMA_PROPERTY_FLAG_SHIFT); uint8_t type_and_flags = (uint8_t) (ECMA_PROPERTY_TYPE_INTERNAL | id_byte); ecma_property_t *property_p = ecma_create_property (object_p, NULL, type_and_flags); ECMA_PROPERTY_VALUE_PTR (property_p)->value = ECMA_NULL_POINTER; return property_p; } /* ecma_create_internal_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_value_t ret_val; if (prop_p == NULL) { ret_val = ECMA_VALUE_TRUE; } else { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); if (!ecma_is_property_configurable (*prop_p)) { ret_val = ECMA_VALUE_FALSE; } else { ecma_delete_property (lex_env_p, ECMA_PROPERTY_VALUE_PTR (prop_p)); ret_val = ECMA_VALUE_TRUE; } } return ret_val; } 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); return ecma_op_object_delete (binding_obj_p, name_p, false); } } /* ecma_op_delete_binding */
/** * Create internal property with specified identifier and store external pointer in the property. * * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. * * @return true - if property was just created with specified value, * false - otherwise, if property existed before the call, it's value was updated. */ bool ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */ ecma_internal_property_id_t id, /**< identifier of internal * property to create */ ecma_external_pointer_t ptr_value) /**< value to store in the property */ { JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); ecma_value_t *prop_p = ecma_find_internal_property (obj_p, id); bool is_new = (prop_p == NULL); if (is_new) { prop_p = ecma_create_internal_property (obj_p, id); } JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (ECMA_PROPERTY_VALUE_PTR (prop_p)->value), size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes); #ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY *prop_p = (ecma_value_t) ptr_value; #else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ ecma_external_pointer_t *handler_p; if (is_new) { handler_p = ecma_alloc_external_pointer (); ECMA_SET_NON_NULL_POINTER (*prop_p, handler_p); } else { handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, *prop_p); } *handler_p = ptr_value; #endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ return is_new; } /* ecma_create_external_pointer_property */
/** * Free memory associated with external pointer stored in the property * * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. */ void ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */ { JERRY_ASSERT (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_NATIVE_CODE || ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE || ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { /* no additional memory was allocated for the pointer storage */ } else { ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); ecma_dealloc_external_pointer (handler_p); } } /* ecma_free_external_pointer_in_property */
/** * [[Delete]] ecma Arguments object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 10.6 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_arguments_object_delete (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ bool is_throw) /**< flag that controls failure handling */ { // 1. ecma_property_t *map_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (map_prop_p)->value); // 2. ecma_property_t *mapped_prop_p = ecma_op_object_get_own_property (map_p, property_name_p); // 3. ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (delete_in_args_ret, ecma_op_general_object_delete (obj_p, property_name_p, is_throw), ret_value); if (ecma_is_value_true (delete_in_args_ret)) { if (mapped_prop_p != NULL) { ecma_value_t delete_in_map_completion = ecma_op_object_delete (map_p, property_name_p, false); JERRY_ASSERT (ecma_is_value_true (delete_in_map_completion)); } ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else { JERRY_ASSERT (ecma_is_value_boolean (delete_in_args_ret)); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } ECMA_FINALIZE (delete_in_args_ret); return ret_value; } /* ecma_op_arguments_object_delete */
/** * Free memory associated with external pointer stored in the property * * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. */ void ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */ { JERRY_ASSERT (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE || ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_p) == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); #ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY /* no additional memory was allocated for the pointer storage */ #else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->value); ecma_dealloc_external_pointer (handler_p); #endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */ } /* ecma_free_external_pointer_in_property */
/** * Get value of function's argument mapped to index of Arguments object. * * Note: * The procedure emulates execution of function described by MakeArgGetter * * @return ecma value * Returned value must be freed with ecma_free_value */ static ecma_value_t ecma_arguments_get_mapped_arg_value (ecma_object_t *map_p, /**< [[ParametersMap]] object */ ecma_property_t *arg_name_prop_p) /**< property of [[ParametersMap]] corresponding to index and value equal to mapped argument's name */ { ecma_property_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (scope_prop_p)->value); JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); ecma_value_t arg_name_prop_value = ecma_get_named_data_property_value (arg_name_prop_p); ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name_prop_value); ecma_value_t completion = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion)); return completion; } /* ecma_arguments_get_mapped_arg_value */
/** * List names of a String object's lazy instantiated properties * * See also: * ecma_op_string_object_get_own_property * * @return string values collection */ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ bool separate_enumerable, /**< true - list enumerable properties * into main collection, * and non-enumerable to collection of * 'skipped non-enumerable' properties, * false - list all properties into main * collection. */ ecma_collection_header_t *main_collection_p, /**< 'main' * collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING); ecma_collection_header_t *for_enumerable_p = main_collection_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? main_collection_p : non_enum_collection_p; (void) for_non_enumerable_p; ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ecma_string_t *prim_value_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, ECMA_PROPERTY_VALUE_PTR (prim_value_prop_p)->value); ecma_length_t length = ecma_string_get_length (prim_value_str_p); for (ecma_length_t i = 0; i < length; i++) { ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ ecma_append_to_values_collection (for_enumerable_p, ecma_make_string_value (name_p), true); ecma_deref_ecma_string (name_p); } } /* ecma_op_string_list_lazy_property_names */
/** * Standard ecma-error object constructor. * * @return pointer to ecma-object representing specified error * with reference counter set to one. */ ecma_object_t * ecma_new_standard_error (ecma_standard_error_t error_type) /**< native error type */ { #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS ecma_builtin_id_t prototype_id = ECMA_BUILTIN_ID__COUNT; switch (error_type) { case ECMA_ERROR_COMMON: { prototype_id = ECMA_BUILTIN_ID_ERROR_PROTOTYPE; break; } case ECMA_ERROR_EVAL: { prototype_id = ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE; break; } case ECMA_ERROR_RANGE: { prototype_id = ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE; break; } case ECMA_ERROR_REFERENCE: { prototype_id = ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE; break; } case ECMA_ERROR_TYPE: { prototype_id = ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE; break; } case ECMA_ERROR_URI: { prototype_id = ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE; break; } case ECMA_ERROR_SYNTAX: { prototype_id = ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE; break; } } ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id); ecma_object_t *new_error_obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (new_error_obj_p, ECMA_INTERNAL_PROPERTY_CLASS); ECMA_PROPERTY_VALUE_PTR (class_prop_p)->value = LIT_MAGIC_STRING_ERROR_UL; return new_error_obj_p; #else /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS */ (void) error_type; return ecma_builtin_get (ECMA_BUILTIN_ID_COMPACT_PROFILE_ERROR); #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ERROR_BUILTINS */ } /* ecma_new_standard_error */
/** * Mark referenced object from property */ static void ecma_gc_mark_property (ecma_property_t *property_p) /**< property */ { switch (ECMA_PROPERTY_GET_TYPE (*property_p)) { case ECMA_PROPERTY_TYPE_NAMEDDATA: { ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (property_p)->value; 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_TYPE_NAMEDACCESSOR: { ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (prop_value_p); ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (prop_value_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_TYPE_INTERNAL: { uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value; switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p)) { case ECMA_INTERNAL_PROPERTY_ECMA_VALUE: /* an ecma_value_t except object */ case ECMA_INTERNAL_PROPERTY_DATE_FLOAT: /* pointer to a ecma_number_t */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: /* pointer to a regexp bytecode array */ 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_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */ { break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: /* an ecma value */ { if (ecma_is_value_object (property_value)) { ecma_object_t *obj_p = ecma_get_object_from_value (property_value); ecma_gc_set_object_visited (obj_p, true); } break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: /* a collection of ecma values */ { ecma_collection_header_t *bound_arg_list_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t, property_value); ecma_collection_iterator_t bound_args_iterator; ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p); for (ecma_length_t i = 0; i < bound_arg_list_p->unit_number; i++) { bool is_moved = ecma_collection_iterator_next (&bound_args_iterator); JERRY_ASSERT (is_moved); if (ecma_is_value_object (*bound_args_iterator.current_value_p)) { ecma_object_t *obj_p = ecma_get_object_from_value (*bound_args_iterator.current_value_p); ecma_gc_set_object_visited (obj_p, true); } } break; } case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */ case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */ case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */ { ecma_object_t *obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, property_value); ecma_gc_set_object_visited (obj_p, true); break; } case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type, * but number of the real internal property types */ { JERRY_UNREACHABLE (); break; } } break; } default: { JERRY_UNREACHABLE (); break; } } } /* ecma_gc_mark_property */
/* * 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 */
/** * The RegExp.prototype object's 'compile' routine * * See also: * ECMA-262 v5, B.2.5.1 * * @return undefined - if compiled successfully * error ecma value - otherwise * * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument */ ecma_value_t pattern_arg, /**< pattern or RegExp object */ ecma_value_t flags_arg) /**< flags */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_is_value_object (this_arg) || ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_REGEXP_UL) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Incomplete RegExp type")); } else { ecma_string_t *pattern_string_p = NULL; uint16_t flags = 0; if (ecma_is_value_object (pattern_arg) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_arg)) == LIT_MAGIC_STRING_REGEXP_UL) { if (!ecma_is_value_undefined (flags_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp compile.")); } else { /* Compile from existing RegExp pbject. */ ecma_object_t *target_p = ecma_get_object_from_value (pattern_arg); /* Get source. */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *prop_p = ecma_op_object_get_property (target_p, magic_string_p); pattern_string_p = ecma_get_string_from_value (ecma_get_named_data_property_value (prop_p)); ecma_deref_ecma_string (magic_string_p); /* Get flags. */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_GLOBAL; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_IGNORE_CASE; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_MULTILINE; } ecma_deref_ecma_string (magic_string_p); ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *this_obj_p = ecma_get_object_from_value (obj_this); /* Get bytecode property. */ ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* TODO: We currently have to re-compile the bytecode, because * we can't copy it without knowing its length. */ const re_compiled_code_t *new_bc_p = NULL; ecma_value_t bc_comp = re_compile_bytecode (&new_bc_p, pattern_string_p, flags); /* Should always succeed, since we're compiling from a source that has been compiled previously. */ JERRY_ASSERT (ecma_is_value_empty (bc_comp)); re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ecma_get_internal_property_value (bc_prop_p)); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (bc_prop_p)->value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ECMA_FINALIZE (obj_this); } } else { /* Get source string. */ if (!ecma_is_value_undefined (pattern_arg)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_arg), ret_value); if (ecma_string_is_empty (ecma_get_string_from_value (regexp_str_value))) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_get_string_from_value (regexp_str_value); ecma_ref_ecma_string (pattern_string_p); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } /* Parse flags. */ if (ecma_is_value_empty (ret_value) && !ecma_is_value_undefined (flags_arg)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_arg), ret_value); ECMA_TRY_CATCH (flags_dummy, re_parse_regexp_flags (ecma_get_string_from_value (flags_str_value), &flags), ret_value); ECMA_FINALIZE (flags_dummy); ECMA_FINALIZE (flags_str_value); } if (ecma_is_value_empty (ret_value)) { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *this_obj_p = ecma_get_object_from_value (obj_this); ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Try to compile bytecode from new source. */ const re_compiled_code_t *new_bc_p = NULL; ECMA_TRY_CATCH (bc_dummy, re_compile_bytecode (&new_bc_p, pattern_string_p, flags), ret_value); re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ecma_get_internal_property_value (bc_prop_p)); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (bc_prop_p)->value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ECMA_FINALIZE (bc_dummy); ECMA_FINALIZE (obj_this); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } } } return ret_value; } /* ecma_builtin_regexp_prototype_compile */