Skip to content

Commit b614c0b

Browse files
committed
Implement Array.prototype.join
JerryScript-DCO-1.0-Signed-off-by: Peter Gal [email protected]
1 parent 36b8fa5 commit b614c0b

File tree

6 files changed

+325
-0
lines changed

6 files changed

+325
-0
lines changed

jerry-core/ecma/base/ecma-magic-strings.inc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_MESSAGE, "message")
205205
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_LEFT_SQUARE_CHAR, "[")
206206
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_RIGHT_SQUARE_CHAR, "]")
207207
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_COLON_CHAR, ":")
208+
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_COMMA_CHAR, ",")
208209
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING_SPACE_CHAR, " ")
209210
ECMA_MAGIC_STRING_DEF (ECMA_MAGIC_STRING__EMPTY, "")
210211

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "ecma-alloc.h"
1717
#include "ecma-array-object.h"
18+
#include "ecma-array-prototype.h"
1819
#include "ecma-builtin-helpers.h"
1920
#include "ecma-builtins.h"
2021
#include "ecma-comparison.h"
@@ -169,6 +170,112 @@ ecma_builtin_array_prototype_object_for_each (ecma_value_t this_arg, /**< this a
169170
return ret_value;
170171
} /* ecma_builtin_array_prototype_object_for_each */
171172

173+
/**
174+
* The Array.prototype object's 'join' routine
175+
*
176+
* See also:
177+
* ECMA-262 v5, 15.4.4.5
178+
*
179+
* @return completion value
180+
* Returned value must be freed with ecma_free_completion_value.
181+
*/
182+
static ecma_completion_value_t
183+
ecma_builtin_array_prototype_join (const ecma_value_t this_arg, /**< this argument */
184+
const ecma_value_t separator_arg) /** < separator argument */
185+
{
186+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
187+
188+
/* 1. */
189+
ECMA_TRY_CATCH (obj_value,
190+
ecma_op_to_object (this_arg),
191+
ret_value);
192+
193+
ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);
194+
195+
ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
196+
197+
/* 2. */
198+
ECMA_TRY_CATCH (length_value,
199+
ecma_op_object_get (obj_p, length_magic_string_p),
200+
ret_value);
201+
202+
ECMA_OP_TO_NUMBER_TRY_CATCH (length_number,
203+
length_value,
204+
ret_value);
205+
206+
/* 3. */
207+
uint32_t length = ecma_number_to_uint32 (length_number);
208+
209+
/* 4-5. */
210+
ECMA_TRY_CATCH (separator_value,
211+
ecma_op_array_get_separator_string (separator_arg),
212+
ret_value);
213+
214+
if (length == 0)
215+
{
216+
/* 6. */
217+
ecma_string_t *empty_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING__EMPTY);
218+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (empty_string_p));
219+
}
220+
else
221+
{
222+
ecma_string_t *separator_string_p = ecma_get_string_from_value (separator_value);
223+
224+
/* 7-8. */
225+
ECMA_TRY_CATCH (first_value,
226+
ecma_op_array_get_to_string_at_index (obj_p, 0),
227+
ret_value);
228+
229+
ecma_string_t *return_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (first_value));
230+
231+
/* 9-10. */
232+
for (uint32_t k = 1; ecma_is_completion_value_empty (ret_value) && (k < length); ++k)
233+
{
234+
/* 10.a */
235+
ecma_string_t *part_string_p = ecma_concat_ecma_strings (return_string_p, separator_string_p);
236+
237+
/* 10.b, 10.c */
238+
ECMA_TRY_CATCH (next_string_value,
239+
ecma_op_array_get_to_string_at_index (obj_p, k),
240+
ret_value);
241+
242+
ecma_string_t *next_string_p = ecma_get_string_from_value (next_string_value);
243+
244+
ecma_deref_ecma_string (return_string_p);
245+
246+
/* 10.d */
247+
return_string_p = ecma_concat_ecma_strings (part_string_p, next_string_p);
248+
249+
ECMA_FINALIZE (next_string_value);
250+
251+
ecma_deref_ecma_string (part_string_p);
252+
}
253+
254+
if (ecma_is_completion_value_empty (ret_value))
255+
{
256+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (return_string_p));
257+
}
258+
else
259+
{
260+
ecma_deref_ecma_string (return_string_p);
261+
}
262+
263+
ECMA_FINALIZE (first_value);
264+
}
265+
266+
ECMA_FINALIZE (separator_value);
267+
268+
ECMA_OP_TO_NUMBER_FINALIZE (length_number);
269+
270+
ECMA_FINALIZE (length_value);
271+
272+
ecma_deref_ecma_string (length_magic_string_p);
273+
274+
ECMA_FINALIZE (obj_value);
275+
276+
return ret_value;
277+
} /* ecma_builtin_array_prototype_join */
278+
172279
/**
173280
* The Array.prototype object's 'toString' routine
174281
*

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ NUMBER_VALUE (ECMA_MAGIC_STRING_LENGTH,
5959
/* Routine properties:
6060
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
6161
ROUTINE (ECMA_MAGIC_STRING_FOR_EACH_UL, ecma_builtin_array_prototype_object_for_each, 2, 1)
62+
ROUTINE (ECMA_MAGIC_STRING_JOIN, ecma_builtin_array_prototype_join, 1, 1)
6263
ROUTINE (ECMA_MAGIC_STRING_TO_STRING_UL, ecma_builtin_array_prototype_object_to_string, 0, 0)
6364
ROUTINE (ECMA_MAGIC_STRING_POP, ecma_builtin_array_prototype_object_pop, 0, 0)
6465
ROUTINE (ECMA_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_FIXED, 1)
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* Copyright 2015 Samsung Electronics Co., Ltd.
2+
* Copyright 2015 University of Szeged.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "ecma-array-prototype.h"
18+
19+
#include "ecma-builtins.h"
20+
#include "ecma-conversion.h"
21+
#include "ecma-function-object.h"
22+
#include "ecma-exceptions.h"
23+
#include "ecma-helpers.h"
24+
#include "ecma-objects.h"
25+
#include "ecma-try-catch-macro.h"
26+
27+
/** \addtogroup ecma ECMA
28+
* @{
29+
*
30+
* \addtogroup ecmabuiltins
31+
* @{
32+
*
33+
* \addtogroup arrayprototype ECMA Array.prototype object built-in operations
34+
* @{
35+
*/
36+
37+
/**
38+
* The Array.prototype.toString's separator creation routine
39+
*
40+
* See also:
41+
* ECMA-262 v5.1, 15.4.4.2 4th step
42+
*
43+
* @return completion value
44+
* Returned value must be freed with ecma_free_completion_value.
45+
*/
46+
ecma_completion_value_t
47+
ecma_op_array_get_separator_string (ecma_value_t separator) /** < possible separator */
48+
{
49+
if (ecma_is_value_undefined (separator))
50+
{
51+
ecma_string_t *comma_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_COMMA_CHAR);
52+
return ecma_make_normal_completion_value (ecma_make_string_value (comma_string_p));
53+
}
54+
else
55+
{
56+
return ecma_op_to_string (separator);
57+
}
58+
} /* ecma_op_array_get_separator_string */
59+
60+
/**
61+
* The Array.prototype's 'toString' single element operation routine
62+
*
63+
* See also:
64+
* ECMA-262 v5.1, 15.4.4.2
65+
*
66+
* @return ecma_completion_value_t value
67+
* Returned value must be freed with ecma_free_completion_value.
68+
*/
69+
ecma_completion_value_t
70+
ecma_op_array_get_to_string_at_index (ecma_object_t *obj_p, /** < this object */
71+
uint32_t index) /** < array index */
72+
{
73+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
74+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
75+
76+
ECMA_TRY_CATCH (index_value,
77+
ecma_op_object_get (obj_p, index_string_p),
78+
ret_value);
79+
80+
if (ecma_is_value_undefined (index_value)
81+
|| ecma_is_value_null (index_value))
82+
{
83+
ecma_string_t *empty_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING__EMPTY);
84+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (empty_string_p));
85+
}
86+
else
87+
{
88+
ret_value = ecma_op_to_string (index_value);
89+
}
90+
91+
ECMA_FINALIZE (index_value)
92+
93+
ecma_deref_ecma_string (index_string_p);
94+
95+
return ret_value;
96+
} /* ecma_op_array_get_to_string_at_index */
97+
98+
/**
99+
* @}
100+
* @}
101+
* @}
102+
*/
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* Copyright 2015 Samsung Electronics Co., Ltd.
2+
* Copyright 2015 University of Szeged.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef ECMA_ARRAY_PROTOTYPE_H
18+
#define ECMA_ARRAY_PROTOTYPE_H
19+
20+
#include "ecma-globals.h"
21+
22+
/** \addtogroup ecma ECMA
23+
* @{
24+
*
25+
* \addtogroup ecmaarrayprototypeops ECMA array prototype's operations
26+
* @{
27+
*/
28+
29+
extern ecma_completion_value_t ecma_op_array_get_separator_string (ecma_value_t separator);
30+
extern ecma_completion_value_t ecma_op_array_get_to_string_at_index (ecma_object_t *obj_p, uint32_t index);
31+
32+
/**
33+
* @}
34+
* @}
35+
*/
36+
37+
#endif /* !ECMA_ARRAY_PROPERTY_H */

