16
16
17
17
#include " ecma-builtin-helpers.h"
18
18
19
+ #include " ecma-alloc.h"
19
20
#include " ecma-array-object.h"
20
21
#include " ecma-builtins.h"
21
22
#include " ecma-conversion.h"
@@ -481,11 +482,19 @@ ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */
481
482
*/
482
483
uint32_t
483
484
ecma_builtin_helper_string_index_normalize (ecma_number_t index, /* *< index */
484
- uint32_t length) /* *< string's length */
485
+ uint32_t length, /* *< string's length */
486
+ bool nan_to_zero) /* *< whether NaN is mapped to zero (t) or length (f) */
485
487
{
486
488
uint32_t norm_index = 0 ;
487
489
488
- if (!ecma_number_is_nan (index) && !ecma_number_is_negative (index))
490
+ if (ecma_number_is_nan (index))
491
+ {
492
+ if (!nan_to_zero)
493
+ {
494
+ norm_index = length;
495
+ }
496
+ }
497
+ else if (!ecma_number_is_negative (index))
489
498
{
490
499
if (ecma_number_is_infinity (index))
491
500
{
@@ -505,6 +514,163 @@ ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */
505
514
return norm_index;
506
515
} /* ecma_builtin_helper_string_index_normalize */
507
516
517
+ /* *
518
+ * Helper function for string indexOf and lastIndexOf functions
519
+ *
520
+ * This function implements string indexOf and lastIndexOf with required checks and conversions.
521
+ *
522
+ * See also:
523
+ * ECMA-262 v5, 15.5.4.7
524
+ * ECMA-262 v5, 15.5.4.8
525
+ *
526
+ * Used by:
527
+ * - The String.prototype.indexOf routine.
528
+ * - The String.prototype.lastIndexOf routine.
529
+ *
530
+ * @return uint32_t - (last)index of search string
531
+ */
532
+ ecma_completion_value_t
533
+ ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /* *< this argument */
534
+ ecma_value_t arg1, /* *< routine's first argument */
535
+ ecma_value_t arg2, /* *< routine's second argument */
536
+ bool firstIndex) /* *< routine's third argument */
537
+ {
538
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
539
+
540
+ /* 1 */
541
+ ECMA_TRY_CATCH (check_coercible_val,
542
+ ecma_op_check_object_coercible (this_arg),
543
+ ret_value);
544
+
545
+ /* 2 */
546
+ ECMA_TRY_CATCH (to_str_val,
547
+ ecma_op_to_string (this_arg),
548
+ ret_value);
549
+
550
+ /* 3 */
551
+ ECMA_TRY_CATCH (search_str_val,
552
+ ecma_op_to_string (arg1),
553
+ ret_value);
554
+
555
+ /* 4 */
556
+ ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num,
557
+ arg2,
558
+ ret_value);
559
+
560
+ /* 6 */
561
+ ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val);
562
+ const ecma_length_t original_len = ecma_string_get_length (original_str_p);
563
+ const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p);
564
+
565
+ /* 4b, 5, 7 */
566
+ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, firstIndex);
567
+
568
+ /* 8 */
569
+ ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val);
570
+ const ecma_length_t search_len = ecma_string_get_length (search_str_p);
571
+ const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p);
572
+
573
+ ecma_number_t *ret_num_p = ecma_alloc_number ();
574
+ *ret_num_p = ecma_int32_to_number (-1 );
575
+
576
+ /* 9 */
577
+ if (search_len <= original_len)
578
+ {
579
+ if (!search_len)
580
+ {
581
+ *ret_num_p = ecma_uint32_to_number (firstIndex ? 0 : original_len);
582
+ }
583
+ else
584
+ {
585
+ /* create utf8 string from original string and advance to position */
586
+ MEM_DEFINE_LOCAL_ARRAY (original_str_utf8_p,
587
+ original_size,
588
+ lit_utf8_byte_t );
589
+
590
+ ecma_string_to_utf8_string (original_str_p,
591
+ original_str_utf8_p,
592
+ (ssize_t ) (original_size));
593
+
594
+ lit_utf8_iterator_t original_it = lit_utf8_iterator_create (original_str_utf8_p, original_size);
595
+
596
+ ecma_length_t index = start;
597
+ lit_utf8_iterator_advance (&original_it, index);
598
+
599
+ /* create utf8 string from search string */
600
+ MEM_DEFINE_LOCAL_ARRAY (search_str_utf8_p,
601
+ search_size,
602
+ lit_utf8_byte_t );
603
+
604
+ ecma_string_to_utf8_string (search_str_p,
605
+ search_str_utf8_p,
606
+ (ssize_t ) (search_size));
607
+
608
+ lit_utf8_iterator_t search_it = lit_utf8_iterator_create (search_str_utf8_p, search_size);
609
+
610
+ /* iterate original string and try to match at each position */
611
+ bool found = false ;
612
+ bool searching = true ;
613
+
614
+ while (!found && searching)
615
+ {
616
+ /* match as long as possible */
617
+ ecma_length_t match_len = 0 ;
618
+ lit_utf8_iterator_pos_t stored_original_pos = lit_utf8_iterator_get_pos (&original_it);
619
+
620
+ while (match_len < search_len &&
621
+ index + match_len < original_len &&
622
+ lit_utf8_iterator_read_next (&original_it) == lit_utf8_iterator_read_next (&search_it))
623
+ {
624
+ match_len++;
625
+ }
626
+
627
+ /* check for match */
628
+ if (match_len == search_len)
629
+ {
630
+ *ret_num_p = ecma_uint32_to_number (index);
631
+ found = true ;
632
+ }
633
+ else
634
+ {
635
+ /* inc/dec index and update iterators and search condition */
636
+ lit_utf8_iterator_seek_bos (&search_it);
637
+ lit_utf8_iterator_seek (&original_it, stored_original_pos);
638
+
639
+ if (firstIndex)
640
+ {
641
+ if ((searching = (index <= original_len - search_len)))
642
+ {
643
+ lit_utf8_iterator_incr (&original_it);
644
+ index++;
645
+ }
646
+ }
647
+ else
648
+ {
649
+ if ((searching = (index > 0 )))
650
+ {
651
+ lit_utf8_iterator_decr (&original_it);
652
+ index--;
653
+ }
654
+ }
655
+ }
656
+ }
657
+
658
+ MEM_FINALIZE_LOCAL_ARRAY (search_str_utf8_p);
659
+ MEM_FINALIZE_LOCAL_ARRAY (original_str_utf8_p);
660
+ }
661
+ }
662
+
663
+ ecma_value_t new_value = ecma_make_number_value (ret_num_p);
664
+ ret_value = ecma_make_normal_completion_value (new_value);
665
+
666
+ ECMA_OP_TO_NUMBER_FINALIZE (pos_num);
667
+ ECMA_FINALIZE (search_str_val);
668
+ ECMA_FINALIZE (to_str_val);
669
+ ECMA_FINALIZE (check_coercible_val);
670
+
671
+ return ret_value;
672
+ } /* ecma_builtin_helper_string_index_normalize */
673
+
508
674
/* *
509
675
* @}
510
676
* @}
0 commit comments