/** * Helper function for increase or decrease the remaining count. * * @return the current remaining count after increase or decrease. */ static ecma_length_t ecma_builtin_promise_remaining_inc_or_dec (ecma_value_t remaining, /**< the remaining count */ bool is_inc) /**< whether to increase the count */ { JERRY_ASSERT (ecma_is_value_object (remaining)); ecma_object_t *remaining_p = ecma_get_object_from_value (remaining); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) remaining_p; JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_NUMBER_UL); JERRY_ASSERT (ecma_is_value_integer_number (ext_object_p->u.class_prop.u.value)); ecma_length_t current = (ecma_length_t) ecma_get_integer_from_value (ext_object_p->u.class_prop.u.value); if (is_inc) { current++; } else { current--; } ext_object_p->u.class_prop.u.value = ecma_make_uint32_value (current); return current; } /* ecma_builtin_promise_remaining_inc_or_dec */
/** * ToBoolean operation. Cannot throw an exception. * * See also: * ECMA-262 v5, 9.2 * * @return true if the logical value is true * false otherwise */ bool ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_simple (value)) { JERRY_ASSERT (ecma_is_value_boolean (value) || ecma_is_value_undefined (value) || ecma_is_value_null (value)); return ecma_is_value_true (value); } if (ecma_is_value_integer_number (value)) { return (value != ecma_make_integer_value (0)); } if (ecma_is_value_float_number (value)) { ecma_number_t num = ecma_get_float_from_value (value); return (!ecma_number_is_nan (num) && !ecma_number_is_zero (num)); } if (ecma_is_value_string (value)) { ecma_string_t *str_p = ecma_get_string_from_value (value); return ecma_string_get_length (str_p) != 0; } JERRY_ASSERT (ecma_is_value_object (value)); return true; } /* ecma_op_to_boolean */
/** * ECMA strict equality comparison routine. * * See also: ECMA-262 v5, 11.9.6 * * @return true - if values are strict equal, * false - otherwise */ bool ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */ ecma_value_t y) /**< second operand */ { if (ecma_is_value_direct (x) || ecma_is_value_direct (y) #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) || ecma_is_value_symbol (x) || ecma_is_value_symbol (y) #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ || ecma_is_value_object (x) || ecma_is_value_object (y)) { JERRY_ASSERT (!ecma_is_value_direct (x) || ecma_is_value_undefined (x) || ecma_is_value_null (x) || ecma_is_value_boolean (x) || ecma_is_value_integer_number (x)); JERRY_ASSERT (!ecma_is_value_direct (y) || ecma_is_value_undefined (y) || ecma_is_value_null (y) || ecma_is_value_boolean (y) || ecma_is_value_integer_number (y)); if ((x != ecma_make_integer_value (0) || !ecma_is_value_float_number (y)) && (y != ecma_make_integer_value (0) || !ecma_is_value_float_number (x))) { return (x == y); } /* The +0 === -0 case handled below. */ } JERRY_ASSERT (ecma_is_value_number (x) || ecma_is_value_string (x)); JERRY_ASSERT (ecma_is_value_number (y) || ecma_is_value_string (y)); if (ecma_is_value_string (x)) { if (!ecma_is_value_string (y)) { return false; } ecma_string_t *x_str_p = ecma_get_string_from_value (x); ecma_string_t *y_str_p = ecma_get_string_from_value (y); return ecma_compare_ecma_strings (x_str_p, y_str_p); } if (!ecma_is_value_number (y)) { return false; } 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 is_x_equal_to_y; } /* ecma_op_strict_equality_compare */
/** * ToString operation. * * See also: * ECMA-262 v5, 9.8 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_string (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (unlikely (ecma_is_value_object (value))) { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (prim_value, ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING), ret_value); ret_value = ecma_op_to_string (prim_value); ECMA_FINALIZE (prim_value); return ret_value; } else { ecma_string_t *res_p = NULL; if (ecma_is_value_string (value)) { res_p = ecma_get_string_from_value (value); res_p = ecma_copy_or_ref_ecma_string (res_p); } else if (ecma_is_value_integer_number (value)) { ecma_integer_value_t num = ecma_get_integer_from_value (value); if (num < 0) { res_p = ecma_new_ecma_string_from_number ((ecma_number_t) num); } else { res_p = ecma_new_ecma_string_from_uint32 ((uint32_t) num); } } else if (ecma_is_value_float_number (value)) { ecma_number_t num = ecma_get_float_from_value (value); res_p = ecma_new_ecma_string_from_number (num); } else if (ecma_is_value_undefined (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); } else if (ecma_is_value_null (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); if (ecma_is_value_true (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); } else { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); } } return ecma_make_string_value (res_p); } } /* ecma_op_to_string */
/** * ToNumber operation. * * See also: * ECMA-262 v5, 9.3 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_to_number (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); if (ecma_is_value_integer_number (value)) { return value; } else if (ecma_is_value_float_number (value)) { return ecma_copy_value (value); } else if (ecma_is_value_string (value)) { ecma_string_t *str_p = ecma_get_string_from_value (value); return ecma_make_number_value (ecma_string_to_number (str_p)); } else if (ecma_is_value_object (value)) { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (primitive_value, ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NUMBER), ret_value); ret_value = ecma_op_to_number (primitive_value); ECMA_FINALIZE (primitive_value); return ret_value; } else { int16_t num = 0; if (ecma_is_value_undefined (value)) { return ecma_make_nan_value (); } else if (ecma_is_value_null (value)) { num = 0; } else { JERRY_ASSERT (ecma_is_value_boolean (value)); if (ecma_is_value_true (value)) { num = 1; } else { num = 0; } } return ecma_make_integer_value (num); } } /* ecma_op_to_number */
/** * 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_VALUE_EMPTY; /* 2. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function.")); } else { /* 4. 11. 18. */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_length_t args_length = arguments_number; ecma_object_t *function_p; ecma_extended_object_t *ext_function_p; if (arguments_number == 0 || (arguments_number == 1 && !ecma_is_value_integer_number (arguments_list_p[0]))) { args_length = 1; function_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_BOUND_FUNCTION); /* 8. */ ext_function_p = (ecma_extended_object_t *) function_p; ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg); ECMA_SET_INTERNAL_VALUE_POINTER (ext_function_p->u.bound_function.target_function, this_arg_obj_p); ext_function_p->u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED; if (arguments_number != 0) { ext_function_p->u.bound_function.args_len_or_this = ecma_copy_value_if_not_object (arguments_list_p[0]); } } else { JERRY_ASSERT (arguments_number > 0); size_t obj_size = sizeof (ecma_extended_object_t) + (args_length * sizeof (ecma_value_t)); function_p = ecma_create_object (prototype_obj_p, obj_size, ECMA_OBJECT_TYPE_BOUND_FUNCTION); /* 8. */ ext_function_p = (ecma_extended_object_t *) function_p; ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg); ECMA_SET_INTERNAL_VALUE_POINTER (ext_function_p->u.bound_function.target_function, this_arg_obj_p); /* NOTE: This solution provides temporary false data about the object's size but prevents GC from freeing it until it's not fully initialized. */ ext_function_p->u.bound_function.args_len_or_this = ECMA_VALUE_UNDEFINED; ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1); for (ecma_length_t i = 0; i < arguments_number; i++) { *args_p++ = ecma_copy_value_if_not_object (arguments_list_p[i]); } ecma_value_t args_len_or_this = ecma_make_integer_value ((ecma_integer_value_t) args_length); ext_function_p->u.bound_function.args_len_or_this = args_len_or_this; } ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ /* 22. */ ret_value = ecma_make_object_value (function_p); } return ret_value; } /* ecma_builtin_function_prototype_object_bind */