• 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-builtins.h"
18 #include "ecma-conversion.h"
19 #include "ecma-exceptions.h"
20 #include "ecma-gc.h"
21 #include "ecma-helpers.h"
22 #include "jcontext.h"
23 #include "ecma-objects.h"
24 #include "ecma-regexp-object.h"
25 #include "ecma-try-catch-macro.h"
26 
27 #if ENABLED (JERRY_BUILTIN_REGEXP)
28 
29 #define ECMA_BUILTINS_INTERNAL
30 #include "ecma-builtins-internal.h"
31 
32 #define BUILTIN_INC_HEADER_NAME "ecma-builtin-regexp.inc.h"
33 #define BUILTIN_UNDERSCORED_ID regexp
34 #include "ecma-builtin-internal-routines-template.inc.h"
35 
36 /** \addtogroup ecma ECMA
37  * @{
38  *
39  * \addtogroup ecmabuiltins
40  * @{
41  *
42  * \addtogroup regexp ECMA RegExp object built-in
43  * @{
44  */
45 
46 static ecma_value_t
ecma_builtin_regexp_dispatch_helper(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)47 ecma_builtin_regexp_dispatch_helper (const ecma_value_t *arguments_list_p, /**< arguments list */
48                                      ecma_length_t arguments_list_len) /**< number of arguments */
49 {
50   ecma_value_t pattern_value = ECMA_VALUE_UNDEFINED;
51   ecma_value_t flags_value = ECMA_VALUE_UNDEFINED;
52 #if ENABLED (JERRY_ES2015)
53   bool create_regexp_from_bc = false;
54   bool free_arguments = false;
55   ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target);
56 #else /* !ENABLED (JERRY_ES2015) */
57   ecma_object_t *new_target_p = NULL;
58 #endif /* ENABLED (JERRY_ES2015) */
59 
60   if (arguments_list_len > 0)
61   {
62     /* pattern string or RegExp object */
63     pattern_value = arguments_list_p[0];
64 
65     if (arguments_list_len > 1)
66     {
67       flags_value = arguments_list_p[1];
68     }
69   }
70 
71 #if ENABLED (JERRY_ES2015)
72   ecma_value_t regexp_value = ecma_op_is_regexp (pattern_value);
73 
74   if (ECMA_IS_VALUE_ERROR (regexp_value))
75   {
76     return regexp_value;
77   }
78 
79   bool pattern_is_regexp = regexp_value == ECMA_VALUE_TRUE;
80   re_compiled_code_t *bc_p = NULL;
81 
82   if (new_target_p == NULL)
83   {
84     new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP);
85 
86     if (pattern_is_regexp && ecma_is_value_undefined (flags_value))
87     {
88       ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value);
89 
90       ecma_value_t pattern_constructor = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_CONSTRUCTOR);
91 
92       if (ECMA_IS_VALUE_ERROR (pattern_constructor))
93       {
94         return pattern_constructor;
95       }
96 
97       bool is_same = ecma_op_same_value (ecma_make_object_value (new_target_p), pattern_constructor);
98       ecma_free_value (pattern_constructor);
99 
100       if (is_same)
101       {
102         return ecma_copy_value (pattern_value);
103       }
104     }
105   }
106 
107   if (ecma_object_is_regexp_object (pattern_value))
108   {
109     ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_value);
110     bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
111                                             pattern_obj_p->u.class_prop.u.value);
112 
113     create_regexp_from_bc = ecma_is_value_undefined (flags_value);
114 
115     if (!create_regexp_from_bc)
116     {
117       pattern_value = bc_p->source;
118     }
119   }
120   else if (pattern_is_regexp)
121   {
122     ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value);
123 
124     pattern_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_SOURCE);
125 
126     if (ECMA_IS_VALUE_ERROR (pattern_value))
127     {
128       return pattern_value;
129     }
130 
131     if (ecma_is_value_undefined (flags_value))
132     {
133       flags_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_FLAGS);
134 
135       if (ECMA_IS_VALUE_ERROR (flags_value))
136       {
137         ecma_free_value (pattern_value);
138         return flags_value;
139       }
140     }
141     else
142     {
143       flags_value = ecma_copy_value (flags_value);
144     }
145 
146     free_arguments = true;
147   }
148 #else /* !ENABLED (JERRY_ES2015) */
149   if (ecma_object_is_regexp_object (pattern_value))
150   {
151     if (ecma_is_value_undefined (flags_value))
152     {
153       return ecma_copy_value (pattern_value);
154     }
155 
156     return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp call."));
157   }
158 #endif /* ENABLED (JERRY_ES2015) */
159 
160   ecma_value_t ret_value = ECMA_VALUE_ERROR;
161   ecma_object_t *new_target_obj_p = ecma_op_regexp_alloc (new_target_p);
162 
163   if (JERRY_LIKELY (new_target_obj_p != NULL))
164   {
165 #if ENABLED (JERRY_ES2015)
166     if (create_regexp_from_bc)
167     {
168       ret_value = ecma_op_create_regexp_from_bytecode (new_target_obj_p, bc_p);
169       JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (ret_value));
170     }
171     else
172 #endif /* ENABLED (JERRY_ES2015) */
173     {
174       ret_value = ecma_op_create_regexp_from_pattern (new_target_obj_p, pattern_value, flags_value);
175 
176       if (ECMA_IS_VALUE_ERROR (ret_value))
177       {
178         ecma_deref_object (new_target_obj_p);
179       }
180     }
181   }
182 
183 #if ENABLED (JERRY_ES2015)
184   if (free_arguments)
185   {
186     ecma_free_value (pattern_value);
187     ecma_free_value (flags_value);
188   }
189 #endif /* ENABLED (JERRY_ES2015) */
190 
191   return ret_value;
192 } /* ecma_builtin_regexp_dispatch_helper */
193 
194 /**
195  * Handle calling [[Call]] of built-in RegExp object
196  *
197  * @return ecma value
198  *         Returned value must be freed with ecma_free_value.
199  */
200 ecma_value_t
ecma_builtin_regexp_dispatch_call(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)201 ecma_builtin_regexp_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
202                                    ecma_length_t arguments_list_len) /**< number of arguments */
203 {
204   return ecma_builtin_regexp_dispatch_helper (arguments_list_p,
205                                               arguments_list_len);
206 } /* ecma_builtin_regexp_dispatch_call */
207 
208 /**
209  * Handle calling [[Construct]] of built-in RegExp object
210  *
211  * @return ecma value
212  *         Returned value must be freed with ecma_free_value.
213  */
214 ecma_value_t
ecma_builtin_regexp_dispatch_construct(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)215 ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
216                                         ecma_length_t arguments_list_len) /**< number of arguments */
217 {
218   return ecma_builtin_regexp_dispatch_helper (arguments_list_p,
219                                               arguments_list_len);
220 } /* ecma_builtin_regexp_dispatch_construct */
221 
222 #if ENABLED (JERRY_ES2015)
223 /**
224  * 21.2.4.2 get RegExp [ @@species ] accessor
225  *
226  * @return ecma_value
227  *         returned value must be freed with ecma_free_value
228  */
229 ecma_value_t
ecma_builtin_regexp_species_get(ecma_value_t this_value)230 ecma_builtin_regexp_species_get (ecma_value_t this_value) /**< This Value */
231 {
232   return ecma_copy_value (this_value);
233 } /* ecma_builtin_regexp_species_get */
234 #endif /* ENABLED (JERRY_ES2015) */
235 
236 /**
237  * @}
238  * @}
239  * @}
240  */
241 
242 #endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
243