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-array-object.h"
18425bb815Sopenharmony_ci#include "ecma-builtins.h"
19425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h"
20425bb815Sopenharmony_ci#include "ecma-exceptions.h"
21425bb815Sopenharmony_ci#include "ecma-gc.h"
22425bb815Sopenharmony_ci#include "ecma-globals.h"
23425bb815Sopenharmony_ci#include "ecma-objects.h"
24425bb815Sopenharmony_ci#include "ecma-function-object.h"
25425bb815Sopenharmony_ci#include "ecma-regexp-object.h"
26425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h"
27425bb815Sopenharmony_ci#include "jcontext.h"
28425bb815Sopenharmony_ci#include "jrt-libc-includes.h"
29425bb815Sopenharmony_ci#include "lit-char-helpers.h"
30425bb815Sopenharmony_ci#include "re-compiler.h"
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_REGEXP)
33425bb815Sopenharmony_ci
34425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL
35425bb815Sopenharmony_ci#include "ecma-builtins-internal.h"
36425bb815Sopenharmony_ci
37425bb815Sopenharmony_ci/** \addtogroup ecma ECMA
38425bb815Sopenharmony_ci * @{
39425bb815Sopenharmony_ci *
40425bb815Sopenharmony_ci * \addtogroup ecmaregexpobject ECMA RegExp object related routines
41425bb815Sopenharmony_ci * @{
42425bb815Sopenharmony_ci */
43425bb815Sopenharmony_ci
44425bb815Sopenharmony_ci/**
45425bb815Sopenharmony_ci * Index of the global capturing group
46425bb815Sopenharmony_ci */
47425bb815Sopenharmony_ci#define RE_GLOBAL_CAPTURE 0
48425bb815Sopenharmony_ci
49425bb815Sopenharmony_ci/**
50425bb815Sopenharmony_ci * Parse RegExp flags (global, ignoreCase, multiline)
51425bb815Sopenharmony_ci *
52425bb815Sopenharmony_ci * See also: ECMA-262 v5, 15.10.4.1
53425bb815Sopenharmony_ci *
54425bb815Sopenharmony_ci * @return empty ecma value - if parsed successfully
55425bb815Sopenharmony_ci *         error ecma value - otherwise
56425bb815Sopenharmony_ci *
57425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value
58425bb815Sopenharmony_ci */
59425bb815Sopenharmony_ciecma_value_t
60425bb815Sopenharmony_ciecma_regexp_parse_flags (ecma_string_t *flags_str_p, /**< Input string with flags */
61425bb815Sopenharmony_ci                         uint16_t *flags_p) /**< [out] parsed flag bits */
62425bb815Sopenharmony_ci{
63425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
64425bb815Sopenharmony_ci  uint16_t result_flags = RE_FLAG_EMPTY;
65425bb815Sopenharmony_ci
66425bb815Sopenharmony_ci  ECMA_STRING_TO_UTF8_STRING (flags_str_p, flags_start_p, flags_start_size);
67425bb815Sopenharmony_ci
68425bb815Sopenharmony_ci  const lit_utf8_byte_t *flags_str_curr_p = flags_start_p;
69425bb815Sopenharmony_ci  const lit_utf8_byte_t *flags_str_end_p = flags_start_p + flags_start_size;
70425bb815Sopenharmony_ci
71425bb815Sopenharmony_ci  while (flags_str_curr_p < flags_str_end_p)
72425bb815Sopenharmony_ci  {
73425bb815Sopenharmony_ci    ecma_regexp_flags_t flag;
74425bb815Sopenharmony_ci    switch (*flags_str_curr_p++)
75425bb815Sopenharmony_ci    {
76425bb815Sopenharmony_ci      case 'g':
77425bb815Sopenharmony_ci      {
78425bb815Sopenharmony_ci        flag = RE_FLAG_GLOBAL;
79425bb815Sopenharmony_ci        break;
80425bb815Sopenharmony_ci      }
81425bb815Sopenharmony_ci      case 'i':
82425bb815Sopenharmony_ci      {
83425bb815Sopenharmony_ci        flag = RE_FLAG_IGNORE_CASE;
84425bb815Sopenharmony_ci        break;
85425bb815Sopenharmony_ci      }
86425bb815Sopenharmony_ci      case 'm':
87425bb815Sopenharmony_ci      {
88425bb815Sopenharmony_ci        flag = RE_FLAG_MULTILINE;
89425bb815Sopenharmony_ci        break;
90425bb815Sopenharmony_ci      }
91425bb815Sopenharmony_ci      case 'y':
92425bb815Sopenharmony_ci      {
93425bb815Sopenharmony_ci        flag = RE_FLAG_STICKY;
94425bb815Sopenharmony_ci        break;
95425bb815Sopenharmony_ci      }
96425bb815Sopenharmony_ci      case 'u':
97425bb815Sopenharmony_ci      {
98425bb815Sopenharmony_ci        flag = RE_FLAG_UNICODE;
99425bb815Sopenharmony_ci        break;
100425bb815Sopenharmony_ci      }
101425bb815Sopenharmony_ci      default:
102425bb815Sopenharmony_ci      {
103425bb815Sopenharmony_ci        flag = RE_FLAG_EMPTY;
104425bb815Sopenharmony_ci        break;
105425bb815Sopenharmony_ci      }
106425bb815Sopenharmony_ci    }
107425bb815Sopenharmony_ci
108425bb815Sopenharmony_ci    if (flag == RE_FLAG_EMPTY || (result_flags & flag) != 0)
109425bb815Sopenharmony_ci    {
110425bb815Sopenharmony_ci      ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("Invalid RegExp flags."));
111425bb815Sopenharmony_ci      break;
112425bb815Sopenharmony_ci    }
113425bb815Sopenharmony_ci
114425bb815Sopenharmony_ci    result_flags = (uint16_t) (result_flags | flag);
115425bb815Sopenharmony_ci  }
116425bb815Sopenharmony_ci
117425bb815Sopenharmony_ci  ECMA_FINALIZE_UTF8_STRING (flags_start_p, flags_start_size);
118425bb815Sopenharmony_ci
119425bb815Sopenharmony_ci  *flags_p = result_flags;
120425bb815Sopenharmony_ci  return ret_value;
121425bb815Sopenharmony_ci} /* ecma_regexp_parse_flags */
122425bb815Sopenharmony_ci
123425bb815Sopenharmony_ci#if !ENABLED (JERRY_ES2015)
124425bb815Sopenharmony_ci/*
125425bb815Sopenharmony_ci * Create the properties of a RegExp instance.
126425bb815Sopenharmony_ci */
127425bb815Sopenharmony_cistatic void
128425bb815Sopenharmony_ciecma_regexp_create_props (ecma_object_t *re_object_p, /**< RegExp object */
129425bb815Sopenharmony_ci                          ecma_string_t *source_p, /**< source string */
130425bb815Sopenharmony_ci                          uint16_t flags) /**< flags */
131425bb815Sopenharmony_ci{
132425bb815Sopenharmony_ci  ecma_property_value_t *prop_value_p;
133425bb815Sopenharmony_ci
134425bb815Sopenharmony_ci  prop_value_p = ecma_create_named_data_property (re_object_p,
135425bb815Sopenharmony_ci                                                  ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE),
136425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_FIXED,
137425bb815Sopenharmony_ci                                                  NULL);
138425bb815Sopenharmony_ci
139425bb815Sopenharmony_ci  ecma_ref_ecma_string (source_p);
140425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_string_value (source_p);
141425bb815Sopenharmony_ci
142425bb815Sopenharmony_ci  prop_value_p = ecma_create_named_data_property (re_object_p,
143425bb815Sopenharmony_ci                                                  ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL),
144425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_FIXED,
145425bb815Sopenharmony_ci                                                  NULL);
146425bb815Sopenharmony_ci
147425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_GLOBAL);
148425bb815Sopenharmony_ci
149425bb815Sopenharmony_ci  prop_value_p = ecma_create_named_data_property (re_object_p,
150425bb815Sopenharmony_ci                                                  ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL),
151425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_FIXED,
152425bb815Sopenharmony_ci                                                  NULL);
153425bb815Sopenharmony_ci
154425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE);
155425bb815Sopenharmony_ci
156425bb815Sopenharmony_ci  prop_value_p = ecma_create_named_data_property (re_object_p,
157425bb815Sopenharmony_ci                                                  ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE),
158425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_FIXED,
159425bb815Sopenharmony_ci                                                  NULL);
160425bb815Sopenharmony_ci
161425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_MULTILINE);
162425bb815Sopenharmony_ci} /* ecma_regexp_create_props */
163425bb815Sopenharmony_ci
164425bb815Sopenharmony_ci/*
165425bb815Sopenharmony_ci * Update the properties of a RegExp instance.
166425bb815Sopenharmony_ci */
167425bb815Sopenharmony_cistatic void
168425bb815Sopenharmony_ciecma_regexp_update_props (ecma_object_t *re_object_p, /**< RegExp object */
169425bb815Sopenharmony_ci                          ecma_string_t *source_p, /**< source string */
170425bb815Sopenharmony_ci                          uint16_t flags) /**< flags */
171425bb815Sopenharmony_ci{
172425bb815Sopenharmony_ci  ecma_property_t *prop_p;
173425bb815Sopenharmony_ci
174425bb815Sopenharmony_ci  prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE));
175425bb815Sopenharmony_ci  JERRY_ASSERT (prop_p != NULL);
176425bb815Sopenharmony_ci  ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
177425bb815Sopenharmony_ci  ecma_free_value (prop_value_p->value);
178425bb815Sopenharmony_ci  ecma_ref_ecma_string (source_p);
179425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_string_value (source_p);
180425bb815Sopenharmony_ci
181425bb815Sopenharmony_ci  prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL));
182425bb815Sopenharmony_ci  JERRY_ASSERT (prop_p != NULL);
183425bb815Sopenharmony_ci  prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
184425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_GLOBAL);
185425bb815Sopenharmony_ci
186425bb815Sopenharmony_ci  prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL));
187425bb815Sopenharmony_ci  JERRY_ASSERT (prop_p != NULL);
188425bb815Sopenharmony_ci  prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
189425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE);
190425bb815Sopenharmony_ci
191425bb815Sopenharmony_ci  prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE));
192425bb815Sopenharmony_ci  JERRY_ASSERT (prop_p != NULL);
193425bb815Sopenharmony_ci  prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
194425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_MULTILINE);
195425bb815Sopenharmony_ci} /* ecma_regexp_update_props */
196425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015) */
197425bb815Sopenharmony_ci
198425bb815Sopenharmony_ci/**
199425bb815Sopenharmony_ci * RegExpAlloc method
200425bb815Sopenharmony_ci *
201425bb815Sopenharmony_ci * See also: ECMA-262 v5, 15.10.4.1
202425bb815Sopenharmony_ci *           ECMA-262 v6, 21.2.3.2.1
203425bb815Sopenharmony_ci *
204425bb815Sopenharmony_ci * Note:
205425bb815Sopenharmony_ci *      Returned value must be freed with ecma_free_value.
206425bb815Sopenharmony_ci *
207425bb815Sopenharmony_ci * @return ecma_object_t
208425bb815Sopenharmony_ci */
209425bb815Sopenharmony_ciecma_object_t *
210425bb815Sopenharmony_ciecma_op_regexp_alloc (ecma_object_t *ctr_obj_p) /**< constructor object pointer */
211425bb815Sopenharmony_ci{
212425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
213425bb815Sopenharmony_ci  if (ctr_obj_p == NULL)
214425bb815Sopenharmony_ci  {
215425bb815Sopenharmony_ci    ctr_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP);
216425bb815Sopenharmony_ci  }
217425bb815Sopenharmony_ci
218425bb815Sopenharmony_ci  ecma_object_t *proto_obj_p = ecma_op_get_prototype_from_constructor (ctr_obj_p,
219425bb815Sopenharmony_ci                                                                       ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
220425bb815Sopenharmony_ci
221425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (proto_obj_p == NULL))
222425bb815Sopenharmony_ci  {
223425bb815Sopenharmony_ci    return proto_obj_p;
224425bb815Sopenharmony_ci  }
225425bb815Sopenharmony_ci
226425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
227425bb815Sopenharmony_ci  JERRY_UNUSED (ctr_obj_p);
228425bb815Sopenharmony_ci  ecma_object_t *proto_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
229425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
230425bb815Sopenharmony_ci
231425bb815Sopenharmony_ci  ecma_object_t *new_object_p = ecma_create_object (proto_obj_p,
232425bb815Sopenharmony_ci                                                    sizeof (ecma_extended_object_t),
233425bb815Sopenharmony_ci                                                    ECMA_OBJECT_TYPE_CLASS);
234425bb815Sopenharmony_ci
235425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
236425bb815Sopenharmony_ci  ecma_deref_object (proto_obj_p);
237425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
238425bb815Sopenharmony_ci
239425bb815Sopenharmony_ci  ecma_extended_object_t *regexp_obj_p = (ecma_extended_object_t *) new_object_p;
240425bb815Sopenharmony_ci
241425bb815Sopenharmony_ci  /* Class id will be initialized after the bytecode is compiled. */
242425bb815Sopenharmony_ci  regexp_obj_p->u.class_prop.class_id = LIT_MAGIC_STRING_UNDEFINED;
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci  ecma_value_t status = ecma_builtin_helper_def_prop (new_object_p,
245425bb815Sopenharmony_ci                                                      ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
246425bb815Sopenharmony_ci                                                      ecma_make_uint32_value (0),
247425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROP_IS_THROW);
248425bb815Sopenharmony_ci
249425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_true (status));
250425bb815Sopenharmony_ci
251425bb815Sopenharmony_ci  return new_object_p;
252425bb815Sopenharmony_ci} /* ecma_op_regexp_alloc */
253425bb815Sopenharmony_ci
254425bb815Sopenharmony_ci/**
255425bb815Sopenharmony_ci * Helper method for initializing an aready existing RegExp object.
256425bb815Sopenharmony_ci */
257425bb815Sopenharmony_cistatic void
258425bb815Sopenharmony_ciecma_op_regexp_initialize (ecma_object_t *regexp_obj_p, /**< RegExp object */
259425bb815Sopenharmony_ci                           const re_compiled_code_t *bc_p, /**< bytecode */
260425bb815Sopenharmony_ci                           ecma_string_t *pattern_str_p, /**< pattern */
261425bb815Sopenharmony_ci                           uint16_t flags) /**< flags */
262425bb815Sopenharmony_ci{
263425bb815Sopenharmony_ci  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) regexp_obj_p;
264425bb815Sopenharmony_ci
265425bb815Sopenharmony_ci#if !ENABLED (JERRY_ES2015)
266425bb815Sopenharmony_ci  if (ext_obj_p->u.class_prop.class_id == LIT_MAGIC_STRING_UNDEFINED)
267425bb815Sopenharmony_ci  {
268425bb815Sopenharmony_ci    /* This instance has not been initialized before. */
269425bb815Sopenharmony_ci    ecma_regexp_create_props (regexp_obj_p, pattern_str_p, flags);
270425bb815Sopenharmony_ci  }
271425bb815Sopenharmony_ci  else
272425bb815Sopenharmony_ci  {
273425bb815Sopenharmony_ci    ecma_regexp_update_props (regexp_obj_p, pattern_str_p, flags);
274425bb815Sopenharmony_ci  }
275425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015) */
276425bb815Sopenharmony_ci
277425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
278425bb815Sopenharmony_ci  JERRY_UNUSED (pattern_str_p);
279425bb815Sopenharmony_ci  JERRY_UNUSED (flags);
280425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
281425bb815Sopenharmony_ci
282425bb815Sopenharmony_ci  ext_obj_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
283425bb815Sopenharmony_ci  ECMA_SET_INTERNAL_VALUE_POINTER (ext_obj_p->u.class_prop.u.value, bc_p);
284425bb815Sopenharmony_ci} /* ecma_op_regexp_initialize */
285425bb815Sopenharmony_ci
286425bb815Sopenharmony_ci/**
287425bb815Sopenharmony_ci * Method for creating a RegExp object from pattern.
288425bb815Sopenharmony_ci *
289425bb815Sopenharmony_ci * Note:
290425bb815Sopenharmony_ci *      Allocation have to happen before invoking this function using ecma_op_regexp_alloc.
291425bb815Sopenharmony_ci *
292425bb815Sopenharmony_ci * @return ecma_value_t
293425bb815Sopenharmony_ci */
294425bb815Sopenharmony_ciecma_value_t
295425bb815Sopenharmony_ciecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p, /**< RegExp object */
296425bb815Sopenharmony_ci                                    ecma_value_t pattern_value, /**< pattern */
297425bb815Sopenharmony_ci                                    ecma_value_t flags_value) /**< flags */
298425bb815Sopenharmony_ci{
299425bb815Sopenharmony_ci  ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value);
300425bb815Sopenharmony_ci  uint16_t flags = 0;
301425bb815Sopenharmony_ci
302425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (pattern_str_p == NULL))
303425bb815Sopenharmony_ci  {
304425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
305425bb815Sopenharmony_ci  }
306425bb815Sopenharmony_ci
307425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (flags_value))
308425bb815Sopenharmony_ci  {
309425bb815Sopenharmony_ci    ecma_string_t *flags_str_p = ecma_op_to_string (flags_value);
310425bb815Sopenharmony_ci
311425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (flags_str_p == NULL))
312425bb815Sopenharmony_ci    {
313425bb815Sopenharmony_ci      ecma_deref_ecma_string (pattern_str_p);
314425bb815Sopenharmony_ci      return ECMA_VALUE_ERROR;
315425bb815Sopenharmony_ci    }
316425bb815Sopenharmony_ci
317425bb815Sopenharmony_ci    ecma_value_t parse_flags_value = ecma_regexp_parse_flags (flags_str_p, &flags);
318425bb815Sopenharmony_ci    ecma_deref_ecma_string (flags_str_p);
319425bb815Sopenharmony_ci
320425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (parse_flags_value))
321425bb815Sopenharmony_ci    {
322425bb815Sopenharmony_ci      ecma_deref_ecma_string (pattern_str_p);
323425bb815Sopenharmony_ci      return parse_flags_value;
324425bb815Sopenharmony_ci    }
325425bb815Sopenharmony_ci
326425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_empty (parse_flags_value));
327425bb815Sopenharmony_ci  }
328425bb815Sopenharmony_ci
329425bb815Sopenharmony_ci  re_compiled_code_t *bc_p = re_compile_bytecode (pattern_str_p, flags);
330425bb815Sopenharmony_ci
331425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (bc_p == NULL))
332425bb815Sopenharmony_ci  {
333425bb815Sopenharmony_ci    ecma_deref_ecma_string (pattern_str_p);
334425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
335425bb815Sopenharmony_ci  }
336425bb815Sopenharmony_ci
337425bb815Sopenharmony_ci  ecma_op_regexp_initialize (regexp_obj_p, bc_p, pattern_str_p, flags);
338425bb815Sopenharmony_ci  ecma_deref_ecma_string (pattern_str_p);
339425bb815Sopenharmony_ci
340425bb815Sopenharmony_ci  return ecma_make_object_value (regexp_obj_p);
341425bb815Sopenharmony_ci} /* ecma_op_create_regexp_from_pattern */
342425bb815Sopenharmony_ci
343425bb815Sopenharmony_ci/**
344425bb815Sopenharmony_ci * Method for creating a RegExp object from bytecode.
345425bb815Sopenharmony_ci *
346425bb815Sopenharmony_ci * Note:
347425bb815Sopenharmony_ci *      Allocation have to happen before invoking this function using ecma_op_regexp_alloc.
348425bb815Sopenharmony_ci *
349425bb815Sopenharmony_ci * @return ecma_value_t
350425bb815Sopenharmony_ci */
351425bb815Sopenharmony_ciecma_value_t
352425bb815Sopenharmony_ciecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, /**< RegExp object */
353425bb815Sopenharmony_ci                                     re_compiled_code_t *bc_p) /**< bytecode */
354425bb815Sopenharmony_ci{
355425bb815Sopenharmony_ci  ecma_bytecode_ref ((ecma_compiled_code_t *) bc_p);
356425bb815Sopenharmony_ci  ecma_string_t *pattern_str_p = ecma_get_string_from_value (bc_p->source);
357425bb815Sopenharmony_ci  uint16_t flags = bc_p->header.status_flags;
358425bb815Sopenharmony_ci
359425bb815Sopenharmony_ci  ecma_op_regexp_initialize (regexp_obj_p, bc_p, pattern_str_p, flags);
360425bb815Sopenharmony_ci
361425bb815Sopenharmony_ci  return ecma_make_object_value (regexp_obj_p);
362425bb815Sopenharmony_ci} /* ecma_op_create_regexp_from_bytecode */
363425bb815Sopenharmony_ci
364425bb815Sopenharmony_ci/**
365425bb815Sopenharmony_ci * Method for creating a RegExp object from pattern with already parsed flags.
366425bb815Sopenharmony_ci *
367425bb815Sopenharmony_ci * Note:
368425bb815Sopenharmony_ci *      Allocation have to happen before invoking this function using ecma_op_regexp_alloc.
369425bb815Sopenharmony_ci *
370425bb815Sopenharmony_ci * @return ecma_value_t
371425bb815Sopenharmony_ci */
372425bb815Sopenharmony_ciecma_value_t
373425bb815Sopenharmony_ciecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p, /**< RegExp object */
374425bb815Sopenharmony_ci                                  ecma_value_t pattern_value, /**< pattern */
375425bb815Sopenharmony_ci                                  uint16_t flags) /**< flags */
376425bb815Sopenharmony_ci{
377425bb815Sopenharmony_ci  ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value);
378425bb815Sopenharmony_ci
379425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (pattern_str_p == NULL))
380425bb815Sopenharmony_ci  {
381425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
382425bb815Sopenharmony_ci  }
383425bb815Sopenharmony_ci
384425bb815Sopenharmony_ci  re_compiled_code_t *bc_p = re_compile_bytecode (pattern_str_p, flags);
385425bb815Sopenharmony_ci  ecma_deref_ecma_string (pattern_str_p);
386425bb815Sopenharmony_ci
387425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (bc_p == NULL))
388425bb815Sopenharmony_ci  {
389425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
390425bb815Sopenharmony_ci  }
391425bb815Sopenharmony_ci
392425bb815Sopenharmony_ci  ecma_op_regexp_initialize (regexp_obj_p, bc_p, pattern_str_p, flags);
393425bb815Sopenharmony_ci
394425bb815Sopenharmony_ci  return ecma_make_object_value (regexp_obj_p);
395425bb815Sopenharmony_ci} /* ecma_op_create_regexp_with_flags */
396425bb815Sopenharmony_ci
397425bb815Sopenharmony_ci/**
398425bb815Sopenharmony_ci * Canonicalize a character
399425bb815Sopenharmony_ci *
400425bb815Sopenharmony_ci * @return ecma_char_t canonicalized character
401425bb815Sopenharmony_ci */
402425bb815Sopenharmony_cilit_code_point_t
403425bb815Sopenharmony_ciecma_regexp_canonicalize_char (lit_code_point_t ch, /**< character */
404425bb815Sopenharmony_ci                               bool unicode) /**< unicode */
405425bb815Sopenharmony_ci{
406425bb815Sopenharmony_ci  if (JERRY_LIKELY (ch <= LIT_UTF8_1_BYTE_CODE_POINT_MAX))
407425bb815Sopenharmony_ci  {
408425bb815Sopenharmony_ci    if (ch >= LIT_CHAR_LOWERCASE_A && ch <= LIT_CHAR_LOWERCASE_Z)
409425bb815Sopenharmony_ci    {
410425bb815Sopenharmony_ci      return (ecma_char_t) (ch - (LIT_CHAR_LOWERCASE_A - LIT_CHAR_UPPERCASE_A));
411425bb815Sopenharmony_ci    }
412425bb815Sopenharmony_ci
413425bb815Sopenharmony_ci    return ch;
414425bb815Sopenharmony_ci  }
415425bb815Sopenharmony_ci
416425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
417425bb815Sopenharmony_ci  /* TODO: Implement case folding for code points in the upper planes. */
418425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (ch > LIT_UTF16_CODE_UNIT_MAX))
419425bb815Sopenharmony_ci  {
420425bb815Sopenharmony_ci    return ch;
421425bb815Sopenharmony_ci  }
422425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
423425bb815Sopenharmony_ci
424425bb815Sopenharmony_ci  ecma_char_t u[LIT_MAXIMUM_OTHER_CASE_LENGTH];
425425bb815Sopenharmony_ci  const ecma_length_t size = lit_char_to_upper_case ((ecma_char_t) ch, u, LIT_MAXIMUM_OTHER_CASE_LENGTH);
426425bb815Sopenharmony_ci
427425bb815Sopenharmony_ci  if (size != 1)
428425bb815Sopenharmony_ci  {
429425bb815Sopenharmony_ci    return ch;
430425bb815Sopenharmony_ci  }
431425bb815Sopenharmony_ci
432425bb815Sopenharmony_ci  const ecma_char_t cu = u[0];
433425bb815Sopenharmony_ci  if (cu <= LIT_UTF8_1_BYTE_CODE_POINT_MAX && !unicode)
434425bb815Sopenharmony_ci  {
435425bb815Sopenharmony_ci    /* 6. */
436425bb815Sopenharmony_ci    return ch;
437425bb815Sopenharmony_ci  }
438425bb815Sopenharmony_ci
439425bb815Sopenharmony_ci  return cu;
440425bb815Sopenharmony_ci} /* ecma_regexp_canonicalize_char */
441425bb815Sopenharmony_ci
442425bb815Sopenharmony_ci/**
443425bb815Sopenharmony_ci * RegExp Canonicalize abstract operation
444425bb815Sopenharmony_ci *
445425bb815Sopenharmony_ci * See also: ECMA-262 v5, 15.10.2.8
446425bb815Sopenharmony_ci *
447425bb815Sopenharmony_ci * @return ecma_char_t canonicalized character
448425bb815Sopenharmony_ci */
449425bb815Sopenharmony_cistatic inline lit_code_point_t JERRY_ATTR_ALWAYS_INLINE
450425bb815Sopenharmony_ciecma_regexp_canonicalize (lit_code_point_t ch, /**< character */
451425bb815Sopenharmony_ci                          uint16_t flags) /**< flags */
452425bb815Sopenharmony_ci{
453425bb815Sopenharmony_ci  if (flags & RE_FLAG_IGNORE_CASE)
454425bb815Sopenharmony_ci  {
455425bb815Sopenharmony_ci    return ecma_regexp_canonicalize_char (ch, flags & RE_FLAG_UNICODE);
456425bb815Sopenharmony_ci  }
457425bb815Sopenharmony_ci
458425bb815Sopenharmony_ci  return ch;
459425bb815Sopenharmony_ci} /* ecma_regexp_canonicalize */
460425bb815Sopenharmony_ci
461425bb815Sopenharmony_ci/**
462425bb815Sopenharmony_ci * Check if a code point is matched by a class escape.
463425bb815Sopenharmony_ci *
464425bb815Sopenharmony_ci * @return true, if code point matches escape
465425bb815Sopenharmony_ci *         false, otherwise
466425bb815Sopenharmony_ci */
467425bb815Sopenharmony_cistatic bool
468425bb815Sopenharmony_ciecma_regexp_check_class_escape (lit_code_point_t cp, /**< char */
469425bb815Sopenharmony_ci                                ecma_class_escape_t escape) /**< escape */
470425bb815Sopenharmony_ci{
471425bb815Sopenharmony_ci  switch (escape)
472425bb815Sopenharmony_ci  {
473425bb815Sopenharmony_ci    case RE_ESCAPE_DIGIT:
474425bb815Sopenharmony_ci    {
475425bb815Sopenharmony_ci      return (cp >= LIT_CHAR_0 && cp <= LIT_CHAR_9);
476425bb815Sopenharmony_ci    }
477425bb815Sopenharmony_ci    case RE_ESCAPE_NOT_DIGIT:
478425bb815Sopenharmony_ci    {
479425bb815Sopenharmony_ci      return (cp < LIT_CHAR_0 || cp > LIT_CHAR_9);
480425bb815Sopenharmony_ci    }
481425bb815Sopenharmony_ci    case RE_ESCAPE_WORD_CHAR:
482425bb815Sopenharmony_ci    {
483425bb815Sopenharmony_ci      return lit_char_is_word_char (cp);
484425bb815Sopenharmony_ci    }
485425bb815Sopenharmony_ci    case RE_ESCAPE_NOT_WORD_CHAR:
486425bb815Sopenharmony_ci    {
487425bb815Sopenharmony_ci      return !lit_char_is_word_char (cp);
488425bb815Sopenharmony_ci    }
489425bb815Sopenharmony_ci    case RE_ESCAPE_WHITESPACE:
490425bb815Sopenharmony_ci    {
491425bb815Sopenharmony_ci      return lit_char_is_white_space ((ecma_char_t) cp);
492425bb815Sopenharmony_ci    }
493425bb815Sopenharmony_ci    case RE_ESCAPE_NOT_WHITESPACE:
494425bb815Sopenharmony_ci    {
495425bb815Sopenharmony_ci      return !lit_char_is_white_space ((ecma_char_t) cp);
496425bb815Sopenharmony_ci    }
497425bb815Sopenharmony_ci    default:
498425bb815Sopenharmony_ci    {
499425bb815Sopenharmony_ci      JERRY_UNREACHABLE ();
500425bb815Sopenharmony_ci    }
501425bb815Sopenharmony_ci  }
502425bb815Sopenharmony_ci} /* ecma_regexp_check_class_escape */
503425bb815Sopenharmony_ci
504425bb815Sopenharmony_ci/**
505425bb815Sopenharmony_ci * Helper function to get current code point or code unit depending on execution mode,
506425bb815Sopenharmony_ci * and advance the string pointer.
507425bb815Sopenharmony_ci *
508425bb815Sopenharmony_ci * @return lit_code_point_t current code point
509425bb815Sopenharmony_ci */
510425bb815Sopenharmony_cistatic lit_code_point_t
511425bb815Sopenharmony_ciecma_regexp_advance (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */
512425bb815Sopenharmony_ci                     const lit_utf8_byte_t **str_p) /**< reference to string pointer */
513425bb815Sopenharmony_ci{
514425bb815Sopenharmony_ci  JERRY_ASSERT (str_p != NULL);
515425bb815Sopenharmony_ci  lit_code_point_t cp = lit_cesu8_read_next (str_p);
516425bb815Sopenharmony_ci
517425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
518425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (re_ctx_p->flags & RE_FLAG_UNICODE)
519425bb815Sopenharmony_ci      && lit_is_code_point_utf16_high_surrogate ((ecma_char_t) cp)
520425bb815Sopenharmony_ci      && *str_p < re_ctx_p->input_end_p)
521425bb815Sopenharmony_ci  {
522425bb815Sopenharmony_ci    const ecma_char_t next_ch = lit_cesu8_peek_next (*str_p);
523425bb815Sopenharmony_ci    if (lit_is_code_point_utf16_low_surrogate (next_ch))
524425bb815Sopenharmony_ci    {
525425bb815Sopenharmony_ci      cp = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) cp, next_ch);
526425bb815Sopenharmony_ci      *str_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT;
527425bb815Sopenharmony_ci    }
528425bb815Sopenharmony_ci  }
529425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
530425bb815Sopenharmony_ci
531425bb815Sopenharmony_ci  return ecma_regexp_canonicalize (cp, re_ctx_p->flags);
532425bb815Sopenharmony_ci} /* ecma_regexp_advance */
533425bb815Sopenharmony_ci
534425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
535425bb815Sopenharmony_ci/**
536425bb815Sopenharmony_ci * Helper function to get current full unicode code point and advance the string pointer.
537425bb815Sopenharmony_ci *
538425bb815Sopenharmony_ci * @return lit_code_point_t current code point
539425bb815Sopenharmony_ci */
540425bb815Sopenharmony_cilit_code_point_t
541425bb815Sopenharmony_ciecma_regexp_unicode_advance (const lit_utf8_byte_t **str_p, /**< reference to string pointer */
542425bb815Sopenharmony_ci                             const lit_utf8_byte_t *end_p) /**< string end pointer */
543425bb815Sopenharmony_ci{
544425bb815Sopenharmony_ci  JERRY_ASSERT (str_p != NULL);
545425bb815Sopenharmony_ci  const lit_utf8_byte_t *current_p = *str_p;
546425bb815Sopenharmony_ci
547425bb815Sopenharmony_ci  lit_code_point_t ch = lit_cesu8_read_next (&current_p);
548425bb815Sopenharmony_ci  if (lit_is_code_point_utf16_high_surrogate ((ecma_char_t) ch)
549425bb815Sopenharmony_ci      && current_p < end_p)
550425bb815Sopenharmony_ci  {
551425bb815Sopenharmony_ci    const ecma_char_t next_ch = lit_cesu8_peek_next (current_p);
552425bb815Sopenharmony_ci    if (lit_is_code_point_utf16_low_surrogate (next_ch))
553425bb815Sopenharmony_ci    {
554425bb815Sopenharmony_ci      ch = lit_convert_surrogate_pair_to_code_point ((ecma_char_t) ch, next_ch);
555425bb815Sopenharmony_ci      current_p += LIT_UTF8_MAX_BYTES_IN_CODE_UNIT;
556425bb815Sopenharmony_ci    }
557425bb815Sopenharmony_ci  }
558425bb815Sopenharmony_ci
559425bb815Sopenharmony_ci  *str_p = current_p;
560425bb815Sopenharmony_ci  return ch;
561425bb815Sopenharmony_ci} /* ecma_regexp_unicode_advance */
562425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
563425bb815Sopenharmony_ci
564425bb815Sopenharmony_ci/**
565425bb815Sopenharmony_ci * Helper function to revert the string pointer to the previous code point.
566425bb815Sopenharmony_ci *
567425bb815Sopenharmony_ci * @return pointer to previous code point
568425bb815Sopenharmony_ci */
569425bb815Sopenharmony_cistatic JERRY_ATTR_NOINLINE const lit_utf8_byte_t *
570425bb815Sopenharmony_ciecma_regexp_step_back (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */
571425bb815Sopenharmony_ci                       const lit_utf8_byte_t *str_p) /**< reference to string pointer */
572425bb815Sopenharmony_ci{
573425bb815Sopenharmony_ci  JERRY_ASSERT (str_p != NULL);
574425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
575425bb815Sopenharmony_ci  lit_code_point_t ch = lit_cesu8_read_prev (&str_p);
576425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (re_ctx_p->flags & RE_FLAG_UNICODE)
577425bb815Sopenharmony_ci      && lit_is_code_point_utf16_low_surrogate (ch)
578425bb815Sopenharmony_ci      && lit_is_code_point_utf16_high_surrogate (lit_cesu8_peek_prev (str_p)))
579425bb815Sopenharmony_ci  {
580425bb815Sopenharmony_ci    str_p -= LIT_UTF8_MAX_BYTES_IN_CODE_UNIT;
581425bb815Sopenharmony_ci  }
582425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
583425bb815Sopenharmony_ci  JERRY_UNUSED (re_ctx_p);
584425bb815Sopenharmony_ci  lit_utf8_decr (&str_p);
585425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015) */
586425bb815Sopenharmony_ci  return str_p;
587425bb815Sopenharmony_ci} /* ecma_regexp_step_back */
588425bb815Sopenharmony_ci
589425bb815Sopenharmony_ci/**
590425bb815Sopenharmony_ci * Recursive function for executing RegExp bytecode.
591425bb815Sopenharmony_ci *
592425bb815Sopenharmony_ci * See also:
593425bb815Sopenharmony_ci *          ECMA-262 v5, 15.10.2.1
594425bb815Sopenharmony_ci *
595425bb815Sopenharmony_ci * @return pointer to the end of the currently matched substring
596425bb815Sopenharmony_ci *         NULL, if pattern did not match
597425bb815Sopenharmony_ci */
598425bb815Sopenharmony_cistatic const lit_utf8_byte_t *
599425bb815Sopenharmony_ciecma_regexp_run (ecma_regexp_ctx_t *re_ctx_p, /**< RegExp matcher context */
600425bb815Sopenharmony_ci                 const uint8_t *bc_p, /**< pointer to the current RegExp bytecode */
601425bb815Sopenharmony_ci                 const lit_utf8_byte_t *str_curr_p) /**< input string pointer */
602425bb815Sopenharmony_ci{
603425bb815Sopenharmony_ci#if (JERRY_STACK_LIMIT != 0)
604425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT))
605425bb815Sopenharmony_ci  {
606425bb815Sopenharmony_ci    return ECMA_RE_OUT_OF_STACK;
607425bb815Sopenharmony_ci  }
608425bb815Sopenharmony_ci#endif /* JERRY_STACK_LIMIT != 0 */
609425bb815Sopenharmony_ci
610425bb815Sopenharmony_ci  const lit_utf8_byte_t *str_start_p = str_curr_p;
611425bb815Sopenharmony_ci  const uint8_t *next_alternative_p = NULL;
612425bb815Sopenharmony_ci
613425bb815Sopenharmony_ci  while (true)
614425bb815Sopenharmony_ci  {
615425bb815Sopenharmony_ci    const re_opcode_t op = re_get_opcode (&bc_p);
616425bb815Sopenharmony_ci
617425bb815Sopenharmony_ci    switch (op)
618425bb815Sopenharmony_ci    {
619425bb815Sopenharmony_ci      case RE_OP_EOF:
620425bb815Sopenharmony_ci      {
621425bb815Sopenharmony_ci        re_ctx_p->captures_p[RE_GLOBAL_CAPTURE].end_p = str_curr_p;
622425bb815Sopenharmony_ci        /* FALLTHRU */
623425bb815Sopenharmony_ci      }
624425bb815Sopenharmony_ci      case RE_OP_ASSERT_END:
625425bb815Sopenharmony_ci      case RE_OP_ITERATOR_END:
626425bb815Sopenharmony_ci      {
627425bb815Sopenharmony_ci        return str_curr_p;
628425bb815Sopenharmony_ci      }
629425bb815Sopenharmony_ci      case RE_OP_ALTERNATIVE_START:
630425bb815Sopenharmony_ci      {
631425bb815Sopenharmony_ci        const uint32_t offset = re_get_value (&bc_p);
632425bb815Sopenharmony_ci        next_alternative_p = bc_p + offset;
633425bb815Sopenharmony_ci        continue;
634425bb815Sopenharmony_ci      }
635425bb815Sopenharmony_ci      case RE_OP_ALTERNATIVE_NEXT:
636425bb815Sopenharmony_ci      {
637425bb815Sopenharmony_ci        while (true)
638425bb815Sopenharmony_ci        {
639425bb815Sopenharmony_ci          const uint32_t offset = re_get_value (&bc_p);
640425bb815Sopenharmony_ci          bc_p += offset;
641425bb815Sopenharmony_ci
642425bb815Sopenharmony_ci          if (*bc_p != RE_OP_ALTERNATIVE_NEXT)
643425bb815Sopenharmony_ci          {
644425bb815Sopenharmony_ci            break;
645425bb815Sopenharmony_ci          }
646425bb815Sopenharmony_ci
647425bb815Sopenharmony_ci          bc_p++;
648425bb815Sopenharmony_ci        }
649425bb815Sopenharmony_ci
650425bb815Sopenharmony_ci        continue;
651425bb815Sopenharmony_ci      }
652425bb815Sopenharmony_ci      case RE_OP_NO_ALTERNATIVE:
653425bb815Sopenharmony_ci      {
654425bb815Sopenharmony_ci        return NULL;
655425bb815Sopenharmony_ci      }
656425bb815Sopenharmony_ci      case RE_OP_CAPTURING_GROUP_START:
657425bb815Sopenharmony_ci      {
658425bb815Sopenharmony_ci        const uint32_t group_idx = re_get_value (&bc_p);
659425bb815Sopenharmony_ci        ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx;
660425bb815Sopenharmony_ci        group_p->subcapture_count = re_get_value (&bc_p);
661425bb815Sopenharmony_ci
662425bb815Sopenharmony_ci        const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p;
663425bb815Sopenharmony_ci        const lit_utf8_byte_t *const saved_end_p = group_p->end_p;
664425bb815Sopenharmony_ci        const uint32_t saved_iterator = group_p->iterator;
665425bb815Sopenharmony_ci
666425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
667425bb815Sopenharmony_ci        group_p->end_p = NULL;
668425bb815Sopenharmony_ci
669425bb815Sopenharmony_ci        /* If zero iterations are allowed, then execute the end opcode which will handle further iterations,
670425bb815Sopenharmony_ci         * otherwise run the 1st iteration immediately by executing group bytecode. */
671425bb815Sopenharmony_ci        if (qmin == 0)
672425bb815Sopenharmony_ci        {
673425bb815Sopenharmony_ci          group_p->iterator = 0;
674425bb815Sopenharmony_ci          group_p->begin_p = NULL;
675425bb815Sopenharmony_ci          const uint32_t end_offset = re_get_value (&bc_p);
676425bb815Sopenharmony_ci          group_p->bc_p = bc_p;
677425bb815Sopenharmony_ci
678425bb815Sopenharmony_ci          bc_p += end_offset;
679425bb815Sopenharmony_ci        }
680425bb815Sopenharmony_ci        else
681425bb815Sopenharmony_ci        {
682425bb815Sopenharmony_ci          group_p->iterator = 1;
683425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
684425bb815Sopenharmony_ci          group_p->bc_p = bc_p;
685425bb815Sopenharmony_ci        }
686425bb815Sopenharmony_ci
687425bb815Sopenharmony_ci        const lit_utf8_byte_t *matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
688425bb815Sopenharmony_ci        group_p->iterator = saved_iterator;
689425bb815Sopenharmony_ci
690425bb815Sopenharmony_ci        if (matched_p == NULL)
691425bb815Sopenharmony_ci        {
692425bb815Sopenharmony_ci          group_p->begin_p = saved_begin_p;
693425bb815Sopenharmony_ci          group_p->end_p = saved_end_p;
694425bb815Sopenharmony_ci          goto fail;
695425bb815Sopenharmony_ci        }
696425bb815Sopenharmony_ci
697425bb815Sopenharmony_ci        return matched_p;
698425bb815Sopenharmony_ci      }
699425bb815Sopenharmony_ci      case RE_OP_NON_CAPTURING_GROUP_START:
700425bb815Sopenharmony_ci      {
701425bb815Sopenharmony_ci        const uint32_t group_idx = re_get_value (&bc_p);
702425bb815Sopenharmony_ci        ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx;
703425bb815Sopenharmony_ci
704425bb815Sopenharmony_ci        group_p->subcapture_start = re_get_value (&bc_p);
705425bb815Sopenharmony_ci        group_p->subcapture_count = re_get_value (&bc_p);
706425bb815Sopenharmony_ci
707425bb815Sopenharmony_ci        const uint32_t saved_iterator = group_p->iterator;
708425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
709425bb815Sopenharmony_ci
710425bb815Sopenharmony_ci        /* If zero iterations are allowed, then execute the end opcode which will handle further iterations,
711425bb815Sopenharmony_ci         * otherwise run the 1st iteration immediately by executing group bytecode. */
712425bb815Sopenharmony_ci        if (qmin == 0)
713425bb815Sopenharmony_ci        {
714425bb815Sopenharmony_ci          group_p->iterator = 0;
715425bb815Sopenharmony_ci          group_p->begin_p = NULL;
716425bb815Sopenharmony_ci          const uint32_t end_offset = re_get_value (&bc_p);
717425bb815Sopenharmony_ci          group_p->bc_p = bc_p;
718425bb815Sopenharmony_ci
719425bb815Sopenharmony_ci          bc_p += end_offset;
720425bb815Sopenharmony_ci        }
721425bb815Sopenharmony_ci        else
722425bb815Sopenharmony_ci        {
723425bb815Sopenharmony_ci          group_p->iterator = 1;
724425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
725425bb815Sopenharmony_ci          group_p->bc_p = bc_p;
726425bb815Sopenharmony_ci        }
727425bb815Sopenharmony_ci
728425bb815Sopenharmony_ci        const lit_utf8_byte_t *matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
729425bb815Sopenharmony_ci        group_p->iterator = saved_iterator;
730425bb815Sopenharmony_ci
731425bb815Sopenharmony_ci        if (matched_p == NULL)
732425bb815Sopenharmony_ci        {
733425bb815Sopenharmony_ci          goto fail;
734425bb815Sopenharmony_ci        }
735425bb815Sopenharmony_ci
736425bb815Sopenharmony_ci        return matched_p;
737425bb815Sopenharmony_ci      }
738425bb815Sopenharmony_ci      case RE_OP_GREEDY_CAPTURING_GROUP_END:
739425bb815Sopenharmony_ci      {
740425bb815Sopenharmony_ci        const uint32_t group_idx = re_get_value (&bc_p);
741425bb815Sopenharmony_ci        ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx;
742425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
743425bb815Sopenharmony_ci
744425bb815Sopenharmony_ci        if (group_p->iterator < qmin)
745425bb815Sopenharmony_ci        {
746425bb815Sopenharmony_ci          /* No need to save begin_p since we don't have to backtrack beyond the minimum iteration count, but we have
747425bb815Sopenharmony_ci           * to clear nested capturing groups. */
748425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
749425bb815Sopenharmony_ci          for (uint32_t i = 1; i < group_p->subcapture_count; ++i)
750425bb815Sopenharmony_ci          {
751425bb815Sopenharmony_ci            group_p[i].begin_p = NULL;
752425bb815Sopenharmony_ci          }
753425bb815Sopenharmony_ci
754425bb815Sopenharmony_ci          group_p->iterator++;
755425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
756425bb815Sopenharmony_ci
757425bb815Sopenharmony_ci          if (matched_p != NULL)
758425bb815Sopenharmony_ci          {
759425bb815Sopenharmony_ci            return matched_p;
760425bb815Sopenharmony_ci          }
761425bb815Sopenharmony_ci
762425bb815Sopenharmony_ci          group_p->iterator--;
763425bb815Sopenharmony_ci          goto fail;
764425bb815Sopenharmony_ci        }
765425bb815Sopenharmony_ci
766425bb815Sopenharmony_ci        /* Empty matches are not allowed after reaching the minimum number of iterations. */
767425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin))
768425bb815Sopenharmony_ci        {
769425bb815Sopenharmony_ci          goto fail;
770425bb815Sopenharmony_ci        }
771425bb815Sopenharmony_ci
772425bb815Sopenharmony_ci        const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET;
773425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->iterator >= qmax))
774425bb815Sopenharmony_ci        {
775425bb815Sopenharmony_ci          /* Reached maximum number of iterations, try to match tail bytecode. */
776425bb815Sopenharmony_ci          group_p->end_p = str_curr_p;
777425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
778425bb815Sopenharmony_ci
779425bb815Sopenharmony_ci          if (matched_p != NULL)
780425bb815Sopenharmony_ci          {
781425bb815Sopenharmony_ci            return matched_p;
782425bb815Sopenharmony_ci          }
783425bb815Sopenharmony_ci
784425bb815Sopenharmony_ci          goto fail;
785425bb815Sopenharmony_ci        }
786425bb815Sopenharmony_ci
787425bb815Sopenharmony_ci        {
788425bb815Sopenharmony_ci          /* Save and clear all nested capturing groups, and try to iterate. */
789425bb815Sopenharmony_ci          JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count);
790425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
791425bb815Sopenharmony_ci          {
792425bb815Sopenharmony_ci            saved_captures_p[i] = group_p[i].begin_p;
793425bb815Sopenharmony_ci            group_p[i].begin_p = NULL;
794425bb815Sopenharmony_ci          }
795425bb815Sopenharmony_ci
796425bb815Sopenharmony_ci          group_p->iterator++;
797425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
798425bb815Sopenharmony_ci
799425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
800425bb815Sopenharmony_ci
801425bb815Sopenharmony_ci          if (matched_p != NULL)
802425bb815Sopenharmony_ci          {
803425bb815Sopenharmony_ci            return matched_p;
804425bb815Sopenharmony_ci          }
805425bb815Sopenharmony_ci
806425bb815Sopenharmony_ci          /* Failed to iterate again, backtrack to current match, and try to run tail bytecode. */
807425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
808425bb815Sopenharmony_ci          {
809425bb815Sopenharmony_ci            group_p[i].begin_p = saved_captures_p[i];
810425bb815Sopenharmony_ci          }
811425bb815Sopenharmony_ci
812425bb815Sopenharmony_ci          group_p->iterator--;
813425bb815Sopenharmony_ci          group_p->end_p = str_curr_p;
814425bb815Sopenharmony_ci        }
815425bb815Sopenharmony_ci
816425bb815Sopenharmony_ci        const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
817425bb815Sopenharmony_ci
818425bb815Sopenharmony_ci        if (tail_match_p != NULL)
819425bb815Sopenharmony_ci        {
820425bb815Sopenharmony_ci          return tail_match_p;
821425bb815Sopenharmony_ci        }
822425bb815Sopenharmony_ci
823425bb815Sopenharmony_ci        goto fail;
824425bb815Sopenharmony_ci      }
825425bb815Sopenharmony_ci      case RE_OP_GREEDY_NON_CAPTURING_GROUP_END:
826425bb815Sopenharmony_ci      {
827425bb815Sopenharmony_ci        const uint32_t group_idx = re_get_value (&bc_p);
828425bb815Sopenharmony_ci        ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx;
829425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
830425bb815Sopenharmony_ci
831425bb815Sopenharmony_ci        if (group_p->iterator < qmin)
832425bb815Sopenharmony_ci        {
833425bb815Sopenharmony_ci          /* No need to save begin_p but we have to clear nested capturing groups. */
834425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
835425bb815Sopenharmony_ci
836425bb815Sopenharmony_ci          ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start;
837425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
838425bb815Sopenharmony_ci          {
839425bb815Sopenharmony_ci            capture_p[i].begin_p = NULL;
840425bb815Sopenharmony_ci          }
841425bb815Sopenharmony_ci
842425bb815Sopenharmony_ci          group_p->iterator++;
843425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
844425bb815Sopenharmony_ci
845425bb815Sopenharmony_ci          if (matched_p != NULL)
846425bb815Sopenharmony_ci          {
847425bb815Sopenharmony_ci            return matched_p;
848425bb815Sopenharmony_ci          }
849425bb815Sopenharmony_ci
850425bb815Sopenharmony_ci          group_p->iterator--;
851425bb815Sopenharmony_ci          goto fail;
852425bb815Sopenharmony_ci        }
853425bb815Sopenharmony_ci
854425bb815Sopenharmony_ci        /* Empty matches are not allowed after reaching the minimum number of iterations. */
855425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin))
856425bb815Sopenharmony_ci        {
857425bb815Sopenharmony_ci          goto fail;
858425bb815Sopenharmony_ci        }
859425bb815Sopenharmony_ci
860425bb815Sopenharmony_ci        const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET;
861425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->iterator >= qmax))
862425bb815Sopenharmony_ci        {
863425bb815Sopenharmony_ci          /* Reached maximum number of iterations, try to match tail bytecode. */
864425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
865425bb815Sopenharmony_ci
866425bb815Sopenharmony_ci          if (matched_p != NULL)
867425bb815Sopenharmony_ci          {
868425bb815Sopenharmony_ci            return matched_p;
869425bb815Sopenharmony_ci          }
870425bb815Sopenharmony_ci
871425bb815Sopenharmony_ci          goto fail;
872425bb815Sopenharmony_ci        }
873425bb815Sopenharmony_ci
874425bb815Sopenharmony_ci        {
875425bb815Sopenharmony_ci          /* Save and clear all nested capturing groups, and try to iterate. */
876425bb815Sopenharmony_ci          JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count);
877425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
878425bb815Sopenharmony_ci          {
879425bb815Sopenharmony_ci            ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i;
880425bb815Sopenharmony_ci            saved_captures_p[i] = capture_p->begin_p;
881425bb815Sopenharmony_ci            capture_p->begin_p = NULL;
882425bb815Sopenharmony_ci          }
883425bb815Sopenharmony_ci
884425bb815Sopenharmony_ci          group_p->iterator++;
885425bb815Sopenharmony_ci          const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p;
886425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
887425bb815Sopenharmony_ci
888425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
889425bb815Sopenharmony_ci
890425bb815Sopenharmony_ci          if (matched_p != NULL)
891425bb815Sopenharmony_ci          {
892425bb815Sopenharmony_ci            return matched_p;
893425bb815Sopenharmony_ci          }
894425bb815Sopenharmony_ci
895425bb815Sopenharmony_ci          /* Failed to iterate again, backtrack to current match, and try to run tail bytecode. */
896425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
897425bb815Sopenharmony_ci          {
898425bb815Sopenharmony_ci            ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i;
899425bb815Sopenharmony_ci            capture_p->begin_p = saved_captures_p[i];
900425bb815Sopenharmony_ci          }
901425bb815Sopenharmony_ci
902425bb815Sopenharmony_ci          group_p->iterator--;
903425bb815Sopenharmony_ci          group_p->begin_p = saved_begin_p;
904425bb815Sopenharmony_ci        }
905425bb815Sopenharmony_ci
906425bb815Sopenharmony_ci        const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
907425bb815Sopenharmony_ci
908425bb815Sopenharmony_ci        if (tail_match_p != NULL)
909425bb815Sopenharmony_ci        {
910425bb815Sopenharmony_ci          return tail_match_p;
911425bb815Sopenharmony_ci        }
912425bb815Sopenharmony_ci
913425bb815Sopenharmony_ci        goto fail;
914425bb815Sopenharmony_ci      }
915425bb815Sopenharmony_ci      case RE_OP_LAZY_CAPTURING_GROUP_END:
916425bb815Sopenharmony_ci      {
917425bb815Sopenharmony_ci        const uint32_t group_idx = re_get_value (&bc_p);
918425bb815Sopenharmony_ci        ecma_regexp_capture_t *const group_p = re_ctx_p->captures_p + group_idx;
919425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
920425bb815Sopenharmony_ci
921425bb815Sopenharmony_ci        if (group_p->iterator < qmin)
922425bb815Sopenharmony_ci        {
923425bb815Sopenharmony_ci          /* No need to save begin_p but we have to clear nested capturing groups. */
924425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
925425bb815Sopenharmony_ci          for (uint32_t i = 1; i < group_p->subcapture_count; ++i)
926425bb815Sopenharmony_ci          {
927425bb815Sopenharmony_ci            group_p[i].begin_p = NULL;
928425bb815Sopenharmony_ci          }
929425bb815Sopenharmony_ci
930425bb815Sopenharmony_ci          group_p->iterator++;
931425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
932425bb815Sopenharmony_ci
933425bb815Sopenharmony_ci          if (matched_p != NULL)
934425bb815Sopenharmony_ci          {
935425bb815Sopenharmony_ci            return matched_p;
936425bb815Sopenharmony_ci          }
937425bb815Sopenharmony_ci
938425bb815Sopenharmony_ci          group_p->iterator--;
939425bb815Sopenharmony_ci          goto fail;
940425bb815Sopenharmony_ci        }
941425bb815Sopenharmony_ci
942425bb815Sopenharmony_ci        /* Empty matches are not allowed after reaching the minimum number of iterations. */
943425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin))
944425bb815Sopenharmony_ci        {
945425bb815Sopenharmony_ci          goto fail;
946425bb815Sopenharmony_ci        }
947425bb815Sopenharmony_ci
948425bb815Sopenharmony_ci        const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET;
949425bb815Sopenharmony_ci        group_p->end_p = str_curr_p;
950425bb815Sopenharmony_ci
951425bb815Sopenharmony_ci        /* Try to match tail bytecode. */
952425bb815Sopenharmony_ci        const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
953425bb815Sopenharmony_ci
954425bb815Sopenharmony_ci        if (tail_match_p != NULL)
955425bb815Sopenharmony_ci        {
956425bb815Sopenharmony_ci          return tail_match_p;
957425bb815Sopenharmony_ci        }
958425bb815Sopenharmony_ci
959425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->iterator >= qmax))
960425bb815Sopenharmony_ci        {
961425bb815Sopenharmony_ci          /* Reached maximum number of iterations and tail bytecode did not match. */
962425bb815Sopenharmony_ci          goto fail;
963425bb815Sopenharmony_ci        }
964425bb815Sopenharmony_ci
965425bb815Sopenharmony_ci        {
966425bb815Sopenharmony_ci          /* Save and clear all nested capturing groups, and try to iterate. */
967425bb815Sopenharmony_ci          JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count);
968425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
969425bb815Sopenharmony_ci          {
970425bb815Sopenharmony_ci            saved_captures_p[i] = group_p[i].begin_p;
971425bb815Sopenharmony_ci            group_p[i].begin_p = NULL;
972425bb815Sopenharmony_ci          }
973425bb815Sopenharmony_ci
974425bb815Sopenharmony_ci          group_p->iterator++;
975425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
976425bb815Sopenharmony_ci
977425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
978425bb815Sopenharmony_ci
979425bb815Sopenharmony_ci          if (matched_p != NULL)
980425bb815Sopenharmony_ci          {
981425bb815Sopenharmony_ci            return matched_p;
982425bb815Sopenharmony_ci          }
983425bb815Sopenharmony_ci
984425bb815Sopenharmony_ci          /* Backtrack to current match. */
985425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
986425bb815Sopenharmony_ci          {
987425bb815Sopenharmony_ci            group_p[i].begin_p = saved_captures_p[i];
988425bb815Sopenharmony_ci          }
989425bb815Sopenharmony_ci
990425bb815Sopenharmony_ci          group_p->iterator--;
991425bb815Sopenharmony_ci        }
992425bb815Sopenharmony_ci
993425bb815Sopenharmony_ci        goto fail;
994425bb815Sopenharmony_ci      }
995425bb815Sopenharmony_ci      case RE_OP_LAZY_NON_CAPTURING_GROUP_END:
996425bb815Sopenharmony_ci      {
997425bb815Sopenharmony_ci        const uint32_t group_idx = re_get_value (&bc_p);
998425bb815Sopenharmony_ci        ecma_regexp_non_capture_t *const group_p = re_ctx_p->non_captures_p + group_idx;
999425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
1000425bb815Sopenharmony_ci
1001425bb815Sopenharmony_ci        if (group_p->iterator < qmin)
1002425bb815Sopenharmony_ci        {
1003425bb815Sopenharmony_ci          /* Clear nested captures. */
1004425bb815Sopenharmony_ci          ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start;
1005425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
1006425bb815Sopenharmony_ci          {
1007425bb815Sopenharmony_ci            capture_p[i].begin_p = NULL;
1008425bb815Sopenharmony_ci          }
1009425bb815Sopenharmony_ci
1010425bb815Sopenharmony_ci          group_p->iterator++;
1011425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
1012425bb815Sopenharmony_ci
1013425bb815Sopenharmony_ci          if (matched_p != NULL)
1014425bb815Sopenharmony_ci          {
1015425bb815Sopenharmony_ci            return matched_p;
1016425bb815Sopenharmony_ci          }
1017425bb815Sopenharmony_ci
1018425bb815Sopenharmony_ci          group_p->iterator--;
1019425bb815Sopenharmony_ci          goto fail;
1020425bb815Sopenharmony_ci        }
1021425bb815Sopenharmony_ci
1022425bb815Sopenharmony_ci        /* Empty matches are not allowed after reaching the minimum number of iterations. */
1023425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->begin_p >= str_curr_p) && (group_p->iterator > qmin))
1024425bb815Sopenharmony_ci        {
1025425bb815Sopenharmony_ci          goto fail;
1026425bb815Sopenharmony_ci        }
1027425bb815Sopenharmony_ci
1028425bb815Sopenharmony_ci        const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET;
1029425bb815Sopenharmony_ci
1030425bb815Sopenharmony_ci        /* Try to match tail bytecode. */
1031425bb815Sopenharmony_ci        const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1032425bb815Sopenharmony_ci
1033425bb815Sopenharmony_ci        if (tail_match_p != NULL)
1034425bb815Sopenharmony_ci        {
1035425bb815Sopenharmony_ci          return tail_match_p;
1036425bb815Sopenharmony_ci        }
1037425bb815Sopenharmony_ci
1038425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (group_p->iterator >= qmax))
1039425bb815Sopenharmony_ci        {
1040425bb815Sopenharmony_ci          /* Reached maximum number of iterations and tail bytecode did not match. */
1041425bb815Sopenharmony_ci          goto fail;
1042425bb815Sopenharmony_ci        }
1043425bb815Sopenharmony_ci
1044425bb815Sopenharmony_ci        {
1045425bb815Sopenharmony_ci          /* Save and clear all nested capturing groups, and try to iterate. */
1046425bb815Sopenharmony_ci          JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, group_p->subcapture_count);
1047425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
1048425bb815Sopenharmony_ci          {
1049425bb815Sopenharmony_ci            ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i;
1050425bb815Sopenharmony_ci            saved_captures_p[i] = capture_p->begin_p;
1051425bb815Sopenharmony_ci            capture_p->begin_p = NULL;
1052425bb815Sopenharmony_ci          }
1053425bb815Sopenharmony_ci
1054425bb815Sopenharmony_ci          group_p->iterator++;
1055425bb815Sopenharmony_ci          const lit_utf8_byte_t *const saved_begin_p = group_p->begin_p;
1056425bb815Sopenharmony_ci          group_p->begin_p = str_curr_p;
1057425bb815Sopenharmony_ci
1058425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, group_p->bc_p, str_curr_p);
1059425bb815Sopenharmony_ci
1060425bb815Sopenharmony_ci          if (matched_p != NULL)
1061425bb815Sopenharmony_ci          {
1062425bb815Sopenharmony_ci            return matched_p;
1063425bb815Sopenharmony_ci          }
1064425bb815Sopenharmony_ci
1065425bb815Sopenharmony_ci          /* Backtrack to current match. */
1066425bb815Sopenharmony_ci          for (uint32_t i = 0; i < group_p->subcapture_count; ++i)
1067425bb815Sopenharmony_ci          {
1068425bb815Sopenharmony_ci            ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + group_p->subcapture_start + i;
1069425bb815Sopenharmony_ci            capture_p->begin_p = saved_captures_p[i];
1070425bb815Sopenharmony_ci          }
1071425bb815Sopenharmony_ci
1072425bb815Sopenharmony_ci          group_p->iterator--;
1073425bb815Sopenharmony_ci          group_p->begin_p = saved_begin_p;
1074425bb815Sopenharmony_ci        }
1075425bb815Sopenharmony_ci
1076425bb815Sopenharmony_ci        goto fail;
1077425bb815Sopenharmony_ci      }
1078425bb815Sopenharmony_ci      case RE_OP_GREEDY_ITERATOR:
1079425bb815Sopenharmony_ci      {
1080425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
1081425bb815Sopenharmony_ci        const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET;
1082425bb815Sopenharmony_ci        const uint32_t end_offset = re_get_value (&bc_p);
1083425bb815Sopenharmony_ci
1084425bb815Sopenharmony_ci        uint32_t iterator = 0;
1085425bb815Sopenharmony_ci        while (iterator < qmin)
1086425bb815Sopenharmony_ci        {
1087425bb815Sopenharmony_ci          str_curr_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1088425bb815Sopenharmony_ci
1089425bb815Sopenharmony_ci          if (str_curr_p == NULL)
1090425bb815Sopenharmony_ci          {
1091425bb815Sopenharmony_ci            goto fail;
1092425bb815Sopenharmony_ci          }
1093425bb815Sopenharmony_ci
1094425bb815Sopenharmony_ci          if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p))
1095425bb815Sopenharmony_ci          {
1096425bb815Sopenharmony_ci            return str_curr_p;
1097425bb815Sopenharmony_ci          }
1098425bb815Sopenharmony_ci
1099425bb815Sopenharmony_ci          iterator++;
1100425bb815Sopenharmony_ci        }
1101425bb815Sopenharmony_ci
1102425bb815Sopenharmony_ci        while (iterator < qmax)
1103425bb815Sopenharmony_ci        {
1104425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1105425bb815Sopenharmony_ci
1106425bb815Sopenharmony_ci          if (matched_p == NULL)
1107425bb815Sopenharmony_ci          {
1108425bb815Sopenharmony_ci            break;
1109425bb815Sopenharmony_ci          }
1110425bb815Sopenharmony_ci
1111425bb815Sopenharmony_ci          if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p))
1112425bb815Sopenharmony_ci          {
1113425bb815Sopenharmony_ci            return str_curr_p;
1114425bb815Sopenharmony_ci          }
1115425bb815Sopenharmony_ci
1116425bb815Sopenharmony_ci          str_curr_p = matched_p;
1117425bb815Sopenharmony_ci          iterator++;
1118425bb815Sopenharmony_ci        }
1119425bb815Sopenharmony_ci
1120425bb815Sopenharmony_ci        const uint8_t *const tail_bc_p = bc_p + end_offset;
1121425bb815Sopenharmony_ci        while (true)
1122425bb815Sopenharmony_ci        {
1123425bb815Sopenharmony_ci          const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, tail_bc_p, str_curr_p);
1124425bb815Sopenharmony_ci
1125425bb815Sopenharmony_ci          if (tail_match_p != NULL)
1126425bb815Sopenharmony_ci          {
1127425bb815Sopenharmony_ci            return tail_match_p;
1128425bb815Sopenharmony_ci          }
1129425bb815Sopenharmony_ci
1130425bb815Sopenharmony_ci          if (JERRY_UNLIKELY (iterator <= qmin))
1131425bb815Sopenharmony_ci          {
1132425bb815Sopenharmony_ci            goto fail;
1133425bb815Sopenharmony_ci          }
1134425bb815Sopenharmony_ci
1135425bb815Sopenharmony_ci          iterator--;
1136425bb815Sopenharmony_ci          JERRY_ASSERT (str_curr_p > re_ctx_p->input_start_p);
1137425bb815Sopenharmony_ci          str_curr_p = ecma_regexp_step_back (re_ctx_p, str_curr_p);
1138425bb815Sopenharmony_ci        }
1139425bb815Sopenharmony_ci
1140425bb815Sopenharmony_ci        JERRY_UNREACHABLE ();
1141425bb815Sopenharmony_ci      }
1142425bb815Sopenharmony_ci      case RE_OP_LAZY_ITERATOR:
1143425bb815Sopenharmony_ci      {
1144425bb815Sopenharmony_ci        const uint32_t qmin = re_get_value (&bc_p);
1145425bb815Sopenharmony_ci        const uint32_t qmax = re_get_value (&bc_p) - RE_QMAX_OFFSET;
1146425bb815Sopenharmony_ci        const uint32_t end_offset = re_get_value (&bc_p);
1147425bb815Sopenharmony_ci
1148425bb815Sopenharmony_ci        uint32_t iterator = 0;
1149425bb815Sopenharmony_ci        while (iterator < qmin)
1150425bb815Sopenharmony_ci        {
1151425bb815Sopenharmony_ci          str_curr_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1152425bb815Sopenharmony_ci
1153425bb815Sopenharmony_ci          if (str_curr_p == NULL)
1154425bb815Sopenharmony_ci          {
1155425bb815Sopenharmony_ci            goto fail;
1156425bb815Sopenharmony_ci          }
1157425bb815Sopenharmony_ci
1158425bb815Sopenharmony_ci          if (ECMA_RE_STACK_LIMIT_REACHED (str_curr_p))
1159425bb815Sopenharmony_ci          {
1160425bb815Sopenharmony_ci            return str_curr_p;
1161425bb815Sopenharmony_ci          }
1162425bb815Sopenharmony_ci
1163425bb815Sopenharmony_ci          iterator++;
1164425bb815Sopenharmony_ci        }
1165425bb815Sopenharmony_ci
1166425bb815Sopenharmony_ci        const uint8_t *const tail_bc_p = bc_p + end_offset;
1167425bb815Sopenharmony_ci        while (true)
1168425bb815Sopenharmony_ci        {
1169425bb815Sopenharmony_ci          const lit_utf8_byte_t *const tail_match_p = ecma_regexp_run (re_ctx_p, tail_bc_p, str_curr_p);
1170425bb815Sopenharmony_ci
1171425bb815Sopenharmony_ci          if (tail_match_p != NULL)
1172425bb815Sopenharmony_ci          {
1173425bb815Sopenharmony_ci            return tail_match_p;
1174425bb815Sopenharmony_ci          }
1175425bb815Sopenharmony_ci
1176425bb815Sopenharmony_ci          if (JERRY_UNLIKELY (iterator >= qmax))
1177425bb815Sopenharmony_ci          {
1178425bb815Sopenharmony_ci            goto fail;
1179425bb815Sopenharmony_ci          }
1180425bb815Sopenharmony_ci
1181425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1182425bb815Sopenharmony_ci
1183425bb815Sopenharmony_ci          if (matched_p == NULL)
1184425bb815Sopenharmony_ci          {
1185425bb815Sopenharmony_ci            goto fail;
1186425bb815Sopenharmony_ci          }
1187425bb815Sopenharmony_ci
1188425bb815Sopenharmony_ci          if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
1189425bb815Sopenharmony_ci          {
1190425bb815Sopenharmony_ci            return matched_p;
1191425bb815Sopenharmony_ci          }
1192425bb815Sopenharmony_ci
1193425bb815Sopenharmony_ci          iterator++;
1194425bb815Sopenharmony_ci          str_curr_p = matched_p;
1195425bb815Sopenharmony_ci        }
1196425bb815Sopenharmony_ci
1197425bb815Sopenharmony_ci        JERRY_UNREACHABLE ();
1198425bb815Sopenharmony_ci      }
1199425bb815Sopenharmony_ci      case RE_OP_BACKREFERENCE:
1200425bb815Sopenharmony_ci      {
1201425bb815Sopenharmony_ci        const uint32_t backref_idx = re_get_value (&bc_p);
1202425bb815Sopenharmony_ci        JERRY_ASSERT (backref_idx >= 1 && backref_idx < re_ctx_p->captures_count);
1203425bb815Sopenharmony_ci        const ecma_regexp_capture_t *capture_p = re_ctx_p->captures_p + backref_idx;
1204425bb815Sopenharmony_ci
1205425bb815Sopenharmony_ci        if (!ECMA_RE_IS_CAPTURE_DEFINED (capture_p) || capture_p->end_p <= capture_p->begin_p)
1206425bb815Sopenharmony_ci        {
1207425bb815Sopenharmony_ci          /* Undefined or zero length captures always match. */
1208425bb815Sopenharmony_ci          continue;
1209425bb815Sopenharmony_ci        }
1210425bb815Sopenharmony_ci
1211425bb815Sopenharmony_ci        const lit_utf8_size_t capture_size = (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p);
1212425bb815Sopenharmony_ci
1213425bb815Sopenharmony_ci        if (str_curr_p + capture_size > re_ctx_p->input_end_p
1214425bb815Sopenharmony_ci            || memcmp (str_curr_p, capture_p->begin_p, capture_size))
1215425bb815Sopenharmony_ci        {
1216425bb815Sopenharmony_ci          goto fail;
1217425bb815Sopenharmony_ci        }
1218425bb815Sopenharmony_ci
1219425bb815Sopenharmony_ci        str_curr_p += capture_size;
1220425bb815Sopenharmony_ci        continue;
1221425bb815Sopenharmony_ci      }
1222425bb815Sopenharmony_ci      case RE_OP_ASSERT_LINE_START:
1223425bb815Sopenharmony_ci      {
1224425bb815Sopenharmony_ci        if (str_curr_p <= re_ctx_p->input_start_p)
1225425bb815Sopenharmony_ci        {
1226425bb815Sopenharmony_ci          continue;
1227425bb815Sopenharmony_ci        }
1228425bb815Sopenharmony_ci
1229425bb815Sopenharmony_ci        if (!(re_ctx_p->flags & RE_FLAG_MULTILINE) || !lit_char_is_line_terminator (lit_cesu8_peek_prev (str_curr_p)))
1230425bb815Sopenharmony_ci        {
1231425bb815Sopenharmony_ci          goto fail;
1232425bb815Sopenharmony_ci        }
1233425bb815Sopenharmony_ci
1234425bb815Sopenharmony_ci        continue;
1235425bb815Sopenharmony_ci      }
1236425bb815Sopenharmony_ci      case RE_OP_ASSERT_LINE_END:
1237425bb815Sopenharmony_ci      {
1238425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p)
1239425bb815Sopenharmony_ci        {
1240425bb815Sopenharmony_ci          continue;
1241425bb815Sopenharmony_ci        }
1242425bb815Sopenharmony_ci
1243425bb815Sopenharmony_ci        if (!(re_ctx_p->flags & RE_FLAG_MULTILINE) || !lit_char_is_line_terminator (lit_cesu8_peek_next (str_curr_p)))
1244425bb815Sopenharmony_ci        {
1245425bb815Sopenharmony_ci          goto fail;
1246425bb815Sopenharmony_ci        }
1247425bb815Sopenharmony_ci
1248425bb815Sopenharmony_ci        continue;
1249425bb815Sopenharmony_ci      }
1250425bb815Sopenharmony_ci      case RE_OP_ASSERT_WORD_BOUNDARY:
1251425bb815Sopenharmony_ci      {
1252425bb815Sopenharmony_ci        const bool is_wordchar_left = ((str_curr_p > re_ctx_p->input_start_p)
1253425bb815Sopenharmony_ci                                       && lit_char_is_word_char (str_curr_p[-1]));
1254425bb815Sopenharmony_ci
1255425bb815Sopenharmony_ci        const bool is_wordchar_right = ((str_curr_p < re_ctx_p->input_end_p)
1256425bb815Sopenharmony_ci                                        && lit_char_is_word_char (str_curr_p[0]));
1257425bb815Sopenharmony_ci        if (is_wordchar_right == is_wordchar_left)
1258425bb815Sopenharmony_ci        {
1259425bb815Sopenharmony_ci          goto fail;
1260425bb815Sopenharmony_ci        }
1261425bb815Sopenharmony_ci
1262425bb815Sopenharmony_ci        continue;
1263425bb815Sopenharmony_ci      }
1264425bb815Sopenharmony_ci      case RE_OP_ASSERT_NOT_WORD_BOUNDARY:
1265425bb815Sopenharmony_ci      {
1266425bb815Sopenharmony_ci        const bool is_wordchar_left = ((str_curr_p > re_ctx_p->input_start_p)
1267425bb815Sopenharmony_ci                                       && lit_char_is_word_char (str_curr_p[-1]));
1268425bb815Sopenharmony_ci
1269425bb815Sopenharmony_ci        const bool is_wordchar_right = ((str_curr_p < re_ctx_p->input_end_p)
1270425bb815Sopenharmony_ci                                        && lit_char_is_word_char (str_curr_p[0]));
1271425bb815Sopenharmony_ci        if (is_wordchar_right != is_wordchar_left)
1272425bb815Sopenharmony_ci        {
1273425bb815Sopenharmony_ci          goto fail;
1274425bb815Sopenharmony_ci        }
1275425bb815Sopenharmony_ci
1276425bb815Sopenharmony_ci        continue;
1277425bb815Sopenharmony_ci      }
1278425bb815Sopenharmony_ci      case RE_OP_ASSERT_LOOKAHEAD_POS:
1279425bb815Sopenharmony_ci      {
1280425bb815Sopenharmony_ci        const uint8_t qmin = re_get_byte (&bc_p);
1281425bb815Sopenharmony_ci        const uint32_t capture_start = re_get_value (&bc_p);
1282425bb815Sopenharmony_ci        const uint32_t capture_count = re_get_value (&bc_p);
1283425bb815Sopenharmony_ci        const uint32_t end_offset = re_get_value (&bc_p);
1284425bb815Sopenharmony_ci
1285425bb815Sopenharmony_ci        /* If qmin is zero, the assertion implicitly matches. */
1286425bb815Sopenharmony_ci        if (qmin == 0)
1287425bb815Sopenharmony_ci        {
1288425bb815Sopenharmony_ci          bc_p += end_offset;
1289425bb815Sopenharmony_ci          continue;
1290425bb815Sopenharmony_ci        }
1291425bb815Sopenharmony_ci
1292425bb815Sopenharmony_ci        /* Capture end pointers might get clobbered and need to be restored after a tail match fail. */
1293425bb815Sopenharmony_ci        JERRY_VLA (const lit_utf8_byte_t *, saved_captures_p, capture_count);
1294425bb815Sopenharmony_ci        for (uint32_t i = 0; i < capture_count; ++i)
1295425bb815Sopenharmony_ci        {
1296425bb815Sopenharmony_ci          ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + capture_start + i;
1297425bb815Sopenharmony_ci          saved_captures_p[i] = capture_p->end_p;
1298425bb815Sopenharmony_ci        }
1299425bb815Sopenharmony_ci
1300425bb815Sopenharmony_ci        /* The first iteration will decide whether the assertion matches depending on whether
1301425bb815Sopenharmony_ci         * the iteration matched or not. */
1302425bb815Sopenharmony_ci        const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1303425bb815Sopenharmony_ci
1304425bb815Sopenharmony_ci        if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
1305425bb815Sopenharmony_ci        {
1306425bb815Sopenharmony_ci          return matched_p;
1307425bb815Sopenharmony_ci        }
1308425bb815Sopenharmony_ci
1309425bb815Sopenharmony_ci        if (matched_p == NULL)
1310425bb815Sopenharmony_ci        {
1311425bb815Sopenharmony_ci          goto fail;
1312425bb815Sopenharmony_ci        }
1313425bb815Sopenharmony_ci
1314425bb815Sopenharmony_ci        const lit_utf8_byte_t *tail_match_p = ecma_regexp_run (re_ctx_p, bc_p + end_offset, str_curr_p);
1315425bb815Sopenharmony_ci
1316425bb815Sopenharmony_ci        if (tail_match_p == NULL)
1317425bb815Sopenharmony_ci        {
1318425bb815Sopenharmony_ci          for (uint32_t i = 0; i < capture_count; ++i)
1319425bb815Sopenharmony_ci          {
1320425bb815Sopenharmony_ci            ecma_regexp_capture_t *const capture_p = re_ctx_p->captures_p + capture_start + i;
1321425bb815Sopenharmony_ci            capture_p->begin_p = NULL;
1322425bb815Sopenharmony_ci            capture_p->end_p = saved_captures_p[i];
1323425bb815Sopenharmony_ci          }
1324425bb815Sopenharmony_ci
1325425bb815Sopenharmony_ci          goto fail;
1326425bb815Sopenharmony_ci        }
1327425bb815Sopenharmony_ci
1328425bb815Sopenharmony_ci        return tail_match_p;
1329425bb815Sopenharmony_ci      }
1330425bb815Sopenharmony_ci      case RE_OP_ASSERT_LOOKAHEAD_NEG:
1331425bb815Sopenharmony_ci      {
1332425bb815Sopenharmony_ci        const uint8_t qmin = re_get_byte (&bc_p);
1333425bb815Sopenharmony_ci        uint32_t capture_idx = re_get_value (&bc_p);
1334425bb815Sopenharmony_ci        const uint32_t capture_count = re_get_value (&bc_p);
1335425bb815Sopenharmony_ci        const uint32_t end_offset = re_get_value (&bc_p);
1336425bb815Sopenharmony_ci
1337425bb815Sopenharmony_ci        /* If qmin is zero, the assertion implicitly matches. */
1338425bb815Sopenharmony_ci        if (qmin > 0)
1339425bb815Sopenharmony_ci        {
1340425bb815Sopenharmony_ci          /* The first iteration will decide whether the assertion matches depending on whether
1341425bb815Sopenharmony_ci           * the iteration matched or not. */
1342425bb815Sopenharmony_ci          const lit_utf8_byte_t *const matched_p = ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1343425bb815Sopenharmony_ci
1344425bb815Sopenharmony_ci          if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
1345425bb815Sopenharmony_ci          {
1346425bb815Sopenharmony_ci            return matched_p;
1347425bb815Sopenharmony_ci          }
1348425bb815Sopenharmony_ci
1349425bb815Sopenharmony_ci          if (matched_p != NULL)
1350425bb815Sopenharmony_ci          {
1351425bb815Sopenharmony_ci            /* Nested capturing groups inside a negative lookahead can never capture, so we clear their results. */
1352425bb815Sopenharmony_ci            const uint32_t capture_end = capture_idx + capture_count;
1353425bb815Sopenharmony_ci            while (capture_idx < capture_end)
1354425bb815Sopenharmony_ci            {
1355425bb815Sopenharmony_ci              re_ctx_p->captures_p[capture_idx++].begin_p = NULL;
1356425bb815Sopenharmony_ci            }
1357425bb815Sopenharmony_ci
1358425bb815Sopenharmony_ci            goto fail;
1359425bb815Sopenharmony_ci          }
1360425bb815Sopenharmony_ci        }
1361425bb815Sopenharmony_ci
1362425bb815Sopenharmony_ci        bc_p += end_offset;
1363425bb815Sopenharmony_ci        continue;
1364425bb815Sopenharmony_ci      }
1365425bb815Sopenharmony_ci      case RE_OP_CLASS_ESCAPE:
1366425bb815Sopenharmony_ci      {
1367425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p)
1368425bb815Sopenharmony_ci        {
1369425bb815Sopenharmony_ci          goto fail;
1370425bb815Sopenharmony_ci        }
1371425bb815Sopenharmony_ci
1372425bb815Sopenharmony_ci        const lit_code_point_t cp = ecma_regexp_advance (re_ctx_p, &str_curr_p);
1373425bb815Sopenharmony_ci
1374425bb815Sopenharmony_ci        const ecma_class_escape_t escape = (ecma_class_escape_t) re_get_byte (&bc_p);
1375425bb815Sopenharmony_ci        if (!ecma_regexp_check_class_escape (cp, escape))
1376425bb815Sopenharmony_ci        {
1377425bb815Sopenharmony_ci          goto fail;
1378425bb815Sopenharmony_ci        }
1379425bb815Sopenharmony_ci
1380425bb815Sopenharmony_ci        continue;
1381425bb815Sopenharmony_ci      }
1382425bb815Sopenharmony_ci      case RE_OP_CHAR_CLASS:
1383425bb815Sopenharmony_ci      {
1384425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p)
1385425bb815Sopenharmony_ci        {
1386425bb815Sopenharmony_ci          goto fail;
1387425bb815Sopenharmony_ci        }
1388425bb815Sopenharmony_ci
1389425bb815Sopenharmony_ci        uint8_t flags = re_get_byte (&bc_p);
1390425bb815Sopenharmony_ci        uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bc_p) : 0;
1391425bb815Sopenharmony_ci        uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bc_p) : 0;
1392425bb815Sopenharmony_ci
1393425bb815Sopenharmony_ci        const lit_code_point_t cp = ecma_regexp_advance (re_ctx_p, &str_curr_p);
1394425bb815Sopenharmony_ci
1395425bb815Sopenharmony_ci        uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK;
1396425bb815Sopenharmony_ci        while (escape_count > 0)
1397425bb815Sopenharmony_ci        {
1398425bb815Sopenharmony_ci          escape_count--;
1399425bb815Sopenharmony_ci          const ecma_class_escape_t escape = re_get_byte (&bc_p);
1400425bb815Sopenharmony_ci          if (ecma_regexp_check_class_escape (cp, escape))
1401425bb815Sopenharmony_ci          {
1402425bb815Sopenharmony_ci            goto class_found;
1403425bb815Sopenharmony_ci          }
1404425bb815Sopenharmony_ci        }
1405425bb815Sopenharmony_ci
1406425bb815Sopenharmony_ci        while (char_count > 0)
1407425bb815Sopenharmony_ci        {
1408425bb815Sopenharmony_ci          char_count--;
1409425bb815Sopenharmony_ci          const lit_code_point_t curr = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE);
1410425bb815Sopenharmony_ci          if (cp == curr)
1411425bb815Sopenharmony_ci          {
1412425bb815Sopenharmony_ci            goto class_found;
1413425bb815Sopenharmony_ci          }
1414425bb815Sopenharmony_ci        }
1415425bb815Sopenharmony_ci
1416425bb815Sopenharmony_ci        while (range_count > 0)
1417425bb815Sopenharmony_ci        {
1418425bb815Sopenharmony_ci          range_count--;
1419425bb815Sopenharmony_ci          const lit_code_point_t begin = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE);
1420425bb815Sopenharmony_ci
1421425bb815Sopenharmony_ci          if (cp < begin)
1422425bb815Sopenharmony_ci          {
1423425bb815Sopenharmony_ci            bc_p += re_ctx_p->char_size;
1424425bb815Sopenharmony_ci            continue;
1425425bb815Sopenharmony_ci          }
1426425bb815Sopenharmony_ci
1427425bb815Sopenharmony_ci          const lit_code_point_t end = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE);
1428425bb815Sopenharmony_ci          if (cp <= end)
1429425bb815Sopenharmony_ci          {
1430425bb815Sopenharmony_ci            goto class_found;
1431425bb815Sopenharmony_ci          }
1432425bb815Sopenharmony_ci        }
1433425bb815Sopenharmony_ci
1434425bb815Sopenharmony_ci        /* Not found */
1435425bb815Sopenharmony_ci        if (flags & RE_CLASS_INVERT)
1436425bb815Sopenharmony_ci        {
1437425bb815Sopenharmony_ci          continue;
1438425bb815Sopenharmony_ci        }
1439425bb815Sopenharmony_ci
1440425bb815Sopenharmony_ci        goto fail;
1441425bb815Sopenharmony_ci
1442425bb815Sopenharmony_ciclass_found:
1443425bb815Sopenharmony_ci        if (flags & RE_CLASS_INVERT)
1444425bb815Sopenharmony_ci        {
1445425bb815Sopenharmony_ci          goto fail;
1446425bb815Sopenharmony_ci        }
1447425bb815Sopenharmony_ci
1448425bb815Sopenharmony_ci        const uint32_t chars_size = char_count * re_ctx_p->char_size;
1449425bb815Sopenharmony_ci        const uint32_t ranges_size = range_count * re_ctx_p->char_size * 2;
1450425bb815Sopenharmony_ci        bc_p = bc_p + escape_count + chars_size + ranges_size;
1451425bb815Sopenharmony_ci        continue;
1452425bb815Sopenharmony_ci      }
1453425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1454425bb815Sopenharmony_ci      case RE_OP_UNICODE_PERIOD:
1455425bb815Sopenharmony_ci      {
1456425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p)
1457425bb815Sopenharmony_ci        {
1458425bb815Sopenharmony_ci          goto fail;
1459425bb815Sopenharmony_ci        }
1460425bb815Sopenharmony_ci
1461425bb815Sopenharmony_ci        const lit_code_point_t cp = ecma_regexp_unicode_advance (&str_curr_p, re_ctx_p->input_end_p);
1462425bb815Sopenharmony_ci
1463425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (cp <= LIT_UTF16_CODE_UNIT_MAX && lit_char_is_line_terminator ((ecma_char_t) cp)))
1464425bb815Sopenharmony_ci        {
1465425bb815Sopenharmony_ci          goto fail;
1466425bb815Sopenharmony_ci        }
1467425bb815Sopenharmony_ci
1468425bb815Sopenharmony_ci        continue;
1469425bb815Sopenharmony_ci      }
1470425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1471425bb815Sopenharmony_ci      case RE_OP_PERIOD:
1472425bb815Sopenharmony_ci      {
1473425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p)
1474425bb815Sopenharmony_ci        {
1475425bb815Sopenharmony_ci          goto fail;
1476425bb815Sopenharmony_ci        }
1477425bb815Sopenharmony_ci
1478425bb815Sopenharmony_ci        const ecma_char_t ch = lit_cesu8_read_next (&str_curr_p);
1479425bb815Sopenharmony_ci
1480425bb815Sopenharmony_ci        if (lit_char_is_line_terminator (ch))
1481425bb815Sopenharmony_ci        {
1482425bb815Sopenharmony_ci          goto fail;
1483425bb815Sopenharmony_ci        }
1484425bb815Sopenharmony_ci
1485425bb815Sopenharmony_ci        continue;
1486425bb815Sopenharmony_ci      }
1487425bb815Sopenharmony_ci      case RE_OP_CHAR:
1488425bb815Sopenharmony_ci      {
1489425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p)
1490425bb815Sopenharmony_ci        {
1491425bb815Sopenharmony_ci          goto fail;
1492425bb815Sopenharmony_ci        }
1493425bb815Sopenharmony_ci
1494425bb815Sopenharmony_ci        const lit_code_point_t ch1 = re_get_char (&bc_p, re_ctx_p->flags & RE_FLAG_UNICODE);
1495425bb815Sopenharmony_ci        const lit_code_point_t ch2 = ecma_regexp_advance (re_ctx_p, &str_curr_p);
1496425bb815Sopenharmony_ci
1497425bb815Sopenharmony_ci        if (ch1 != ch2)
1498425bb815Sopenharmony_ci        {
1499425bb815Sopenharmony_ci          goto fail;
1500425bb815Sopenharmony_ci        }
1501425bb815Sopenharmony_ci
1502425bb815Sopenharmony_ci        continue;
1503425bb815Sopenharmony_ci      }
1504425bb815Sopenharmony_ci      default:
1505425bb815Sopenharmony_ci      {
1506425bb815Sopenharmony_ci        JERRY_ASSERT (op == RE_OP_BYTE);
1507425bb815Sopenharmony_ci
1508425bb815Sopenharmony_ci        if (str_curr_p >= re_ctx_p->input_end_p
1509425bb815Sopenharmony_ci            || *bc_p++ != *str_curr_p++)
1510425bb815Sopenharmony_ci        {
1511425bb815Sopenharmony_ci          goto fail;
1512425bb815Sopenharmony_ci        }
1513425bb815Sopenharmony_ci
1514425bb815Sopenharmony_ci        continue;
1515425bb815Sopenharmony_ci      }
1516425bb815Sopenharmony_ci    }
1517425bb815Sopenharmony_ci
1518425bb815Sopenharmony_ci    JERRY_UNREACHABLE ();
1519425bb815Sopenharmony_cifail:
1520425bb815Sopenharmony_ci    bc_p = next_alternative_p;
1521425bb815Sopenharmony_ci
1522425bb815Sopenharmony_ci    if (bc_p == NULL || *bc_p++ != RE_OP_ALTERNATIVE_NEXT)
1523425bb815Sopenharmony_ci    {
1524425bb815Sopenharmony_ci      /* None of the alternatives matched. */
1525425bb815Sopenharmony_ci      return NULL;
1526425bb815Sopenharmony_ci    }
1527425bb815Sopenharmony_ci
1528425bb815Sopenharmony_ci    /* Get the end of the new alternative and continue execution. */
1529425bb815Sopenharmony_ci    str_curr_p = str_start_p;
1530425bb815Sopenharmony_ci    const uint32_t offset = re_get_value (&bc_p);
1531425bb815Sopenharmony_ci    next_alternative_p = bc_p + offset;
1532425bb815Sopenharmony_ci  }
1533425bb815Sopenharmony_ci} /* ecma_regexp_run */
1534425bb815Sopenharmony_ci
1535425bb815Sopenharmony_ci/**
1536425bb815Sopenharmony_ci * Match a RegExp at a specific position in the input string.
1537425bb815Sopenharmony_ci *
1538425bb815Sopenharmony_ci * @return pointer to the end of the matched sub-string
1539425bb815Sopenharmony_ci *         NULL, if pattern did not match
1540425bb815Sopenharmony_ci */
1541425bb815Sopenharmony_cistatic const lit_utf8_byte_t *
1542425bb815Sopenharmony_ciecma_regexp_match (ecma_regexp_ctx_t *re_ctx_p, /**< RegExp matcher context */
1543425bb815Sopenharmony_ci                   const uint8_t *bc_p, /**< pointer to the current RegExp bytecode */
1544425bb815Sopenharmony_ci                   const lit_utf8_byte_t *str_curr_p) /**< input string pointer */
1545425bb815Sopenharmony_ci{
1546425bb815Sopenharmony_ci  re_ctx_p->captures_p[RE_GLOBAL_CAPTURE].begin_p = str_curr_p;
1547425bb815Sopenharmony_ci
1548425bb815Sopenharmony_ci  for (uint32_t i = 1; i < re_ctx_p->captures_count; ++i)
1549425bb815Sopenharmony_ci  {
1550425bb815Sopenharmony_ci    re_ctx_p->captures_p[i].begin_p = NULL;
1551425bb815Sopenharmony_ci  }
1552425bb815Sopenharmony_ci
1553425bb815Sopenharmony_ci  return ecma_regexp_run (re_ctx_p, bc_p, str_curr_p);
1554425bb815Sopenharmony_ci} /* ecma_regexp_match */
1555425bb815Sopenharmony_ci
1556425bb815Sopenharmony_ci/*
1557425bb815Sopenharmony_ci * Helper function to get the result of a capture
1558425bb815Sopenharmony_ci *
1559425bb815Sopenharmony_ci * @return string value, if capture is defined
1560425bb815Sopenharmony_ci *         undefined, otherwise
1561425bb815Sopenharmony_ci */
1562425bb815Sopenharmony_ciecma_value_t
1563425bb815Sopenharmony_ciecma_regexp_get_capture_value (const ecma_regexp_capture_t *const capture_p) /**< capture */
1564425bb815Sopenharmony_ci{
1565425bb815Sopenharmony_ci  if (ECMA_RE_IS_CAPTURE_DEFINED (capture_p))
1566425bb815Sopenharmony_ci  {
1567425bb815Sopenharmony_ci    JERRY_ASSERT (capture_p->end_p >= capture_p->begin_p);
1568425bb815Sopenharmony_ci    const lit_utf8_size_t capture_size = (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p);
1569425bb815Sopenharmony_ci    ecma_string_t *const capture_str_p = ecma_new_ecma_string_from_utf8 (capture_p->begin_p, capture_size);
1570425bb815Sopenharmony_ci    return ecma_make_string_value (capture_str_p);
1571425bb815Sopenharmony_ci  }
1572425bb815Sopenharmony_ci
1573425bb815Sopenharmony_ci  return ECMA_VALUE_UNDEFINED;
1574425bb815Sopenharmony_ci} /* ecma_regexp_get_capture_value */
1575425bb815Sopenharmony_ci
1576425bb815Sopenharmony_ci/**
1577425bb815Sopenharmony_ci * Helper function to create a result array from the captures in a regexp context
1578425bb815Sopenharmony_ci *
1579425bb815Sopenharmony_ci * @return ecma value containing the created array object
1580425bb815Sopenharmony_ci */
1581425bb815Sopenharmony_cistatic ecma_value_t
1582425bb815Sopenharmony_ciecma_regexp_create_result_object (ecma_regexp_ctx_t *re_ctx_p, /**< regexp context */
1583425bb815Sopenharmony_ci                                  ecma_string_t *input_string_p, /**< input ecma string */
1584425bb815Sopenharmony_ci                                  uint32_t index) /**< match index */
1585425bb815Sopenharmony_ci{
1586425bb815Sopenharmony_ci  ecma_value_t result_array = ecma_op_create_array_object (0, 0, false);
1587425bb815Sopenharmony_ci  ecma_object_t *result_p = ecma_get_object_from_value (result_array);
1588425bb815Sopenharmony_ci
1589425bb815Sopenharmony_ci  for (uint32_t i = 0; i < re_ctx_p->captures_count; i++)
1590425bb815Sopenharmony_ci  {
1591425bb815Sopenharmony_ci    ecma_value_t capture_value = ecma_regexp_get_capture_value (re_ctx_p->captures_p + i);
1592425bb815Sopenharmony_ci    ecma_builtin_helper_def_prop_by_index (result_p,
1593425bb815Sopenharmony_ci                                           i,
1594425bb815Sopenharmony_ci                                           capture_value,
1595425bb815Sopenharmony_ci                                           ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
1596425bb815Sopenharmony_ci    ecma_free_value (capture_value);
1597425bb815Sopenharmony_ci  }
1598425bb815Sopenharmony_ci
1599425bb815Sopenharmony_ci  ecma_builtin_helper_def_prop (result_p,
1600425bb815Sopenharmony_ci                                ecma_get_magic_string (LIT_MAGIC_STRING_INDEX),
1601425bb815Sopenharmony_ci                                ecma_make_uint32_value (index),
1602425bb815Sopenharmony_ci                                ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
1603425bb815Sopenharmony_ci
1604425bb815Sopenharmony_ci  ecma_builtin_helper_def_prop (result_p,
1605425bb815Sopenharmony_ci                                ecma_get_magic_string (LIT_MAGIC_STRING_INPUT),
1606425bb815Sopenharmony_ci                                ecma_make_string_value (input_string_p),
1607425bb815Sopenharmony_ci                                ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
1608425bb815Sopenharmony_ci
1609425bb815Sopenharmony_ci  return result_array;
1610425bb815Sopenharmony_ci} /* ecma_regexp_create_result_object */
1611425bb815Sopenharmony_ci
1612425bb815Sopenharmony_ci/**
1613425bb815Sopenharmony_ci * Helper function to initialize a regexp match context
1614425bb815Sopenharmony_ci */
1615425bb815Sopenharmony_cistatic void
1616425bb815Sopenharmony_ciecma_regexp_initialize_context (ecma_regexp_ctx_t *ctx_p, /**< regexp context */
1617425bb815Sopenharmony_ci                                const re_compiled_code_t *bc_p, /**< regexp bytecode */
1618425bb815Sopenharmony_ci                                const lit_utf8_byte_t *input_start_p, /**< pointer to input string */
1619425bb815Sopenharmony_ci                                const lit_utf8_byte_t *input_end_p) /**< pointer to end of input string */
1620425bb815Sopenharmony_ci{
1621425bb815Sopenharmony_ci  JERRY_ASSERT (ctx_p != NULL);
1622425bb815Sopenharmony_ci  JERRY_ASSERT (bc_p != NULL);
1623425bb815Sopenharmony_ci  JERRY_ASSERT (input_start_p != NULL);
1624425bb815Sopenharmony_ci  JERRY_ASSERT (input_end_p >= input_start_p);
1625425bb815Sopenharmony_ci
1626425bb815Sopenharmony_ci  ctx_p->flags = bc_p->header.status_flags;
1627425bb815Sopenharmony_ci  ctx_p->char_size = (ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t);
1628425bb815Sopenharmony_ci
1629425bb815Sopenharmony_ci  ctx_p->input_start_p = input_start_p;
1630425bb815Sopenharmony_ci  ctx_p->input_end_p = input_end_p;
1631425bb815Sopenharmony_ci
1632425bb815Sopenharmony_ci  ctx_p->captures_count = bc_p->captures_count;
1633425bb815Sopenharmony_ci  ctx_p->non_captures_count = bc_p->non_captures_count;
1634425bb815Sopenharmony_ci
1635425bb815Sopenharmony_ci  ctx_p->captures_p = jmem_heap_alloc_block (ctx_p->captures_count * sizeof (ecma_regexp_capture_t));
1636425bb815Sopenharmony_ci
1637425bb815Sopenharmony_ci  if (ctx_p->non_captures_count > 0)
1638425bb815Sopenharmony_ci  {
1639425bb815Sopenharmony_ci    ctx_p->non_captures_p = jmem_heap_alloc_block (ctx_p->non_captures_count * sizeof (ecma_regexp_non_capture_t));
1640425bb815Sopenharmony_ci  }
1641425bb815Sopenharmony_ci} /* ecma_regexp_initialize_context */
1642425bb815Sopenharmony_ci
1643425bb815Sopenharmony_ci/**
1644425bb815Sopenharmony_ci * Helper function to clean up a regexp context
1645425bb815Sopenharmony_ci */
1646425bb815Sopenharmony_cistatic void
1647425bb815Sopenharmony_ciecma_regexp_cleanup_context (ecma_regexp_ctx_t *ctx_p) /**< regexp context */
1648425bb815Sopenharmony_ci{
1649425bb815Sopenharmony_ci  JERRY_ASSERT (ctx_p != NULL);
1650425bb815Sopenharmony_ci  jmem_heap_free_block (ctx_p->captures_p, ctx_p->captures_count * sizeof (ecma_regexp_capture_t));
1651425bb815Sopenharmony_ci
1652425bb815Sopenharmony_ci  if (ctx_p->non_captures_count > 0)
1653425bb815Sopenharmony_ci  {
1654425bb815Sopenharmony_ci    jmem_heap_free_block (ctx_p->non_captures_p, ctx_p->non_captures_count * sizeof (ecma_regexp_non_capture_t));
1655425bb815Sopenharmony_ci  }
1656425bb815Sopenharmony_ci} /* ecma_regexp_cleanup_context */
1657425bb815Sopenharmony_ci
1658425bb815Sopenharmony_ci/**
1659425bb815Sopenharmony_ci * RegExp helper function to start the recursive matching algorithm
1660425bb815Sopenharmony_ci * and create the result Array object
1661425bb815Sopenharmony_ci *
1662425bb815Sopenharmony_ci * See also:
1663425bb815Sopenharmony_ci *          ECMA-262 v5, 15.10.6.2
1664425bb815Sopenharmony_ci *
1665425bb815Sopenharmony_ci * @return array object - if matched
1666425bb815Sopenharmony_ci *         null         - otherwise
1667425bb815Sopenharmony_ci *
1668425bb815Sopenharmony_ci *         May raise error.
1669425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value
1670425bb815Sopenharmony_ci */
1671425bb815Sopenharmony_ciecma_value_t
1672425bb815Sopenharmony_ciecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */
1673425bb815Sopenharmony_ci                         ecma_string_t *input_string_p) /**< input string */
1674425bb815Sopenharmony_ci{
1675425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
1676425bb815Sopenharmony_ci
1677425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_object_is_regexp_object (ecma_make_object_value (regexp_object_p)));
1678425bb815Sopenharmony_ci
1679425bb815Sopenharmony_ci  ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) regexp_object_p;
1680425bb815Sopenharmony_ci  re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
1681425bb815Sopenharmony_ci                                                                  ext_object_p->u.class_prop.u.value);
1682425bb815Sopenharmony_ci
1683425bb815Sopenharmony_ci  lit_utf8_size_t input_size;
1684425bb815Sopenharmony_ci  lit_utf8_size_t input_length;
1685425bb815Sopenharmony_ci  uint8_t input_flags = ECMA_STRING_FLAG_IS_ASCII;
1686425bb815Sopenharmony_ci  const lit_utf8_byte_t *input_buffer_p = ecma_string_get_chars (input_string_p,
1687425bb815Sopenharmony_ci                                                                 &input_size,
1688425bb815Sopenharmony_ci                                                                 &input_length,
1689425bb815Sopenharmony_ci                                                                 NULL,
1690425bb815Sopenharmony_ci                                                                 &input_flags);
1691425bb815Sopenharmony_ci
1692425bb815Sopenharmony_ci  const lit_utf8_byte_t *input_curr_p = input_buffer_p;
1693425bb815Sopenharmony_ci  uint32_t index = 0;
1694425bb815Sopenharmony_ci  if (bc_p->header.status_flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY))
1695425bb815Sopenharmony_ci  {
1696425bb815Sopenharmony_ci    ecma_string_t *lastindex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);
1697425bb815Sopenharmony_ci    ecma_value_t lastindex_value = ecma_op_object_get_own_data_prop (regexp_object_p, lastindex_str_p);
1698425bb815Sopenharmony_ci
1699425bb815Sopenharmony_ci    ecma_number_t lastindex_num;
1700425bb815Sopenharmony_ci    ret_value = ecma_op_to_integer (lastindex_value, &lastindex_num);
1701425bb815Sopenharmony_ci
1702425bb815Sopenharmony_ci    ecma_free_value (lastindex_value);
1703425bb815Sopenharmony_ci
1704425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (ret_value))
1705425bb815Sopenharmony_ci    {
1706425bb815Sopenharmony_ci      goto cleanup_string;
1707425bb815Sopenharmony_ci    }
1708425bb815Sopenharmony_ci
1709425bb815Sopenharmony_ci    /* TODO: Replace with ToLength */
1710425bb815Sopenharmony_ci    if (lastindex_num < 0.0f)
1711425bb815Sopenharmony_ci    {
1712425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1713425bb815Sopenharmony_ci      lastindex_num = 0.0f;
1714425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
1715425bb815Sopenharmony_ci      lastindex_num = input_length + 1;
1716425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1717425bb815Sopenharmony_ci    }
1718425bb815Sopenharmony_ci    index = ecma_number_to_uint32 (lastindex_num);
1719425bb815Sopenharmony_ci
1720425bb815Sopenharmony_ci    if (index > input_length)
1721425bb815Sopenharmony_ci    {
1722425bb815Sopenharmony_ci      ret_value = ecma_op_object_put (regexp_object_p,
1723425bb815Sopenharmony_ci                                      lastindex_str_p,
1724425bb815Sopenharmony_ci                                      ecma_make_integer_value (0),
1725425bb815Sopenharmony_ci                                      true);
1726425bb815Sopenharmony_ci
1727425bb815Sopenharmony_ci      if (!ECMA_IS_VALUE_ERROR (ret_value))
1728425bb815Sopenharmony_ci      {
1729425bb815Sopenharmony_ci        JERRY_ASSERT (ecma_is_value_boolean (ret_value));
1730425bb815Sopenharmony_ci        /* lastIndex is out of bounds, the match should fail. */
1731425bb815Sopenharmony_ci        ret_value = ECMA_VALUE_NULL;
1732425bb815Sopenharmony_ci      }
1733425bb815Sopenharmony_ci
1734425bb815Sopenharmony_ci      goto cleanup_string;
1735425bb815Sopenharmony_ci    }
1736425bb815Sopenharmony_ci
1737425bb815Sopenharmony_ci    if (index > 0)
1738425bb815Sopenharmony_ci    {
1739425bb815Sopenharmony_ci      if (input_flags & ECMA_STRING_FLAG_IS_ASCII)
1740425bb815Sopenharmony_ci      {
1741425bb815Sopenharmony_ci        input_curr_p += index;
1742425bb815Sopenharmony_ci      }
1743425bb815Sopenharmony_ci      else
1744425bb815Sopenharmony_ci      {
1745425bb815Sopenharmony_ci        for (uint32_t i = 0; i < index; i++)
1746425bb815Sopenharmony_ci        {
1747425bb815Sopenharmony_ci          lit_utf8_incr (&input_curr_p);
1748425bb815Sopenharmony_ci        }
1749425bb815Sopenharmony_ci      }
1750425bb815Sopenharmony_ci    }
1751425bb815Sopenharmony_ci  }
1752425bb815Sopenharmony_ci
1753425bb815Sopenharmony_ci  const lit_utf8_byte_t *input_end_p = input_buffer_p + input_size;
1754425bb815Sopenharmony_ci  ecma_regexp_ctx_t re_ctx;
1755425bb815Sopenharmony_ci  ecma_regexp_initialize_context (&re_ctx,
1756425bb815Sopenharmony_ci                                  bc_p,
1757425bb815Sopenharmony_ci                                  input_buffer_p,
1758425bb815Sopenharmony_ci                                  input_end_p);
1759425bb815Sopenharmony_ci
1760425bb815Sopenharmony_ci  /* 2. Try to match */
1761425bb815Sopenharmony_ci  uint8_t *bc_start_p = (uint8_t *) (bc_p + 1);
1762425bb815Sopenharmony_ci  const lit_utf8_byte_t *matched_p = NULL;
1763425bb815Sopenharmony_ci
1764425bb815Sopenharmony_ci  JERRY_ASSERT (index <= input_length);
1765425bb815Sopenharmony_ci  while (true)
1766425bb815Sopenharmony_ci  {
1767425bb815Sopenharmony_ci    matched_p = ecma_regexp_match (&re_ctx, bc_start_p, input_curr_p);
1768425bb815Sopenharmony_ci
1769425bb815Sopenharmony_ci    if (matched_p != NULL)
1770425bb815Sopenharmony_ci    {
1771425bb815Sopenharmony_ci      break;
1772425bb815Sopenharmony_ci    }
1773425bb815Sopenharmony_ci
1774425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1775425bb815Sopenharmony_ci    if (re_ctx.flags & RE_FLAG_STICKY)
1776425bb815Sopenharmony_ci    {
1777425bb815Sopenharmony_ci      ecma_value_t put_result = ecma_op_object_put (regexp_object_p,
1778425bb815Sopenharmony_ci                                                    ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
1779425bb815Sopenharmony_ci                                                    ecma_make_uint32_value (0),
1780425bb815Sopenharmony_ci                                                    true);
1781425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (put_result))
1782425bb815Sopenharmony_ci      {
1783425bb815Sopenharmony_ci        ret_value = put_result;
1784425bb815Sopenharmony_ci        goto cleanup_context;
1785425bb815Sopenharmony_ci      }
1786425bb815Sopenharmony_ci
1787425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_boolean (put_result));
1788425bb815Sopenharmony_ci      ret_value = ECMA_VALUE_NULL;
1789425bb815Sopenharmony_ci      goto cleanup_context;
1790425bb815Sopenharmony_ci    }
1791425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1792425bb815Sopenharmony_ci
1793425bb815Sopenharmony_ci    if (input_curr_p >= input_end_p)
1794425bb815Sopenharmony_ci    {
1795425bb815Sopenharmony_ci      if (re_ctx.flags & RE_FLAG_GLOBAL)
1796425bb815Sopenharmony_ci      {
1797425bb815Sopenharmony_ci        ecma_value_t put_result = ecma_op_object_put (regexp_object_p,
1798425bb815Sopenharmony_ci                                                      ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
1799425bb815Sopenharmony_ci                                                      ecma_make_uint32_value (0),
1800425bb815Sopenharmony_ci                                                      true);
1801425bb815Sopenharmony_ci        if (ECMA_IS_VALUE_ERROR (put_result))
1802425bb815Sopenharmony_ci        {
1803425bb815Sopenharmony_ci          ret_value = put_result;
1804425bb815Sopenharmony_ci          goto cleanup_context;
1805425bb815Sopenharmony_ci        }
1806425bb815Sopenharmony_ci
1807425bb815Sopenharmony_ci        JERRY_ASSERT (ecma_is_value_boolean (put_result));
1808425bb815Sopenharmony_ci      }
1809425bb815Sopenharmony_ci
1810425bb815Sopenharmony_ci      /* Failed to match, return 'null'. */
1811425bb815Sopenharmony_ci      ret_value = ECMA_VALUE_NULL;
1812425bb815Sopenharmony_ci      goto cleanup_context;
1813425bb815Sopenharmony_ci    }
1814425bb815Sopenharmony_ci
1815425bb815Sopenharmony_ci    JERRY_ASSERT (input_curr_p < input_end_p);
1816425bb815Sopenharmony_ci
1817425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1818425bb815Sopenharmony_ci    if (re_ctx.flags & RE_FLAG_UNICODE)
1819425bb815Sopenharmony_ci    {
1820425bb815Sopenharmony_ci      index++;
1821425bb815Sopenharmony_ci      const lit_code_point_t cp = ecma_regexp_unicode_advance (&input_curr_p,
1822425bb815Sopenharmony_ci                                                               input_end_p);
1823425bb815Sopenharmony_ci
1824425bb815Sopenharmony_ci      if (cp > LIT_UTF16_CODE_UNIT_MAX)
1825425bb815Sopenharmony_ci      {
1826425bb815Sopenharmony_ci        index++;
1827425bb815Sopenharmony_ci      }
1828425bb815Sopenharmony_ci
1829425bb815Sopenharmony_ci      continue;
1830425bb815Sopenharmony_ci    }
1831425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1832425bb815Sopenharmony_ci
1833425bb815Sopenharmony_ci    index++;
1834425bb815Sopenharmony_ci    lit_utf8_incr (&input_curr_p);
1835425bb815Sopenharmony_ci  }
1836425bb815Sopenharmony_ci
1837425bb815Sopenharmony_ci  JERRY_ASSERT (matched_p != NULL);
1838425bb815Sopenharmony_ci
1839425bb815Sopenharmony_ci  if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
1840425bb815Sopenharmony_ci  {
1841425bb815Sopenharmony_ci    ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Stack limit exceeded."));
1842425bb815Sopenharmony_ci    goto cleanup_context;
1843425bb815Sopenharmony_ci  }
1844425bb815Sopenharmony_ci
1845425bb815Sopenharmony_ci  if (re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY))
1846425bb815Sopenharmony_ci  {
1847425bb815Sopenharmony_ci    JERRY_ASSERT (index <= input_length);
1848425bb815Sopenharmony_ci
1849425bb815Sopenharmony_ci    lit_utf8_size_t match_length;
1850425bb815Sopenharmony_ci    const lit_utf8_byte_t *match_begin_p = re_ctx.captures_p[0].begin_p;
1851425bb815Sopenharmony_ci    const lit_utf8_byte_t *match_end_p = re_ctx.captures_p[0].end_p;
1852425bb815Sopenharmony_ci
1853425bb815Sopenharmony_ci    if (input_flags & ECMA_STRING_FLAG_IS_ASCII)
1854425bb815Sopenharmony_ci    {
1855425bb815Sopenharmony_ci      match_length = (lit_utf8_size_t) (match_end_p - match_begin_p);
1856425bb815Sopenharmony_ci    }
1857425bb815Sopenharmony_ci    else
1858425bb815Sopenharmony_ci    {
1859425bb815Sopenharmony_ci      match_length = lit_utf8_string_length (match_begin_p,
1860425bb815Sopenharmony_ci                                             (lit_utf8_size_t) (match_end_p - match_begin_p));
1861425bb815Sopenharmony_ci    }
1862425bb815Sopenharmony_ci
1863425bb815Sopenharmony_ci    ecma_value_t put_result = ecma_op_object_put (regexp_object_p,
1864425bb815Sopenharmony_ci                                                  ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
1865425bb815Sopenharmony_ci                                                  ecma_make_uint32_value (index + match_length),
1866425bb815Sopenharmony_ci                                                  true);
1867425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (put_result))
1868425bb815Sopenharmony_ci    {
1869425bb815Sopenharmony_ci      ret_value = put_result;
1870425bb815Sopenharmony_ci      goto cleanup_context;
1871425bb815Sopenharmony_ci    }
1872425bb815Sopenharmony_ci
1873425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_boolean (put_result));
1874425bb815Sopenharmony_ci  }
1875425bb815Sopenharmony_ci
1876425bb815Sopenharmony_ci  ret_value = ecma_regexp_create_result_object (&re_ctx, input_string_p, index);
1877425bb815Sopenharmony_ci
1878425bb815Sopenharmony_cicleanup_context:
1879425bb815Sopenharmony_ci  ecma_regexp_cleanup_context (&re_ctx);
1880425bb815Sopenharmony_ci
1881425bb815Sopenharmony_cicleanup_string:
1882425bb815Sopenharmony_ci  if (input_flags & ECMA_STRING_FLAG_MUST_BE_FREED)
1883425bb815Sopenharmony_ci  {
1884425bb815Sopenharmony_ci    jmem_heap_free_block ((void *) input_buffer_p, input_size);
1885425bb815Sopenharmony_ci  }
1886425bb815Sopenharmony_ci
1887425bb815Sopenharmony_ci  return ret_value;
1888425bb815Sopenharmony_ci} /* ecma_regexp_exec_helper */
1889425bb815Sopenharmony_ci
1890425bb815Sopenharmony_ci/**
1891425bb815Sopenharmony_ci * Helper function for converting a RegExp pattern parameter to string.
1892425bb815Sopenharmony_ci *
1893425bb815Sopenharmony_ci * See also:
1894425bb815Sopenharmony_ci *         RegExp.compile
1895425bb815Sopenharmony_ci *         RegExp dispatch call
1896425bb815Sopenharmony_ci *
1897425bb815Sopenharmony_ci * @return empty value if success, error value otherwise
1898425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
1899425bb815Sopenharmony_ci */
1900425bb815Sopenharmony_ciecma_string_t *
1901425bb815Sopenharmony_ciecma_regexp_read_pattern_str_helper (ecma_value_t pattern_arg) /**< the RegExp pattern */
1902425bb815Sopenharmony_ci{
1903425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (pattern_arg))
1904425bb815Sopenharmony_ci  {
1905425bb815Sopenharmony_ci    ecma_string_t *pattern_string_p = ecma_op_to_string (pattern_arg);
1906425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (pattern_string_p == NULL) || !ecma_string_is_empty (pattern_string_p))
1907425bb815Sopenharmony_ci    {
1908425bb815Sopenharmony_ci      return pattern_string_p;
1909425bb815Sopenharmony_ci    }
1910425bb815Sopenharmony_ci  }
1911425bb815Sopenharmony_ci
1912425bb815Sopenharmony_ci  return ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP);
1913425bb815Sopenharmony_ci} /* ecma_regexp_read_pattern_str_helper */
1914425bb815Sopenharmony_ci
1915425bb815Sopenharmony_ci/**
1916425bb815Sopenharmony_ci * Helper function for RegExp based string searches
1917425bb815Sopenharmony_ci *
1918425bb815Sopenharmony_ci * See also:
1919425bb815Sopenharmony_ci *          ECMA-262 v6, 21.2.5.9
1920425bb815Sopenharmony_ci *
1921425bb815Sopenharmony_ci * @return index of the match
1922425bb815Sopenharmony_ci */
1923425bb815Sopenharmony_ciecma_value_t
1924425bb815Sopenharmony_ciecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */
1925425bb815Sopenharmony_ci                           ecma_value_t string_arg) /**< string argument */
1926425bb815Sopenharmony_ci{
1927425bb815Sopenharmony_ci  /* 2. */
1928425bb815Sopenharmony_ci  if (!ecma_is_value_object (regexp_arg))
1929425bb815Sopenharmony_ci  {
1930425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
1931425bb815Sopenharmony_ci  }
1932425bb815Sopenharmony_ci
1933425bb815Sopenharmony_ci  ecma_value_t result = ECMA_VALUE_ERROR;
1934425bb815Sopenharmony_ci
1935425bb815Sopenharmony_ci  /* 3-4. */
1936425bb815Sopenharmony_ci  ecma_string_t *const string_p = ecma_op_to_string (string_arg);
1937425bb815Sopenharmony_ci  if (string_p == NULL)
1938425bb815Sopenharmony_ci  {
1939425bb815Sopenharmony_ci    return result;
1940425bb815Sopenharmony_ci  }
1941425bb815Sopenharmony_ci
1942425bb815Sopenharmony_ci  ecma_object_t *const regexp_object_p = ecma_get_object_from_value (regexp_arg);
1943425bb815Sopenharmony_ci
1944425bb815Sopenharmony_ci  /* 5-6. */
1945425bb815Sopenharmony_ci  ecma_string_t *const last_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);
1946425bb815Sopenharmony_ci  const ecma_value_t prev_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p);
1947425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (prev_last_index))
1948425bb815Sopenharmony_ci  {
1949425bb815Sopenharmony_ci    goto cleanup_string;
1950425bb815Sopenharmony_ci  }
1951425bb815Sopenharmony_ci
1952425bb815Sopenharmony_ci  /* 7-8. */
1953425bb815Sopenharmony_ci  const ecma_value_t status = ecma_op_object_put (regexp_object_p, last_index_str_p, ecma_make_uint32_value (0), true);
1954425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (status))
1955425bb815Sopenharmony_ci  {
1956425bb815Sopenharmony_ci    ecma_free_value (prev_last_index);
1957425bb815Sopenharmony_ci    goto cleanup_string;
1958425bb815Sopenharmony_ci  }
1959425bb815Sopenharmony_ci
1960425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_boolean (status));
1961425bb815Sopenharmony_ci
1962425bb815Sopenharmony_ci  /* 9-10. */
1963425bb815Sopenharmony_ci  const ecma_value_t match = ecma_op_regexp_exec (regexp_arg, string_p);
1964425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (match))
1965425bb815Sopenharmony_ci  {
1966425bb815Sopenharmony_ci    ecma_free_value (prev_last_index);
1967425bb815Sopenharmony_ci    goto cleanup_string;
1968425bb815Sopenharmony_ci  }
1969425bb815Sopenharmony_ci
1970425bb815Sopenharmony_ci  /* 11-12. */
1971425bb815Sopenharmony_ci  result = ecma_op_object_put (regexp_object_p, last_index_str_p, prev_last_index, true);
1972425bb815Sopenharmony_ci  ecma_free_value (prev_last_index);
1973425bb815Sopenharmony_ci
1974425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (result))
1975425bb815Sopenharmony_ci  {
1976425bb815Sopenharmony_ci    ecma_free_value (match);
1977425bb815Sopenharmony_ci    goto cleanup_string;
1978425bb815Sopenharmony_ci  }
1979425bb815Sopenharmony_ci
1980425bb815Sopenharmony_ci  /* 13-14. */
1981425bb815Sopenharmony_ci  if (ecma_is_value_null (match))
1982425bb815Sopenharmony_ci  {
1983425bb815Sopenharmony_ci    result = ecma_make_int32_value (-1);
1984425bb815Sopenharmony_ci  }
1985425bb815Sopenharmony_ci  else
1986425bb815Sopenharmony_ci  {
1987425bb815Sopenharmony_ci    ecma_object_t *const match_p = ecma_get_object_from_value (match);
1988425bb815Sopenharmony_ci    result = ecma_op_object_get_by_magic_id (match_p, LIT_MAGIC_STRING_INDEX);
1989425bb815Sopenharmony_ci    ecma_deref_object (match_p);
1990425bb815Sopenharmony_ci  }
1991425bb815Sopenharmony_ci
1992425bb815Sopenharmony_cicleanup_string:
1993425bb815Sopenharmony_ci  ecma_deref_ecma_string (string_p);
1994425bb815Sopenharmony_ci  return result;
1995425bb815Sopenharmony_ci} /* ecma_regexp_search_helper */
1996425bb815Sopenharmony_ci
1997425bb815Sopenharmony_ci/**
1998425bb815Sopenharmony_ci * Helper function for RegExp based string split operation
1999425bb815Sopenharmony_ci *
2000425bb815Sopenharmony_ci * See also:
2001425bb815Sopenharmony_ci *          ECMA-262 v6, 21.2.5.11
2002425bb815Sopenharmony_ci *
2003425bb815Sopenharmony_ci * @return array of split and captured strings
2004425bb815Sopenharmony_ci */
2005425bb815Sopenharmony_ciecma_value_t
2006425bb815Sopenharmony_ciecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */
2007425bb815Sopenharmony_ci                          ecma_value_t string_arg, /**< string value */
2008425bb815Sopenharmony_ci                          ecma_value_t limit_arg) /**< limit value */
2009425bb815Sopenharmony_ci{
2010425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2011425bb815Sopenharmony_ci  /* 2. */
2012425bb815Sopenharmony_ci  if (!ecma_is_value_object (this_arg))
2013425bb815Sopenharmony_ci  {
2014425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
2015425bb815Sopenharmony_ci  }
2016425bb815Sopenharmony_ci
2017425bb815Sopenharmony_ci  ecma_value_t result = ECMA_VALUE_ERROR;
2018425bb815Sopenharmony_ci
2019425bb815Sopenharmony_ci  /* 3-4. */
2020425bb815Sopenharmony_ci  ecma_string_t *const string_p = ecma_op_to_string (string_arg);
2021425bb815Sopenharmony_ci  if (string_p == NULL)
2022425bb815Sopenharmony_ci  {
2023425bb815Sopenharmony_ci    return result;
2024425bb815Sopenharmony_ci  }
2025425bb815Sopenharmony_ci
2026425bb815Sopenharmony_ci  /* 5-6. */
2027425bb815Sopenharmony_ci  ecma_object_t *const regexp_obj_p = ecma_get_object_from_value (this_arg);
2028425bb815Sopenharmony_ci  ecma_value_t constructor = ecma_op_species_constructor (regexp_obj_p, ECMA_BUILTIN_ID_REGEXP);
2029425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (constructor))
2030425bb815Sopenharmony_ci  {
2031425bb815Sopenharmony_ci    goto cleanup_string;
2032425bb815Sopenharmony_ci  }
2033425bb815Sopenharmony_ci
2034425bb815Sopenharmony_ci  ecma_object_t *const constructor_obj_p = ecma_get_object_from_value (constructor);
2035425bb815Sopenharmony_ci
2036425bb815Sopenharmony_ci  /* 7-8. */
2037425bb815Sopenharmony_ci  ecma_value_t flags = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS);
2038425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (flags))
2039425bb815Sopenharmony_ci  {
2040425bb815Sopenharmony_ci    ecma_deref_object (constructor_obj_p);
2041425bb815Sopenharmony_ci    goto cleanup_string;
2042425bb815Sopenharmony_ci  }
2043425bb815Sopenharmony_ci
2044425bb815Sopenharmony_ci  ecma_string_t *flags_str_p = ecma_op_to_string (flags);
2045425bb815Sopenharmony_ci  ecma_free_value (flags);
2046425bb815Sopenharmony_ci
2047425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (flags_str_p == NULL))
2048425bb815Sopenharmony_ci  {
2049425bb815Sopenharmony_ci    ecma_deref_object (constructor_obj_p);
2050425bb815Sopenharmony_ci    goto cleanup_string;
2051425bb815Sopenharmony_ci  }
2052425bb815Sopenharmony_ci
2053425bb815Sopenharmony_ci  lit_utf8_size_t flags_size;
2054425bb815Sopenharmony_ci  uint8_t flags_str_flags = ECMA_STRING_FLAG_IS_ASCII;
2055425bb815Sopenharmony_ci  const lit_utf8_byte_t *flags_buffer_p = ecma_string_get_chars (flags_str_p,
2056425bb815Sopenharmony_ci                                                                 &flags_size,
2057425bb815Sopenharmony_ci                                                                 NULL,
2058425bb815Sopenharmony_ci                                                                 NULL,
2059425bb815Sopenharmony_ci                                                                 &flags_str_flags);
2060425bb815Sopenharmony_ci
2061425bb815Sopenharmony_ci  bool unicode = false;
2062425bb815Sopenharmony_ci  bool sticky = false;
2063425bb815Sopenharmony_ci
2064425bb815Sopenharmony_ci  /* 9-11. */
2065425bb815Sopenharmony_ci  const lit_utf8_byte_t *const flags_end_p = flags_buffer_p + flags_size;
2066425bb815Sopenharmony_ci  for (const lit_utf8_byte_t *current_p = flags_buffer_p; current_p < flags_end_p; ++current_p)
2067425bb815Sopenharmony_ci  {
2068425bb815Sopenharmony_ci    switch (*current_p)
2069425bb815Sopenharmony_ci    {
2070425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_U:
2071425bb815Sopenharmony_ci      {
2072425bb815Sopenharmony_ci        unicode = true;
2073425bb815Sopenharmony_ci        break;
2074425bb815Sopenharmony_ci      }
2075425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_Y:
2076425bb815Sopenharmony_ci      {
2077425bb815Sopenharmony_ci        sticky = true;
2078425bb815Sopenharmony_ci        break;
2079425bb815Sopenharmony_ci      }
2080425bb815Sopenharmony_ci    }
2081425bb815Sopenharmony_ci  }
2082425bb815Sopenharmony_ci
2083425bb815Sopenharmony_ci  if (flags_str_flags & ECMA_STRING_FLAG_MUST_BE_FREED)
2084425bb815Sopenharmony_ci  {
2085425bb815Sopenharmony_ci    jmem_heap_free_block ((void *) flags_buffer_p, flags_size);
2086425bb815Sopenharmony_ci  }
2087425bb815Sopenharmony_ci
2088425bb815Sopenharmony_ci  /* 12. */
2089425bb815Sopenharmony_ci  if (!sticky)
2090425bb815Sopenharmony_ci  {
2091425bb815Sopenharmony_ci    ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (flags_str_p);
2092425bb815Sopenharmony_ci    ecma_stringbuilder_append_byte (&builder, LIT_CHAR_LOWERCASE_Y);
2093425bb815Sopenharmony_ci
2094425bb815Sopenharmony_ci    ecma_deref_ecma_string (flags_str_p);
2095425bb815Sopenharmony_ci    flags_str_p = ecma_stringbuilder_finalize (&builder);
2096425bb815Sopenharmony_ci  }
2097425bb815Sopenharmony_ci
2098425bb815Sopenharmony_ci  /* 13-14. */
2099425bb815Sopenharmony_ci  ecma_value_t arguments[] = { this_arg, ecma_make_string_value (flags_str_p) };
2100425bb815Sopenharmony_ci  ecma_value_t splitter = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, arguments, 2);
2101425bb815Sopenharmony_ci
2102425bb815Sopenharmony_ci  ecma_deref_ecma_string (flags_str_p);
2103425bb815Sopenharmony_ci  ecma_deref_object (constructor_obj_p);
2104425bb815Sopenharmony_ci
2105425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (splitter))
2106425bb815Sopenharmony_ci  {
2107425bb815Sopenharmony_ci    goto cleanup_string;
2108425bb815Sopenharmony_ci  }
2109425bb815Sopenharmony_ci
2110425bb815Sopenharmony_ci  ecma_object_t *const splitter_obj_p = ecma_get_object_from_value (splitter);
2111425bb815Sopenharmony_ci
2112425bb815Sopenharmony_ci  /* 17. */
2113425bb815Sopenharmony_ci  uint32_t limit = UINT32_MAX;
2114425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (limit_arg))
2115425bb815Sopenharmony_ci  {
2116425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (ecma_op_to_length (limit_arg, &limit)))
2117425bb815Sopenharmony_ci    {
2118425bb815Sopenharmony_ci      goto cleanup_splitter;
2119425bb815Sopenharmony_ci    }
2120425bb815Sopenharmony_ci  }
2121425bb815Sopenharmony_ci
2122425bb815Sopenharmony_ci  /* 15. */
2123425bb815Sopenharmony_ci  ecma_value_t array = ecma_op_create_array_object (NULL, 0, false);
2124425bb815Sopenharmony_ci
2125425bb815Sopenharmony_ci  /* 21. */
2126425bb815Sopenharmony_ci  if (limit == 0)
2127425bb815Sopenharmony_ci  {
2128425bb815Sopenharmony_ci    result = array;
2129425bb815Sopenharmony_ci    goto cleanup_splitter;
2130425bb815Sopenharmony_ci  }
2131425bb815Sopenharmony_ci
2132425bb815Sopenharmony_ci  const lit_utf8_size_t string_length = ecma_string_get_length (string_p);
2133425bb815Sopenharmony_ci
2134425bb815Sopenharmony_ci  ecma_object_t *const array_p = ecma_get_object_from_value (array);
2135425bb815Sopenharmony_ci  ecma_length_t array_length = 0;
2136425bb815Sopenharmony_ci
2137425bb815Sopenharmony_ci  /* 22. */
2138425bb815Sopenharmony_ci  if (string_length == 0)
2139425bb815Sopenharmony_ci  {
2140425bb815Sopenharmony_ci    const ecma_value_t match = ecma_op_regexp_exec (splitter, string_p);
2141425bb815Sopenharmony_ci
2142425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (match))
2143425bb815Sopenharmony_ci    {
2144425bb815Sopenharmony_ci      goto cleanup_array;
2145425bb815Sopenharmony_ci    }
2146425bb815Sopenharmony_ci
2147425bb815Sopenharmony_ci    if (ecma_is_value_null (match))
2148425bb815Sopenharmony_ci    {
2149425bb815Sopenharmony_ci      result = ecma_builtin_helper_def_prop_by_index (array_p,
2150425bb815Sopenharmony_ci                                                      array_length,
2151425bb815Sopenharmony_ci                                                      ecma_make_string_value (string_p),
2152425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2153425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_true (result));
2154425bb815Sopenharmony_ci    }
2155425bb815Sopenharmony_ci
2156425bb815Sopenharmony_ci    ecma_free_value (match);
2157425bb815Sopenharmony_ci    result = array;
2158425bb815Sopenharmony_ci    goto cleanup_splitter;
2159425bb815Sopenharmony_ci  }
2160425bb815Sopenharmony_ci
2161425bb815Sopenharmony_ci  /* 23. */
2162425bb815Sopenharmony_ci  uint32_t current_index = 0;
2163425bb815Sopenharmony_ci  uint32_t previous_index = 0;
2164425bb815Sopenharmony_ci
2165425bb815Sopenharmony_ci  ecma_string_t *const lastindex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);
2166425bb815Sopenharmony_ci
2167425bb815Sopenharmony_ci  /* 24. */
2168425bb815Sopenharmony_ci  while (current_index < string_length)
2169425bb815Sopenharmony_ci  {
2170425bb815Sopenharmony_ci    /* 24.a-b. */
2171425bb815Sopenharmony_ci    result = ecma_op_object_put (splitter_obj_p,
2172425bb815Sopenharmony_ci                                 lastindex_str_p,
2173425bb815Sopenharmony_ci                                 ecma_make_uint32_value (current_index),
2174425bb815Sopenharmony_ci                                 true);
2175425bb815Sopenharmony_ci
2176425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2177425bb815Sopenharmony_ci    {
2178425bb815Sopenharmony_ci      goto cleanup_array;
2179425bb815Sopenharmony_ci    }
2180425bb815Sopenharmony_ci
2181425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_true (result));
2182425bb815Sopenharmony_ci
2183425bb815Sopenharmony_ci    /* 24.c-d. */
2184425bb815Sopenharmony_ci    result = ecma_op_regexp_exec (splitter, string_p);
2185425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2186425bb815Sopenharmony_ci    {
2187425bb815Sopenharmony_ci      goto cleanup_array;
2188425bb815Sopenharmony_ci    }
2189425bb815Sopenharmony_ci
2190425bb815Sopenharmony_ci    /* 24.e. */
2191425bb815Sopenharmony_ci    if (ecma_is_value_null (result))
2192425bb815Sopenharmony_ci    {
2193425bb815Sopenharmony_ci      current_index = ecma_op_advance_string_index (string_p, current_index, unicode);
2194425bb815Sopenharmony_ci      continue;
2195425bb815Sopenharmony_ci    }
2196425bb815Sopenharmony_ci
2197425bb815Sopenharmony_ci    ecma_object_t *const match_array_p = ecma_get_object_from_value (result);
2198425bb815Sopenharmony_ci
2199425bb815Sopenharmony_ci    /* 24.f.i. */
2200425bb815Sopenharmony_ci    result = ecma_op_object_get (splitter_obj_p, lastindex_str_p);
2201425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2202425bb815Sopenharmony_ci    {
2203425bb815Sopenharmony_ci      ecma_deref_object (match_array_p);
2204425bb815Sopenharmony_ci      goto cleanup_array;
2205425bb815Sopenharmony_ci    }
2206425bb815Sopenharmony_ci
2207425bb815Sopenharmony_ci    uint32_t end_index;
2208425bb815Sopenharmony_ci    const ecma_value_t length_value = ecma_op_to_length (result, &end_index);
2209425bb815Sopenharmony_ci    ecma_free_value (result);
2210425bb815Sopenharmony_ci
2211425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (length_value))
2212425bb815Sopenharmony_ci    {
2213425bb815Sopenharmony_ci      result = ECMA_VALUE_ERROR;
2214425bb815Sopenharmony_ci      ecma_deref_object (match_array_p);
2215425bb815Sopenharmony_ci      goto cleanup_array;
2216425bb815Sopenharmony_ci    }
2217425bb815Sopenharmony_ci
2218425bb815Sopenharmony_ci    /* 24.f.iii. */
2219425bb815Sopenharmony_ci    if (previous_index == end_index)
2220425bb815Sopenharmony_ci    {
2221425bb815Sopenharmony_ci      ecma_deref_object (match_array_p);
2222425bb815Sopenharmony_ci      current_index = ecma_op_advance_string_index (string_p, current_index, unicode);
2223425bb815Sopenharmony_ci      continue;
2224425bb815Sopenharmony_ci    }
2225425bb815Sopenharmony_ci
2226425bb815Sopenharmony_ci    /* 24.f.iv.1-4. */
2227425bb815Sopenharmony_ci    ecma_string_t *const split_str_p = ecma_string_substr (string_p, previous_index, current_index);
2228425bb815Sopenharmony_ci
2229425bb815Sopenharmony_ci    result = ecma_builtin_helper_def_prop_by_index (array_p,
2230425bb815Sopenharmony_ci                                                    array_length++,
2231425bb815Sopenharmony_ci                                                    ecma_make_string_value (split_str_p),
2232425bb815Sopenharmony_ci                                                    ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2233425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_true (result));
2234425bb815Sopenharmony_ci    ecma_deref_ecma_string (split_str_p);
2235425bb815Sopenharmony_ci
2236425bb815Sopenharmony_ci    /* 24.f.iv.5. */
2237425bb815Sopenharmony_ci    if (array_length == limit)
2238425bb815Sopenharmony_ci    {
2239425bb815Sopenharmony_ci      ecma_deref_object (match_array_p);
2240425bb815Sopenharmony_ci      result = array;
2241425bb815Sopenharmony_ci      goto cleanup_splitter;
2242425bb815Sopenharmony_ci    }
2243425bb815Sopenharmony_ci
2244425bb815Sopenharmony_ci    /* 24.f.iv.6. */
2245425bb815Sopenharmony_ci    previous_index = end_index;
2246425bb815Sopenharmony_ci
2247425bb815Sopenharmony_ci    /* 24.f.iv.7-8. */
2248425bb815Sopenharmony_ci    uint32_t match_length;
2249425bb815Sopenharmony_ci    result = ecma_op_object_get_length (match_array_p, &match_length);
2250425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2251425bb815Sopenharmony_ci    {
2252425bb815Sopenharmony_ci      ecma_deref_object (match_array_p);
2253425bb815Sopenharmony_ci      goto cleanup_array;
2254425bb815Sopenharmony_ci    }
2255425bb815Sopenharmony_ci
2256425bb815Sopenharmony_ci    /* 24.f.iv.9. */
2257425bb815Sopenharmony_ci    match_length = (match_length > 0) ? match_length - 1 : match_length;
2258425bb815Sopenharmony_ci
2259425bb815Sopenharmony_ci    uint32_t match_index = 1;
2260425bb815Sopenharmony_ci    while (match_index <= match_length)
2261425bb815Sopenharmony_ci    {
2262425bb815Sopenharmony_ci      /* 24.f.iv.11.a-b. */
2263425bb815Sopenharmony_ci      result = ecma_op_object_get_by_uint32_index (match_array_p, match_index++);
2264425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
2265425bb815Sopenharmony_ci      {
2266425bb815Sopenharmony_ci        ecma_deref_object (match_array_p);
2267425bb815Sopenharmony_ci        goto cleanup_array;
2268425bb815Sopenharmony_ci      }
2269425bb815Sopenharmony_ci
2270425bb815Sopenharmony_ci      const ecma_value_t capture = result;
2271425bb815Sopenharmony_ci
2272425bb815Sopenharmony_ci      /* 24.f.iv.11.c. */
2273425bb815Sopenharmony_ci      result = ecma_builtin_helper_def_prop_by_index (array_p,
2274425bb815Sopenharmony_ci                                                      array_length++,
2275425bb815Sopenharmony_ci                                                      capture,
2276425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2277425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_true (result));
2278425bb815Sopenharmony_ci
2279425bb815Sopenharmony_ci      ecma_free_value (capture);
2280425bb815Sopenharmony_ci
2281425bb815Sopenharmony_ci      if (array_length == limit)
2282425bb815Sopenharmony_ci      {
2283425bb815Sopenharmony_ci        ecma_deref_object (match_array_p);
2284425bb815Sopenharmony_ci        result = array;
2285425bb815Sopenharmony_ci        goto cleanup_splitter;
2286425bb815Sopenharmony_ci      }
2287425bb815Sopenharmony_ci    }
2288425bb815Sopenharmony_ci
2289425bb815Sopenharmony_ci    /* 24.f.iv.12. */
2290425bb815Sopenharmony_ci    current_index = end_index;
2291425bb815Sopenharmony_ci
2292425bb815Sopenharmony_ci    ecma_deref_object (match_array_p);
2293425bb815Sopenharmony_ci  }
2294425bb815Sopenharmony_ci
2295425bb815Sopenharmony_ci  ecma_string_t *const end_str_p = ecma_string_substr (string_p, previous_index, string_length);
2296425bb815Sopenharmony_ci  result = ecma_builtin_helper_def_prop_by_index (array_p,
2297425bb815Sopenharmony_ci                                                  array_length++,
2298425bb815Sopenharmony_ci                                                  ecma_make_string_value (end_str_p),
2299425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2300425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_true (result));
2301425bb815Sopenharmony_ci  ecma_deref_ecma_string (end_str_p);
2302425bb815Sopenharmony_ci
2303425bb815Sopenharmony_ci  result = array;
2304425bb815Sopenharmony_ci  goto cleanup_splitter;
2305425bb815Sopenharmony_ci
2306425bb815Sopenharmony_cicleanup_array:
2307425bb815Sopenharmony_ci  ecma_deref_object (array_p);
2308425bb815Sopenharmony_cicleanup_splitter:
2309425bb815Sopenharmony_ci  ecma_deref_object (splitter_obj_p);
2310425bb815Sopenharmony_cicleanup_string:
2311425bb815Sopenharmony_ci  ecma_deref_ecma_string (string_p);
2312425bb815Sopenharmony_ci
2313425bb815Sopenharmony_ci  return result;
2314425bb815Sopenharmony_ci#else /* ENABLED (JERRY_ES2015) */
2315425bb815Sopenharmony_ci  ecma_value_t result = ECMA_VALUE_ERROR;
2316425bb815Sopenharmony_ci
2317425bb815Sopenharmony_ci  /* 2. */
2318425bb815Sopenharmony_ci  ecma_string_t *string_p = ecma_op_to_string (string_arg);
2319425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (string_p == NULL))
2320425bb815Sopenharmony_ci  {
2321425bb815Sopenharmony_ci    return result;
2322425bb815Sopenharmony_ci  }
2323425bb815Sopenharmony_ci
2324425bb815Sopenharmony_ci  /* 5. */
2325425bb815Sopenharmony_ci  uint32_t limit = UINT32_MAX;
2326425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (limit_arg))
2327425bb815Sopenharmony_ci  {
2328425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (ecma_op_to_length (limit_arg, &limit)))
2329425bb815Sopenharmony_ci    {
2330425bb815Sopenharmony_ci      goto cleanup_string;
2331425bb815Sopenharmony_ci    }
2332425bb815Sopenharmony_ci  }
2333425bb815Sopenharmony_ci
2334425bb815Sopenharmony_ci  /* 15. */
2335425bb815Sopenharmony_ci  ecma_value_t array = ecma_op_create_array_object (NULL, 0, false);
2336425bb815Sopenharmony_ci
2337425bb815Sopenharmony_ci  /* 21. */
2338425bb815Sopenharmony_ci  if (limit == 0)
2339425bb815Sopenharmony_ci  {
2340425bb815Sopenharmony_ci    result = array;
2341425bb815Sopenharmony_ci    goto cleanup_string;
2342425bb815Sopenharmony_ci  }
2343425bb815Sopenharmony_ci
2344425bb815Sopenharmony_ci  ecma_object_t *const array_p = ecma_get_object_from_value (array);
2345425bb815Sopenharmony_ci  ecma_length_t array_length = 0;
2346425bb815Sopenharmony_ci
2347425bb815Sopenharmony_ci  ecma_object_t *const regexp_p = ecma_get_object_from_value (this_arg);
2348425bb815Sopenharmony_ci  ecma_extended_object_t *const ext_object_p = (ecma_extended_object_t *) regexp_p;
2349425bb815Sopenharmony_ci  re_compiled_code_t *const bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
2350425bb815Sopenharmony_ci                                                                        ext_object_p->u.class_prop.u.value);
2351425bb815Sopenharmony_ci
2352425bb815Sopenharmony_ci  lit_utf8_size_t string_size;
2353425bb815Sopenharmony_ci  lit_utf8_size_t string_length;
2354425bb815Sopenharmony_ci  uint8_t string_flags = ECMA_STRING_FLAG_IS_ASCII;
2355425bb815Sopenharmony_ci  const lit_utf8_byte_t *string_buffer_p = ecma_string_get_chars (string_p,
2356425bb815Sopenharmony_ci                                                                  &string_size,
2357425bb815Sopenharmony_ci                                                                  &string_length,
2358425bb815Sopenharmony_ci                                                                  NULL,
2359425bb815Sopenharmony_ci                                                                  &string_flags);
2360425bb815Sopenharmony_ci
2361425bb815Sopenharmony_ci  const lit_utf8_byte_t *current_str_p = string_buffer_p;
2362425bb815Sopenharmony_ci  const lit_utf8_byte_t *previous_str_p = string_buffer_p;
2363425bb815Sopenharmony_ci  const lit_utf8_byte_t *const string_end_p = string_buffer_p + string_size;
2364425bb815Sopenharmony_ci
2365425bb815Sopenharmony_ci  ecma_regexp_ctx_t re_ctx;
2366425bb815Sopenharmony_ci  ecma_regexp_initialize_context (&re_ctx,
2367425bb815Sopenharmony_ci                                  bc_p,
2368425bb815Sopenharmony_ci                                  string_buffer_p,
2369425bb815Sopenharmony_ci                                  string_buffer_p + string_size);
2370425bb815Sopenharmony_ci
2371425bb815Sopenharmony_ci  uint8_t *const bc_start_p = (uint8_t *) (bc_p + 1);
2372425bb815Sopenharmony_ci
2373425bb815Sopenharmony_ci  if (string_length == 0)
2374425bb815Sopenharmony_ci  {
2375425bb815Sopenharmony_ci    const lit_utf8_byte_t *const matched_p = ecma_regexp_match (&re_ctx, bc_start_p, current_str_p);
2376425bb815Sopenharmony_ci
2377425bb815Sopenharmony_ci    if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
2378425bb815Sopenharmony_ci    {
2379425bb815Sopenharmony_ci      result = ecma_raise_range_error (ECMA_ERR_MSG ("Stack limit exceeded."));
2380425bb815Sopenharmony_ci      goto cleanup_array;
2381425bb815Sopenharmony_ci    }
2382425bb815Sopenharmony_ci
2383425bb815Sopenharmony_ci    if (matched_p == NULL)
2384425bb815Sopenharmony_ci    {
2385425bb815Sopenharmony_ci      result = ecma_builtin_helper_def_prop_by_index (array_p,
2386425bb815Sopenharmony_ci                                                      array_length,
2387425bb815Sopenharmony_ci                                                      ecma_make_string_value (string_p),
2388425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2389425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_true (result));
2390425bb815Sopenharmony_ci    }
2391425bb815Sopenharmony_ci
2392425bb815Sopenharmony_ci    result = array;
2393425bb815Sopenharmony_ci    goto cleanup_context;
2394425bb815Sopenharmony_ci  }
2395425bb815Sopenharmony_ci
2396425bb815Sopenharmony_ci  /* 13. */
2397425bb815Sopenharmony_ci  while (current_str_p < string_end_p)
2398425bb815Sopenharmony_ci  {
2399425bb815Sopenharmony_ci    /* 13.a. */
2400425bb815Sopenharmony_ci    const lit_utf8_byte_t *const matched_p = ecma_regexp_match (&re_ctx, bc_start_p, current_str_p);
2401425bb815Sopenharmony_ci
2402425bb815Sopenharmony_ci    if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
2403425bb815Sopenharmony_ci    {
2404425bb815Sopenharmony_ci      result = ecma_raise_range_error (ECMA_ERR_MSG ("Stack limit exceeded."));
2405425bb815Sopenharmony_ci      goto cleanup_array;
2406425bb815Sopenharmony_ci    }
2407425bb815Sopenharmony_ci
2408425bb815Sopenharmony_ci    if (matched_p == NULL || matched_p == previous_str_p)
2409425bb815Sopenharmony_ci    {
2410425bb815Sopenharmony_ci      lit_utf8_incr (&current_str_p);
2411425bb815Sopenharmony_ci      continue;
2412425bb815Sopenharmony_ci    }
2413425bb815Sopenharmony_ci
2414425bb815Sopenharmony_ci    /* 13.c.iii.1. */
2415425bb815Sopenharmony_ci    ecma_string_t *const str_p = ecma_new_ecma_string_from_utf8 (previous_str_p,
2416425bb815Sopenharmony_ci                                                                 (lit_utf8_size_t) (current_str_p - previous_str_p));
2417425bb815Sopenharmony_ci
2418425bb815Sopenharmony_ci    result = ecma_builtin_helper_def_prop_by_index (array_p,
2419425bb815Sopenharmony_ci                                                    array_length++,
2420425bb815Sopenharmony_ci                                                    ecma_make_string_value (str_p),
2421425bb815Sopenharmony_ci                                                    ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2422425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_true (result));
2423425bb815Sopenharmony_ci    ecma_deref_ecma_string (str_p);
2424425bb815Sopenharmony_ci
2425425bb815Sopenharmony_ci    if (array_length == limit)
2426425bb815Sopenharmony_ci    {
2427425bb815Sopenharmony_ci      result = array;
2428425bb815Sopenharmony_ci      goto cleanup_context;
2429425bb815Sopenharmony_ci    }
2430425bb815Sopenharmony_ci
2431425bb815Sopenharmony_ci    /* 13.c.iii.5. */
2432425bb815Sopenharmony_ci    previous_str_p = matched_p;
2433425bb815Sopenharmony_ci
2434425bb815Sopenharmony_ci    uint32_t index = 1;
2435425bb815Sopenharmony_ci    while (index < re_ctx.captures_count)
2436425bb815Sopenharmony_ci    {
2437425bb815Sopenharmony_ci      const ecma_value_t capture = ecma_regexp_get_capture_value (re_ctx.captures_p + index);
2438425bb815Sopenharmony_ci      result = ecma_builtin_helper_def_prop_by_index (array_p,
2439425bb815Sopenharmony_ci                                                      array_length++,
2440425bb815Sopenharmony_ci                                                      capture,
2441425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2442425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_true (result));
2443425bb815Sopenharmony_ci      ecma_free_value (capture);
2444425bb815Sopenharmony_ci
2445425bb815Sopenharmony_ci      if (array_length == limit)
2446425bb815Sopenharmony_ci      {
2447425bb815Sopenharmony_ci        result = array;
2448425bb815Sopenharmony_ci        goto cleanup_context;
2449425bb815Sopenharmony_ci      }
2450425bb815Sopenharmony_ci
2451425bb815Sopenharmony_ci      index++;
2452425bb815Sopenharmony_ci    }
2453425bb815Sopenharmony_ci
2454425bb815Sopenharmony_ci    /* 13.c.iii.8. */
2455425bb815Sopenharmony_ci    current_str_p = matched_p;
2456425bb815Sopenharmony_ci  }
2457425bb815Sopenharmony_ci
2458425bb815Sopenharmony_ci  ecma_string_t *const str_p = ecma_new_ecma_string_from_utf8 (previous_str_p,
2459425bb815Sopenharmony_ci                                                               (lit_utf8_size_t) (string_end_p - previous_str_p));
2460425bb815Sopenharmony_ci
2461425bb815Sopenharmony_ci  result = ecma_builtin_helper_def_prop_by_index (array_p,
2462425bb815Sopenharmony_ci                                                  array_length++,
2463425bb815Sopenharmony_ci                                                  ecma_make_string_value (str_p),
2464425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
2465425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_true (result));
2466425bb815Sopenharmony_ci  ecma_deref_ecma_string (str_p);
2467425bb815Sopenharmony_ci
2468425bb815Sopenharmony_ci  result = array;
2469425bb815Sopenharmony_ci  goto cleanup_context;
2470425bb815Sopenharmony_ci
2471425bb815Sopenharmony_cicleanup_array:
2472425bb815Sopenharmony_ci  ecma_deref_object (array_p);
2473425bb815Sopenharmony_cicleanup_context:
2474425bb815Sopenharmony_ci  ecma_regexp_cleanup_context (&re_ctx);
2475425bb815Sopenharmony_ci  if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED)
2476425bb815Sopenharmony_ci  {
2477425bb815Sopenharmony_ci    jmem_heap_free_block ((void *) string_buffer_p, string_size);
2478425bb815Sopenharmony_ci  }
2479425bb815Sopenharmony_cicleanup_string:
2480425bb815Sopenharmony_ci  ecma_deref_ecma_string (string_p);
2481425bb815Sopenharmony_ci
2482425bb815Sopenharmony_ci  return result;
2483425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2484425bb815Sopenharmony_ci} /* ecma_regexp_split_helper */
2485425bb815Sopenharmony_ci
2486425bb815Sopenharmony_ci/**
2487425bb815Sopenharmony_ci * Fast path for RegExp based replace operation
2488425bb815Sopenharmony_ci *
2489425bb815Sopenharmony_ci * This method assumes the following:
2490425bb815Sopenharmony_ci *   - The RegExp object is a built-in RegExp
2491425bb815Sopenharmony_ci *   - The 'exec' method of the RegExp object is the built-in 'exec' method
2492425bb815Sopenharmony_ci *   - The 'lastIndex' property is writable
2493425bb815Sopenharmony_ci *
2494425bb815Sopenharmony_ci * The standard would normally require us to first execute the regexp and collect the results,
2495425bb815Sopenharmony_ci * and after that iterate over the collected results and replace them.
2496425bb815Sopenharmony_ci * The assumptions above guarantee that during the matching phase there will be no exceptions thrown,
2497425bb815Sopenharmony_ci * which means we can do the match/replace in a single loop, without collecting the results.
2498425bb815Sopenharmony_ci *
2499425bb815Sopenharmony_ci * @return string value if successful
2500425bb815Sopenharmony_ci *         thrown value otherwise
2501425bb815Sopenharmony_ci */
2502425bb815Sopenharmony_cistatic ecma_value_t
2503425bb815Sopenharmony_ciecma_regexp_replace_helper_fast (ecma_replace_context_t *ctx_p, /**<replace context */
2504425bb815Sopenharmony_ci                                 const re_compiled_code_t *bc_p, /**< regexp bytecode */
2505425bb815Sopenharmony_ci                                 ecma_string_t *string_p, /**< source string */
2506425bb815Sopenharmony_ci                                 ecma_value_t replace_arg) /**< replace argument */
2507425bb815Sopenharmony_ci{
2508425bb815Sopenharmony_ci  JERRY_ASSERT (bc_p != NULL);
2509425bb815Sopenharmony_ci  ecma_value_t result = ECMA_VALUE_EMPTY;
2510425bb815Sopenharmony_ci
2511425bb815Sopenharmony_ci  uint8_t string_flags = ECMA_STRING_FLAG_IS_ASCII;
2512425bb815Sopenharmony_ci  lit_utf8_size_t string_length;
2513425bb815Sopenharmony_ci  ctx_p->string_p = ecma_string_get_chars (string_p,
2514425bb815Sopenharmony_ci                                           &(ctx_p->string_size),
2515425bb815Sopenharmony_ci                                           &string_length,
2516425bb815Sopenharmony_ci                                           NULL,
2517425bb815Sopenharmony_ci                                           &string_flags);
2518425bb815Sopenharmony_ci
2519425bb815Sopenharmony_ci  const lit_utf8_byte_t *const string_end_p = ctx_p->string_p + ctx_p->string_size;
2520425bb815Sopenharmony_ci  const uint8_t *const bc_start_p = (const uint8_t *) (bc_p + 1);
2521425bb815Sopenharmony_ci  const lit_utf8_byte_t *matched_p = NULL;
2522425bb815Sopenharmony_ci  const lit_utf8_byte_t *current_p = ctx_p->string_p;
2523425bb815Sopenharmony_ci  const lit_utf8_byte_t *last_append_p = current_p;
2524425bb815Sopenharmony_ci  JERRY_ASSERT (ctx_p->index <= string_length);
2525425bb815Sopenharmony_ci
2526425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2527425bb815Sopenharmony_ci  /* Global matches always start at index 0, but Sticky matches may have a non-zero lastIndex. */
2528425bb815Sopenharmony_ci  if (ctx_p->index > 0)
2529425bb815Sopenharmony_ci  {
2530425bb815Sopenharmony_ci    if (string_flags & ECMA_STRING_FLAG_IS_ASCII)
2531425bb815Sopenharmony_ci    {
2532425bb815Sopenharmony_ci      current_p += ctx_p->index;
2533425bb815Sopenharmony_ci    }
2534425bb815Sopenharmony_ci    else
2535425bb815Sopenharmony_ci    {
2536425bb815Sopenharmony_ci      ecma_length_t index = ctx_p->index;
2537425bb815Sopenharmony_ci      while (index--)
2538425bb815Sopenharmony_ci      {
2539425bb815Sopenharmony_ci        lit_utf8_incr (&current_p);
2540425bb815Sopenharmony_ci      }
2541425bb815Sopenharmony_ci    }
2542425bb815Sopenharmony_ci  }
2543425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2544425bb815Sopenharmony_ci
2545425bb815Sopenharmony_ci  ecma_regexp_ctx_t re_ctx;
2546425bb815Sopenharmony_ci  ecma_regexp_initialize_context (&re_ctx,
2547425bb815Sopenharmony_ci                                  bc_p,
2548425bb815Sopenharmony_ci                                  ctx_p->string_p,
2549425bb815Sopenharmony_ci                                  string_end_p);
2550425bb815Sopenharmony_ci
2551425bb815Sopenharmony_ci  ctx_p->builder = ecma_stringbuilder_create ();
2552425bb815Sopenharmony_ci  ctx_p->capture_count = re_ctx.captures_count;
2553425bb815Sopenharmony_ci  ctx_p->u.captures_p = re_ctx.captures_p;
2554425bb815Sopenharmony_ci
2555425bb815Sopenharmony_ci  while (true)
2556425bb815Sopenharmony_ci  {
2557425bb815Sopenharmony_ci    matched_p = ecma_regexp_match (&re_ctx, bc_start_p, current_p);
2558425bb815Sopenharmony_ci
2559425bb815Sopenharmony_ci    if (matched_p != NULL)
2560425bb815Sopenharmony_ci    {
2561425bb815Sopenharmony_ci      if (ECMA_RE_STACK_LIMIT_REACHED (matched_p))
2562425bb815Sopenharmony_ci      {
2563425bb815Sopenharmony_ci        result = ecma_raise_range_error (ECMA_ERR_MSG ("Stack limit exceeded."));
2564425bb815Sopenharmony_ci        goto cleanup_builder;
2565425bb815Sopenharmony_ci      }
2566425bb815Sopenharmony_ci
2567425bb815Sopenharmony_ci      const lit_utf8_size_t remaining_size = (lit_utf8_size_t) (current_p - last_append_p);
2568425bb815Sopenharmony_ci      ecma_stringbuilder_append_raw (&(ctx_p->builder), last_append_p, remaining_size);
2569425bb815Sopenharmony_ci
2570425bb815Sopenharmony_ci      if (ctx_p->replace_str_p != NULL)
2571425bb815Sopenharmony_ci      {
2572425bb815Sopenharmony_ci        ctx_p->matched_p = current_p;
2573425bb815Sopenharmony_ci        const ecma_regexp_capture_t *const global_capture_p = re_ctx.captures_p;
2574425bb815Sopenharmony_ci        ctx_p->matched_size = (lit_utf8_size_t) (global_capture_p->end_p - global_capture_p->begin_p);
2575425bb815Sopenharmony_ci        ctx_p->match_byte_pos = (lit_utf8_size_t) (current_p - re_ctx.input_start_p);
2576425bb815Sopenharmony_ci
2577425bb815Sopenharmony_ci        ecma_builtin_replace_substitute (ctx_p);
2578425bb815Sopenharmony_ci      }
2579425bb815Sopenharmony_ci      else
2580425bb815Sopenharmony_ci      {
2581425bb815Sopenharmony_ci        ecma_collection_t *arguments_p = ecma_new_collection ();
2582425bb815Sopenharmony_ci
2583425bb815Sopenharmony_ci        for (uint32_t i = 0; i < re_ctx.captures_count; i++)
2584425bb815Sopenharmony_ci        {
2585425bb815Sopenharmony_ci          ecma_value_t capture = ecma_regexp_get_capture_value (re_ctx.captures_p + i);
2586425bb815Sopenharmony_ci          ecma_collection_push_back (arguments_p, capture);
2587425bb815Sopenharmony_ci        }
2588425bb815Sopenharmony_ci
2589425bb815Sopenharmony_ci        ecma_collection_push_back (arguments_p, ecma_make_uint32_value (ctx_p->index));
2590425bb815Sopenharmony_ci        ecma_ref_ecma_string (string_p);
2591425bb815Sopenharmony_ci        ecma_collection_push_back (arguments_p, ecma_make_string_value (string_p));
2592425bb815Sopenharmony_ci        ecma_object_t *function_p = ecma_get_object_from_value (replace_arg);
2593425bb815Sopenharmony_ci
2594425bb815Sopenharmony_ci        result = ecma_op_function_call (function_p,
2595425bb815Sopenharmony_ci                                        ECMA_VALUE_UNDEFINED,
2596425bb815Sopenharmony_ci                                        arguments_p->buffer_p,
2597425bb815Sopenharmony_ci                                        arguments_p->item_count);
2598425bb815Sopenharmony_ci
2599425bb815Sopenharmony_ci        ecma_collection_free (arguments_p);
2600425bb815Sopenharmony_ci
2601425bb815Sopenharmony_ci        if (ECMA_IS_VALUE_ERROR (result))
2602425bb815Sopenharmony_ci        {
2603425bb815Sopenharmony_ci          goto cleanup_builder;
2604425bb815Sopenharmony_ci        }
2605425bb815Sopenharmony_ci
2606425bb815Sopenharmony_ci        /* 16.m.v */
2607425bb815Sopenharmony_ci        ecma_string_t *const replace_result_p = ecma_op_to_string (result);
2608425bb815Sopenharmony_ci        ecma_free_value (result);
2609425bb815Sopenharmony_ci
2610425bb815Sopenharmony_ci        if (replace_result_p == NULL)
2611425bb815Sopenharmony_ci        {
2612425bb815Sopenharmony_ci          result = ECMA_VALUE_ERROR;
2613425bb815Sopenharmony_ci          goto cleanup_builder;
2614425bb815Sopenharmony_ci        }
2615425bb815Sopenharmony_ci
2616425bb815Sopenharmony_ci        ecma_stringbuilder_append (&(ctx_p->builder), replace_result_p);
2617425bb815Sopenharmony_ci        ecma_deref_ecma_string (replace_result_p);
2618425bb815Sopenharmony_ci      }
2619425bb815Sopenharmony_ci
2620425bb815Sopenharmony_ci      const ecma_regexp_capture_t *global_capture_p = re_ctx.captures_p;
2621425bb815Sopenharmony_ci      last_append_p = global_capture_p->end_p;
2622425bb815Sopenharmony_ci
2623425bb815Sopenharmony_ci      if (!(re_ctx.flags & RE_FLAG_GLOBAL))
2624425bb815Sopenharmony_ci      {
2625425bb815Sopenharmony_ci        break;
2626425bb815Sopenharmony_ci      }
2627425bb815Sopenharmony_ci
2628425bb815Sopenharmony_ci      const lit_utf8_size_t matched_size = (lit_utf8_size_t) (global_capture_p->end_p - global_capture_p->begin_p);
2629425bb815Sopenharmony_ci      if (matched_size > 0)
2630425bb815Sopenharmony_ci      {
2631425bb815Sopenharmony_ci        ctx_p->index += lit_utf8_string_length (current_p, matched_size);
2632425bb815Sopenharmony_ci        current_p = last_append_p;
2633425bb815Sopenharmony_ci        continue;
2634425bb815Sopenharmony_ci      }
2635425bb815Sopenharmony_ci    }
2636425bb815Sopenharmony_ci
2637425bb815Sopenharmony_ci    if (current_p >= string_end_p)
2638425bb815Sopenharmony_ci    {
2639425bb815Sopenharmony_ci      break;
2640425bb815Sopenharmony_ci    }
2641425bb815Sopenharmony_ci
2642425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2643425bb815Sopenharmony_ci    if ((re_ctx.flags & RE_FLAG_UNICODE) != 0)
2644425bb815Sopenharmony_ci    {
2645425bb815Sopenharmony_ci      ctx_p->index++;
2646425bb815Sopenharmony_ci      const lit_code_point_t cp = ecma_regexp_unicode_advance (&current_p,
2647425bb815Sopenharmony_ci                                                               string_end_p);
2648425bb815Sopenharmony_ci
2649425bb815Sopenharmony_ci      if (cp > LIT_UTF16_CODE_UNIT_MAX)
2650425bb815Sopenharmony_ci      {
2651425bb815Sopenharmony_ci        ctx_p->index++;
2652425bb815Sopenharmony_ci      }
2653425bb815Sopenharmony_ci
2654425bb815Sopenharmony_ci      continue;
2655425bb815Sopenharmony_ci    }
2656425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2657425bb815Sopenharmony_ci
2658425bb815Sopenharmony_ci    ctx_p->index++;
2659425bb815Sopenharmony_ci    lit_utf8_incr (&current_p);
2660425bb815Sopenharmony_ci  }
2661425bb815Sopenharmony_ci
2662425bb815Sopenharmony_ci  const lit_utf8_size_t trailing_size = (lit_utf8_size_t) (string_end_p - last_append_p);
2663425bb815Sopenharmony_ci  ecma_stringbuilder_append_raw (&(ctx_p->builder), last_append_p, trailing_size);
2664425bb815Sopenharmony_ci
2665425bb815Sopenharmony_ci  result = ecma_make_string_value (ecma_stringbuilder_finalize (&(ctx_p->builder)));
2666425bb815Sopenharmony_ci  goto cleanup_context;
2667425bb815Sopenharmony_ci
2668425bb815Sopenharmony_cicleanup_builder:
2669425bb815Sopenharmony_ci  ecma_stringbuilder_destroy (&(ctx_p->builder));
2670425bb815Sopenharmony_ci
2671425bb815Sopenharmony_cicleanup_context:
2672425bb815Sopenharmony_ci  ecma_regexp_cleanup_context (&re_ctx);
2673425bb815Sopenharmony_ci
2674425bb815Sopenharmony_ci  if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED)
2675425bb815Sopenharmony_ci  {
2676425bb815Sopenharmony_ci    jmem_heap_free_block ((void *) ctx_p->string_p, ctx_p->string_size);
2677425bb815Sopenharmony_ci  }
2678425bb815Sopenharmony_ci
2679425bb815Sopenharmony_ci  return result;
2680425bb815Sopenharmony_ci} /* ecma_regexp_replace_helper_fast */
2681425bb815Sopenharmony_ci
2682425bb815Sopenharmony_ci/**
2683425bb815Sopenharmony_ci * Helper function for RegExp based replacing
2684425bb815Sopenharmony_ci *
2685425bb815Sopenharmony_ci * See also:
2686425bb815Sopenharmony_ci *          String.prototype.replace
2687425bb815Sopenharmony_ci *          RegExp.prototype[@@replace]
2688425bb815Sopenharmony_ci *
2689425bb815Sopenharmony_ci * @return result string of the replacement, if successful
2690425bb815Sopenharmony_ci *         error value, otherwise
2691425bb815Sopenharmony_ci */
2692425bb815Sopenharmony_ciecma_value_t
2693425bb815Sopenharmony_ciecma_regexp_replace_helper (ecma_value_t this_arg, /**< this argument */
2694425bb815Sopenharmony_ci                            ecma_value_t string_arg, /**< source string */
2695425bb815Sopenharmony_ci                            ecma_value_t replace_arg) /**< replace string */
2696425bb815Sopenharmony_ci{
2697425bb815Sopenharmony_ci  /* 2. */
2698425bb815Sopenharmony_ci  if (!ecma_is_value_object (this_arg))
2699425bb815Sopenharmony_ci  {
2700425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
2701425bb815Sopenharmony_ci  }
2702425bb815Sopenharmony_ci
2703425bb815Sopenharmony_ci  ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg);
2704425bb815Sopenharmony_ci
2705425bb815Sopenharmony_ci  ecma_replace_context_t replace_ctx;
2706425bb815Sopenharmony_ci  replace_ctx.index = 0;
2707425bb815Sopenharmony_ci
2708425bb815Sopenharmony_ci  /* 3. */
2709425bb815Sopenharmony_ci  ecma_string_t *string_p = ecma_op_to_string (string_arg);
2710425bb815Sopenharmony_ci  if (string_p == NULL)
2711425bb815Sopenharmony_ci  {
2712425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
2713425bb815Sopenharmony_ci  }
2714425bb815Sopenharmony_ci
2715425bb815Sopenharmony_ci  ecma_value_t result = ECMA_VALUE_ERROR;
2716425bb815Sopenharmony_ci
2717425bb815Sopenharmony_ci  /* 6. */
2718425bb815Sopenharmony_ci  replace_ctx.replace_str_p = NULL;
2719425bb815Sopenharmony_ci  if (!ecma_op_is_callable (replace_arg))
2720425bb815Sopenharmony_ci  {
2721425bb815Sopenharmony_ci    replace_ctx.replace_str_p = ecma_op_to_string (replace_arg);
2722425bb815Sopenharmony_ci
2723425bb815Sopenharmony_ci    if (replace_ctx.replace_str_p == NULL)
2724425bb815Sopenharmony_ci    {
2725425bb815Sopenharmony_ci      goto cleanup_string;
2726425bb815Sopenharmony_ci    }
2727425bb815Sopenharmony_ci  }
2728425bb815Sopenharmony_ci
2729425bb815Sopenharmony_ci  /* 8 */
2730425bb815Sopenharmony_ci  result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_GLOBAL);
2731425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (result))
2732425bb815Sopenharmony_ci  {
2733425bb815Sopenharmony_ci    goto cleanup_replace;
2734425bb815Sopenharmony_ci  }
2735425bb815Sopenharmony_ci
2736425bb815Sopenharmony_ci  const bool global = ecma_op_to_boolean (result);
2737425bb815Sopenharmony_ci  ecma_free_value (result);
2738425bb815Sopenharmony_ci
2739425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2740425bb815Sopenharmony_ci  const lit_utf8_size_t string_length = ecma_string_get_length (string_p);
2741425bb815Sopenharmony_ci  bool unicode = false;
2742425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2743425bb815Sopenharmony_ci
2744425bb815Sopenharmony_ci  /* 10. */
2745425bb815Sopenharmony_ci  if (global)
2746425bb815Sopenharmony_ci  {
2747425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2748425bb815Sopenharmony_ci    result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_UNICODE);
2749425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2750425bb815Sopenharmony_ci    {
2751425bb815Sopenharmony_ci      goto cleanup_replace;
2752425bb815Sopenharmony_ci    }
2753425bb815Sopenharmony_ci
2754425bb815Sopenharmony_ci    unicode = ecma_op_to_boolean (result);
2755425bb815Sopenharmony_ci    ecma_free_value (result);
2756425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2757425bb815Sopenharmony_ci
2758425bb815Sopenharmony_ci    result = ecma_op_object_put (this_obj_p,
2759425bb815Sopenharmony_ci                                 ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
2760425bb815Sopenharmony_ci                                 ecma_make_uint32_value (0),
2761425bb815Sopenharmony_ci                                 true);
2762425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2763425bb815Sopenharmony_ci    {
2764425bb815Sopenharmony_ci      goto cleanup_replace;
2765425bb815Sopenharmony_ci    }
2766425bb815Sopenharmony_ci
2767425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_boolean (result));
2768425bb815Sopenharmony_ci  }
2769425bb815Sopenharmony_ci
2770425bb815Sopenharmony_ci#if !ENABLED (JERRY_ES2015)
2771425bb815Sopenharmony_ci  ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) this_obj_p;
2772425bb815Sopenharmony_ci  const re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
2773425bb815Sopenharmony_ci                                                                    re_obj_p->u.class_prop.u.value);
2774425bb815Sopenharmony_ci
2775425bb815Sopenharmony_ci  result = ecma_regexp_replace_helper_fast (&replace_ctx,
2776425bb815Sopenharmony_ci                                            bc_p,
2777425bb815Sopenharmony_ci                                            string_p,
2778425bb815Sopenharmony_ci                                            replace_arg);
2779425bb815Sopenharmony_ci
2780425bb815Sopenharmony_ci  goto cleanup_replace;
2781425bb815Sopenharmony_ci#else /* ENABLED (JERRY_ES2015) */
2782425bb815Sopenharmony_ci  result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC);
2783425bb815Sopenharmony_ci
2784425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (result))
2785425bb815Sopenharmony_ci  {
2786425bb815Sopenharmony_ci    goto cleanup_replace;
2787425bb815Sopenharmony_ci  }
2788425bb815Sopenharmony_ci
2789425bb815Sopenharmony_ci  /* Check for fast path. */
2790425bb815Sopenharmony_ci  if (ecma_op_is_callable (result))
2791425bb815Sopenharmony_ci  {
2792425bb815Sopenharmony_ci    ecma_extended_object_t *function_p = (ecma_extended_object_t *) ecma_get_object_from_value (result);
2793425bb815Sopenharmony_ci    if (ecma_object_class_is (this_obj_p, LIT_MAGIC_STRING_REGEXP_UL)
2794425bb815Sopenharmony_ci        && ecma_builtin_is_regexp_exec (function_p))
2795425bb815Sopenharmony_ci    {
2796425bb815Sopenharmony_ci      result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_STICKY);
2797425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
2798425bb815Sopenharmony_ci      {
2799425bb815Sopenharmony_ci        goto cleanup_replace;
2800425bb815Sopenharmony_ci      }
2801425bb815Sopenharmony_ci
2802425bb815Sopenharmony_ci      const bool sticky = ecma_op_to_boolean (result);
2803425bb815Sopenharmony_ci      ecma_free_value (result);
2804425bb815Sopenharmony_ci
2805425bb815Sopenharmony_ci      if (sticky && !global)
2806425bb815Sopenharmony_ci      {
2807425bb815Sopenharmony_ci        ecma_string_t *lastindex_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);
2808425bb815Sopenharmony_ci        ecma_value_t lastindex_value = ecma_op_object_get_own_data_prop (this_obj_p, lastindex_str_p);
2809425bb815Sopenharmony_ci
2810425bb815Sopenharmony_ci        result = ecma_op_to_length (lastindex_value, &replace_ctx.index);
2811425bb815Sopenharmony_ci        ecma_free_value (lastindex_value);
2812425bb815Sopenharmony_ci
2813425bb815Sopenharmony_ci        if (ECMA_IS_VALUE_ERROR (result))
2814425bb815Sopenharmony_ci        {
2815425bb815Sopenharmony_ci          goto cleanup_replace;
2816425bb815Sopenharmony_ci        }
2817425bb815Sopenharmony_ci
2818425bb815Sopenharmony_ci        if (replace_ctx.index > string_length)
2819425bb815Sopenharmony_ci        {
2820425bb815Sopenharmony_ci          ecma_deref_object ((ecma_object_t *) function_p);
2821425bb815Sopenharmony_ci
2822425bb815Sopenharmony_ci          result = ecma_op_object_put (this_obj_p,
2823425bb815Sopenharmony_ci                                       ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
2824425bb815Sopenharmony_ci                                       ecma_make_uint32_value (0),
2825425bb815Sopenharmony_ci                                       true);
2826425bb815Sopenharmony_ci          JERRY_ASSERT (ecma_is_value_true (result));
2827425bb815Sopenharmony_ci
2828425bb815Sopenharmony_ci          ecma_ref_ecma_string (string_p);
2829425bb815Sopenharmony_ci          result = ecma_make_string_value (string_p);
2830425bb815Sopenharmony_ci          goto cleanup_replace;
2831425bb815Sopenharmony_ci        }
2832425bb815Sopenharmony_ci      }
2833425bb815Sopenharmony_ci
2834425bb815Sopenharmony_ci      ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) this_obj_p;
2835425bb815Sopenharmony_ci      const re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
2836425bb815Sopenharmony_ci                                                                            re_obj_p->u.class_prop.u.value);
2837425bb815Sopenharmony_ci
2838425bb815Sopenharmony_ci      result = ecma_regexp_replace_helper_fast (&replace_ctx,
2839425bb815Sopenharmony_ci                                                bc_p,
2840425bb815Sopenharmony_ci                                                string_p,
2841425bb815Sopenharmony_ci                                                replace_arg);
2842425bb815Sopenharmony_ci
2843425bb815Sopenharmony_ci      ecma_deref_object ((ecma_object_t *) function_p);
2844425bb815Sopenharmony_ci      goto cleanup_replace;
2845425bb815Sopenharmony_ci    }
2846425bb815Sopenharmony_ci  }
2847425bb815Sopenharmony_ci
2848425bb815Sopenharmony_ci  ecma_collection_t *results_p = ecma_new_collection ();
2849425bb815Sopenharmony_ci
2850425bb815Sopenharmony_ci  while (true)
2851425bb815Sopenharmony_ci  {
2852425bb815Sopenharmony_ci    /* 13.a */
2853425bb815Sopenharmony_ci    if (ecma_op_is_callable (result))
2854425bb815Sopenharmony_ci    {
2855425bb815Sopenharmony_ci      ecma_object_t *const function_p = ecma_get_object_from_value (result);
2856425bb815Sopenharmony_ci
2857425bb815Sopenharmony_ci      ecma_value_t arguments[] = { ecma_make_string_value (string_p) };
2858425bb815Sopenharmony_ci      result = ecma_op_function_call (function_p, this_arg, arguments, 1);
2859425bb815Sopenharmony_ci
2860425bb815Sopenharmony_ci      ecma_deref_object (function_p);
2861425bb815Sopenharmony_ci
2862425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
2863425bb815Sopenharmony_ci      {
2864425bb815Sopenharmony_ci        goto cleanup_results;
2865425bb815Sopenharmony_ci      }
2866425bb815Sopenharmony_ci
2867425bb815Sopenharmony_ci      if (!ecma_is_value_object (result) && !ecma_is_value_null (result))
2868425bb815Sopenharmony_ci      {
2869425bb815Sopenharmony_ci        ecma_free_value (result);
2870425bb815Sopenharmony_ci        result = ecma_raise_type_error (ECMA_ERR_MSG ("Return value of 'exec' must be an Object or Null"));
2871425bb815Sopenharmony_ci        goto cleanup_results;
2872425bb815Sopenharmony_ci      }
2873425bb815Sopenharmony_ci    }
2874425bb815Sopenharmony_ci    else
2875425bb815Sopenharmony_ci    {
2876425bb815Sopenharmony_ci      ecma_free_value (result);
2877425bb815Sopenharmony_ci
2878425bb815Sopenharmony_ci      if (!ecma_object_class_is (this_obj_p, LIT_MAGIC_STRING_REGEXP_UL))
2879425bb815Sopenharmony_ci      {
2880425bb815Sopenharmony_ci        result = ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a valid RegExp object"));
2881425bb815Sopenharmony_ci        goto cleanup_results;
2882425bb815Sopenharmony_ci      }
2883425bb815Sopenharmony_ci
2884425bb815Sopenharmony_ci      result = ecma_regexp_exec_helper (this_obj_p, string_p);
2885425bb815Sopenharmony_ci    }
2886425bb815Sopenharmony_ci
2887425bb815Sopenharmony_ci    /* 13.c */
2888425bb815Sopenharmony_ci    if (ecma_is_value_null (result))
2889425bb815Sopenharmony_ci    {
2890425bb815Sopenharmony_ci      break;
2891425bb815Sopenharmony_ci    }
2892425bb815Sopenharmony_ci
2893425bb815Sopenharmony_ci    /* 13.d.i */
2894425bb815Sopenharmony_ci    ecma_collection_push_back (results_p, result);
2895425bb815Sopenharmony_ci
2896425bb815Sopenharmony_ci    if (!global)
2897425bb815Sopenharmony_ci    {
2898425bb815Sopenharmony_ci      break;
2899425bb815Sopenharmony_ci    }
2900425bb815Sopenharmony_ci
2901425bb815Sopenharmony_ci    /* 13.d.iii.1 */
2902425bb815Sopenharmony_ci    result = ecma_op_object_get_by_uint32_index (ecma_get_object_from_value (result), 0);
2903425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2904425bb815Sopenharmony_ci    {
2905425bb815Sopenharmony_ci      goto cleanup_results;
2906425bb815Sopenharmony_ci    }
2907425bb815Sopenharmony_ci
2908425bb815Sopenharmony_ci    ecma_string_t *match_str_p = ecma_op_to_string (result);
2909425bb815Sopenharmony_ci    ecma_free_value (result);
2910425bb815Sopenharmony_ci
2911425bb815Sopenharmony_ci    if (match_str_p == NULL)
2912425bb815Sopenharmony_ci    {
2913425bb815Sopenharmony_ci      result = ECMA_VALUE_ERROR;
2914425bb815Sopenharmony_ci      goto cleanup_results;
2915425bb815Sopenharmony_ci    }
2916425bb815Sopenharmony_ci
2917425bb815Sopenharmony_ci    const bool is_empty = ecma_string_is_empty (match_str_p);
2918425bb815Sopenharmony_ci    ecma_deref_ecma_string (match_str_p);
2919425bb815Sopenharmony_ci
2920425bb815Sopenharmony_ci    /* 13.d.iii.3 */
2921425bb815Sopenharmony_ci    if (is_empty)
2922425bb815Sopenharmony_ci    {
2923425bb815Sopenharmony_ci      result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL);
2924425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
2925425bb815Sopenharmony_ci      {
2926425bb815Sopenharmony_ci        goto cleanup_results;
2927425bb815Sopenharmony_ci      }
2928425bb815Sopenharmony_ci
2929425bb815Sopenharmony_ci      uint32_t index;
2930425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (ecma_op_to_length (result, &index)))
2931425bb815Sopenharmony_ci      {
2932425bb815Sopenharmony_ci        ecma_free_value (result);
2933425bb815Sopenharmony_ci        result = ECMA_VALUE_ERROR;
2934425bb815Sopenharmony_ci        goto cleanup_results;
2935425bb815Sopenharmony_ci      }
2936425bb815Sopenharmony_ci
2937425bb815Sopenharmony_ci      ecma_free_value (result);
2938425bb815Sopenharmony_ci
2939425bb815Sopenharmony_ci      index = ecma_op_advance_string_index (string_p, index, unicode);
2940425bb815Sopenharmony_ci
2941425bb815Sopenharmony_ci      /* 10.d.iii.3.c */
2942425bb815Sopenharmony_ci      result = ecma_op_object_put (this_obj_p,
2943425bb815Sopenharmony_ci                                   ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
2944425bb815Sopenharmony_ci                                   ecma_make_uint32_value (index),
2945425bb815Sopenharmony_ci                                   true);
2946425bb815Sopenharmony_ci
2947425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
2948425bb815Sopenharmony_ci      {
2949425bb815Sopenharmony_ci        goto cleanup_results;
2950425bb815Sopenharmony_ci      }
2951425bb815Sopenharmony_ci
2952425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_boolean (result));
2953425bb815Sopenharmony_ci    }
2954425bb815Sopenharmony_ci
2955425bb815Sopenharmony_ci    result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC);
2956425bb815Sopenharmony_ci
2957425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2958425bb815Sopenharmony_ci    {
2959425bb815Sopenharmony_ci      goto cleanup_results;
2960425bb815Sopenharmony_ci    }
2961425bb815Sopenharmony_ci  }
2962425bb815Sopenharmony_ci
2963425bb815Sopenharmony_ci  uint8_t string_flags = ECMA_STRING_FLAG_IS_ASCII;
2964425bb815Sopenharmony_ci  replace_ctx.string_p = ecma_string_get_chars (string_p,
2965425bb815Sopenharmony_ci                                                &(replace_ctx.string_size),
2966425bb815Sopenharmony_ci                                                NULL,
2967425bb815Sopenharmony_ci                                                NULL,
2968425bb815Sopenharmony_ci                                                &string_flags);
2969425bb815Sopenharmony_ci
2970425bb815Sopenharmony_ci  /* 14. */
2971425bb815Sopenharmony_ci  replace_ctx.builder = ecma_stringbuilder_create ();
2972425bb815Sopenharmony_ci  replace_ctx.matched_p = NULL;
2973425bb815Sopenharmony_ci  replace_ctx.capture_count = 0;
2974425bb815Sopenharmony_ci
2975425bb815Sopenharmony_ci  /* 15. */
2976425bb815Sopenharmony_ci  const lit_utf8_byte_t *source_position_p = replace_ctx.string_p;
2977425bb815Sopenharmony_ci  const lit_utf8_byte_t *const string_end_p = replace_ctx.string_p + replace_ctx.string_size;
2978425bb815Sopenharmony_ci
2979425bb815Sopenharmony_ci  /* 16. */
2980425bb815Sopenharmony_ci  for (ecma_value_t *current_p = results_p->buffer_p;
2981425bb815Sopenharmony_ci       current_p < results_p->buffer_p + results_p->item_count;
2982425bb815Sopenharmony_ci       current_p++)
2983425bb815Sopenharmony_ci  {
2984425bb815Sopenharmony_ci    /* 16.a */
2985425bb815Sopenharmony_ci    ecma_object_t *current_object_p = ecma_get_object_from_value (*current_p);
2986425bb815Sopenharmony_ci
2987425bb815Sopenharmony_ci    uint32_t capture_count;
2988425bb815Sopenharmony_ci    result = ecma_op_object_get_length (current_object_p, &capture_count);
2989425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
2990425bb815Sopenharmony_ci    {
2991425bb815Sopenharmony_ci      goto cleanup_builder;
2992425bb815Sopenharmony_ci    }
2993425bb815Sopenharmony_ci
2994425bb815Sopenharmony_ci    /* 16.c */
2995425bb815Sopenharmony_ci    capture_count = (capture_count > 0) ? capture_count - 1 : capture_count;
2996425bb815Sopenharmony_ci
2997425bb815Sopenharmony_ci    /* 16.d */
2998425bb815Sopenharmony_ci    result = ecma_op_object_get_by_uint32_index (current_object_p, 0);
2999425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
3000425bb815Sopenharmony_ci    {
3001425bb815Sopenharmony_ci      goto cleanup_builder;
3002425bb815Sopenharmony_ci    }
3003425bb815Sopenharmony_ci
3004425bb815Sopenharmony_ci    ecma_string_t *matched_str_p = ecma_op_to_string (result);
3005425bb815Sopenharmony_ci    ecma_free_value (result);
3006425bb815Sopenharmony_ci
3007425bb815Sopenharmony_ci    /* 16.e */
3008425bb815Sopenharmony_ci    if (matched_str_p == NULL)
3009425bb815Sopenharmony_ci    {
3010425bb815Sopenharmony_ci      result = ECMA_VALUE_ERROR;
3011425bb815Sopenharmony_ci      goto cleanup_builder;
3012425bb815Sopenharmony_ci    }
3013425bb815Sopenharmony_ci
3014425bb815Sopenharmony_ci    /* 16.g */
3015425bb815Sopenharmony_ci    result = ecma_op_object_get_by_magic_id (current_object_p, LIT_MAGIC_STRING_INDEX);
3016425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
3017425bb815Sopenharmony_ci    {
3018425bb815Sopenharmony_ci      ecma_deref_ecma_string (matched_str_p);
3019425bb815Sopenharmony_ci      goto cleanup_builder;
3020425bb815Sopenharmony_ci    }
3021425bb815Sopenharmony_ci
3022425bb815Sopenharmony_ci    const ecma_value_t index_value = result;
3023425bb815Sopenharmony_ci
3024425bb815Sopenharmony_ci    ecma_number_t position_num;
3025425bb815Sopenharmony_ci    result = ecma_op_to_integer (index_value, &position_num);
3026425bb815Sopenharmony_ci    ecma_free_value (index_value);
3027425bb815Sopenharmony_ci
3028425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
3029425bb815Sopenharmony_ci    {
3030425bb815Sopenharmony_ci      ecma_deref_ecma_string (matched_str_p);
3031425bb815Sopenharmony_ci      goto cleanup_builder;
3032425bb815Sopenharmony_ci    }
3033425bb815Sopenharmony_ci
3034425bb815Sopenharmony_ci    /* 16.i */
3035425bb815Sopenharmony_ci    lit_utf8_size_t position = JERRY_MIN ((lit_utf8_size_t) JERRY_MAX (position_num, 0.0f), string_length);
3036425bb815Sopenharmony_ci
3037425bb815Sopenharmony_ci    /* 16.k */
3038425bb815Sopenharmony_ci    ecma_collection_t *arguments_p = ecma_new_collection ();
3039425bb815Sopenharmony_ci    ecma_collection_push_back (arguments_p, ecma_make_string_value (matched_str_p));
3040425bb815Sopenharmony_ci
3041425bb815Sopenharmony_ci    /* 16.j, l */
3042425bb815Sopenharmony_ci    uint32_t n = 1;
3043425bb815Sopenharmony_ci    while (n <= capture_count)
3044425bb815Sopenharmony_ci    {
3045425bb815Sopenharmony_ci      result = ecma_op_object_get_by_uint32_index (current_object_p, n);
3046425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
3047425bb815Sopenharmony_ci      {
3048425bb815Sopenharmony_ci        ecma_collection_free (arguments_p);
3049425bb815Sopenharmony_ci        goto cleanup_builder;
3050425bb815Sopenharmony_ci      }
3051425bb815Sopenharmony_ci
3052425bb815Sopenharmony_ci      /* 16.l.iii */
3053425bb815Sopenharmony_ci      if (!ecma_is_value_undefined (result))
3054425bb815Sopenharmony_ci      {
3055425bb815Sopenharmony_ci        ecma_string_t *capture_str_p = ecma_op_to_string (result);
3056425bb815Sopenharmony_ci        ecma_free_value (result);
3057425bb815Sopenharmony_ci
3058425bb815Sopenharmony_ci        if (capture_str_p == NULL)
3059425bb815Sopenharmony_ci        {
3060425bb815Sopenharmony_ci          ecma_collection_free (arguments_p);
3061425bb815Sopenharmony_ci          result = ECMA_VALUE_ERROR;
3062425bb815Sopenharmony_ci          goto cleanup_builder;
3063425bb815Sopenharmony_ci        }
3064425bb815Sopenharmony_ci
3065425bb815Sopenharmony_ci        result = ecma_make_string_value (capture_str_p);
3066425bb815Sopenharmony_ci      }
3067425bb815Sopenharmony_ci
3068425bb815Sopenharmony_ci      /* 16.l.iv */
3069425bb815Sopenharmony_ci      ecma_collection_push_back (arguments_p, result);
3070425bb815Sopenharmony_ci      n++;
3071425bb815Sopenharmony_ci    }
3072425bb815Sopenharmony_ci
3073425bb815Sopenharmony_ci    const bool should_replace = (position >= replace_ctx.index);
3074425bb815Sopenharmony_ci    /* 16.p */
3075425bb815Sopenharmony_ci    if (should_replace)
3076425bb815Sopenharmony_ci    {
3077425bb815Sopenharmony_ci      const lit_utf8_byte_t *match_position_p;
3078425bb815Sopenharmony_ci      const lit_utf8_size_t matched_str_size = ecma_string_get_size (matched_str_p);
3079425bb815Sopenharmony_ci      const lit_utf8_size_t matched_str_length = ecma_string_get_length (matched_str_p);
3080425bb815Sopenharmony_ci
3081425bb815Sopenharmony_ci      if (string_flags & ECMA_STRING_FLAG_IS_ASCII)
3082425bb815Sopenharmony_ci      {
3083425bb815Sopenharmony_ci        match_position_p = replace_ctx.string_p + position;
3084425bb815Sopenharmony_ci      }
3085425bb815Sopenharmony_ci      else
3086425bb815Sopenharmony_ci      {
3087425bb815Sopenharmony_ci        match_position_p = source_position_p;
3088425bb815Sopenharmony_ci        lit_utf8_size_t distance = position - replace_ctx.index;
3089425bb815Sopenharmony_ci        while (distance--)
3090425bb815Sopenharmony_ci        {
3091425bb815Sopenharmony_ci          lit_utf8_incr (&match_position_p);
3092425bb815Sopenharmony_ci        }
3093425bb815Sopenharmony_ci      }
3094425bb815Sopenharmony_ci
3095425bb815Sopenharmony_ci      ecma_stringbuilder_append_raw (&replace_ctx.builder,
3096425bb815Sopenharmony_ci                                    source_position_p,
3097425bb815Sopenharmony_ci                                    (lit_utf8_size_t) (match_position_p - source_position_p));
3098425bb815Sopenharmony_ci      replace_ctx.match_byte_pos = (lit_utf8_size_t) (match_position_p - replace_ctx.string_p);
3099425bb815Sopenharmony_ci
3100425bb815Sopenharmony_ci      if ((string_flags & ECMA_STRING_FLAG_IS_ASCII) && matched_str_size == matched_str_length)
3101425bb815Sopenharmony_ci      {
3102425bb815Sopenharmony_ci        source_position_p = JERRY_MIN (match_position_p + matched_str_size, string_end_p);
3103425bb815Sopenharmony_ci      }
3104425bb815Sopenharmony_ci      else
3105425bb815Sopenharmony_ci      {
3106425bb815Sopenharmony_ci        lit_utf8_size_t code_unit_count = matched_str_length;
3107425bb815Sopenharmony_ci
3108425bb815Sopenharmony_ci        while (code_unit_count-- > 0 && JERRY_LIKELY (match_position_p < string_end_p))
3109425bb815Sopenharmony_ci        {
3110425bb815Sopenharmony_ci          lit_utf8_incr (&match_position_p);
3111425bb815Sopenharmony_ci        }
3112425bb815Sopenharmony_ci
3113425bb815Sopenharmony_ci        source_position_p = match_position_p;
3114425bb815Sopenharmony_ci      }
3115425bb815Sopenharmony_ci
3116425bb815Sopenharmony_ci      replace_ctx.index = JERRY_MIN (position + matched_str_length, string_length);
3117425bb815Sopenharmony_ci    }
3118425bb815Sopenharmony_ci
3119425bb815Sopenharmony_ci    /* 16.m */
3120425bb815Sopenharmony_ci    if (replace_ctx.replace_str_p == NULL)
3121425bb815Sopenharmony_ci    {
3122425bb815Sopenharmony_ci      /* 16.m.i-ii.
3123425bb815Sopenharmony_ci       * arguments_p already contains <<Matched, cap1, cap2, ..., capN>> */
3124425bb815Sopenharmony_ci
3125425bb815Sopenharmony_ci      /* 16.m.iii */
3126425bb815Sopenharmony_ci      ecma_collection_push_back (arguments_p, ecma_make_uint32_value (position));
3127425bb815Sopenharmony_ci      ecma_ref_ecma_string (string_p);
3128425bb815Sopenharmony_ci      ecma_collection_push_back (arguments_p, ecma_make_string_value (string_p));
3129425bb815Sopenharmony_ci
3130425bb815Sopenharmony_ci      result = ecma_op_function_call (ecma_get_object_from_value (replace_arg),
3131425bb815Sopenharmony_ci                                      ECMA_VALUE_UNDEFINED,
3132425bb815Sopenharmony_ci                                      arguments_p->buffer_p,
3133425bb815Sopenharmony_ci                                      arguments_p->item_count);
3134425bb815Sopenharmony_ci
3135425bb815Sopenharmony_ci      ecma_collection_free (arguments_p);
3136425bb815Sopenharmony_ci
3137425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
3138425bb815Sopenharmony_ci      {
3139425bb815Sopenharmony_ci        goto cleanup_builder;
3140425bb815Sopenharmony_ci      }
3141425bb815Sopenharmony_ci
3142425bb815Sopenharmony_ci      /* 16.m.v */
3143425bb815Sopenharmony_ci      ecma_string_t *const replace_result_p = ecma_op_to_string (result);
3144425bb815Sopenharmony_ci      ecma_free_value (result);
3145425bb815Sopenharmony_ci
3146425bb815Sopenharmony_ci      if (replace_result_p == NULL)
3147425bb815Sopenharmony_ci      {
3148425bb815Sopenharmony_ci        result = ECMA_VALUE_ERROR;
3149425bb815Sopenharmony_ci        goto cleanup_builder;
3150425bb815Sopenharmony_ci      }
3151425bb815Sopenharmony_ci
3152425bb815Sopenharmony_ci      /* 16.m/p */
3153425bb815Sopenharmony_ci      if (should_replace)
3154425bb815Sopenharmony_ci      {
3155425bb815Sopenharmony_ci        ecma_stringbuilder_append (&replace_ctx.builder, replace_result_p);
3156425bb815Sopenharmony_ci      }
3157425bb815Sopenharmony_ci
3158425bb815Sopenharmony_ci      ecma_deref_ecma_string (replace_result_p);
3159425bb815Sopenharmony_ci    }
3160425bb815Sopenharmony_ci    else
3161425bb815Sopenharmony_ci    {
3162425bb815Sopenharmony_ci      /* 16.n/p */
3163425bb815Sopenharmony_ci      if (should_replace)
3164425bb815Sopenharmony_ci      {
3165425bb815Sopenharmony_ci        replace_ctx.u.collection_p = arguments_p;
3166425bb815Sopenharmony_ci        ecma_builtin_replace_substitute (&replace_ctx);
3167425bb815Sopenharmony_ci      }
3168425bb815Sopenharmony_ci
3169425bb815Sopenharmony_ci      ecma_collection_free (arguments_p);
3170425bb815Sopenharmony_ci    }
3171425bb815Sopenharmony_ci  }
3172425bb815Sopenharmony_ci
3173425bb815Sopenharmony_ci  /* 18. */
3174425bb815Sopenharmony_ci  JERRY_ASSERT (replace_ctx.index <= string_length);
3175425bb815Sopenharmony_ci  ecma_stringbuilder_append_raw (&(replace_ctx.builder),
3176425bb815Sopenharmony_ci                                 source_position_p,
3177425bb815Sopenharmony_ci                                 (lit_utf8_size_t) (string_end_p - source_position_p));
3178425bb815Sopenharmony_ci
3179425bb815Sopenharmony_ci  result = ecma_make_string_value (ecma_stringbuilder_finalize (&replace_ctx.builder));
3180425bb815Sopenharmony_ci  goto cleanup_chars;
3181425bb815Sopenharmony_ci
3182425bb815Sopenharmony_cicleanup_builder:
3183425bb815Sopenharmony_ci  ecma_stringbuilder_destroy (&replace_ctx.builder);
3184425bb815Sopenharmony_ci
3185425bb815Sopenharmony_cicleanup_chars:
3186425bb815Sopenharmony_ci  if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED)
3187425bb815Sopenharmony_ci  {
3188425bb815Sopenharmony_ci    jmem_heap_free_block ((void *) replace_ctx.string_p, replace_ctx.string_size);
3189425bb815Sopenharmony_ci  }
3190425bb815Sopenharmony_ci
3191425bb815Sopenharmony_cicleanup_results:
3192425bb815Sopenharmony_ci  ecma_collection_free (results_p);
3193425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015) */
3194425bb815Sopenharmony_ci
3195425bb815Sopenharmony_cicleanup_replace:
3196425bb815Sopenharmony_ci  if (replace_ctx.replace_str_p != NULL)
3197425bb815Sopenharmony_ci  {
3198425bb815Sopenharmony_ci    ecma_deref_ecma_string (replace_ctx.replace_str_p);
3199425bb815Sopenharmony_ci  }
3200425bb815Sopenharmony_ci
3201425bb815Sopenharmony_cicleanup_string:
3202425bb815Sopenharmony_ci  ecma_deref_ecma_string (string_p);
3203425bb815Sopenharmony_ci
3204425bb815Sopenharmony_ci  return result;
3205425bb815Sopenharmony_ci} /* ecma_regexp_replace_helper */
3206425bb815Sopenharmony_ci
3207425bb815Sopenharmony_ci/**
3208425bb815Sopenharmony_ci * Helper function for RegExp based matching
3209425bb815Sopenharmony_ci *
3210425bb815Sopenharmony_ci * See also:
3211425bb815Sopenharmony_ci *          String.prototype.match
3212425bb815Sopenharmony_ci *          RegExp.prototype[@@match]
3213425bb815Sopenharmony_ci *
3214425bb815Sopenharmony_ci * @return ecma_value_t
3215425bb815Sopenharmony_ci */
3216425bb815Sopenharmony_ciecma_value_t
3217425bb815Sopenharmony_ciecma_regexp_match_helper (ecma_value_t this_arg, /**< this argument */
3218425bb815Sopenharmony_ci                          ecma_value_t string_arg) /**< source string */
3219425bb815Sopenharmony_ci{
3220425bb815Sopenharmony_ci  if (!ecma_is_value_object (this_arg))
3221425bb815Sopenharmony_ci  {
3222425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
3223425bb815Sopenharmony_ci  }
3224425bb815Sopenharmony_ci
3225425bb815Sopenharmony_ci  ecma_string_t *str_p = ecma_op_to_string (string_arg);
3226425bb815Sopenharmony_ci
3227425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (str_p == NULL))
3228425bb815Sopenharmony_ci  {
3229425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
3230425bb815Sopenharmony_ci  }
3231425bb815Sopenharmony_ci
3232425bb815Sopenharmony_ci  ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
3233425bb815Sopenharmony_ci
3234425bb815Sopenharmony_ci  ecma_value_t global_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_GLOBAL);
3235425bb815Sopenharmony_ci
3236425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (global_value))
3237425bb815Sopenharmony_ci  {
3238425bb815Sopenharmony_ci    ecma_deref_ecma_string (str_p);
3239425bb815Sopenharmony_ci    return global_value;
3240425bb815Sopenharmony_ci  }
3241425bb815Sopenharmony_ci
3242425bb815Sopenharmony_ci  bool global = ecma_op_to_boolean (global_value);
3243425bb815Sopenharmony_ci
3244425bb815Sopenharmony_ci  ecma_free_value (global_value);
3245425bb815Sopenharmony_ci
3246425bb815Sopenharmony_ci  if (!global)
3247425bb815Sopenharmony_ci  {
3248425bb815Sopenharmony_ci    ecma_value_t result = ecma_op_regexp_exec (this_arg, str_p);
3249425bb815Sopenharmony_ci    ecma_deref_ecma_string (str_p);
3250425bb815Sopenharmony_ci    return result;
3251425bb815Sopenharmony_ci  }
3252425bb815Sopenharmony_ci
3253425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
3254425bb815Sopenharmony_ci  ecma_value_t full_unicode_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_UNICODE);
3255425bb815Sopenharmony_ci
3256425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (full_unicode_value))
3257425bb815Sopenharmony_ci  {
3258425bb815Sopenharmony_ci    ecma_deref_ecma_string (str_p);
3259425bb815Sopenharmony_ci    return full_unicode_value;
3260425bb815Sopenharmony_ci  }
3261425bb815Sopenharmony_ci
3262425bb815Sopenharmony_ci  bool full_unicode = ecma_op_to_boolean (full_unicode_value);
3263425bb815Sopenharmony_ci
3264425bb815Sopenharmony_ci  ecma_free_value (full_unicode_value);
3265425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
3266425bb815Sopenharmony_ci
3267425bb815Sopenharmony_ci  ecma_value_t set_status = ecma_op_object_put (obj_p,
3268425bb815Sopenharmony_ci                                                ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
3269425bb815Sopenharmony_ci                                                ecma_make_uint32_value (0),
3270425bb815Sopenharmony_ci                                                true);
3271425bb815Sopenharmony_ci
3272425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (set_status))
3273425bb815Sopenharmony_ci  {
3274425bb815Sopenharmony_ci    ecma_deref_ecma_string (str_p);
3275425bb815Sopenharmony_ci    return set_status;
3276425bb815Sopenharmony_ci  }
3277425bb815Sopenharmony_ci
3278425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_ERROR;
3279425bb815Sopenharmony_ci  ecma_value_t result_array = ecma_op_create_array_object (0, 0, false);
3280425bb815Sopenharmony_ci  ecma_object_t *result_array_p = ecma_get_object_from_value (result_array);
3281425bb815Sopenharmony_ci  uint32_t n = 0;
3282425bb815Sopenharmony_ci
3283425bb815Sopenharmony_ci  while (true)
3284425bb815Sopenharmony_ci  {
3285425bb815Sopenharmony_ci    ecma_value_t result_value = ecma_op_regexp_exec (this_arg, str_p);
3286425bb815Sopenharmony_ci
3287425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result_value))
3288425bb815Sopenharmony_ci    {
3289425bb815Sopenharmony_ci      goto result_cleanup;
3290425bb815Sopenharmony_ci    }
3291425bb815Sopenharmony_ci
3292425bb815Sopenharmony_ci    if (ecma_is_value_null (result_value))
3293425bb815Sopenharmony_ci    {
3294425bb815Sopenharmony_ci      if (n == 0)
3295425bb815Sopenharmony_ci      {
3296425bb815Sopenharmony_ci        ret_value = ECMA_VALUE_NULL;
3297425bb815Sopenharmony_ci        goto result_cleanup;
3298425bb815Sopenharmony_ci      }
3299425bb815Sopenharmony_ci
3300425bb815Sopenharmony_ci      ecma_deref_ecma_string (str_p);
3301425bb815Sopenharmony_ci      return result_array;
3302425bb815Sopenharmony_ci    }
3303425bb815Sopenharmony_ci
3304425bb815Sopenharmony_ci    ecma_object_t *result_value_p = ecma_get_object_from_value (result_value);
3305425bb815Sopenharmony_ci    ecma_value_t match_str_value = ecma_op_object_get_by_uint32_index (result_value_p, 0);
3306425bb815Sopenharmony_ci
3307425bb815Sopenharmony_ci    ecma_deref_object (result_value_p);
3308425bb815Sopenharmony_ci
3309425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (match_str_value))
3310425bb815Sopenharmony_ci    {
3311425bb815Sopenharmony_ci      goto result_cleanup;
3312425bb815Sopenharmony_ci    }
3313425bb815Sopenharmony_ci
3314425bb815Sopenharmony_ci    ecma_string_t *match_str_p = ecma_op_to_string (match_str_value);
3315425bb815Sopenharmony_ci
3316425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (match_str_p == NULL))
3317425bb815Sopenharmony_ci    {
3318425bb815Sopenharmony_ci      ecma_free_value (match_str_value);
3319425bb815Sopenharmony_ci      goto result_cleanup;
3320425bb815Sopenharmony_ci    }
3321425bb815Sopenharmony_ci
3322425bb815Sopenharmony_ci    ecma_value_t new_prop = ecma_builtin_helper_def_prop_by_index (result_array_p,
3323425bb815Sopenharmony_ci                                                                   n,
3324425bb815Sopenharmony_ci                                                                   match_str_value,
3325425bb815Sopenharmony_ci                                                                   ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
3326425bb815Sopenharmony_ci
3327425bb815Sopenharmony_ci    JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_prop));
3328425bb815Sopenharmony_ci
3329425bb815Sopenharmony_ci    ecma_value_t match_result = ECMA_VALUE_ERROR;
3330425bb815Sopenharmony_ci    if (ecma_string_is_empty (match_str_p))
3331425bb815Sopenharmony_ci    {
3332425bb815Sopenharmony_ci      ecma_value_t this_index = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LASTINDEX_UL);
3333425bb815Sopenharmony_ci
3334425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (this_index))
3335425bb815Sopenharmony_ci      {
3336425bb815Sopenharmony_ci        goto match_cleanup;
3337425bb815Sopenharmony_ci      }
3338425bb815Sopenharmony_ci
3339425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
3340425bb815Sopenharmony_ci      uint32_t index;
3341425bb815Sopenharmony_ci      ecma_value_t length_value = ecma_op_to_length (this_index, &index);
3342425bb815Sopenharmony_ci
3343425bb815Sopenharmony_ci      ecma_free_value (this_index);
3344425bb815Sopenharmony_ci
3345425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (length_value))
3346425bb815Sopenharmony_ci      {
3347425bb815Sopenharmony_ci        goto match_cleanup;
3348425bb815Sopenharmony_ci      }
3349425bb815Sopenharmony_ci
3350425bb815Sopenharmony_ci      uint32_t next_index = ecma_op_advance_string_index (str_p, index, full_unicode);
3351425bb815Sopenharmony_ci
3352425bb815Sopenharmony_ci      ecma_value_t next_set_status = ecma_op_object_put (obj_p,
3353425bb815Sopenharmony_ci                                                         ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
3354425bb815Sopenharmony_ci                                                         ecma_make_uint32_value (next_index),
3355425bb815Sopenharmony_ci                                                         true);
3356425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
3357425bb815Sopenharmony_ci      ecma_number_t next_index = ecma_get_number_from_value (this_index);
3358425bb815Sopenharmony_ci
3359425bb815Sopenharmony_ci      ecma_value_t next_set_status = ecma_op_object_put (obj_p,
3360425bb815Sopenharmony_ci                                                         ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
3361425bb815Sopenharmony_ci                                                         ecma_make_number_value (next_index + 1),
3362425bb815Sopenharmony_ci                                                         true);
3363425bb815Sopenharmony_ci
3364425bb815Sopenharmony_ci      ecma_free_value (this_index);
3365425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
3366425bb815Sopenharmony_ci
3367425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (next_set_status))
3368425bb815Sopenharmony_ci      {
3369425bb815Sopenharmony_ci        goto match_cleanup;
3370425bb815Sopenharmony_ci      }
3371425bb815Sopenharmony_ci    }
3372425bb815Sopenharmony_ci
3373425bb815Sopenharmony_ci    match_result = ECMA_VALUE_EMPTY;
3374425bb815Sopenharmony_ci
3375425bb815Sopenharmony_cimatch_cleanup:
3376425bb815Sopenharmony_ci    ecma_deref_ecma_string (match_str_p);
3377425bb815Sopenharmony_ci    ecma_free_value (match_str_value);
3378425bb815Sopenharmony_ci
3379425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (match_result))
3380425bb815Sopenharmony_ci    {
3381425bb815Sopenharmony_ci      goto result_cleanup;
3382425bb815Sopenharmony_ci    }
3383425bb815Sopenharmony_ci
3384425bb815Sopenharmony_ci    n++;
3385425bb815Sopenharmony_ci  }
3386425bb815Sopenharmony_ci
3387425bb815Sopenharmony_ciresult_cleanup:
3388425bb815Sopenharmony_ci  ecma_deref_ecma_string (str_p);
3389425bb815Sopenharmony_ci  ecma_deref_object (result_array_p);
3390425bb815Sopenharmony_ci  return ret_value;
3391425bb815Sopenharmony_ci} /* ecma_regexp_match_helper */
3392425bb815Sopenharmony_ci
3393425bb815Sopenharmony_ci/**
3394425bb815Sopenharmony_ci * RegExpExec operation
3395425bb815Sopenharmony_ci *
3396425bb815Sopenharmony_ci * See also:
3397425bb815Sopenharmony_ci *          ECMA-262 v6.0, 21.2.5.2.1
3398425bb815Sopenharmony_ci *
3399425bb815Sopenharmony_ci * @return ecma value
3400425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
3401425bb815Sopenharmony_ci */
3402425bb815Sopenharmony_ciecma_value_t
3403425bb815Sopenharmony_ciecma_op_regexp_exec (ecma_value_t this_arg, /**< this argument */
3404425bb815Sopenharmony_ci                     ecma_string_t *str_p) /**< input string */
3405425bb815Sopenharmony_ci{
3406425bb815Sopenharmony_ci  ecma_object_t *arg_obj_p = ecma_get_object_from_value (this_arg);
3407425bb815Sopenharmony_ci
3408425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
3409425bb815Sopenharmony_ci  ecma_value_t exec = ecma_op_object_get_by_magic_id (arg_obj_p, LIT_MAGIC_STRING_EXEC);
3410425bb815Sopenharmony_ci
3411425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (exec))
3412425bb815Sopenharmony_ci  {
3413425bb815Sopenharmony_ci    return exec;
3414425bb815Sopenharmony_ci  }
3415425bb815Sopenharmony_ci
3416425bb815Sopenharmony_ci  if (ecma_op_is_callable (exec))
3417425bb815Sopenharmony_ci  {
3418425bb815Sopenharmony_ci    ecma_object_t *function_p = ecma_get_object_from_value (exec);
3419425bb815Sopenharmony_ci    ecma_value_t arguments[] = { ecma_make_string_value (str_p) };
3420425bb815Sopenharmony_ci
3421425bb815Sopenharmony_ci    ecma_value_t result = ecma_op_function_call (function_p, this_arg, arguments, 1);
3422425bb815Sopenharmony_ci
3423425bb815Sopenharmony_ci    ecma_deref_object (function_p);
3424425bb815Sopenharmony_ci
3425425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (result))
3426425bb815Sopenharmony_ci    {
3427425bb815Sopenharmony_ci      return result;
3428425bb815Sopenharmony_ci    }
3429425bb815Sopenharmony_ci
3430425bb815Sopenharmony_ci    if (!ecma_is_value_object (result) && !ecma_is_value_null (result))
3431425bb815Sopenharmony_ci    {
3432425bb815Sopenharmony_ci      ecma_free_value (result);
3433425bb815Sopenharmony_ci      return ecma_raise_type_error (ECMA_ERR_MSG ("Return value of 'exec' must be an Object or Null"));
3434425bb815Sopenharmony_ci    }
3435425bb815Sopenharmony_ci
3436425bb815Sopenharmony_ci    return result;
3437425bb815Sopenharmony_ci  }
3438425bb815Sopenharmony_ci  else
3439425bb815Sopenharmony_ci  {
3440425bb815Sopenharmony_ci    ecma_free_value (exec);
3441425bb815Sopenharmony_ci  }
3442425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
3443425bb815Sopenharmony_ci
3444425bb815Sopenharmony_ci  if (!ecma_object_is_regexp_object (this_arg))
3445425bb815Sopenharmony_ci  {
3446425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a valid RegExp object"));
3447425bb815Sopenharmony_ci  }
3448425bb815Sopenharmony_ci
3449425bb815Sopenharmony_ci  return ecma_regexp_exec_helper (arg_obj_p, str_p);
3450425bb815Sopenharmony_ci} /* ecma_op_regexp_exec */
3451425bb815Sopenharmony_ci
3452425bb815Sopenharmony_ci/**
3453425bb815Sopenharmony_ci * @}
3454425bb815Sopenharmony_ci * @}
3455425bb815Sopenharmony_ci */
3456425bb815Sopenharmony_ci
3457425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
3458