toNumber operation should handle binary and octal literals (#3471)
JerryScript-DCO-1.0-Signed-off-by: Virag Orkenyi orkvi@inf.u-szeged.hu
This commit is contained in:
committed by
Robert Fancsik
parent
b3b1dfdabd
commit
b6c2e6eb54
@@ -280,13 +280,87 @@ static const uint8_t ecma_uint4_clz[] = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
|||||||
*/
|
*/
|
||||||
#define EPSILON 0.0000001
|
#define EPSILON 0.0000001
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ECMA-defined conversion from string to number for different radixes (2, 8, 16).
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* ECMA-262 v5 9.3.1
|
||||||
|
* ECMA-262 v6 7.1.3.1
|
||||||
|
*
|
||||||
|
* @return NaN - if the conversion fails
|
||||||
|
* converted number - otherwise
|
||||||
|
*/
|
||||||
|
static ecma_number_t
|
||||||
|
ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||||
|
const lit_utf8_byte_t *end_p, /**< end of utf-8 string */
|
||||||
|
uint32_t radix) /**< radix */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (radix == 2 || radix == 8 || radix == 16);
|
||||||
|
ecma_number_t num = ECMA_NUMBER_ZERO;
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
if (radix <= 8)
|
||||||
|
{
|
||||||
|
lit_code_point_t upper_limit = LIT_CHAR_0 + radix;
|
||||||
|
|
||||||
|
for (const lit_utf8_byte_t * iter_p = str_p; iter_p <= end_p; iter_p++)
|
||||||
|
{
|
||||||
|
int32_t digit_value;
|
||||||
|
|
||||||
|
if (*iter_p >= LIT_CHAR_0 && *iter_p < upper_limit)
|
||||||
|
{
|
||||||
|
digit_value = (*iter_p - LIT_CHAR_0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ecma_number_make_nan ();
|
||||||
|
}
|
||||||
|
|
||||||
|
num = num * radix + (ecma_number_t) digit_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
|
for (const lit_utf8_byte_t * iter_p = str_p; iter_p <= end_p; iter_p++)
|
||||||
|
{
|
||||||
|
int32_t digit_value;
|
||||||
|
|
||||||
|
if (*iter_p >= LIT_CHAR_0
|
||||||
|
&& *iter_p <= LIT_CHAR_9)
|
||||||
|
{
|
||||||
|
digit_value = (*iter_p - LIT_CHAR_0);
|
||||||
|
}
|
||||||
|
else if (*iter_p >= LIT_CHAR_LOWERCASE_A
|
||||||
|
&& *iter_p <= LIT_CHAR_LOWERCASE_F)
|
||||||
|
{
|
||||||
|
digit_value = 10 + (*iter_p - LIT_CHAR_LOWERCASE_A);
|
||||||
|
}
|
||||||
|
else if (*iter_p >= LIT_CHAR_UPPERCASE_A
|
||||||
|
&& *iter_p <= LIT_CHAR_UPPERCASE_F)
|
||||||
|
{
|
||||||
|
digit_value = 10 + (*iter_p - LIT_CHAR_UPPERCASE_A);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ecma_number_make_nan ();
|
||||||
|
}
|
||||||
|
|
||||||
|
num = num * radix + (ecma_number_t) digit_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
} /* ecma_utf8_string_to_number_by_radix */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ECMA-defined conversion of string to Number.
|
* ECMA-defined conversion of string to Number.
|
||||||
*
|
*
|
||||||
* See also:
|
* See also:
|
||||||
* ECMA-262 v5, 9.3.1
|
* ECMA-262 v5, 9.3.1
|
||||||
*
|
*
|
||||||
* @return ecma-number
|
* @return NaN - if the conversion fails
|
||||||
|
* converted number - otherwise
|
||||||
*/
|
*/
|
||||||
ecma_number_t
|
ecma_number_t
|
||||||
ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
||||||
@@ -307,46 +381,28 @@ ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, /**< utf-8 string */
|
|||||||
return ECMA_NUMBER_ZERO;
|
return ECMA_NUMBER_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((end_p >= str_p + 2)
|
if (end_p >= str_p + 2
|
||||||
&& str_p[0] == LIT_CHAR_0
|
&& str_p[0] == LIT_CHAR_0)
|
||||||
&& (str_p[1] == LIT_CHAR_LOWERCASE_X
|
|
||||||
|| str_p[1] == LIT_CHAR_UPPERCASE_X))
|
|
||||||
{
|
{
|
||||||
/* Hex literal handling */
|
switch (LEXER_TO_ASCII_LOWERCASE (str_p[1]))
|
||||||
str_p += 2;
|
|
||||||
|
|
||||||
ecma_number_t num = ECMA_NUMBER_ZERO;
|
|
||||||
|
|
||||||
for (const lit_utf8_byte_t * iter_p = str_p;
|
|
||||||
iter_p <= end_p;
|
|
||||||
iter_p++)
|
|
||||||
{
|
{
|
||||||
int32_t digit_value;
|
case LIT_CHAR_LOWERCASE_X :
|
||||||
|
|
||||||
if (*iter_p >= LIT_CHAR_0
|
|
||||||
&& *iter_p <= LIT_CHAR_9)
|
|
||||||
{
|
{
|
||||||
digit_value = (*iter_p - LIT_CHAR_0);
|
return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 16);
|
||||||
}
|
}
|
||||||
else if (*iter_p >= LIT_CHAR_LOWERCASE_A
|
case LIT_CHAR_LOWERCASE_O :
|
||||||
&& *iter_p <= LIT_CHAR_LOWERCASE_F)
|
|
||||||
{
|
{
|
||||||
digit_value = 10 + (*iter_p - LIT_CHAR_LOWERCASE_A);
|
return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 8);
|
||||||
}
|
}
|
||||||
else if (*iter_p >= LIT_CHAR_UPPERCASE_A
|
case LIT_CHAR_LOWERCASE_B :
|
||||||
&& *iter_p <= LIT_CHAR_UPPERCASE_F)
|
|
||||||
{
|
{
|
||||||
digit_value = 10 + (*iter_p - LIT_CHAR_UPPERCASE_A);
|
return ecma_utf8_string_to_number_by_radix (str_p + 2, end_p, 2);
|
||||||
}
|
}
|
||||||
else
|
default:
|
||||||
{
|
{
|
||||||
return ecma_number_make_nan ();
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
num = num * 16 + (ecma_number_t) digit_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return num;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sign = false; /* positive */
|
bool sign = false; /* positive */
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/* 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(+"0b1101001" === 105);
|
||||||
|
assert(+"0B1101001" === 105);
|
||||||
|
assert(+"0o767" === 503);
|
||||||
|
assert(+"0O767" === 503);
|
||||||
|
|
||||||
|
function assertNaN(str) {
|
||||||
|
assert(isNaN(+str));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNaN("0b");
|
||||||
|
assertNaN("0b12");
|
||||||
|
assertNaN("0b10101100103");
|
||||||
|
assertNaN("0b101foo");
|
||||||
|
assertNaN("0bfoo101");
|
||||||
|
assertNaN("0b12345");
|
||||||
|
|
||||||
|
assertNaN("0B");
|
||||||
|
assertNaN("0B12");
|
||||||
|
assertNaN("0B10101100103");
|
||||||
|
assertNaN("0B101foo");
|
||||||
|
assertNaN("0Bfoo101");
|
||||||
|
assertNaN("0B12345");
|
||||||
|
|
||||||
|
assertNaN("0o");
|
||||||
|
assertNaN("0o1289");
|
||||||
|
assertNaN("0o88888");
|
||||||
|
assertNaN("0o12345foo");
|
||||||
|
assertNaN("0ofoo12345");
|
||||||
|
|
||||||
|
assertNaN("0O");
|
||||||
|
assertNaN("0O1289");
|
||||||
|
assertNaN("0O88888");
|
||||||
|
assertNaN("0O12345foo");
|
||||||
|
assertNaN("0Ofoo12345");
|
||||||
Reference in New Issue
Block a user