/** * 'Greater-than' opcode handler. * * See also: ECMA-262 v5, 11.8.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t opfunc_greater_than (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, false); if (ECMA_IS_VALUE_ERROR (ret_value)) { return ret_value; } if (ecma_is_value_undefined (ret_value)) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } else { JERRY_ASSERT (ecma_is_value_boolean (ret_value)); } return ret_value; } /* opfunc_greater_than */
/** * Relation opcode handler. * * See also: ECMA-262 v5, 11.8.1, 11.8.2, 11.8.3, 11.8.4 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t opfunc_relation (ecma_value_t left_value, /**< left value */ ecma_value_t right_value, /**< right value */ bool left_first, /**< 'LeftFirst' flag */ bool is_invert) /**< is invert */ { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, left_first); if (ECMA_IS_VALUE_ERROR (ret_value)) { return ret_value; } if (ecma_is_value_undefined (ret_value)) { ret_value = ECMA_VALUE_FALSE; } else { JERRY_ASSERT (ecma_is_value_boolean (ret_value)); if (is_invert) { ret_value = ecma_invert_boolean_value (ret_value); } } return ret_value; } /* opfunc_relation */
/** * Equality opcode handler. * * See also: ECMA-262 v5, 11.9.1, 11.9.2 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t opfunc_equality (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); ecma_value_t compare_result = ecma_op_abstract_equality_compare (left_value, right_value); JERRY_ASSERT (ecma_is_value_boolean (compare_result) || ECMA_IS_VALUE_ERROR (compare_result)); return compare_result; } /* opfunc_equality */
/** * Implementation of 'CreateArrayFromList' specialized for iterators * * See also: * ECMA-262 v6, 7.3.16. * * Note: * Returned value must be freed with ecma_free_value. * * @return new array object */ ecma_value_t ecma_create_array_from_iter_element (ecma_value_t value, /**< value */ ecma_value_t index_value) /**< iterator index */ { /* 2. */ ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); /* 3 - 4. */ for (uint32_t index = 0; index < 2; index++) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); /* 4.a */ ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, (index == 0) ? index_value : value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, false); /* Failure handling */ /* 4.b */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); } /* 5. */ return new_array; } /* ecma_create_array_from_iter_element */
/** * Number object creation operation. * * See also: ECMA-262 v5, 15.7.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ { ecma_value_t conv_to_num_completion = ecma_op_to_number (arg); if (ECMA_IS_VALUE_ERROR (conv_to_num_completion)) { return conv_to_num_completion; } #ifndef CONFIG_DISABLE_NUMBER_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE); #else /* CONFIG_DISABLE_NUMBER_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_NUMBER_BUILTIN */ ecma_object_t *object_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); ecma_deref_object (prototype_obj_p); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_NUMBER_UL; /* Pass reference (no need to free conv_to_num_completion). */ ext_object_p->u.class_prop.value = conv_to_num_completion; return ecma_make_object_value (object_p); } /* ecma_op_create_number_object */
/** * 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 */
/** * 'in' opcode handler. * * See also: ECMA-262 v5, 11.8.7 * * @return ecma value * returned value must be freed with ecma_free_value. */ ecma_value_t opfunc_in (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { if (!ecma_is_value_object (right_value)) { return ecma_raise_type_error (ECMA_ERR_MSG ("Expected an object in 'in' check.")); } bool to_string = !ecma_is_value_string (left_value); if (to_string) { left_value = ecma_op_to_string (left_value); if (ECMA_IS_VALUE_ERROR (left_value)) { return left_value; } } ecma_string_t *left_value_prop_name_p = ecma_get_string_from_value (left_value); ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); ecma_value_t result = ecma_make_boolean_value (ecma_op_object_has_property (right_value_obj_p, left_value_prop_name_p)); if (to_string) { ecma_free_value (left_value); } return result; } /* opfunc_in */
/** * Number object creation operation. * * See also: ECMA-262 v5, 15.7.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ { ecma_value_t conv_to_num_completion = ecma_op_to_number (arg); if (ECMA_IS_VALUE_ERROR (conv_to_num_completion)) { return conv_to_num_completion; } #ifndef CONFIG_DISABLE_NUMBER_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE); #else /* CONFIG_DISABLE_NUMBER_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_NUMBER_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); ECMA_PROPERTY_VALUE_PTR (class_prop_p)->value = LIT_MAGIC_STRING_NUMBER_UL; ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); /* Pass reference (no need to free conv_to_num_completion). */ ecma_set_internal_property_value (prim_value_prop_p, conv_to_num_completion); return ecma_make_object_value (obj_p); } /* ecma_op_create_number_object */
/** * CreateMutableBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_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) { uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE; if (is_deletable) { prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_CONFIGURABLE); } ecma_create_named_data_property (lex_env_p, name_p, prop_attributes, NULL); } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_value_t completion; if (!ecma_get_object_extensible (binding_obj_p)) { return ECMA_VALUE_EMPTY; } completion = ecma_builtin_helper_def_prop (binding_obj_p, name_p, ECMA_VALUE_UNDEFINED, is_deletable ? ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE : ECMA_PROPERTY_ENUMERABLE_WRITABLE, true); /* Failure handling */ if (ECMA_IS_VALUE_ERROR (completion)) { return completion; } else { JERRY_ASSERT (ecma_is_value_boolean (completion)); } } return ECMA_VALUE_EMPTY; } /* ecma_op_create_mutable_binding */
/** * ArrayBuffer object creation operation. * * See also: ES2015 24.1.1.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< list of arguments that * are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_number_t length_num = 0; if (arguments_list_len > 0) { if (ecma_is_value_number (arguments_list_p[0])) { length_num = ecma_get_number_from_value (arguments_list_p[0]); } else { ecma_value_t to_number_value = ecma_op_to_number (arguments_list_p[0]); if (ECMA_IS_VALUE_ERROR (to_number_value)) { return to_number_value; } length_num = ecma_get_number_from_value (to_number_value); ecma_free_value (to_number_value); } if (ecma_number_is_nan (length_num)) { length_num = 0; } const uint32_t maximum_size_in_byte = UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1; if (length_num <= -1.0 || length_num > (double) maximum_size_in_byte + 0.5) { return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid ArrayBuffer length.")); } } uint32_t length_uint32 = ecma_number_to_uint32 (length_num); return ecma_make_object_value (ecma_arraybuffer_new_object (length_uint32)); } /* ecma_op_create_arraybuffer_object */
/** * SetMutableBinding operation. * * See also: ECMA-262 v5, 10.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_string_t *name_p, /**< argument N */ ecma_value_t value, /**< argument V */ bool is_strict) /**< argument S */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); JERRY_ASSERT (name_p != NULL); if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); if (ecma_is_property_writable (*property_p)) { ecma_named_data_property_assign_value (lex_env_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); } else if (is_strict) { return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set.")); } } else { JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); if (ECMA_IS_VALUE_ERROR (completion)) { return completion; } JERRY_ASSERT (ecma_is_value_boolean (completion)); } return ECMA_VALUE_EMPTY; } /* ecma_op_set_mutable_binding */
/** * The Object.keys and Object.getOwnPropertyNames routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return ecma value - Array of property names. * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ bool only_enumerable_properties) /**< list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); uint32_t index = 0; ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, only_enumerable_properties, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter)) { ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_p, index_string_p, *iter.current_value_p, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (index_string_p); index++; } ecma_free_values_collection (props_p, true); return new_array; } /* ecma_builtin_helper_object_get_properties */
/** * Process enqueued Promise jobs until the first thrown error or until the * jobqueue becomes empty. * * @return result of the last processed job - if the jobqueue was non-empty, * undefined - otherwise. */ ecma_value_t ecma_process_all_enqueued_jobs (void) { ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); while (JERRY_CONTEXT (job_queue_head_p) != NULL && !ECMA_IS_VALUE_ERROR (ret)) { ecma_job_queueitem_t *item_p = JERRY_CONTEXT (job_queue_head_p); JERRY_CONTEXT (job_queue_head_p) = JERRY_CONTEXT (job_queue_head_p)->next_p; void *job_p = item_p->job_p; ecma_job_handler_t handler = item_p->handler; jmem_heap_free_block (item_p, sizeof (ecma_job_queueitem_t)); ecma_free_value (ret); ret = handler (job_p); } return ret; } /* ecma_process_all_enqueued_jobs */
/** * Get value of function's argument mapped to index of Arguments object. * * Note: * The procedure emulates execution of function described by MakeArgGetter * * @return ecma value * Returned value must be freed with ecma_free_value */ static ecma_value_t ecma_arguments_get_mapped_arg_value (ecma_object_t *map_p, /**< [[ParametersMap]] object */ ecma_property_t *arg_name_prop_p) /**< property of [[ParametersMap]] corresponding to index and value equal to mapped argument's name */ { ecma_property_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (scope_prop_p)->value); JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); ecma_value_t arg_name_prop_value = ecma_get_named_data_property_value (arg_name_prop_p); ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name_prop_value); ecma_value_t completion = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion)); return completion; } /* ecma_arguments_get_mapped_arg_value */
/** * String object creation operation. * * See also: ECMA-262 v5, 15.5.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_value_t prim_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); if (arguments_list_len > 0) { prim_value = ecma_op_to_string (arguments_list_p[0]); if (ECMA_IS_VALUE_ERROR (prim_value)) { return prim_value; } JERRY_ASSERT (ecma_is_value_string (prim_value)); } #ifndef CONFIG_DISABLE_STRING_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE); #else /* CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *object_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); ecma_deref_object (prototype_obj_p); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_STRING_UL; ext_object_p->u.class_prop.u.value = prim_value; return ecma_make_object_value (object_p); } /* ecma_op_create_string_object */
/** * 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 value of function's argument mapped to index of Arguments object. * * Note: * The procedure emulates execution of function described by MakeArgGetter * * @return ecma value * Returned value must be freed with ecma_free_value */ void ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ ecma_property_t *property_p) /**< property value */ { ecma_value_t *map_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p); ecma_value_t arg_name = ecma_op_object_find (map_p, property_name_p); if (!ecma_is_value_found (arg_name)) { return; } ecma_value_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *scope_prop_p); JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name); ecma_value_t value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); ecma_deref_ecma_string (arg_name_p); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); ecma_named_data_property_assign_value (object_p, property_p, value); ecma_free_value (value); /* These properties cannot be cached. This is a temporary * workaround until the property management is fully rewritten. */ if (ecma_is_property_lcached (property_p)) { ecma_lcache_invalidate (object_p, property_name_p, property_p); } } /* ecma_arguments_update_mapped_arg_value */
/** * Dispatch set date functions * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_dispatch_set (uint16_t builtin_routine_id, /**< built-in wide routine * identifier */ ecma_extended_object_t *ext_object_p, /**< date extended object */ ecma_number_t date_num, /**< date converted to number */ const ecma_value_t arguments_list[], /**< list of arguments * passed to routine */ ecma_length_t arguments_number) /**< length of arguments' list */ { ecma_number_t converted_number[4]; ecma_length_t conversions = 0; /* If the first argument is not specified, it is always converted to NaN. */ converted_number[0] = ecma_number_make_nan (); switch (builtin_routine_id) { #ifndef CONFIG_DISABLE_ANNEXB_BUILTIN case ECMA_DATE_PROTOTYPE_SET_YEAR: #endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */ case ECMA_DATE_PROTOTYPE_SET_DATE: case ECMA_DATE_PROTOTYPE_SET_UTC_DATE: case ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS: case ECMA_DATE_PROTOTYPE_SET_MILLISECONDS: { conversions = 1; break; } case ECMA_DATE_PROTOTYPE_SET_MONTH: case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH: case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS: case ECMA_DATE_PROTOTYPE_SET_SECONDS: { conversions = 2; break; } case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR: case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR: case ECMA_DATE_PROTOTYPE_SET_MINUTES: case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES: { conversions = 3; break; } default: { JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_HOURS || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_HOURS); conversions = 4; break; } } if (conversions > arguments_number) { conversions = arguments_number; } for (ecma_length_t i = 0; i < conversions; i++) { ecma_value_t value = ecma_op_to_number (arguments_list[i]); if (ECMA_IS_VALUE_ERROR (value)) { return value; } converted_number[i] = ecma_get_number_from_value (value); ecma_free_value (value); } ecma_number_t day_part; ecma_number_t time_part; if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_DATE) { if (ecma_number_is_nan (date_num)) { if (ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE (builtin_routine_id)) { date_num = ECMA_NUMBER_ZERO; } else { return ecma_make_number_value (date_num); } } time_part = ecma_date_time_within_day (date_num); ecma_number_t year = ecma_date_year_from_time (date_num); ecma_number_t month = ecma_date_month_from_time (date_num); ecma_number_t day = ecma_date_date_from_time (date_num); switch (builtin_routine_id) { case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR: case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR: { year = converted_number[0]; if (conversions >= 2) { month = converted_number[1]; } if (conversions >= 3) { day = converted_number[2]; } break; } #ifndef CONFIG_DISABLE_ANNEXB_BUILTIN case ECMA_DATE_PROTOTYPE_SET_YEAR: { year = converted_number[0]; if (year >= 0 && year <= 99) { year += 1900; } break; } #endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */ case ECMA_DATE_PROTOTYPE_SET_MONTH: case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH: { month = converted_number[0]; if (conversions >= 2) { day = converted_number[1]; } break; } default: { JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_DATE || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_DATE); day = converted_number[0]; break; } } day_part = ecma_date_make_day (year, month, day); #ifndef CONFIG_DISABLE_ANNEXB_BUILTIN if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_YEAR) { builtin_routine_id = ECMA_DATE_PROTOTYPE_SET_UTC_YEAR; if (ecma_number_is_nan (converted_number[0])) { day_part = 0; time_part = converted_number[0]; } } #endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */ } else { if (ecma_number_is_nan (date_num)) { return ecma_make_number_value (date_num); } day_part = ecma_date_day (date_num); ecma_number_t hour = ecma_date_hour_from_time (date_num); ecma_number_t min = ecma_date_min_from_time (date_num); ecma_number_t sec = ecma_date_sec_from_time (date_num); ecma_number_t ms = ecma_date_ms_from_time (date_num); switch (builtin_routine_id) { case ECMA_DATE_PROTOTYPE_SET_HOURS: case ECMA_DATE_PROTOTYPE_SET_UTC_HOURS: { hour = converted_number[0]; if (conversions >= 2) { min = converted_number[1]; } if (conversions >= 3) { sec = converted_number[2]; } if (conversions >= 4) { ms = converted_number[3]; } break; } case ECMA_DATE_PROTOTYPE_SET_MINUTES: case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES: { min = converted_number[0]; if (conversions >= 2) { sec = converted_number[1]; } if (conversions >= 3) { ms = converted_number[2]; } break; } case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS: case ECMA_DATE_PROTOTYPE_SET_SECONDS: { sec = converted_number[0]; if (conversions >= 2) { ms = converted_number[1]; } break; } default: { JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_MILLISECONDS); ms = converted_number[0]; break; } } time_part = ecma_date_make_time (hour, min, sec, ms); } bool is_utc = BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id); ecma_number_t full_date = ecma_date_make_date (day_part, time_part); if (!is_utc) { full_date = ecma_date_utc (full_date); } full_date = ecma_date_time_clip (full_date); *ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, ext_object_p->u.class_prop.u.value) = full_date; return ecma_make_number_value (full_date); } /* ecma_builtin_date_prototype_dispatch_set */
/** * [[Call]] implementation for Function objects, * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION) * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION), * and for built-in Function objects * from section 15 (ECMA_OBJECT_TYPE_FUNCTION). * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ ecma_value_t this_arg_value, /**< 'this' argument's value */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< length of arguments list */ { JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); JERRY_ASSERT (ecma_op_is_callable (ecma_make_object_value (func_obj_p))); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { if (unlikely (ecma_get_object_is_builtin (func_obj_p))) { ret_value = ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } else { /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_func_p->u.function.scope_cp); // 8. ecma_value_t this_binding; bool is_strict; bool is_no_lex_env; const ecma_compiled_code_t *bytecode_data_p; bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, ext_func_p->u.function.bytecode_cp); is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) ? true : false; is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false; // 1. if (is_strict) { this_binding = ecma_copy_value (this_arg_value); } else if (ecma_is_value_undefined (this_arg_value) || ecma_is_value_null (this_arg_value)) { // 2. this_binding = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL)); } else { // 3., 4. this_binding = ecma_op_to_object (this_arg_value); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding)); } // 5. ecma_object_t *local_env_p; if (is_no_lex_env) { local_env_p = scope_p; } else { local_env_p = ecma_create_decl_lex_env (scope_p); if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED) { ecma_op_create_arguments_object (func_obj_p, local_env_p, arguments_list_p, arguments_list_len, bytecode_data_p); } } ret_value = vm_run (bytecode_data_p, this_binding, local_env_p, false, arguments_list_p, arguments_list_len); if (!is_no_lex_env) { ecma_deref_object (local_env_p); } ecma_free_value (this_binding); } } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
/** * String object creation operation. * * See also: ECMA-262 v5, 15.5.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_string_t *prim_prop_str_value_p; ecma_number_t length_value; if (arguments_list_len == 0) { prim_prop_str_value_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY); length_value = ECMA_NUMBER_ZERO; } else { ecma_value_t to_str_arg_value = ecma_op_to_string (arguments_list_p[0]); if (ECMA_IS_VALUE_ERROR (to_str_arg_value)) { return to_str_arg_value; } else { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (to_str_arg_value)); JERRY_ASSERT (ecma_is_value_string (to_str_arg_value)); prim_prop_str_value_p = ecma_get_string_from_value (to_str_arg_value); ecma_length_t string_len = ecma_string_get_length (prim_prop_str_value_p); length_value = ((ecma_number_t) (uint32_t) string_len); } } #ifndef CONFIG_DISABLE_STRING_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE); #else /* CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_STRING); ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_STRING type. * * See also: ecma_object_get_class_name */ ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_set_internal_property_value (prim_value_prop_p, ecma_make_string_value (prim_prop_str_value_p)); // 15.5.5.1 ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, length_magic_string_p, ECMA_PROPERTY_FIXED); ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_value)); ecma_deref_ecma_string (length_magic_string_p); return ecma_make_object_value (obj_p); } /* ecma_op_create_string_object */
/** * ECMA abstract equality comparison routine. * * See also: ECMA-262 v5, 11.9.3 * * Note: * This function might raise an exception, so the * returned value must be freed with ecma_free_value. * * @return true - if values are equal, * false - otherwise * error - in case of any problems */ ecma_value_t ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ ecma_value_t y) /**< second operand */ { if (x == y) { return ECMA_VALUE_TRUE; } if (ecma_are_values_integer_numbers (x, y)) { /* Note: the (x == y) comparison captures the true case. */ return ECMA_VALUE_FALSE; } if (ecma_is_value_number (x)) { if (ecma_is_value_number (y)) { /* 1.c */ ecma_number_t x_num = ecma_get_number_from_value (x); ecma_number_t y_num = ecma_get_number_from_value (y); bool is_x_equal_to_y = (x_num == y_num); #ifndef JERRY_NDEBUG bool is_x_equal_to_y_check; if (ecma_number_is_nan (x_num) || ecma_number_is_nan (y_num)) { is_x_equal_to_y_check = false; } else if (x_num == y_num || (ecma_number_is_zero (x_num) && ecma_number_is_zero (y_num))) { is_x_equal_to_y_check = true; } else { is_x_equal_to_y_check = false; } JERRY_ASSERT (is_x_equal_to_y == is_x_equal_to_y_check); #endif /* !JERRY_NDEBUG */ return ecma_make_boolean_value (is_x_equal_to_y); } /* Swap values. */ ecma_value_t tmp = x; x = y; y = tmp; } if (ecma_is_value_string (x)) { if (ecma_is_value_string (y)) { /* 1., d. */ ecma_string_t *x_str_p = ecma_get_string_from_value (x); ecma_string_t *y_str_p = ecma_get_string_from_value (y); bool is_equal = ecma_compare_ecma_strings (x_str_p, y_str_p); return ecma_make_boolean_value (is_equal); } if (ecma_is_value_number (y)) { /* 4. */ ecma_value_t x_num_value = ecma_op_to_number (x); if (ECMA_IS_VALUE_ERROR (x_num_value)) { return x_num_value; } ecma_value_t compare_result = ecma_op_abstract_equality_compare (x_num_value, y); ecma_free_value (x_num_value); return compare_result; } /* Swap values. */ ecma_value_t tmp = x; x = y; y = tmp; } #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) if (ecma_is_value_symbol (x)) { return ECMA_VALUE_FALSE; } #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ if (ecma_is_value_boolean (y)) { if (ecma_is_value_boolean (x)) { /* 1., e. */ /* Note: the (x == y) comparison captures the true case. */ return ECMA_VALUE_FALSE; } /* 7. */ return ecma_op_abstract_equality_compare (x, ecma_make_integer_value (ecma_is_value_true (y) ? 1 : 0)); } if (ecma_is_value_object (x)) { if (ecma_is_value_string (y) #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) || ecma_is_value_symbol (y) #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ || ecma_is_value_number (y)) { /* 9. */ ecma_value_t x_prim_value = ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NO); if (ECMA_IS_VALUE_ERROR (x_prim_value)) { return x_prim_value; } ecma_value_t compare_result = ecma_op_abstract_equality_compare (x_prim_value, y); ecma_free_value (x_prim_value); return compare_result; } /* 1., f. */ /* Note: the (x == y) comparison captures the true case. */ return ECMA_VALUE_FALSE; } if (ecma_is_value_boolean (x)) { /* 6. */ return ecma_op_abstract_equality_compare (ecma_make_integer_value (ecma_is_value_true (x) ? 1 : 0), y); } if (ecma_is_value_undefined (x) || ecma_is_value_null (x)) { /* 1. a., b. */ /* 2., 3. */ bool is_equal = ecma_is_value_undefined (y) || ecma_is_value_null (y); return ecma_make_boolean_value (is_equal); } return ECMA_VALUE_FALSE; } /* ecma_op_abstract_equality_compare */
/** * ECMA abstract relational comparison routine. * * See also: ECMA-262 v5, 11.8.5 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_abstract_relational_compare (ecma_value_t x, /**< first operand */ ecma_value_t y, /**< second operand */ bool left_first) /**< 'LeftFirst' flag */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; /* 1., 2. */ ecma_value_t prim_first_converted_value = ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NUMBER); if (ECMA_IS_VALUE_ERROR (prim_first_converted_value)) { return prim_first_converted_value; } ecma_value_t prim_second_converted_value = ecma_op_to_primitive (y, ECMA_PREFERRED_TYPE_NUMBER); if (ECMA_IS_VALUE_ERROR (prim_second_converted_value)) { ecma_free_value (prim_first_converted_value); return prim_second_converted_value; } const ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value; const ecma_value_t py = left_first ? prim_second_converted_value : prim_first_converted_value; const bool is_px_string = ecma_is_value_string (px); const bool is_py_string = ecma_is_value_string (py); if (!(is_px_string && is_py_string)) { /* 3. */ /* a. */ ECMA_OP_TO_NUMBER_TRY_CATCH (nx, px, ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (ny, py, ret_value); /* b. */ if (ecma_number_is_nan (nx) || ecma_number_is_nan (ny)) { /* c., d. */ ret_value = ECMA_VALUE_UNDEFINED; } else { bool is_x_less_than_y = (nx < ny); #ifndef JERRY_NDEBUG bool is_x_less_than_y_check; if (nx == ny || (ecma_number_is_zero (nx) && ecma_number_is_zero (ny))) { /* e., f., g. */ is_x_less_than_y_check = false; } else if (ecma_number_is_infinity (nx) && !ecma_number_is_negative (nx)) { /* h. */ is_x_less_than_y_check = false; } else if (ecma_number_is_infinity (ny) && !ecma_number_is_negative (ny)) { /* i. */ is_x_less_than_y_check = true; } else if (ecma_number_is_infinity (ny) && ecma_number_is_negative (ny)) { /* j. */ is_x_less_than_y_check = false; } else if (ecma_number_is_infinity (nx) && ecma_number_is_negative (nx)) { /* k. */ is_x_less_than_y_check = true; } else { /* l. */ JERRY_ASSERT (!ecma_number_is_nan (nx) && !ecma_number_is_infinity (nx)); JERRY_ASSERT (!ecma_number_is_nan (ny) && !ecma_number_is_infinity (ny)); JERRY_ASSERT (!(ecma_number_is_zero (nx) && ecma_number_is_zero (ny))); if (nx < ny) { is_x_less_than_y_check = true; } else { is_x_less_than_y_check = false; } } JERRY_ASSERT (is_x_less_than_y_check == is_x_less_than_y); #endif /* !JERRY_NDEBUG */ ret_value = ecma_make_boolean_value (is_x_less_than_y); } ECMA_OP_TO_NUMBER_FINALIZE (ny); ECMA_OP_TO_NUMBER_FINALIZE (nx); } else { /* 4. */ JERRY_ASSERT (is_px_string && is_py_string); ecma_string_t *str_x_p = ecma_get_string_from_value (px); ecma_string_t *str_y_p = ecma_get_string_from_value (py); bool is_px_less = ecma_compare_ecma_strings_relational (str_x_p, str_y_p); ret_value = ecma_make_boolean_value (is_px_less); } ecma_free_value (prim_second_converted_value); ecma_free_value (prim_first_converted_value); return ret_value; } /* ecma_op_abstract_relational_compare */
/** * 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 */
/** * ToPropertyDescriptor operation. * * See also: * ECMA-262 v5, 8.10.5 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor if return value is normal empty completion value */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); // 1. if (!ecma_is_value_object (obj_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); // 2. ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); // 3. ecma_string_t *enumerable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE); if (ecma_op_object_get_property (obj_p, enumerable_magic_string_p) != NULL) { ECMA_TRY_CATCH (enumerable_prop_value, ecma_op_object_get (obj_p, enumerable_magic_string_p), ret_value); prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = ecma_op_to_boolean (enumerable_prop_value); ECMA_FINALIZE (enumerable_prop_value); } ecma_deref_ecma_string (enumerable_magic_string_p); if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 4. ecma_string_t *configurable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE); if (ecma_op_object_get_property (obj_p, configurable_magic_string_p) != NULL) { ECMA_TRY_CATCH (configurable_prop_value, ecma_op_object_get (obj_p, configurable_magic_string_p), ret_value); prop_desc.is_configurable_defined = true; prop_desc.is_configurable = ecma_op_to_boolean (configurable_prop_value); ECMA_FINALIZE (configurable_prop_value); } ecma_deref_ecma_string (configurable_magic_string_p); } if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 5. ecma_string_t *value_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUE); if (ecma_op_object_get_property (obj_p, value_magic_string_p) != NULL) { ECMA_TRY_CATCH (value_prop_value, ecma_op_object_get (obj_p, value_magic_string_p), ret_value); prop_desc.is_value_defined = true; prop_desc.value = ecma_copy_value (value_prop_value); ECMA_FINALIZE (value_prop_value); } ecma_deref_ecma_string (value_magic_string_p); } if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 6. ecma_string_t *writable_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE); if (ecma_op_object_get_property (obj_p, writable_magic_string_p) != NULL) { ECMA_TRY_CATCH (writable_prop_value, ecma_op_object_get (obj_p, writable_magic_string_p), ret_value); prop_desc.is_writable_defined = true; prop_desc.is_writable = ecma_op_to_boolean (writable_prop_value); ECMA_FINALIZE (writable_prop_value); } ecma_deref_ecma_string (writable_magic_string_p); } if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 7. ecma_string_t *get_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GET); if (ecma_op_object_get_property (obj_p, get_magic_string_p) != NULL) { ECMA_TRY_CATCH (get_prop_value, ecma_op_object_get (obj_p, get_magic_string_p), ret_value); if (!ecma_op_is_callable (get_prop_value) && !ecma_is_value_undefined (get_prop_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { prop_desc.is_get_defined = true; if (ecma_is_value_undefined (get_prop_value)) { prop_desc.get_p = NULL; } else { JERRY_ASSERT (ecma_is_value_object (get_prop_value)); ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value); ecma_ref_object (get_p); prop_desc.get_p = get_p; } } ECMA_FINALIZE (get_prop_value); } ecma_deref_ecma_string (get_magic_string_p); } if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 8. ecma_string_t *set_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SET); if (ecma_op_object_get_property (obj_p, set_magic_string_p) != NULL) { ECMA_TRY_CATCH (set_prop_value, ecma_op_object_get (obj_p, set_magic_string_p), ret_value); if (!ecma_op_is_callable (set_prop_value) && !ecma_is_value_undefined (set_prop_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { prop_desc.is_set_defined = true; if (ecma_is_value_undefined (set_prop_value)) { prop_desc.set_p = NULL; } else { JERRY_ASSERT (ecma_is_value_object (set_prop_value)); ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value); ecma_ref_object (set_p); prop_desc.set_p = set_p; } } ECMA_FINALIZE (set_prop_value); } ecma_deref_ecma_string (set_magic_string_p); } if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); // 9. if (prop_desc.is_get_defined || prop_desc.is_set_defined) { if (prop_desc.is_value_defined || prop_desc.is_writable_defined) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } } } if (!ECMA_IS_VALUE_ERROR (ret_value)) { JERRY_ASSERT (ecma_is_value_empty (ret_value)); } else { ecma_free_property_descriptor (&prop_desc); } *out_prop_desc_p = prop_desc; } return ret_value; } /* ecma_op_to_property_descriptor */
ecma_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ { lit_magic_string_id_t type_string; if (ecma_is_value_undefined (this_arg)) { type_string = LIT_MAGIC_STRING_UNDEFINED_UL; } else if (ecma_is_value_null (this_arg)) { type_string = LIT_MAGIC_STRING_NULL_UL; } else { ecma_value_t obj_this = ecma_op_to_object (this_arg); if (ECMA_IS_VALUE_ERROR (obj_this)) { return obj_this; } JERRY_ASSERT (ecma_is_value_object (obj_this)); ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); type_string = ecma_object_get_class_name (obj_p); ecma_free_value (obj_this); } ecma_string_t *ret_string_p; /* Building string "[object #type#]" where type is 'Undefined', 'Null' or one of possible object's classes. The string with null character is maximum 19 characters long. */ const lit_utf8_size_t buffer_size = 19; JMEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *buffer_ptr = str_buffer; const lit_magic_string_id_t magic_string_ids[] = { LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, LIT_MAGIC_STRING_OBJECT, LIT_MAGIC_STRING_SPACE_CHAR, type_string, LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR }; for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) { buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); } ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); return ecma_make_string_value (ret_string_p); } /* ecma_builtin_helper_object_to_string */
/** * Update the length of an array to a new length * * @return ecma value * Returned value must be freed with ecma_free_value */ extern ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ ecma_value_t new_value, /**< new length value */ uint32_t flags) /**< configuration options */ { bool is_throw = (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW); ecma_value_t completion = ecma_op_to_number (new_value); if (ECMA_IS_VALUE_ERROR (completion)) { return completion; } JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion) && ecma_is_value_number (completion)); ecma_number_t new_len_num = ecma_get_number_from_value (completion); ecma_free_value (completion); if (ecma_is_value_object (new_value)) { ecma_value_t compared_num_val = ecma_op_to_number (new_value); if (ECMA_IS_VALUE_ERROR (completion)) { return compared_num_val; } new_len_num = ecma_get_number_from_value (compared_num_val); ecma_free_value (compared_num_val); } uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); if (((ecma_number_t) new_len_uint32) != new_len_num) { return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length.")); } if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT) { return ecma_reject (is_throw); } ecma_string_t magic_string_length; ecma_init_ecma_length_string (&magic_string_length); ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); uint32_t old_len_uint32 = ecma_get_uint32_from_value (len_prop_value_p->value); if (new_len_num == old_len_uint32) { /* Only the writable flag must be updated. */ if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) { if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { ecma_set_property_writable_attr (len_prop_p, false); } else if (!ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else if (!ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } uint32_t current_len_uint32 = new_len_uint32; if (new_len_uint32 < old_len_uint32) { current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32); } ecma_value_assign_uint32 (&len_prop_value_p->value, current_len_uint32); if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) && !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { ecma_set_property_writable_attr (len_prop_p, false); } if (current_len_uint32 == new_len_uint32) { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } return ecma_reject (is_throw); } /* ecma_op_array_object_set_length */
/** * Runtime Semantics: PerformPromiseRace. * * See also: * ES2015 25.4.4.3.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_do_race (ecma_value_t array, /**< the array for race */ ecma_value_t capability, /**< PromiseCapability record */ ecma_value_t ctor) /**< the caller of Promise.race */ { JERRY_ASSERT (ecma_is_value_object (capability) && ecma_is_value_object (array) && ecma_is_value_object (ctor)); JERRY_ASSERT (ecma_get_object_builtin_id (ecma_get_object_from_value (ctor)) == ECMA_BUILTIN_ID_PROMISE); JERRY_ASSERT (ecma_get_object_type (ecma_get_object_from_value (array)) == ECMA_OBJECT_TYPE_ARRAY); ecma_value_t ret = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); ecma_object_t *array_p = ecma_get_object_from_value (array); ecma_value_t len_value = ecma_op_object_get (array_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); ecma_length_t len = (ecma_length_t) ecma_get_integer_from_value (len_value); ecma_fast_free_value (len_value); ecma_string_t *str_promise = ecma_new_ecma_string_from_uint32 (ECMA_PROMISE_PROPERTY_PROMISE); 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); ecma_value_t resolve = ecma_op_object_get (ecma_get_object_from_value (capability), str_resolve); ecma_value_t reject = ecma_op_object_get (ecma_get_object_from_value (capability), str_reject); for (ecma_length_t index = 0; index <= len; index++) { /* b-d. */ if (index == len) { ret = ecma_op_object_get (ecma_get_object_from_value (capability), str_promise); break; } /* e. */ ecma_string_t *str_index = ecma_new_ecma_string_from_uint32 (index); ecma_value_t array_item = ecma_op_object_get (array_p, str_index); ecma_deref_ecma_string (str_index); /* h. */ ecma_value_t next_promise = ecma_builtin_promise_resolve (ctor, array_item); ecma_free_value (array_item); /* i. */ if (ECMA_IS_VALUE_ERROR (next_promise)) { ret = next_promise; break; } /* j. */ ecma_value_t then_result = ecma_promise_then (next_promise, resolve, reject); ecma_free_value (next_promise); /* k. */ if (ECMA_IS_VALUE_ERROR (then_result)) { ret = then_result; break; } ecma_free_value (then_result); } ecma_free_value (reject); ecma_free_value (resolve); ecma_deref_ecma_string (str_promise); ecma_deref_ecma_string (str_resolve); ecma_deref_ecma_string (str_reject); JERRY_ASSERT (!ecma_is_value_empty (ret)); return ret; } /* ecma_builtin_promise_do_race */
/** * Send result of evaluated expression or throw an error. * * @return true - if execution should be resumed * false - otherwise */ static bool jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */ size_t eval_string_size) /**< evaluated string size */ { JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED); JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE); ecma_value_t result = ecma_op_eval_chars_buffer (eval_string_p + 1, eval_string_size - 1, true, false); JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE); if (!ECMA_IS_VALUE_ERROR (result)) { if (eval_string_p[0] != JERRY_DEBUGGER_EVAL_EVAL) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); JERRY_CONTEXT (error_value) = result; /* Stop where the error is caught. */ JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; if (eval_string_p[0] == JERRY_DEBUGGER_EVAL_THROW) { JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION; } else { JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_EXCEPTION; } return true; } if (!ecma_is_value_string (result)) { ecma_value_t to_string_value = ecma_op_to_string (result); ecma_free_value (result); result = to_string_value; } } ecma_value_t message = result; uint8_t type = JERRY_DEBUGGER_EVAL_OK; if (ECMA_IS_VALUE_ERROR (result)) { type = JERRY_DEBUGGER_EVAL_ERROR; result = JERRY_CONTEXT (error_value); if (ecma_is_value_object (result)) { message = ecma_op_object_find (ecma_get_object_from_value (result), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); if (!ecma_is_value_string (message) || ecma_string_is_empty (ecma_get_string_from_value (message))) { ecma_free_value (message); lit_magic_string_id_t id = ecma_object_get_class_name (ecma_get_object_from_value (result)); ecma_free_value (result); const lit_utf8_byte_t *string_p = lit_get_magic_string_utf8 (id); jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, string_p, strlen ((const char *) string_p)); return false; } } else { /* Primitive type. */ message = ecma_op_to_string (result); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (message)); } ecma_free_value (result); } ecma_string_t *string_p = ecma_get_string_from_value (message); ECMA_STRING_TO_UTF8_STRING (string_p, buffer_p, buffer_size); jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, buffer_p, buffer_size); ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); ecma_free_value (message); return false; } /* jerry_debugger_send_eval */
/** * 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 */
/** * 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 */