1 /* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecma-alloc.h"
17 #include "ecma-array-object.h"
18 #include "ecma-builtins.h"
19 #include "ecma-builtin-helpers.h"
20 #include "ecma-conversion.h"
21 #include "ecma-exceptions.h"
22 #include "ecma-function-object.h"
23 #include "ecma-globals.h"
24 #include "ecma-gc.h"
25 #include "ecma-helpers.h"
26 #include "ecma-objects.h"
27 #include "ecma-regexp-object.h"
28 #include "ecma-try-catch-macro.h"
29 #include "lit-char-helpers.h"
30
31 #if ENABLED (JERRY_BUILTIN_REGEXP)
32 #include "ecma-regexp-object.h"
33 #include "re-compiler.h"
34
35 #define ECMA_BUILTINS_INTERNAL
36 #include "ecma-builtins-internal.h"
37
38 #define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp-prototype.inc.h"
39 #define BUILTIN_UNDERSCORED_ID regexp_prototype
40 #include "ecma-builtin-internal-routines-template.inc.h"
41
42 /** \addtogroup ecma ECMA
43 * @{
44 *
45 * \addtogroup ecmabuiltins
46 * @{
47 *
48 * \addtogroup regexpprototype ECMA RegExp.prototype object built-in
49 * @{
50 */
51
52 #if ENABLED (JERRY_ES2015)
53 /**
54 * Helper function to retrieve the flags associated with a RegExp object
55 *
56 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
57 * ECMA_VALUE_EMPTY - otherwise
58 */
59 static ecma_value_t
ecma_builtin_regexp_prototype_flags_helper(ecma_value_t this,uint16_t * flags_p)60 ecma_builtin_regexp_prototype_flags_helper (ecma_value_t this, /**< this value */
61 uint16_t *flags_p) /**< [out] flags */
62 {
63 if (!ecma_object_is_regexp_object (this))
64 {
65 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a RegExp object"));
66 }
67
68 ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (this);
69 re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
70 re_obj_p->u.class_prop.u.value);
71
72 *flags_p = bc_p->header.status_flags;
73 return ECMA_VALUE_EMPTY;
74 } /* ecma_builtin_regexp_prototype_flags_helper */
75
76 /**
77 * The RegExp.prototype object's 'flags' accessor property
78 *
79 * See also:
80 * ECMA-262 v6, 21.2.5.3
81 *
82 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
83 * string value - otherwise
84 *
85 * Returned value must be freed with ecma_free_value.
86 */
87 static ecma_value_t
ecma_builtin_regexp_prototype_get_flags(ecma_value_t this_arg)88 ecma_builtin_regexp_prototype_get_flags (ecma_value_t this_arg) /**< this argument */
89 {
90 static const lit_magic_string_id_t flag_lit_ids[] =
91 {
92 LIT_MAGIC_STRING_GLOBAL,
93 LIT_MAGIC_STRING_IGNORECASE_UL,
94 LIT_MAGIC_STRING_MULTILINE,
95 LIT_MAGIC_STRING_UNICODE,
96 LIT_MAGIC_STRING_STICKY
97 };
98
99 static const lit_utf8_byte_t flag_chars[] =
100 {
101 LIT_CHAR_LOWERCASE_G,
102 LIT_CHAR_LOWERCASE_I,
103 LIT_CHAR_LOWERCASE_M,
104 LIT_CHAR_LOWERCASE_U,
105 LIT_CHAR_LOWERCASE_Y
106 };
107
108 if (!ecma_is_value_object (this_arg))
109 {
110 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' value is not an object."));
111 }
112
113 ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
114
115 ecma_stringbuilder_t builder = ecma_stringbuilder_create ();
116 for (uint32_t i = 0; i < sizeof (flag_lit_ids) / sizeof (lit_magic_string_id_t); i++)
117 {
118 ecma_value_t result = ecma_op_object_get_by_magic_id (object_p, flag_lit_ids[i]);
119 if (ECMA_IS_VALUE_ERROR (result))
120 {
121 ecma_stringbuilder_destroy (&builder);
122 return result;
123 }
124
125 if (ecma_op_to_boolean (result))
126 {
127 ecma_stringbuilder_append_byte (&builder, flag_chars[i]);
128 }
129
130 ecma_free_value (result);
131 }
132
133 return ecma_make_string_value (ecma_stringbuilder_finalize (&builder));
134 } /* ecma_builtin_regexp_prototype_get_flags */
135
136 /**
137 * The EscapeRegExpPattern method.
138 *
139 * See also:
140 * ECMA-262 v6, 21.2.3.2.4
141 *
142 * @return ecma_value_t
143 */
144 static ecma_value_t
ecma_op_escape_regexp_pattern(ecma_string_t * pattern_str_p)145 ecma_op_escape_regexp_pattern (ecma_string_t *pattern_str_p) /**< RegExp pattern */
146 {
147 ecma_stringbuilder_t builder = ecma_stringbuilder_create ();
148
149 ECMA_STRING_TO_UTF8_STRING (pattern_str_p, pattern_start_p, pattern_start_size);
150
151 const lit_utf8_byte_t *pattern_str_curr_p = pattern_start_p;
152 const lit_utf8_byte_t *pattern_str_end_p = pattern_start_p + pattern_start_size;
153
154 while (pattern_str_curr_p < pattern_str_end_p)
155 {
156 ecma_char_t c = lit_cesu8_read_next (&pattern_str_curr_p);
157
158 switch (c)
159 {
160 case LIT_CHAR_SLASH:
161 {
162 ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\/", 2);
163 break;
164 }
165 case LIT_CHAR_LF:
166 {
167 ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\n", 2);
168 break;
169 }
170 case LIT_CHAR_CR:
171 {
172 ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\r", 2);
173 break;
174 }
175 case LIT_CHAR_LS:
176 {
177 ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2028", 6);
178 break;
179 }
180 case LIT_CHAR_PS:
181 {
182 ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2029", 6);
183 break;
184 }
185 case LIT_CHAR_BACKSLASH:
186 {
187 JERRY_ASSERT (pattern_str_curr_p < pattern_str_end_p);
188 ecma_stringbuilder_append_char (&builder, LIT_CHAR_BACKSLASH);
189 ecma_stringbuilder_append_char (&builder, lit_cesu8_read_next (&pattern_str_curr_p));
190 break;
191 }
192 default:
193 {
194 ecma_stringbuilder_append_char (&builder, c);
195 break;
196 }
197 }
198 }
199
200 ECMA_FINALIZE_UTF8_STRING (pattern_start_p, pattern_start_size);
201
202 return ecma_make_string_value (ecma_stringbuilder_finalize (&builder));
203 } /* ecma_op_escape_regexp_pattern */
204
205 /**
206 * The RegExp.prototype object's 'source' accessor property
207 *
208 * See also:
209 * ECMA-262 v6, 21.2.5.10
210 *
211 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
212 * string value - otherwise
213 *
214 * Returned value must be freed with ecma_free_value.
215 */
216 static ecma_value_t
ecma_builtin_regexp_prototype_get_source(ecma_value_t this_arg)217 ecma_builtin_regexp_prototype_get_source (ecma_value_t this_arg) /**< this argument */
218 {
219 if (!ecma_object_is_regexp_object (this_arg))
220 {
221 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a RegExp object"));
222 }
223
224 ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (this_arg);
225 re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
226 re_obj_p->u.class_prop.u.value);
227
228 return ecma_op_escape_regexp_pattern (ecma_get_string_from_value (bc_p->source));
229 } /* ecma_builtin_regexp_prototype_get_source */
230
231 /**
232 * The RegExp.prototype object's 'global' accessor property
233 *
234 * See also:
235 * ECMA-262 v6, 21.2.5.4
236 *
237 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
238 * ECMA_VALUE_TRUE - if 'global' flag is set
239 * ECMA_VALUE_FALSE - otherwise
240 *
241 * Returned value must be freed with ecma_free_value.
242 */
243 static ecma_value_t
ecma_builtin_regexp_prototype_get_global(ecma_value_t this_arg)244 ecma_builtin_regexp_prototype_get_global (ecma_value_t this_arg) /**< this argument */
245 {
246 uint16_t flags = RE_FLAG_EMPTY;
247 ecma_value_t ret_value = ecma_builtin_regexp_prototype_flags_helper (this_arg, &flags);
248 if (ECMA_IS_VALUE_ERROR (ret_value))
249 {
250 return ret_value;
251 }
252
253 return ecma_make_boolean_value (flags & RE_FLAG_GLOBAL);
254 } /* ecma_builtin_regexp_prototype_get_global */
255
256 /**
257 * The RegExp.prototype object's 'ignoreCase' accessor property
258 *
259 * See also:
260 * ECMA-262 v6, 21.2.5.5
261 *
262 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
263 * ECMA_VALUE_TRUE - if 'ignoreCase' flag is set
264 * ECMA_VALUE_FALSE - otherwise
265 *
266 * Returned value must be freed with ecma_free_value.
267 */
268 static ecma_value_t
ecma_builtin_regexp_prototype_get_ignorecase(ecma_value_t this_arg)269 ecma_builtin_regexp_prototype_get_ignorecase (ecma_value_t this_arg) /**< this argument */
270 {
271 uint16_t flags = RE_FLAG_EMPTY;
272 ecma_value_t ret_value = ecma_builtin_regexp_prototype_flags_helper (this_arg, &flags);
273 if (ECMA_IS_VALUE_ERROR (ret_value))
274 {
275 return ret_value;
276 }
277
278 return ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE);
279 } /* ecma_builtin_regexp_prototype_get_ignorecase */
280
281 /**
282 * The RegExp.prototype object's 'multiline' accessor property
283 *
284 * See also:
285 * ECMA-262 v6, 21.2.5.7
286 *
287 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
288 * ECMA_VALUE_TRUE - if 'multiline' flag is set
289 * ECMA_VALUE_FALSE - otherwise
290 *
291 * Returned value must be freed with ecma_free_value.
292 */
293 static ecma_value_t
ecma_builtin_regexp_prototype_get_multiline(ecma_value_t this_arg)294 ecma_builtin_regexp_prototype_get_multiline (ecma_value_t this_arg) /**< this argument */
295 {
296 uint16_t flags = RE_FLAG_EMPTY;
297 ecma_value_t ret_value = ecma_builtin_regexp_prototype_flags_helper (this_arg, &flags);
298 if (ECMA_IS_VALUE_ERROR (ret_value))
299 {
300 return ret_value;
301 }
302
303 return ecma_make_boolean_value (flags & RE_FLAG_MULTILINE);
304 } /* ecma_builtin_regexp_prototype_get_multiline */
305
306 /**
307 * The RegExp.prototype object's 'sticky' accessor property
308 *
309 * See also:
310 * ECMA-262 v6, 21.2.5.12
311 *
312 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
313 * ECMA_VALUE_TRUE - if 'sticky' flag is set
314 * ECMA_VALUE_FALSE - otherwise
315 *
316 * Returned value must be freed with ecma_free_value.
317 */
318 static ecma_value_t
ecma_builtin_regexp_prototype_get_sticky(ecma_value_t this_arg)319 ecma_builtin_regexp_prototype_get_sticky (ecma_value_t this_arg) /**< this argument */
320 {
321 uint16_t flags = RE_FLAG_EMPTY;
322 ecma_value_t ret_value = ecma_builtin_regexp_prototype_flags_helper (this_arg, &flags);
323 if (ECMA_IS_VALUE_ERROR (ret_value))
324 {
325 return ret_value;
326 }
327
328 return ecma_make_boolean_value (flags & RE_FLAG_STICKY);
329 } /* ecma_builtin_regexp_prototype_get_sticky */
330
331 /**
332 * The RegExp.prototype object's 'unicode' accessor property
333 *
334 * See also:
335 * ECMA-262 v6, 21.2.5.15
336 *
337 * @return ECMA_VALUE_ERROR - if 'this' is not a RegExp object
338 * ECMA_VALUE_TRUE - if 'unicode' flag is set
339 * ECMA_VALUE_FALSE - otherwise
340 *
341 * Returned value must be freed with ecma_free_value.
342 */
343 static ecma_value_t
ecma_builtin_regexp_prototype_get_unicode(ecma_value_t this_arg)344 ecma_builtin_regexp_prototype_get_unicode (ecma_value_t this_arg) /**< this argument */
345 {
346 uint16_t flags = RE_FLAG_EMPTY;
347 ecma_value_t ret_value = ecma_builtin_regexp_prototype_flags_helper (this_arg, &flags);
348 if (ECMA_IS_VALUE_ERROR (ret_value))
349 {
350 return ret_value;
351 }
352
353 return ecma_make_boolean_value (flags & RE_FLAG_UNICODE);
354 } /* ecma_builtin_regexp_prototype_get_unicode */
355 #endif /* ENABLED (JERRY_ES2015) */
356
357 #if ENABLED (JERRY_BUILTIN_ANNEXB)
358
359 /**
360 * The RegExp.prototype object's 'compile' routine
361 *
362 * See also:
363 * ECMA-262 v5, B.2.5.1
364 *
365 * @return undefined - if compiled successfully
366 * error ecma value - otherwise
367 *
368 * Returned value must be freed with ecma_free_value.
369 */
370 static ecma_value_t
ecma_builtin_regexp_prototype_compile(ecma_value_t this_arg,ecma_value_t pattern_arg,ecma_value_t flags_arg)371 ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument */
372 ecma_value_t pattern_arg, /**< pattern or RegExp object */
373 ecma_value_t flags_arg) /**< flags */
374 {
375 if (!ecma_object_is_regexp_object (this_arg)
376 #if !ENABLED (JERRY_ES2015)
377 || ecma_get_object_from_value (this_arg) == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)
378 #endif /* !ENABLED (JERRY_ES2015) */
379 )
380 {
381 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a RegExp object"));
382 }
383
384 ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg);
385 ecma_extended_object_t *regexp_obj_p = (ecma_extended_object_t *) this_obj_p;
386 re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
387 regexp_obj_p->u.class_prop.u.value);
388
389 ecma_value_t status = ecma_builtin_helper_def_prop (this_obj_p,
390 ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
391 ecma_make_uint32_value (0),
392 ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROP_IS_THROW);
393
394 JERRY_ASSERT (ecma_is_value_true (status));
395
396 if (ecma_object_is_regexp_object (pattern_arg))
397 {
398 if (!ecma_is_value_undefined (flags_arg))
399 {
400 return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument"));
401 }
402
403 ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_arg);
404 re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
405 pattern_obj_p->u.class_prop.u.value);
406
407 ecma_ref_object (this_obj_p);
408 /* ecma_op_create_regexp_from_bytecode will never throw an error while re-initalizing the regexp object, so we
409 * can deref the old bytecode without leaving a dangling pointer. */
410 ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p);
411 return ecma_op_create_regexp_from_bytecode (this_obj_p, bc_p);
412 }
413
414 ecma_value_t ret_value = ecma_op_create_regexp_from_pattern (this_obj_p, pattern_arg, flags_arg);
415
416 if (!ECMA_IS_VALUE_ERROR (ret_value))
417 {
418 ecma_ref_object (this_obj_p);
419 ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p);
420 }
421
422 return ret_value;
423 } /* ecma_builtin_regexp_prototype_compile */
424
425 #endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */
426
427 /**
428 * The RegExp.prototype object's 'exec' routine
429 *
430 * See also:
431 * ECMA-262 v5, 15.10.6.2
432 *
433 * @return array object containing the results - if the matched
434 * null - otherwise
435 *
436 * May raise error, so returned value must be freed with ecma_free_value.
437 */
438 static ecma_value_t
ecma_builtin_regexp_prototype_exec(ecma_value_t this_arg,ecma_value_t arg)439 ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */
440 ecma_value_t arg) /**< routine's argument */
441 {
442 if (!ecma_object_is_regexp_object (this_arg))
443 {
444 return ecma_raise_type_error (ECMA_ERR_MSG ("Incomplete RegExp type"));
445 }
446
447 ecma_value_t obj_this = ecma_op_to_object (this_arg);
448 if (ECMA_IS_VALUE_ERROR (obj_this))
449 {
450 return obj_this;
451 }
452
453 ecma_string_t *input_str_p = ecma_op_to_string (arg);
454 if (JERRY_UNLIKELY (input_str_p == NULL))
455 {
456 ecma_free_value (obj_this);
457 return ECMA_VALUE_ERROR;
458 }
459
460 ecma_value_t ret_value = ecma_regexp_exec_helper (ecma_get_object_from_value (obj_this), input_str_p);
461
462 ecma_free_value (obj_this);
463 ecma_deref_ecma_string (input_str_p);
464
465 return ret_value;
466 } /* ecma_builtin_regexp_prototype_exec */
467
468 /**
469 * The RegExp.prototype object's 'test' routine
470 *
471 * See also:
472 * ECMA-262 v5, 15.10.6.3
473 * ECMA-262 v6, 21.2.5.13
474 *
475 * @return true - if match is not null
476 * false - otherwise
477 *
478 * May raise error, so returned value must be freed with ecma_free_value.
479 */
480 static ecma_value_t
ecma_builtin_regexp_prototype_test(ecma_value_t this_arg,ecma_value_t arg)481 ecma_builtin_regexp_prototype_test (ecma_value_t this_arg, /**< this argument */
482 ecma_value_t arg) /**< routine's argument */
483 {
484 #if ENABLED (JERRY_ES2015)
485 if (!ecma_is_value_object (this_arg))
486 {
487 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' value is not an object"));
488 }
489
490 ecma_string_t *arg_str_p = ecma_op_to_string (arg);
491
492 if (JERRY_UNLIKELY (arg_str_p == NULL))
493 {
494 return ECMA_VALUE_ERROR;
495 }
496
497 ecma_value_t result = ecma_op_regexp_exec (this_arg, arg_str_p);
498
499 ecma_deref_ecma_string (arg_str_p);
500
501 if (ECMA_IS_VALUE_ERROR (result))
502 {
503 return result;
504 }
505 #else /* !ENABLED (JERRY_ES2015) */
506 ecma_value_t result = ecma_builtin_regexp_prototype_exec (this_arg, arg);
507
508 if (ECMA_IS_VALUE_ERROR (result))
509 {
510 return result;
511 }
512 #endif /* ENABLED (JERRY_ES2015) */
513
514 ecma_value_t ret_value = ecma_make_boolean_value (!ecma_is_value_null (result));
515 ecma_free_value (result);
516
517 return ret_value;
518 } /* ecma_builtin_regexp_prototype_test */
519
520 /**
521 * The RegExp.prototype object's 'toString' routine
522 *
523 * See also:
524 * ECMA-262 v5, 15.10.6.4
525 *
526 * @return ecma value
527 * Returned value must be freed with ecma_free_value.
528 */
529 static ecma_value_t
ecma_builtin_regexp_prototype_to_string(ecma_value_t this_arg)530 ecma_builtin_regexp_prototype_to_string (ecma_value_t this_arg) /**< this argument */
531 {
532 #if ENABLED (JERRY_ES2015)
533 if (!ecma_is_value_object (this_arg))
534 {
535 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' value is not an object."));
536 }
537
538 ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
539
540 ecma_value_t result = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_SOURCE);
541 if (ECMA_IS_VALUE_ERROR (result))
542 {
543 return result;
544 }
545
546 ecma_string_t *source_p = ecma_op_to_string (result);
547 ecma_free_value (result);
548
549 if (source_p == NULL)
550 {
551 return ECMA_VALUE_ERROR;
552 }
553
554 result = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_FLAGS);
555 if (ECMA_IS_VALUE_ERROR (result))
556 {
557 ecma_deref_ecma_string (source_p);
558 return result;
559 }
560
561 ecma_string_t *flags_p = ecma_op_to_string (result);
562 ecma_free_value (result);
563
564 if (flags_p == NULL)
565 {
566 ecma_deref_ecma_string (source_p);
567 return ECMA_VALUE_ERROR;
568 }
569
570 ecma_stringbuilder_t builder = ecma_stringbuilder_create ();
571 ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SLASH);
572 ecma_stringbuilder_append (&builder, source_p);
573 ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SLASH);
574 ecma_stringbuilder_append (&builder, flags_p);
575
576 ecma_deref_ecma_string (source_p);
577 ecma_deref_ecma_string (flags_p);
578
579 return ecma_make_string_value (ecma_stringbuilder_finalize (&builder));
580 #else /* !ENABLED (JERRY_ES2015) */
581 if (!ecma_object_is_regexp_object (this_arg))
582 {
583 return ecma_raise_type_error (ECMA_ERR_MSG ("'this' value is not a RegExp object."));
584 }
585
586 ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
587 ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) obj_p;
588
589 re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
590 re_obj_p->u.class_prop.u.value);
591
592 ecma_string_t *source_p = ecma_get_string_from_value (bc_p->source);
593 uint16_t flags = bc_p->header.status_flags;
594
595 ecma_stringbuilder_t result = ecma_stringbuilder_create ();
596 ecma_stringbuilder_append_byte (&result, LIT_CHAR_SLASH);
597 ecma_stringbuilder_append (&result, source_p);
598 ecma_stringbuilder_append_byte (&result, LIT_CHAR_SLASH);
599
600 if (flags & RE_FLAG_GLOBAL)
601 {
602 ecma_stringbuilder_append_byte (&result, LIT_CHAR_LOWERCASE_G);
603 }
604
605 if (flags & RE_FLAG_IGNORE_CASE)
606 {
607 ecma_stringbuilder_append_byte (&result, LIT_CHAR_LOWERCASE_I);
608 }
609
610 if (flags & RE_FLAG_MULTILINE)
611 {
612 ecma_stringbuilder_append_byte (&result, LIT_CHAR_LOWERCASE_M);
613 }
614
615 return ecma_make_string_value (ecma_stringbuilder_finalize (&result));
616 #endif /* ENABLED (JERRY_ES2015) */
617 } /* ecma_builtin_regexp_prototype_to_string */
618
619 #if ENABLED (JERRY_ES2015)
620 /**
621 * Helper function to determine if method is the builtin exec method
622 *
623 * @return true, if function is the builtin exec method
624 * false, otherwise
625 */
626 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_builtin_is_regexp_exec(ecma_extended_object_t * obj_p)627 ecma_builtin_is_regexp_exec (ecma_extended_object_t *obj_p)
628 {
629 return (ecma_get_object_is_builtin ((ecma_object_t *) obj_p)
630 && obj_p->u.built_in.routine_id == ECMA_ROUTINE_LIT_MAGIC_STRING_EXECecma_builtin_regexp_prototype_exec);
631 } /* ecma_builtin_is_regexp_exec */
632
633 /**
634 * The RegExp.prototype object's '@@replace' routine
635 *
636 * See also:
637 * ECMA-262 v6.0, 21.2.5.8
638 *
639 * @return ecma value
640 * Returned value must be freed with ecma_free_value.
641 */
642 static ecma_value_t
ecma_builtin_regexp_prototype_symbol_replace(ecma_value_t this_arg,ecma_value_t string_arg,ecma_value_t replace_arg)643 ecma_builtin_regexp_prototype_symbol_replace (ecma_value_t this_arg, /**< this argument */
644 ecma_value_t string_arg, /**< source string */
645 ecma_value_t replace_arg) /**< replace string */
646 {
647 return ecma_regexp_replace_helper (this_arg, string_arg, replace_arg);
648 } /* ecma_builtin_regexp_prototype_symbol_replace */
649
650 /**
651 * The RegExp.prototype object's '@@search' routine
652 *
653 * See also:
654 * ECMA-262 v6.0, 21.2.5.9
655 *
656 * @return ecma value
657 * Returned value must be freed with ecma_free_value.
658 */
659 static ecma_value_t
ecma_builtin_regexp_prototype_symbol_search(ecma_value_t this_arg,ecma_value_t string_arg)660 ecma_builtin_regexp_prototype_symbol_search (ecma_value_t this_arg, /**< this argument */
661 ecma_value_t string_arg) /**< string argument */
662 {
663 return ecma_regexp_search_helper (this_arg, string_arg);
664 } /* ecma_builtin_regexp_prototype_symbol_search */
665
666 /**
667 * The RegExp.prototype object's '@@split' routine
668 *
669 * See also:
670 * ECMA-262 v6.0, 21.2.5.11
671 *
672 * @return ecma value
673 * Returned value must be freed with ecma_free_value.
674 */
675 static ecma_value_t
ecma_builtin_regexp_prototype_symbol_split(ecma_value_t this_arg,ecma_value_t string_arg,ecma_value_t limit_arg)676 ecma_builtin_regexp_prototype_symbol_split (ecma_value_t this_arg, /**< this argument */
677 ecma_value_t string_arg, /**< source string */
678 ecma_value_t limit_arg) /**< limit */
679 {
680 return ecma_regexp_split_helper (this_arg, string_arg, limit_arg);
681 } /* ecma_builtin_regexp_prototype_symbol_split */
682
683 /**
684 * The RegExp.prototype object's '@@match' routine
685 *
686 * See also:
687 * ECMA-262 v6.0, 21.2.5.6
688 *
689 * @return ecma value
690 * Returned value must be freed with ecma_free_value.
691 */
692 static ecma_value_t
ecma_builtin_regexp_prototype_symbol_match(ecma_value_t this_arg,ecma_value_t string_arg)693 ecma_builtin_regexp_prototype_symbol_match (ecma_value_t this_arg, /**< this argument */
694 ecma_value_t string_arg) /**< source string */
695 {
696 return ecma_regexp_match_helper (this_arg, string_arg);
697 } /* ecma_builtin_regexp_prototype_symbol_match */
698 #endif /* ENABLED (JERRY_ES2015) */
699
700 /**
701 * @}
702 * @}
703 * @}
704 */
705
706 #endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
707