Skip to content

Commit 756494b

Browse files
committed
Fix Array.prototype.concat() when 'this' is not an array.
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
1 parent b414329 commit 756494b

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

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

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,24 +113,47 @@ ecma_builtin_array_prototype_object_concat (ecma_value_t this_arg, /**< this arg
113113
ecma_completion_value_t new_array = ecma_op_create_array_object (0, 0, false);
114114
ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array);
115115

116+
/* 5.b */
117+
if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL)
118+
{
119+
/* 5.b.iii */
120+
for (uint32_t index = 0;
121+
index < len && ecma_is_completion_value_empty (ret_value);
122+
index++, new_array_index++)
123+
{
124+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
125+
/* 5.b.iii.3.a */
126+
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, index_string_p), ret_value);
116127

117-
for (uint32_t index = 0;
118-
index < len && ecma_is_completion_value_empty (ret_value);
119-
index++, new_array_index++)
128+
/* Using [[Put]] is equvalent to [[DefineOwnProperty]] in this case, so we use it for simplicity. */
129+
ecma_completion_value_t put_comp = ecma_op_object_put (new_array_p,
130+
index_string_p,
131+
get_value,
132+
false);
133+
JERRY_ASSERT (ecma_is_completion_value_normal (put_comp));
134+
ecma_free_completion_value (put_comp);
135+
136+
ECMA_FINALIZE (get_value);
137+
ecma_deref_ecma_string (index_string_p);
138+
}
139+
}
140+
/* 5.c */
141+
else
120142
{
121-
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
122-
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, index_string_p), ret_value);
143+
ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index);
123144

124-
/* Using [[Put]] is equvalent to [[DefineOwnProperty]] in this case, so we use it for simplicity. */
145+
/* 5.c.i */
125146
ecma_completion_value_t put_comp = ecma_op_object_put (new_array_p,
126-
index_string_p,
127-
get_value,
147+
new_array_index_string_p,
148+
this_arg,
128149
false);
129-
JERRY_ASSERT (ecma_is_completion_value_normal (put_comp));
150+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));
130151
ecma_free_completion_value (put_comp);
131152

132-
ECMA_FINALIZE (get_value);
133-
ecma_deref_ecma_string (index_string_p);
153+
ecma_deref_ecma_string (new_array_index_string_p);
154+
155+
/* 5.c.ii */
156+
new_array_index++;
134157
}
135158

136159
for (uint32_t arg_index = 0;

tests/jerry/array-prototype-concat.js

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@ for (i = 0; i < array.length; i++) {
2121
assert(array[i] === new_arr[i]);
2222
}
2323

24-
var obj = {};
24+
var obj = { concat : Array.prototype.concat };
2525
var arr1 = ["Apple", 6, "Peach"];
2626
var arr2 = [obj, "Cherry", "Grape"];
2727

28+
var new_array = obj.concat(arr1);
29+
assert(new_array.length === 4);
30+
assert(new_array[0] === obj);
31+
assert(new_array[1] === "Apple");
32+
assert(new_array[2] === 6);
33+
assert(new_array[3] === "Peach");
34+
2835
var new_array = arr1.concat(arr2, obj, 1);
2936

3037
assert(new_array.length === 8);
@@ -50,24 +57,13 @@ for (i = 0; i < result.length; i++) {
5057
assert(result[i] === expected[i]);
5158
}
5259

53-
// Checking behavior when unable to get length
54-
var obj = { concat : Array.prototype.concat }
55-
Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } });
56-
57-
try {
58-
obj.concat();
59-
assert(false);
60-
} catch (e) {
61-
assert(e.message === "foo");
62-
assert(e instanceof ReferenceError);
63-
}
64-
6560
// Checking behavior when unable to get element
66-
var obj = { concat : Array.prototype.concat, length : 1 }
67-
Object.defineProperty(obj, '0', { 'get' : function () {throw new ReferenceError ("foo"); } });
61+
var arr = []
62+
Object.defineProperty(arr, '0', { 'get' : function () {throw new ReferenceError ("foo"); } });
63+
arr.length = 1;
6864

6965
try {
70-
obj.concat();
66+
arr.concat();
7167
assert(false);
7268
} catch (e) {
7369
assert(e.message === "foo");

0 commit comments

Comments
 (0)