• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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