From 076f515d618d939087eaed4b1ef318c7115551ef Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Thu, 30 May 2019 12:34:19 -0400 Subject: [PATCH] Implement the string iterators (#2873) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- jerry-core/ecma/base/ecma-gc.c | 23 ++- jerry-core/ecma/base/ecma-globals.h | 5 +- jerry-core/ecma/base/ecma-helpers-string.c | 18 +++ jerry-core/ecma/base/ecma-helpers.h | 3 + .../ecma-builtin-array-iterator-prototype.c | 13 +- .../ecma-builtin-string-iterator-prototype.c | 152 ++++++++++++++++++ ...ma-builtin-string-iterator-prototype.inc.h | 34 ++++ .../ecma-builtin-string-prototype.c | 35 ++++ .../ecma-builtin-string-prototype.inc.h | 4 + .../ecma/builtin-objects/ecma-builtins.inc.h | 7 + .../ecma/operations/ecma-iterator-object.c | 4 +- jerry-core/ecma/operations/ecma-objects.c | 6 + jerry-core/lit/lit-magic-strings.inc.h | 7 +- jerry-core/lit/lit-magic-strings.ini | 1 + tests/jerry/es2015/string-iterator.js | 77 +++++++++ 15 files changed, 372 insertions(+), 17 deletions(-) create mode 100644 jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c create mode 100644 jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h create mode 100644 tests/jerry/es2015/string-iterator.js diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 86617fd50..099ebaadd 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -329,15 +329,17 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ #if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) case ECMA_PSEUDO_ARRAY_ITERATOR: { - ecma_object_t *iterated_obj_p = ECMA_GET_POINTER (ecma_object_t, - ext_object_p->u.pseudo_array.u2.iterated_value_cp); - - if (iterated_obj_p != NULL) + ecma_value_t iterated_value = ext_object_p->u.pseudo_array.u2.iterated_value; + if (!ecma_is_value_empty (iterated_value)) { - ecma_gc_set_object_visited (iterated_obj_p); + ecma_gc_set_object_visited (ecma_get_object_from_value (iterated_value)); } break; } + case ECMA_PSEUDO_STRING_ITERATOR: + { + break; + } #endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ default: { @@ -755,6 +757,17 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t)); return; } + case ECMA_PSEUDO_STRING_ITERATOR: + { + ecma_value_t iterated_value = ext_object_p->u.pseudo_array.u2.iterated_value; + + if (!ecma_is_value_empty (iterated_value)) + { + ecma_deref_ecma_string (ecma_get_string_from_value (iterated_value)); + } + ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t)); + return; + } #endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ default: { diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 1d1a9201a..5bad24f71 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -628,8 +628,9 @@ typedef enum ECMA_PSEUDO_ARRAY_TYPEDARRAY = 1, /**< TypedArray which does NOT need extra space to store length and offset */ ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO = 2, /**< TypedArray which NEEDS extra space to store length and offset */ ECMA_PSEUDO_ARRAY_ITERATOR = 3, /**< Array iterator object (ECMAScript v6, 22.1.5.1) */ + ECMA_PSEUDO_STRING_ITERATOR = 4, /**< Array iterator object (ECMAScript v6, 22.1.5.1) */ - ECMA_PSEUDO_ARRAY__MAX = ECMA_PSEUDO_ARRAY_ITERATOR /**< maximum value */ + ECMA_PSEUDO_ARRAY__MAX = ECMA_PSEUDO_STRING_ITERATOR /**< maximum value */ } ecma_pseudo_array_type_t; /** @@ -836,7 +837,7 @@ typedef struct { ecma_value_t lex_env_cp; /**< for arguments: lexical environment */ ecma_value_t arraybuffer; /**< for typedarray: internal arraybuffer */ - ecma_value_t iterated_value_cp; /**< for %Iterator%: [[IteratedObject]] property */ + ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */ } u2; } pseudo_array; diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index fa53d9796..8d60cc3fb 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -476,6 +476,24 @@ ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit) /**< code unit */ return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); } /* ecma_new_ecma_string_from_code_unit */ +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) +/** + * Allocate new ecma-string and fill it with cesu-8 character which represents specified code units + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, /**< code unit */ + ecma_char_t second_code_unit) /**< code unit */ +{ + lit_utf8_byte_t lit_utf8_bytes[2 * LIT_UTF8_MAX_BYTES_IN_CODE_UNIT]; + lit_utf8_size_t bytes_size = lit_code_unit_to_utf8 (first_code_unit, lit_utf8_bytes); + bytes_size += lit_code_unit_to_utf8 (second_code_unit, lit_utf8_bytes + bytes_size); + + return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); +} /* ecma_new_ecma_string_from_code_units */ +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ + /** * Allocate new ecma-string and fill it with ecma-number * diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 3d2b04c1f..74458a86f 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -230,6 +230,9 @@ ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit); +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) +ecma_string_t *ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, ecma_char_t second_code_unit); +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ ecma_string_t *ecma_new_ecma_string_from_uint32 (uint32_t uint32_number); ecma_string_t *ecma_get_ecma_string_from_uint32 (uint32_t uint32_number); ecma_string_t *ecma_new_ecma_string_from_number (ecma_number_t num); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c index 0eb3bb6b2..7c7db5959 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c @@ -66,21 +66,22 @@ ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< t ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; /* 3. */ - if (ext_obj_p->u.pseudo_array.type != ECMA_PSEUDO_ARRAY_ITERATOR) + if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_PSEUDO_ARRAY + || ext_obj_p->u.pseudo_array.type != ECMA_PSEUDO_ARRAY_ITERATOR) { return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an iterator.")); } - ecma_object_t *array_object_p = ECMA_GET_POINTER (ecma_object_t, - ext_obj_p->u.pseudo_array.u2.iterated_value_cp); - + ecma_value_t iterated_value = ext_obj_p->u.pseudo_array.u2.iterated_value; /* 4 - 5 */ - if (array_object_p == NULL) + if (ecma_is_value_empty (iterated_value)) { return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); } + ecma_object_t *array_object_p = ecma_get_object_from_value (iterated_value); + uint32_t length; /* 8 - 9. */ @@ -147,7 +148,7 @@ ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< t if (index >= length) { - ECMA_SET_POINTER (ext_obj_p->u.pseudo_array.u2.iterated_value_cp, NULL); + ext_obj_p->u.pseudo_array.u2.iterated_value = ECMA_VALUE_EMPTY; return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c new file mode 100644 index 000000000..d2bab9cef --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c @@ -0,0 +1,152 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-iterator-object.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) + +#if !ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) +#error "Iterator builtin requires ES2015 symbol builtin" +#endif /* !ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-string-iterator-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID string_iterator_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup %stringiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in + * @{ + */ + +/** + * The %StringIteratorPrototype% object's 'next' routine + * + * See also: + * ECMA-262 v6, 22.1.5.2.1 + * + * Note: + * Returned value must be freed with ecma_free_value. + * + * @return iterator result object, if success + * error - otherwise + */ +static ecma_value_t +ecma_builtin_string_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ +{ + /* 1 - 2. */ + if (!ecma_is_value_object (this_val)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an object.")); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + + /* 3. */ + if (ecma_get_object_type (obj_p) != ECMA_OBJECT_TYPE_PSEUDO_ARRAY + || ext_obj_p->u.pseudo_array.type != ECMA_PSEUDO_STRING_ITERATOR) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an iterator.")); + } + + ecma_value_t iterated_value = ext_obj_p->u.pseudo_array.u2.iterated_value; + + /* 4 - 5 */ + if (ecma_is_value_empty (iterated_value)) + { + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + JERRY_ASSERT (ecma_is_value_string (iterated_value)); + + + ecma_string_t *string_p = ecma_get_string_from_value (iterated_value); + + /* 6. */ + ecma_length_t position = ext_obj_p->u.pseudo_array.u1.iterator_index; + + if (JERRY_UNLIKELY (position == ECMA_ITERATOR_INDEX_LIMIT)) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("String iteration cannot be continued.")); + } + + /* 7. */ + ecma_length_t len = ecma_string_get_length (string_p); + + /* 8. */ + if (position >= len) + { + ecma_deref_ecma_string (string_p); + ext_obj_p->u.pseudo_array.u2.iterated_value = ECMA_VALUE_EMPTY; + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); + } + + /* 9. */ + ecma_char_t first = ecma_string_get_char_at_pos (string_p, position); + + ecma_string_t *result_str_p; + ecma_length_t result_size = 1; + + /* 10. */ + if (first < LIT_UTF16_HIGH_SURROGATE_MIN || first > LIT_UTF16_HIGH_SURROGATE_MAX || (position + 1 == len)) + { + result_str_p = ecma_new_ecma_string_from_code_unit (first); + } + /* 11. */ + else + { + /* 11.a */ + ecma_char_t second = ecma_string_get_char_at_pos (string_p, (ecma_length_t) (position + 1)); + + /* 11.b */ + if (second < LIT_UTF16_LOW_SURROGATE_MIN || second > LIT_UTF16_LOW_SURROGATE_MAX) + { + result_str_p = ecma_new_ecma_string_from_code_unit (first); + } + /* 11.c */ + else + { + result_str_p = ecma_new_ecma_string_from_code_units (first, second); + result_size = 2; + } + } + + /* 13. */ + ext_obj_p->u.pseudo_array.u1.iterator_index = (uint16_t) (position + result_size); + + /* 14. */ + ecma_value_t result = ecma_create_iter_result_object (ecma_make_string_value (result_str_p), ECMA_VALUE_FALSE); + ecma_deref_ecma_string (result_str_p); + + return result; +} /* ecma_builtin_string_iterator_prototype_object_next */ + +/** + * @} + * @} + * @} + */ + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h new file mode 100644 index 000000000..9a04570e7 --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.inc.h @@ -0,0 +1,34 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * %StringIteratorPrototype% built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) + +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_STRING_ITERATOR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_NEXT, ecma_builtin_string_iterator_prototype_object_next, 0, 0) + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index ee2640b2c..68f538b67 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -23,6 +23,7 @@ #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" +#include "ecma-iterator-object.h" #include "ecma-objects.h" #include "ecma-string-object.h" #include "ecma-try-catch-macro.h" @@ -2164,6 +2165,40 @@ ecma_builtin_string_prototype_object_substr (ecma_value_t this_arg, /**< this ar #endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) +/** + * The String.prototype object's @@iterator routine + * + * See also: + * ECMA-262 v6, 21.1.3.27 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_string_prototype_object_iterator (ecma_value_t this_arg) /**< this argument */ +{ + ecma_value_t coercible = ecma_op_check_object_coercible (this_arg); + + if (ECMA_IS_VALUE_ERROR (coercible)) + { + return coercible; + } + + ecma_value_t to_string = ecma_op_to_string (this_arg); + + if (ECMA_IS_VALUE_ERROR (to_string)) + { + return to_string; + } + + return ecma_op_create_iterator_object (to_string, + ecma_builtin_get (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE), + ECMA_PSEUDO_STRING_ITERATOR, + 0); +} /* ecma_builtin_string_prototype_object_iterator */ +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ + /** * @} * @} diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h index 378b66894..08eb610c4 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.inc.h @@ -67,6 +67,10 @@ ROUTINE (LIT_MAGIC_STRING_TRIM, ecma_builtin_string_prototype_object_trim, 0, 0) ROUTINE (LIT_MAGIC_STRING_SUBSTR, ecma_builtin_string_prototype_object_substr, 2, 2) #endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */ +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) +ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ecma_builtin_string_prototype_object_iterator, 0, 0) +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ + #endif /* ENABLED (JERRY_BUILTIN_STRING) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h index 5882c1182..4ce9b56eb 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -490,6 +490,13 @@ BUILTIN (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE, ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, true, array_iterator_prototype) + +/* The %StringIteratorPrototype% object (ECMA-262 v6, 22.1.5.2) */ +BUILTIN (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE, + ECMA_OBJECT_TYPE_GENERAL, + ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE, + true, + string_iterator_prototype) #endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) diff --git a/jerry-core/ecma/operations/ecma-iterator-object.c b/jerry-core/ecma/operations/ecma-iterator-object.c index 88f48b83b..61d60624f 100644 --- a/jerry-core/ecma/operations/ecma-iterator-object.c +++ b/jerry-core/ecma/operations/ecma-iterator-object.c @@ -138,10 +138,8 @@ ecma_op_create_iterator_object (ecma_value_t iterated_value, /**< value from cre uint8_t extra_info) /**< extra information */ { /* 1. */ - JERRY_ASSERT (ecma_is_value_object (iterated_value)); JERRY_ASSERT (iterator_type >= ECMA_PSEUDO_ARRAY_ITERATOR && iterator_type <= ECMA_PSEUDO_ARRAY__MAX); - ecma_object_t *iterated_obj_p = ecma_get_object_from_value (iterated_value); /* 2. */ ecma_object_t *object_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), @@ -151,7 +149,7 @@ ecma_op_create_iterator_object (ecma_value_t iterated_value, /**< value from cre ext_obj_p->u.pseudo_array.type = iterator_type; /* 3. */ - ECMA_SET_NON_NULL_POINTER (ext_obj_p->u.pseudo_array.u2.iterated_value_cp, iterated_obj_p); + ext_obj_p->u.pseudo_array.u2.iterated_value = iterated_value; /* 4. */ ext_obj_p->u.pseudo_array.u1.iterator_index = 0; /* 5. */ diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 59010894f..cb3e32475 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1943,6 +1943,12 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */ { return LIT_MAGIC_STRING_ARRAY_ITERATOR_UL; } +#endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) + case ECMA_PSEUDO_STRING_ITERATOR: + { + return LIT_MAGIC_STRING_STRING_ITERATOR_UL; + } #endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ default: { diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 2c56da9c7..75eb3acbd 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -651,6 +651,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, "setPrototypeOf") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, "setUTCFullYear") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, "toLocaleString") +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_ITERATOR_UL, "String Iterator") +#endif #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MILLISECONDS_UL, "getMilliseconds") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MILLISECONDS_UL, "setMilliseconds") @@ -778,7 +781,9 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (14, LIT_MAGIC_STRING_REFERENCE_ERROR_UL #else LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (14, LIT_MAGIC_STRING_DEFINE_PROPERTY_UL) #endif -#if ENABLED (JERRY_BUILTIN_DATE) +#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (15, LIT_MAGIC_STRING_STRING_ITERATOR_UL) +#elif ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (15, LIT_MAGIC_STRING_GET_MILLISECONDS_UL) #else LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (15, LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL) diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index 596296646..344dad8a6 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -289,6 +289,7 @@ LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL = "hasOwnProperty" LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL = "setPrototypeOf" LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL = "setUTCFullYear" LIT_MAGIC_STRING_TO_LOCALE_STRING_UL = "toLocaleString" +LIT_MAGIC_STRING_STRING_ITERATOR_UL = "String Iterator" LIT_MAGIC_STRING_GET_MILLISECONDS_UL = "getMilliseconds" LIT_MAGIC_STRING_SET_MILLISECONDS_UL = "setMilliseconds" LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL = "defineProperties" diff --git a/tests/jerry/es2015/string-iterator.js b/tests/jerry/es2015/string-iterator.js new file mode 100644 index 000000000..df037a709 --- /dev/null +++ b/tests/jerry/es2015/string-iterator.js @@ -0,0 +1,77 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +try { + String.prototype[Symbol.iterator].call(undefined); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +try { + String.prototype[Symbol.iterator].call(Symbol('foo')); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +var str = 'foobar'; +var iterator = str[Symbol.iterator](); + +try { + iterator.next.call(5); + assert (false); +} catch (e) { + assert(e instanceof TypeError); +} + +try { + iterator.next.call({}); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +var str = 'Example string.'; +var expected = ['E', 'x', 'a', 'm', 'p', 'l', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', '.']; + +var iterator = str[Symbol.iterator](); +var next = iterator.next(); +var idx = 0; + +while (!next.done) { + assert(next.value === expected[idx++]); + assert(next.done === false); + next = iterator.next(); +} + +assert(next.value === undefined); + +var str = '^o𓙦һR񼴆]ŭ媖?᯾豼עW򏋁'; +var expected = ['^', 'o', '𓙦', 'һ', 'R', '񼴆', ']', 'ŭ', '媖', '?', '᯾', '豼', 'ע', 'W', '򏋁']; + +iterator = str[Symbol.iterator](); +next = iterator.next(); +idx = 0; + +while (!next.done) { + assert(next.value === expected[idx++]); + assert(next.done === false); + next = iterator.next(); +} + +assert(next.value === undefined); + +assert(iterator.toString() === '[object String Iterator]'); +assert(iterator[Symbol.toStringTag] === 'String Iterator');