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