• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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