Use custom dispatcher for Global object's routines (#2794)

Binary size gain:
     - Intel: ~780B (gcc-7.3)
     - Arm: ~450B (arm-linux-gnueabi-gcc-7.3)

The change also contains the renovation of each builtin routine to use early return in case of error to make the code less complicated.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2019-04-16 07:48:04 +02:00
committed by László Langó
parent e944cdaa8b
commit c818930cdc
3 changed files with 669 additions and 711 deletions
@@ -33,6 +33,31 @@
#define ECMA_BUILTINS_INTERNAL #define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h" #include "ecma-builtins-internal.h"
/**
* This object has a custom dispatch function.
*/
#define BUILTIN_CUSTOM_DISPATCH
/**
* List of built-in routine identifiers.
*/
enum
{
ECMA_GLOBAL_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1,
/* Note: these 5 routine ids must be in this order */
ECMA_GLOBAL_IS_NAN,
ECMA_GLOBAL_IS_FINITE,
ECMA_GLOBAL_EVAL,
ECMA_GLOBAL_PARSE_INT,
ECMA_GLOBAL_PARSE_FLOAT,
ECMA_GLOBAL_DECODE_URI,
ECMA_GLOBAL_DECODE_URI_COMPONENT,
ECMA_GLOBAL_ENCODE_URI,
ECMA_GLOBAL_ENCODE_URI_COMPONENT,
ECMA_GLOBAL_ESCAPE,
ECMA_GLOBAL_UNESCAPE,
};
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-global.inc.h" #define BUILTIN_INC_HEADER_NAME "ecma-builtin-global.inc.h"
#define BUILTIN_UNDERSCORED_ID global #define BUILTIN_UNDERSCORED_ID global
#include "ecma-builtin-internal-routines-template.inc.h" #include "ecma-builtin-internal-routines-template.inc.h"
@@ -57,11 +82,13 @@
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_eval (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument */
ecma_value_t x) /**< routine's first argument */
{ {
JERRY_UNUSED (this_arg); if (JERRY_UNLIKELY (!ecma_is_value_string (x)))
ecma_value_t ret_value = ECMA_VALUE_EMPTY; {
/* step 1 */
return ecma_copy_value (x);
}
uint32_t parse_opts = vm_is_direct_eval_form_call () ? ECMA_PARSE_DIRECT_EVAL : ECMA_PARSE_NO_OPTS; uint32_t parse_opts = vm_is_direct_eval_form_call () ? ECMA_PARSE_DIRECT_EVAL : ECMA_PARSE_NO_OPTS;
@@ -72,21 +99,35 @@ ecma_builtin_global_object_eval (ecma_value_t this_arg, /**< this argument */
parse_opts |= ECMA_PARSE_STRICT_MODE; parse_opts |= ECMA_PARSE_STRICT_MODE;
} }
if (!ecma_is_value_string (x))
{
/* step 1 */
ret_value = ecma_copy_value (x);
}
else
{
/* steps 2 to 8 */ /* steps 2 to 8 */
ret_value = ecma_op_eval (ecma_get_string_from_value (x), return ecma_op_eval (ecma_get_string_from_value (x), parse_opts);
parse_opts);
}
return ret_value;
} /* ecma_builtin_global_object_eval */ } /* ecma_builtin_global_object_eval */
/**
* Helper function for trimming leading whitespaces
* for the Global object's 'parseInt' and 'parseFloat' routines
*/
static void
ecma_builtin_global_remove_leading_white_spaces (const lit_utf8_byte_t **string_curr_p, /**< [in, out] current string
* position */
const lit_utf8_byte_t *string_end_p, /**< end of the string buffer */
const lit_utf8_byte_t **start_p) /**< [in, out] start position of the
* trimmed string */
{
while (*string_curr_p < string_end_p)
{
ecma_char_t current_char = lit_utf8_read_next (string_curr_p);
if (!lit_char_is_white_space (current_char)
&& !lit_char_is_line_terminator (current_char))
{
lit_utf8_decr (string_curr_p);
*start_p = *string_curr_p;
break;
}
}
} /* ecma_builtin_global_remove_leading_white_spaces */
/** /**
* The Global object's 'parseInt' routine * The Global object's 'parseInt' routine
* *
@@ -97,44 +138,31 @@ ecma_builtin_global_object_eval (ecma_value_t this_arg, /**< this argument */
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_parse_int (const lit_utf8_byte_t *string_buff, /**< routine's first argument's
ecma_value_t string, /**< routine's first argument */ * string buffer */
lit_utf8_size_t string_buff_size, /**< routine's first argument's
* string buffer's size */
ecma_value_t radix) /**< routine's second argument */ ecma_value_t radix) /**< routine's second argument */
{ {
JERRY_UNUSED (this_arg); if (string_buff_size <= 0)
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
/* 1. */
ECMA_TRY_CATCH (string_var, ecma_op_to_string (string), ret_value);
ecma_string_t *number_str_p = ecma_get_string_from_value (string_var);
ECMA_STRING_TO_UTF8_STRING (number_str_p, string_buff, string_buff_size);
if (string_buff_size > 0)
{ {
const lit_utf8_byte_t *string_curr_p = (lit_utf8_byte_t *) string_buff; return ecma_make_nan_value ();
}
const lit_utf8_byte_t *string_curr_p = string_buff;
const lit_utf8_byte_t *string_end_p = string_buff + string_buff_size; const lit_utf8_byte_t *string_end_p = string_buff + string_buff_size;
/* 2. Remove leading whitespace. */ /* 2. Remove leading whitespace. */
const lit_utf8_byte_t *start_p = string_end_p; const lit_utf8_byte_t *start_p = string_end_p;
const lit_utf8_byte_t *end_p = start_p; const lit_utf8_byte_t *end_p = start_p;
while (string_curr_p < string_end_p) ecma_builtin_global_remove_leading_white_spaces (&string_curr_p, string_end_p, &start_p);
{
ecma_char_t current_char = lit_utf8_read_next (&string_curr_p);
if (!lit_char_is_white_space (current_char) if (string_curr_p >= string_end_p)
&& !lit_char_is_line_terminator (current_char))
{ {
lit_utf8_decr (&string_curr_p); return ecma_make_nan_value ();
start_p = string_curr_p;
break;
}
} }
if (string_curr_p < string_end_p)
{
/* 3. */ /* 3. */
int sign = 1; int sign = 1;
@@ -156,7 +184,14 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument
} }
/* 6. */ /* 6. */
ECMA_OP_TO_NUMBER_TRY_CATCH (radix_num, radix, ret_value); ecma_number_t radix_num;
radix = ecma_get_number (radix, &radix_num);
if (!ecma_is_value_empty (radix))
{
return radix;
}
int32_t rad = ecma_number_to_int32 (radix_num); int32_t rad = ecma_number_to_int32 (radix_num);
/* 7.*/ /* 7.*/
@@ -168,7 +203,7 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument
/* 8.a */ /* 8.a */
if (rad < 2 || rad > 36) if (rad < 2 || rad > 36)
{ {
ret_value = ecma_make_nan_value (); return ecma_make_nan_value ();
} }
/* 8.b */ /* 8.b */
else if (rad != 16) else if (rad != 16)
@@ -182,8 +217,6 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument
rad = 10; rad = 10;
} }
if (ecma_is_value_empty (ret_value))
{
/* 10. */ /* 10. */
if (strip_prefix if (strip_prefix
&& ((end_p - start_p) >= 2) && ((end_p - start_p) >= 2)
@@ -233,12 +266,9 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument
/* 12. */ /* 12. */
if (end_p == start_p) if (end_p == start_p)
{ {
ret_value = ecma_make_nan_value (); return ecma_make_nan_value ();
}
} }
if (ecma_is_value_empty (ret_value))
{
ecma_number_t value = ECMA_NUMBER_ZERO; ecma_number_t value = ECMA_NUMBER_ZERO;
ecma_number_t multiplier = 1.0f; ecma_number_t multiplier = 1.0f;
@@ -274,25 +304,7 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument
value *= (ecma_number_t) sign; value *= (ecma_number_t) sign;
} }
ret_value = ecma_make_number_value (value); return ecma_make_number_value (value);
}
ECMA_OP_TO_NUMBER_FINALIZE (radix_num);
}
else
{
ret_value = ecma_make_nan_value ();
}
}
else
{
ret_value = ecma_make_nan_value ();
}
ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size);
ECMA_FINALIZE (string_var);
return ret_value;
} /* ecma_builtin_global_object_parse_int */ } /* ecma_builtin_global_object_parse_int */
/** /**
@@ -305,20 +317,16 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg, /**< this argument
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_parse_float (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_parse_float (const lit_utf8_byte_t *string_buff, /**< routine's first argument's
ecma_value_t string) /**< routine's first argument */ * string buffer */
lit_utf8_size_t string_buff_size) /**< routine's first argument's
* string buffer's size */
{ {
JERRY_UNUSED (this_arg); if (string_buff_size <= 0)
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
/* 1. */
ECMA_TRY_CATCH (string_var, ecma_op_to_string (string), ret_value);
ecma_string_t *number_str_p = ecma_get_string_from_value (string_var);
ECMA_STRING_TO_UTF8_STRING (number_str_p, string_buff, string_buff_size);
if (string_buff_size > 0)
{ {
return ecma_make_nan_value ();
}
const lit_utf8_byte_t *str_curr_p = string_buff; const lit_utf8_byte_t *str_curr_p = string_buff;
const lit_utf8_byte_t *str_end_p = string_buff + string_buff_size; const lit_utf8_byte_t *str_end_p = string_buff + string_buff_size;
@@ -326,18 +334,7 @@ ecma_builtin_global_object_parse_float (ecma_value_t this_arg, /**< this argumen
const lit_utf8_byte_t *end_p = str_end_p; const lit_utf8_byte_t *end_p = str_end_p;
/* 2. Find first non whitespace char and set starting position. */ /* 2. Find first non whitespace char and set starting position. */
while (str_curr_p < str_end_p) ecma_builtin_global_remove_leading_white_spaces (&str_curr_p, str_end_p, &start_p);
{
ecma_char_t current_char = lit_utf8_read_next (&str_curr_p);
if (!lit_char_is_white_space (current_char)
&& !lit_char_is_line_terminator (current_char))
{
lit_utf8_decr (&str_curr_p);
start_p = str_curr_p;
break;
}
}
bool sign = false; bool sign = false;
ecma_char_t current; ecma_char_t current;
@@ -369,16 +366,22 @@ ecma_builtin_global_object_parse_float (ecma_value_t this_arg, /**< this argumen
if (infinity_str_curr_p == infinity_str_end_p) if (infinity_str_curr_p == infinity_str_end_p)
{ {
/* String matched Infinity. */ /* String matched Infinity. */
ret_value = ecma_make_number_value (ecma_number_make_infinity (sign)); return ecma_make_number_value (ecma_number_make_infinity (sign));
break;
} }
} }
/* Reset to starting position. */ /* Reset to starting position. */
str_curr_p = start_p; str_curr_p = start_p;
if (ecma_is_value_empty (ret_value) && str_curr_p < str_end_p) /* String ended after sign character, or was empty after removing leading whitespace. */
if (str_curr_p >= str_end_p)
{ {
return ecma_make_nan_value ();
}
/* Reset to starting position. */
str_curr_p = start_p;
current = *str_curr_p; current = *str_curr_p;
bool has_whole_part = false; bool has_whole_part = false;
@@ -480,38 +483,18 @@ ecma_builtin_global_object_parse_float (ecma_value_t this_arg, /**< this argumen
/* String did not contain a valid number. */ /* String did not contain a valid number. */
if (start_p == end_p) if (start_p == end_p)
{ {
ret_value = ecma_make_nan_value (); return ecma_make_nan_value ();
} }
else
{
/* 5. */ /* 5. */
ecma_number_t ret_num = ecma_utf8_string_to_number (start_p, ecma_number_t ret_num = ecma_utf8_string_to_number (start_p, (lit_utf8_size_t) (end_p - start_p));
(lit_utf8_size_t) (end_p - start_p));
if (sign) if (sign)
{ {
ret_num *= ECMA_NUMBER_MINUS_ONE; ret_num *= ECMA_NUMBER_MINUS_ONE;
} }
ret_value = ecma_make_number_value (ret_num); return ecma_make_number_value (ret_num);
}
}
/* String ended after sign character, or was empty after removing leading whitespace. */
else if (ecma_is_value_empty (ret_value))
{
ret_value = ecma_make_nan_value ();
}
}
/* String length is zero. */
else
{
ret_value = ecma_make_nan_value ();
}
ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size);
ECMA_FINALIZE (string_var);
return ret_value;
} /* ecma_builtin_global_object_parse_float */ } /* ecma_builtin_global_object_parse_float */
/** /**
@@ -524,19 +507,9 @@ ecma_builtin_global_object_parse_float (ecma_value_t this_arg, /**< this argumen
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_is_nan (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_is_nan (ecma_number_t arg_num) /**< routine's first argument */
ecma_value_t arg) /**< routine's first argument */
{ {
JERRY_UNUSED (this_arg); return ecma_make_boolean_value (ecma_number_is_nan (arg_num));
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
ret_value = ecma_make_boolean_value (ecma_number_is_nan (arg_num));
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
return ret_value;
} /* ecma_builtin_global_object_is_nan */ } /* ecma_builtin_global_object_is_nan */
/** /**
@@ -549,21 +522,12 @@ ecma_builtin_global_object_is_nan (ecma_value_t this_arg, /**< this argument */
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_is_finite (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_is_finite (ecma_number_t arg_num) /**< routine's first argument */
ecma_value_t arg) /**< routine's first argument */
{ {
JERRY_UNUSED (this_arg);
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
bool is_finite = !(ecma_number_is_nan (arg_num) bool is_finite = !(ecma_number_is_nan (arg_num)
|| ecma_number_is_infinity (arg_num)); || ecma_number_is_infinity (arg_num));
ret_value = ecma_make_boolean_value (is_finite);
ECMA_OP_TO_NUMBER_FINALIZE (arg_num); return ecma_make_boolean_value (is_finite);
return ret_value;
} /* ecma_builtin_global_object_is_finite */ } /* ecma_builtin_global_object_is_finite */
/** /**
@@ -607,39 +571,25 @@ static const uint8_t unescaped_uri_component_set[16] =
#define URI_ENCODED_BYTE_SIZE (3) #define URI_ENCODED_BYTE_SIZE (3)
/** /**
* Helper function to decode URI. * The Global object's 'decodeURI' and 'decodeURIComponent' routines
*
* See also:
* ECMA-262 v5, 15.1.3.1
* ECMA-262 v5, 15.1.3.2
* *
* @return ecma value * @return ecma value
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_decode_uri_helper (ecma_value_t uri, /**< uri argument */ ecma_builtin_global_object_decode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's
* string buffer */
lit_utf8_size_t input_size, /**< routine's first argument's
* string buffer's size */
const uint8_t *reserved_uri_bitset) /**< reserved characters bitset */ const uint8_t *reserved_uri_bitset) /**< reserved characters bitset */
{ {
JERRY_UNUSED (uri);
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ECMA_TRY_CATCH (string,
ecma_op_to_string (uri),
ret_value);
JERRY_ASSERT (ecma_is_value_string (string));
ecma_string_t *input_string_p = ecma_get_string_from_value (string);
lit_utf8_size_t input_size = ecma_string_get_size (input_string_p);
JMEM_DEFINE_LOCAL_ARRAY (input_start_p,
input_size + 1,
lit_utf8_byte_t);
ecma_string_to_utf8_bytes (input_string_p, input_start_p, input_size);
input_start_p[input_size] = LIT_BYTE_NULL;
lit_utf8_byte_t *input_char_p = input_start_p; lit_utf8_byte_t *input_char_p = input_start_p;
lit_utf8_byte_t *input_end_p = input_start_p + input_size; lit_utf8_byte_t *input_end_p = input_start_p + input_size;
lit_utf8_size_t output_size = 0; lit_utf8_size_t output_size = 0;
/* /*
* The URI decoding has two major phases: first we validate the input, * The URI decoding has two major phases: first we validate the input,
* and compute the length of the output, then we decode the input. * and compute the length of the output, then we decode the input.
@@ -663,8 +613,7 @@ ecma_builtin_global_object_decode_uri_helper (ecma_value_t uri, /**< uri argumen
if (!lit_read_code_unit_from_hex (input_char_p + 1, 2, &decoded_byte)) if (!lit_read_code_unit_from_hex (input_char_p + 1, 2, &decoded_byte))
{ {
ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid hexadecimal value.")); return ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid hexadecimal value."));
break;
} }
input_char_p += URI_ENCODED_BYTE_SIZE; input_char_p += URI_ENCODED_BYTE_SIZE;
@@ -695,8 +644,8 @@ ecma_builtin_global_object_decode_uri_helper (ecma_value_t uri, /**< uri argumen
} }
} }
if (ecma_is_value_empty (ret_value)) ecma_value_t ret_value = ECMA_VALUE_EMPTY;
{
JMEM_DEFINE_LOCAL_ARRAY (output_start_p, JMEM_DEFINE_LOCAL_ARRAY (output_start_p,
output_size, output_size,
lit_utf8_byte_t); lit_utf8_byte_t);
@@ -825,49 +774,10 @@ ecma_builtin_global_object_decode_uri_helper (ecma_value_t uri, /**< uri argumen
} }
JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); JMEM_FINALIZE_LOCAL_ARRAY (output_start_p);
}
JMEM_FINALIZE_LOCAL_ARRAY (input_start_p);
ECMA_FINALIZE (string);
return ret_value; return ret_value;
} /* ecma_builtin_global_object_decode_uri_helper */ } /* ecma_builtin_global_object_decode_uri_helper */
/**
* The Global object's 'decodeURI' routine
*
* See also:
* ECMA-262 v5, 15.1.3.1
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_global_object_decode_uri (ecma_value_t this_arg, /**< this argument */
ecma_value_t encoded_uri) /**< routine's first argument */
{
JERRY_UNUSED (this_arg);
return ecma_builtin_global_object_decode_uri_helper (encoded_uri, unescaped_uri_set);
} /* ecma_builtin_global_object_decode_uri */
/**
* The Global object's 'decodeURIComponent' routine
*
* See also:
* ECMA-262 v5, 15.1.3.2
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_global_object_decode_uri_component (ecma_value_t this_arg, /**< this argument */
ecma_value_t encoded_uri_component) /**< routine's
* first argument */
{
JERRY_UNUSED (this_arg);
return ecma_builtin_global_object_decode_uri_helper (encoded_uri_component, unescaped_uri_component_set);
} /* ecma_builtin_global_object_decode_uri_component */
/** /**
* Helper function to encode byte as hexadecimal values. * Helper function to encode byte as hexadecimal values.
*/ */
@@ -885,32 +795,22 @@ ecma_builtin_global_object_byte_to_hex (lit_utf8_byte_t *dest_p, /**< destinatio
} /* ecma_builtin_global_object_byte_to_hex */ } /* ecma_builtin_global_object_byte_to_hex */
/** /**
* Helper function to encode URI. * The Global object's 'encodeURI' and 'encodeURIComponent' routines
*
* See also:
* ECMA-262 v5, 15.1.3.3
* ECMA-262 v5, 15.1.3.4
* *
* @return ecma value * @return ecma value
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_encode_uri_helper (ecma_value_t uri, /**< uri argument */ ecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's
* string buffer */
lit_utf8_size_t input_size, /**< routine's first argument's
* string buffer's size */
const uint8_t *unescaped_uri_bitset_p) /**< unescaped bitset */ const uint8_t *unescaped_uri_bitset_p) /**< unescaped bitset */
{ {
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ECMA_TRY_CATCH (string,
ecma_op_to_string (uri),
ret_value);
JERRY_ASSERT (ecma_is_value_string (string));
ecma_string_t *input_string_p = ecma_get_string_from_value (string);
lit_utf8_size_t input_size = ecma_string_get_size (input_string_p);
JMEM_DEFINE_LOCAL_ARRAY (input_start_p,
input_size,
lit_utf8_byte_t);
ecma_string_to_utf8_bytes (input_string_p, input_start_p, input_size);
/* /*
* The URI encoding has two major phases: first we validate the input, * The URI encoding has two major phases: first we validate the input,
* and compute the length of the output, then we encode the input. * and compute the length of the output, then we encode the input.
@@ -931,8 +831,7 @@ ecma_builtin_global_object_encode_uri_helper (ecma_value_t uri, /**< uri argumen
if (lit_is_code_point_utf16_low_surrogate (ch)) if (lit_is_code_point_utf16_low_surrogate (ch))
{ {
ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing."));
break;
} }
cp = ch; cp = ch;
@@ -941,8 +840,7 @@ ecma_builtin_global_object_encode_uri_helper (ecma_value_t uri, /**< uri argumen
{ {
if (input_char_p == input_end_p) if (input_char_p == input_end_p)
{ {
ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing."));
break;
} }
ecma_char_t next_ch; ecma_char_t next_ch;
@@ -955,8 +853,7 @@ ecma_builtin_global_object_encode_uri_helper (ecma_value_t uri, /**< uri argumen
} }
else else
{ {
ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing."));
break;
} }
} }
@@ -979,8 +876,8 @@ ecma_builtin_global_object_encode_uri_helper (ecma_value_t uri, /**< uri argumen
} }
} }
if (ecma_is_value_empty (ret_value)) ecma_value_t ret_value;
{
JMEM_DEFINE_LOCAL_ARRAY (output_start_p, JMEM_DEFINE_LOCAL_ARRAY (output_start_p,
output_length, output_length,
lit_utf8_byte_t); lit_utf8_byte_t);
@@ -1037,48 +934,10 @@ ecma_builtin_global_object_encode_uri_helper (ecma_value_t uri, /**< uri argumen
ret_value = ecma_make_string_value (output_string_p); ret_value = ecma_make_string_value (output_string_p);
JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); JMEM_FINALIZE_LOCAL_ARRAY (output_start_p);
}
JMEM_FINALIZE_LOCAL_ARRAY (input_start_p);
ECMA_FINALIZE (string);
return ret_value; return ret_value;
} /* ecma_builtin_global_object_encode_uri_helper */ } /* ecma_builtin_global_object_encode_uri_helper */
/**
* The Global object's 'encodeURI' routine
*
* See also:
* ECMA-262 v5, 15.1.3.3
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_global_object_encode_uri (ecma_value_t this_arg, /**< this argument */
ecma_value_t uri) /**< routine's first argument */
{
JERRY_UNUSED (this_arg);
return ecma_builtin_global_object_encode_uri_helper (uri, unescaped_uri_set);
} /* ecma_builtin_global_object_encode_uri */
/**
* The Global object's 'encodeURIComponent' routine
*
* See also:
* ECMA-262 v5, 15.1.3.4
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_global_object_encode_uri_component (ecma_value_t this_arg, /**< this argument */
ecma_value_t uri_component) /**< routine's first argument */
{
JERRY_UNUSED (this_arg);
return ecma_builtin_global_object_encode_uri_helper (uri_component, unescaped_uri_component_set);
} /* ecma_builtin_global_object_encode_uri_component */
#if ENABLED (JERRY_BUILTIN_ANNEXB) #if ENABLED (JERRY_BUILTIN_ANNEXB)
/** /**
@@ -1113,25 +972,11 @@ static const uint8_t ecma_escape_set[16] =
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_escape (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_escape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's
ecma_value_t arg) /**< routine's first argument */ * string buffer */
lit_utf8_size_t input_size) /**< routine's first argument's
* string buffer's size */
{ {
JERRY_UNUSED (this_arg);
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ECMA_TRY_CATCH (string,
ecma_op_to_string (arg),
ret_value);
ecma_string_t *input_string_p = ecma_get_string_from_value (string);
lit_utf8_size_t input_size = ecma_string_get_size (input_string_p);
JMEM_DEFINE_LOCAL_ARRAY (input_start_p,
input_size,
lit_utf8_byte_t);
ecma_string_to_utf8_bytes (input_string_p, input_start_p, input_size);
/* /*
* The escape routine has two major phases: first we compute * The escape routine has two major phases: first we compute
* the length of the output, then we encode the input. * the length of the output, then we encode the input.
@@ -1165,6 +1010,8 @@ ecma_builtin_global_object_escape (ecma_value_t this_arg, /**< this argument */
} }
} }
ecma_value_t ret_value;
JMEM_DEFINE_LOCAL_ARRAY (output_start_p, JMEM_DEFINE_LOCAL_ARRAY (output_start_p,
output_length, output_length,
lit_utf8_byte_t); lit_utf8_byte_t);
@@ -1218,9 +1065,6 @@ ecma_builtin_global_object_escape (ecma_value_t this_arg, /**< this argument */
JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); JMEM_FINALIZE_LOCAL_ARRAY (output_start_p);
JMEM_FINALIZE_LOCAL_ARRAY (input_start_p);
ECMA_FINALIZE (string);
return ret_value; return ret_value;
} /* ecma_builtin_global_object_escape */ } /* ecma_builtin_global_object_escape */
@@ -1234,22 +1078,11 @@ ecma_builtin_global_object_escape (ecma_value_t this_arg, /**< this argument */
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_global_object_unescape (ecma_value_t this_arg, /**< this argument */ ecma_builtin_global_object_unescape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's
ecma_value_t arg) /**< routine's first argument */ * string buffer */
lit_utf8_size_t input_size) /**< routine's first argument's
* string buffer's size */
{ {
JERRY_UNUSED (this_arg);
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
/* 1. */
ECMA_TRY_CATCH (string, ecma_op_to_string (arg), ret_value);
ecma_string_t *input_string_p = ecma_get_string_from_value (string);
/* 2. */
lit_utf8_size_t input_size = ecma_string_get_size (input_string_p);
/* 3. */
JMEM_DEFINE_LOCAL_ARRAY (input_start_p, input_size, lit_utf8_byte_t);
ecma_string_to_utf8_bytes (input_string_p, input_start_p, input_size);
const lit_utf8_byte_t *input_curr_p = input_start_p; const lit_utf8_byte_t *input_curr_p = input_start_p;
const lit_utf8_byte_t *input_end_p = input_start_p + input_size; const lit_utf8_byte_t *input_end_p = input_start_p + input_size;
/* 4. */ /* 4. */
@@ -1319,16 +1152,141 @@ ecma_builtin_global_object_unescape (ecma_value_t this_arg, /**< this argument *
lit_utf8_size_t output_length = (lit_utf8_size_t) (output_char_p - input_start_p); lit_utf8_size_t output_length = (lit_utf8_size_t) (output_char_p - input_start_p);
ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (input_start_p, output_length); ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (input_start_p, output_length);
ret_value = ecma_make_string_value (output_string_p); return ecma_make_string_value (output_string_p);
JMEM_FINALIZE_LOCAL_ARRAY (input_start_p);
ECMA_FINALIZE (string);
return ret_value;
} /* ecma_builtin_global_object_unescape */ } /* ecma_builtin_global_object_unescape */
#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ #endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */
/**
* Dispatcher of the built-in's routines
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
ecma_builtin_global_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine identifier */
ecma_value_t this_arg, /**< 'this' argument value */
const ecma_value_t arguments_list_p[], /**< list of arguments
* passed to routine */
ecma_length_t arguments_number) /**< length of arguments' list */
{
JERRY_UNUSED (this_arg);
JERRY_UNUSED (arguments_list_p);
JERRY_UNUSED (arguments_number);
ecma_value_t routine_arg_1 = arguments_list_p[0];
if (builtin_routine_id == ECMA_GLOBAL_EVAL)
{
return ecma_builtin_global_object_eval (routine_arg_1);
}
if (builtin_routine_id <= ECMA_GLOBAL_IS_FINITE)
{
ecma_number_t arg_num;
routine_arg_1 = ecma_get_number (routine_arg_1, &arg_num);
if (!ecma_is_value_empty (routine_arg_1))
{
return routine_arg_1;
}
if (builtin_routine_id == ECMA_GLOBAL_IS_NAN)
{
return ecma_builtin_global_object_is_nan (arg_num);
}
JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_IS_FINITE);
return ecma_builtin_global_object_is_finite (arg_num);
}
ecma_value_t string_value = ecma_op_to_string (routine_arg_1);
if (ECMA_IS_VALUE_ERROR (string_value))
{
return string_value;
}
ecma_string_t *str_p = ecma_get_string_from_value (string_value);
ecma_value_t ret_value;
if (builtin_routine_id <= ECMA_GLOBAL_PARSE_FLOAT)
{
ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size);
if (builtin_routine_id == ECMA_GLOBAL_PARSE_INT)
{
ret_value = ecma_builtin_global_object_parse_int (string_buff,
string_buff_size,
arguments_list_p[1]);
}
else
{
JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_PARSE_FLOAT);
ret_value = ecma_builtin_global_object_parse_float (string_buff,
string_buff_size);
}
ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size);
ecma_deref_ecma_string (str_p);
return ret_value;
}
lit_utf8_size_t input_size = ecma_string_get_size (str_p);
JMEM_DEFINE_LOCAL_ARRAY (input_start_p,
input_size + 1,
lit_utf8_byte_t);
ecma_string_to_utf8_bytes (str_p, input_start_p, input_size);
input_start_p[input_size] = LIT_BYTE_NULL;
switch (builtin_routine_id)
{
#if ENABLED (JERRY_BUILTIN_ANNEXB)
case ECMA_GLOBAL_ESCAPE:
{
ret_value = ecma_builtin_global_object_escape (input_start_p, input_size);
break;
}
case ECMA_GLOBAL_UNESCAPE:
{
ret_value = ecma_builtin_global_object_unescape (input_start_p, input_size);
break;
}
#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */
case ECMA_GLOBAL_DECODE_URI:
case ECMA_GLOBAL_DECODE_URI_COMPONENT:
{
const uint8_t *uri_set = (builtin_routine_id == ECMA_GLOBAL_DECODE_URI ? unescaped_uri_set
: unescaped_uri_component_set);
ret_value = ecma_builtin_global_object_decode_uri_helper (input_start_p, input_size, uri_set);
break;
}
default:
{
JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI
|| builtin_routine_id == ECMA_GLOBAL_ENCODE_URI_COMPONENT);
const uint8_t *uri_set = (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI ? unescaped_uri_set
: unescaped_uri_component_set);
ret_value = ecma_builtin_global_object_encode_uri_helper (input_start_p, input_size, uri_set);
break;
}
}
JMEM_FINALIZE_LOCAL_ARRAY (input_start_p);
ecma_deref_ecma_string (str_p);
return ret_value;
} /* ecma_builtin_global_dispatch_routine */
/** /**
* @} * @}
* @} * @}
@@ -215,19 +215,19 @@ OBJECT_VALUE (LIT_MAGIC_STRING_SYMBOL_UL,
/* Routine properties: /* Routine properties:
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
ROUTINE (LIT_MAGIC_STRING_EVAL, ecma_builtin_global_object_eval, 1, 1) ROUTINE (LIT_MAGIC_STRING_EVAL, ECMA_GLOBAL_EVAL, 1, 1)
ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ecma_builtin_global_object_parse_float, 1, 1) ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_GLOBAL_PARSE_FLOAT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_IS_NAN, ecma_builtin_global_object_is_nan, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_NAN, ECMA_GLOBAL_IS_NAN, 1, 1)
ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ecma_builtin_global_object_is_finite, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ECMA_GLOBAL_IS_FINITE, 1, 1)
ROUTINE (LIT_MAGIC_STRING_DECODE_URI, ecma_builtin_global_object_decode_uri, 1, 1) ROUTINE (LIT_MAGIC_STRING_DECODE_URI, ECMA_GLOBAL_DECODE_URI, 1, 1)
ROUTINE (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, ecma_builtin_global_object_decode_uri_component, 1, 1) ROUTINE (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, ECMA_GLOBAL_DECODE_URI_COMPONENT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_ENCODE_URI, ecma_builtin_global_object_encode_uri, 1, 1) ROUTINE (LIT_MAGIC_STRING_ENCODE_URI, ECMA_GLOBAL_ENCODE_URI, 1, 1)
ROUTINE (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, ecma_builtin_global_object_encode_uri_component, 1, 1) ROUTINE (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, ECMA_GLOBAL_ENCODE_URI_COMPONENT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ecma_builtin_global_object_parse_int, 2, 2) ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ECMA_GLOBAL_PARSE_INT, 2, 2)
#if ENABLED (JERRY_BUILTIN_ANNEXB) #if ENABLED (JERRY_BUILTIN_ANNEXB)
ROUTINE (LIT_MAGIC_STRING_ESCAPE, ecma_builtin_global_object_escape, 1, 1) ROUTINE (LIT_MAGIC_STRING_ESCAPE, ECMA_GLOBAL_ESCAPE, 1, 1)
ROUTINE (LIT_MAGIC_STRING_UNESCAPE, ecma_builtin_global_object_unescape, 1, 1) ROUTINE (LIT_MAGIC_STRING_UNESCAPE, ECMA_GLOBAL_UNESCAPE, 1, 1)
#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ #endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */
#include "ecma-builtin-helpers-macro-undefs.inc.h" #include "ecma-builtin-helpers-macro-undefs.inc.h"
+1 -1
View File
@@ -102,7 +102,7 @@ assert (decodeURIComponent ("%70%71%72%73%74%75%76%77%78%79%7a%7b%7c%7d%7e") ===
assert (decodeURI ("%6A%6B%6C%6D%6E%6F") === "jklmno"); assert (decodeURI ("%6A%6B%6C%6D%6E%6F") === "jklmno");
assert (decodeURI ("%C3%A9") === "\xe9"); assert (decodeURI ("%C3%A9") === "\xe9");
assert (decodeURI ("%e2%b1%a5") === "\u2c65"); assert (decodeURI ("%e2%b1%a5") === "\u2c65");
/* assert (decodeURI ("%f0%90%90%a8") === "\ud801\udc28"); */ assert (decodeURI ("%f0%90%90%a8") === "\ud801\udc28");
checkDecodeURIParseError ("13%"); checkDecodeURIParseError ("13%");
checkDecodeURIParseError ("%0g"); checkDecodeURIParseError ("%0g");