From d0435e1db0f489c6e1edca694705600734b7aca4 Mon Sep 17 00:00:00 2001 From: Virag Orkenyi Date: Tue, 27 Aug 2019 10:18:51 +0200 Subject: [PATCH] Implemented Number object routines (#2972) Implemented Number.isNaN & Number.isFinite & Number.isSafeInteger & Number.isInteger & Number.EPSILON. JerryScript-DCO-1.0-Signed-off-by: Virag Orkenyi orkvi@inf.u-szeged.hu --- jerry-core/ecma/base/ecma-globals.h | 17 ++- .../builtin-objects/ecma-builtin-number.c | 129 ++++++++++++++++++ .../builtin-objects/ecma-builtin-number.inc.h | 8 ++ .../builtin-objects/ecma-builtins-internal.h | 4 + .../ecma/builtin-objects/ecma-builtins.c | 6 +- jerry-core/lit/lit-magic-strings.inc.h | 6 + jerry-core/lit/lit-magic-strings.ini | 2 + tests/jerry/es2015/number-isfinite.js | 19 +++ tests/jerry/es2015/number-isinteger.js | 21 +++ tests/jerry/es2015/number-isnan.js | 19 +++ tests/jerry/es2015/number-issafeinteger.js | 20 +++ 11 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 tests/jerry/es2015/number-isfinite.js create mode 100644 tests/jerry/es2015/number-isinteger.js create mode 100644 tests/jerry/es2015/number-isnan.js create mode 100644 tests/jerry/es2015/number-issafeinteger.js diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 8a7e77728..9f7f57f8b 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1109,7 +1109,22 @@ typedef double ecma_number_t; */ # define ECMA_NUMBER_MIN_VALUE ((ecma_number_t) 5e-324) #endif /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ - +#if ENABLED (JERRY_ES2015_BUILTIN) +/** + * Number.EPSILON + * + * See also: ECMA_262 v6, 20.1.2.1 + */ +# define ECMA_NUMBER_EPSILON ((ecma_number_t) 2.2204460492503130808472633361816e-16) +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ +#if ENABLED (JERRY_ES2015_BUILTIN) +/** + * Number.MAX_SAFE_INTEGER + * + * See also: ECMA_262 v6, 20.1.2.1 + */ +# define ECMA_NUMBER_MAX_SAFE_INTEGER ((ecma_number_t) 0x1FFFFFFFFFFFFF) +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ /** * Euler number */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number.c b/jerry-core/ecma/builtin-objects/ecma-builtin-number.c index f34854b98..26544080f 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number.c @@ -24,6 +24,7 @@ #include "ecma-objects.h" #include "ecma-try-catch-macro.h" #include "jrt.h" +#include "math.h" #if ENABLED (JERRY_BUILTIN_NUMBER) @@ -91,6 +92,134 @@ ecma_builtin_number_dispatch_construct (const ecma_value_t *arguments_list_p, /* } } /* ecma_builtin_number_dispatch_construct */ +#if ENABLED (JERRY_ES2015_BUILTIN) +/** + * The Number object 'isFinite' routine + * + * See also: + * ECMA-262 v6, 20.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_object_is_finite (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + JERRY_UNUSED (this_arg); + + if (ecma_is_value_number (arg)) + { + ecma_number_t num = ecma_get_number_from_value (arg); + if (!(ecma_number_is_nan (num) || ecma_number_is_infinity (num))) + { + return ECMA_VALUE_TRUE; + } + } + return ECMA_VALUE_FALSE; +} /* ecma_builtin_number_object_is_finite */ + +/** + * The Number object 'isNan' routine + * + * See also: + * ECMA-262 v6, 20.1.2.4 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_object_is_nan (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + JERRY_UNUSED (this_arg); + + if (ecma_is_value_number (arg)) + { + ecma_number_t num_val = ecma_get_number_from_value (arg); + + if (ecma_number_is_nan (num_val)) + { + return ECMA_VALUE_TRUE; + } + } + return ECMA_VALUE_FALSE; +} /* ecma_builtin_number_object_is_nan */ + +/** + * The Number object 'isInteger' routine + * + * See also: + * ECMA-262 v6, 20.1.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_object_is_integer (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + JERRY_UNUSED (this_arg); + if (!ecma_is_value_number (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t num = ecma_get_number_from_value (arg); + + if (ecma_number_is_nan (num) || ecma_number_is_infinity (num)) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t int_num = ecma_number_trunc (num); + + if (int_num != num) + { + return ECMA_VALUE_FALSE; + } + + return ECMA_VALUE_TRUE; +} /* ecma_builtin_number_object_is_integer */ + +/** + * The Number object 'isSafeInteger' routine + * + * See also: + * ECMA-262 v6, 20.1.2.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_number_object_is_safe_integer (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg) /**< routine's argument */ +{ + JERRY_UNUSED (this_arg); + + if (!ecma_is_value_number (arg)) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t num = ecma_get_number_from_value (arg); + + if (ecma_number_is_nan (num) || ecma_number_is_infinity (num)) + { + return ECMA_VALUE_FALSE; + } + + ecma_number_t int_num = ecma_number_trunc (num); + + if (int_num == num && fabs (int_num) <= ECMA_NUMBER_MAX_SAFE_INTEGER) + { + return ECMA_VALUE_TRUE; + } + + return ECMA_VALUE_FALSE; +} /* ecma_builtin_number_object_is_safe_integer */ +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ + /** * @} * @} diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h index 0d768a4b8..695f9cb9d 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h @@ -64,4 +64,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, #endif /* ENABLED (JERRY_BUILTIN_NUMBER) */ +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +#if ENABLED (JERRY_ES2015_BUILTIN) +ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ecma_builtin_number_object_is_finite, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_NAN, ecma_builtin_number_object_is_nan, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_INTEGER, ecma_builtin_number_object_is_integer, 1, 1) +ROUTINE (LIT_MAGIC_STRING_IS_SAFE_INTEGER, ecma_builtin_number_object_is_safe_integer, 1, 1) +#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h index bf3b6fb0a..c82672bd9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h @@ -48,6 +48,10 @@ typedef enum { ECMA_BUILTIN_NUMBER_MAX = 256, /**< value of ECMA_NUMBER_MAX_VALUE */ ECMA_BUILTIN_NUMBER_MIN, /**< value of ECMA_NUMBER_MIN_VALUE */ +#if ENABLED (JERRY_ES2015_BUILTIN) + ECMA_BUILTIN_NUMBER_EPSILON, /**< value of ECMA_NUMBER_EPSILON */ + ECMA_BUILTIN_NUMBER_MAX_SAFE_INTEGER, /**< value of ECMA_NUMBER_MAX_SAFE_INTEGER */ +#endif /* ENABLED (JERRY_BUILTIN_NUMBER) */ ECMA_BUILTIN_NUMBER_E, /**< value of ECMA_NUMBER_E */ ECMA_BUILTIN_NUMBER_PI, /**< value of ECMA_NUMBER_PI */ ECMA_BUILTIN_NUMBER_LN10, /**< value of ECMA_NUMBER_LN10 */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index fd98cd8db..b0af8931f 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -741,6 +741,10 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * { ECMA_NUMBER_MAX_VALUE, ECMA_NUMBER_MIN_VALUE, +#if ENABLED (JERRY_ES2015_BUILTIN) + ECMA_NUMBER_EPSILON, + ECMA_NUMBER_MAX_SAFE_INTEGER, +#endif /* ENABLED (JERRY_BUILTIN_NUMBER) */ ECMA_NUMBER_E, ECMA_NUMBER_PI, ECMA_NUMBER_LN10, @@ -748,7 +752,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * ECMA_NUMBER_LOG2E, ECMA_NUMBER_LOG10E, ECMA_NUMBER_SQRT2, - ECMA_NUMBER_SQRT_1_2 + ECMA_NUMBER_SQRT_1_2, }; num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX]; diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 0efe7445d..fcead7c1f 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -512,6 +512,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DAY_UL, "getUTCDay") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT16_UL, "getUint16") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT32_UL, "getUint32") #endif +#if ENABLED (JERRY_ES2015_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_INTEGER, "isInteger") +#endif #if ENABLED (JERRY_BUILTIN_REGEXP) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LASTINDEX_UL, "lastIndex") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MULTILINE, "multiline") @@ -667,6 +670,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MINUTES_UL, "getUTCMinutes") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_SECONDS_UL, "getUTCSeconds") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, "isPrototypeOf") +#if ENABLED (JERRY_ES2015_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SAFE_INTEGER, "isSafeInteger") +#endif #if ENABLED (JERRY_BUILTIN_STRING) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOCALE_COMPARE_UL, "localeCompare") #endif diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index 1a37d1249..7ae4b1a0f 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -209,6 +209,7 @@ LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL = "-Infinity" LIT_MAGIC_STRING_ARGUMENTS_UL = "Arguments" LIT_MAGIC_STRING_EVAL_ERROR_UL = "EvalError" LIT_MAGIC_STRING_INT8_ARRAY_UL = "Int8Array" +LIT_MAGIC_STRING_IS_INTEGER = "isInteger" LIT_MAGIC_STRING_MAX_VALUE_U = "MAX_VALUE" LIT_MAGIC_STRING_MIN_VALUE_U = "MIN_VALUE" LIT_MAGIC_STRING_TYPE_ERROR_UL = "TypeError" @@ -287,6 +288,7 @@ LIT_MAGIC_STRING_TO_TIME_STRING_UL = "toTimeString" LIT_MAGIC_STRING_GET_UTC_MINUTES_UL = "getUTCMinutes" LIT_MAGIC_STRING_GET_UTC_SECONDS_UL = "getUTCSeconds" LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL = "isPrototypeOf" +LIT_MAGIC_STRING_IS_SAFE_INTEGER = "isSafeInteger" LIT_MAGIC_STRING_LOCALE_COMPARE_UL = "localeCompare" LIT_MAGIC_STRING_SET_UTC_MINUTES_UL = "setUTCMinutes" LIT_MAGIC_STRING_SET_UTC_SECONDS_UL = "setUTCSeconds" diff --git a/tests/jerry/es2015/number-isfinite.js b/tests/jerry/es2015/number-isfinite.js new file mode 100644 index 000000000..cd2620cee --- /dev/null +++ b/tests/jerry/es2015/number-isfinite.js @@ -0,0 +1,19 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert(Number['isFinite'] (Infinity) === false); +assert(Number['isFinite'] (-Infinity) === false); +assert(Number['isFinite'] (NaN) === false); +assert(Number['isFinite'] (0) === true); +assert(Number['isFinite'] (2e64) === true); diff --git a/tests/jerry/es2015/number-isinteger.js b/tests/jerry/es2015/number-isinteger.js new file mode 100644 index 000000000..2d4ae4a19 --- /dev/null +++ b/tests/jerry/es2015/number-isinteger.js @@ -0,0 +1,21 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert(Number['isInteger'] ('valami') === false); +assert(Number['isInteger'] (NaN) === false); +assert(Number['isInteger'] (Infinity) === false); +assert(Number['isInteger'] (-Infinity) === false); +assert(Number['isInteger'] (3.5) === false); +assert(Number['isInteger'] (-100000) === true); +assert(Number['isInteger'] (5.0000000000000001) === true); diff --git a/tests/jerry/es2015/number-isnan.js b/tests/jerry/es2015/number-isnan.js new file mode 100644 index 000000000..b9a49d354 --- /dev/null +++ b/tests/jerry/es2015/number-isnan.js @@ -0,0 +1,19 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert(Number['isNaN'] ('valami') === false); +assert(Number['isNaN'] (NaN) === true); +assert(Number['isNaN'] (1) === false); +assert(Number['isNaN'] (Number.NaN) === true); +assert(Number['isNaN'] (0 / 0) === true); diff --git a/tests/jerry/es2015/number-issafeinteger.js b/tests/jerry/es2015/number-issafeinteger.js new file mode 100644 index 000000000..2c2578516 --- /dev/null +++ b/tests/jerry/es2015/number-issafeinteger.js @@ -0,0 +1,20 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert(Number['isSafeInteger'] (Math.pow(2, 53)) === false); +assert(Number['isSafeInteger'] (Math.pow(2, 53) - 1) === true); +assert(Number['isSafeInteger'] (NaN) === false); +assert(Number['isSafeInteger'] (-3.0) === true); +assert(Number['isSafeInteger'] (Infinity) === false); +assert(Number['isSafeInteger'] (3.5) === false);