/** * Common function to create a formatted JSON string. * * See also: * ECMA-262 v5, 15.12.3 * * Used by: * - ecma_builtin_json_object step 10.b * - ecma_builtin_json_array step 10.b * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/ ecma_string_t *right_bracket_p, /**< right bracket*/ ecma_string_t *stepback_p, /**< stepback*/ ecma_collection_header_t *partial_p, /**< key-value pairs*/ ecma_json_stringify_context_t *context_p) /**< context*/ { /* 10.b */ ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); ecma_string_t *line_feed_p = ecma_get_magic_string (LIT_MAGIC_STRING_NEW_LINE_CHAR); ecma_string_t *properties_str_p; ecma_string_t *separator_p; /* 10.b.i */ ecma_string_t *tmp_str_p = ecma_concat_ecma_strings (comma_str_p, line_feed_p); ecma_deref_ecma_string (comma_str_p); separator_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (separator_p, context_p->indent_str_p); ecma_deref_ecma_string (separator_p); separator_p = tmp_str_p; /* 10.b.ii */ properties_str_p = ecma_builtin_helper_json_create_separated_properties (partial_p, separator_p); ecma_deref_ecma_string (separator_p); /* 10.b.iii */ ecma_string_t *final_str_p; tmp_str_p = ecma_concat_ecma_strings (left_bracket_p, line_feed_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, context_p->indent_str_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, properties_str_p); ecma_deref_ecma_string (final_str_p); ecma_deref_ecma_string (properties_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, line_feed_p); ecma_deref_ecma_string (line_feed_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, stepback_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, right_bracket_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; return ecma_make_string_value (final_str_p); } /* ecma_builtin_helper_json_create_formatted_json */
/** * Implementation of 'CreateArrayFromList' specialized for iterators * * See also: * ECMA-262 v6, 7.3.16. * * Note: * Returned value must be freed with ecma_free_value. * * @return new array object */ ecma_value_t ecma_create_array_from_iter_element (ecma_value_t value, /**< value */ ecma_value_t index_value) /**< iterator index */ { /* 2. */ ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); /* 3 - 4. */ for (uint32_t index = 0; index < 2; index++) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); /* 4.a */ ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, (index == 0) ? index_value : value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, false); /* Failure handling */ /* 4.b */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); } /* 5. */ return new_array; } /* ecma_create_array_from_iter_element */
/** * The Date.prototype object's 'toJSON' routine * * See also: * ECMA-262 v5, 15.9.5.44 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_to_json (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< key */ { JERRY_UNUSED (arg); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (obj, ecma_op_to_object (this_arg), ret_value); /* 2. */ ECMA_TRY_CATCH (tv, ecma_op_to_primitive (obj, ECMA_PREFERRED_TYPE_NUMBER), ret_value); /* 3. */ if (ecma_is_value_number (tv)) { ecma_number_t num_value = ecma_get_number_from_value (tv); if (ecma_number_is_nan (num_value) || ecma_number_is_infinity (num_value)) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL); } } if (ecma_is_value_empty (ret_value)) { ecma_string_t *to_iso_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_ISO_STRING_UL); ecma_object_t *value_obj_p = ecma_get_object_from_value (obj); /* 4. */ ECMA_TRY_CATCH (to_iso, ecma_op_object_get (value_obj_p, to_iso_str_p), ret_value); /* 5. */ if (!ecma_op_is_callable (to_iso)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } /* 6. */ else { ecma_object_t *to_iso_obj_p = ecma_get_object_from_value (to_iso); ret_value = ecma_op_function_call (to_iso_obj_p, this_arg, NULL, 0); } ECMA_FINALIZE (to_iso); ecma_deref_ecma_string (to_iso_str_p); } ECMA_FINALIZE (tv); ECMA_FINALIZE (obj); return ret_value; } /* ecma_builtin_date_prototype_to_json */
/** * External function object creation operation. * * Note: * external function object is implementation-defined object type * that represent functions implemented in native code, using Embedding API * * @return pointer to newly created external function object */ ecma_object_t * ecma_op_create_external_function_object (ecma_external_pointer_t code_p) /**< pointer to external native handler */ { ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *function_obj_p; function_obj_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION); ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION type. * * See also: ecma_object_get_class_name */ ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p; ext_func_obj_p->u.external_function = code_p; ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE); ecma_builtin_helper_def_prop (function_obj_p, magic_string_prototype_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), true, /* Writable */ false, /* Enumerable */ false, /* Configurable */ false); /* Failure handling */ ecma_deref_ecma_string (magic_string_prototype_p); return function_obj_p; } /* ecma_op_create_external_function_object */
/** * Free the ecma value */ void ecma_free_value (ecma_value_t value) /**< value description */ { switch (ecma_get_value_type_field (value)) { case ECMA_TYPE_SIMPLE: { /* doesn't hold additional memory */ break; } case ECMA_TYPE_NUMBER: { ecma_number_t *number_p = ecma_get_number_from_value (value); ecma_dealloc_number (number_p); break; } case ECMA_TYPE_STRING: { ecma_string_t *string_p = ecma_get_string_from_value (value); ecma_deref_ecma_string (string_p); break; } case ECMA_TYPE_OBJECT: { ecma_deref_object (ecma_get_object_from_value (value)); break; } } } /* ecma_free_value */
/** * Free specified ECMA-reference. * * Warning: * freeing invalidates all copies of the reference. */ void ecma_free_reference (ecma_reference_t ref) /**< reference */ { ecma_free_value (ref.base); ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp)); } /* ecma_free_reference */
/** * Delete the object's property. * * Warning: specified property must be owned by specified object. */ void ecma_delete_property (ecma_object_t *object_p, /**< object */ ecma_property_t *prop_p) /**< property */ { ecma_property_header_t *cur_prop_p = ecma_get_property_list (object_p); ecma_property_header_t *prev_prop_p = NULL; while (true) { JERRY_ASSERT (cur_prop_p != NULL); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p)); ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p; for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { if ((cur_prop_p->types + i) == prop_p) { ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]); ecma_free_property (object_p, name_p, cur_prop_p->types + i); prop_pair_p->names_cp[i] = ECMA_NULL_POINTER; if (name_p != NULL) { ecma_deref_ecma_string (name_p); } JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (cur_prop_p->types[1 - i].type_and_flags != ECMA_PROPERTY_TYPE_DELETED) { /* The other property is still valid. */ return; } JERRY_ASSERT (cur_prop_p->types[i].type_and_flags == ECMA_PROPERTY_TYPE_DELETED); if (prev_prop_p == NULL) { object_p->property_list_or_bound_object_cp = cur_prop_p->next_property_cp; } else { prev_prop_p->next_property_cp = cur_prop_p->next_property_cp; } ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p); return; } } prev_prop_p = cur_prop_p; cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t, cur_prop_p->next_property_cp); } } /* ecma_delete_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 */
/** * 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 */
/** * The RegExp.prototype object's 'exec' routine * * See also: * ECMA-262 v5, 15.10.6.2 * * @return array object containing the results - if the matched * null - otherwise * * May raise error, so returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { 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_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ECMA_TRY_CATCH (input_str_value, ecma_op_to_string (arg), ret_value); ecma_property_t *bytecode_prop_p; ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); bytecode_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); void *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, ecma_get_internal_property_value (bytecode_prop_p)); if (bytecode_p == NULL) { /* Missing bytecode means empty RegExp: '/(?:)/', so always return empty string. */ ecma_string_t *capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_value_t arguments_list[1]; arguments_list[0] = ecma_make_string_value (capture_str_p); ret_value = ecma_op_create_array_object (arguments_list, 1, false); ecma_deref_ecma_string (capture_str_p); re_set_result_array_properties (ecma_get_object_from_value (ret_value), ecma_get_string_from_value (input_str_value), 1, 0); } else { ret_value = ecma_regexp_exec_helper (obj_this, input_str_value, false); } ECMA_FINALIZE (input_str_value); ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_regexp_prototype_exec */
/** * Checks whether the property name is "length". * * @return true if the property name is length * false otherwise */ static inline bool __attr_always_inline___ ecma_op_general_object_property_name_is_length (ecma_string_t *property_name_p) /**< property name */ { ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); bool property_name_is_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); return property_name_is_length; } /* ecma_op_general_object_property_name_is_length */
/** * Common function to concatenate key-value pairs into an ecma-string. * * See also: * ECMA-262 v5, 15.12.3 * * Used by: * - ecma_builtin_helper_json_create_formatted_json step 10.b.ii * - ecma_builtin_helper_json_create_non_formatted_json step 10.a.i * * @return pointer to ecma-string * Returned value must be freed with ecma_deref_ecma_string. */ ecma_string_t * ecma_builtin_helper_json_create_separated_properties (ecma_collection_header_t *partial_p, /**< key-value pairs*/ ecma_string_t *separator_p) /**< separator*/ { ecma_string_t *properties_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_string_t *tmp_str_p; ecma_collection_iterator_t iterator; ecma_collection_iterator_init (&iterator, partial_p); uint32_t index = 0; while (ecma_collection_iterator_next (&iterator)) { ecma_value_t name_value = *iterator.current_value_p; ecma_string_t *current_p = ecma_get_string_from_value (name_value); if (index == 0) { index++; tmp_str_p = ecma_concat_ecma_strings (properties_str_p, current_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; continue; } tmp_str_p = ecma_concat_ecma_strings (properties_str_p, separator_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (properties_str_p, current_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; } return properties_str_p; } /* ecma_builtin_helper_json_create_separated_properties */
/** * Construct a Function object for specified built-in routine * * See also: ECMA-262 v5, 15 * * @return pointer to constructed Function object */ ecma_object_t* ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**< identifier of built-in object that initially contains property with the routine */ uint16_t routine_id, /**< builtin-wide identifier of the built-in object's routine property */ ecma_number_t length_prop_num_value) /**< ecma-number - value of 'length' property of function object to create */ { ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *func_obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); ecma_deref_object (prototype_obj_p); ecma_set_object_is_builtin (func_obj_p, true); uint64_t packed_value = jrt_set_bit_field_value (0, builtin_id, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH); packed_value = jrt_set_bit_field_value (packed_value, routine_id, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS, ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH); ecma_property_t *routine_id_prop_p = ecma_create_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID); JERRY_ASSERT ((uint32_t) packed_value == packed_value); routine_id_prop_p->u.internal_property.value = (uint32_t) packed_value; ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_create_named_data_property (func_obj_p, magic_string_length_p, false, false, false); ecma_deref_ecma_string (magic_string_length_p); ecma_number_t* len_p = ecma_alloc_number (); *len_p = length_prop_num_value; ecma_set_named_data_property_value (len_prop_p, ecma_make_number_value (len_p)); return func_obj_p; } /* ecma_builtin_make_function_object_for_routine */
/** * 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_with_message (ecma_standard_error_t error_type, /**< native error type */ ecma_string_t *message_string_p) /**< message string */ { ecma_object_t *new_error_obj_p = ecma_new_standard_error (error_type); ecma_string_t *message_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE); ecma_property_t *prop_p = ecma_create_named_data_property (new_error_obj_p, message_magic_string_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE); ecma_ref_ecma_string (message_string_p); ecma_set_named_data_property_value (prop_p, ecma_make_string_value (message_string_p)); ecma_deref_ecma_string (message_magic_string_p); return new_error_obj_p; } /* ecma_new_standard_error_with_message */
/** * Invalidate specified LCache entry */ static void ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to invalidate */ { JERRY_ASSERT (entry_p != NULL); JERRY_ASSERT (entry_p->object_cp != ECMA_NULL_POINTER); ecma_deref_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, entry_p->object_cp)); entry_p->object_cp = ECMA_NULL_POINTER; ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, entry_p->prop_name_cp)); if (entry_p->prop_p != NULL) { ecma_set_property_lcached (entry_p->prop_p, false); } } /* ecma_lcache_invalidate_entry */
/** * External function object creation operation. * * Note: * external function object is implementation-defined object type * that represent functions implemented in native code, using Embedding API * * @return pointer to newly created external function object */ ecma_object_t* ecma_op_create_external_function_object (ecma_external_pointer_t code_p) /**< pointer to external native handler */ { ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *function_obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION); ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION type. * * See also: ecma_object_get_class_name */ bool is_created = ecma_create_external_pointer_property (function_obj_p, ECMA_INTERNAL_PROPERTY_NATIVE_CODE, (ecma_external_pointer_t) code_p); JERRY_ASSERT (is_created); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; } ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE); ecma_op_object_define_own_property (function_obj_p, magic_string_prototype_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_prototype_p); return function_obj_p; } /* ecma_op_create_external_function_object */
/** * Deletes a variable. * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t vm_op_delete_var (lit_cpointer_t name_literal, /**< name literal */ ecma_object_t *lex_env_p, /**< lexical environment */ bool is_strict) /**< strict mode */ { ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *var_name_str_p; var_name_str_p = ecma_new_ecma_string_from_lit_cp (name_literal); ecma_reference_t ref = ecma_op_get_identifier_reference (lex_env_p, var_name_str_p, is_strict); JERRY_ASSERT (!ref.is_strict); if (ecma_is_value_undefined (ref.base)) { completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else { ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p); JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p)); ECMA_TRY_CATCH (delete_op_ret_val, ecma_op_delete_binding (ref_base_lex_env_p, ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp)), completion_value); completion_value = delete_op_ret_val; ECMA_FINALIZE (delete_op_ret_val); } ecma_free_reference (ref); ecma_deref_ecma_string (var_name_str_p); return completion_value; } /* vm_op_delete_var */
/** * The Object.keys and Object.getOwnPropertyNames routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return ecma value - Array of property names. * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ bool only_enumerable_properties) /**< list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); uint32_t index = 0; ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, only_enumerable_properties, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter)) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, *iter.current_value_p, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); index++; } ecma_free_values_collection (props_p, true); return new_array; } /* ecma_builtin_helper_object_get_properties */
/** * List names of a String object's lazy instantiated properties * * @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_CLASS); ecma_collection_header_t *for_enumerable_p = main_collection_p; ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL); ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.class_prop.u.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), 0); ecma_deref_ecma_string (name_p); } ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH), 0); } /* ecma_op_string_list_lazy_property_names */
/** * Raise a standard ecma-error with the given type and message. * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_raise_standard_error (ecma_standard_error_t error_type, /**< error type */ const lit_utf8_byte_t *msg_p) /**< error message */ { ecma_object_t *error_obj_p; if (msg_p != NULL) { ecma_string_t *error_msg_p = ecma_new_ecma_string_from_utf8 (msg_p, lit_zt_utf8_string_size (msg_p)); error_obj_p = ecma_new_standard_error_with_message (error_type, error_msg_p); ecma_deref_ecma_string (error_msg_p); } else { error_obj_p = ecma_new_standard_error (error_type); } return ecma_make_error_obj_value (error_obj_p); } /* ecma_raise_standard_error */
/** * 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; JERRY_UNUSED (for_non_enumerable_p); ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_string_t *prim_value_str_p; prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p)); 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 */
/** * Send string representation of exception to the client. * * @return true - if the data sent successfully to the debugger client, * false - otherwise */ bool jerry_debugger_send_exception_string (void) { ecma_string_t *string_p = NULL; ecma_value_t exception_value = JERRY_CONTEXT (error_value); if (ecma_is_value_object (exception_value)) { string_p = jerry_debugger_exception_object_to_string (exception_value); if (string_p == NULL) { string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (exception_value)); } } else if (ecma_is_value_string (exception_value)) { string_p = ecma_get_string_from_value (exception_value); ecma_ref_ecma_string (string_p); } else { exception_value = ecma_op_to_string (exception_value); string_p = ecma_get_string_from_value (exception_value); } ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size); bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR, JERRY_DEBUGGER_NO_SUBTYPE, string_data_p, string_size); ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size); ecma_deref_ecma_string (string_p); return result; } /* jerry_debugger_send_exception_string */
/** * Convert decimal value to 4 digit hexadecimal string value. * * See also: * ECMA-262 v5, 15.12.3 * * Used by: * - ecma_builtin_json_quote step 2.c.iii * * @return pointer to ecma-string * Returned value must be freed with ecma_deref_ecma_string. */ ecma_string_t * ecma_builtin_helper_json_create_hex_digit_ecma_string (uint8_t value) /**< value in decimal*/ { /* 2.c.iii */ ecma_string_t *hex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); JMEM_DEFINE_LOCAL_ARRAY (hex_buff, 4, lit_utf8_byte_t); for (uint32_t i = 0; i < 4; i++) { uint8_t remainder = value % 16; lit_utf8_byte_t ch = ' '; if (remainder < 10) { ch = (lit_utf8_byte_t) (LIT_CHAR_0 + remainder); } else { uint8_t a = (uint8_t) (remainder - 10); ch = (lit_utf8_byte_t) (LIT_CHAR_LOWERCASE_A + a); } hex_buff[3 - i] = ch; value = value / 16; } ecma_deref_ecma_string (hex_str_p); hex_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) hex_buff, 4); JMEM_FINALIZE_LOCAL_ARRAY (hex_buff); JERRY_ASSERT (ecma_string_get_length (hex_str_p)); return hex_str_p; } /* ecma_builtin_helper_json_create_hex_digit_ecma_string */
/** * 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 */ void ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ ecma_property_t *property_p) /**< property value */ { ecma_value_t *map_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p); ecma_value_t arg_name = ecma_op_object_find (map_p, property_name_p); if (!ecma_is_value_found (arg_name)) { return; } ecma_value_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, *scope_prop_p); JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name); ecma_value_t value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); ecma_deref_ecma_string (arg_name_p); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); ecma_named_data_property_assign_value (object_p, property_p, value); ecma_free_value (value); /* These properties cannot be cached. This is a temporary * workaround until the property management is fully rewritten. */ if (ecma_is_property_lcached (property_p)) { ecma_lcache_invalidate (object_p, property_name_p, property_p); } } /* ecma_arguments_update_mapped_arg_value */
/** * The Object.prototype object's 'toLocaleString' routine * * See also: * ECMA-262 v5, 15.2.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */ { ecma_value_t return_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (obj_val, ecma_op_to_object (this_arg), return_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_val); ecma_string_t *to_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_STRING_UL); /* 2. */ ECMA_TRY_CATCH (to_string_val, ecma_op_object_get (obj_p, to_string_magic_string_p), return_value); /* 3. */ if (!ecma_op_is_callable (to_string_val)) { return_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { /* 4. */ ecma_object_t *to_string_func_obj_p = ecma_get_object_from_value (to_string_val); return_value = ecma_op_function_call (to_string_func_obj_p, this_arg, NULL, 0); } ECMA_FINALIZE (to_string_val); ecma_deref_ecma_string (to_string_magic_string_p); ECMA_FINALIZE (obj_val); return return_value; } /* ecma_builtin_object_prototype_object_to_locale_string */
/** * The Object.prototype object's 'toLocaleString' routine * * See also: * ECMA-262 v5, 15.2.4.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */ { ecma_completion_value_t return_value = ecma_make_empty_completion_value (); /* 1. */ ECMA_TRY_CATCH (obj_val, ecma_op_to_object (this_arg), return_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_val); ecma_string_t *to_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_STRING_UL); /* 2. */ ECMA_TRY_CATCH (to_string_val, ecma_op_object_get (obj_p, to_string_magic_string_p), return_value); /* 3. */ if (!ecma_op_is_callable (to_string_val)) { return_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { /* 4. */ ecma_object_t *to_string_func_obj_p = ecma_get_object_from_value (to_string_val); return_value = ecma_op_function_call (to_string_func_obj_p, this_arg, NULL); } ECMA_FINALIZE (to_string_val); ecma_deref_ecma_string (to_string_magic_string_p); ECMA_FINALIZE (obj_val); return return_value; } /* ecma_builtin_object_prototype_object_to_locale_string */
/** * Array object creation operation. * * See also: ECMA-262 v5, 15.4.2.1 * ECMA-262 v5, 15.4.2.2 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to Array constructor */ ecma_length_t arguments_list_len, /**< length of the arguments' list */ bool is_treat_single_arg_as_length) /**< if the value is true, arguments_list_len is 1 and single argument is Number, then treat the single argument as new Array's length rather than as single item of the Array */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); uint32_t length; const ecma_value_t *array_items_p; ecma_length_t array_items_count; if (is_treat_single_arg_as_length && arguments_list_len == 1 && ecma_is_value_number (arguments_list_p[0])) { ecma_number_t *num_p = ecma_get_number_from_value (arguments_list_p[0]); uint32_t num_uint32 = ecma_number_to_uint32 (*num_p); if (*num_p != ecma_uint32_to_number (num_uint32)) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { length = num_uint32; array_items_p = NULL; array_items_count = 0; } } else { length = arguments_list_len; array_items_p = arguments_list_p; array_items_count = arguments_list_len; } #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN */ ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ARRAY_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (array_prototype_obj_p, true, ECMA_OBJECT_TYPE_ARRAY); ecma_deref_object (array_prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. * * See also: ecma_object_get_class_name */ ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_number_t *length_num_p = ecma_alloc_number (); *length_num_p = ecma_uint32_to_number (length); ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, length_magic_string_p, true, false, false); ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_num_p)); ecma_deref_ecma_string (length_magic_string_p); for (uint32_t index = 0; index < array_items_count; index++) { if (ecma_is_value_array_hole (array_items_p[index])) { continue; } ecma_string_t *item_name_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_builtin_helper_def_prop (obj_p, item_name_string_p, array_items_p[index], true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ ecma_deref_ecma_string (item_name_string_p); } return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } /* ecma_op_create_array_object */
/** * [[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 completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_array_object_define_own_property (ecma_object_t *obj_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 */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); // 1. 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); JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA); // 2. ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); ecma_number_t *num_p = ecma_get_number_from_value (old_len_value); uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p); // 3. bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_property_name_equal_length) { // a. if (!property_desc_p->is_value_defined) { // i. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } ecma_number_t new_len_num; // c. ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value); if (ecma_is_completion_value_throw (completion)) { return completion; } JERRY_ASSERT (ecma_is_completion_value_normal (completion) && ecma_is_value_number (ecma_get_completion_value_value (completion))); new_len_num = *ecma_get_number_from_completion_value (completion); ecma_free_completion_value (completion); uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); // d. if (ecma_uint32_to_number (new_len_uint32) != new_len_num) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { // b., e. ecma_number_t *new_len_num_p = ecma_alloc_number (); *new_len_num_p = new_len_num; ecma_property_descriptor_t new_len_property_desc = *property_desc_p; new_len_property_desc.value = ecma_make_number_value (new_len_num_p); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // f. if (new_len_uint32 >= old_len_uint32) { // i. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ret_value = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); } else { // g. if (!ecma_is_property_writable (len_prop_p)) { ret_value = ecma_reject (is_throw); } else { // h. bool new_writable; if (!new_len_property_desc.is_writable_defined || new_len_property_desc.is_writable) { new_writable = true; } else { // ii. new_writable = false; // iii. new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = true; } // j. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); /* Handling normal false and throw values */ if (!ecma_is_completion_value_normal_true (succeeded)) { JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded) || ecma_is_completion_value_throw (succeeded)); // k. ret_value = succeeded; } else { // l JERRY_ASSERT (new_len_uint32 < old_len_uint32); /* * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated */ bool is_reduce_succeeded = true; ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, true, false, false); ecma_length_t array_index_props_num = array_index_props_p->unit_number; MEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, array_index_props_p); uint32_t array_index_values_pos = 0; while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); uint32_t index; bool is_index = ecma_string_get_array_index (property_name_p, &index); JERRY_ASSERT (is_index); JERRY_ASSERT (index < old_len_uint32); array_index_values_p[array_index_values_pos++] = index; } JERRY_ASSERT (array_index_values_pos == array_index_props_num); while (array_index_values_pos != 0 && array_index_values_p[--array_index_values_pos] >= new_len_uint32) { uint32_t index = array_index_values_p[array_index_values_pos]; // ii. ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p, index_string_p, false); ecma_deref_ecma_string (index_string_p); if (ecma_is_completion_value_normal_false (delete_succeeded)) { // iii. new_len_uint32 = (index + 1u); ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value); // 1. *new_len_num_p = ecma_uint32_to_number (index + 1u); // 2. if (!new_writable) { new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = false; } // 3. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); is_reduce_succeeded = false; break; } } MEM_FINALIZE_LOCAL_ARRAY (array_index_values_p); ecma_free_values_collection (array_index_props_p, true); if (!is_reduce_succeeded) { ret_value = ecma_reject (is_throw); } else { // m. if (!new_writable) { ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); prop_desc_not_writable.is_writable_defined = true; prop_desc_not_writable.is_writable = false; ecma_completion_value_t completion_set_not_writable; magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &prop_desc_not_writable, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable)); } ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } } } } ecma_dealloc_number (new_len_num_p); return ret_value; } JERRY_UNREACHABLE (); } else { // 4.a. uint32_t index; if (!ecma_string_get_array_index (property_name_p, &index)) { // 5. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } // 4. // b. if (index >= old_len_uint32 && !ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } // c. ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, false); // d. JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded) || ecma_is_completion_value_normal_false (succeeded)); if (ecma_is_completion_value_normal_false (succeeded)) { return ecma_reject (is_throw); } // e. if (index >= old_len_uint32) { // i., ii. ecma_number_t *num_p = ecma_alloc_number (); *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE); ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p)); ecma_dealloc_number (num_p); } // f. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } JERRY_UNREACHABLE (); } /* ecma_op_array_object_define_own_property */
/** * Helper function for concatenating an ecma_value_t to an Array. * * See also: * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c * * Used by: * - The Array.prototype.concat routine. * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */ uint32_t *length_p, /**< in-out: array's length */ ecma_value_t value) /**< value to concat */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 5.b */ if (ecma_is_value_object (value) && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)) { ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 5.b.ii */ ECMA_TRY_CATCH (arg_len_value, ecma_op_object_get (ecma_get_object_from_value (value), magic_string_length_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value); uint32_t arg_len = ecma_number_to_uint32 (arg_len_number); /* 5.b.iii */ for (uint32_t array_index = 0; array_index < arg_len && ecma_is_completion_value_empty (ret_value); array_index++) { ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index); /* 5.b.iii.2 */ if (ecma_op_object_get_property (ecma_get_object_from_value (value), array_index_string_p) != NULL) { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index); /* 5.b.iii.3.a */ ECMA_TRY_CATCH (get_value, ecma_op_object_get (ecma_get_object_from_value (value), array_index_string_p), ret_value); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = get_value; prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } /* 5.b.iii.3.b */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p, new_array_index_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp)); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (new_array_index_string_p); } ecma_deref_ecma_string (array_index_string_p); } *length_p += arg_len; ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number); ECMA_FINALIZE (arg_len_value); ecma_deref_ecma_string (magic_string_length_p); } else { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = value; prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } /* 5.c.i */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p, new_array_index_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp)); ecma_deref_ecma_string (new_array_index_string_p); } if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_builtin_helper_array_concat_value */
/** * The Object.keys and Object.getOwnPropertyName routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return completion value - Array of property names. * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */ bool only_enumerable_properties) /** < list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_completion_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (ecma_is_completion_value_normal (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array); uint32_t index = 0; for (ecma_property_t *property_p = ecma_get_property_list (obj_p); property_p != NULL; property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p)) { ecma_string_t *property_name_p; if (property_p->type == ECMA_PROPERTY_NAMEDDATA) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_p->u.named_data_property.name_p); } else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_p->u.named_accessor_property.name_p); } else { continue; } if (only_enumerable_properties && !ecma_is_property_enumerable (property_p)) { continue; } JERRY_ASSERT (property_name_p != NULL); ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_property_descriptor_t item_prop_desc = ecma_make_empty_property_descriptor (); { item_prop_desc.is_value_defined = true; item_prop_desc.value = ecma_make_string_value (property_name_p); item_prop_desc.is_writable_defined = true; item_prop_desc.is_writable = true; item_prop_desc.is_enumerable_defined = true; item_prop_desc.is_enumerable = true; item_prop_desc.is_configurable_defined = true; item_prop_desc.is_configurable = true; } ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_p, index_string_p, &item_prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)); ecma_free_completion_value (completion); ecma_deref_ecma_string (index_string_p); index++; } return new_array; } /* ecma_builtin_helper_object_get_properties */