Skip to content

Commit 466dc90

Browse files
Yuyuporerobika
authored andcommitted
Add toLength and toInteger operations (#3146)
JerryScript-DCO-1.0-Signed-off-by: Daniella Barsony [email protected]
1 parent c17da4f commit 466dc90

File tree

5 files changed

+371
-0
lines changed

5 files changed

+371
-0
lines changed

jerry-core/ecma/operations/ecma-conversion.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* Implementation of ECMA-defined conversion routines
1818
*/
1919

20+
#include <math.h>
21+
2022
#include "ecma-alloc.h"
2123
#include "ecma-boolean-object.h"
2224
#include "ecma-conversion.h"
@@ -910,6 +912,119 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */
910912
return ret_value;
911913
} /* ecma_op_to_property_descriptor */
912914

915+
/**
916+
* ToInteger operation.
917+
*
918+
* See also:
919+
* ECMA-262 v5, 9.4
920+
* ECMA-262 v6, 7.1.4
921+
*
922+
* @return ECMA_VALUE_EMPTY if successful
923+
* conversion error otherwise
924+
*/
925+
ecma_value_t
926+
ecma_op_to_integer (ecma_value_t value, /**< ecma value*/
927+
ecma_number_t *number_p) /**< [out] ecma number */
928+
{
929+
if (ECMA_IS_VALUE_ERROR (value))
930+
{
931+
return value;
932+
}
933+
934+
/* 1 */
935+
ecma_value_t to_number = ecma_get_number (value, number_p);
936+
937+
/* 2 */
938+
if (ECMA_IS_VALUE_ERROR (to_number))
939+
{
940+
return to_number;
941+
}
942+
943+
ecma_number_t number = *number_p;
944+
945+
/* 3 */
946+
if (ecma_number_is_nan (number))
947+
{
948+
*number_p = ECMA_NUMBER_ZERO;
949+
return ECMA_VALUE_EMPTY;
950+
}
951+
952+
/* 4 */
953+
if (ecma_number_is_zero (number) || ecma_number_is_infinity (number))
954+
{
955+
return ECMA_VALUE_EMPTY;
956+
}
957+
958+
ecma_number_t floor_fabs = floor (fabs (number));
959+
960+
/* 5 */
961+
*number_p = ecma_number_is_negative (number) ? -floor_fabs : floor_fabs;
962+
return ECMA_VALUE_EMPTY;
963+
} /* ecma_op_to_integer */
964+
965+
/**
966+
* ToLength operation.
967+
*
968+
* See also:
969+
* ECMA-262 v6, 7.1.15
970+
*
971+
* @return ECMA_VALUE_EMPTY if successful
972+
* conversion error otherwise
973+
*/
974+
ecma_value_t
975+
ecma_op_to_length (ecma_value_t value, /**< ecma value*/
976+
uint32_t *length) /**< [out] ecma number */
977+
{
978+
/* 1 */
979+
if (ECMA_IS_VALUE_ERROR (value))
980+
{
981+
return value;
982+
}
983+
984+
#if ENABLED (JERRY_ES2015)
985+
/* 2 */
986+
ecma_number_t num;
987+
ecma_value_t length_num = ecma_op_to_integer (value, &num);
988+
989+
/* 3 */
990+
if (ECMA_IS_VALUE_ERROR (length_num))
991+
{
992+
return length_num;
993+
}
994+
995+
/* 4 */
996+
if (num <= 0.0f)
997+
{
998+
*length = 0;
999+
return ECMA_VALUE_EMPTY;
1000+
}
1001+
1002+
/* 5 */
1003+
if (num >= (ecma_number_t) UINT32_MAX)
1004+
{
1005+
*length = UINT32_MAX;
1006+
return ECMA_VALUE_EMPTY;
1007+
}
1008+
1009+
/* 6 */
1010+
*length = (uint32_t) num;
1011+
return ECMA_VALUE_EMPTY;
1012+
#else /* !ENABLED (JERRY_ES2015) */
1013+
/* In the case of ES5, ToLength(ES6) operation is the same as ToUint32(ES5) */
1014+
ecma_number_t num;
1015+
ecma_value_t to_number = ecma_get_number (value, &num);
1016+
1017+
/* 2 */
1018+
if (ECMA_IS_VALUE_ERROR (to_number))
1019+
{
1020+
return to_number;
1021+
}
1022+
1023+
*length = ecma_number_to_uint32 (num);
1024+
return ECMA_VALUE_EMPTY;
1025+
#endif /* ENABLED (JERRY_ES2015) */
1026+
} /* ecma_op_to_length */
1027+
9131028
/**
9141029
* @}
9151030
* @}

jerry-core/ecma/operations/ecma-conversion.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ ecma_value_t ecma_get_number (ecma_value_t value, ecma_number_t *number_p);
4949
ecma_value_t ecma_op_to_string (ecma_value_t value);
5050
ecma_string_t *ecma_op_to_prop_name (ecma_value_t value);
5151
ecma_value_t ecma_op_to_object (ecma_value_t value);
52+
ecma_value_t ecma_op_to_integer (ecma_value_t value, ecma_number_t *number_p);
53+
ecma_value_t ecma_op_to_length (ecma_value_t value, uint32_t *length);
5254

5355
ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p);
5456
ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, ecma_property_descriptor_t *out_prop_desc_p);

tests/unit-core/test-to-integer.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright JS Foundation and other contributors, http://js.foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "ecma-globals.h"
18+
#include "ecma-helpers.h"
19+
#include "ecma-conversion.h"
20+
#include "ecma-init-finalize.h"
21+
#include "ecma-exceptions.h"
22+
#include "jerryscript.h"
23+
#include "jcontext.h"
24+
25+
#include "test-common.h"
26+
27+
/**
28+
* Unit test's main function.
29+
*/
30+
int
31+
main (void)
32+
{
33+
TEST_INIT ();
34+
35+
jmem_init ();
36+
ecma_init ();
37+
38+
ecma_number_t num;
39+
40+
ecma_value_t int_num = ecma_make_int32_value (123);
41+
42+
ecma_number_t result = ecma_op_to_integer (int_num, &num);
43+
44+
ecma_free_value (int_num);
45+
46+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
47+
TEST_ASSERT (num == 123);
48+
49+
/* 2 */
50+
ecma_value_t error = ecma_raise_type_error (ECMA_ERR_MSG ("I am a neat little error message"));
51+
52+
result = ecma_op_to_integer (error, &num);
53+
54+
ecma_free_value (JERRY_CONTEXT (error_value));
55+
56+
TEST_ASSERT (ECMA_IS_VALUE_ERROR (result));
57+
58+
/* 3 */
59+
ecma_value_t nan = ecma_make_nan_value ();
60+
61+
result = ecma_op_to_integer (nan, &num);
62+
63+
ecma_free_value (nan);
64+
65+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
66+
TEST_ASSERT (num == 0);
67+
68+
/* 4 */
69+
/* -0 */
70+
ecma_value_t negative_zero = ecma_make_number_value (-0.0f);
71+
72+
result = ecma_op_to_integer (negative_zero, &num);
73+
74+
ecma_free_value (negative_zero);
75+
76+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
77+
TEST_ASSERT (1.0f / num == ecma_number_make_infinity (true));
78+
79+
/* +0 */
80+
ecma_value_t positive_zero = ecma_make_number_value (+0.0f);
81+
82+
result = ecma_op_to_integer (positive_zero, &num);
83+
84+
ecma_free_value (positive_zero);
85+
86+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
87+
TEST_ASSERT (1.0f / num == ecma_number_make_infinity (false));
88+
89+
/* -infinity */
90+
ecma_value_t negative_infinity = ecma_make_number_value (ecma_number_make_infinity (true));
91+
92+
result = ecma_op_to_integer (negative_infinity, &num);
93+
94+
ecma_free_value (negative_infinity);
95+
96+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
97+
TEST_ASSERT (num == ecma_number_make_infinity (true));
98+
99+
/* +infinity */
100+
ecma_value_t positive_infinity = ecma_make_number_value (ecma_number_make_infinity (false));
101+
102+
result = ecma_op_to_integer (positive_infinity, &num);
103+
104+
ecma_free_value (positive_infinity);
105+
106+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
107+
TEST_ASSERT (num == ecma_number_make_infinity (false));
108+
109+
/* 5 */
110+
ecma_value_t floor = ecma_make_number_value (3.001f);
111+
112+
result = ecma_op_to_integer (floor, &num);
113+
114+
ecma_free_value (floor);
115+
116+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
117+
TEST_ASSERT (num == 3);
118+
119+
ecma_value_t floor2 = ecma_make_number_value (-26.5973);
120+
121+
result = ecma_op_to_integer (floor2, &num);
122+
123+
ecma_free_value (floor2);
124+
125+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
126+
TEST_ASSERT (num == -26);
127+
128+
ecma_finalize ();
129+
jmem_finalize ();
130+
131+
return 0;
132+
} /* main */
133+
134+

