diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c index fd863f1b73..fb7f6baddb 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -1224,8 +1224,9 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu } } /* 13. */ - else if (item_count > delete_count) + else { + JERRY_ASSERT (item_count > delete_count); /* 13.b */ for (k = len - delete_count; k > start && ecma_is_value_empty (ret_value); k--) { diff --git a/tests/jerry/array-prototype-splice.js b/tests/jerry/array-prototype-splice.js index c5c01ab505..9735fe4729 100644 --- a/tests/jerry/array-prototype-splice.js +++ b/tests/jerry/array-prototype-splice.js @@ -175,3 +175,183 @@ try { assert (e.message === "foo"); assert (e instanceof ReferenceError); } + + +/* ES v5.1 15.4.4.12.5. + Checking behavior when the first argument of the function is an object, which throws error */ +try { + var o = {}; + Object.defineProperty(o, 'toString', { 'get' : function() { throw new ReferenceError("1"); } }); + [1, 2].splice(o); + assert(false); +} catch (e) { + assert(e instanceof ReferenceError); + assert(e.message == "1"); +} + +/* ES v5.1 15.4.4.12.7. + Checking behavior when the second argument of the function is an object, which throws error */ +try { + var o = {}; + Object.defineProperty(o, 'toString', { 'get' : function() { throw new ReferenceError("2"); } }); + [1, 2].splice(1, o); + assert(false); +} catch (e) { + assert(e instanceof ReferenceError); + assert(e.message == "2"); +} + +/* ES v5.1 15.4.4.12.9.b + Checking behavior when the first element throws error */ +try { + var a = [1, 5, 6, 7, 8, 5]; + Object.defineProperty(a, '0', { 'get' : function() { throw new ReferenceError("foo0"); } }); + Array.prototype.splice.call(a, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); + assert(false); +} catch (e) { + assert(e instanceof ReferenceError); + assert(e.message == "foo0"); +} + +/* ES v5.1 15.4.4.12.12.b.iii. + Checking behavior when an element of the array throws error */ +try { + f = function() { throw new TypeError("4"); }; + obj = {get: f, valueOf : f, toString: f}; + arr = [1, 2, obj, 4, 5]; + Object.defineProperty(arr, '4', { 'get' : f }); + arr.splice(1, 3, obj); + assert(false); +} catch (e) { + assert(e instanceof TypeError); + assert(e.message == "4"); +} + +/* ES v5.1 15.4.4.12 12.b.iv. + Checking behavior when a modified object is an element of the array */ +try { + f = function() { + delete arr[3]; + arr.length = 13; + Object.defineProperty(arr, '5', function() { }); + }; + obj = {get: f, valueOf : f, toString: f}; + arr = [1, 2, obj, 4, 5]; + Object.defineProperty(arr, '2',{ 'get' : f } ); + for(var i = 0; i < arr.length; i++) { + var a = arr[i]; + } + arr.splice(1, 4, obj); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.12.12.b.v. + Checking behavior when elements are getting deleted by an element which only has a get function */ +try{ + f = function() { + for(var i = 0; i < arr.length; i++) { + delete arr[i]; + } + }; + arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + delete arr[2]; + Object.defineProperty(arr, '2', { 'get' : f }); + arr.splice(1, 7, 5); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.12.12.d.i. + Checking behavior when a modified object is an element of the array and deletes the elements */ +try { + f = function() { + for(var i = 0; i < arr.length; i++) { + delete arr[i]; + } + }; + obj = {get: f, valueOf : f, toString: f }; + arr = [1, 2, obj, 4, 5]; + for(var i = 0; i < 6; i++) + { + Object.defineProperty(arr, i, { 'get' : f }); + } + arr.splice(1, 3, obj); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.12.13.b.iii. + Checking behavior when a yet non existing element will throw an error */ +try { + f = function () { throw new TypeError("6");}; + arr = [1, 2, 4, 5]; + Object.defineProperty(arr, '4',{ 'get' : f }); + arr.splice(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + assert(false); +} catch (e) { + assert(e instanceof TypeError); + assert(e.message == "6"); +} + +/* ES v5.1 15.4.4.12.13.b.iv.2. + Checking behavior when the last element gets deleted */ +try { + f = function () { delete arr[23]; }; + 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]; + delete arr[23]; + Object.defineProperty(arr, '23', { 'get' : f }); + arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.12.13.b.v.1. + Checking behavior when the last element throws error */ +try { + f = function() { + for(var i = 0; i < arr.length; i++) + { + delete arr[i]; + } + }; + 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]; + delete arr[23]; + Object.defineProperty(arr, '23', { 'get' : f }); + arr.splice(1, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.12.15.b. + Checking behavior when the issue is the same as above, but splice has more arguments */ +try { + f = function() { + for(var i = 0; i < arr.length; i++) + { + delete arr[i]; + } + }; + arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + delete arr[2]; + Object.defineProperty(arr, '2', { 'get' : f }); + arr.splice(1, 7, 5, 5, 5, 5); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.12.16. + Checking behavior when the array is empty, large, and not writable */ +try { + arr = []; + Object.defineProperty(arr, 'length', { value : 999, writable: false }); + arr.splice(1, 2, 4, 5); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +}