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 (¤t_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 (¤t_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 (¤t_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 (¤t_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 (¤t_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