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 46static ecma_value_t 47ecma_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 */ 200ecma_value_t 201ecma_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 */ 214ecma_value_t 215ecma_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 */ 229ecma_value_t 230ecma_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