Skip to content

Commit 676a3d1

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 676a3d1

File tree

2 files changed

+249
-1
lines changed

2 files changed

+249
-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: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,250 @@ 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()
251+
{
252+
delete arr[3];
253+
arr.length = 13;
254+
Object.defineProperty(arr, '5', function() { })
255+
};
256+
obj = {get: f, valueOf : f, toString: f};
257+
arr = [1, 2, obj, 4, 5];
258+
Object.defineProperty(arr, '2',{ 'get' : f } );
259+
for(var i = 0; i < arr.length; i++)
260+
{
261+
var a = arr[i];
262+
}
263+
arr.splice(1, 4, obj);
264+
assert(false);
265+
} catch (e) {
266+
assert(e instanceof TypeError);
267+
}
268+
269+
// Checking behavior when a modified object is an element of the array and deletes the elements
270+
try {
271+
f = function()
272+
{
273+
for(var i = 0; i < arr.length; i++)
274+
{
275+
delete arr[i]
276+
}
277+
};
278+
obj = {get: f, valueOf : f, toString: f };
279+
arr = [1, 2, obj, 4, 5];
280+
for(var i = 0; i < 6; i++)
281+
{
282+
Object.defineProperty(arr, i, { 'get' : f });
283+
}
284+
arr.splice(1, 3, obj);
285+
assert(false);
286+
} catch (e) {
287+
assert(e instanceof TypeError);
288+
}
289+
290+
// Checking behavior when an element of the array throws error
291+
try {
292+
f = function() { throw new TypeError("4"); };
293+
obj = {get: f, valueOf : f, toString: f};
294+
arr = [1, 2, obj, 4, 5];
295+
Object.defineProperty(arr, '4', { 'get' : f });
296+
arr.splice(1, 3, obj);
297+
assert(false);
298+
} catch (e) {
299+
assert(e instanceof TypeError);
300+
assert(e.message == "4");
301+
}
302+
303+
// Checking behavior when elements are getting deleted the following way
304+
try{
305+
f = function()
306+
{
307+
for(var i = 0; i < arr.length; i++)
308+
{
309+
delete arr[i];
310+
}
311+
};
312+
f1 = function() { delete arr[2]; };
313+
f2 = function() { delete arr[3]; };
314+
f3 = function() { delete arr[4]; };
315+
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
316+
delete arr[2];
317+
delete arr[3];
318+
Object.defineProperty(arr, '0', { 'get' : f });
319+
Object.defineProperty(arr, '1', { 'get' : f });
320+
Object.defineProperty(arr, '2', { 'get' : f });
321+
Object.defineProperty(arr, '3', { 'get' : f });
322+
Object.defineProperty(arr, '8', { 'get' : f1 });
323+
Object.defineProperty(arr, '9', { 'get' : f2 });
324+
Object.defineProperty(arr, '10', { 'get' : f3 });
325+
arr.splice(1, 7, 5);
326+
} catch (e) {
327+
assert(e instanceof TypeError);
328+
}
329+
330+
// Checking behavior when elements are getting deleted the same way, but there are more elements and arguments
331+
try {
332+
f = function()
333+
{
334+
for(var i = 0; i < arr.length; i++)
335+
{
336+
delete arr[i];
337+
}
338+
};
339+
f1 = function() { delete arr[2]; };
340+
f2 = function() { delete arr[3]; };
341+
f3 = function() { delete arr[4]; };
342+
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];
343+
delete arr[2];
344+
delete arr[3];
345+
Object.defineProperty(arr, '0', { 'get' : f });
346+
Object.defineProperty(arr, '1', { 'get' : f });
347+
Object.defineProperty(arr, '2', { 'get' : f });
348+
Object.defineProperty(arr, '3', { 'get' : f });
349+
Object.defineProperty(arr, '8', { 'get' : f });
350+
Object.defineProperty(arr, '9', { 'get' : f2 });
351+
Object.defineProperty(arr, '10', { 'get' : f3 });
352+
arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
353+
assert(false);
354+
} catch (e) {
355+
assert(e instanceof TypeError);
356+
}
357+
358+
// Checking behavior when first 3 elements throw error
359+
try {
360+
var a = [1, 5, 6, 7, 8, 5];
361+
Object.defineProperty(a, '1', { 'get' : function() { throw new ReferenceError("foo1"); } });
362+
Object.defineProperty(a, '0', { 'get' : function() { throw new ReferenceError("foo0"); } });
363+
Object.defineProperty(a, '2', { 'get' : function() { throw new ReferenceError("foo2"); } });
364+
Array.prototype.splice.call(a, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
365+
assert(false);
366+
} catch (e) {
367+
assert(e instanceof ReferenceError);
368+
assert(e.message == "foo0");
369+
}
370+
371+
// Checking behavior when last 3 elements throw error
372+
try {
373+
f = function()
374+
{
375+
for(var i = 0; i < arr.length; i++)
376+
{
377+
delete arr[i]
378+
}
379+
};
380+
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];
381+
delete arr[22];
382+
delete arr[23];
383+
Object.defineProperty(arr, '21', { 'get' : f });
384+
Object.defineProperty(arr, '22', { 'get' : f });
385+
Object.defineProperty(arr, '23', { 'get' : f });
386+
arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
387+
assert(false);
388+
} catch (e) {
389+
assert(e instanceof TypeError);
390+
}
391+
392+
// Checking behavior when a yet non existing element will throw an error
393+
try {
394+
f = function () { throw new TypeError("6");};
395+
arr = [1, 2, 4, 5];
396+
Object.defineProperty(arr, '4',{ 'get' : f });
397+
arr.splice(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
398+
assert(false);
399+
} catch (e) {
400+
assert(e instanceof TypeError);
401+
assert(e.message == "6");
402+
}
403+
404+
// Checking behavior when the last element gets deleted
405+
try {
406+
f = function () { delete arr[23];};
407+
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];
408+
delete arr[23];
409+
Object.defineProperty(arr, '23',{ 'get' : f });
410+
arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
411+
assert(false);
412+
} catch (e) {
413+
assert(e instanceof TypeError);
414+
}
415+
416+
// Checking behavior when the array is empty, large, and not writable
417+
try {
418+
arr = [];
419+
Object.defineProperty(arr, 'length', { value : 999, writable: false });
420+
arr.splice(1, 2, 4, 5);
421+
assert(false);
422+
} catch (e) {
423+
assert(e instanceof TypeError);
424+
}

0 commit comments

Comments
 (0)