tests/jerry/array_prototype_join.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
assert ([].join() === "");
17+
assert ([1].join() === "1");
18+
assert ([1, 2].join() === "1,2");
19+
20+
21+
assert ([].join('--') === "");
22+
assert ([1].join("--") === "1");
23+
assert ([1, 2].join('--') === "1--2");
24+
25+
assert ([1,2,3].join({toString: function() { return "--"; }}) === "1--2--3");
26+
27+
28+
// Join should use 'length' to as the number of elements int the array.
29+
var lst = [1,2,3,4];
30+
lst.length = 3;
31+
assert (lst.join() === [1,2,3].join());
32+
33+
// Checking behavior when unable to get length.
34+
var obj = {};
35+
Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } });
36+
obj.join = Array.prototype.join;
37+
38+
try {
39+
obj.join();
40+
// Should not be reached.
41+
assert (false);
42+
} catch (e) {
43+
assert (e.message === "foo");
44+
assert (e instanceof ReferenceError);
45+
}
46+
47+
// Check join argument fail.
48+
try {
49+
[1,2,3].join({toString: function() { throw new ReferenceError ("foo"); }});
50+
// Should not be reached.
51+
assert (false);
52+
} catch (e) {
53+
assert (e.message === "foo");
54+
assert (e instanceof ReferenceError);
55+
}
56+
57+
// Check single join element fail.
58+
try {
59+
[1, 2, {toString: function() { throw new ReferenceError ("foo"); }}, 4].join();
60+
// Should not be reached.
61+
assert (false);
62+
} catch (e) {
63+
assert (e.message === "foo");
64+
assert (e instanceof ReferenceError);
65+
}
66+
67+
// Check join on different object.
68+
var obj_2 = {};
69+
obj_2.length = 3;
70+
obj_2[0] = 1;
71+
obj_2[1] = 2;
72+
obj_2[2] = 3;
73+
obj_2[3] = 4;
74+
75+
obj_2.join = Array.prototype.join;
76+
77+
assert (obj_2.join() === "1,2,3");

0 commit comments

Comments
 (0)