@@ -532,73 +532,167 @@ ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */
532532} /* ecma_builtin_helper_string_index_normalize */
533533
534534/**
535- * Helper function for string indexOf and lastIndexOf functions
536- *
537- * This function implements string indexOf and lastIndexOf with required checks and conversions.
535+ * Helper function for string indexOf, lastIndexOf, startsWith, includes, endsWith functions
538536 *
539537 * See also:
540538 * ECMA-262 v5, 15.5.4.7
541539 * ECMA-262 v5, 15.5.4.8
540+ * ECMA-262 v6, 21.1.3.6
541+ * ECMA-262 v6, 21.1.3.7
542+ * ECMA-262 v6, 21.1.3.18
542543 *
543544 * Used by:
544545 * - The String.prototype.indexOf routine.
545546 * - The String.prototype.lastIndexOf routine.
547+ * - The String.prototype.startsWith routine.
548+ * - The String.prototype.includes routine.
549+ * - The String.prototype.endsWith routine.
546550 *
547- * @return ecma_value_t - (last) index of search string as an ecma-value
551+ * @return ecma_value_t - Returns index (last index) or a
552+ * boolean value
548553 */
549554ecma_value_t
550555ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg , /**< this argument */
551556 ecma_value_t arg1 , /**< routine's first argument */
552557 ecma_value_t arg2 , /**< routine's second argument */
553- bool first_index ) /**< routine's third argument */
558+ ecma_string_index_of_mode_t mode ) /**< routine's mode */
554559{
555- ecma_value_t ret_value = ECMA_VALUE_EMPTY ;
556-
557560 /* 1 */
558- ECMA_TRY_CATCH (check_coercible_val ,
559- ecma_op_check_object_coercible (this_arg ),
560- ret_value );
561+ if (ECMA_IS_VALUE_ERROR (ecma_op_check_object_coercible (this_arg )))
562+ {
563+ return ECMA_VALUE_ERROR ;
564+ }
561565
562566 /* 2 */
563- ECMA_TRY_CATCH (to_str_val ,
564- ecma_op_to_string (this_arg ),
565- ret_value );
567+ ecma_value_t to_str_val = ecma_op_to_string (this_arg );
566568
567- /* 3 */
568- ECMA_TRY_CATCH (search_str_val ,
569- ecma_op_to_string (arg1 ),
570- ret_value );
571-
572- /* 4 */
573- ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num ,
574- arg2 ,
575- ret_value );
569+ if (ECMA_IS_VALUE_ERROR (to_str_val ))
570+ {
571+ return to_str_val ;
572+ }
576573
577- /* 5 (indexOf) -- 6 (lastIndexOf) */
574+ /* 5 (indexOf), 6 (lastIndexOf), 11 (startsWith, includes ) */
578575 ecma_string_t * original_str_p = ecma_get_string_from_value (to_str_val );
579576 const ecma_length_t original_len = ecma_string_get_length (original_str_p );
580577
581- /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */
582- ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num , original_len , first_index );
578+ #if ENABLED (JERRY_ES2015_BUILTIN )
579+ /* 4, 6 (startsWith, includes, endsWith) */
580+ if (mode >= ECMA_STRING_STARTS_WITH
581+ && (ecma_is_value_object (arg1 )
582+ && ecma_object_class_is (ecma_get_object_from_value (arg1 ), LIT_MAGIC_STRING_REGEXP_UL )))
583+ {
584+ JERRY_ASSERT (ECMA_STRING_LAST_INDEX_OF < mode && mode <= ECMA_STRING_ENDS_WITH );
585+ ecma_deref_ecma_string (original_str_p );
586+ return ecma_raise_type_error (ECMA_ERR_MSG ("Search string can't be of type: RegExp" ));
587+ }
588+ #endif /* ENABLED (JERRY_ES2015_BUILTIN) */
583589
584- /* 7 (indexOf) -- 8 (lastIndexOf) */
590+ /* 3 */
591+ ecma_value_t search_str_val = ecma_op_to_string (arg1 );
592+
593+ if (ECMA_IS_VALUE_ERROR (search_str_val ))
594+ {
595+ ecma_deref_ecma_string (original_str_p );
596+ return search_str_val ;
597+ }
598+
599+ /* 7, 8 */
585600 ecma_string_t * search_str_p = ecma_get_string_from_value (search_str_val );
586601
602+ /* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */
603+ ecma_number_t pos_num ;
604+ ecma_value_t ret_value = ecma_get_number (arg2 , & pos_num );
605+
606+ /* 10 (startsWith, includes), 11 (endsWith) */
607+ if (ECMA_IS_VALUE_ERROR (ret_value ))
608+ {
609+ ecma_deref_ecma_string (original_str_p );
610+ ecma_deref_ecma_string (search_str_p );
611+ return ret_value ;
612+ }
613+
614+ bool use_first_index = mode != ECMA_STRING_LAST_INDEX_OF ;
615+
616+ /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */
617+ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num , original_len , use_first_index );
618+
587619 ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE ;
588620
589- /* 8 (indexOf) -- 9 (lastIndexOf) */
590621 ecma_length_t index_of = 0 ;
591- if (ecma_builtin_helper_string_find_index (original_str_p , search_str_p , first_index , start , & index_of ))
622+
623+ ret_value = ECMA_VALUE_FALSE ;
624+
625+ switch (mode )
592626 {
593- ret_num = ((ecma_number_t ) index_of );
594- }
627+ #if ENABLED (JERRY_ES2015_BUILTIN )
628+ case ECMA_STRING_STARTS_WITH :
629+ {
630+ if (pos_num + start > original_len )
631+ {
632+ break ;
633+ }
634+
635+ if (ecma_builtin_helper_string_find_index (original_str_p , search_str_p , true, start , & index_of ))
636+ {
637+ /* 15, 16 (startsWith) */
638+ ret_value = ecma_make_boolean_value (index_of == start );
639+ }
640+ break ;
641+ }
642+ case ECMA_STRING_INCLUDES :
643+ {
644+ if (ecma_builtin_helper_string_find_index (original_str_p , search_str_p , true, start , & index_of ))
645+ {
646+ ret_value = ECMA_VALUE_TRUE ;
647+ }
648+ break ;
649+ }
650+ case ECMA_STRING_ENDS_WITH :
651+ {
652+ if (start == 0 )
653+ {
654+ start = original_len ;
655+ }
656+
657+ ecma_length_t search_str_len = ecma_string_get_length (search_str_p );
595658
596- ret_value = ecma_make_number_value (ret_num );
659+ if (search_str_len == 0 )
660+ {
661+ ret_value = ECMA_VALUE_TRUE ;
662+ break ;
663+ }
664+
665+ int32_t start_ends_with = (int32_t ) (start - search_str_len );
666+
667+ if (start_ends_with < 0 )
668+ {
669+ break ;
670+ }
671+ if (ecma_builtin_helper_string_find_index (original_str_p , search_str_p , true,
672+ (ecma_length_t ) start_ends_with , & index_of ))
673+ {
674+ ret_value = ecma_make_boolean_value (index_of == (ecma_length_t ) start_ends_with );
675+ }
676+ break ;
677+ }
678+ #endif /* ENABLED (JERRY_ES2015_BUILTIN) */
679+
680+ case ECMA_STRING_INDEX_OF :
681+ case ECMA_STRING_LAST_INDEX_OF :
682+ default :
683+ {
684+ /* 8 (indexOf) -- 9 (lastIndexOf) */
685+ if (ecma_builtin_helper_string_find_index (original_str_p , search_str_p , use_first_index , start , & index_of ))
686+ {
687+ ret_num = ((ecma_number_t ) index_of );
688+ }
689+ ret_value = ecma_make_number_value (ret_num );
690+ break ;
691+ }
692+ }
597693
598- ECMA_OP_TO_NUMBER_FINALIZE (pos_num );
599- ECMA_FINALIZE (search_str_val );
600- ECMA_FINALIZE (to_str_val );
601- ECMA_FINALIZE (check_coercible_val );
694+ ecma_deref_ecma_string (search_str_p );
695+ ecma_deref_ecma_string (original_str_p );
602696
603697 return ret_value ;
604698} /* ecma_builtin_helper_string_prototype_object_index_of */
0 commit comments