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