@@ -430,7 +430,6 @@ ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */
430430 *
431431 * Used by:
432432 * - The String.prototype.substring routine.
433- * - The String.prototype.indexOf routine.
434433 * - The ecma_builtin_helper_string_prototype_object_index_of helper routine.
435434 *
436435 * @return uint32_t - the normalized value of the index
@@ -469,7 +468,7 @@ ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */
469468 return norm_index;
470469} /* ecma_builtin_helper_string_index_normalize */
471470
472- /*
471+ /* *
473472 * Helper function for string indexOf and lastIndexOf functions
474473 *
475474 * This function implements string indexOf and lastIndexOf with required checks and conversions.
@@ -488,7 +487,7 @@ ecma_completion_value_t
488487ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /* *< this argument */
489488 ecma_value_t arg1, /* *< routine's first argument */
490489 ecma_value_t arg2, /* *< routine's second argument */
491- bool firstIndex ) /* *< routine's third argument */
490+ bool first_index ) /* *< routine's third argument */
492491{
493492 ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
494493
@@ -512,28 +511,74 @@ ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**
512511 arg2,
513512 ret_value);
514513
515- /* 6 */
514+ /* 5 (indexOf) -- 6 (lastIndexOf) */
516515 ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val);
517516 const ecma_length_t original_len = ecma_string_get_length (original_str_p);
518- const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p);
519517
520- /* 4b, 5, 7 */
521- ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, firstIndex );
518+ /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */
519+ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, first_index );
522520
523- /* 8 */
521+ /* 7 (indexOf) -- 8 (lastIndexOf) */
524522 ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val);
525- const ecma_length_t search_len = ecma_string_get_length (search_str_p);
526- const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p);
527523
528524 ecma_number_t *ret_num_p = ecma_alloc_number ();
529525 *ret_num_p = ecma_int32_to_number (-1 );
530526
531- /* 9 */
527+ /* 8 (indexOf) -- 9 (lastIndexOf) */
528+ ecma_length_t index_of = 0 ;
529+ if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, first_index, start, &index_of))
530+ {
531+ *ret_num_p = ecma_uint32_to_number (index_of);
532+ }
533+
534+ ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
535+
536+ ECMA_OP_TO_NUMBER_FINALIZE (pos_num);
537+ ECMA_FINALIZE (search_str_val);
538+ ECMA_FINALIZE (to_str_val);
539+ ECMA_FINALIZE (check_coercible_val);
540+
541+ return ret_value;
542+ } /* ecma_builtin_helper_string_prototype_object_index_of */
543+
544+ /* *
545+ * Helper function for finding index of a search string
546+ *
547+ * This function clamps the given index to the [0, length] range.
548+ * If the index is negative, 0 value is used.
549+ * If the index is greater than the length of the string, the normalized index will be the length of the string.
550+ * NaN is mapped to zero or length depending on the nan_to_zero parameter.
551+ *
552+ * See also:
553+ * ECMA-262 v5, 15.5.4.7,8,11
554+ *
555+ * Used by:
556+ * - The ecma_builtin_helper_string_prototype_object_index_of helper routine.
557+ * - The ecma_builtin_string_prototype_object_replace_match helper routine.
558+ *
559+ * @return uint32_t - the normalized value of the index
560+ */
561+ bool
562+ ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, /* *< index */
563+ ecma_string_t *search_str_p, /* *< string's length */
564+ bool first_index, /* *< whether search for first (t) or last (f) index */
565+ ecma_length_t start_pos, /* *< start position */
566+ ecma_length_t *ret_index_p) /* *> position found in original string */
567+ {
568+ bool match_found = false ;
569+
570+ const ecma_length_t original_len = ecma_string_get_length (original_str_p);
571+ const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p);
572+
573+ const ecma_length_t search_len = ecma_string_get_length (search_str_p);
574+ const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p);
575+
532576 if (search_len <= original_len)
533577 {
534578 if (!search_len)
535579 {
536- *ret_num_p = ecma_uint32_to_number (firstIndex ? 0 : original_len);
580+ match_found = true ;
581+ *ret_index_p = first_index ? 0 : original_len;
537582 }
538583 else
539584 {
@@ -547,7 +592,7 @@ ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**
547592 (ssize_t ) (original_size));
548593 JERRY_ASSERT (sz >= 0 );
549594
550- ecma_length_t index = start ;
595+ ecma_length_t index = start_pos ;
551596
552597 lit_utf8_byte_t *original_str_curr_p = original_str_utf8_p + index;
553598
@@ -565,33 +610,42 @@ ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**
565610
566611 /* iterate original string and try to match at each position */
567612 bool searching = true ;
568-
613+ ecma_char_t first_char = lit_utf8_read_next (&search_str_curr_p);
569614 while (searching)
570615 {
571616 /* match as long as possible */
572617 ecma_length_t match_len = 0 ;
573618 lit_utf8_byte_t *stored_original_str_curr_p = original_str_curr_p;
574619
575- while (match_len < search_len &&
576- index + match_len < original_len &&
577- lit_utf8_read_next (&original_str_curr_p) == lit_utf8_read_next (&search_str_curr_p) )
620+ if (match_len < search_len &&
621+ index + match_len < original_len &&
622+ lit_utf8_read_next (&original_str_curr_p) == first_char )
578623 {
624+ lit_utf8_byte_t *nested_search_str_curr_p = search_str_curr_p;
579625 match_len++;
626+
627+ while (match_len < search_len &&
628+ index + match_len < original_len &&
629+ lit_utf8_read_next (&original_str_curr_p) == lit_utf8_read_next (&nested_search_str_curr_p))
630+ {
631+ match_len++;
632+ }
580633 }
581634
582635 /* check for match */
583636 if (match_len == search_len)
584637 {
585- *ret_num_p = ecma_uint32_to_number (index);
638+ match_found = true ;
639+ *ret_index_p = index;
640+
586641 break ;
587642 }
588643 else
589644 {
590645 /* inc/dec index and update iterators and search condition */
591- search_str_curr_p = search_str_utf8_p;
592646 original_str_curr_p = stored_original_str_curr_p;
593647
594- if (firstIndex )
648+ if (first_index )
595649 {
596650 if ((searching = (index <= original_len - search_len)))
597651 {
@@ -615,16 +669,8 @@ ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**
615669 }
616670 }
617671
618- ecma_value_t new_value = ecma_make_number_value (ret_num_p);
619- ret_value = ecma_make_normal_completion_value (new_value);
620-
621- ECMA_OP_TO_NUMBER_FINALIZE (pos_num);
622- ECMA_FINALIZE (search_str_val);
623- ECMA_FINALIZE (to_str_val);
624- ECMA_FINALIZE (check_coercible_val);
625-
626- return ret_value;
627- } /* ecma_builtin_helper_string_index_normalize */
672+ return match_found;
673+ } /* ecma_builtin_helper_string_find_index */
628674
629675/* *
630676 * Helper function for using [[DefineOwnProperty]].
0 commit comments