Skip to content

Commit 05c044f

Browse files
committed
Increase test coverage: Array.prototype.splice
Branch coverage: Before: 56/78 After: 78/78 Also found opportunity for optimization, that "else if" branch is not needed, should be replaced with an "else". JerryScript-DCO-1.0-Signed-off-by: Mate Dabis [email protected]
1 parent 0c20f8e commit 05c044f

File tree

2 files changed

+220
-1
lines changed

2 files changed

+220
-1
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1378,8 +1378,9 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg
13781378
}
13791379
}
13801380
/* 13. */
1381-
else if (item_count > delete_count)
1381+
else
13821382
{
1383+
JERRY_ASSERT (item_count > delete_count);
13831384
/* 13.b */
13841385
for (k = len - delete_count; k > start && ecma_is_value_empty (ret_value); k--)
13851386
{

tests/jerry/array-prototype-splice.js

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,221 @@ try {
175175
assert (e.message === "foo");
176176
assert (e instanceof ReferenceError);
177177
}
178+
179+
// Checking behavior when the function's this_argument is undefined
180+
try {
181+
Array.prototype.splice.call(undefined);
182+
assert(false);
183+
} catch (e) {
184+
assert(e instanceof TypeError);
185+
}
186+
187+
// Checking behavior when length is an object, which throws error
188+
try {
189+
var o = {};
190+
Object.defineProperty(o, 'toString', { 'get' : function() { throw new ReferenceError("foo"); } });
191+
var a = { length : o };
192+
Array.prototype.splice.call(a);
193+
assert(false);
194+
} catch (e) {
195+
assert(e instanceof ReferenceError);
196+
assert(e.message == "foo");
197+
}
198+
199+
// Checking behavior when the first argument of the function is an object, which throws error
200+
try {
201+
var o = {};
202+
Object.defineProperty(o, 'toString', { 'get' : function() { throw new ReferenceError("1"); } });
203+
[1, 2].splice(o);
204+
assert(false);
205+
} catch (e) {
206+
assert(e instanceof ReferenceError);
207+
assert(e.message == "1");
208+
}
209+
210+
// Checking behavior when the second argument of the function is an object, which throws error
211+
try {
212+
var o = {};
213+
Object.defineProperty(o, 'toString', { 'get' : function() { throw new ReferenceError("2"); } });
214+
[1, 2].splice(1, o);
215+
assert(false);
216+
} catch (e) {
217+
assert(e instanceof ReferenceError);
218+
assert(e.message == "2");
219+
}
220+
221+
// Checking behavior when the third element of the array throws error
222+
try {
223+
var a = [1, 5, ,2];
224+
Object.defineProperty(a, '2', { 'get' : function() { throw new ReferenceError("3"); } });
225+
a.splice(1, 7, 7, 7, 7, 7);
226+
assert(false);
227+
} catch (e) {
228+
assert(e instanceof ReferenceError);
229+
assert(e.message == "3");
230+
}
231+
232+
// Checking behavior when the function's this_argument is an object, witch only contains a length
233+
var a = {length : 13};
234+
Array.prototype.splice.call(a, function () {delete a});
235+
assert(a.length === 0);
236+
237+
// Checking behavior when the first element of the array throws error
238+
try {
239+
var a = [1, 5, 6, 7, 8, 5];
240+
Object.defineProperty(a, '0', { 'get' : function() { throw new ReferenceError("foo0"); } });
241+
Array.prototype.splice.call(a, 0, 3);
242+
assert(false);
243+
} catch (e) {
244+
assert(e instanceof ReferenceError);
245+
assert(e.message == "foo0");
246+
}
247+
248+
// Checking behavior when a modified object is an element of the array
249+
try {
250+
f = function() {delete arr[3]; arr.length = 13; Object.defineProperty(arr, '5', function() { })};
251+
obj = {get: f, valueOf : f, toString: f};
252+
arr = [1, 2, obj, 4, 5];
253+
Object.defineProperty(arr, '2',{ 'get' : f } );
254+
for(var i = 0; i < arr.length; i++)
255+
{
256+
var a = arr[i];
257+
}
258+
arr.splice(1, 4, obj);
259+
assert(false);
260+
} catch (e) {
261+
assert(e instanceof TypeError);
262+
}
263+
264+
// Checking behavior when a modified object is an element of the array and deletes the elements
265+
try {
266+
f = function() { for(var i = 0; i < arr.length; i++) { delete arr[i]} };
267+
obj = {get: f, valueOf : f, toString: f};
268+
arr = [1, 2, obj, 4, 5];
269+
for(var i = 0; i < 6; i++)
270+
{
271+
Object.defineProperty(arr, i, { 'get' : f });
272+
}
273+
arr.splice(1, 3, obj);
274+
assert(false);
275+
} catch (e) {
276+
assert(e instanceof TypeError);
277+
}
278+
279+
// Checking behavior when an element of the array throws error
280+
try {
281+
f = function() { throw new TypeError("4");};
282+
obj = {get: f, valueOf : f, toString: f};
283+
arr = [1, 2, obj, 4, 5];
284+
Object.defineProperty(arr, '4', { 'get' : f });
285+
arr.splice(1, 3, obj);
286+
assert(false);
287+
} catch (e) {
288+
assert(e instanceof TypeError);
289+
assert(e.message == "4");
290+
}
291+
292+
// Checking behavior when elements are getting deleted the following way
293+
try{
294+
f = function() { for(var i = 0; i < arr.length; i++) { delete arr[i]} };
295+
f1 = function() { delete arr[2];};
296+
f2 = function() { delete arr[3];};
297+
f3 = function() { delete arr[4];};
298+
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
299+
delete arr[2];
300+
delete arr[3];
301+
Object.defineProperty(arr, '0', { 'get' : f });
302+
Object.defineProperty(arr, '1', { 'get' : f });
303+
Object.defineProperty(arr, '2', { 'get' : f });
304+
Object.defineProperty(arr, '3', { 'get' : f });
305+
Object.defineProperty(arr, '8', { 'get' : f1 });
306+
Object.defineProperty(arr, '9', { 'get' : f2 });
307+
Object.defineProperty(arr, '10', { 'get' : f3 });
308+
arr.splice(1, 7, 5);
309+
} catch (e) {
310+
assert(e instanceof TypeError);
311+
}
312+
313+
// Checking behaior when elements are getting deleted the same way, but there are more elements and arguments
314+
try {
315+
f = function() { for(var i=0; i<arr.length; i++) { delete arr[i]} };
316+
f1 = function() { delete arr[2];};
317+
f2 = function() { delete arr[3];};
318+
f3 = function() { delete arr[4];};
319+
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
320+
delete arr[2];
321+
delete arr[3];
322+
Object.defineProperty(arr, '0', { 'get' : f });
323+
Object.defineProperty(arr, '1', { 'get' : f });
324+
Object.defineProperty(arr, '2', { 'get' : f });
325+
Object.defineProperty(arr, '3', { 'get' : f });
326+
Object.defineProperty(arr, '8', { 'get' : f });
327+
Object.defineProperty(arr, '9', { 'get' : f2 });
328+
Object.defineProperty(arr, '10', { 'get' : f3 });
329+
arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
330+
assert(false);
331+
} catch (e) {
332+
assert(e instanceof TypeError);
333+
}
334+
335+
// Checking behavior when first 3 elements throw error
336+
try {
337+
var a = [1, 5, 6, 7, 8, 5];
338+
Object.defineProperty(a, '1', { 'get' : function() { throw new ReferenceError("foo1"); } });
339+
Object.defineProperty(a, '0', { 'get' : function() { throw new ReferenceError("foo0"); } });
340+
Object.defineProperty(a, '2', { 'get' : function() { throw new ReferenceError("foo2"); } });
341+
Array.prototype.splice.call(a, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
342+
assert(false);
343+
} catch (e) {
344+
assert(e instanceof ReferenceError);
345+
assert(e.message == "foo0");
346+
}
347+
348+
// Checking behavior when last 3 elements throw error
349+
try {
350+
f = function() { for(var i=0; i<arr.length; i++) { delete arr[i]} };
351+
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
352+
delete arr[22];
353+
delete arr[23];
354+
Object.defineProperty(arr, '21',{ 'get' : f });
355+
Object.defineProperty(arr, '22',{ 'get' : f });
356+
Object.defineProperty(arr, '23',{ 'get' : f });
357+
arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
358+
assert(false);
359+
} catch (e) {
360+
assert(e instanceof TypeError);
361+
}
362+
363+
// Checking behavior when a yet non existing element will throw an error
364+
try {
365+
f = function () { throw new TypeError("6");};
366+
arr = [1, 2, 4, 5];
367+
Object.defineProperty(arr, '4',{ 'get' : f });
368+
arr.splice(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
369+
assert(false);
370+
} catch (e) {
371+
assert(e instanceof TypeError);
372+
assert(e.message == "6");
373+
}
374+
375+
// Checking behavior when the last element gets deleted
376+
try {
377+
f = function () { delete arr[23];};
378+
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
379+
delete arr[23];
380+
Object.defineProperty(arr, '23',{ 'get' : f });
381+
arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
382+
assert(false);
383+
} catch (e) {
384+
assert(e instanceof TypeError);
385+
}
386+
387+
// Checking behavior when the array is empty, large, and not writable
388+
try {
389+
arr = [];
390+
Object.defineProperty(arr, 'length', { value : 999, writable: false });
391+
arr.splice(1, 2, 4, 5);
392+
assert(false);
393+
} catch (e) {
394+
assert(e instanceof TypeError);
395+
}

0 commit comments

Comments
 (0)