Skip to content

Commit 6ec4455

Browse files
authored
Implement Symbol.matchAll (#4082)
The following methods were implemented: - String.prototype.matchAll based on ECMA-262 v11, 21.1.3.12 - RegExp.prototype[@@matchall] based on ECMA-262 v11, 21.2.5.8 - RegExp String Iterator Object based on 21.2.7 JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi [email protected]
1 parent 1d42d17 commit 6ec4455

24 files changed

+964
-82
lines changed

docs/02.API-REFERENCE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ Well-known symbols:
181181
- JERRY_SYMBOL_TO_PRIMITIVE - @@toPrimitive well-known symbol
182182
- JERRY_SYMBOL_TO_STRING_TAG - @@toStringTag well-known symbol
183183
- JERRY_SYMBOL_UNSCOPABLES - @@unscopables well-known symbol
184+
- JERRY_SYMBOL_MATCH_ALL - @@matchAll well-known symbol
184185

185186
*New in version 2.4*.
186187

jerry-core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ set(SOURCE_CORE_FILES
199199
ecma/builtin-objects/ecma-builtin-referenceerror.c
200200
ecma/builtin-objects/ecma-builtin-reflect.c
201201
ecma/builtin-objects/ecma-builtin-regexp-prototype.c
202+
ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.c
202203
ecma/builtin-objects/ecma-builtin-regexp.c
203204
ecma/builtin-objects/ecma-builtin-set-iterator-prototype.c
204205
ecma/builtin-objects/ecma-builtin-set-prototype.c
@@ -386,6 +387,7 @@ if(ENABLE_AMALGAM)
386387
ecma/builtin-objects/ecma-builtin-referenceerror.inc.h
387388
ecma/builtin-objects/ecma-builtin-reflect.inc.h
388389
ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h
390+
ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.inc.h
389391
ecma/builtin-objects/ecma-builtin-regexp.inc.h
390392
ecma/builtin-objects/ecma-builtin-set-iterator-prototype.inc.h
391393
ecma/builtin-objects/ecma-builtin-set-prototype.inc.h

jerry-core/ecma/base/ecma-gc.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,13 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
813813
{
814814
break;
815815
}
816+
case ECMA_PSEUDO_REGEXP_STRING_ITERATOR:
817+
{
818+
ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) object_p;
819+
ecma_value_t regexp = regexp_string_iterator_obj->iterating_regexp;
820+
ecma_gc_set_object_visited (ecma_get_object_from_value (regexp));
821+
break;
822+
}
816823
#endif /* ENABLED (JERRY_ESNEXT) */
817824
default:
818825
{
@@ -1728,6 +1735,19 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
17281735

17291736
break;
17301737
}
1738+
case ECMA_PSEUDO_REGEXP_STRING_ITERATOR:
1739+
{
1740+
ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) object_p;
1741+
ecma_value_t iterated_string = regexp_string_iterator_obj->iterated_string;
1742+
1743+
if (!ecma_is_value_empty (iterated_string))
1744+
{
1745+
ecma_deref_ecma_string (ecma_get_string_from_value (iterated_string));
1746+
}
1747+
1748+
ext_object_size = sizeof (ecma_regexp_string_iterator_t);
1749+
break;
1750+
}
17311751
#endif /* ENABLED (JERRY_ESNEXT) */
17321752
default:
17331753
{

jerry-core/ecma/base/ecma-globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ typedef enum
685685
ECMA_PSEUDO_SET_ITERATOR = 4, /**< Set iterator object (ECMAScript v6, 23.2.5.1) */
686686
ECMA_PSEUDO_MAP_ITERATOR = 5, /**< Map iterator object (ECMAScript v6, 23.1.5.1) */
687687
ECMA_PSEUDO_STRING_ITERATOR = 6, /**< String iterator object (ECMAScript v6, 22.1.5.1) */
688+
ECMA_PSEUDO_REGEXP_STRING_ITERATOR = 7, /** RegExp string iterator object (ECMAScript v11, 21.2.7) */
688689
ECMA_PSEUDO_ARRAY__MAX = ECMA_PSEUDO_STRING_ITERATOR /**< maximum value */
689690
} ecma_pseudo_array_type_t;
690691

jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ enum
6868
ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH,
6969
ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE,
7070
ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT,
71+
ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL,
7172
#endif /* ENABLED (JERRY_ESNEXT) */
7273
};
7374

@@ -514,6 +515,147 @@ ecma_builtin_is_regexp_exec (ecma_extended_object_t *obj_p)
514515
} /* ecma_builtin_is_regexp_exec */
515516
#endif /* ENABLED (JERRY_ESNEXT) */
516517

518+
#if ENABLED (JERRY_ESNEXT)
519+
/**
520+
* The RegExp.prototype object's 'matchAll' routine
521+
*
522+
* See also:
523+
* ECMA-262 v11, 21.2.5.8
524+
*
525+
* @return ecma_value_t
526+
*/
527+
static ecma_value_t
528+
ecma_builtin_regexp_prototype_match_all (ecma_object_t *regexp_obj_p, /**< this argument */
529+
ecma_value_t string_arg) /**< source string */
530+
{
531+
/* 3. */
532+
ecma_string_t *str_p = ecma_op_to_string (string_arg);
533+
534+
if (JERRY_UNLIKELY (str_p == NULL))
535+
{
536+
return ECMA_VALUE_ERROR;
537+
}
538+
539+
/* 4. */
540+
ecma_value_t constructor = ecma_op_species_constructor (regexp_obj_p, ECMA_BUILTIN_ID_REGEXP);
541+
542+
if (ECMA_IS_VALUE_ERROR (constructor))
543+
{
544+
ecma_deref_ecma_string (str_p);
545+
return constructor;
546+
}
547+
548+
/* 5. */
549+
ecma_value_t get_flag = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_FLAGS);
550+
551+
if (ECMA_IS_VALUE_ERROR (get_flag))
552+
{
553+
ecma_deref_ecma_string (str_p);
554+
ecma_free_value (constructor);
555+
return get_flag;
556+
}
557+
558+
ecma_string_t *flags = ecma_op_to_string (get_flag);
559+
560+
ecma_free_value (get_flag);
561+
562+
if (JERRY_UNLIKELY (flags == NULL))
563+
{
564+
ecma_deref_ecma_string (str_p);
565+
ecma_free_value (constructor);
566+
return ECMA_VALUE_ERROR;
567+
}
568+
569+
/* 6. */
570+
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
571+
ecma_value_t flags_value = ecma_make_string_value (flags);
572+
ecma_value_t match_args[] = { ecma_make_object_value (regexp_obj_p), flags_value};
573+
ecma_value_t matcher = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, match_args, 2);
574+
575+
ecma_deref_object (constructor_obj_p);
576+
577+
if (ECMA_IS_VALUE_ERROR (matcher))
578+
{
579+
ecma_deref_ecma_string (str_p);
580+
ecma_deref_ecma_string (flags);
581+
return matcher;
582+
}
583+
584+
/* 7. */
585+
ecma_value_t get_last_index = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL);
586+
587+
if (ECMA_IS_VALUE_ERROR (get_last_index))
588+
{
589+
ecma_deref_ecma_string (str_p);
590+
ecma_deref_ecma_string (flags);
591+
ecma_free_value (matcher);
592+
return get_last_index;
593+
}
594+
595+
ecma_length_t last_index;
596+
ecma_value_t to_len = ecma_op_to_length (get_last_index, &last_index);
597+
598+
ecma_free_value (get_last_index);
599+
600+
if (ECMA_IS_VALUE_ERROR (to_len))
601+
{
602+
ecma_deref_ecma_string (str_p);
603+
ecma_deref_ecma_string (flags);
604+
ecma_free_value (matcher);
605+
return to_len;
606+
}
607+
608+
/* 8. */
609+
ecma_object_t *matcher_obj_p = ecma_get_object_from_value (matcher);
610+
ecma_value_t last_index_value = ecma_make_length_value (last_index);
611+
ecma_value_t set = ecma_op_object_put (matcher_obj_p,
612+
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
613+
last_index_value,
614+
true);
615+
616+
ecma_free_value (last_index_value);
617+
618+
if (ECMA_IS_VALUE_ERROR (set))
619+
{
620+
ecma_deref_ecma_string (str_p);
621+
ecma_deref_ecma_string (flags);
622+
ecma_deref_object (matcher_obj_p);
623+
}
624+
625+
uint16_t parsed_flag;
626+
ecma_value_t flag_parse = ecma_regexp_parse_flags (flags, &parsed_flag);
627+
628+
ecma_deref_ecma_string (flags);
629+
630+
if (ECMA_IS_VALUE_ERROR (flag_parse))
631+
{
632+
ecma_deref_ecma_string (str_p);
633+
ecma_deref_object (matcher_obj_p);
634+
return flag_parse;
635+
}
636+
637+
/* 13. */
638+
ecma_object_t *result_obj;
639+
ecma_object_t *proto_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_STRING_ITERATOR_PROTOTYPE);
640+
result_obj = ecma_create_object (proto_p,
641+
sizeof (ecma_regexp_string_iterator_t),
642+
ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
643+
644+
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) result_obj;
645+
ext_obj_p->u.pseudo_array.type = (uint8_t) ECMA_PSEUDO_REGEXP_STRING_ITERATOR;
646+
ext_obj_p->u.pseudo_array.extra_info = (uint8_t) (parsed_flag & (RE_FLAG_GLOBAL | RE_FLAG_UNICODE));
647+
648+
ecma_regexp_string_iterator_t *regexp_string_iterator_obj = (ecma_regexp_string_iterator_t *) result_obj;
649+
650+
regexp_string_iterator_obj->iterating_regexp = matcher;
651+
regexp_string_iterator_obj->iterated_string = ecma_make_string_value (str_p);
652+
653+
ecma_deref_object (matcher_obj_p);
654+
655+
return ecma_make_object_value (result_obj);
656+
} /* ecma_builtin_regexp_prototype_match_all */
657+
#endif /* ENABLED (JERRY_ESNEXT) */
658+
517659
/**
518660
* Dispatcher of the Regexp built-in's routines
519661
*
@@ -584,6 +726,10 @@ ecma_builtin_regexp_prototype_dispatch_routine (uint8_t builtin_routine_id, /**<
584726
{
585727
return ecma_regexp_match_helper (this_arg, arguments_list_p[0]);
586728
}
729+
case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL:
730+
{
731+
return ecma_builtin_regexp_prototype_match_all (obj_p, arguments_list_p[0]);
732+
}
587733
case ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE:
588734
{
589735
return ecma_regexp_replace_helper (this_arg, arguments_list_p[0], arguments_list_p[1]);

jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.inc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ ROUTINE (LIT_GLOBAL_SYMBOL_REPLACE, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_REPLACE
6363
ROUTINE (LIT_GLOBAL_SYMBOL_SEARCH, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SEARCH, 1, 1)
6464
ROUTINE (LIT_GLOBAL_SYMBOL_SPLIT, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_SPLIT, 2, 2)
6565
ROUTINE (LIT_GLOBAL_SYMBOL_MATCH, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH, 1, 1)
66+
ROUTINE (LIT_GLOBAL_SYMBOL_MATCH_ALL, ECMA_REGEXP_PROTOTYPE_ROUTINE_SYMBOL_MATCH_ALL, 1, 1)
6667
#else /* !ENABLED (JERRY_ESNEXT) */
6768
/* ECMA-262 v5, 15.10.7.1 */
6869
STRING_VALUE (LIT_MAGIC_STRING_SOURCE,

0 commit comments

Comments
 (0)