@@ -529,6 +529,140 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this a
529
529
return ret_value;
530
530
} /* ecma_builtin_array_prototype_object_index_of */
531
531
532
+ /* *
533
+ * The Array.prototype object's 'lastIndexOf' routine
534
+ *
535
+ * See also:
536
+ * ECMA-262 v5, 15.4.4.15
537
+ *
538
+ * @return completion value
539
+ * Returned value must be freed with ecma_free_completion_value.
540
+ */
541
+ static ecma_completion_value_t
542
+ ecma_builtin_array_prototype_object_last_index_of (ecma_value_t this_arg, /* *< this argument */
543
+ ecma_value_t arg1, /* *< searchElement */
544
+ ecma_value_t arg2) /* *< fromIndex */
545
+ {
546
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
547
+
548
+ /* 1. */
549
+ ECMA_TRY_CATCH (obj_this,
550
+ ecma_op_to_object (this_arg),
551
+ ret_value);
552
+
553
+ ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
554
+ ecma_string_t *magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
555
+
556
+ /* 2. */
557
+ ECMA_TRY_CATCH (len_value,
558
+ ecma_op_object_get (obj_p, magic_string_length_p),
559
+ ret_value);
560
+
561
+ ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
562
+
563
+ /* 3. */
564
+ uint32_t len = ecma_number_to_uint32 (len_number);
565
+
566
+ ecma_number_t * num_p = ecma_alloc_number ();
567
+ *num_p = ecma_int32_to_number (-1 );
568
+
569
+ /* 4. */
570
+ if (len == 0 )
571
+ {
572
+ ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
573
+ }
574
+ else
575
+ {
576
+ uint32_t k = len - 1 ;
577
+
578
+ /* 5. */
579
+ if (!ecma_is_value_undefined (arg2))
580
+ {
581
+ ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value);
582
+ int32_t n = ecma_number_to_int32 (arg_from_idx);
583
+
584
+ /* 6. */
585
+ if (n >= 0 )
586
+ {
587
+ /* min(n, len - 1)*/
588
+ if ((uint32_t ) n > len - 1 )
589
+ {
590
+ k = len - 1 ;
591
+ }
592
+ else
593
+ {
594
+ k = (uint32_t ) n;
595
+ }
596
+ }
597
+ /* 7. */
598
+ else
599
+ {
600
+ n = -n;
601
+
602
+ /* We prevent k from being negative, so that we can use an uint32 */
603
+ if ((uint32_t ) n <= len)
604
+ {
605
+ k = len - (uint32_t ) n;
606
+ }
607
+ else
608
+ {
609
+ /*
610
+ * If k would be negative, we set it to UINT_MAX. See reasoning for this in the comment
611
+ * at the for loop below.
612
+ */
613
+ k = (uint32_t ) -1 ;
614
+ }
615
+ }
616
+
617
+ ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx);
618
+ }
619
+
620
+ /* 8.
621
+ * We should break from the loop when k < 0. We can still use an uint32_t for k, and check
622
+ * for an underflow instead. This is safe, because k will always start in [0, len - 1],
623
+ * and len is in [0, UINT_MAX], so k >= len means we've had an underflow, and should stop.
624
+ */
625
+ for (;k < len && *num_p < 0 && ecma_is_completion_value_empty (ret_value); k--)
626
+ {
627
+ /* 8.a */
628
+ ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (k);
629
+
630
+ /* 8.a */
631
+ if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL )
632
+ {
633
+ /* 8.b.i */
634
+ ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, idx_str_p), ret_value);
635
+
636
+ /* 8.b.ii */
637
+ if (ecma_op_strict_equality_compare (arg1, get_value))
638
+ {
639
+ *num_p = ecma_uint32_to_number (k);
640
+ }
641
+
642
+ ECMA_FINALIZE (get_value);
643
+ }
644
+
645
+ ecma_deref_ecma_string (idx_str_p);
646
+ }
647
+
648
+ if (ecma_is_completion_value_empty (ret_value))
649
+ {
650
+ ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
651
+ }
652
+ else
653
+ {
654
+ ecma_dealloc_number (num_p);
655
+ }
656
+ }
657
+
658
+ ECMA_OP_TO_NUMBER_FINALIZE (len_number);
659
+ ECMA_FINALIZE (len_value);
660
+ ecma_deref_ecma_string (magic_string_length_p);
661
+ ECMA_FINALIZE (obj_this);
662
+
663
+ return ret_value;
664
+ } /* ecma_builtin_array_prototype_object_last_index_of */
665
+
532
666
/* *
533
667
* The Array.prototype object's 'shift' routine
534
668
*
0 commit comments