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 */
45 enum
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 */
85 static ecma_value_t
ecma_builtin_global_object_eval(ecma_value_t x)86 ecma_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 */
123 static ecma_value_t
ecma_builtin_global_object_is_nan(ecma_number_t arg_num)124 ecma_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 */
138 static ecma_value_t
ecma_builtin_global_object_is_finite(ecma_number_t arg_num)139 ecma_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 */
152 static bool
ecma_builtin_global_object_character_is_in(uint32_t character,const uint8_t * bitset)153 ecma_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 */
165 static 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 */
176 static 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 */
197 static ecma_value_t
ecma_builtin_global_object_decode_uri_helper(lit_utf8_byte_t * input_start_p,lit_utf8_size_t input_size,const uint8_t * reserved_uri_bitset)198 ecma_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 */
395 static void
ecma_builtin_global_object_byte_to_hex(lit_utf8_byte_t * dest_p,uint32_t byte)396 ecma_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 */
418 static ecma_value_t
ecma_builtin_global_object_encode_uri_helper(lit_utf8_byte_t * input_start_p,lit_utf8_size_t input_size,const uint8_t * unescaped_uri_bitset_p)419 ecma_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 */
570 static 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 */
585 static ecma_value_t
ecma_builtin_global_object_escape(lit_utf8_byte_t * input_start_p,lit_utf8_size_t input_size)586 ecma_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 */
691 static ecma_value_t
ecma_builtin_global_object_unescape(lit_utf8_byte_t * input_start_p,lit_utf8_size_t input_size)692 ecma_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 */
777 ecma_value_t
ecma_builtin_global_dispatch_routine(uint16_t builtin_routine_id,ecma_value_t this_arg,const ecma_value_t arguments_list_p[],ecma_length_t arguments_number)778 ecma_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