/** * Helper function for using [[DefineOwnProperty]]. * * See also: * ECMA-262 v5, 8.12.9 * ECMA-262 v5, 15.4.5.1 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */ ecma_string_t *index_p, /**< index string */ ecma_value_t value, /**< value */ bool writable, /**< writable */ bool enumerable, /**< enumerable */ bool configurable, /**< configurable */ bool is_throw) /**< is_throw */ { 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 = writable; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = enumerable; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = configurable; return ecma_op_object_define_own_property (obj_p, index_p, &prop_desc, is_throw); } /* ecma_builtin_helper_def_prop */
/** * CreateMutableBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ bool is_deletable) /**< argument D */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (name_p != NULL); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_create_named_data_property (lex_env_p, name_p, true, false, is_deletable); } 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); 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 = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = is_deletable; } ecma_completion_value_t completion = ecma_op_object_define_own_property (binding_obj_p, name_p, &prop_desc, true); if (ecma_is_completion_value_throw (completion)) { return completion; } else { JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); } } return ecma_make_empty_completion_value (); } /* ecma_op_create_mutable_binding */
/** * The Object object's 'defineProperty' routine * * See also: * ECMA-262 v5, 15.2.3.6 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_object_define_property (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2, /**< routine's second argument */ ecma_value_t arg3) /**< routine's third argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (!ecma_is_value_object (arg1)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg1); ECMA_TRY_CATCH (name_str_value, ecma_op_to_string (arg2), ret_value); ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); ecma_property_descriptor_t prop_desc; ECMA_TRY_CATCH (conv_result, ecma_op_to_property_descriptor (arg3, &prop_desc), ret_value); ECMA_TRY_CATCH (define_own_prop_ret, ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc, true), ret_value); ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg1, true)); ECMA_FINALIZE (define_own_prop_ret); ecma_free_property_descriptor (&prop_desc); ECMA_FINALIZE (conv_result); ECMA_FINALIZE (name_str_value); } return ret_value; } /* ecma_builtin_object_object_define_property */
/** * 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 */
/** * The Function.prototype object's 'bind' routine * * See also: * ECMA-262 v5, 15.3.4.5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this argument */ const ecma_value_t *arguments_list_p, /**< list of arguments */ ecma_length_t arguments_number) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { /* 4. 11. 18. */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *function_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_BOUND_FUNCTION); ecma_deref_object (prototype_obj_p); /* 7. */ ecma_value_t *target_function_prop_p; target_function_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION); ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg); ECMA_SET_INTERNAL_VALUE_POINTER (*target_function_prop_p, this_arg_obj_p); /* 8. */ ecma_value_t *bound_this_prop_p; bound_this_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS); const ecma_length_t arg_count = arguments_number; if (arg_count > 0) { *bound_this_prop_p = ecma_copy_value_if_not_object (arguments_list_p[0]); } else { *bound_this_prop_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } if (arg_count > 1) { ecma_collection_header_t *bound_args_collection_p; bound_args_collection_p = ecma_new_values_collection (&arguments_list_p[1], arg_count - 1, false); ecma_value_t *bound_args_prop_p; bound_args_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS); ECMA_SET_INTERNAL_VALUE_POINTER (*bound_args_prop_p, bound_args_collection_p); } /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ /* 16. */ ecma_number_t length = ECMA_NUMBER_ZERO; ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); /* 15. */ if (ecma_object_get_class_name (this_arg_obj_p) == LIT_MAGIC_STRING_FUNCTION_UL) { ecma_value_t get_len_value = ecma_op_object_get (this_arg_obj_p, magic_string_length_p); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value)); JERRY_ASSERT (ecma_is_value_number (get_len_value)); const ecma_length_t bound_arg_count = arg_count > 1 ? arg_count - 1 : 0; /* 15.a */ length = ecma_get_number_from_value (get_len_value) - ((ecma_number_t) bound_arg_count); ecma_free_value (get_len_value); /* 15.b */ if (ecma_number_is_negative (length)) { length = ECMA_NUMBER_ZERO; } } /* 17. */ ecma_value_t completion = ecma_builtin_helper_def_prop (function_p, magic_string_length_p, ecma_make_number_value (length), false, /* Writable */ false, /* Enumerable */ false, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_boolean (completion)); ecma_deref_ecma_string (magic_string_length_p); /* 19-21. */ ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); completion = ecma_op_object_define_own_property (function_p, magic_string_caller_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_boolean (completion)); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); completion = ecma_op_object_define_own_property (function_p, magic_string_arguments_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_boolean (completion)); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); /* 22. */ ret_value = ecma_make_object_value (function_p); } return ret_value; } /* ecma_builtin_function_prototype_object_bind */
/** * Define the necessary properties for the result array (index, input, length). */ void re_set_result_array_properties (ecma_object_t *array_obj_p, /**< result array */ ecma_string_t *input_str_p, /**< input string */ uint32_t num_of_elements, /**< Number of array elements */ int32_t index) /** index of matching */ { /* Set index property of the result array */ ecma_string_t *result_prop_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INDEX); { ecma_property_descriptor_t array_item_prop_desc = ecma_make_empty_property_descriptor (); array_item_prop_desc.is_value_defined = true; ecma_number_t *num_p = ecma_alloc_number (); *num_p = (ecma_number_t) index; array_item_prop_desc.value = ecma_make_number_value (num_p); array_item_prop_desc.is_writable_defined = true; array_item_prop_desc.is_writable = true; array_item_prop_desc.is_enumerable_defined = true; array_item_prop_desc.is_enumerable = true; array_item_prop_desc.is_configurable_defined = true; array_item_prop_desc.is_configurable = true; ecma_op_object_define_own_property (array_obj_p, result_prop_str_p, &array_item_prop_desc, true); ecma_dealloc_number (num_p); } ecma_deref_ecma_string (result_prop_str_p); /* Set input property of the result array */ result_prop_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INPUT); { ecma_property_descriptor_t array_item_prop_desc = ecma_make_empty_property_descriptor (); array_item_prop_desc.is_value_defined = true; array_item_prop_desc.value = ecma_make_string_value (input_str_p); array_item_prop_desc.is_writable_defined = true; array_item_prop_desc.is_writable = true; array_item_prop_desc.is_enumerable_defined = true; array_item_prop_desc.is_enumerable = true; array_item_prop_desc.is_configurable_defined = true; array_item_prop_desc.is_configurable = true; ecma_op_object_define_own_property (array_obj_p, result_prop_str_p, &array_item_prop_desc, true); } ecma_deref_ecma_string (result_prop_str_p); /* Set length property of the result array */ result_prop_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); { ecma_property_descriptor_t array_item_prop_desc = ecma_make_empty_property_descriptor (); array_item_prop_desc.is_value_defined = true; ecma_number_t *num_p = ecma_alloc_number (); *num_p = (ecma_number_t) (num_of_elements); array_item_prop_desc.value = ecma_make_number_value (num_p); array_item_prop_desc.is_writable_defined = false; array_item_prop_desc.is_enumerable_defined = false; array_item_prop_desc.is_configurable_defined = false; ecma_op_object_define_own_property (array_obj_p, result_prop_str_p, &array_item_prop_desc, true); ecma_dealloc_number (num_p); } ecma_deref_ecma_string (result_prop_str_p); } /* re_set_result_array_properties */
/** * Function object creation operation. * * See also: ECMA-262 v5, 13.2 * * @return pointer to newly created Function object */ ecma_object_t * ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */ bool is_decl_in_strict_mode, /**< is function declared in strict mode code? */ const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */ { bool is_strict_mode_code = is_decl_in_strict_mode; if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) { is_strict_mode_code = true; } // 1., 4., 13. ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *func_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_FUNCTION); ecma_deref_object (prototype_obj_p); // 2., 6., 7., 8. /* * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object. * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION * that defines which version of the routine should be used on demand. */ // 3. /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p; // 9. ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.scope_cp, scope_p); // 10., 11., 12. ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p); ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); // 14., 15., 16., 17., 18. /* * 'length' and 'prototype' properties are instantiated lazily * * See also: ecma_op_function_try_lazy_instantiate_property */ // 19. if (is_strict_mode_code) { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); ecma_op_object_define_own_property (func_p, magic_string_caller_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); ecma_op_object_define_own_property (func_p, magic_string_arguments_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); } return func_p; } /* ecma_op_create_function_object */
/** * [[Put]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.5 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_put (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ ecma_value_t value, /**< ecma-value */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); // 1. if (!ecma_op_object_can_put (obj_p, property_name_p)) { if (is_throw) { // a. return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { // b. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE); } } // 2. ecma_property_t *own_desc_p = ecma_op_object_get_own_property (obj_p, property_name_p); // 3. if (own_desc_p != NULL && own_desc_p->type == ECMA_PROPERTY_NAMEDDATA) { // a. ecma_property_descriptor_t value_desc = ecma_make_empty_property_descriptor (); { value_desc.is_value_defined = true; value_desc.value = value; } // b., c. return ecma_op_object_define_own_property (obj_p, property_name_p, &value_desc, is_throw); } // 4. ecma_property_t *desc_p = ecma_op_object_get_property (obj_p, property_name_p); // 5. if (desc_p != NULL && desc_p->type == ECMA_PROPERTY_NAMEDACCESSOR) { // a. ecma_object_t *setter_p = ecma_get_named_accessor_property_setter (desc_p); JERRY_ASSERT (setter_p != NULL); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ECMA_TRY_CATCH (call_ret, ecma_op_function_call_array_args (setter_p, ecma_make_object_value (obj_p), &value, 1), ret_value); ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); ECMA_FINALIZE (call_ret); return ret_value; } else { // 6.a., 6.b. return ecma_builtin_helper_def_prop (obj_p, property_name_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ is_throw); /* Failure handling */ } JERRY_UNREACHABLE (); } /* ecma_op_general_object_put */
/** * 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++) { ecma_string_t* item_name_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 = array_items_p[index]; 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_op_object_define_own_property (obj_p, item_name_string_p, &item_prop_desc, false); 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 */
/** * The String.prototype object's 'match' routine * * See also: * ECMA-262 v5, 15.5.4.10 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_match (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ ECMA_TRY_CATCH (this_check_coercible_value, ecma_op_check_object_coercible (this_arg), ret_value); /* 2. */ ECMA_TRY_CATCH (this_to_string_value, ecma_op_to_string (this_arg), ret_value); ecma_value_t regexp_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 3. */ if (ecma_is_value_object (arg) && ecma_object_get_class_name (ecma_get_object_from_value (arg)) == LIT_MAGIC_STRING_REGEXP_UL) { regexp_value = ecma_copy_value (arg, true); } else { /* 4. */ ecma_value_t regexp_arguments[1] = { arg }; ECMA_TRY_CATCH (new_regexp_value, ecma_builtin_regexp_dispatch_construct (regexp_arguments, 1), ret_value); regexp_value = ecma_copy_value (new_regexp_value, true); ECMA_FINALIZE (new_regexp_value); } if (ecma_is_completion_value_empty (ret_value)) { JERRY_ASSERT (!ecma_is_value_empty (regexp_value)); ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_value); ecma_string_t *global_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); /* 5. */ ECMA_TRY_CATCH (global_value, ecma_op_object_get (regexp_obj_p, global_string_p), ret_value); JERRY_ASSERT (ecma_is_value_boolean (global_value)); ecma_value_t exec_arguments[1] = { this_to_string_value }; if (!ecma_is_value_true (global_value)) { /* 7. */ ret_value = ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC, regexp_value, exec_arguments, 1); } else { /* 8.a. */ ecma_number_t *zero_number_p = ecma_alloc_number (); *zero_number_p = 0; ecma_string_t *index_zero_string_p = ecma_new_ecma_string_from_uint32 (0); ecma_string_t *last_index_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ECMA_TRY_CATCH (put_value, ecma_op_object_put (regexp_obj_p, last_index_string_p, ecma_make_number_value (zero_number_p), true), ret_value); /* 8.b. */ ECMA_TRY_CATCH (new_array_value, ecma_op_create_array_object (NULL, 0, false), ret_value); ecma_object_t *new_array_obj_p = ecma_get_object_from_value (new_array_value); /* 8.c. */ ecma_number_t previous_last_index = 0; /* 8.d. */ uint32_t n = 0; /* 8.e. */ bool last_match = true; //ecma_completion_value_t exec_result = ecma_make_empty_completion_value (); /* 8.f. */ while (last_match && ecma_is_completion_value_empty (ret_value)) { /* 8.f.i. */ ECMA_TRY_CATCH (exec_value, ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC, regexp_value, exec_arguments, 1), ret_value); if (ecma_is_value_null (exec_value)) { /* 8.f.ii. */ last_match = false; } else { /* 8.f.iii. */ ECMA_TRY_CATCH (this_index_value, ecma_op_object_get (regexp_obj_p, last_index_string_p), ret_value); ECMA_TRY_CATCH (this_index_number, ecma_op_to_number (this_index_value), ret_value); ecma_number_t this_index = *ecma_get_number_from_value (this_index_number); /* 8.f.iii.2. */ if (this_index == previous_last_index) { ecma_number_t *new_last_index_p = ecma_alloc_number (); *new_last_index_p = this_index + 1; /* 8.f.iii.2.a. */ ECMA_TRY_CATCH (index_put_value, ecma_op_object_put (regexp_obj_p, last_index_string_p, ecma_make_number_value (new_last_index_p), true), ret_value); /* 8.f.iii.2.b. */ previous_last_index = this_index + 1; ECMA_FINALIZE (index_put_value); ecma_dealloc_number (new_last_index_p); } else { /* 8.f.iii.3. */ previous_last_index = this_index; } if (ecma_is_completion_value_empty (ret_value)) { /* 8.f.iii.4. */ JERRY_ASSERT (ecma_is_value_object (exec_value)); ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value); ECMA_TRY_CATCH (match_string_value, ecma_op_object_get (exec_obj_p, index_zero_string_p), ret_value); /* 8.f.iii.5. */ ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = match_string_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; } ecma_string_t *current_index_str_p = ecma_new_ecma_string_from_uint32 (n); ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_obj_p, current_index_str_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)); ecma_deref_ecma_string (current_index_str_p); /* 8.f.iii.6. */ n++; ECMA_FINALIZE (match_string_value); } ECMA_FINALIZE (this_index_number); ECMA_FINALIZE (this_index_value); } ECMA_FINALIZE (exec_value); } if (ecma_is_completion_value_empty (ret_value)) { if (n == 0) { /* 8.g. */ ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_NULL); } else { /* 8.h. */ ret_value = ecma_make_normal_completion_value (ecma_copy_value (new_array_value, true)); } } ECMA_FINALIZE (new_array_value); ECMA_FINALIZE (put_value); ecma_deref_ecma_string (last_index_string_p); ecma_deref_ecma_string (index_zero_string_p); ecma_dealloc_number (zero_number_p); } ECMA_FINALIZE (global_value); ecma_deref_ecma_string (global_string_p); ecma_free_value (regexp_value, true); } ECMA_FINALIZE (this_to_string_value); ECMA_FINALIZE (this_check_coercible_value); return ret_value; } /* ecma_builtin_string_prototype_object_match */
/** * The Object object's 'defineProperties' routine * * See also: * ECMA-262 v5, 15.2.3.7 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // 1. if (!ecma_is_value_object (arg1)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg1); // 2. ECMA_TRY_CATCH (props, ecma_op_to_object (arg2), ret_value); ecma_object_t *props_p = ecma_get_object_from_value (props); // 3. ecma_collection_header_t *prop_names_p = ecma_op_object_get_property_names (props_p, false, true, false); uint32_t property_number = prop_names_p->unit_number; ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, prop_names_p); // 4. MEM_DEFINE_LOCAL_ARRAY (property_descriptors, property_number, ecma_property_descriptor_t); uint32_t property_descriptor_number = 0; while (ecma_collection_iterator_next (&iter) && ecma_is_completion_value_empty (ret_value)) { // 5.a ECMA_TRY_CATCH (desc_obj, ecma_op_object_get (props_p, ecma_get_string_from_value (*iter.current_value_p)), ret_value); // 5.b ECMA_TRY_CATCH (conv_result, ecma_op_to_property_descriptor (desc_obj, &property_descriptors[property_descriptor_number]), ret_value); property_descriptor_number++; ECMA_FINALIZE (conv_result); ECMA_FINALIZE (desc_obj); } // 6. ecma_collection_iterator_init (&iter, prop_names_p); for (uint32_t index = 0; index < property_number && ecma_is_completion_value_empty (ret_value); index++) { bool is_next = ecma_collection_iterator_next (&iter); JERRY_ASSERT (is_next); ECMA_TRY_CATCH (define_own_prop_ret, ecma_op_object_define_own_property (obj_p, ecma_get_string_from_value (*iter.current_value_p), &property_descriptors[index], true), ret_value); ECMA_FINALIZE (define_own_prop_ret); } // Clean up for (uint32_t index = 0; index < property_descriptor_number; index++) { ecma_free_property_descriptor (&property_descriptors[index]); } MEM_FINALIZE_LOCAL_ARRAY (property_descriptors); ecma_free_values_collection (prop_names_p, true); // 7. if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg1, true)); } ECMA_FINALIZE (props); } return ret_value; } /* ecma_builtin_object_object_define_properties */
/** * The Object object's 'freeze' routine * * See also: * ECMA-262 v5, 15.2.3.9 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_object_freeze (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // 1. if (!ecma_is_value_object (arg)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { // 2. ecma_object_t *obj_p = ecma_get_object_from_value (arg); ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter) && ecma_is_completion_value_empty (ret_value)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); // 2.a ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p); // 2.b if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_writable (property_p)) { prop_desc.is_writable = false; } // 2.c if (ecma_is_property_configurable (property_p)) { prop_desc.is_configurable = false; } // 2.d ECMA_TRY_CATCH (define_own_prop_ret, ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc, true), ret_value); ECMA_FINALIZE (define_own_prop_ret); ecma_free_property_descriptor (&prop_desc); } ecma_free_values_collection (props_p, true); if (ecma_is_completion_value_empty (ret_value)) { // 3. ecma_set_object_extensible (obj_p, false); // 4. ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg, true)); } } return ret_value; } /* ecma_builtin_object_object_freeze */
/** * Arguments object creation operation. * * See also: ECMA-262 v5, 10.6 */ void ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ ecma_object_t *lex_env_p, /**< lexical environment the Arguments object is created for */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_number, /**< length of arguments list */ const ecma_compiled_code_t *bytecode_data_p) /**< byte code */ { // 2., 3., 6. ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); ecma_object_t *obj_p = ecma_create_object (prototype_p, false, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_p); // 11.a, 11.b for (ecma_length_t indx = 0; indx < arguments_number; indx++) { ecma_value_t completion; ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 (indx); completion = ecma_builtin_helper_def_prop (obj_p, indx_string_p, arguments_list_p[indx], true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (indx_string_p); } bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; // 1. // 4. 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_ARGUMENTS_UL; // 7. ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); ecma_value_t completion = ecma_builtin_helper_def_prop (obj_p, length_magic_string_p, ecma_make_uint32_value (arguments_number), true, /* Writable */ false, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (length_magic_string_p); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); if (bytecode_data_p != NULL) { ecma_length_t formal_params_number; jmem_cpointer_t *literal_p; if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); } else { cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); } if (!is_strict && arguments_number > 0 && formal_params_number > 0) { // 8. ecma_object_t *map_p = ecma_op_create_object_object_noarg (); // 11.c for (uint32_t indx = 0; indx < formal_params_number; indx++) { // i. if (literal_p[indx] == JMEM_CP_NULL) { continue; } ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, literal_p[indx]); ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 ((uint32_t) indx); prop_desc.is_value_defined = true; prop_desc.value = ecma_make_string_value (name_p); prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; completion = ecma_op_object_define_own_property (map_p, indx_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (indx_string_p); } // 12. ecma_set_object_type (obj_p, ECMA_OBJECT_TYPE_ARGUMENTS); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARGUMENTS type. * * See also: ecma_object_get_class_name */ ecma_delete_property (obj_p, class_prop_p); ecma_property_t *parameters_map_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (parameters_map_prop_p)->value, map_p); ecma_property_t *scope_prop_p = ecma_create_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (scope_prop_p)->value, lex_env_p); ecma_deref_object (map_p); } } // 13. if (!is_strict) { ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE); completion = ecma_builtin_helper_def_prop (obj_p, callee_magic_string_p, ecma_make_object_value (func_obj_p), true, /* Writable */ false, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (callee_magic_string_p); } else { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); // 14. prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; 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 *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE); completion = ecma_op_object_define_own_property (obj_p, callee_magic_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (callee_magic_string_p); ecma_string_t *caller_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); completion = ecma_op_object_define_own_property (obj_p, caller_magic_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (caller_magic_string_p); ecma_deref_object (thrower_p); } ecma_string_t *arguments_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); if (is_strict) { ecma_op_create_immutable_binding (lex_env_p, arguments_string_p); ecma_op_initialize_immutable_binding (lex_env_p, arguments_string_p, ecma_make_object_value (obj_p)); } else { ecma_value_t completion = ecma_op_create_mutable_binding (lex_env_p, arguments_string_p, false); JERRY_ASSERT (ecma_is_value_empty (completion)); completion = ecma_op_set_mutable_binding (lex_env_p, arguments_string_p, ecma_make_object_value (obj_p), false); JERRY_ASSERT (ecma_is_value_empty (completion)); } ecma_deref_ecma_string (arguments_string_p); ecma_deref_object (obj_p); } /* ecma_op_create_arguments_object */
/** * FromPropertyDescriptor operation. * * See also: * ECMA-262 v5, 8.10.4 * * @return constructed object */ ecma_object_t * ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p) /**< property descriptor */ { // 2. ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); ecma_value_t completion; ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; 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; } // 3. if (src_prop_desc_p->is_value_defined || src_prop_desc_p->is_writable_defined) { JERRY_ASSERT (prop_desc.is_value_defined && prop_desc.is_writable_defined); // a. prop_desc.value = src_prop_desc_p->value; ecma_string_t *value_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUE); completion = ecma_op_object_define_own_property (obj_p, value_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (value_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); // b. const bool is_writable = (src_prop_desc_p->is_writable); prop_desc.value = ecma_make_simple_value (is_writable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_string_t *writable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE); completion = ecma_op_object_define_own_property (obj_p, writable_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (writable_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); } else { // 4. JERRY_ASSERT (src_prop_desc_p->is_get_defined || src_prop_desc_p->is_set_defined); // a. if (src_prop_desc_p->get_p == NULL) { prop_desc.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { prop_desc.value = ecma_make_object_value (src_prop_desc_p->get_p); } ecma_string_t *get_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GET); completion = ecma_op_object_define_own_property (obj_p, get_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (get_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); // b. if (src_prop_desc_p->set_p == NULL) { prop_desc.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { prop_desc.value = ecma_make_object_value (src_prop_desc_p->set_p); } ecma_string_t *set_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SET); completion = ecma_op_object_define_own_property (obj_p, set_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (set_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); } const bool is_enumerable = src_prop_desc_p->is_enumerable; prop_desc.value = ecma_make_simple_value (is_enumerable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_string_t *enumerable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE); completion = ecma_op_object_define_own_property (obj_p, enumerable_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (enumerable_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); const bool is_configurable = src_prop_desc_p->is_configurable; prop_desc.value = ecma_make_simple_value (is_configurable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); ecma_string_t *configurable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE); completion = ecma_op_object_define_own_property (obj_p, configurable_magic_string_p, &prop_desc, false); ecma_deref_ecma_string (configurable_magic_string_p); JERRY_ASSERT (ecma_is_value_true (completion)); return obj_p; } /* ecma_op_from_property_descriptor */
/** * Function object creation operation. * * See also: ECMA-262 v5, 13.2 * * @return pointer to newly created Function object */ ecma_object_t* ecma_op_create_function_object (ecma_string_t* formal_parameter_list_p[], /**< formal parameters list */ ecma_length_t formal_parameters_number, /**< formal parameters list's length */ ecma_object_t *scope_p, /**< function's scope */ bool is_strict, /**< 'strict' flag */ bool do_instantiate_arguments_object, /**< should an Arguments object be instantiated * for the function object upon call */ const vm_instr_t *instrs_p, /**< byte-code array */ vm_instr_counter_t first_instr_pos) /**< position of first instruction * of function's body */ { // 1., 4., 13. ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *f = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_FUNCTION); ecma_deref_object (prototype_obj_p); // 2., 6., 7., 8. /* * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object. * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION * that defines which version of the routine should be used on demand. */ // 3. /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ // 9. ecma_property_t *scope_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_SCOPE); ECMA_SET_POINTER (scope_prop_p->u.internal_property.value, scope_p); // 10., 11. ecma_property_t *formal_parameters_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS); if (formal_parameters_number != 0) { /* * Reverse formal parameter list */ for (ecma_length_t i = 0; i < formal_parameters_number / 2; i++) { ecma_string_t *tmp_p = formal_parameter_list_p[i]; formal_parameter_list_p[i] = formal_parameter_list_p[formal_parameters_number - 1u - i]; formal_parameter_list_p[formal_parameters_number - 1u - i] = tmp_p; } ecma_collection_header_t *formal_parameters_collection_p = ecma_new_strings_collection (formal_parameter_list_p, formal_parameters_number); ECMA_SET_POINTER (formal_parameters_prop_p->u.internal_property.value, formal_parameters_collection_p); } else { JERRY_ASSERT (formal_parameters_prop_p->u.internal_property.value == ECMA_NULL_POINTER); } // 12. ecma_property_t *bytecode_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CODE_BYTECODE); MEM_CP_SET_NON_NULL_POINTER (bytecode_prop_p->u.internal_property.value, instrs_p); ecma_property_t *code_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET); code_prop_p->u.internal_property.value = ecma_pack_code_internal_property_value (is_strict, do_instantiate_arguments_object, first_instr_pos); // 14. ecma_number_t* len_p = ecma_alloc_number (); *len_p = ecma_uint32_to_number (formal_parameters_number); // 15. ecma_property_descriptor_t length_prop_desc = ecma_make_empty_property_descriptor (); length_prop_desc.is_value_defined = true; length_prop_desc.value = ecma_make_number_value (len_p); ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_object_define_own_property (f, magic_string_length_p, &length_prop_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)); ecma_dealloc_number (len_p); len_p = NULL; // 16. ecma_object_t *proto_p = ecma_op_create_object_object_noarg (); // 17. ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = ecma_make_object_value (f); 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 = true; } ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); ecma_op_object_define_own_property (proto_p, magic_string_constructor_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_constructor_p); // 18. prop_desc.value = ecma_make_object_value (proto_p); 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 (f, magic_string_prototype_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_prototype_p); ecma_deref_object (proto_p); // 19. if (is_strict) { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); ecma_op_object_define_own_property (f, magic_string_caller_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); ecma_op_object_define_own_property (f, magic_string_arguments_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); } return f; } /* ecma_op_create_function_object */
/** * 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 */
/** * 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 */
/** * [[Put]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.5 * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 * * @return ecma value * The returned value must be freed with ecma_free_value. * * Returns with ECMA_SIMPLE_VALUE_TRUE if the operation is * successful. Otherwise it returns with an error object * or ECMA_SIMPLE_VALUE_FALSE. * * Note: even if is_throw is false, the setter can throw an * error, and this function returns with that error. */ ecma_value_t ecma_op_general_object_put (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ ecma_value_t value, /**< ecma value */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); ecma_object_t *setter_p = NULL; ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, property_name_p); if (prop_p != NULL) { if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { if (ecma_is_property_writable (prop_p)) { const ecma_object_type_t type = ecma_get_object_type (obj_p); if (type == ECMA_OBJECT_TYPE_ARGUMENTS || (type == ECMA_OBJECT_TYPE_ARRAY && ecma_op_general_object_property_name_is_length (property_name_p))) { /* These cases cannot be optimized. */ ecma_property_descriptor_t value_desc = ecma_make_empty_property_descriptor (); value_desc.is_value_defined = true; value_desc.value = value; return ecma_op_object_define_own_property (obj_p, property_name_p, &value_desc, is_throw); } /* There is no need for special casing arrays here because changing the * value of an existing property never changes the length of an array. */ ecma_named_data_property_assign_value (obj_p, prop_p, value); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } else { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); setter_p = ecma_get_named_accessor_property_setter (prop_p); } } else { ecma_object_t *proto_p = ecma_get_object_prototype (obj_p); bool create_new_property = true; if (proto_p != NULL) { ecma_property_t *inherited_prop_p = ecma_op_object_get_property (proto_p, property_name_p); if (inherited_prop_p != NULL) { if (ECMA_PROPERTY_GET_TYPE (inherited_prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { setter_p = ecma_get_named_accessor_property_setter (inherited_prop_p); create_new_property = false; } else { create_new_property = ecma_is_property_writable (inherited_prop_p); } } } if (create_new_property && ecma_get_object_extensible (obj_p)) { const ecma_object_type_t type = ecma_get_object_type (obj_p); if (type == ECMA_OBJECT_TYPE_ARGUMENTS) { return ecma_builtin_helper_def_prop (obj_p, property_name_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ is_throw); /* Failure handling */ } uint32_t index; if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_string_get_array_index (property_name_p, &index)) { /* Since the length of an array is a non-configurable named data * property, the prop_p must be a non-NULL pointer for all arrays. */ JERRY_ASSERT (!ecma_op_general_object_property_name_is_length (property_name_p)); ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); uint32_t old_len = ecma_get_uint32_from_value (ecma_get_named_data_property_value (len_prop_p)); if (index < UINT32_MAX && index >= old_len) { if (!ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); } } ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p, property_name_p, true, /* Writable */ true, /* Enumerable */ true); /* Configurable */ JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (new_prop_p))); ecma_set_named_data_property_value (new_prop_p, ecma_copy_value_if_not_object (value)); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } if (setter_p == NULL) { return ecma_reject (is_throw); } ecma_value_t ret_value = ecma_op_function_call (setter_p, ecma_make_object_value (obj_p), &value, 1); if (!ecma_is_value_error (ret_value)) { ecma_fast_free_value (ret_value); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_op_general_object_put */