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