Skip to content

Commit 4f5ffb4

Browse files
authored
Implement Iterator interface and Array iterators (#2640)
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
1 parent 2dd854d commit 4f5ffb4

21 files changed

+1045
-6
lines changed

jerry-core/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
# define CONFIG_DISABLE_ES2015_CLASS
4242
# define CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
4343
# define CONFIG_DISABLE_ES2015_FUNCTION_REST_PARAMETER
44+
# define CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN
4445
# define CONFIG_DISABLE_ES2015_MAP_BUILTIN
4546
# define CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
4647
# define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
369369
break;
370370
}
371371
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
372+
#ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN
373+
case ECMA_PSEUDO_ARRAY_ITERATOR:
374+
{
375+
break;
376+
}
377+
#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */
372378
default:
373379
{
374380
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
@@ -762,6 +768,13 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
762768
return;
763769
}
764770
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
771+
#ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN
772+
case ECMA_PSEUDO_ARRAY_ITERATOR:
773+
{
774+
ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t));
775+
return;
776+
}
777+
#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */
765778
default:
766779
{
767780
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -664,8 +664,9 @@ typedef enum
664664
ECMA_PSEUDO_ARRAY_ARGUMENTS = 0, /**< Arguments object (10.6) */
665665
ECMA_PSEUDO_ARRAY_TYPEDARRAY = 1, /**< TypedArray which does NOT need extra space to store length and offset */
666666
ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO = 2, /**< TypedArray which NEEDS extra space to store length and offset */
667+
ECMA_PSEUDO_ARRAY_ITERATOR = 3, /**< Array iterator object (ECMAScript v6, 22.1.5.1) */
667668

668-
ECMA_PSEUDO_ARRAY__MAX = ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO /**< maximum value */
669+
ECMA_PSEUDO_ARRAY__MAX = ECMA_PSEUDO_ARRAY_ITERATOR /**< maximum value */
669670
} ecma_pseudo_array_type_t;
670671

671672
/**
@@ -686,6 +687,18 @@ typedef enum
686687
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND /**< maximum value */
687688
} ecma_lexical_environment_type_t;
688689

690+
#ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN
691+
/**
692+
* Types of array iterators.
693+
*/
694+
typedef enum
695+
{
696+
ECMA_ARRAY_ITERATOR_KEYS, /**< List only key indices */
697+
ECMA_ARRAY_ITERATOR_VALUES, /**< List only key values */
698+
ECMA_ARRAY_ITERATOR_KEYS_VALUES, /**< List key indices and values */
699+
} ecma_array_iterator_type_t;
700+
#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */
701+
689702
/**
690703
* Offset for JERRY_CONTEXT (status_flags) top 8 bits.
691704
*/
@@ -846,18 +859,21 @@ typedef struct
846859
*/
847860
struct
848861
{
849-
uint8_t type; /**< pseudo array type, e.g. Arguments, TypedArray*/
862+
uint8_t type; /**< pseudo array type, e.g. Arguments, TypedArray, ArrayIterator */
850863
uint8_t extra_info; /**< extra information about the object.
851-
* e.g. element_width_shift for typed arrays */
864+
* e.g. element_width_shift for typed arrays,
865+
* [[IterationKind]] property for %Iterator% */
852866
union
853867
{
854868
uint16_t length; /**< for arguments: length of names */
855869
uint16_t class_id; /**< for typedarray: the specific class name */
870+
uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */
856871
} u1;
857872
union
858873
{
859874
ecma_value_t lex_env_cp; /**< for arguments: lexical environment */
860875
ecma_value_t arraybuffer; /**< for typedarray: internal arraybuffer */
876+
ecma_value_t iterated_value_cp; /**< for %Iterator%: [[IteratedObject]] property */
861877
} u2;
862878
} pseudo_array;
863879

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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 */
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
/*
17+
* %ArrayIteratorPrototype% built-in description
18+
*/
19+
20+
#include "ecma-builtin-helpers-macro-defines.inc.h"
21+
22+
#ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN
23+
24+
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
25+
LIT_MAGIC_STRING_ARRAY_ITERATOR_UL,
26+
ECMA_PROPERTY_FLAG_CONFIGURABLE)
27+
28+
/* Routine properties:
29+
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
30+
ROUTINE (LIT_MAGIC_STRING_NEXT, ecma_builtin_array_iterator_prototype_object_next, 0, 0)
31+
32+
#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */
33+
34+
#include "ecma-builtin-helpers-macro-undefs.inc.h"

0 commit comments

Comments
 (0)