1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h" 17425bb815Sopenharmony_ci 18425bb815Sopenharmony_ci#include "ecma-alloc.h" 19425bb815Sopenharmony_ci#include "ecma-array-object.h" 20425bb815Sopenharmony_ci#include "ecma-builtins.h" 21425bb815Sopenharmony_ci#include "ecma-builtin-object.h" 22425bb815Sopenharmony_ci#include "ecma-conversion.h" 23425bb815Sopenharmony_ci#include "ecma-function-object.h" 24425bb815Sopenharmony_ci#include "ecma-exceptions.h" 25425bb815Sopenharmony_ci#include "ecma-gc.h" 26425bb815Sopenharmony_ci#include "ecma-helpers.h" 27425bb815Sopenharmony_ci#include "jmem.h" 28425bb815Sopenharmony_ci#include "ecma-objects.h" 29425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h" 30425bb815Sopenharmony_ci#include "lit-magic-strings.h" 31425bb815Sopenharmony_ci#include "lit-char-helpers.h" 32425bb815Sopenharmony_ci 33425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 34425bb815Sopenharmony_ci * @{ 35425bb815Sopenharmony_ci * 36425bb815Sopenharmony_ci * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations 37425bb815Sopenharmony_ci * @{ 38425bb815Sopenharmony_ci */ 39425bb815Sopenharmony_ci 40425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 41425bb815Sopenharmony_ci/** 42425bb815Sopenharmony_ci * Helper function for Object.prototype.toString routine when 43425bb815Sopenharmony_ci * the @@toStringTag property is present 44425bb815Sopenharmony_ci * 45425bb815Sopenharmony_ci * See also: 46425bb815Sopenharmony_ci * ECMA-262 v6, 19.1.3.6 47425bb815Sopenharmony_ci * 48425bb815Sopenharmony_ci * @return ecma value 49425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 50425bb815Sopenharmony_ci */ 51425bb815Sopenharmony_cistatic ecma_value_t 52425bb815Sopenharmony_ciecma_builtin_helper_object_to_string_tag_helper (ecma_value_t tag_value) /**< string tag */ 53425bb815Sopenharmony_ci{ 54425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_string (tag_value)); 55425bb815Sopenharmony_ci 56425bb815Sopenharmony_ci ecma_string_t *tag_str_p = ecma_get_string_from_value (tag_value); 57425bb815Sopenharmony_ci ecma_string_t *ret_string_p; 58425bb815Sopenharmony_ci 59425bb815Sopenharmony_ci /* Building string "[object #@@toStringTag#]" 60425bb815Sopenharmony_ci The string size will be size("[object ") + size(#@@toStringTag#) + size ("]"). */ 61425bb815Sopenharmony_ci const lit_utf8_size_t buffer_size = 9 + ecma_string_get_size (tag_str_p); 62425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); 63425bb815Sopenharmony_ci 64425bb815Sopenharmony_ci lit_utf8_byte_t *buffer_ptr = str_buffer; 65425bb815Sopenharmony_ci 66425bb815Sopenharmony_ci const lit_magic_string_id_t magic_string_ids[] = 67425bb815Sopenharmony_ci { 68425bb815Sopenharmony_ci LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, 69425bb815Sopenharmony_ci LIT_MAGIC_STRING_OBJECT, 70425bb815Sopenharmony_ci LIT_MAGIC_STRING_SPACE_CHAR, 71425bb815Sopenharmony_ci }; 72425bb815Sopenharmony_ci 73425bb815Sopenharmony_ci /* Copy to buffer the "[object " string */ 74425bb815Sopenharmony_ci for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) 75425bb815Sopenharmony_ci { 76425bb815Sopenharmony_ci buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, 77425bb815Sopenharmony_ci (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); 78425bb815Sopenharmony_ci 79425bb815Sopenharmony_ci JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); 80425bb815Sopenharmony_ci } 81425bb815Sopenharmony_ci 82425bb815Sopenharmony_ci /* Copy to buffer the #@@toStringTag# string */ 83425bb815Sopenharmony_ci buffer_ptr += ecma_string_copy_to_cesu8_buffer (tag_str_p, buffer_ptr, 84425bb815Sopenharmony_ci (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); 85425bb815Sopenharmony_ci 86425bb815Sopenharmony_ci JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); 87425bb815Sopenharmony_ci 88425bb815Sopenharmony_ci /* Copy to buffer the "]" string */ 89425bb815Sopenharmony_ci buffer_ptr = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR, buffer_ptr, 90425bb815Sopenharmony_ci (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); 91425bb815Sopenharmony_ci 92425bb815Sopenharmony_ci JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); 93425bb815Sopenharmony_ci 94425bb815Sopenharmony_ci ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); 95425bb815Sopenharmony_ci 96425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (str_buffer); 97425bb815Sopenharmony_ci ecma_deref_ecma_string (tag_str_p); 98425bb815Sopenharmony_ci 99425bb815Sopenharmony_ci return ecma_make_string_value (ret_string_p); 100425bb815Sopenharmony_ci} /* ecma_builtin_helper_object_to_string_tag_helper */ 101425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 102425bb815Sopenharmony_ci 103425bb815Sopenharmony_ci/** 104425bb815Sopenharmony_ci * Common implementation of the Object.prototype.toString routine 105425bb815Sopenharmony_ci * 106425bb815Sopenharmony_ci * See also: 107425bb815Sopenharmony_ci * ECMA-262 v5, 15.2.4.2 108425bb815Sopenharmony_ci * 109425bb815Sopenharmony_ci * Used by: 110425bb815Sopenharmony_ci * - The Object.prototype.toString routine. 111425bb815Sopenharmony_ci * - The Array.prototype.toString routine as fallback. 112425bb815Sopenharmony_ci * 113425bb815Sopenharmony_ci * @return ecma value 114425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 115425bb815Sopenharmony_ci */ 116425bb815Sopenharmony_ci 117425bb815Sopenharmony_ciecma_value_t 118425bb815Sopenharmony_ciecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ 119425bb815Sopenharmony_ci{ 120425bb815Sopenharmony_ci lit_magic_string_id_t type_string; 121425bb815Sopenharmony_ci 122425bb815Sopenharmony_ci if (ecma_is_value_undefined (this_arg)) 123425bb815Sopenharmony_ci { 124425bb815Sopenharmony_ci type_string = LIT_MAGIC_STRING_UNDEFINED_UL; 125425bb815Sopenharmony_ci } 126425bb815Sopenharmony_ci else if (ecma_is_value_null (this_arg)) 127425bb815Sopenharmony_ci { 128425bb815Sopenharmony_ci type_string = LIT_MAGIC_STRING_NULL_UL; 129425bb815Sopenharmony_ci } 130425bb815Sopenharmony_ci else 131425bb815Sopenharmony_ci { 132425bb815Sopenharmony_ci ecma_value_t obj_this = ecma_op_to_object (this_arg); 133425bb815Sopenharmony_ci 134425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (obj_this)) 135425bb815Sopenharmony_ci { 136425bb815Sopenharmony_ci return obj_this; 137425bb815Sopenharmony_ci } 138425bb815Sopenharmony_ci 139425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_object (obj_this)); 140425bb815Sopenharmony_ci 141425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); 142425bb815Sopenharmony_ci 143425bb815Sopenharmony_ci type_string = ecma_object_get_class_name (obj_p); 144425bb815Sopenharmony_ci 145425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 146425bb815Sopenharmony_ci ecma_value_t tag_value = ecma_op_object_get_by_symbol_id (obj_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG); 147425bb815Sopenharmony_ci 148425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (tag_value)) 149425bb815Sopenharmony_ci { 150425bb815Sopenharmony_ci ecma_deref_object (obj_p); 151425bb815Sopenharmony_ci return tag_value; 152425bb815Sopenharmony_ci } 153425bb815Sopenharmony_ci 154425bb815Sopenharmony_ci if (ecma_is_value_string (tag_value)) 155425bb815Sopenharmony_ci { 156425bb815Sopenharmony_ci ecma_deref_object (obj_p); 157425bb815Sopenharmony_ci return ecma_builtin_helper_object_to_string_tag_helper (tag_value); 158425bb815Sopenharmony_ci } 159425bb815Sopenharmony_ci 160425bb815Sopenharmony_ci ecma_free_value (tag_value); 161425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_ci ecma_deref_object (obj_p); 164425bb815Sopenharmony_ci } 165425bb815Sopenharmony_ci 166425bb815Sopenharmony_ci ecma_string_t *ret_string_p; 167425bb815Sopenharmony_ci 168425bb815Sopenharmony_ci /* Building string "[object #type#]" where type is 'Undefined', 169425bb815Sopenharmony_ci 'Null' or one of possible object's classes. 170425bb815Sopenharmony_ci The string with null character is maximum 27 characters long. */ 171425bb815Sopenharmony_ci const lit_utf8_size_t buffer_size = 27; 172425bb815Sopenharmony_ci JERRY_VLA (lit_utf8_byte_t, str_buffer, buffer_size); 173425bb815Sopenharmony_ci 174425bb815Sopenharmony_ci lit_utf8_byte_t *buffer_ptr = str_buffer; 175425bb815Sopenharmony_ci 176425bb815Sopenharmony_ci const lit_magic_string_id_t magic_string_ids[] = 177425bb815Sopenharmony_ci { 178425bb815Sopenharmony_ci LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, 179425bb815Sopenharmony_ci LIT_MAGIC_STRING_OBJECT, 180425bb815Sopenharmony_ci LIT_MAGIC_STRING_SPACE_CHAR, 181425bb815Sopenharmony_ci type_string, 182425bb815Sopenharmony_ci LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR 183425bb815Sopenharmony_ci }; 184425bb815Sopenharmony_ci 185425bb815Sopenharmony_ci for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) 186425bb815Sopenharmony_ci { 187425bb815Sopenharmony_ci buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, 188425bb815Sopenharmony_ci (lit_utf8_size_t) ((str_buffer + buffer_size) - buffer_ptr)); 189425bb815Sopenharmony_ci JERRY_ASSERT (buffer_ptr <= str_buffer + buffer_size); 190425bb815Sopenharmony_ci } 191425bb815Sopenharmony_ci 192425bb815Sopenharmony_ci ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_ptr - str_buffer)); 193425bb815Sopenharmony_ci 194425bb815Sopenharmony_ci return ecma_make_string_value (ret_string_p); 195425bb815Sopenharmony_ci} /* ecma_builtin_helper_object_to_string */ 196425bb815Sopenharmony_ci 197425bb815Sopenharmony_ci/** 198425bb815Sopenharmony_ci * The Array.prototype's 'toLocaleString' single element operation routine 199425bb815Sopenharmony_ci * 200425bb815Sopenharmony_ci * See also: 201425bb815Sopenharmony_ci * ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d 202425bb815Sopenharmony_ci * 203425bb815Sopenharmony_ci * @return ecma value 204425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 205425bb815Sopenharmony_ci */ 206425bb815Sopenharmony_ciecma_string_t * 207425bb815Sopenharmony_ciecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ 208425bb815Sopenharmony_ci uint32_t index) /**< array index */ 209425bb815Sopenharmony_ci{ 210425bb815Sopenharmony_ci ecma_value_t index_value = ecma_op_object_get_by_uint32_index (obj_p, index); 211425bb815Sopenharmony_ci 212425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (index_value)) 213425bb815Sopenharmony_ci { 214425bb815Sopenharmony_ci return NULL; 215425bb815Sopenharmony_ci } 216425bb815Sopenharmony_ci 217425bb815Sopenharmony_ci if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) 218425bb815Sopenharmony_ci { 219425bb815Sopenharmony_ci return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); 220425bb815Sopenharmony_ci } 221425bb815Sopenharmony_ci 222425bb815Sopenharmony_ci ecma_value_t index_obj_value = ecma_op_to_object (index_value); 223425bb815Sopenharmony_ci 224425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (index_obj_value)) 225425bb815Sopenharmony_ci { 226425bb815Sopenharmony_ci ecma_free_value (index_value); 227425bb815Sopenharmony_ci return NULL; 228425bb815Sopenharmony_ci } 229425bb815Sopenharmony_ci 230425bb815Sopenharmony_ci ecma_string_t *ret_string_p = NULL; 231425bb815Sopenharmony_ci ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value); 232425bb815Sopenharmony_ci ecma_value_t to_locale_value = ecma_op_object_get_by_magic_id (index_obj_p, LIT_MAGIC_STRING_TO_LOCALE_STRING_UL); 233425bb815Sopenharmony_ci 234425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (to_locale_value)) 235425bb815Sopenharmony_ci { 236425bb815Sopenharmony_ci goto cleanup; 237425bb815Sopenharmony_ci } 238425bb815Sopenharmony_ci 239425bb815Sopenharmony_ci if (!ecma_op_is_callable (to_locale_value)) 240425bb815Sopenharmony_ci { 241425bb815Sopenharmony_ci ecma_free_value (to_locale_value); 242425bb815Sopenharmony_ci ecma_raise_type_error (ECMA_ERR_MSG ("'toLocaleString' is missing or not a function.")); 243425bb815Sopenharmony_ci goto cleanup; 244425bb815Sopenharmony_ci } 245425bb815Sopenharmony_ci 246425bb815Sopenharmony_ci ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value); 247425bb815Sopenharmony_ci ecma_value_t call_value = ecma_op_function_call (locale_func_obj_p, 248425bb815Sopenharmony_ci index_obj_value, 249425bb815Sopenharmony_ci NULL, 250425bb815Sopenharmony_ci 0); 251425bb815Sopenharmony_ci ecma_deref_object (locale_func_obj_p); 252425bb815Sopenharmony_ci 253425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (call_value)) 254425bb815Sopenharmony_ci { 255425bb815Sopenharmony_ci goto cleanup; 256425bb815Sopenharmony_ci } 257425bb815Sopenharmony_ci 258425bb815Sopenharmony_ci ret_string_p = ecma_op_to_string (call_value); 259425bb815Sopenharmony_ci ecma_free_value (call_value); 260425bb815Sopenharmony_ci 261425bb815Sopenharmony_cicleanup: 262425bb815Sopenharmony_ci ecma_deref_object (index_obj_p); 263425bb815Sopenharmony_ci ecma_free_value (index_value); 264425bb815Sopenharmony_ci 265425bb815Sopenharmony_ci return ret_string_p; 266425bb815Sopenharmony_ci} /* ecma_builtin_helper_get_to_locale_string_at_index */ 267425bb815Sopenharmony_ci 268425bb815Sopenharmony_ci/** 269425bb815Sopenharmony_ci * The Object.keys and Object.getOwnPropertyNames routine's common part. 270425bb815Sopenharmony_ci * 271425bb815Sopenharmony_ci * See also: 272425bb815Sopenharmony_ci * ECMA-262 v5, 15.2.3.4 steps 2-5 273425bb815Sopenharmony_ci * ECMA-262 v5, 15.2.3.14 steps 3-6 274425bb815Sopenharmony_ci * 275425bb815Sopenharmony_ci * @return ecma value - Array of property names. 276425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 277425bb815Sopenharmony_ci */ 278425bb815Sopenharmony_ciecma_value_t 279425bb815Sopenharmony_ciecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ 280425bb815Sopenharmony_ci uint32_t opts) /**< any combination of ecma_list_properties_options_t */ 281425bb815Sopenharmony_ci{ 282425bb815Sopenharmony_ci JERRY_ASSERT (obj_p != NULL); 283425bb815Sopenharmony_ci 284425bb815Sopenharmony_ci ecma_collection_t *props_p = ecma_op_object_get_property_names (obj_p, opts); 285425bb815Sopenharmony_ci 286425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY) 287425bb815Sopenharmony_ci if (props_p == NULL) 288425bb815Sopenharmony_ci { 289425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 290425bb815Sopenharmony_ci } 291425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */ 292425bb815Sopenharmony_ci 293425bb815Sopenharmony_ci if (props_p->item_count == 0) 294425bb815Sopenharmony_ci { 295425bb815Sopenharmony_ci ecma_collection_destroy (props_p); 296425bb815Sopenharmony_ci return ecma_op_create_array_object (NULL, 0, false); 297425bb815Sopenharmony_ci } 298425bb815Sopenharmony_ci 299425bb815Sopenharmony_ci ecma_value_t new_array = ecma_op_create_array_object (props_p->buffer_p, props_p->item_count, false); 300425bb815Sopenharmony_ci ecma_collection_free (props_p); 301425bb815Sopenharmony_ci 302425bb815Sopenharmony_ci return new_array; 303425bb815Sopenharmony_ci} /* ecma_builtin_helper_object_get_properties */ 304425bb815Sopenharmony_ci 305425bb815Sopenharmony_ci/** 306425bb815Sopenharmony_ci * Helper function to normalizing an array index 307425bb815Sopenharmony_ci * 308425bb815Sopenharmony_ci * See also: 309425bb815Sopenharmony_ci * ECMA-262 v5, 15.4.4.10 steps 5, 6, 7 part 2, 8 310425bb815Sopenharmony_ci * ECMA-262 v5, 15.4.4.12 steps 5, 6 311425bb815Sopenharmony_ci * ECMA-262 v5, 15.5.4.13 steps 4 - 7 312425bb815Sopenharmony_ci * ECMA-262 v6, 22.1.3.6 steps 5 - 7, 8 part 2, 9, 10 313425bb815Sopenharmony_ci * ECMA-262 v6, 22.1.3.3 steps 5 - 10, 11 part 2, 12, 13 314425bb815Sopenharmony_ci * ECMA-262 v6, 22.2.3.5 steps 5 - 10, 11 part 2, 12, 13 315425bb815Sopenharmony_ci * ECMA-262 v6, 22.2.3.23 steps 5 - 10 316425bb815Sopenharmony_ci * ECMA-262 v6, 24.1.4.3 steps 6 - 8, 9 part 2, 10, 11 317425bb815Sopenharmony_ci * ECMA-262 v6, 22.2.3.26 steps 7 - 9, 10 part 2, 11, 12 318425bb815Sopenharmony_ci * ECMA-262 v6, 22.2.3.8 steps 5 - 7, 8 part 2, 9, 10 319425bb815Sopenharmony_ci * 320425bb815Sopenharmony_ci * Used by: 321425bb815Sopenharmony_ci * - The Array.prototype.slice routine. 322425bb815Sopenharmony_ci * - The Array.prototype.splice routine. 323425bb815Sopenharmony_ci * - The String.prototype.slice routine. 324425bb815Sopenharmony_ci * - The Array.prototype.fill routine. 325425bb815Sopenharmony_ci * - The Array.prototype.copyWithin routine. 326425bb815Sopenharmony_ci * - The TypedArray.prototype.copyWithin routine. 327425bb815Sopenharmony_ci * - The TypedArray.prototype.slice routine. 328425bb815Sopenharmony_ci * - The ArrayBuffer.prototype.slice routine. 329425bb815Sopenharmony_ci * - The TypedArray.prototype.subarray routine. 330425bb815Sopenharmony_ci * - The TypedArray.prototype.fill routine. 331425bb815Sopenharmony_ci * 332425bb815Sopenharmony_ci * @return ECMA_VALUE_EMPTY if successful 333425bb815Sopenharmony_ci * conversion error otherwise 334425bb815Sopenharmony_ci */ 335425bb815Sopenharmony_ciuint32_t 336425bb815Sopenharmony_ciecma_builtin_helper_array_index_normalize (ecma_value_t arg, /**< index */ 337425bb815Sopenharmony_ci uint32_t length, /**< array's length */ 338425bb815Sopenharmony_ci uint32_t *number_p) /**< [out] uint32_t */ 339425bb815Sopenharmony_ci{ 340425bb815Sopenharmony_ci ecma_number_t to_int; 341425bb815Sopenharmony_ci 342425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg, &to_int))) 343425bb815Sopenharmony_ci { 344425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 345425bb815Sopenharmony_ci } 346425bb815Sopenharmony_ci 347425bb815Sopenharmony_ci *number_p = ((to_int < 0) ? (uint32_t) JERRY_MAX ((length + to_int), 0) 348425bb815Sopenharmony_ci : (uint32_t) JERRY_MIN (to_int, length)); 349425bb815Sopenharmony_ci 350425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 351425bb815Sopenharmony_ci} /* ecma_builtin_helper_array_index_normalize */ 352425bb815Sopenharmony_ci 353425bb815Sopenharmony_ci/** 354425bb815Sopenharmony_ci * Helper function for concatenating an ecma_value_t to an Array. 355425bb815Sopenharmony_ci * 356425bb815Sopenharmony_ci * See also: 357425bb815Sopenharmony_ci * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c 358425bb815Sopenharmony_ci * 359425bb815Sopenharmony_ci * Used by: 360425bb815Sopenharmony_ci * - The Array.prototype.concat routine. 361425bb815Sopenharmony_ci * 362425bb815Sopenharmony_ci * @return ecma value 363425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 364425bb815Sopenharmony_ci */ 365425bb815Sopenharmony_ciecma_value_t 366425bb815Sopenharmony_ciecma_builtin_helper_array_concat_value (ecma_object_t *array_obj_p, /**< array */ 367425bb815Sopenharmony_ci uint32_t *length_p, /**< [in,out] array's length */ 368425bb815Sopenharmony_ci ecma_value_t value) /**< value to concat */ 369425bb815Sopenharmony_ci{ 370425bb815Sopenharmony_ci /* 5.b */ 371425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 372425bb815Sopenharmony_ci ecma_value_t is_spreadable = ecma_op_is_concat_spreadable (value); 373425bb815Sopenharmony_ci 374425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (is_spreadable)) 375425bb815Sopenharmony_ci { 376425bb815Sopenharmony_ci return is_spreadable; 377425bb815Sopenharmony_ci } 378425bb815Sopenharmony_ci 379425bb815Sopenharmony_ci bool spread_object = is_spreadable == ECMA_VALUE_TRUE; 380425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */ 381425bb815Sopenharmony_ci bool spread_object = ecma_is_value_true (ecma_is_value_array (value)); 382425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 383425bb815Sopenharmony_ci 384425bb815Sopenharmony_ci if (spread_object) 385425bb815Sopenharmony_ci { 386425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (value); 387425bb815Sopenharmony_ci 388425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 389425bb815Sopenharmony_ci uint32_t arg_len; 390425bb815Sopenharmony_ci ecma_value_t error = ecma_op_object_get_length (obj_p, &arg_len); 391425bb815Sopenharmony_ci 392425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (error)) 393425bb815Sopenharmony_ci { 394425bb815Sopenharmony_ci return error; 395425bb815Sopenharmony_ci } 396425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */ 397425bb815Sopenharmony_ci /* 5.b.ii */ 398425bb815Sopenharmony_ci uint32_t arg_len = ecma_array_get_length (obj_p); 399425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 400425bb815Sopenharmony_ci /* 5.b.iii */ 401425bb815Sopenharmony_ci for (uint32_t array_index = 0; array_index < arg_len; array_index++) 402425bb815Sopenharmony_ci { 403425bb815Sopenharmony_ci /* 5.b.iii.2 */ 404425bb815Sopenharmony_ci ecma_value_t get_value = ecma_op_object_find_by_uint32_index (obj_p, array_index); 405425bb815Sopenharmony_ci 406425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (get_value)) 407425bb815Sopenharmony_ci { 408425bb815Sopenharmony_ci return get_value; 409425bb815Sopenharmony_ci } 410425bb815Sopenharmony_ci 411425bb815Sopenharmony_ci if (!ecma_is_value_found (get_value)) 412425bb815Sopenharmony_ci { 413425bb815Sopenharmony_ci continue; 414425bb815Sopenharmony_ci } 415425bb815Sopenharmony_ci 416425bb815Sopenharmony_ci /* 5.b.iii.3.b */ 417425bb815Sopenharmony_ci /* This will always be a simple value since 'is_throw' is false, so no need to free. */ 418425bb815Sopenharmony_ci ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, 419425bb815Sopenharmony_ci *length_p + array_index, 420425bb815Sopenharmony_ci get_value, 421425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); 422425bb815Sopenharmony_ci 423425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_true (put_comp)); 424425bb815Sopenharmony_ci ecma_free_value (get_value); 425425bb815Sopenharmony_ci } 426425bb815Sopenharmony_ci 427425bb815Sopenharmony_ci *length_p += arg_len; 428425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 429425bb815Sopenharmony_ci } 430425bb815Sopenharmony_ci 431425bb815Sopenharmony_ci /* 5.c.i */ 432425bb815Sopenharmony_ci /* This will always be a simple value since 'is_throw' is false, so no need to free. */ 433425bb815Sopenharmony_ci ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, 434425bb815Sopenharmony_ci (*length_p)++, 435425bb815Sopenharmony_ci value, 436425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); 437425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_true (put_comp)); 438425bb815Sopenharmony_ci 439425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 440425bb815Sopenharmony_ci} /* ecma_builtin_helper_array_concat_value */ 441425bb815Sopenharmony_ci 442425bb815Sopenharmony_ci/** 443425bb815Sopenharmony_ci * Helper function to normalizing a string index 444425bb815Sopenharmony_ci * 445425bb815Sopenharmony_ci * This function clamps the given index to the [0, length] range. 446425bb815Sopenharmony_ci * If the index is negative, 0 value is used. 447425bb815Sopenharmony_ci * If the index is greater than the length of the string, the normalized index will be the length of the string. 448425bb815Sopenharmony_ci * NaN is mapped to zero or length depending on the nan_to_zero parameter. 449425bb815Sopenharmony_ci * 450425bb815Sopenharmony_ci * See also: 451425bb815Sopenharmony_ci * ECMA-262 v5, 15.5.4.15 452425bb815Sopenharmony_ci * 453425bb815Sopenharmony_ci * Used by: 454425bb815Sopenharmony_ci * - The String.prototype.substring routine. 455425bb815Sopenharmony_ci * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. 456425bb815Sopenharmony_ci * 457425bb815Sopenharmony_ci * @return uint32_t - the normalized value of the index 458425bb815Sopenharmony_ci */ 459425bb815Sopenharmony_ciuint32_t 460425bb815Sopenharmony_ciecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */ 461425bb815Sopenharmony_ci uint32_t length, /**< string's length */ 462425bb815Sopenharmony_ci bool nan_to_zero) /**< whether NaN is mapped to zero (t) or length (f) */ 463425bb815Sopenharmony_ci{ 464425bb815Sopenharmony_ci uint32_t norm_index = 0; 465425bb815Sopenharmony_ci 466425bb815Sopenharmony_ci if (ecma_number_is_nan (index)) 467425bb815Sopenharmony_ci { 468425bb815Sopenharmony_ci if (!nan_to_zero) 469425bb815Sopenharmony_ci { 470425bb815Sopenharmony_ci norm_index = length; 471425bb815Sopenharmony_ci } 472425bb815Sopenharmony_ci } 473425bb815Sopenharmony_ci else if (!ecma_number_is_negative (index)) 474425bb815Sopenharmony_ci { 475425bb815Sopenharmony_ci if (ecma_number_is_infinity (index)) 476425bb815Sopenharmony_ci { 477425bb815Sopenharmony_ci norm_index = length; 478425bb815Sopenharmony_ci } 479425bb815Sopenharmony_ci else 480425bb815Sopenharmony_ci { 481425bb815Sopenharmony_ci norm_index = ecma_number_to_uint32 (index); 482425bb815Sopenharmony_ci 483425bb815Sopenharmony_ci if (norm_index > length) 484425bb815Sopenharmony_ci { 485425bb815Sopenharmony_ci norm_index = length; 486425bb815Sopenharmony_ci } 487425bb815Sopenharmony_ci } 488425bb815Sopenharmony_ci } 489425bb815Sopenharmony_ci 490425bb815Sopenharmony_ci return norm_index; 491425bb815Sopenharmony_ci} /* ecma_builtin_helper_string_index_normalize */ 492425bb815Sopenharmony_ci 493425bb815Sopenharmony_ci/** 494425bb815Sopenharmony_ci * Helper function for string indexOf, lastIndexOf, startsWith, includes, endsWith functions 495425bb815Sopenharmony_ci * 496425bb815Sopenharmony_ci * See also: 497425bb815Sopenharmony_ci * ECMA-262 v5, 15.5.4.7 498425bb815Sopenharmony_ci * ECMA-262 v5, 15.5.4.8 499425bb815Sopenharmony_ci * ECMA-262 v6, 21.1.3.6 500425bb815Sopenharmony_ci * ECMA-262 v6, 21.1.3.7 501425bb815Sopenharmony_ci * ECMA-262 v6, 21.1.3.18 502425bb815Sopenharmony_ci * 503425bb815Sopenharmony_ci * Used by: 504425bb815Sopenharmony_ci * - The String.prototype.indexOf routine. 505425bb815Sopenharmony_ci * - The String.prototype.lastIndexOf routine. 506425bb815Sopenharmony_ci * - The String.prototype.startsWith routine. 507425bb815Sopenharmony_ci * - The String.prototype.includes routine. 508425bb815Sopenharmony_ci * - The String.prototype.endsWith routine. 509425bb815Sopenharmony_ci * 510425bb815Sopenharmony_ci * @return ecma_value_t - Returns index (last index) or a 511425bb815Sopenharmony_ci * boolean value 512425bb815Sopenharmony_ci */ 513425bb815Sopenharmony_ciecma_value_t 514425bb815Sopenharmony_ciecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_str_p, /**< this argument */ 515425bb815Sopenharmony_ci ecma_value_t arg1, /**< routine's first argument */ 516425bb815Sopenharmony_ci ecma_value_t arg2, /**< routine's second argument */ 517425bb815Sopenharmony_ci ecma_string_index_of_mode_t mode) /**< routine's mode */ 518425bb815Sopenharmony_ci{ 519425bb815Sopenharmony_ci /* 5 (indexOf) -- 6 (lastIndexOf) */ 520425bb815Sopenharmony_ci const ecma_length_t original_len = ecma_string_get_length (original_str_p); 521425bb815Sopenharmony_ci 522425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 523425bb815Sopenharmony_ci /* 4, 6 (startsWith, includes, endsWith) */ 524425bb815Sopenharmony_ci if (mode >= ECMA_STRING_STARTS_WITH) 525425bb815Sopenharmony_ci { 526425bb815Sopenharmony_ci ecma_value_t regexp = ecma_op_is_regexp (arg1); 527425bb815Sopenharmony_ci 528425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (regexp)) 529425bb815Sopenharmony_ci { 530425bb815Sopenharmony_ci return regexp; 531425bb815Sopenharmony_ci } 532425bb815Sopenharmony_ci 533425bb815Sopenharmony_ci if (regexp == ECMA_VALUE_TRUE) 534425bb815Sopenharmony_ci { 535425bb815Sopenharmony_ci JERRY_ASSERT (ECMA_STRING_LAST_INDEX_OF < mode && mode <= ECMA_STRING_ENDS_WITH); 536425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("Search string can't be of type: RegExp")); 537425bb815Sopenharmony_ci } 538425bb815Sopenharmony_ci } 539425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 540425bb815Sopenharmony_ci 541425bb815Sopenharmony_ci /* 7, 8 */ 542425bb815Sopenharmony_ci ecma_string_t *search_str_p = ecma_op_to_string (arg1); 543425bb815Sopenharmony_ci 544425bb815Sopenharmony_ci if (JERRY_UNLIKELY (search_str_p == NULL)) 545425bb815Sopenharmony_ci { 546425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 547425bb815Sopenharmony_ci } 548425bb815Sopenharmony_ci 549425bb815Sopenharmony_ci /* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */ 550425bb815Sopenharmony_ci ecma_number_t pos_num; 551425bb815Sopenharmony_ci ecma_value_t ret_value; 552425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 553425bb815Sopenharmony_ci if (mode > ECMA_STRING_LAST_INDEX_OF) 554425bb815Sopenharmony_ci { 555425bb815Sopenharmony_ci ret_value = ecma_op_to_integer (arg2, &pos_num); 556425bb815Sopenharmony_ci } 557425bb815Sopenharmony_ci else 558425bb815Sopenharmony_ci { 559425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 560425bb815Sopenharmony_ci ret_value = ecma_get_number (arg2, &pos_num); 561425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 562425bb815Sopenharmony_ci } 563425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 564425bb815Sopenharmony_ci 565425bb815Sopenharmony_ci /* 10 (startsWith, includes), 11 (endsWith) */ 566425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (ret_value)) 567425bb815Sopenharmony_ci { 568425bb815Sopenharmony_ci ecma_deref_ecma_string (search_str_p); 569425bb815Sopenharmony_ci return ret_value; 570425bb815Sopenharmony_ci } 571425bb815Sopenharmony_ci 572425bb815Sopenharmony_ci bool use_first_index = mode != ECMA_STRING_LAST_INDEX_OF; 573425bb815Sopenharmony_ci 574425bb815Sopenharmony_ci /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */ 575425bb815Sopenharmony_ci ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, use_first_index); 576425bb815Sopenharmony_ci 577425bb815Sopenharmony_ci ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE; 578425bb815Sopenharmony_ci 579425bb815Sopenharmony_ci ecma_length_t index_of = 0; 580425bb815Sopenharmony_ci 581425bb815Sopenharmony_ci ret_value = ECMA_VALUE_FALSE; 582425bb815Sopenharmony_ci 583425bb815Sopenharmony_ci switch (mode) 584425bb815Sopenharmony_ci { 585425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 586425bb815Sopenharmony_ci case ECMA_STRING_STARTS_WITH: 587425bb815Sopenharmony_ci { 588425bb815Sopenharmony_ci const ecma_length_t search_len = ecma_string_get_length (search_str_p); 589425bb815Sopenharmony_ci 590425bb815Sopenharmony_ci if (search_len + start > original_len) 591425bb815Sopenharmony_ci { 592425bb815Sopenharmony_ci break; 593425bb815Sopenharmony_ci } 594425bb815Sopenharmony_ci 595425bb815Sopenharmony_ci if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, true, start, &index_of)) 596425bb815Sopenharmony_ci { 597425bb815Sopenharmony_ci /* 15, 16 (startsWith) */ 598425bb815Sopenharmony_ci ret_value = ecma_make_boolean_value (index_of == start); 599425bb815Sopenharmony_ci } 600425bb815Sopenharmony_ci break; 601425bb815Sopenharmony_ci } 602425bb815Sopenharmony_ci case ECMA_STRING_INCLUDES: 603425bb815Sopenharmony_ci { 604425bb815Sopenharmony_ci if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, true, start, &index_of)) 605425bb815Sopenharmony_ci { 606425bb815Sopenharmony_ci ret_value = ECMA_VALUE_TRUE; 607425bb815Sopenharmony_ci } 608425bb815Sopenharmony_ci break; 609425bb815Sopenharmony_ci } 610425bb815Sopenharmony_ci case ECMA_STRING_ENDS_WITH: 611425bb815Sopenharmony_ci { 612425bb815Sopenharmony_ci if (start == 0) 613425bb815Sopenharmony_ci { 614425bb815Sopenharmony_ci start = original_len; 615425bb815Sopenharmony_ci } 616425bb815Sopenharmony_ci 617425bb815Sopenharmony_ci ecma_length_t search_str_len = ecma_string_get_length (search_str_p); 618425bb815Sopenharmony_ci 619425bb815Sopenharmony_ci if (search_str_len == 0) 620425bb815Sopenharmony_ci { 621425bb815Sopenharmony_ci ret_value = ECMA_VALUE_TRUE; 622425bb815Sopenharmony_ci break; 623425bb815Sopenharmony_ci } 624425bb815Sopenharmony_ci 625425bb815Sopenharmony_ci int32_t start_ends_with = (int32_t) (start - search_str_len); 626425bb815Sopenharmony_ci 627425bb815Sopenharmony_ci if (start_ends_with < 0) 628425bb815Sopenharmony_ci { 629425bb815Sopenharmony_ci break; 630425bb815Sopenharmony_ci } 631425bb815Sopenharmony_ci if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, true, 632425bb815Sopenharmony_ci (ecma_length_t) start_ends_with, &index_of)) 633425bb815Sopenharmony_ci { 634425bb815Sopenharmony_ci ret_value = ecma_make_boolean_value (index_of == (ecma_length_t) start_ends_with); 635425bb815Sopenharmony_ci } 636425bb815Sopenharmony_ci break; 637425bb815Sopenharmony_ci } 638425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 639425bb815Sopenharmony_ci 640425bb815Sopenharmony_ci case ECMA_STRING_INDEX_OF: 641425bb815Sopenharmony_ci case ECMA_STRING_LAST_INDEX_OF: 642425bb815Sopenharmony_ci default: 643425bb815Sopenharmony_ci { 644425bb815Sopenharmony_ci /* 8 (indexOf) -- 9 (lastIndexOf) */ 645425bb815Sopenharmony_ci if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, use_first_index, start, &index_of)) 646425bb815Sopenharmony_ci { 647425bb815Sopenharmony_ci ret_num = ((ecma_number_t) index_of); 648425bb815Sopenharmony_ci } 649425bb815Sopenharmony_ci ret_value = ecma_make_number_value (ret_num); 650425bb815Sopenharmony_ci break; 651425bb815Sopenharmony_ci } 652425bb815Sopenharmony_ci } 653425bb815Sopenharmony_ci 654425bb815Sopenharmony_ci ecma_deref_ecma_string (search_str_p); 655425bb815Sopenharmony_ci 656425bb815Sopenharmony_ci return ret_value; 657425bb815Sopenharmony_ci} /* ecma_builtin_helper_string_prototype_object_index_of */ 658425bb815Sopenharmony_ci 659425bb815Sopenharmony_ci/** 660425bb815Sopenharmony_ci * Helper function for finding index of a search string 661425bb815Sopenharmony_ci * 662425bb815Sopenharmony_ci * This function clamps the given index to the [0, length] range. 663425bb815Sopenharmony_ci * If the index is negative, 0 value is used. 664425bb815Sopenharmony_ci * If the index is greater than the length of the string, the normalized index will be the length of the string. 665425bb815Sopenharmony_ci * NaN is mapped to zero or length depending on the nan_to_zero parameter. 666425bb815Sopenharmony_ci * 667425bb815Sopenharmony_ci * See also: 668425bb815Sopenharmony_ci * ECMA-262 v5, 15.5.4.7,8,11 669425bb815Sopenharmony_ci * 670425bb815Sopenharmony_ci * Used by: 671425bb815Sopenharmony_ci * - The ecma_builtin_helper_string_prototype_object_index_of helper routine. 672425bb815Sopenharmony_ci * - The ecma_builtin_string_prototype_object_replace_match helper routine. 673425bb815Sopenharmony_ci * 674425bb815Sopenharmony_ci * @return bool - whether there is a match for the search string 675425bb815Sopenharmony_ci */ 676425bb815Sopenharmony_cibool 677425bb815Sopenharmony_ciecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /**< index */ 678425bb815Sopenharmony_ci ecma_string_t *search_str_p, /**< string's length */ 679425bb815Sopenharmony_ci bool first_index, /**< whether search for first (t) or last (f) index */ 680425bb815Sopenharmony_ci ecma_length_t start_pos, /**< start position */ 681425bb815Sopenharmony_ci ecma_length_t *ret_index_p) /**< [out] position found in original string */ 682425bb815Sopenharmony_ci{ 683425bb815Sopenharmony_ci bool match_found = false; 684425bb815Sopenharmony_ci const ecma_length_t original_len = ecma_string_get_length (original_str_p); 685425bb815Sopenharmony_ci const ecma_length_t search_len = ecma_string_get_length (search_str_p); 686425bb815Sopenharmony_ci 687425bb815Sopenharmony_ci if (search_len <= original_len) 688425bb815Sopenharmony_ci { 689425bb815Sopenharmony_ci if (!search_len) 690425bb815Sopenharmony_ci { 691425bb815Sopenharmony_ci match_found = true; 692425bb815Sopenharmony_ci *ret_index_p = first_index ? start_pos : original_len; 693425bb815Sopenharmony_ci } 694425bb815Sopenharmony_ci else 695425bb815Sopenharmony_ci { 696425bb815Sopenharmony_ci /* create utf8 string from original string and advance to position */ 697425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (original_str_p, original_str_utf8_p, original_str_size); 698425bb815Sopenharmony_ci 699425bb815Sopenharmony_ci ecma_length_t index = start_pos; 700425bb815Sopenharmony_ci 701425bb815Sopenharmony_ci const lit_utf8_byte_t *original_str_curr_p = original_str_utf8_p; 702425bb815Sopenharmony_ci for (ecma_length_t idx = 0; idx < index; idx++) 703425bb815Sopenharmony_ci { 704425bb815Sopenharmony_ci lit_utf8_incr (&original_str_curr_p); 705425bb815Sopenharmony_ci } 706425bb815Sopenharmony_ci 707425bb815Sopenharmony_ci /* create utf8 string from search string */ 708425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (search_str_p, search_str_utf8_p, search_str_size); 709425bb815Sopenharmony_ci 710425bb815Sopenharmony_ci const lit_utf8_byte_t *search_str_curr_p = search_str_utf8_p; 711425bb815Sopenharmony_ci 712425bb815Sopenharmony_ci /* iterate original string and try to match at each position */ 713425bb815Sopenharmony_ci bool searching = true; 714425bb815Sopenharmony_ci ecma_char_t first_char = lit_cesu8_read_next (&search_str_curr_p); 715425bb815Sopenharmony_ci while (searching) 716425bb815Sopenharmony_ci { 717425bb815Sopenharmony_ci /* match as long as possible */ 718425bb815Sopenharmony_ci ecma_length_t match_len = 0; 719425bb815Sopenharmony_ci const lit_utf8_byte_t *stored_original_str_curr_p = original_str_curr_p; 720425bb815Sopenharmony_ci 721425bb815Sopenharmony_ci if (match_len < search_len && 722425bb815Sopenharmony_ci index + match_len < original_len && 723425bb815Sopenharmony_ci lit_cesu8_read_next (&original_str_curr_p) == first_char) 724425bb815Sopenharmony_ci { 725425bb815Sopenharmony_ci const lit_utf8_byte_t *nested_search_str_curr_p = search_str_curr_p; 726425bb815Sopenharmony_ci match_len++; 727425bb815Sopenharmony_ci 728425bb815Sopenharmony_ci while (match_len < search_len && 729425bb815Sopenharmony_ci index + match_len < original_len && 730425bb815Sopenharmony_ci lit_cesu8_read_next (&original_str_curr_p) == lit_cesu8_read_next (&nested_search_str_curr_p)) 731425bb815Sopenharmony_ci { 732425bb815Sopenharmony_ci match_len++; 733425bb815Sopenharmony_ci } 734425bb815Sopenharmony_ci } 735425bb815Sopenharmony_ci 736425bb815Sopenharmony_ci /* check for match */ 737425bb815Sopenharmony_ci if (match_len == search_len) 738425bb815Sopenharmony_ci { 739425bb815Sopenharmony_ci match_found = true; 740425bb815Sopenharmony_ci *ret_index_p = index; 741425bb815Sopenharmony_ci 742425bb815Sopenharmony_ci break; 743425bb815Sopenharmony_ci } 744425bb815Sopenharmony_ci else 745425bb815Sopenharmony_ci { 746425bb815Sopenharmony_ci /* inc/dec index and update iterators and search condition */ 747425bb815Sopenharmony_ci original_str_curr_p = stored_original_str_curr_p; 748425bb815Sopenharmony_ci 749425bb815Sopenharmony_ci if (first_index) 750425bb815Sopenharmony_ci { 751425bb815Sopenharmony_ci if ((searching = (index <= original_len - search_len))) 752425bb815Sopenharmony_ci { 753425bb815Sopenharmony_ci lit_utf8_incr (&original_str_curr_p); 754425bb815Sopenharmony_ci index++; 755425bb815Sopenharmony_ci } 756425bb815Sopenharmony_ci } 757425bb815Sopenharmony_ci else 758425bb815Sopenharmony_ci { 759425bb815Sopenharmony_ci if ((searching = (index > 0))) 760425bb815Sopenharmony_ci { 761425bb815Sopenharmony_ci lit_utf8_decr (&original_str_curr_p); 762425bb815Sopenharmony_ci index--; 763425bb815Sopenharmony_ci } 764425bb815Sopenharmony_ci } 765425bb815Sopenharmony_ci } 766425bb815Sopenharmony_ci } 767425bb815Sopenharmony_ci 768425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (search_str_utf8_p, search_str_size); 769425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (original_str_utf8_p, original_str_size); 770425bb815Sopenharmony_ci } 771425bb815Sopenharmony_ci } 772425bb815Sopenharmony_ci 773425bb815Sopenharmony_ci return match_found; 774425bb815Sopenharmony_ci} /* ecma_builtin_helper_string_find_index */ 775425bb815Sopenharmony_ci 776425bb815Sopenharmony_ci/** 777425bb815Sopenharmony_ci * Helper function for using [[DefineOwnProperty]] specialized for indexed property names 778425bb815Sopenharmony_ci * 779425bb815Sopenharmony_ci * Note: this method falls back to the general ecma_builtin_helper_def_prop 780425bb815Sopenharmony_ci * 781425bb815Sopenharmony_ci * @return ecma value 782425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 783425bb815Sopenharmony_ci */ 784425bb815Sopenharmony_ciecma_value_t 785425bb815Sopenharmony_ciecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, /**< object */ 786425bb815Sopenharmony_ci uint32_t index, /**< property index */ 787425bb815Sopenharmony_ci ecma_value_t value, /**< value */ 788425bb815Sopenharmony_ci uint32_t opts) /**< any combination of ecma_property_flag_t bits */ 789425bb815Sopenharmony_ci{ 790425bb815Sopenharmony_ci if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) 791425bb815Sopenharmony_ci { 792425bb815Sopenharmony_ci return ecma_builtin_helper_def_prop (obj_p, 793425bb815Sopenharmony_ci ECMA_CREATE_DIRECT_UINT32_STRING (index), 794425bb815Sopenharmony_ci value, 795425bb815Sopenharmony_ci opts); 796425bb815Sopenharmony_ci } 797425bb815Sopenharmony_ci 798425bb815Sopenharmony_ci ecma_string_t *index_str_p = ecma_new_non_direct_string_from_uint32 (index); 799425bb815Sopenharmony_ci ecma_value_t ret_value = ecma_builtin_helper_def_prop (obj_p, 800425bb815Sopenharmony_ci index_str_p, 801425bb815Sopenharmony_ci value, 802425bb815Sopenharmony_ci opts); 803425bb815Sopenharmony_ci ecma_deref_ecma_string (index_str_p); 804425bb815Sopenharmony_ci 805425bb815Sopenharmony_ci return ret_value; 806425bb815Sopenharmony_ci} /* ecma_builtin_helper_def_prop_by_index */ 807425bb815Sopenharmony_ci 808425bb815Sopenharmony_ci/** 809425bb815Sopenharmony_ci * Helper function for using [[DefineOwnProperty]]. 810425bb815Sopenharmony_ci * 811425bb815Sopenharmony_ci * See also: 812425bb815Sopenharmony_ci * ECMA-262 v5, 8.12.9 813425bb815Sopenharmony_ci * ECMA-262 v5, 15.4.5.1 814425bb815Sopenharmony_ci * 815425bb815Sopenharmony_ci * @return ecma value 816425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 817425bb815Sopenharmony_ci */ 818425bb815Sopenharmony_ciecma_value_t 819425bb815Sopenharmony_ciecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */ 820425bb815Sopenharmony_ci ecma_string_t *name_p, /**< name string */ 821425bb815Sopenharmony_ci ecma_value_t value, /**< value */ 822425bb815Sopenharmony_ci uint32_t opts) /**< any combination of ecma_property_flag_t bits 823425bb815Sopenharmony_ci * with the optional ECMA_IS_THROW flag */ 824425bb815Sopenharmony_ci{ 825425bb815Sopenharmony_ci ecma_property_descriptor_t prop_desc; 826425bb815Sopenharmony_ci 827425bb815Sopenharmony_ci prop_desc.flags = (uint16_t) (ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS | opts); 828425bb815Sopenharmony_ci 829425bb815Sopenharmony_ci prop_desc.value = value; 830425bb815Sopenharmony_ci 831425bb815Sopenharmony_ci return ecma_op_object_define_own_property (obj_p, 832425bb815Sopenharmony_ci name_p, 833425bb815Sopenharmony_ci &prop_desc); 834425bb815Sopenharmony_ci} /* ecma_builtin_helper_def_prop */ 835425bb815Sopenharmony_ci 836425bb815Sopenharmony_ci/** 837425bb815Sopenharmony_ci * GetSubstitution abstract operation 838425bb815Sopenharmony_ci * 839425bb815Sopenharmony_ci * See: 840425bb815Sopenharmony_ci * ECMA-262 v6.0 21.1.3.14.1 841425bb815Sopenharmony_ci */ 842425bb815Sopenharmony_civoid 843425bb815Sopenharmony_ciecma_builtin_replace_substitute (ecma_replace_context_t *ctx_p) /**< replace context */ 844425bb815Sopenharmony_ci{ 845425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->string_p != NULL); 846425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->matched_p == NULL 847425bb815Sopenharmony_ci || (ctx_p->matched_p >= ctx_p->string_p 848425bb815Sopenharmony_ci && ctx_p->matched_p <= ctx_p->string_p + ctx_p->string_size)); 849425bb815Sopenharmony_ci 850425bb815Sopenharmony_ci lit_utf8_size_t replace_size; 851425bb815Sopenharmony_ci uint8_t replace_flags = ECMA_STRING_FLAG_IS_ASCII; 852425bb815Sopenharmony_ci const lit_utf8_byte_t *replace_buf_p = ecma_string_get_chars (ctx_p->replace_str_p, 853425bb815Sopenharmony_ci &replace_size, 854425bb815Sopenharmony_ci NULL, 855425bb815Sopenharmony_ci NULL, 856425bb815Sopenharmony_ci &replace_flags); 857425bb815Sopenharmony_ci 858425bb815Sopenharmony_ci const lit_utf8_byte_t *const replace_end_p = replace_buf_p + replace_size; 859425bb815Sopenharmony_ci const lit_utf8_byte_t *curr_p = replace_buf_p; 860425bb815Sopenharmony_ci const lit_utf8_byte_t *last_inserted_end_p = replace_buf_p; 861425bb815Sopenharmony_ci 862425bb815Sopenharmony_ci while (curr_p < replace_end_p) 863425bb815Sopenharmony_ci { 864425bb815Sopenharmony_ci if (*curr_p++ == LIT_CHAR_DOLLAR_SIGN) 865425bb815Sopenharmony_ci { 866425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), 867425bb815Sopenharmony_ci last_inserted_end_p, 868425bb815Sopenharmony_ci (lit_utf8_size_t) (curr_p - last_inserted_end_p - 1)); 869425bb815Sopenharmony_ci if (curr_p >= replace_end_p) 870425bb815Sopenharmony_ci { 871425bb815Sopenharmony_ci last_inserted_end_p = curr_p - 1; 872425bb815Sopenharmony_ci break; 873425bb815Sopenharmony_ci } 874425bb815Sopenharmony_ci 875425bb815Sopenharmony_ci const lit_utf8_byte_t c = *curr_p++; 876425bb815Sopenharmony_ci 877425bb815Sopenharmony_ci switch (c) 878425bb815Sopenharmony_ci { 879425bb815Sopenharmony_ci case LIT_CHAR_DOLLAR_SIGN: 880425bb815Sopenharmony_ci { 881425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&(ctx_p->builder), LIT_CHAR_DOLLAR_SIGN); 882425bb815Sopenharmony_ci break; 883425bb815Sopenharmony_ci } 884425bb815Sopenharmony_ci case LIT_CHAR_AMPERSAND: 885425bb815Sopenharmony_ci { 886425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 887425bb815Sopenharmony_ci if (JERRY_UNLIKELY (ctx_p->matched_p == NULL)) 888425bb815Sopenharmony_ci { 889425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->capture_count == 0); 890425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->u.collection_p != NULL); 891425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->u.collection_p->item_count > 0); 892425bb815Sopenharmony_ci const ecma_value_t match_value = ctx_p->u.collection_p->buffer_p[0]; 893425bb815Sopenharmony_ci 894425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_string (match_value)); 895425bb815Sopenharmony_ci ecma_stringbuilder_append (&(ctx_p->builder), ecma_get_string_from_value (match_value)); 896425bb815Sopenharmony_ci break; 897425bb815Sopenharmony_ci } 898425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 899425bb815Sopenharmony_ci 900425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->matched_p != NULL); 901425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), ctx_p->matched_p, ctx_p->matched_size); 902425bb815Sopenharmony_ci break; 903425bb815Sopenharmony_ci } 904425bb815Sopenharmony_ci case LIT_CHAR_GRAVE_ACCENT: 905425bb815Sopenharmony_ci { 906425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), ctx_p->string_p, ctx_p->match_byte_pos); 907425bb815Sopenharmony_ci break; 908425bb815Sopenharmony_ci } 909425bb815Sopenharmony_ci case LIT_CHAR_SINGLE_QUOTE: 910425bb815Sopenharmony_ci { 911425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 912425bb815Sopenharmony_ci if (JERRY_UNLIKELY (ctx_p->matched_p == NULL)) 913425bb815Sopenharmony_ci { 914425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->capture_count == 0); 915425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->u.collection_p != NULL); 916425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->u.collection_p->item_count > 0); 917425bb815Sopenharmony_ci const ecma_value_t match_value = ctx_p->u.collection_p->buffer_p[0]; 918425bb815Sopenharmony_ci 919425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_string (match_value)); 920425bb815Sopenharmony_ci const ecma_string_t *const matched_p = ecma_get_string_from_value (match_value); 921425bb815Sopenharmony_ci const lit_utf8_size_t match_size = ecma_string_get_size (matched_p); 922425bb815Sopenharmony_ci const lit_utf8_byte_t *const begin_p = ctx_p->string_p + ctx_p->match_byte_pos + match_size; 923425bb815Sopenharmony_ci 924425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), 925425bb815Sopenharmony_ci begin_p, 926425bb815Sopenharmony_ci (lit_utf8_size_t) (ctx_p->string_p + ctx_p->string_size - begin_p)); 927425bb815Sopenharmony_ci break; 928425bb815Sopenharmony_ci } 929425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 930425bb815Sopenharmony_ci 931425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->matched_p != NULL); 932425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), 933425bb815Sopenharmony_ci ctx_p->matched_p + ctx_p->matched_size, 934425bb815Sopenharmony_ci ctx_p->string_size - ctx_p->match_byte_pos - ctx_p->matched_size); 935425bb815Sopenharmony_ci break; 936425bb815Sopenharmony_ci } 937425bb815Sopenharmony_ci default: 938425bb815Sopenharmony_ci { 939425bb815Sopenharmony_ci const lit_utf8_byte_t *const number_begin_p = curr_p - 1; 940425bb815Sopenharmony_ci 941425bb815Sopenharmony_ci if (lit_char_is_decimal_digit (c)) 942425bb815Sopenharmony_ci { 943425bb815Sopenharmony_ci uint32_t capture_count = ctx_p->capture_count; 944425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 945425bb815Sopenharmony_ci if (capture_count == 0 && ctx_p->u.collection_p != NULL) 946425bb815Sopenharmony_ci { 947425bb815Sopenharmony_ci capture_count = ctx_p->u.collection_p->item_count; 948425bb815Sopenharmony_ci } 949425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 950425bb815Sopenharmony_ci 951425bb815Sopenharmony_ci uint8_t idx = (uint8_t) (c - LIT_CHAR_0); 952425bb815Sopenharmony_ci if (curr_p < replace_end_p && lit_char_is_decimal_digit (*(curr_p))) 953425bb815Sopenharmony_ci { 954425bb815Sopenharmony_ci uint8_t two_digit_index = (uint8_t) (idx * 10 + (uint8_t) (*(curr_p) - LIT_CHAR_0)); 955425bb815Sopenharmony_ci if (two_digit_index < capture_count) 956425bb815Sopenharmony_ci { 957425bb815Sopenharmony_ci idx = two_digit_index; 958425bb815Sopenharmony_ci curr_p++; 959425bb815Sopenharmony_ci } 960425bb815Sopenharmony_ci } 961425bb815Sopenharmony_ci 962425bb815Sopenharmony_ci if (idx > 0 && idx < capture_count) 963425bb815Sopenharmony_ci { 964425bb815Sopenharmony_ci if (ctx_p->capture_count > 0) 965425bb815Sopenharmony_ci { 966425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_REGEXP) 967425bb815Sopenharmony_ci JERRY_ASSERT (ctx_p->u.captures_p != NULL); 968425bb815Sopenharmony_ci const ecma_regexp_capture_t *const capture_p = ctx_p->u.captures_p + idx; 969425bb815Sopenharmony_ci 970425bb815Sopenharmony_ci if (ECMA_RE_IS_CAPTURE_DEFINED (capture_p)) 971425bb815Sopenharmony_ci { 972425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), 973425bb815Sopenharmony_ci capture_p->begin_p, 974425bb815Sopenharmony_ci (lit_utf8_size_t) (capture_p->end_p - capture_p->begin_p)); 975425bb815Sopenharmony_ci } 976425bb815Sopenharmony_ci 977425bb815Sopenharmony_ci break; 978425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */ 979425bb815Sopenharmony_ci } 980425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 981425bb815Sopenharmony_ci else if (ctx_p->u.collection_p != NULL) 982425bb815Sopenharmony_ci { 983425bb815Sopenharmony_ci const ecma_value_t capture_value = ctx_p->u.collection_p->buffer_p[idx]; 984425bb815Sopenharmony_ci if (!ecma_is_value_undefined (capture_value)) 985425bb815Sopenharmony_ci { 986425bb815Sopenharmony_ci ecma_stringbuilder_append (&(ctx_p->builder), ecma_get_string_from_value (capture_value)); 987425bb815Sopenharmony_ci } 988425bb815Sopenharmony_ci 989425bb815Sopenharmony_ci break; 990425bb815Sopenharmony_ci } 991425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 992425bb815Sopenharmony_ci } 993425bb815Sopenharmony_ci } 994425bb815Sopenharmony_ci 995425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&(ctx_p->builder), LIT_CHAR_DOLLAR_SIGN); 996425bb815Sopenharmony_ci curr_p = number_begin_p; 997425bb815Sopenharmony_ci break; 998425bb815Sopenharmony_ci } 999425bb815Sopenharmony_ci } 1000425bb815Sopenharmony_ci 1001425bb815Sopenharmony_ci last_inserted_end_p = curr_p; 1002425bb815Sopenharmony_ci } 1003425bb815Sopenharmony_ci } 1004425bb815Sopenharmony_ci 1005425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&(ctx_p->builder), 1006425bb815Sopenharmony_ci last_inserted_end_p, 1007425bb815Sopenharmony_ci (lit_utf8_size_t) (replace_end_p - last_inserted_end_p)); 1008425bb815Sopenharmony_ci 1009425bb815Sopenharmony_ci if (replace_flags & ECMA_STRING_FLAG_MUST_BE_FREED) 1010425bb815Sopenharmony_ci { 1011425bb815Sopenharmony_ci jmem_heap_free_block ((void *) replace_buf_p, replace_size); 1012425bb815Sopenharmony_ci } 1013425bb815Sopenharmony_ci} /* ecma_builtin_replace_substitute */ 1014425bb815Sopenharmony_ci 1015425bb815Sopenharmony_ci/** 1016425bb815Sopenharmony_ci * @} 1017425bb815Sopenharmony_ci * @} 1018425bb815Sopenharmony_ci */ 1019