1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecma-alloc.h" 17#include "ecma-builtins.h" 18#include "ecma-conversion.h" 19#include "ecma-eval.h" 20#include "ecma-exceptions.h" 21#include "ecma-gc.h" 22#include "ecma-globals.h" 23#include "ecma-helpers.h" 24#include "ecma-try-catch-macro.h" 25#include "jrt.h" 26#include "lit-char-helpers.h" 27#include "lit-magic-strings.h" 28#include "lit-strings.h" 29#include "vm.h" 30#include "jcontext.h" 31#include "jrt-libc-includes.h" 32#include "jrt-bit-fields.h" 33 34#define ECMA_BUILTINS_INTERNAL 35#include "ecma-builtins-internal.h" 36 37/** 38 * This object has a custom dispatch function. 39 */ 40#define BUILTIN_CUSTOM_DISPATCH 41 42/** 43 * List of built-in routine identifiers. 44 */ 45enum 46{ 47 ECMA_GLOBAL_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, 48 /* Note: these 5 routine ids must be in this order */ 49 ECMA_GLOBAL_IS_NAN, 50 ECMA_GLOBAL_IS_FINITE, 51 ECMA_GLOBAL_EVAL, 52 ECMA_GLOBAL_PARSE_INT, 53 ECMA_GLOBAL_PARSE_FLOAT, 54 ECMA_GLOBAL_DECODE_URI, 55 ECMA_GLOBAL_DECODE_URI_COMPONENT, 56 ECMA_GLOBAL_ENCODE_URI, 57 ECMA_GLOBAL_ENCODE_URI_COMPONENT, 58 ECMA_GLOBAL_ESCAPE, 59 ECMA_GLOBAL_UNESCAPE, 60}; 61 62#define BUILTIN_INC_HEADER_NAME "ecma-builtin-global.inc.h" 63#define BUILTIN_UNDERSCORED_ID global 64#include "ecma-builtin-internal-routines-template.inc.h" 65 66/** \addtogroup ecma ECMA 67 * @{ 68 * 69 * \addtogroup ecmabuiltins 70 * @{ 71 * 72 * \addtogroup global ECMA Global object built-in 73 * @{ 74 */ 75 76/** 77 * The Global object's 'eval' routine 78 * 79 * See also: 80 * ECMA-262 v5, 15.1.2.1 81 * 82 * @return ecma value 83 * Returned value must be freed with ecma_free_value. 84 */ 85static ecma_value_t 86ecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument */ 87{ 88 if (JERRY_UNLIKELY (!ecma_is_value_string (x))) 89 { 90 /* step 1 */ 91 return ecma_copy_value (x); 92 } 93 94 uint32_t parse_opts = vm_is_direct_eval_form_call () ? ECMA_PARSE_DIRECT_EVAL : ECMA_PARSE_NO_OPTS; 95 96 /* See also: ECMA-262 v5, 10.1.1 */ 97 if (parse_opts && vm_is_strict_mode ()) 98 { 99 JERRY_ASSERT (parse_opts & ECMA_PARSE_DIRECT_EVAL); 100 parse_opts |= ECMA_PARSE_STRICT_MODE; 101 } 102 103#if ENABLED (JERRY_ES2015) 104 if (vm_is_direct_eval_form_call ()) 105 { 106 parse_opts |= ECMA_GET_LOCAL_PARSE_OPTS (); 107 } 108#endif /* ENABLED (JERRY_ES2015) */ 109 110 /* steps 2 to 8 */ 111 return ecma_op_eval (ecma_get_string_from_value (x), parse_opts); 112} /* ecma_builtin_global_object_eval */ 113 114/** 115 * The Global object's 'isNaN' routine 116 * 117 * See also: 118 * ECMA-262 v5, 15.1.2.4 119 * 120 * @return ecma value 121 * Returned value must be freed with ecma_free_value. 122 */ 123static ecma_value_t 124ecma_builtin_global_object_is_nan (ecma_number_t arg_num) /**< routine's first argument */ 125{ 126 return ecma_make_boolean_value (ecma_number_is_nan (arg_num)); 127} /* ecma_builtin_global_object_is_nan */ 128 129/** 130 * The Global object's 'isFinite' routine 131 * 132 * See also: 133 * ECMA-262 v5, 15.1.2.5 134 * 135 * @return ecma value 136 * Returned value must be freed with ecma_free_value. 137 */ 138static ecma_value_t 139ecma_builtin_global_object_is_finite (ecma_number_t arg_num) /**< routine's first argument */ 140{ 141 bool is_finite = !(ecma_number_is_nan (arg_num) 142 || ecma_number_is_infinity (arg_num)); 143 144 return ecma_make_boolean_value (is_finite); 145} /* ecma_builtin_global_object_is_finite */ 146 147/** 148 * Helper function to check whether a character is in a character bitset. 149 * 150 * @return true if the character is in the character bitset. 151 */ 152static bool 153ecma_builtin_global_object_character_is_in (uint32_t character, /**< character */ 154 const uint8_t *bitset) /**< character set */ 155{ 156 JERRY_ASSERT (character < 128); 157 return (bitset[character >> 3] & (1u << (character & 0x7))) != 0; 158} /* ecma_builtin_global_object_character_is_in */ 159 160/** 161 * Unescaped URI characters bitset: 162 * One bit for each character between 0 - 127. 163 * Bit is set if the character is in the unescaped URI set. 164 */ 165static const uint8_t unescaped_uri_set[16] = 166{ 167 0x0, 0x0, 0x0, 0x0, 0xda, 0xff, 0xff, 0xaf, 168 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 169}; 170 171/** 172 * Unescaped URI component characters bitset: 173 * One bit for each character between 0 - 127. 174 * Bit is set if the character is in the unescaped component URI set. 175 */ 176static const uint8_t unescaped_uri_component_set[16] = 177{ 178 0x0, 0x0, 0x0, 0x0, 0x82, 0x67, 0xff, 0x3, 179 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47 180}; 181 182/** 183 * Format is a percent sign followed by two hex digits. 184 */ 185#define URI_ENCODED_BYTE_SIZE (3) 186 187/** 188 * The Global object's 'decodeURI' and 'decodeURIComponent' routines 189 * 190 * See also: 191 * ECMA-262 v5, 15.1.3.1 192 * ECMA-262 v5, 15.1.3.2 193 * 194 * @return ecma value 195 * Returned value must be freed with ecma_free_value. 196 */ 197static ecma_value_t 198ecma_builtin_global_object_decode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 199 * string buffer */ 200 lit_utf8_size_t input_size, /**< routine's first argument's 201 * string buffer's size */ 202 const uint8_t *reserved_uri_bitset) /**< reserved characters bitset */ 203{ 204 lit_utf8_byte_t *input_char_p = input_start_p; 205 lit_utf8_byte_t *input_end_p = input_start_p + input_size; 206 lit_utf8_size_t output_size = 0; 207 /* 208 * The URI decoding has two major phases: first we validate the input, 209 * and compute the length of the output, then we decode the input. 210 */ 211 212 while (input_char_p < input_end_p) 213 { 214 /* 215 * We expect that the input is a valid UTF-8 sequence, 216 * so characters >= 0x80 can be let through. 217 */ 218 219 if (*input_char_p != '%') 220 { 221 output_size++; 222 input_char_p++; 223 continue; 224 } 225 226 uint32_t hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); 227 if (hex_value == UINT32_MAX) 228 { 229 return ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid hexadecimal value.")); 230 } 231 232 ecma_char_t decoded_byte = (ecma_char_t) hex_value; 233 input_char_p += URI_ENCODED_BYTE_SIZE; 234 235 if (decoded_byte <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 236 { 237 /* 238 * We don't decode those bytes, which are part of reserved_uri_bitset 239 * but not part of unescaped_uri_component_set. 240 */ 241 if (ecma_builtin_global_object_character_is_in (decoded_byte, reserved_uri_bitset) 242 && !ecma_builtin_global_object_character_is_in (decoded_byte, unescaped_uri_component_set)) 243 { 244 output_size += URI_ENCODED_BYTE_SIZE; 245 } 246 else 247 { 248 output_size++; 249 } 250 } 251 else if ((decoded_byte & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) 252 { 253 output_size += 3; 254 } 255 else 256 { 257 output_size++; 258 } 259 } 260 261 ecma_value_t ret_value = ECMA_VALUE_EMPTY; 262 263 JMEM_DEFINE_LOCAL_ARRAY (output_start_p, 264 output_size, 265 lit_utf8_byte_t); 266 267 input_char_p = input_start_p; 268 lit_utf8_byte_t *output_char_p = output_start_p; 269 270 while (input_char_p < input_end_p) 271 { 272 /* Input decode. */ 273 if (*input_char_p != '%') 274 { 275 *output_char_p++ = *input_char_p++; 276 continue; 277 } 278 279 uint32_t hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); 280 if (hex_value == UINT32_MAX) 281 { 282 ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid hexadecimal value.")); 283 break; 284 } 285 286 ecma_char_t decoded_byte = (ecma_char_t) hex_value; 287 input_char_p += URI_ENCODED_BYTE_SIZE; 288 289 if (decoded_byte <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 290 { 291 if (ecma_builtin_global_object_character_is_in (decoded_byte, reserved_uri_bitset) 292 && !ecma_builtin_global_object_character_is_in (decoded_byte, unescaped_uri_component_set)) 293 { 294 *output_char_p = '%'; 295 output_char_p++; 296 input_char_p -= 2; 297 } 298 else 299 { 300 *output_char_p++ = (lit_utf8_byte_t) decoded_byte; 301 } 302 } 303 else 304 { 305 uint32_t bytes_count; 306 307 if ((decoded_byte & LIT_UTF8_2_BYTE_MASK) == LIT_UTF8_2_BYTE_MARKER) 308 { 309 bytes_count = 2; 310 } 311 else if ((decoded_byte & LIT_UTF8_3_BYTE_MASK) == LIT_UTF8_3_BYTE_MARKER) 312 { 313 bytes_count = 3; 314 } 315 else if ((decoded_byte & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) 316 { 317 bytes_count = 4; 318 } 319 else 320 { 321 ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 character.")); 322 break; 323 } 324 325 lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; 326 octets[0] = (lit_utf8_byte_t) decoded_byte; 327 bool is_valid = true; 328 329 for (uint32_t i = 1; i < bytes_count; i++) 330 { 331 if (input_char_p >= input_end_p || *input_char_p != '%') 332 { 333 is_valid = false; 334 break; 335 } 336 else 337 { 338 hex_value = lit_char_hex_lookup (input_char_p + 1, input_end_p, 2); 339 340 if (hex_value == UINT32_MAX || (hex_value & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) 341 { 342 is_valid = false; 343 break; 344 } 345 346 input_char_p += URI_ENCODED_BYTE_SIZE; 347 octets[i] = (lit_utf8_byte_t) hex_value; 348 } 349 } 350 351 if (!is_valid 352 || !lit_is_valid_utf8_string (octets, bytes_count)) 353 { 354 ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 string.")); 355 break; 356 } 357 358 lit_code_point_t cp; 359 lit_read_code_point_from_utf8 (octets, bytes_count, &cp); 360 361 if (lit_is_code_point_utf16_high_surrogate (cp) 362 || lit_is_code_point_utf16_low_surrogate (cp)) 363 { 364 ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 codepoint.")); 365 break; 366 } 367 368 output_char_p += lit_code_point_to_cesu8 (cp, output_char_p); 369 } 370 } 371 372 if (ecma_is_value_empty (ret_value)) 373 { 374 JERRY_ASSERT (output_start_p + output_size == output_char_p); 375 376 if (lit_is_valid_cesu8_string (output_start_p, output_size)) 377 { 378 ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_size); 379 ret_value = ecma_make_string_value (output_string_p); 380 } 381 else 382 { 383 ret_value = ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid CESU8 string.")); 384 } 385 } 386 387 JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); 388 389 return ret_value; 390} /* ecma_builtin_global_object_decode_uri_helper */ 391 392/** 393 * Helper function to encode byte as hexadecimal values. 394 */ 395static void 396ecma_builtin_global_object_byte_to_hex (lit_utf8_byte_t *dest_p, /**< destination pointer */ 397 uint32_t byte) /**< value */ 398{ 399 JERRY_ASSERT (byte < 256); 400 401 dest_p[0] = LIT_CHAR_PERCENT; 402 ecma_char_t hex_digit = (ecma_char_t) (byte >> 4); 403 dest_p[1] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); 404 hex_digit = (lit_utf8_byte_t) (byte & 0xf); 405 dest_p[2] = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); 406} /* ecma_builtin_global_object_byte_to_hex */ 407 408/** 409 * The Global object's 'encodeURI' and 'encodeURIComponent' routines 410 * 411 * See also: 412 * ECMA-262 v5, 15.1.3.3 413 * ECMA-262 v5, 15.1.3.4 414 * 415 * @return ecma value 416 * Returned value must be freed with ecma_free_value. 417 */ 418static ecma_value_t 419ecma_builtin_global_object_encode_uri_helper (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 420 * string buffer */ 421 lit_utf8_size_t input_size, /**< routine's first argument's 422 * string buffer's size */ 423 const uint8_t *unescaped_uri_bitset_p) /**< unescaped bitset */ 424{ 425 /* 426 * The URI encoding has two major phases: first we validate the input, 427 * and compute the length of the output, then we encode the input. 428 */ 429 430 lit_utf8_byte_t *input_char_p = input_start_p; 431 const lit_utf8_byte_t *input_end_p = input_start_p + input_size; 432 lit_utf8_size_t output_length = 0; 433 lit_code_point_t cp; 434 ecma_char_t ch; 435 lit_utf8_byte_t octets[LIT_UTF8_MAX_BYTES_IN_CODE_POINT]; 436 memset (octets, LIT_BYTE_NULL, LIT_UTF8_MAX_BYTES_IN_CODE_POINT); 437 438 while (input_char_p < input_end_p) 439 { 440 /* Input validation, we need to reject stray surrogates. */ 441 input_char_p += lit_read_code_unit_from_utf8 (input_char_p, &ch); 442 443 if (lit_is_code_point_utf16_low_surrogate (ch)) 444 { 445 return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); 446 } 447 448 cp = ch; 449 450 if (lit_is_code_point_utf16_high_surrogate (ch)) 451 { 452 if (input_char_p == input_end_p) 453 { 454 return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); 455 } 456 457 ecma_char_t next_ch; 458 lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (input_char_p, &next_ch); 459 460 if (lit_is_code_point_utf16_low_surrogate (next_ch)) 461 { 462 cp = lit_convert_surrogate_pair_to_code_point (ch, next_ch); 463 input_char_p += read_size; 464 } 465 else 466 { 467 return ecma_raise_uri_error (ECMA_ERR_MSG ("Unicode surrogate pair missing.")); 468 } 469 } 470 471 lit_utf8_size_t utf_size = lit_code_point_to_utf8 (cp, octets); 472 473 if (utf_size == 1) 474 { 475 if (ecma_builtin_global_object_character_is_in (octets[0], unescaped_uri_bitset_p)) 476 { 477 output_length++; 478 } 479 else 480 { 481 output_length += URI_ENCODED_BYTE_SIZE; 482 } 483 } 484 else 485 { 486 output_length += utf_size * URI_ENCODED_BYTE_SIZE; 487 } 488 } 489 490 ecma_value_t ret_value; 491 492 JMEM_DEFINE_LOCAL_ARRAY (output_start_p, 493 output_length, 494 lit_utf8_byte_t); 495 496 lit_utf8_byte_t *output_char_p = output_start_p; 497 input_char_p = input_start_p; 498 499 while (input_char_p < input_end_p) 500 { 501 /* Input decode. */ 502 input_char_p += lit_read_code_unit_from_utf8 (input_char_p, &ch); 503 cp = ch; 504 505 if (lit_is_code_point_utf16_high_surrogate (ch)) 506 { 507 ecma_char_t next_ch; 508 lit_utf8_size_t read_size = lit_read_code_unit_from_utf8 (input_char_p, &next_ch); 509 510 if (lit_is_code_point_utf16_low_surrogate (next_ch)) 511 { 512 cp = lit_convert_surrogate_pair_to_code_point (ch, next_ch); 513 input_char_p += read_size; 514 } 515 } 516 517 lit_utf8_size_t utf_size = lit_code_point_to_utf8 (cp, octets); 518 519 if (utf_size == 1) 520 { 521 if (ecma_builtin_global_object_character_is_in (octets[0], unescaped_uri_bitset_p)) 522 { 523 *output_char_p++ = octets[0]; 524 } 525 else 526 { 527 ecma_builtin_global_object_byte_to_hex (output_char_p, octets[0]); 528 output_char_p += URI_ENCODED_BYTE_SIZE; 529 } 530 } 531 else 532 { 533 for (uint32_t i = 0; i < utf_size; i++) 534 { 535 ecma_builtin_global_object_byte_to_hex (output_char_p, octets[i]); 536 output_char_p += URI_ENCODED_BYTE_SIZE; 537 } 538 } 539 } 540 541 JERRY_ASSERT (output_start_p + output_length == output_char_p); 542 543 ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_length); 544 545 ret_value = ecma_make_string_value (output_string_p); 546 547 JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); 548 549 return ret_value; 550} /* ecma_builtin_global_object_encode_uri_helper */ 551 552#if ENABLED (JERRY_BUILTIN_ANNEXB) 553 554/** 555 * Maximum value of a byte. 556 */ 557#define ECMA_ESCAPE_MAXIMUM_BYTE_VALUE (255) 558 559/** 560 * Format is a percent sign followed by lowercase u and four hex digits. 561 */ 562#define ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE (6) 563 564/** 565 * Escape characters bitset: 566 * One bit for each character between 0 - 127. 567 * Bit is set if the character does not need to be converted to %xx form. 568 * These characters are: a-z A-Z 0-9 @ * _ + - . / 569 */ 570static const uint8_t ecma_escape_set[16] = 571{ 572 0x0, 0x0, 0x0, 0x0, 0x0, 0xec, 0xff, 0x3, 573 0xff, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x7 574}; 575 576/** 577 * The Global object's 'escape' routine 578 * 579 * See also: 580 * ECMA-262 v5, B.2.1 581 * 582 * @return ecma value 583 * Returned value must be freed with ecma_free_value. 584 */ 585static ecma_value_t 586ecma_builtin_global_object_escape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 587 * string buffer */ 588 lit_utf8_size_t input_size) /**< routine's first argument's 589 * string buffer's size */ 590{ 591 /* 592 * The escape routine has two major phases: first we compute 593 * the length of the output, then we encode the input. 594 */ 595 const lit_utf8_byte_t *input_curr_p = input_start_p; 596 const lit_utf8_byte_t *input_end_p = input_start_p + input_size; 597 lit_utf8_size_t output_length = 0; 598 599 while (input_curr_p < input_end_p) 600 { 601 ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); 602 603 if (chr <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 604 { 605 if (ecma_builtin_global_object_character_is_in ((uint32_t) chr, ecma_escape_set)) 606 { 607 output_length++; 608 } 609 else 610 { 611 output_length += URI_ENCODED_BYTE_SIZE; 612 } 613 } 614 else if (chr > ECMA_ESCAPE_MAXIMUM_BYTE_VALUE) 615 { 616 output_length += ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE; 617 } 618 else 619 { 620 output_length += URI_ENCODED_BYTE_SIZE; 621 } 622 } 623 624 ecma_value_t ret_value; 625 626 JMEM_DEFINE_LOCAL_ARRAY (output_start_p, 627 output_length, 628 lit_utf8_byte_t); 629 630 lit_utf8_byte_t *output_char_p = output_start_p; 631 632 input_curr_p = input_start_p; 633 634 while (input_curr_p < input_end_p) 635 { 636 ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); 637 638 if (chr <= LIT_UTF8_1_BYTE_CODE_POINT_MAX) 639 { 640 if (ecma_builtin_global_object_character_is_in ((uint32_t) chr, ecma_escape_set)) 641 { 642 *output_char_p = (lit_utf8_byte_t) chr; 643 output_char_p++; 644 } 645 else 646 { 647 ecma_builtin_global_object_byte_to_hex (output_char_p, (lit_utf8_byte_t) chr); 648 output_char_p += URI_ENCODED_BYTE_SIZE; 649 } 650 } 651 else if (chr > ECMA_ESCAPE_MAXIMUM_BYTE_VALUE) 652 { 653 /* 654 * Although ecma_builtin_global_object_byte_to_hex inserts a percent (%) sign 655 * the follow-up changes overwrites it. We call this function twice to 656 * produce four hexadecimal characters (%uxxxx format). 657 */ 658 ecma_builtin_global_object_byte_to_hex (output_char_p + 3, (lit_utf8_byte_t) (chr & 0xff)); 659 ecma_builtin_global_object_byte_to_hex (output_char_p + 1, (lit_utf8_byte_t) (chr >> JERRY_BITSINBYTE)); 660 output_char_p[0] = LIT_CHAR_PERCENT; 661 output_char_p[1] = LIT_CHAR_LOWERCASE_U; 662 output_char_p += ECMA_ESCAPE_ENCODED_UNICODE_CHARACTER_SIZE; 663 } 664 else 665 { 666 ecma_builtin_global_object_byte_to_hex (output_char_p, (lit_utf8_byte_t) chr); 667 output_char_p += URI_ENCODED_BYTE_SIZE; 668 } 669 } 670 671 JERRY_ASSERT (output_start_p + output_length == output_char_p); 672 673 ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (output_start_p, output_length); 674 675 ret_value = ecma_make_string_value (output_string_p); 676 677 JMEM_FINALIZE_LOCAL_ARRAY (output_start_p); 678 679 return ret_value; 680} /* ecma_builtin_global_object_escape */ 681 682/** 683 * The Global object's 'unescape' routine 684 * 685 * See also: 686 * ECMA-262 v5, B.2.2 687 * 688 * @return ecma value 689 * Returned value must be freed with ecma_free_value. 690 */ 691static ecma_value_t 692ecma_builtin_global_object_unescape (lit_utf8_byte_t *input_start_p, /**< routine's first argument's 693 * string buffer */ 694 lit_utf8_size_t input_size) /**< routine's first argument's 695 * string buffer's size */ 696{ 697 const lit_utf8_byte_t *input_curr_p = input_start_p; 698 const lit_utf8_byte_t *input_end_p = input_start_p + input_size; 699 /* 4. */ 700 /* The length of input string is always greater than output string 701 * so we re-use the input string buffer. 702 * The %xx is three byte long, and the maximum encoded value is 0xff, 703 * which maximum encoded length is two byte. Similar to this, the maximum 704 * encoded length of %uxxxx is four byte. */ 705 lit_utf8_byte_t *output_char_p = input_start_p; 706 707 /* The state of parsing that tells us where we are in an escape pattern. 708 * 0 we are outside of pattern, 709 * 1 found '%', start of pattern, 710 * 2 found first hex digit of '%xy' pattern 711 * 3 found valid '%xy' pattern 712 * 4 found 'u', start of '%uwxyz' pattern 713 * 5-7 found hex digits of '%uwxyz' pattern 714 * 8 found valid '%uwxyz' pattern 715 */ 716 uint8_t status = 0; 717 ecma_char_t hex_digits = 0; 718 /* 5. */ 719 while (input_curr_p < input_end_p) 720 { 721 /* 6. */ 722 ecma_char_t chr = lit_cesu8_read_next (&input_curr_p); 723 724 /* 7-8. */ 725 if (status == 0 && chr == LIT_CHAR_PERCENT) 726 { 727 /* Found '%' char, start of escape sequence. */ 728 status = 1; 729 } 730 /* 9-10. */ 731 else if (status == 1 && chr == LIT_CHAR_LOWERCASE_U) 732 { 733 /* Found 'u' char after '%'. */ 734 status = 4; 735 } 736 else if (status > 0 && lit_char_is_hex_digit (chr)) 737 { 738 /* Found hexadecimal digit in escape sequence. */ 739 hex_digits = (ecma_char_t) (hex_digits * 16 + (ecma_char_t) lit_char_hex_to_int (chr)); 740 status++; 741 } 742 else 743 { 744 /* Previously found hexadecimal digit in escape sequence but it's not valid '%xy' pattern 745 * so essentially it was only a simple character. */ 746 status = 0; 747 } 748 749 /* 11-17. Found valid '%uwxyz' or '%xy' escape. */ 750 if (status == 8 || status == 3) 751 { 752 output_char_p -= (status == 3) ? 2 : 5; 753 status = 0; 754 chr = hex_digits; 755 hex_digits = 0; 756 } 757 758 /* Copying character. */ 759 lit_utf8_size_t lit_size = lit_code_unit_to_utf8 (chr, output_char_p); 760 output_char_p += lit_size; 761 JERRY_ASSERT (output_char_p <= input_curr_p); 762 } 763 764 lit_utf8_size_t output_length = (lit_utf8_size_t) (output_char_p - input_start_p); 765 ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (input_start_p, output_length); 766 return ecma_make_string_value (output_string_p); 767} /* ecma_builtin_global_object_unescape */ 768 769#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ 770 771/** 772 * Dispatcher of the built-in's routines 773 * 774 * @return ecma value 775 * Returned value must be freed with ecma_free_value. 776 */ 777ecma_value_t 778ecma_builtin_global_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine identifier */ 779 ecma_value_t this_arg, /**< 'this' argument value */ 780 const ecma_value_t arguments_list_p[], /**< list of arguments 781 * passed to routine */ 782 ecma_length_t arguments_number) /**< length of arguments' list */ 783{ 784 JERRY_UNUSED (this_arg); 785 JERRY_UNUSED (arguments_list_p); 786 JERRY_UNUSED (arguments_number); 787 788 ecma_value_t routine_arg_1 = arguments_list_p[0]; 789 790 if (builtin_routine_id == ECMA_GLOBAL_EVAL) 791 { 792 return ecma_builtin_global_object_eval (routine_arg_1); 793 } 794 795 if (builtin_routine_id <= ECMA_GLOBAL_IS_FINITE) 796 { 797 ecma_number_t arg_num; 798 799 routine_arg_1 = ecma_get_number (routine_arg_1, &arg_num); 800 801 if (!ecma_is_value_empty (routine_arg_1)) 802 { 803 return routine_arg_1; 804 } 805 806 if (builtin_routine_id == ECMA_GLOBAL_IS_NAN) 807 { 808 return ecma_builtin_global_object_is_nan (arg_num); 809 } 810 811 JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_IS_FINITE); 812 813 return ecma_builtin_global_object_is_finite (arg_num); 814 } 815 816 ecma_string_t *str_p = ecma_op_to_string (routine_arg_1); 817 818 if (JERRY_UNLIKELY (str_p == NULL)) 819 { 820 return ECMA_VALUE_ERROR; 821 } 822 823 ecma_value_t ret_value; 824 825 if (builtin_routine_id <= ECMA_GLOBAL_PARSE_FLOAT) 826 { 827 ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); 828 829 if (builtin_routine_id == ECMA_GLOBAL_PARSE_INT) 830 { 831 ret_value = ecma_number_parse_int (string_buff, 832 string_buff_size, 833 arguments_list_p[1]); 834 } 835 else 836 { 837 JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_PARSE_FLOAT); 838 ret_value = ecma_number_parse_float (string_buff, 839 string_buff_size); 840 } 841 842 ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); 843 ecma_deref_ecma_string (str_p); 844 return ret_value; 845 } 846 847 lit_utf8_size_t input_size = ecma_string_get_size (str_p); 848 849 JMEM_DEFINE_LOCAL_ARRAY (input_start_p, 850 input_size + 1, 851 lit_utf8_byte_t); 852 853 ecma_string_to_utf8_bytes (str_p, input_start_p, input_size); 854 855 input_start_p[input_size] = LIT_BYTE_NULL; 856 857 switch (builtin_routine_id) 858 { 859#if ENABLED (JERRY_BUILTIN_ANNEXB) 860 case ECMA_GLOBAL_ESCAPE: 861 { 862 ret_value = ecma_builtin_global_object_escape (input_start_p, input_size); 863 break; 864 } 865 case ECMA_GLOBAL_UNESCAPE: 866 { 867 ret_value = ecma_builtin_global_object_unescape (input_start_p, input_size); 868 break; 869 } 870#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ 871 case ECMA_GLOBAL_DECODE_URI: 872 case ECMA_GLOBAL_DECODE_URI_COMPONENT: 873 { 874 const uint8_t *uri_set = (builtin_routine_id == ECMA_GLOBAL_DECODE_URI ? unescaped_uri_set 875 : unescaped_uri_component_set); 876 877 ret_value = ecma_builtin_global_object_decode_uri_helper (input_start_p, input_size, uri_set); 878 break; 879 } 880 default: 881 { 882 JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI 883 || builtin_routine_id == ECMA_GLOBAL_ENCODE_URI_COMPONENT); 884 885 const uint8_t *uri_set = (builtin_routine_id == ECMA_GLOBAL_ENCODE_URI ? unescaped_uri_set 886 : unescaped_uri_component_set); 887 888 ret_value = ecma_builtin_global_object_encode_uri_helper (input_start_p, input_size, uri_set); 889 break; 890 } 891 } 892 893 JMEM_FINALIZE_LOCAL_ARRAY (input_start_p); 894 895 ecma_deref_ecma_string (str_p); 896 return ret_value; 897} /* ecma_builtin_global_dispatch_routine */ 898 899/** 900 * @} 901 * @} 902 * @} 903 */ 904