Skip to content

Commit c8d2fdb

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 c8d2fdb

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

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

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,24 +113,40 @@ 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+
if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL)
117+
{
118+
for (uint32_t index = 0;
119+
index < len && ecma_is_completion_value_empty (ret_value);
120+
index++, new_array_index++)
121+
{
122+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
123+
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, index_string_p), ret_value);
116124

117-
for (uint32_t index = 0;
118-
index < len && ecma_is_completion_value_empty (ret_value);
119-
index++, new_array_index++)
125+
/* Using [[Put]] is equvalent to [[DefineOwnProperty]] in this case, so we use it for simplicity. */
126+
ecma_completion_value_t put_comp = ecma_op_object_put (new_array_p,
127+
index_string_p,
128+
get_value,
129+
false);
130+
JERRY_ASSERT (ecma_is_completion_value_normal (put_comp));
131+
ecma_free_completion_value (put_comp);
132+
133+
ECMA_FINALIZE (get_value);
134+
ecma_deref_ecma_string (index_string_p);
135+
}
136+
}
137+
else
120138
{
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);
139+
ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index);
123140

124-
/* Using [[Put]] is equvalent to [[DefineOwnProperty]] in this case, so we use it for simplicity. */
125141
ecma_completion_value_t put_comp = ecma_op_object_put (new_array_p,
126-
index_string_p,
127-
get_value,
142+
new_array_index_string_p,
143+
this_arg,
128144
false);
129-
JERRY_ASSERT (ecma_is_completion_value_normal (put_comp));
145+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));
130146
ecma_free_completion_value (put_comp);
131147

132-
ECMA_FINALIZE (get_value);
133-
ecma_deref_ecma_string (index_string_p);
148+
ecma_deref_ecma_string (new_array_index_string_p);
149+
new_array_index++;
134150
}
135151

136152
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)