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