tests/unit-core/test-to-length.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright JS Foundation and other contributors, http://js.foundation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "ecma-globals.h"
18+
#include "ecma-helpers.h"
19+
#include "ecma-conversion.h"
20+
#include "ecma-init-finalize.h"
21+
#include "ecma-exceptions.h"
22+
#include "jerryscript.h"
23+
#include "jcontext.h"
24+
25+
#include "test-common.h"
26+
27+
/**
28+
* Unit test's main function.
29+
*/
30+
int
31+
main (void)
32+
{
33+
TEST_INIT ();
34+
35+
jmem_init ();
36+
ecma_init ();
37+
38+
uint32_t num;
39+
40+
ecma_value_t int_num = ecma_make_int32_value (123);
41+
42+
uint32_t result = ecma_op_to_length (int_num, &num);
43+
44+
ecma_free_value (int_num);
45+
46+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
47+
TEST_ASSERT (num == 123);
48+
49+
/* 1, 3 */
50+
ecma_value_t error_throw = ecma_raise_type_error (ECMA_ERR_MSG ("I'm an error"));
51+
52+
result = ecma_op_to_length (error_throw, &num);
53+
54+
ecma_free_value (JERRY_CONTEXT (error_value));
55+
56+
TEST_ASSERT (ECMA_IS_VALUE_ERROR (result));
57+
58+
/* zero */
59+
ecma_value_t zero = ecma_make_int32_value (0);
60+
61+
result = ecma_op_to_length (zero, &num);
62+
63+
ecma_free_value (zero);
64+
65+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
66+
TEST_ASSERT (num == 0);
67+
68+
/* negative */
69+
ecma_value_t negative = ecma_make_number_value (-26.5973f);
70+
71+
result = ecma_op_to_length (negative, &num);
72+
73+
ecma_free_value (negative);
74+
75+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
76+
#if ENABLED (JERRY_ES2015)
77+
TEST_ASSERT (num == 0);
78+
#else /* !ENABLED (JERRY_ES2015) */
79+
TEST_ASSERT (num == 4294967270);
80+
#endif /* ENABLED (JERRY_ES2015) */
81+
82+
/* +infinity */
83+
ecma_value_t positive_infinity = ecma_make_number_value (ecma_number_make_infinity (false));
84+
85+
result = ecma_op_to_length (positive_infinity, &num);
86+
87+
ecma_free_value (positive_infinity);
88+
89+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
90+
#if ENABLED (JERRY_ES2015)
91+
TEST_ASSERT (num == UINT32_MAX);
92+
#else /* !ENABLED (JERRY_ES2015) */
93+
TEST_ASSERT (num == 0);
94+
#endif /* ENABLED (JERRY_ES2015) */
95+
96+
/* -infinity */
97+
ecma_value_t negative_infinity = ecma_make_number_value (ecma_number_make_infinity (true));
98+
99+
result = ecma_op_to_length (negative_infinity, &num);
100+
101+
ecma_free_value (negative_infinity);
102+
103+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
104+
TEST_ASSERT (num == 0);
105+
106+
/* NaN */
107+
ecma_value_t nan = ecma_make_nan_value ();
108+
109+
result = ecma_op_to_length (nan, &num);
110+
111+
ecma_free_value (nan);
112+
113+
TEST_ASSERT (!ECMA_IS_VALUE_ERROR (result));
114+
TEST_ASSERT (num == 0);
115+
116+
ecma_finalize ();
117+
jmem_finalize ();
118+
119+
return 0;
120+
} /* main */

0 commit comments

Comments
 (0)