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