Skip to content

Commit d7e48c0

Browse files
committed
Implement Iterator interface and Array iterators
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
1 parent 924f4bb commit d7e48c0

21 files changed

+1017
-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_BUILTIN
373+
case ECMA_PSEUDO_ARRAY_ITERATOR:
374+
{
375+
break;
376+
}
377+
#endif /* !CONFIG_DISABLE_ES2015_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: 17 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,16 @@ typedef enum
686687
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND /**< maximum value */
687688
} ecma_lexical_environment_type_t;
688689

690+
/**
691+
* Types of array iterators.
692+
*/
693+
typedef enum
694+
{
695+
ECMA_ARRAY_ITERATOR_KEYS, /**< List only key indices */
696+
ECMA_ARRAY_ITERATOR_VALUES, /**< List only key values */
697+
ECMA_ARRAY_ITERATOR_KEYS_VALUES, /**< List key indices and values */
698+
} ecma_array_iterator_type_t;
699+
689700
/**
690701
* Offset for JERRY_CONTEXT (status_flags) top 8 bits.
691702
*/
@@ -846,18 +857,21 @@ typedef struct
846857
*/
847858
struct
848859
{
849-
uint8_t type; /**< pseudo array type, e.g. Arguments, TypedArray*/
860+
uint8_t type; /**< pseudo array type, e.g. Arguments, TypedArray, ArrayIterator */
850861
uint8_t extra_info; /**< extra information about the object.
851-
* e.g. element_width_shift for typed arrays */
862+
* e.g. element_width_shift for typed arrays,
863+
* [[IterationKind]] property for %Iterator% */
852864
union
853865
{
854866
uint16_t length; /**< for arguments: length of names */
855867
uint16_t class_id; /**< for typedarray: the specific class name */
868+
uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */
856869
} u1;
857870
union
858871
{
859872
ecma_value_t lex_env_cp; /**< for arguments: lexical environment */
860873
ecma_value_t arraybuffer; /**< for typedarray: internal arraybuffer */
874+
ecma_value_t iterated_value_cp; /**< for %Iterator%: [[IteratedObject]] property */
861875
} u2;
862876
} pseudo_array;
863877

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
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+
* @return ecma value
51+
* Returned value must be freed with ecma_free_value.
52+
*/
53+
static ecma_value_t
54+
ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< this argument */
55+
{
56+
/* 1 - 2. */
57+
if (!ecma_is_value_object (this_val))
58+
{
59+
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an object."));
60+
}
61+
62+
ecma_object_t *obj_p = ecma_get_object_from_value (this_val);
63+
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
64+
65+
/* 3. */
66+
if (ext_obj_p->u.pseudo_array.type != ECMA_PSEUDO_ARRAY_ITERATOR)
67+
{
68+
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an iterator."));
69+
}
70+
71+
ecma_object_t *array_object_p = ECMA_GET_POINTER (ecma_object_t,
72+
ext_obj_p->u.pseudo_array.u2.iterated_value_cp);
73+
74+
75+
/* 4 - 5 */
76+
if (array_object_p == NULL)
77+
{
78+
return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
79+
}
80+
81+
uint32_t length;
82+
83+
/* 8 - 9. */
84+
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
85+
if (ecma_is_typedarray (ecma_make_object_value (array_object_p)))
86+
{
87+
length = ecma_typedarray_get_length (array_object_p);
88+
}
89+
else
90+
{
91+
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
92+
JERRY_ASSERT (ecma_get_object_type (array_object_p) == ECMA_OBJECT_TYPE_ARRAY);
93+
94+
ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_object_p;
95+
96+
length = ext_array_obj_p->u.array.length;
97+
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
98+
}
99+
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
100+
101+
uint32_t index = ext_obj_p->u.pseudo_array.u1.iterator_index;
102+
103+
if (JERRY_UNLIKELY (index == ECMA_ITERATOR_INDEX_LIMIT))
104+
{
105+
/* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]]
106+
property is stored as an internal property */
107+
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX);
108+
ecma_value_t index_value = ecma_op_object_get (obj_p, prop_name_p);
109+
110+
if (!ecma_is_value_undefined (index_value))
111+
{
112+
index = (uint32_t) (ecma_get_number_from_value (index_value) + 1);
113+
}
114+
115+
ecma_value_t put_result = ecma_op_object_put (obj_p,
116+
prop_name_p,
117+
ecma_make_uint32_value (index),
118+
true);
119+
120+
JERRY_ASSERT (ecma_is_value_true (put_result));
121+
122+
ecma_free_value (index_value);
123+
}
124+
else
125+
{
126+
/* 11. */
127+
ext_obj_p->u.pseudo_array.u1.iterator_index++;
128+
}
129+
130+
if (index >= length)
131+
{
132+
ECMA_SET_POINTER (ext_obj_p->u.pseudo_array.u2.iterated_value_cp, NULL);
133+
return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
134+
}
135+
136+
/* 7. */
137+
uint8_t iterator_type = ext_obj_p->u.pseudo_array.extra_info;
138+
139+
if (iterator_type == ECMA_ARRAY_ITERATOR_KEYS)
140+
{
141+
/* 12. */
142+
return ecma_create_iter_result_object (ecma_make_uint32_value (index), ECMA_VALUE_FALSE);
143+
}
144+
145+
ecma_value_t result;
146+
147+
/* 13. */
148+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
149+
150+
/* 14. */
151+
ecma_value_t get_value = ecma_op_object_get (array_object_p, index_string_p);
152+
ecma_deref_ecma_string (index_string_p);
153+
154+
/* 15. */
155+
if (ECMA_IS_VALUE_ERROR (get_value))
156+
{
157+
return get_value;
158+
}
159+
160+
/* 16. */
161+
if (iterator_type == ECMA_ARRAY_ITERATOR_VALUES)
162+
{
163+
result = ecma_create_iter_result_object (get_value, ECMA_VALUE_FALSE);
164+
}
165+
else
166+
{
167+
/* 17.a */
168+
JERRY_ASSERT (iterator_type == ECMA_ARRAY_ITERATOR_KEYS_VALUES);
169+
170+
/* 17.b */
171+
ecma_value_t entry_array_value;
172+
entry_array_value = ecma_create_array_from_iter_element (get_value,
173+
ecma_make_uint32_value (index));
174+
175+
result = ecma_create_iter_result_object (entry_array_value, ECMA_VALUE_FALSE);
176+
ecma_free_value (entry_array_value);
177+
}
178+
179+
ecma_free_value (get_value);
180+
181+
return result;
182+
} /* ecma_builtin_array_iterator_prototype_object_next */
183+
184+
/**
185+
* @}
186+
* @}
187+
* @}
188+
*/
189+
190+
#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)