1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "ecma-alloc.h" 17425bb815Sopenharmony_ci#include "ecma-builtins.h" 18425bb815Sopenharmony_ci#include "ecma-conversion.h" 19425bb815Sopenharmony_ci#include "ecma-eval.h" 20425bb815Sopenharmony_ci#include "ecma-exceptions.h" 21425bb815Sopenharmony_ci#include "ecma-gc.h" 22425bb815Sopenharmony_ci#include "ecma-globals.h" 23425bb815Sopenharmony_ci#include "ecma-helpers.h" 24425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h" 25425bb815Sopenharmony_ci#include "jrt.h" 26425bb815Sopenharmony_ci#include "lit-char-helpers.h" 27425bb815Sopenharmony_ci#include "lit-magic-strings.h" 28425bb815Sopenharmony_ci#include "lit-strings.h" 29425bb815Sopenharmony_ci#include "vm.h" 30425bb815Sopenharmony_ci#include "jcontext.h" 31425bb815Sopenharmony_ci#include "jrt-libc-includes.h" 32425bb815Sopenharmony_ci#include "jrt-bit-fields.h" 33425bb815Sopenharmony_ci 34425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL 35425bb815Sopenharmony_ci#include "ecma-builtins-internal.h" 36425bb815Sopenharmony_ci 37425bb815Sopenharmony_ci/** 38425bb815Sopenharmony_ci * This object has a custom dispatch function. 39425bb815Sopenharmony_ci */ 40425bb815Sopenharmony_ci#define BUILTIN_CUSTOM_DISPATCH 41425bb815Sopenharmony_ci 42425bb815Sopenharmony_ci/** 43425bb815Sopenharmony_ci * List of built-in routine identifiers. 44425bb815Sopenharmony_ci */ 45425bb815Sopenharmony_cienum 46425bb815Sopenharmony_ci{ 47425bb815Sopenharmony_ci ECMA_GLOBAL_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, 48425bb815Sopenharmony_ci /* Note: these 5 routine ids must be in this order */ 49425bb815Sopenharmony_ci ECMA_GLOBAL_IS_NAN, 50425bb815Sopenharmony_ci ECMA_GLOBAL_IS_FINITE, 51425bb815Sopenharmony_ci ECMA_GLOBAL_EVAL, 52425bb815Sopenharmony_ci ECMA_GLOBAL_PARSE_INT, 53425bb815Sopenharmony_ci ECMA_GLOBAL_PARSE_FLOAT, 54425bb815Sopenharmony_ci ECMA_GLOBAL_DECODE_URI, 55425bb815Sopenharmony_ci ECMA_GLOBAL_DECODE_URI_COMPONENT, 56425bb815Sopenharmony_ci ECMA_GLOBAL_ENCODE_URI, 57425bb815Sopenharmony_ci ECMA_GLOBAL_ENCODE_URI_COMPONENT, 58425bb815Sopenharmony_ci ECMA_GLOBAL_ESCAPE, 59425bb815Sopenharmony_ci ECMA_GLOBAL_UNESCAPE, 60425bb815Sopenharmony_ci}; 61425bb815Sopenharmony_ci 62425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-global.inc.h" 63425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID global 64425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h" 65425bb815Sopenharmony_ci 66425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 67425bb815Sopenharmony_ci * @{ 68425bb815Sopenharmony_ci * 69425bb815Sopenharmony_ci * \addtogroup ecmabuiltins 70425bb815Sopenharmony_ci * @{ 71425bb815Sopenharmony_ci * 72425bb815Sopenharmony_ci * \addtogroup global ECMA Global object built-in 73425bb815Sopenharmony_ci * @{ 74425bb815Sopenharmony_ci */ 75425bb815Sopenharmony_ci 76425bb815Sopenharmony_ci/** 77425bb815Sopenharmony_ci * The Global object's 'eval' routine 78425bb815Sopenharmony_ci * 79425bb815Sopenharmony_ci * See also: 80425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.2.1 81425bb815Sopenharmony_ci * 82425bb815Sopenharmony_ci * @return ecma value 83425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 84425bb815Sopenharmony_ci */ 85425bb815Sopenharmony_cistatic ecma_value_t 86425bb815Sopenharmony_ciecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument */ 87425bb815Sopenharmony_ci{ 88425bb815Sopenharmony_ci if (JERRY_UNLIKELY (!ecma_is_value_string (x))) 89425bb815Sopenharmony_ci { 90425bb815Sopenharmony_ci /* step 1 */ 91425bb815Sopenharmony_ci return ecma_copy_value (x); 92425bb815Sopenharmony_ci } 93425bb815Sopenharmony_ci 94425bb815Sopenharmony_ci uint32_t parse_opts = vm_is_direct_eval_form_call () ? ECMA_PARSE_DIRECT_EVAL : ECMA_PARSE_NO_OPTS; 95425bb815Sopenharmony_ci 96425bb815Sopenharmony_ci /* See also: ECMA-262 v5, 10.1.1 */ 97425bb815Sopenharmony_ci if (parse_opts && vm_is_strict_mode ()) 98425bb815Sopenharmony_ci { 99425bb815Sopenharmony_ci JERRY_ASSERT (parse_opts & ECMA_PARSE_DIRECT_EVAL); 100425bb815Sopenharmony_ci parse_opts |= ECMA_PARSE_STRICT_MODE; 101425bb815Sopenharmony_ci } 102425bb815Sopenharmony_ci 103425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 104425bb815Sopenharmony_ci if (vm_is_direct_eval_form_call ()) 105425bb815Sopenharmony_ci { 106425bb815Sopenharmony_ci parse_opts |= ECMA_GET_LOCAL_PARSE_OPTS (); 107425bb815Sopenharmony_ci } 108425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 109425bb815Sopenharmony_ci 110425bb815Sopenharmony_ci /* steps 2 to 8 */ 111425bb815Sopenharmony_ci return ecma_op_eval (ecma_get_string_from_value (x), parse_opts); 112425bb815Sopenharmony_ci} /* ecma_builtin_global_object_eval */ 113425bb815Sopenharmony_ci 114425bb815Sopenharmony_ci/** 115425bb815Sopenharmony_ci * The Global object's 'isNaN' routine 116425bb815Sopenharmony_ci * 117425bb815Sopenharmony_ci * See also: 118425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.2.4 119425bb815Sopenharmony_ci * 120425bb815Sopenharmony_ci * @return ecma value 121425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 122425bb815Sopenharmony_ci */ 123425bb815Sopenharmony_cistatic ecma_value_t 124425bb815Sopenharmony_ciecma_builtin_global_object_is_nan (ecma_number_t arg_num) /**< routine's first argument */ 125425bb815Sopenharmony_ci{ 126425bb815Sopenharmony_ci return ecma_make_boolean_value (ecma_number_is_nan (arg_num)); 127425bb815Sopenharmony_ci} /* ecma_builtin_global_object_is_nan */ 128425bb815Sopenharmony_ci 129425bb815Sopenharmony_ci/** 130425bb815Sopenharmony_ci * The Global object's 'isFinite' routine 131425bb815Sopenharmony_ci * 132425bb815Sopenharmony_ci * See also: 133425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.2.5 134425bb815Sopenharmony_ci * 135425bb815Sopenharmony_ci * @return ecma value 136425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 137425bb815Sopenharmony_ci */ 138425bb815Sopenharmony_cistatic ecma_value_t 139425bb815Sopenharmony_ciecma_builtin_global_object_is_finite (ecma_number_t arg_num) /**< routine's first argument */ 140425bb815Sopenharmony_ci{ 141425bb815Sopenharmony_ci bool is_finite = !(ecma_number_is_nan (arg_num) 142425bb815Sopenharmony_ci || ecma_number_is_infinity (arg_num)); 143425bb815Sopenharmony_ci 144425bb815Sopenharmony_ci return ecma_make_boolean_value (is_finite); 145425bb815Sopenharmony_ci} /* ecma_builtin_global_object_is_finite */ 146425bb815Sopenharmony_ci 147425bb815Sopenharmony_ci/** 148425bb815Sopenharmony_ci * Helper function to check whether a character is in a character bitset. 149425bb815Sopenharmony_ci * 150425bb815Sopenharmony_ci * @return true if the character is in the character bitset. 151425bb815Sopenharmony_ci */ 152425bb815Sopenharmony_cistatic bool 153425bb815Sopenharmony_ciecma_builtin_global_object_character_is_in (uint32_t character, /**< character */ 154425bb815Sopenharmony_ci const uint8_t *bitset) /**< character set */ 155425bb815Sopenharmony_ci{ 156425bb815Sopenharmony_ci JERRY_ASSERT (character < 128); 157425bb815Sopenharmony_ci return (bitset[character >> 3] & (1u << (character & 0x7))) != 0; 158425bb815Sopenharmony_ci} /* ecma_builtin_global_object_character_is_in */ 159425bb815Sopenharmony_ci 160425bb815Sopenharmony_ci/** 161425bb815Sopenharmony_ci * Unescaped URI characters bitset: 162425bb815Sopenharmony_ci * One bit for each character between 0 - 127. 163425bb815Sopenharmony_ci * Bit is set if the character is in the unescaped URI set. 164425bb815Sopenharmony_ci */ 165425bb815Sopenharmony_cistatic const uint8_t unescaped_uri_set[16] = 166425bb815Sopenharmony_ci{ 167425bb815Sopenharmony_ci 0x0, 0x0, 0x0, 0x0, 0xda, 0xff, 0xff, 0xaf, 168425bb815Sopenharmony_ci 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 169425bb815Sopenharmony_ci}; 170425bb815Sopenharmony_ci 171425bb815Sopenharmony_ci/** 172425bb815Sopenharmony_ci * Unescaped URI component characters bitset: 173425bb815Sopenharmony_ci * One bit for each character between 0 - 127. 174425bb815Sopenharmony_ci * Bit is set if the character is in the unescaped component URI set. 175425bb815Sopenharmony_ci */ 176425bb815Sopenharmony_cistatic const uint8_t unescaped_uri_component_set[16] = 177425bb815Sopenharmony_ci{ 178425bb815Sopenharmony_ci 0x0, 0x0, 0x0, 0x0, 0x82, 0x67, 0xff, 0x3, 179425bb815Sopenharmony_ci 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 180425bb815Sopenharmony_ci}; 181425bb815Sopenharmony_ci 182425bb815Sopenharmony_ci/** 183425bb815Sopenharmony_ci * Format is a percent sign followed by two hex digits. 184425bb815Sopenharmony_ci */ 185425bb815Sopenharmony_ci#define URI_ENCODED_BYTE_SIZE (3) 186425bb815Sopenharmony_ci 187425bb815Sopenharmony_ci/** 188425bb815Sopenharmony_ci * The Global object's 'decodeURI' and 'decodeURIComponent' routines 189425bb815Sopenharmony_ci * 190425bb815Sopenharmony_ci * See also: 191425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.3.1 192425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.3.2 193425bb815Sopenharmony_ci * 194425bb815Sopenharmony_ci * @return ecma value 195425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 196425bb815Sopenharmony_ci */ 197425bb815Sopenharmony_cistatic ecma_value_t 198425bb815Sopenharmony_ciecma_builtin_global_object_decode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 199425bb815Sopenharmony_ci * string buffer */ 200425bb815Sopenharmony_ci lit_utf8_size_t input_size, /**< routine's first argument's 201425bb815Sopenharmony_ci * string buffer's size */ 202425bb815Sopenharmony_ci const uint8_t *reserved_uri_bitset) /**< reserved characters bitset */ 203425bb815Sopenharmony_ci{ 204425bb815Sopenharmony_ci lit_utf8_byte_t *input_char_p = input_start_p; 205425bb815Sopenharmony_ci lit_utf8_byte_t *input_end_p = input_start_p + input_size; 206425bb815Sopenharmony_ci lit_utf8_size_t output_size = 0; 207425bb815Sopenharmony_ci /* 208425bb815Sopenharmony_ci * The URI decoding has two major phases: first we validate the input, 209425bb815Sopenharmony_ci * and compute the length of the output, then we decode the input. 210425bb815Sopenharmony_ci */ 211425bb815Sopenharmony_ci 212425bb815Sopenharmony_ci while (input_char_p < input_end_p) 213425bb815Sopenharmony_ci { 214425bb815Sopenharmony_ci /* 215425bb815Sopenharmony_ci * We expect that the input is a valid UTF-8 sequence, 216425bb815Sopenharmony_ci * so characters >= 0x80 can be let through. 217425bb815Sopenharmony_ci */ 218425bb815Sopenharmony_ci 219425bb815Sopenharmony_ci if (*input_char_p != '%') 220425bb815Sopenharmony_ci { 221425bb815Sopenharmony_ci output_size++; 222425bb815Sopenharmony_ci input_char_p++; 223425bb815Sopenharmony_ci continue; 224425bb815Sopenharmony_ci } 225425bb815Sopenharmony_ci 226425bb815Sopenharmony_ci uint32_t hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); 227425bb815Sopenharmony_ci if (hex_value == UINT32_MAX) 228425bb815Sopenharmony_ci { 229425bb815Sopenharmony_ci return ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid hexadecimal value.")); 230425bb815Sopenharmony_ci } 231425bb815Sopenharmony_ci 232425bb815Sopenharmony_ci ecma_char_t decoded_byte = (ecma_char_t) hex_value; 233425bb815Sopenharmony_ci input_char_p += URI_ENCODED_BYTE_SIZE; 234425bb815Sopenharmony_ci 235425bb815Sopenharmony_ci if (decoded_byte <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 236425bb815Sopenharmony_ci { 237425bb815Sopenharmony_ci /* 238425bb815Sopenharmony_ci * We don't decode those bytes, which are part of reserved_uri_bitset 239425bb815Sopenharmony_ci * but not part of unescaped_uri_component_set. 240425bb815Sopenharmony_ci */ 241425bb815Sopenharmony_ci if (ecma_builtin_global_object_character_is_in (decoded_byte, reserved_uri_bitset) 242425bb815Sopenharmony_ci && !ecma_builtin_global_object_character_is_in (decoded_byte, unescaped_uri_component_set)) 243425bb815Sopenharmony_ci { 244425bb815Sopenharmony_ci output_size += URI_ENCODED_BYTE_SIZE; 245425bb815Sopenharmony_ci } 246425bb815Sopenharmony_ci else 247425bb815Sopenharmony_ci { 248425bb815Sopenharmony_ci output_size++; 249425bb815Sopenharmony_ci } 250425bb815Sopenharmony_ci } 251425bb815Sopenharmony_ci else if ((decoded_byte & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) 252425bb815Sopenharmony_ci { 253425bb815Sopenharmony_ci output_size += 3; 254425bb815Sopenharmony_ci } 255425bb815Sopenharmony_ci else 256425bb815Sopenharmony_ci { 257425bb815Sopenharmony_ci output_size++; 258425bb815Sopenharmony_ci } 259425bb815Sopenharmony_ci } 260425bb815Sopenharmony_ci 261425bb815Sopenharmony_ci ecma_value_t ret_value = ECMA_VALUE_EMPTY; 262425bb815Sopenharmony_ci 263425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (output_start_p, 264425bb815Sopenharmony_ci output_size, 265425bb815Sopenharmony_ci lit_utf8_byte_t); 266425bb815Sopenharmony_ci 267425bb815Sopenharmony_ci input_char_p = input_start_p; 268425bb815Sopenharmony_ci lit_utf8_byte_t *output_char_p = output_start_p; 269425bb815Sopenharmony_ci 270425bb815Sopenharmony_ci while (input_char_p < input_end_p) 271425bb815Sopenharmony_ci { 272425bb815Sopenharmony_ci /* Input decode. */ 273425bb815Sopenharmony_ci if (*input_char_p != '%') 274425bb815Sopenharmony_ci { 275425bb815Sopenharmony_ci *output_char_p++ = *input_char_p++; 276425bb815Sopenharmony_ci continue; 277425bb815Sopenharmony_ci } 278425bb815Sopenharmony_ci 279425bb815Sopenharmony_ci uint32_t hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); 280425bb815Sopenharmony_ci if (hex_value == UINT32_MAX) 281425bb815Sopenharmony_ci { 282425bb815Sopenharmony_ci ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid hexadecimal value.")); 283425bb815Sopenharmony_ci break; 284425bb815Sopenharmony_ci } 285425bb815Sopenharmony_ci 286425bb815Sopenharmony_ci ecma_char_t decoded_byte = (ecma_char_t) hex_value; 287425bb815Sopenharmony_ci input_char_p += URI_ENCODED_BYTE_SIZE; 288425bb815Sopenharmony_ci 289425bb815Sopenharmony_ci if (decoded_byte <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 290425bb815Sopenharmony_ci { 291425bb815Sopenharmony_ci if (ecma_builtin_global_object_character_is_in (decoded_byte, reserved_uri_bitset) 292425bb815Sopenharmony_ci && !ecma_builtin_global_object_character_is_in (decoded_byte, unescaped_uri_component_set)) 293425bb815Sopenharmony_ci { 294425bb815Sopenharmony_ci *output_char_p = '%'; 295425bb815Sopenharmony_ci output_char_p++; 296425bb815Sopenharmony_ci input_char_p -= 2; 297425bb815Sopenharmony_ci } 298425bb815Sopenharmony_ci else 299425bb815Sopenharmony_ci { 300425bb815Sopenharmony_ci *output_char_p++ = (lit_utf8_byte_t) decoded_byte; 301425bb815Sopenharmony_ci } 302425bb815Sopenharmony_ci } 303425bb815Sopenharmony_ci else 304425bb815Sopenharmony_ci { 305425bb815Sopenharmony_ci uint32_t bytes_count; 306425bb815Sopenharmony_ci 307425bb815Sopenharmony_ci if ((decoded_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) 308425bb815Sopenharmony_ci { 309425bb815Sopenharmony_ci bytes_count = 2; 310425bb815Sopenharmony_ci } 311425bb815Sopenharmony_ci else if ((decoded_byte & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) 312425bb815Sopenharmony_ci { 313425bb815Sopenharmony_ci bytes_count = 3; 314425bb815Sopenharmony_ci } 315425bb815Sopenharmony_ci else if ((decoded_byte & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) 316425bb815Sopenharmony_ci { 317425bb815Sopenharmony_ci bytes_count = 4; 318425bb815Sopenharmony_ci } 319425bb815Sopenharmony_ci else 320425bb815Sopenharmony_ci { 321425bb815Sopenharmony_ci ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 character.")); 322425bb815Sopenharmony_ci break; 323425bb815Sopenharmony_ci } 324425bb815Sopenharmony_ci 325425bb815Sopenharmony_ci lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; 326425bb815Sopenharmony_ci octets[0] = (lit_utf8_byte_t) decoded_byte; 327425bb815Sopenharmony_ci bool is_valid = true; 328425bb815Sopenharmony_ci 329425bb815Sopenharmony_ci for (uint32_t i = 1; i < bytes_count; i++) 330425bb815Sopenharmony_ci { 331425bb815Sopenharmony_ci if (input_char_p >= input_end_p || *input_char_p != '%') 332425bb815Sopenharmony_ci { 333425bb815Sopenharmony_ci is_valid = false; 334425bb815Sopenharmony_ci break; 335425bb815Sopenharmony_ci } 336425bb815Sopenharmony_ci else 337425bb815Sopenharmony_ci { 338425bb815Sopenharmony_ci hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); 339425bb815Sopenharmony_ci 340425bb815Sopenharmony_ci if (hex_value == UINT32_MAX || (hex_value & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) 341425bb815Sopenharmony_ci { 342425bb815Sopenharmony_ci is_valid = false; 343425bb815Sopenharmony_ci break; 344425bb815Sopenharmony_ci } 345425bb815Sopenharmony_ci 346425bb815Sopenharmony_ci input_char_p += URI_ENCODED_BYTE_SIZE; 347425bb815Sopenharmony_ci octets[i] = (lit_utf8_byte_t) hex_value; 348425bb815Sopenharmony_ci } 349425bb815Sopenharmony_ci } 350425bb815Sopenharmony_ci 351425bb815Sopenharmony_ci if (!is_valid 352425bb815Sopenharmony_ci || !lit_is_valid_utf8_string (octets, bytes_count)) 353425bb815Sopenharmony_ci { 354425bb815Sopenharmony_ci ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 string.")); 355425bb815Sopenharmony_ci break; 356425bb815Sopenharmony_ci } 357425bb815Sopenharmony_ci 358425bb815Sopenharmony_ci lit_code_point_t cp; 359425bb815Sopenharmony_ci lit_read_code_point_from_utf8 (octets, bytes_count, &cp); 360425bb815Sopenharmony_ci 361425bb815Sopenharmony_ci if (lit_is_code_point_utf16_high_surrogate (cp) 362425bb815Sopenharmony_ci || lit_is_code_point_utf16_low_surrogate (cp)) 363425bb815Sopenharmony_ci { 364425bb815Sopenharmony_ci ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 codepoint.")); 365425bb815Sopenharmony_ci break; 366425bb815Sopenharmony_ci } 367425bb815Sopenharmony_ci 368425bb815Sopenharmony_ci output_char_p += lit_code_point_to_cesu8 (cp, output_char_p); 369425bb815Sopenharmony_ci } 370425bb815Sopenharmony_ci } 371425bb815Sopenharmony_ci 372425bb815Sopenharmony_ci if (ecma_is_value_empty (ret_value)) 373425bb815Sopenharmony_ci { 374425bb815Sopenharmony_ci JERRY_ASSERT (output_start_p + output_size == output_char_p); 375425bb815Sopenharmony_ci 376425bb815Sopenharmony_ci if (lit_is_valid_cesu8_string (output_start_p, output_size)) 377425bb815Sopenharmony_ci { 378425bb815Sopenharmony_ci ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_size); 379425bb815Sopenharmony_ci ret_value = ecma_make_string_value (output_string_p); 380425bb815Sopenharmony_ci } 381425bb815Sopenharmony_ci else 382425bb815Sopenharmony_ci { 383425bb815Sopenharmony_ci ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid CESU8 string.")); 384425bb815Sopenharmony_ci } 385425bb815Sopenharmony_ci } 386425bb815Sopenharmony_ci 387425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); 388425bb815Sopenharmony_ci 389425bb815Sopenharmony_ci return ret_value; 390425bb815Sopenharmony_ci} /* ecma_builtin_global_object_decode_uri_helper */ 391425bb815Sopenharmony_ci 392425bb815Sopenharmony_ci/** 393425bb815Sopenharmony_ci * Helper function to encode byte as hexadecimal values. 394425bb815Sopenharmony_ci */ 395425bb815Sopenharmony_cistatic void 396425bb815Sopenharmony_ciecma_builtin_global_object_byte_to_hex (lit_utf8_byte_t *dest_p, /**< destination pointer */ 397425bb815Sopenharmony_ci uint32_t byte) /**< value */ 398425bb815Sopenharmony_ci{ 399425bb815Sopenharmony_ci JERRY_ASSERT (byte < 256); 400425bb815Sopenharmony_ci 401425bb815Sopenharmony_ci dest_p[0] = LIT_CHAR_PERCENT; 402425bb815Sopenharmony_ci ecma_char_t hex_digit = (ecma_char_t) (byte >> 4); 403425bb815Sopenharmony_ci dest_p[1] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); 404425bb815Sopenharmony_ci hex_digit = (lit_utf8_byte_t) (byte & 0xf); 405425bb815Sopenharmony_ci dest_p[2] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); 406425bb815Sopenharmony_ci} /* ecma_builtin_global_object_byte_to_hex */ 407425bb815Sopenharmony_ci 408425bb815Sopenharmony_ci/** 409425bb815Sopenharmony_ci * The Global object's 'encodeURI' and 'encodeURIComponent' routines 410425bb815Sopenharmony_ci * 411425bb815Sopenharmony_ci * See also: 412425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.3.3 413425bb815Sopenharmony_ci * ECMA-262 v5, 15.1.3.4 414425bb815Sopenharmony_ci * 415425bb815Sopenharmony_ci * @return ecma value 416425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 417425bb815Sopenharmony_ci */ 418425bb815Sopenharmony_cistatic ecma_value_t 419425bb815Sopenharmony_ciecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 420425bb815Sopenharmony_ci * string buffer */ 421425bb815Sopenharmony_ci lit_utf8_size_t input_size, /**< routine's first argument's 422425bb815Sopenharmony_ci * string buffer's size */ 423425bb815Sopenharmony_ci const uint8_t *unescaped_uri_bitset_p) /**< unescaped bitset */ 424425bb815Sopenharmony_ci{ 425425bb815Sopenharmony_ci /* 426425bb815Sopenharmony_ci * The URI encoding has two major phases: first we validate the input, 427425bb815Sopenharmony_ci * and compute the length of the output, then we encode the input. 428425bb815Sopenharmony_ci */ 429425bb815Sopenharmony_ci 430425bb815Sopenharmony_ci lit_utf8_byte_t *input_char_p = input_start_p; 431425bb815Sopenharmony_ci const lit_utf8_byte_t *input_end_p = input_start_p + input_size; 432425bb815Sopenharmony_ci lit_utf8_size_t output_length = 0; 433425bb815Sopenharmony_ci lit_code_point_t cp; 434425bb815Sopenharmony_ci ecma_char_t ch; 435425bb815Sopenharmony_ci lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; 436425bb815Sopenharmony_ci memset (octets, LIT_BYTE_NULL, LIT_UTF8_MAX_BYTES_IN_CODE_POINT); 437425bb815Sopenharmony_ci 438425bb815Sopenharmony_ci while (input_char_p < input_end_p) 439425bb815Sopenharmony_ci { 440425bb815Sopenharmony_ci /* Input validation, we need to reject stray surrogates. */ 441425bb815Sopenharmony_ci input_char_p += lit_read_code_unit_from_utf8 (input_char_p, &ch); 442425bb815Sopenharmony_ci 443425bb815Sopenharmony_ci if (lit_is_code_point_utf16_low_surrogate (ch)) 444425bb815Sopenharmony_ci { 445425bb815Sopenharmony_ci return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); 446425bb815Sopenharmony_ci } 447425bb815Sopenharmony_ci 448425bb815Sopenharmony_ci cp = ch; 449425bb815Sopenharmony_ci 450425bb815Sopenharmony_ci if (lit_is_code_point_utf16_high_surrogate (ch)) 451425bb815Sopenharmony_ci { 452425bb815Sopenharmony_ci if (input_char_p == input_end_p) 453425bb815Sopenharmony_ci { 454425bb815Sopenharmony_ci return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); 455425bb815Sopenharmony_ci } 456425bb815Sopenharmony_ci 457425bb815Sopenharmony_ci ecma_char_t next_ch; 458425bb815Sopenharmony_ci lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (input_char_p, &next_ch); 459425bb815Sopenharmony_ci 460425bb815Sopenharmony_ci if (lit_is_code_point_utf16_low_surrogate (next_ch)) 461425bb815Sopenharmony_ci { 462425bb815Sopenharmony_ci cp = lit_convert_surrogate_pair_to_code_point (ch, next_ch); 463425bb815Sopenharmony_ci input_char_p += read_size; 464425bb815Sopenharmony_ci } 465425bb815Sopenharmony_ci else 466425bb815Sopenharmony_ci { 467425bb815Sopenharmony_ci return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); 468425bb815Sopenharmony_ci } 469425bb815Sopenharmony_ci } 470425bb815Sopenharmony_ci 471425bb815Sopenharmony_ci lit_utf8_size_t utf_size = lit_code_point_to_utf8 (cp, octets); 472425bb815Sopenharmony_ci 473425bb815Sopenharmony_ci if (utf_size == 1) 474425bb815Sopenharmony_ci { 475425bb815Sopenharmony_ci if (ecma_builtin_global_object_character_is_in (octets[0], unescaped_uri_bitset_p)) 476425bb815Sopenharmony_ci { 477425bb815Sopenharmony_ci output_length++; 478425bb815Sopenharmony_ci } 479425bb815Sopenharmony_ci else 480425bb815Sopenharmony_ci { 481425bb815Sopenharmony_ci output_length += URI_ENCODED_BYTE_SIZE; 482425bb815Sopenharmony_ci } 483425bb815Sopenharmony_ci } 484425bb815Sopenharmony_ci else 485425bb815Sopenharmony_ci { 486425bb815Sopenharmony_ci output_length += utf_size * URI_ENCODED_BYTE_SIZE; 487425bb815Sopenharmony_ci } 488425bb815Sopenharmony_ci } 489425bb815Sopenharmony_ci 490425bb815Sopenharmony_ci ecma_value_t ret_value; 491425bb815Sopenharmony_ci 492425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (output_start_p, 493425bb815Sopenharmony_ci output_length, 494425bb815Sopenharmony_ci lit_utf8_byte_t); 495425bb815Sopenharmony_ci 496425bb815Sopenharmony_ci lit_utf8_byte_t *output_char_p = output_start_p; 497425bb815Sopenharmony_ci input_char_p = input_start_p; 498425bb815Sopenharmony_ci 499425bb815Sopenharmony_ci while (input_char_p < input_end_p) 500425bb815Sopenharmony_ci { 501425bb815Sopenharmony_ci /* Input decode. */ 502425bb815Sopenharmony_ci input_char_p += lit_read_code_unit_from_utf8 (input_char_p, &ch); 503425bb815Sopenharmony_ci cp = ch; 504425bb815Sopenharmony_ci 505425bb815Sopenharmony_ci if (lit_is_code_point_utf16_high_surrogate (ch)) 506425bb815Sopenharmony_ci { 507425bb815Sopenharmony_ci ecma_char_t next_ch; 508425bb815Sopenharmony_ci lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (input_char_p, &next_ch); 509425bb815Sopenharmony_ci 510425bb815Sopenharmony_ci if (lit_is_code_point_utf16_low_surrogate (next_ch)) 511425bb815Sopenharmony_ci { 512425bb815Sopenharmony_ci cp = lit_convert_surrogate_pair_to_code_point (ch, next_ch); 513425bb815Sopenharmony_ci input_char_p += read_size; 514425bb815Sopenharmony_ci } 515425bb815Sopenharmony_ci } 516425bb815Sopenharmony_ci 517425bb815Sopenharmony_ci lit_utf8_size_t utf_size = lit_code_point_to_utf8 (cp, octets); 518425bb815Sopenharmony_ci 519425bb815Sopenharmony_ci if (utf_size == 1) 520425bb815Sopenharmony_ci { 521425bb815Sopenharmony_ci if (ecma_builtin_global_object_character_is_in (octets[0], unescaped_uri_bitset_p)) 522425bb815Sopenharmony_ci { 523425bb815Sopenharmony_ci *output_char_p++ = octets[0]; 524425bb815Sopenharmony_ci } 525425bb815Sopenharmony_ci else 526425bb815Sopenharmony_ci { 527425bb815Sopenharmony_ci ecma_builtin_global_object_byte_to_hex (output_char_p, octets[0]); 528425bb815Sopenharmony_ci output_char_p += URI_ENCODED_BYTE_SIZE; 529425bb815Sopenharmony_ci } 530425bb815Sopenharmony_ci } 531425bb815Sopenharmony_ci else 532425bb815Sopenharmony_ci { 533425bb815Sopenharmony_ci for (uint32_t i = 0; i < utf_size; i++) 534425bb815Sopenharmony_ci { 535425bb815Sopenharmony_ci ecma_builtin_global_object_byte_to_hex (output_char_p, octets[i]); 536425bb815Sopenharmony_ci output_char_p += URI_ENCODED_BYTE_SIZE; 537425bb815Sopenharmony_ci } 538425bb815Sopenharmony_ci } 539425bb815Sopenharmony_ci } 540425bb815Sopenharmony_ci 541425bb815Sopenharmony_ci JERRY_ASSERT (output_start_p + output_length == output_char_p); 542425bb815Sopenharmony_ci 543425bb815Sopenharmony_ci ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_length); 544425bb815Sopenharmony_ci 545425bb815Sopenharmony_ci ret_value = ecma_make_string_value (output_string_p); 546425bb815Sopenharmony_ci 547425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); 548425bb815Sopenharmony_ci 549425bb815Sopenharmony_ci return ret_value; 550425bb815Sopenharmony_ci} /* ecma_builtin_global_object_encode_uri_helper */ 551425bb815Sopenharmony_ci 552425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_ANNEXB) 553425bb815Sopenharmony_ci 554425bb815Sopenharmony_ci/** 555425bb815Sopenharmony_ci * Maximum value of a byte. 556425bb815Sopenharmony_ci */ 557425bb815Sopenharmony_ci#define ECMA_ESCAPE_MAXIMUM_BYTE_VALUE (255) 558425bb815Sopenharmony_ci 559425bb815Sopenharmony_ci/** 560425bb815Sopenharmony_ci * Format is a percent sign followed by lowercase u and four hex digits. 561425bb815Sopenharmony_ci */ 562425bb815Sopenharmony_ci#define ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE (6) 563425bb815Sopenharmony_ci 564425bb815Sopenharmony_ci/** 565425bb815Sopenharmony_ci * Escape characters bitset: 566425bb815Sopenharmony_ci * One bit for each character between 0 - 127. 567425bb815Sopenharmony_ci * Bit is set if the character does not need to be converted to %xx form. 568425bb815Sopenharmony_ci * These characters are: a-z A-Z 0-9 @ * _ + - . / 569425bb815Sopenharmony_ci */ 570425bb815Sopenharmony_cistatic const uint8_t ecma_escape_set[16] = 571425bb815Sopenharmony_ci{ 572425bb815Sopenharmony_ci 0x0, 0x0, 0x0, 0x0, 0x0, 0xec, 0xff, 0x3, 573425bb815Sopenharmony_ci 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x7 574425bb815Sopenharmony_ci}; 575425bb815Sopenharmony_ci 576425bb815Sopenharmony_ci/** 577425bb815Sopenharmony_ci * The Global object's 'escape' routine 578425bb815Sopenharmony_ci * 579425bb815Sopenharmony_ci * See also: 580425bb815Sopenharmony_ci * ECMA-262 v5, B.2.1 581425bb815Sopenharmony_ci * 582425bb815Sopenharmony_ci * @return ecma value 583425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 584425bb815Sopenharmony_ci */ 585425bb815Sopenharmony_cistatic ecma_value_t 586425bb815Sopenharmony_ciecma_builtin_global_object_escape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 587425bb815Sopenharmony_ci * string buffer */ 588425bb815Sopenharmony_ci lit_utf8_size_t input_size) /**< routine's first argument's 589425bb815Sopenharmony_ci * string buffer's size */ 590425bb815Sopenharmony_ci{ 591425bb815Sopenharmony_ci /* 592425bb815Sopenharmony_ci * The escape routine has two major phases: first we compute 593425bb815Sopenharmony_ci * the length of the output, then we encode the input. 594425bb815Sopenharmony_ci */ 595425bb815Sopenharmony_ci const lit_utf8_byte_t *input_curr_p = input_start_p; 596425bb815Sopenharmony_ci const lit_utf8_byte_t *input_end_p = input_start_p + input_size; 597425bb815Sopenharmony_ci lit_utf8_size_t output_length = 0; 598425bb815Sopenharmony_ci 599425bb815Sopenharmony_ci while (input_curr_p < input_end_p) 600425bb815Sopenharmony_ci { 601425bb815Sopenharmony_ci ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); 602425bb815Sopenharmony_ci 603425bb815Sopenharmony_ci if (chr <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 604425bb815Sopenharmony_ci { 605425bb815Sopenharmony_ci if (ecma_builtin_global_object_character_is_in ((uint32_t) chr, ecma_escape_set)) 606425bb815Sopenharmony_ci { 607425bb815Sopenharmony_ci output_length++; 608425bb815Sopenharmony_ci } 609425bb815Sopenharmony_ci else 610425bb815Sopenharmony_ci { 611425bb815Sopenharmony_ci output_length += URI_ENCODED_BYTE_SIZE; 612425bb815Sopenharmony_ci } 613425bb815Sopenharmony_ci } 614425bb815Sopenharmony_ci else if (chr > ECMA_ESCAPE_MAXIMUM_BYTE_VALUE) 615425bb815Sopenharmony_ci { 616425bb815Sopenharmony_ci output_length += ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE; 617425bb815Sopenharmony_ci } 618425bb815Sopenharmony_ci else 619425bb815Sopenharmony_ci { 620425bb815Sopenharmony_ci output_length += URI_ENCODED_BYTE_SIZE; 621425bb815Sopenharmony_ci } 622425bb815Sopenharmony_ci } 623425bb815Sopenharmony_ci 624425bb815Sopenharmony_ci ecma_value_t ret_value; 625425bb815Sopenharmony_ci 626425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (output_start_p, 627425bb815Sopenharmony_ci output_length, 628425bb815Sopenharmony_ci lit_utf8_byte_t); 629425bb815Sopenharmony_ci 630425bb815Sopenharmony_ci lit_utf8_byte_t *output_char_p = output_start_p; 631425bb815Sopenharmony_ci 632425bb815Sopenharmony_ci input_curr_p = input_start_p; 633425bb815Sopenharmony_ci 634425bb815Sopenharmony_ci while (input_curr_p < input_end_p) 635425bb815Sopenharmony_ci { 636425bb815Sopenharmony_ci ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); 637425bb815Sopenharmony_ci 638425bb815Sopenharmony_ci if (chr <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 639425bb815Sopenharmony_ci { 640425bb815Sopenharmony_ci if (ecma_builtin_global_object_character_is_in ((uint32_t) chr, ecma_escape_set)) 641425bb815Sopenharmony_ci { 642425bb815Sopenharmony_ci *output_char_p = (lit_utf8_byte_t) chr; 643425bb815Sopenharmony_ci output_char_p++; 644425bb815Sopenharmony_ci } 645425bb815Sopenharmony_ci else 646425bb815Sopenharmony_ci { 647425bb815Sopenharmony_ci ecma_builtin_global_object_byte_to_hex (output_char_p, (lit_utf8_byte_t) chr); 648425bb815Sopenharmony_ci output_char_p += URI_ENCODED_BYTE_SIZE; 649425bb815Sopenharmony_ci } 650425bb815Sopenharmony_ci } 651425bb815Sopenharmony_ci else if (chr > ECMA_ESCAPE_MAXIMUM_BYTE_VALUE) 652425bb815Sopenharmony_ci { 653425bb815Sopenharmony_ci /* 654425bb815Sopenharmony_ci * Although ecma_builtin_global_object_byte_to_hex inserts a percent (%) sign 655425bb815Sopenharmony_ci * the follow-up changes overwrites it. We call this function twice to 656425bb815Sopenharmony_ci * produce four hexadecimal characters (%uxxxx format). 657425bb815Sopenharmony_ci */ 658425bb815Sopenharmony_ci ecma_builtin_global_object_byte_to_hex (output_char_p + 3, (lit_utf8_byte_t) (chr & 0xff)); 659425bb815Sopenharmony_ci ecma_builtin_global_object_byte_to_hex (output_char_p + 1, (lit_utf8_byte_t) (chr >> JERRY_BITSINBYTE)); 660425bb815Sopenharmony_ci output_char_p[0] = LIT_CHAR_PERCENT; 661425bb815Sopenharmony_ci output_char_p[1] = LIT_CHAR_LOWERCASE_U; 662425bb815Sopenharmony_ci output_char_p += ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE; 663425bb815Sopenharmony_ci } 664425bb815Sopenharmony_ci else 665425bb815Sopenharmony_ci { 666425bb815Sopenharmony_ci ecma_builtin_global_object_byte_to_hex (output_char_p, (lit_utf8_byte_t) chr); 667425bb815Sopenharmony_ci output_char_p += URI_ENCODED_BYTE_SIZE; 668425bb815Sopenharmony_ci } 669425bb815Sopenharmony_ci } 670425bb815Sopenharmony_ci 671425bb815Sopenharmony_ci JERRY_ASSERT (output_start_p + output_length == output_char_p); 672425bb815Sopenharmony_ci 673425bb815Sopenharmony_ci ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_length); 674425bb815Sopenharmony_ci 675425bb815Sopenharmony_ci ret_value = ecma_make_string_value (output_string_p); 676425bb815Sopenharmony_ci 677425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); 678425bb815Sopenharmony_ci 679425bb815Sopenharmony_ci return ret_value; 680425bb815Sopenharmony_ci} /* ecma_builtin_global_object_escape */ 681425bb815Sopenharmony_ci 682425bb815Sopenharmony_ci/** 683425bb815Sopenharmony_ci * The Global object's 'unescape' routine 684425bb815Sopenharmony_ci * 685425bb815Sopenharmony_ci * See also: 686425bb815Sopenharmony_ci * ECMA-262 v5, B.2.2 687425bb815Sopenharmony_ci * 688425bb815Sopenharmony_ci * @return ecma value 689425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 690425bb815Sopenharmony_ci */ 691425bb815Sopenharmony_cistatic ecma_value_t 692425bb815Sopenharmony_ciecma_builtin_global_object_unescape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 693425bb815Sopenharmony_ci * string buffer */ 694425bb815Sopenharmony_ci lit_utf8_size_t input_size) /**< routine's first argument's 695425bb815Sopenharmony_ci * string buffer's size */ 696425bb815Sopenharmony_ci{ 697425bb815Sopenharmony_ci const lit_utf8_byte_t *input_curr_p = input_start_p; 698425bb815Sopenharmony_ci const lit_utf8_byte_t *input_end_p = input_start_p + input_size; 699425bb815Sopenharmony_ci /* 4. */ 700425bb815Sopenharmony_ci /* The length of input string is always greater than output string 701425bb815Sopenharmony_ci * so we re-use the input string buffer. 702425bb815Sopenharmony_ci * The %xx is three byte long, and the maximum encoded value is 0xff, 703425bb815Sopenharmony_ci * which maximum encoded length is two byte. Similar to this, the maximum 704425bb815Sopenharmony_ci * encoded length of %uxxxx is four byte. */ 705425bb815Sopenharmony_ci lit_utf8_byte_t *output_char_p = input_start_p; 706425bb815Sopenharmony_ci 707425bb815Sopenharmony_ci /* The state of parsing that tells us where we are in an escape pattern. 708425bb815Sopenharmony_ci * 0 we are outside of pattern, 709425bb815Sopenharmony_ci * 1 found '%', start of pattern, 710425bb815Sopenharmony_ci * 2 found first hex digit of '%xy' pattern 711425bb815Sopenharmony_ci * 3 found valid '%xy' pattern 712425bb815Sopenharmony_ci * 4 found 'u', start of '%uwxyz' pattern 713425bb815Sopenharmony_ci * 5-7 found hex digits of '%uwxyz' pattern 714425bb815Sopenharmony_ci * 8 found valid '%uwxyz' pattern 715425bb815Sopenharmony_ci */ 716425bb815Sopenharmony_ci uint8_t status = 0; 717425bb815Sopenharmony_ci ecma_char_t hex_digits = 0; 718425bb815Sopenharmony_ci /* 5. */ 719425bb815Sopenharmony_ci while (input_curr_p < input_end_p) 720425bb815Sopenharmony_ci { 721425bb815Sopenharmony_ci /* 6. */ 722425bb815Sopenharmony_ci ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); 723425bb815Sopenharmony_ci 724425bb815Sopenharmony_ci /* 7-8. */ 725425bb815Sopenharmony_ci if (status == 0 && chr == LIT_CHAR_PERCENT) 726425bb815Sopenharmony_ci { 727425bb815Sopenharmony_ci /* Found '%' char, start of escape sequence. */ 728425bb815Sopenharmony_ci status = 1; 729425bb815Sopenharmony_ci } 730425bb815Sopenharmony_ci /* 9-10. */ 731425bb815Sopenharmony_ci else if (status == 1 && chr == LIT_CHAR_LOWERCASE_U) 732425bb815Sopenharmony_ci { 733425bb815Sopenharmony_ci /* Found 'u' char after '%'. */ 734425bb815Sopenharmony_ci status = 4; 735425bb815Sopenharmony_ci } 736425bb815Sopenharmony_ci else if (status > 0 && lit_char_is_hex_digit (chr)) 737425bb815Sopenharmony_ci { 738425bb815Sopenharmony_ci /* Found hexadecimal digit in escape sequence. */ 739425bb815Sopenharmony_ci hex_digits = (ecma_char_t) (hex_digits * 16 + (ecma_char_t) lit_char_hex_to_int (chr)); 740425bb815Sopenharmony_ci status++; 741425bb815Sopenharmony_ci } 742425bb815Sopenharmony_ci else 743425bb815Sopenharmony_ci { 744425bb815Sopenharmony_ci /* Previously found hexadecimal digit in escape sequence but it's not valid '%xy' pattern 745425bb815Sopenharmony_ci * so essentially it was only a simple character. */ 746425bb815Sopenharmony_ci status = 0; 747425bb815Sopenharmony_ci } 748425bb815Sopenharmony_ci 749425bb815Sopenharmony_ci /* 11-17. Found valid '%uwxyz' or '%xy' escape. */ 750425bb815Sopenharmony_ci if (status == 8 || status == 3) 751425bb815Sopenharmony_ci { 752425bb815Sopenharmony_ci output_char_p -= (status == 3) ? 2 : 5; 753425bb815Sopenharmony_ci status = 0; 754425bb815Sopenharmony_ci chr = hex_digits; 755425bb815Sopenharmony_ci hex_digits = 0; 756425bb815Sopenharmony_ci } 757425bb815Sopenharmony_ci 758425bb815Sopenharmony_ci /* Copying character. */ 759425bb815Sopenharmony_ci lit_utf8_size_t lit_size = lit_code_unit_to_utf8 (chr, output_char_p); 760425bb815Sopenharmony_ci output_char_p += lit_size; 761425bb815Sopenharmony_ci JERRY_ASSERT (output_char_p <= input_curr_p); 762425bb815Sopenharmony_ci } 763425bb815Sopenharmony_ci 764425bb815Sopenharmony_ci lit_utf8_size_t output_length = (lit_utf8_size_t) (output_char_p - input_start_p); 765425bb815Sopenharmony_ci ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (input_start_p, output_length); 766425bb815Sopenharmony_ci return ecma_make_string_value (output_string_p); 767425bb815Sopenharmony_ci} /* ecma_builtin_global_object_unescape */ 768425bb815Sopenharmony_ci 769425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ 770425bb815Sopenharmony_ci 771425bb815Sopenharmony_ci/** 772425bb815Sopenharmony_ci * Dispatcher of the built-in's routines 773425bb815Sopenharmony_ci * 774425bb815Sopenharmony_ci * @return ecma value 775425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 776425bb815Sopenharmony_ci */ 777425bb815Sopenharmony_ciecma_value_t 778425bb815Sopenharmony_ciecma_builtin_global_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine identifier */ 779425bb815Sopenharmony_ci ecma_value_t this_arg, /**< 'this' argument value */ 780425bb815Sopenharmony_ci const ecma_value_t arguments_list_p[], /**< list of arguments 781425bb815Sopenharmony_ci * passed to routine */ 782425bb815Sopenharmony_ci ecma_length_t arguments_number) /**< length of arguments' list */ 783425bb815Sopenharmony_ci{ 784425bb815Sopenharmony_ci JERRY_UNUSED (this_arg); 785425bb815Sopenharmony_ci JERRY_UNUSED (arguments_list_p); 786425bb815Sopenharmony_ci JERRY_UNUSED (arguments_number); 787425bb815Sopenharmony_ci 788425bb815Sopenharmony_ci ecma_value_t routine_arg_1 = arguments_list_p[0]; 789425bb815Sopenharmony_ci 790425bb815Sopenharmony_ci if (builtin_routine_id == ECMA_GLOBAL_EVAL) 791425bb815Sopenharmony_ci { 792425bb815Sopenharmony_ci return ecma_builtin_global_object_eval (routine_arg_1); 793425bb815Sopenharmony_ci } 794425bb815Sopenharmony_ci 795425bb815Sopenharmony_ci if (builtin_routine_id <= ECMA_GLOBAL_IS_FINITE) 796425bb815Sopenharmony_ci { 797425bb815Sopenharmony_ci ecma_number_t arg_num; 798425bb815Sopenharmony_ci 799425bb815Sopenharmony_ci routine_arg_1 = ecma_get_number (routine_arg_1, &arg_num); 800425bb815Sopenharmony_ci 801425bb815Sopenharmony_ci if (!ecma_is_value_empty (routine_arg_1)) 802425bb815Sopenharmony_ci { 803425bb815Sopenharmony_ci return routine_arg_1; 804425bb815Sopenharmony_ci } 805425bb815Sopenharmony_ci 806425bb815Sopenharmony_ci if (builtin_routine_id == ECMA_GLOBAL_IS_NAN) 807425bb815Sopenharmony_ci { 808425bb815Sopenharmony_ci return ecma_builtin_global_object_is_nan (arg_num); 809425bb815Sopenharmony_ci } 810425bb815Sopenharmony_ci 811425bb815Sopenharmony_ci JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_IS_FINITE); 812425bb815Sopenharmony_ci 813425bb815Sopenharmony_ci return ecma_builtin_global_object_is_finite (arg_num); 814425bb815Sopenharmony_ci } 815425bb815Sopenharmony_ci 816425bb815Sopenharmony_ci ecma_string_t *str_p = ecma_op_to_string (routine_arg_1); 817425bb815Sopenharmony_ci 818425bb815Sopenharmony_ci if (JERRY_UNLIKELY (str_p == NULL)) 819425bb815Sopenharmony_ci { 820425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 821425bb815Sopenharmony_ci } 822425bb815Sopenharmony_ci 823425bb815Sopenharmony_ci ecma_value_t ret_value; 824425bb815Sopenharmony_ci 825425bb815Sopenharmony_ci if (builtin_routine_id <= ECMA_GLOBAL_PARSE_FLOAT) 826425bb815Sopenharmony_ci { 827425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); 828425bb815Sopenharmony_ci 829425bb815Sopenharmony_ci if (builtin_routine_id == ECMA_GLOBAL_PARSE_INT) 830425bb815Sopenharmony_ci { 831425bb815Sopenharmony_ci ret_value = ecma_number_parse_int (string_buff, 832425bb815Sopenharmony_ci string_buff_size, 833425bb815Sopenharmony_ci arguments_list_p[1]); 834425bb815Sopenharmony_ci } 835425bb815Sopenharmony_ci else 836425bb815Sopenharmony_ci { 837425bb815Sopenharmony_ci JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_PARSE_FLOAT); 838425bb815Sopenharmony_ci ret_value = ecma_number_parse_float (string_buff, 839425bb815Sopenharmony_ci string_buff_size); 840425bb815Sopenharmony_ci } 841425bb815Sopenharmony_ci 842425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); 843425bb815Sopenharmony_ci ecma_deref_ecma_string (str_p); 844425bb815Sopenharmony_ci return ret_value; 845425bb815Sopenharmony_ci } 846425bb815Sopenharmony_ci 847425bb815Sopenharmony_ci lit_utf8_size_t input_size = ecma_string_get_size (str_p); 848425bb815Sopenharmony_ci 849425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (input_start_p, 850425bb815Sopenharmony_ci input_size + 1, 851425bb815Sopenharmony_ci lit_utf8_byte_t); 852425bb815Sopenharmony_ci 853425bb815Sopenharmony_ci ecma_string_to_utf8_bytes (str_p, input_start_p, input_size); 854425bb815Sopenharmony_ci 855425bb815Sopenharmony_ci input_start_p[input_size] = LIT_BYTE_NULL; 856425bb815Sopenharmony_ci 857425bb815Sopenharmony_ci switch (builtin_routine_id) 858425bb815Sopenharmony_ci { 859425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_ANNEXB) 860425bb815Sopenharmony_ci case ECMA_GLOBAL_ESCAPE: 861425bb815Sopenharmony_ci { 862425bb815Sopenharmony_ci ret_value = ecma_builtin_global_object_escape (input_start_p, input_size); 863425bb815Sopenharmony_ci break; 864425bb815Sopenharmony_ci } 865425bb815Sopenharmony_ci case ECMA_GLOBAL_UNESCAPE: 866425bb815Sopenharmony_ci { 867425bb815Sopenharmony_ci ret_value = ecma_builtin_global_object_unescape (input_start_p, input_size); 868425bb815Sopenharmony_ci break; 869425bb815Sopenharmony_ci } 870425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ 871425bb815Sopenharmony_ci case ECMA_GLOBAL_DECODE_URI: 872425bb815Sopenharmony_ci case ECMA_GLOBAL_DECODE_URI_COMPONENT: 873425bb815Sopenharmony_ci { 874425bb815Sopenharmony_ci const uint8_t *uri_set = (builtin_routine_id == ECMA_GLOBAL_DECODE_URI ? unescaped_uri_set 875425bb815Sopenharmony_ci : unescaped_uri_component_set); 876425bb815Sopenharmony_ci 877425bb815Sopenharmony_ci ret_value = ecma_builtin_global_object_decode_uri_helper (input_start_p, input_size, uri_set); 878425bb815Sopenharmony_ci break; 879425bb815Sopenharmony_ci } 880425bb815Sopenharmony_ci default: 881425bb815Sopenharmony_ci { 882425bb815Sopenharmony_ci JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI 883425bb815Sopenharmony_ci || builtin_routine_id == ECMA_GLOBAL_ENCODE_URI_COMPONENT); 884425bb815Sopenharmony_ci 885425bb815Sopenharmony_ci const uint8_t *uri_set = (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI ? unescaped_uri_set 886425bb815Sopenharmony_ci : unescaped_uri_component_set); 887425bb815Sopenharmony_ci 888425bb815Sopenharmony_ci ret_value = ecma_builtin_global_object_encode_uri_helper (input_start_p, input_size, uri_set); 889425bb815Sopenharmony_ci break; 890425bb815Sopenharmony_ci } 891425bb815Sopenharmony_ci } 892425bb815Sopenharmony_ci 893425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (input_start_p); 894425bb815Sopenharmony_ci 895425bb815Sopenharmony_ci ecma_deref_ecma_string (str_p); 896425bb815Sopenharmony_ci return ret_value; 897425bb815Sopenharmony_ci} /* ecma_builtin_global_dispatch_routine */ 898425bb815Sopenharmony_ci 899425bb815Sopenharmony_ci/** 900425bb815Sopenharmony_ci * @} 901425bb815Sopenharmony_ci * @} 902425bb815Sopenharmony_ci * @} 903425bb815Sopenharmony_ci */ 904