/** * The Function.prototype object's 'call' routine * * See also: * ECMA-262 v5, 15.3.4.4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_call (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 */ { if (!ecma_op_is_callable (this_arg)) { return ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); if (arguments_number == 0) { /* Even a 'this' argument is missing. */ return ecma_op_function_call (func_obj_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), NULL, 0); } else { return ecma_op_function_call (func_obj_p, arguments_list_p[0], arguments_list_p + 1, (ecma_length_t) (arguments_number - 1u)); } } } /* ecma_builtin_function_prototype_object_call */
/** * The Function.prototype object's 'call' routine * * See also: * ECMA-262 v5, 15.3.4.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_function_prototype_object_call (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 */ { if (!ecma_op_is_callable (this_arg)) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); if (arguments_number == 0) { return ecma_op_function_call (func_obj_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), NULL, 0); } else { return ecma_op_function_call (func_obj_p, arguments_list_p[0], (arguments_number == 1u) ? NULL : (arguments_list_p + 1), (ecma_length_t) (arguments_number - 1u)); } } } /* ecma_builtin_function_prototype_object_call */
/** * Reject the promise if the value is error. * * See also: * ES2015 25.4.1.1.1 * * @return ecma value of the new promise. * Returned value must be freed with ecma_free_value. */ inline static ecma_value_t ecma_builtin_promise_reject_abrupt (ecma_value_t capability) /**< reject description */ { ecma_value_t reason = JERRY_CONTEXT (error_value); ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); ecma_deref_ecma_string (str_reject); ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (reject), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &reason, 1); ecma_free_value (reject); if (ECMA_IS_VALUE_ERROR (call_ret)) { return call_ret; } ecma_free_value (call_ret); ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE); ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise); ecma_deref_ecma_string (str_promise); return promise_new; } /* ecma_builtin_promise_reject_abrupt */
/** * The Array.prototype's 'toLocaleString' single element operation routine * * See also: * ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ uint32_t index) /**< array index */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, index_string_p), ret_value); if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) { ecma_string_t *return_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ret_value = ecma_make_string_value (return_string_p); } else { ECMA_TRY_CATCH (index_obj_value, ecma_op_to_object (index_value), ret_value); ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value); ecma_string_t *locale_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL); ECMA_TRY_CATCH (to_locale_value, ecma_op_object_get (index_obj_p, locale_string_magic_string_p), ret_value); if (ecma_op_is_callable (to_locale_value)) { ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value); ECMA_TRY_CATCH (call_value, ecma_op_function_call (locale_func_obj_p, ecma_make_object_value (index_obj_p), NULL, 0), ret_value); ret_value = ecma_op_to_string (call_value); ECMA_FINALIZE (call_value); } else { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } ECMA_FINALIZE (to_locale_value); ecma_deref_ecma_string (locale_string_magic_string_p); ECMA_FINALIZE (index_obj_value); } ECMA_FINALIZE (index_value); ecma_deref_ecma_string (index_string_p); return ret_value; } /* ecma_builtin_helper_get_to_locale_string_at_index */
/** * 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_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); /* 2. */ ECMA_TRY_CATCH (to_string_val, ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_TO_STRING_UL), return_value); /* 3. */ if (!ecma_op_is_callable (to_string_val)) { return_value = ecma_raise_type_error (ECMA_ERR_MSG ("'toString is missing or not a function.'")); } 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_FINALIZE (obj_val); return return_value; } /* ecma_builtin_object_prototype_object_to_locale_string */
/** * 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 */
/** * 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 ret_value = ECMA_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_VALUE_NULL; } } if (ecma_is_value_empty (ret_value)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (obj); /* 4. */ ECMA_TRY_CATCH (to_iso, ecma_op_object_get_by_magic_id (value_obj_p, LIT_MAGIC_STRING_TO_ISO_STRING_UL), ret_value); /* 5. */ if (!ecma_op_is_callable (to_iso)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("'toISOString' is missing or not a function.")); } /* 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_FINALIZE (tv); ECMA_FINALIZE (obj); return ret_value; } /* ecma_builtin_date_prototype_to_json */
/** * Process the PromiseResolveThenableJob. * * See also: ES2015 25.4.2.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ static ecma_value_t ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be operated */ { ecma_job_promise_resolve_thenable_t *job_p = (ecma_job_promise_resolve_thenable_t *) obj_p; ecma_object_t *promise_p = ecma_get_object_from_value (job_p->promise); ecma_string_t str_resolve, str_reject; ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION); ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION); ecma_value_t resolve = ecma_op_object_get (promise_p, &str_resolve); ecma_value_t reject = ecma_op_object_get (promise_p, &str_reject); ecma_value_t argv[] = { resolve, reject }; ecma_value_t ret; ecma_value_t then_call_result = ecma_op_function_call (ecma_get_object_from_value (job_p->then), job_p->thenable, argv, 2); ret = then_call_result; if (ECMA_IS_VALUE_ERROR (then_call_result)) { ret = ecma_op_function_call (ecma_get_object_from_value (reject), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &then_call_result, 1); ecma_free_value (then_call_result); } ecma_free_value (resolve); ecma_free_value (reject); ecma_free_promise_resolve_thenable_job (job_p); return ret; } /* ecma_process_promise_resolve_thenable_job */
/** * [[Get]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_get (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); // 1. const ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, property_name_p); // 2. if (prop_p == NULL) { return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); } // 3. if (prop_p->type == ECMA_PROPERTY_NAMEDDATA) { return ecma_make_normal_completion_value (ecma_copy_value (ecma_get_named_data_property_value (prop_p), true)); } else { // 4. ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_p); // 5. if (getter_p == NULL) { return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { return ecma_op_function_call (getter_p, ecma_make_object_value (obj_p), NULL); } } JERRY_UNREACHABLE (); } /* ecma_op_general_object_get */
/** * 'Function call' opcode handler. * * See also: ECMA-262 v5, 11.2.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t opfunc_call_n (ecma_value_t this_value, /**< this object value */ ecma_value_t func_value, /**< function object value */ const ecma_value_t *arguments_list_p, /**< stack pointer */ ecma_length_t arguments_list_len) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_op_is_callable (func_value)) { return ecma_raise_type_error (""); } ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); ret_value = ecma_op_function_call (func_obj_p, this_value, arguments_list_p, arguments_list_len); return ret_value; } /* opfunc_call_n */
/** * 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 */
/** * 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 */
/** * Resolve value corresponding to reference. * * @return value of the reference */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ ecma_string_t *name_p) /**< identifier's name */ { JERRY_ASSERT (lex_env_p != NULL); while (lex_env_p != NULL) { ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p); if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); if (property_p != NULL) { return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); } } else if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND) { ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); #ifndef CONFIG_ECMA_LCACHE_DISABLE ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p); if (property_p != NULL) { ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { return ecma_fast_copy_value (prop_value_p->value); } JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_value_p); if (getter_p == NULL) { return ECMA_VALUE_UNDEFINED; } ecma_value_t base_value = ecma_make_object_value (binding_obj_p); return ecma_op_function_call (getter_p, base_value, NULL, 0); } #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ ecma_value_t prop_value = ecma_op_object_find (binding_obj_p, name_p); if (ecma_is_value_found (prop_value)) { return prop_value; } } else { #if ENABLED (JERRY_ES2015_CLASS) JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND); #else /* !ENABLED (JERRY_ES2015_CLASS) */ JERRY_UNREACHABLE (); #endif /* ENABLED (JERRY_ES2015_CLASS) */ } lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } #ifdef JERRY_ENABLE_ERROR_MESSAGES ecma_value_t name_val = ecma_make_string_value (name_p); ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, "% is not defined", name_val); #else /* !JERRY_ENABLE_ERROR_MESSAGES */ ecma_value_t error_value = ecma_raise_reference_error (NULL); #endif /* JERRY_ENABLE_ERROR_MESSAGES */ return error_value; } /* ecma_op_resolve_reference_value */
/** * Resolve value corresponding to reference. * * @return value of the reference */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ ecma_string_t *name_p, /**< identifier's name */ bool is_strict) /**< strict mode */ { JERRY_ASSERT (lex_env_p != NULL); while (lex_env_p != NULL) { if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); if (property_p != NULL) { ecma_value_t prop_value = ecma_get_named_data_property_value (property_p); /* is the binding mutable? */ if (unlikely (!ecma_is_property_writable (property_p) && ecma_is_value_empty (prop_value))) { /* unitialized mutable binding */ if (is_strict) { return ecma_raise_reference_error (ECMA_ERR_MSG ("")); } else { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } return ecma_fast_copy_value (prop_value); } } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND || ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_property_t *property_p = ecma_op_object_get_property (binding_obj_p, name_p); if (likely (property_p != NULL)) { if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { return ecma_fast_copy_value (ecma_get_named_data_property_value (property_p)); } ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (property_p); if (getter_p == NULL) { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } return ecma_op_function_call (getter_p, ecma_make_object_value (binding_obj_p), NULL, 0); } } lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } return ecma_raise_reference_error (ECMA_ERR_MSG ("")); } /* ecma_op_resolve_reference_value */
/** * [[DefaultValue]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.8 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); if (hint == ECMA_PREFERRED_TYPE_NO) { if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL) { hint = ECMA_PREFERRED_TYPE_STRING; } else { hint = ECMA_PREFERRED_TYPE_NUMBER; } } for (uint32_t i = 1; i <= 2; i++) { lit_magic_string_id_t function_name_magic_string_id; if ((i == 1 && hint == ECMA_PREFERRED_TYPE_STRING) || (i == 2 && hint == ECMA_PREFERRED_TYPE_NUMBER)) { function_name_magic_string_id = LIT_MAGIC_STRING_TO_STRING_UL; } else { function_name_magic_string_id = LIT_MAGIC_STRING_VALUE_OF_UL; } ecma_string_t *function_name_p = ecma_get_magic_string (function_name_magic_string_id); ecma_completion_value_t function_value_get_completion = ecma_op_object_get (obj_p, function_name_p); ecma_deref_ecma_string (function_name_p); if (!ecma_is_completion_value_normal (function_value_get_completion)) { return function_value_get_completion; } ecma_completion_value_t call_completion = ecma_make_empty_completion_value (); if (ecma_op_is_callable (ecma_get_completion_value_value (function_value_get_completion))) { ecma_object_t *func_obj_p = ecma_get_object_from_completion_value (function_value_get_completion); call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL); } ecma_free_completion_value (function_value_get_completion); if (!ecma_is_completion_value_normal (call_completion)) { return call_completion; } if (!ecma_is_completion_value_empty (call_completion) && !ecma_is_value_object (ecma_get_completion_value_value (call_completion))) { return call_completion; } ecma_free_completion_value (call_completion); } return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } /* ecma_op_general_object_default_value */
/** * The processor for PromiseReactionJob. * * See also: ES2015 25.4.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ static ecma_value_t ecma_process_promise_reaction_job (void *obj_p) /**< the job to be operated */ { ecma_job_promise_reaction_t *job_p = (ecma_job_promise_reaction_t *) obj_p; ecma_object_t *reaction_p = ecma_get_object_from_value (job_p->reaction); ecma_string_t *str_capability = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_CAPABILITY); ecma_string_t *str_handler = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_HANDLER); ecma_string_t *str_resolve = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE); ecma_string_t *str_reject = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); /* 2. */ ecma_value_t capability = ecma_op_object_get (reaction_p, str_capability); /* 3. */ ecma_value_t handler = ecma_op_object_get (reaction_p, str_handler); JERRY_ASSERT (ecma_is_value_boolean (handler) || ecma_op_is_callable (handler)); ecma_value_t handler_result; if (ecma_is_value_boolean (handler)) { /* 4-5. True indicates "identity" and false indicates "thrower" */ handler_result = ecma_copy_value (job_p->argument); } else { /* 6. */ handler_result = ecma_op_function_call (ecma_get_object_from_value (handler), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &(job_p->argument), 1); } ecma_value_t status; if (ecma_is_value_false (handler) || ECMA_IS_VALUE_ERROR (handler_result)) { if (ECMA_IS_VALUE_ERROR (handler_result)) { handler_result = ecma_get_value_from_error_value (handler_result); } /* 7. */ ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); JERRY_ASSERT (ecma_op_is_callable (reject)); status = ecma_op_function_call (ecma_get_object_from_value (reject), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &handler_result, 1); ecma_free_value (reject); } else { /* 8. */ ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve); JERRY_ASSERT (ecma_op_is_callable (resolve)); status = ecma_op_function_call (ecma_get_object_from_value (resolve), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &handler_result, 1); ecma_free_value (resolve); } ecma_free_value (handler_result); ecma_free_value (handler); ecma_free_value (capability); ecma_deref_ecma_string (str_capability); ecma_deref_ecma_string (str_handler); ecma_deref_ecma_string (str_resolve); ecma_deref_ecma_string (str_reject); ecma_free_promise_reaction_job (job_p); return status; } /* ecma_process_promise_reaction_job */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function.")); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL, 0); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); /* 4. */ ecma_value_t length_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH); if (ECMA_IS_VALUE_ERROR (length_value)) { return length_value; } ecma_number_t length_number; ecma_value_t get_result = ecma_get_number (length_value, &length_number); ecma_free_value (length_value); if (ECMA_IS_VALUE_ERROR (get_result)) { return get_result; } JERRY_ASSERT (ecma_is_value_empty (get_result)); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); if (length >= ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Too many arguments declared for Function.apply().")); } else { /* 6. */ JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t); uint32_t index = 0; /* 7. */ for (index = 0; index < length; index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t get_value = ecma_op_object_get (obj_p, curr_idx_str_p); ecma_deref_ecma_string (curr_idx_str_p); if (ECMA_IS_VALUE_ERROR (get_value)) { ret_value = get_value; break; } arguments_list_p[index] = get_value; } if (ecma_is_value_empty (ret_value)) { JERRY_ASSERT (index == length); ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, length); } for (uint32_t remove_index = 0; remove_index < index; remove_index++) { ecma_free_value (arguments_list_p[remove_index]); } JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); } } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * PutValue operation part (object base). * * See also: ECMA-262 v5, 8.7.2, section 4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_put_value_object_base (ecma_reference_t ref, /**< ECMA-reference */ ecma_value_t value) /**< ECMA-value */ { const ecma_value_t base = ref.base; const bool is_unresolvable_reference = ecma_is_value_undefined (base); const bool has_primitive_base = (ecma_is_value_boolean (base) || ecma_is_value_number (base) || ecma_is_value_string (base)); const bool has_object_base = (ecma_is_value_object (base) && !(ecma_is_lexical_environment (ecma_get_object_from_value (base)))); const bool is_property_reference = has_primitive_base || has_object_base; JERRY_ASSERT (!is_unresolvable_reference); JERRY_ASSERT (is_property_reference); // 4.a if (!has_primitive_base) { // 4.b case 1 ecma_object_t *obj_p = ecma_get_object_from_value (base); JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (put_ret_value, ecma_op_object_put (obj_p, ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp), value, ref.is_strict), ret_value); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_FINALIZE (put_ret_value); return ret_value; } else { // 4.b case 2 ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // sub_1. ECMA_TRY_CATCH (obj_base, ecma_op_to_object (base), ret_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_base); JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); ecma_string_t *referenced_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp); // sub_2. if (!ecma_op_object_can_put (obj_p, referenced_name_p)) { ret_value = ecma_reject_put (ref.is_strict); } else { // sub_3. ecma_property_t *own_prop_p = ecma_op_object_get_own_property (obj_p, referenced_name_p); // sub_5. ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, referenced_name_p); // sub_4., sub_7 if ((own_prop_p != NULL && (own_prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDDATA)) || (prop_p == NULL) || !(prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDACCESSOR)) { ret_value = ecma_reject_put (ref.is_strict); } else { // sub_6. JERRY_ASSERT (prop_p != NULL && (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDACCESSOR)); ecma_object_t *setter_p = ecma_get_named_accessor_property_setter (prop_p); JERRY_ASSERT (setter_p != NULL); ECMA_TRY_CATCH (call_ret, ecma_op_function_call (setter_p, base, &value, 1), ret_value); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_FINALIZE (call_ret); } } ECMA_FINALIZE (obj_base); return ret_value; } } /* ecma_op_put_value_object_base */
/** * The common function for 'reject' and 'resolve'. * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ ecma_value_t argument, /**< argument for reject or resolve */ bool is_resolve) /**< whether it is for resolve routine */ { if (!ecma_is_value_object (this_arg)) { return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object.")); } uint8_t builtin_id = ecma_get_object_builtin_id (ecma_get_object_from_value (this_arg)); if (builtin_id != ECMA_BUILTIN_ID_PROMISE) { return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not the Promise constructor.")); } if (is_resolve && ecma_is_value_object (argument) && ecma_is_promise (ecma_get_object_from_value (argument))) { return ecma_copy_value (argument); } ecma_value_t capability = ecma_promise_new_capability (); if (ECMA_IS_VALUE_ERROR (capability)) { return capability; } ecma_string_t *str; if (is_resolve) { str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_RESOLVE); } else { str = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_REJECT); } ecma_value_t func = ecma_op_object_get (ecma_get_object_from_value (capability), str); ecma_deref_ecma_string (str); ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func), ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), &argument, 1); ecma_free_value (func); if (ECMA_IS_VALUE_ERROR (call_ret)) { return call_ret; } ecma_free_value (call_ret); ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE); ecma_value_t promise_new = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise); ecma_deref_ecma_string (str_promise); ecma_free_value (capability); return promise_new; } /* ecma_builtin_promise_reject_or_resolve */
/** * Abstract operation Walk defined in 15.12.2 * * See also: * ECMA-262 v5, 15.12.2 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */ ecma_object_t *holder_p, /**< holder object */ ecma_string_t *name_p) /**< property name */ { JERRY_ASSERT (reviver_p); JERRY_ASSERT (holder_p); JERRY_ASSERT (name_p); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (value_get, ecma_op_object_get (holder_p, name_p), ret_value); if (ecma_is_value_object (value_get)) { ecma_object_t *object_p = ecma_get_object_from_value (value_get); ecma_collection_header_t *props_p = ecma_op_object_get_property_names (object_p, false, true, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter) && ecma_is_value_empty (ret_value)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); ECMA_TRY_CATCH (value_walk, ecma_builtin_json_walk (reviver_p, object_p, property_name_p), ret_value); /* * We cannot optimize this function since any members * can be changed (deleted) by the reviver function. */ if (ecma_is_value_undefined (value_walk)) { ecma_value_t delete_val = ecma_op_general_object_delete (object_p, property_name_p, false); JERRY_ASSERT (ecma_is_value_boolean (delete_val)); } else { ecma_builtin_json_define_value_property (object_p, property_name_p, value_walk); } ECMA_FINALIZE (value_walk); } ecma_free_values_collection (props_p, true); } if (ecma_is_value_empty (ret_value)) { ecma_value_t arguments_list[2]; arguments_list[0] = ecma_make_string_value (name_p); arguments_list[1] = value_get; /* * The completion value can be anything including exceptions. */ ret_value = ecma_op_function_call (reviver_p, ecma_make_object_value (holder_p), arguments_list, 2); } else { JERRY_ASSERT (ecma_is_value_error (ret_value)); } ECMA_FINALIZE (value_get); return ret_value; } /* ecma_builtin_json_walk */
/** * Abstract operation 'Str' defined in 15.12.3 * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_str (ecma_string_t *key_p, /**< property key*/ ecma_object_t *holder_p, /**< the object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (value, ecma_op_object_get (holder_p, key_p), ret_value); ecma_value_t my_val = ecma_copy_value (value, true); /* 2. */ if (ecma_is_value_object (my_val)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (my_val); ecma_string_t *to_json_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_JSON_UL); /* 2.a */ ECMA_TRY_CATCH (toJSON, ecma_op_object_get (value_obj_p, to_json_str_p), ret_value); /* 2.b */ if (ecma_op_is_callable (toJSON)) { ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value }; ecma_object_t *toJSON_obj_p = ecma_get_object_from_value (toJSON); ECMA_TRY_CATCH (func_ret_val, ecma_op_function_call (toJSON_obj_p, my_val, call_args, 1), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (func_ret_val, true); ECMA_FINALIZE (func_ret_val); } ECMA_FINALIZE (toJSON); ecma_deref_ecma_string (to_json_str_p); } /* 3. */ if (context_p->replacer_function_p && ecma_is_value_empty (ret_value)) { ecma_value_t holder_value = ecma_make_object_value (holder_p); ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value, my_val }; ECMA_TRY_CATCH (func_ret_val, ecma_op_function_call (context_p->replacer_function_p, holder_value, call_args, 2), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (func_ret_val, true); ECMA_FINALIZE (func_ret_val); } /* 4. */ if (ecma_is_value_object (my_val) && ecma_is_value_empty (ret_value)) { ecma_object_t *obj_p = ecma_get_object_from_value (my_val); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 4.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL) { ECMA_TRY_CATCH (val, ecma_op_to_number (my_val), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 4.b */ else if (class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (my_val), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 4.c */ else if (class_name == LIT_MAGIC_STRING_BOOLEAN_UL) { ECMA_TRY_CATCH (val, ecma_op_to_primitive (my_val, ECMA_PREFERRED_TYPE_NO), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } if (ecma_is_value_empty (ret_value)) { /* 5. - 7. */ if (ecma_is_value_null (my_val) || ecma_is_value_boolean (my_val)) { ret_value = ecma_op_to_string (my_val); JERRY_ASSERT (!ecma_is_value_error (ret_value)); } /* 8. */ else if (ecma_is_value_string (my_val)) { ecma_string_t *value_str_p = ecma_get_string_from_value (my_val); ret_value = ecma_builtin_json_quote (value_str_p); } /* 9. */ else if (ecma_is_value_number (my_val)) { ecma_number_t num_value_p = *ecma_get_number_from_value (my_val); /* 9.a */ if (!ecma_number_is_nan (num_value_p) && !ecma_number_is_infinity (num_value_p)) { ret_value = ecma_op_to_string (my_val); JERRY_ASSERT (!ecma_is_value_error (ret_value)); } else { /* 9.b */ ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); ret_value = ecma_make_string_value (null_str_p); } } /* 10. */ else if (ecma_is_value_object (my_val) && !ecma_op_is_callable (my_val)) { ecma_object_t *obj_p = ecma_get_object_from_value (my_val); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 10.a */ if (class_name == LIT_MAGIC_STRING_ARRAY_UL) { ECMA_TRY_CATCH (val, ecma_builtin_json_array (obj_p, context_p), ret_value); ret_value = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 10.b */ else { ECMA_TRY_CATCH (val, ecma_builtin_json_object (obj_p, context_p), ret_value); ret_value = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } else { /* 11. */ ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } ecma_free_value (my_val); ECMA_FINALIZE (value); return ret_value; } /* ecma_builtin_json_str */
/** * GetValue operation part (object base). * * See also: ECMA-262 v5, 8.7.1, section 4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_get_value_object_base (ecma_reference_t ref) /**< ECMA-reference */ { const ecma_value_t base = ref.base; const bool is_unresolvable_reference = ecma_is_value_undefined (base); const bool has_primitive_base = (ecma_is_value_boolean (base) || ecma_is_value_number (base) || ecma_is_value_string (base)); const bool has_object_base = (ecma_is_value_object (base) && !(ecma_is_lexical_environment (ecma_get_object_from_value (base)))); const bool is_property_reference = has_primitive_base || has_object_base; JERRY_ASSERT (!is_unresolvable_reference); JERRY_ASSERT (is_property_reference); ecma_string_t *referenced_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, ref.referenced_name_cp); // 4.a if (!has_primitive_base) { // 4.b case 1 ecma_object_t *obj_p = ecma_get_object_from_value (base); JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); return ecma_op_object_get (obj_p, referenced_name_p); } else { // 4.b case 2 ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // 1. ECMA_TRY_CATCH (obj_base, ecma_op_to_object (base), ret_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_base); JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); // 2. ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, referenced_name_p); if (prop_p == NULL) { // 3. ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else if (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDDATA) { // 4. ret_value = ecma_copy_value (ecma_get_named_data_property_value (prop_p), true); } else { // 5. JERRY_ASSERT (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDACCESSOR); ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (prop_p); // 6. if (obj_p == NULL) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { // 7. ret_value = ecma_op_function_call (obj_p, base, NULL, 0); } } ECMA_FINALIZE (obj_base); return ret_value; } } /* ecma_op_get_value_object_base */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { 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 (arg2); ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 4. */ ECMA_TRY_CATCH (length_value, ecma_op_object_get (obj_p, length_magic_string_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, length_value, ret_value); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); /* 6. */ ecma_collection_header_t *arg_collection_p = ecma_new_values_collection (NULL, 0, true); /* 7. */ for (uint32_t index = 0; index < length && ecma_is_completion_value_empty (ret_value); index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value); ecma_append_to_values_collection (arg_collection_p, get_value, true); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (curr_idx_str_p); } JERRY_ASSERT (arg_collection_p->unit_number == length || !ecma_is_completion_value_empty (ret_value)); if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_op_function_call (func_obj_p, arg1, arg_collection_p); } ecma_free_values_collection (arg_collection_p, true); ECMA_OP_TO_NUMBER_FINALIZE (length_number); ECMA_FINALIZE (length_value); ecma_deref_ecma_string (length_magic_string_p); } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * The Function.prototype object's 'apply' routine * * See also: * ECMA-262 v5, 15.3.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_apply (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< first argument */ ecma_value_t arg2) /**< second argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *func_obj_p = ecma_get_object_from_value (this_arg); /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { ret_value = ecma_op_function_call (func_obj_p, arg1, NULL, 0); } else { /* 3. */ if (!ecma_is_value_object (arg2)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); /* 4. */ ECMA_TRY_CATCH (length_value, ecma_op_object_get (obj_p, length_magic_string_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, length_value, ret_value); /* 5. */ const uint32_t length = ecma_number_to_uint32 (length_number); /* 6. */ JMEM_DEFINE_LOCAL_ARRAY (arguments_list_p, length, ecma_value_t); uint32_t last_index = 0; /* 7. */ for (uint32_t index = 0; index < length && ecma_is_value_empty (ret_value); index++) { ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value); arguments_list_p[index] = ecma_copy_value (get_value); last_index = index + 1; ECMA_FINALIZE (get_value); ecma_deref_ecma_string (curr_idx_str_p); } if (ecma_is_value_empty (ret_value)) { JERRY_ASSERT (last_index == length); ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, length); } for (uint32_t index = 0; index < last_index; index++) { ecma_free_value (arguments_list_p[index]); } JMEM_FINALIZE_LOCAL_ARRAY (arguments_list_p); ECMA_OP_TO_NUMBER_FINALIZE (length_number); ECMA_FINALIZE (length_value); ecma_deref_ecma_string (length_magic_string_p); } } } return ret_value; } /* ecma_builtin_function_prototype_object_apply */
/** * [[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 */