|
| 1 | +/* Copyright JS Foundation and other contributors, http://js.foundation |
| 2 | + * |
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | + * you may not use this file except in compliance with the License. |
| 5 | + * You may obtain a copy of the License at |
| 6 | + * |
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | + * |
| 9 | + * Unless required by applicable law or agreed to in writing, software |
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS |
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | + * See the License for the specific language governing permissions and |
| 13 | + * limitations under the License. |
| 14 | + */ |
| 15 | + |
| 16 | +#include "ecma-builtin-helpers.h" |
| 17 | +#include "ecma-builtins.h" |
| 18 | +#include "ecma-iterator-object.h" |
| 19 | +#include "ecma-typedarray-object.h" |
| 20 | + |
| 21 | +#ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN |
| 22 | + |
| 23 | +#ifdef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN |
| 24 | +#error "Iterator builtin requires ES2015 symbol builtin" |
| 25 | +#endif /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ |
| 26 | + |
| 27 | +#define ECMA_BUILTINS_INTERNAL |
| 28 | +#include "ecma-builtins-internal.h" |
| 29 | + |
| 30 | +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-iterator-prototype.inc.h" |
| 31 | +#define BUILTIN_UNDERSCORED_ID array_iterator_prototype |
| 32 | +#include "ecma-builtin-internal-routines-template.inc.h" |
| 33 | + |
| 34 | +/** \addtogroup ecma ECMA |
| 35 | + * @{ |
| 36 | + * |
| 37 | + * \addtogroup ecmabuiltins |
| 38 | + * @{ |
| 39 | + * |
| 40 | + * \addtogroup %arrayiteratorprototype% ECMA %ArrayIteratorPrototype% object built-in |
| 41 | + * @{ |
| 42 | + */ |
| 43 | + |
| 44 | +/** |
| 45 | + * The %ArrayIteratorPrototype% object's 'next' routine |
| 46 | + * |
| 47 | + * See also: |
| 48 | + * ECMA-262 v6, 22.1.5.2.1 |
| 49 | + * |
| 50 | + * Note: |
| 51 | + * Returned value must be freed with ecma_free_value. |
| 52 | + * |
| 53 | + * @return iterator result object, if success |
| 54 | + * error - otherwise |
| 55 | + */ |
| 56 | +static ecma_value_t |
| 57 | +ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */ |
| 58 | +{ |
| 59 | + /* 1 - 2. */ |
| 60 | + if (!ecma_is_value_object (this_val)) |
| 61 | + { |
| 62 | + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an object.")); |
| 63 | + } |
| 64 | + |
| 65 | + ecma_object_t *obj_p = ecma_get_object_from_value (this_val); |
| 66 | + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; |
| 67 | + |
| 68 | + /* 3. */ |
| 69 | + if (ext_obj_p->u.pseudo_array.type != ECMA_PSEUDO_ARRAY_ITERATOR) |
| 70 | + { |
| 71 | + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an iterator.")); |
| 72 | + } |
| 73 | + |
| 74 | + ecma_object_t *array_object_p = ECMA_GET_POINTER (ecma_object_t, |
| 75 | + ext_obj_p->u.pseudo_array.u2.iterated_value_cp); |
| 76 | + |
| 77 | + |
| 78 | + /* 4 - 5 */ |
| 79 | + if (array_object_p == NULL) |
| 80 | + { |
| 81 | + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); |
| 82 | + } |
| 83 | + |
| 84 | + uint32_t length; |
| 85 | + |
| 86 | + /* 8 - 9. */ |
| 87 | +#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN |
| 88 | + if (ecma_is_typedarray (ecma_make_object_value (array_object_p))) |
| 89 | + { |
| 90 | + length = ecma_typedarray_get_length (array_object_p); |
| 91 | + } |
| 92 | + else |
| 93 | + { |
| 94 | +#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ |
| 95 | + JERRY_ASSERT (ecma_get_object_type (array_object_p) == ECMA_OBJECT_TYPE_ARRAY); |
| 96 | + |
| 97 | + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_object_p; |
| 98 | + |
| 99 | + length = ext_array_obj_p->u.array.length; |
| 100 | +#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN |
| 101 | + } |
| 102 | +#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ |
| 103 | + |
| 104 | + uint32_t index = ext_obj_p->u.pseudo_array.u1.iterator_index; |
| 105 | + |
| 106 | + if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT)) |
| 107 | + { |
| 108 | + /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] |
| 109 | + property is stored as an internal property */ |
| 110 | + ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); |
| 111 | + ecma_value_t index_value = ecma_op_object_get (obj_p, prop_name_p); |
| 112 | + |
| 113 | + if (!ecma_is_value_undefined (index_value)) |
| 114 | + { |
| 115 | + index = (uint32_t) (ecma_get_number_from_value (index_value) + 1); |
| 116 | + } |
| 117 | + |
| 118 | + ecma_value_t put_result = ecma_op_object_put (obj_p, |
| 119 | + prop_name_p, |
| 120 | + ecma_make_uint32_value (index), |
| 121 | + true); |
| 122 | + |
| 123 | + JERRY_ASSERT (ecma_is_value_true (put_result)); |
| 124 | + |
| 125 | + ecma_free_value (index_value); |
| 126 | + } |
| 127 | + else |
| 128 | + { |
| 129 | + /* 11. */ |
| 130 | + ext_obj_p->u.pseudo_array.u1.iterator_index++; |
| 131 | + } |
| 132 | + |
| 133 | + if (index >= length) |
| 134 | + { |
| 135 | + ECMA_SET_POINTER (ext_obj_p->u.pseudo_array.u2.iterated_value_cp, NULL); |
| 136 | + return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE); |
| 137 | + } |
| 138 | + |
| 139 | + /* 7. */ |
| 140 | + uint8_t iterator_type = ext_obj_p->u.pseudo_array.extra_info; |
| 141 | + |
| 142 | + if (iterator_type == ECMA_ARRAY_ITERATOR_KEYS) |
| 143 | + { |
| 144 | + /* 12. */ |
| 145 | + return ecma_create_iter_result_object (ecma_make_uint32_value (index), ECMA_VALUE_FALSE); |
| 146 | + } |
| 147 | + |
| 148 | + /* 13. */ |
| 149 | + ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); |
| 150 | + |
| 151 | + /* 14. */ |
| 152 | + ecma_value_t get_value = ecma_op_object_get (array_object_p, index_string_p); |
| 153 | + ecma_deref_ecma_string (index_string_p); |
| 154 | + |
| 155 | + /* 15. */ |
| 156 | + if (ECMA_IS_VALUE_ERROR (get_value)) |
| 157 | + { |
| 158 | + return get_value; |
| 159 | + } |
| 160 | + |
| 161 | + ecma_value_t result; |
| 162 | + |
| 163 | + /* 16. */ |
| 164 | + if (iterator_type == ECMA_ARRAY_ITERATOR_VALUES) |
| 165 | + { |
| 166 | + result = ecma_create_iter_result_object (get_value, ECMA_VALUE_FALSE); |
| 167 | + } |
| 168 | + else |
| 169 | + { |
| 170 | + /* 17.a */ |
| 171 | + JERRY_ASSERT (iterator_type == ECMA_ARRAY_ITERATOR_KEYS_VALUES); |
| 172 | + |
| 173 | + /* 17.b */ |
| 174 | + ecma_value_t entry_array_value; |
| 175 | + entry_array_value = ecma_create_array_from_iter_element (get_value, |
| 176 | + ecma_make_uint32_value (index)); |
| 177 | + |
| 178 | + result = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE); |
| 179 | + ecma_free_value (entry_array_value); |
| 180 | + } |
| 181 | + |
| 182 | + ecma_free_value (get_value); |
| 183 | + |
| 184 | + return result; |
| 185 | +} /* ecma_builtin_array_iterator_prototype_object_next */ |
| 186 | + |
| 187 | +/** |
| 188 | + * @} |
| 189 | + * @} |
| 190 | + * @} |
| 191 | + */ |
| 192 | + |
| 193 | +#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */ |
0 commit comments