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..530b7e5dac 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -579,7 +579,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar ECMA_FINALIZE (put_value); } /* 6.j */ - else if (lower_exist && !upper_exist) + else if (lower_exist) { ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, lower_str_p, true), ret_value); ECMA_TRY_CATCH (put_value, ecma_op_object_put (obj_p, upper_str_p, lower_value, true), ret_value); @@ -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-concat.js b/tests/jerry/array-prototype-concat.js index dc1f37889d..a0d26545f8 100644 --- a/tests/jerry/array-prototype-concat.js +++ b/tests/jerry/array-prototype-concat.js @@ -74,3 +74,17 @@ try { assert(e.message === "foo"); assert(e instanceof ReferenceError); } + +/* ES v5.1 15.4.4.4.5. + Checking behavior when unable to get element from a given array */ +arr1 = []; +arr2 = []; +arr3 = []; +Object.defineProperty(arr2, '0', { 'get' : function () {throw new ReferenceError ("foo"); } }); + +try { + arr1.concat(arr2, arr3); + assert(false); +} catch (e) { + assert(e instanceof ReferenceError); +} diff --git a/tests/jerry/array-prototype-join.js b/tests/jerry/array-prototype-join.js index 96233d0e72..2629732f75 100644 --- a/tests/jerry/array-prototype-join.js +++ b/tests/jerry/array-prototype-join.js @@ -74,3 +74,16 @@ obj_2[3] = 4; obj_2.join = Array.prototype.join; assert (obj_2.join() === "1,2,3"); + +/* ES v5.1 15.4.4.5.7. + Checking behavior when an element throws error */ +try { + var f = function () { throw new TypeError("ooo");}; + var arr = [0, 1, 2, 3]; + Object.defineProperty(arr, '0', { 'get' : f }); + Array.prototype.join.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); + assert(e.message == "ooo"); +} diff --git a/tests/jerry/array-prototype-pop.js b/tests/jerry/array-prototype-pop.js index 0d58dcba50..dab96c06db 100644 --- a/tests/jerry/array-prototype-pop.js +++ b/tests/jerry/array-prototype-pop.js @@ -72,3 +72,27 @@ try { assert(e.message === "foo"); assert(e instanceof ReferenceError); } + +/* ES v5.1 15.4.4.6.5.c + Checking behavior when unable to delete property */ +var obj = {pop : Array.prototype.pop, length : 2}; +Object.defineProperty(obj, '1', function () {}); + +try { + obj.pop(); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.6.5.d + Checking behavior when array is not modifiable */ +var obj = {pop : Array.prototype.pop, length : 2}; +Object.freeze(obj); + +try { + obj.pop(); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} diff --git a/tests/jerry/array-prototype-push.js b/tests/jerry/array-prototype-push.js index 84a55e9bfb..3c83838aca 100644 --- a/tests/jerry/array-prototype-push.js +++ b/tests/jerry/array-prototype-push.js @@ -74,3 +74,15 @@ try { } assert(o.length === 1); assert(o[0] === "z"); + +/* ES v5.1 15.4.4.7.5. + Checking behavior when array is non-extensible while pushing */ +var arr = []; +Object.freeze(arr); + +try { + arr.push(1, 2); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} diff --git a/tests/jerry/array-prototype-reverse.js b/tests/jerry/array-prototype-reverse.js index 69be5af418..0434a55f2b 100644 --- a/tests/jerry/array-prototype-reverse.js +++ b/tests/jerry/array-prototype-reverse.js @@ -43,3 +43,77 @@ try { assert(e.message === "foo"); assert(e instanceof ReferenceError); } + +/* ES v5.1 15.4.4.8.6.e. + Checking behavior when unable to get the last element */ +var obj = { reverse : Array.prototype.reverse, length : 4 }; +Object.defineProperty(obj, '3', { 'get' : function () {throw new ReferenceError ("foo"); } }); + +try { + obj.reverse(); + assert(false); +} catch (e) { + assert(e.message === "foo"); + assert(e instanceof ReferenceError); +} + +/* ES v5.1 15.4.4.8.6.h.i. + Checking behavior when first 3 elements are not writable */ +try { + var arr = [,,, 3, 4, 5, 6,,,,,,,,,0, 1, 2, 3, 4, 5, 6]; + Object.defineProperty(arr, '0', {}); + Object.defineProperty(arr, '1', {}); + Object.defineProperty(arr, '2', {}); + Array.prototype.reverse.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.8.6.h.ii. + Checking behavior when last 3 elements are not writable */ +try { + var arr = [0, 1, 2, 3, 4, 5, 6,,,,,,,,,0, 1, 2, 3,,,]; + Object.defineProperty(arr, '19', {}); + Object.defineProperty(arr, '20', {}); + Object.defineProperty(arr, '21', {}); + Array.prototype.reverse.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.8.6.i.i. + Checking behavior when first elements do not exist and the array is freezed */ +try { + var arr = [,,,,,,,,,,,,,,,,0, 1, 2, 3, 4, 5, 6]; + arr = Object.freeze(arr); + Array.prototype.reverse.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.8.6.i.ii. + Checking behavior when unable to get the first 2 elements */ +var obj = { reverse : Array.prototype.reverse, length : 4 }; +Object.defineProperty(obj, '2', { value : 0 }); +Object.defineProperty(obj, '3', { value : 0 }); +try { + obj.reverse(); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.8.6.j.i. + Checking behavior when unable to get the last 2 elements */ +var obj = { reverse : Array.prototype.reverse, length : 4 }; +Object.defineProperty(obj, '0', { value : 0 }); +Object.defineProperty(obj, '1', { value : 0 }); +try { + obj.reverse(); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} diff --git a/tests/jerry/array-prototype-shift.js b/tests/jerry/array-prototype-shift.js index 843c17c943..a188f2ffbb 100644 --- a/tests/jerry/array-prototype-shift.js +++ b/tests/jerry/array-prototype-shift.js @@ -77,3 +77,61 @@ try { assert(e.message === "foo"); assert(e instanceof ReferenceError); } + +/* ES v5.1 15.4.4.9.7.c. + Checking behavior when the array is freezed */ +try { + f = function () { throw new ReferenceError("getter"); }; + arr = { length : 9 }; + Object.defineProperty(arr, '8', { 'get' : f }); + Array.prototype.shift.call(arr); + assert(false); +} catch (e) { + assert(e instanceof ReferenceError); + assert(e.message == "getter"); +} + +/* ES v5.1 15.4.4.9.7.d.ii. + Checking behavior when the array is freezed */ +try { + arr = { length : 9 }; + Object.defineProperty(arr, '8', { value : 8 }); + Object.defineProperty(arr, '7', { value : 7 }); + Array.prototype.shift.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.9.7.e.i. + Checking behavior when the first element is null */ +try { + arr = { length : 9 }; + Object.defineProperty(arr, '0', { value : null }); + Array.prototype.shift.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.9.8. + Checking behavior when last element is not writable */ +try { + arr = { length : 9 }; + Object.defineProperty(arr, '8', { writable : false }); + Array.prototype.shift.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.9.9. + Checking behavior when the array is freezed */ +try { + arr = { length : 9 }; + Object.freeze(arr); + Array.prototype.shift.call(arr); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} diff --git a/tests/jerry/array-prototype-slice.js b/tests/jerry/array-prototype-slice.js index bb1a2e800b..1ba2f9fc5a 100644 --- a/tests/jerry/array-prototype-slice.js +++ b/tests/jerry/array-prototype-slice.js @@ -110,3 +110,44 @@ try { assert (e.message === "foo"); assert (e instanceof ReferenceError); } + +/* ES v5.1 15.4.4.10.5. + Checking behavior when start value throws exception */ +var arg1 = { }; +Object.defineProperty(arg1, 'valueOf', { 'get' : function () { throw new ReferenceError ("foo"); } }); +var obj = { slice : Array.prototype.slice }; + +try { + obj.slice(arg1); + assert(false); +} catch (e) { + assert(e.message === 'foo'); + assert(e instanceof ReferenceError); +} + +/* ES v5.1 15.4.4.10.7. + Checking behavior when end value throws exception */ +var arg2 = { }; +Object.defineProperty(arg2, 'valueOf', { 'get' : function () { throw new ReferenceError ("foo"); } }); +var obj = { slice : Array.prototype.slice }; + +try { + obj.slice(0, arg2); + assert(false); +} catch (e) { + assert(e.message === 'foo'); + assert(e instanceof ReferenceError); +} + +/* ES v5.1 15.4.4.10.10. + Checking behavior when unable to get element */ +var obj = { length : 3, slice : Array.prototype.slice }; +Object.defineProperty(obj, '1', { 'get' : function () { throw new ReferenceError ("foo"); } }); + +try { + obj.slice(0, 3); + assert (false); +} catch (e) { + assert (e.message === "foo"); + assert (e instanceof ReferenceError); +} diff --git a/tests/jerry/array-prototype-sort.js b/tests/jerry/array-prototype-sort.js index 22b9d4ecff..a036e18d18 100644 --- a/tests/jerry/array-prototype-sort.js +++ b/tests/jerry/array-prototype-sort.js @@ -92,3 +92,95 @@ try { assert(e.message === "foo"); assert(e instanceof ReferenceError); } + +// Checking behavior when unable to get elements +var obj = { sort : Array.prototype.sort, length : 2}; +Object.defineProperty(obj, '0', { 'get' : function () { throw new ReferenceError ("foo"); } }); +Object.defineProperty(obj, '1', { 'get' : function () { throw new ReferenceError ("bar"); } }); + +try { + obj.sort(); + assert(false); +} catch (e) { + assert(e.message === "foo"); + assert(e instanceof ReferenceError); +} + +// Checking behavior when array is non-extensible while sorting +var arr = [1, 0]; + +try { + arr.sort(function () { Object.freeze(arr) }); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +// Checking behavior when unable to delete property +var obj = {sort : Array.prototype.sort, '0' : 2, '1' : 1, length : 4}; +Object.defineProperty(obj, '3', function () {}); + +try { + obj.sort(); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +// Checking behavior when unable to get the last element +var arr = [1, 2, ]; +Object.defineProperty(arr, '2', { 'get' : function () { throw new ReferenceError ("foo"); } }); + +try { + arr.sort(); + assert(false); +} catch (e) { + assert(e.message === 'foo'); + assert(e instanceof ReferenceError); +} + +// Checking behavior when lhs_value throws exception at comparefn +f = function () { throw new ReferenceError('foo'); }; +obj = { 'toString' : f }; +arr = [obj, 1]; + +try { + arr.sort(); + assert(false); +} catch (e) { + assert(e.message === 'foo'); + assert(e instanceof ReferenceError); +} + +// Checking behavior when rhs_value throws exception at comparefn +f = function () { throw new ReferenceError('foo'); }; +obj = { 'toString' : f }; +arr = [1, obj]; + +try { + arr.sort(); + assert(false); +} catch (e) { + assert(e.message === 'foo'); + assert(e instanceof ReferenceError); +} + +// Sorting when array elements are the same string +arr = ['foo', 'foo']; +arr.sort(); + +assert(arr[0] === 'foo'); +assert(arr[1] === 'foo'); + +// Checking behavior when comparefn's call value cannot be converted to number +obj = { }; +Object.defineProperty(obj, 'toString', function () { }); +f = function () { return obj }; +arr = [1, 2]; + +try { + arr.sort(f); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} diff --git a/tests/jerry/array-prototype-splice.js b/tests/jerry/array-prototype-splice.js index c5c01ab505..d64119ed31 100644 --- a/tests/jerry/array-prototype-splice.js +++ b/tests/jerry/array-prototype-splice.js @@ -175,3 +175,187 @@ 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 */ +function f0() { throw new TypeError("4"); }; + +try { + obj = {get: f0, valueOf : f0, toString: f0}; + arr = [1, 2, obj, 4, 5]; + Object.defineProperty(arr, '4', { 'get' : f0 }); + 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 */ +function f() { + delete arr[3]; + arr.length = 13; + Object.defineProperty(arr, '5', function() { }); +}; + +try { + 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 */ +function f1() { + for(var i = 0; i < arr.length; i++) { + delete arr[i]; + } +}; + +try{ + arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + delete arr[2]; + Object.defineProperty(arr, '2', { 'get' : f1 }); + 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 */ +function f2() { + for(var i = 0; i < arr.length; i++) { + delete arr[i]; + } +}; + +try { + obj = {get: f2, valueOf : f2, toString: f2 }; + arr = [1, 2, obj, 4, 5]; + for(var i = 0; i < 6; i++) { + Object.defineProperty(arr, i, { 'get' : f2 }); + } + 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 */ +function f3() { throw new TypeError("6");}; + +try { + arr = [1, 2, 4, 5]; + Object.defineProperty(arr, '4',{ 'get' : f3 }); + 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 */ +function f4() { delete arr[23]; }; + +try { + 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' : f4 }); + 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 */ +function f5() { + for(var i = 0; i < arr.length; i++) { + delete arr[i]; + } +}; + +try { + 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' : f5 }); + 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 */ +function f6() { + for(var i = 0; i < arr.length; i++) { + delete arr[i]; + } +}; + +try { + arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + delete arr[2]; + Object.defineProperty(arr, '2', { 'get' : f6 }); + 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); +} diff --git a/tests/jerry/array-prototype-unshift.js b/tests/jerry/array-prototype-unshift.js index a4394d415c..1ba97b7d77 100644 --- a/tests/jerry/array-prototype-unshift.js +++ b/tests/jerry/array-prototype-unshift.js @@ -101,3 +101,25 @@ assert(obj[0] === "baz"); assert(obj[1] === "foo"); assert(obj[2] === undefined); assert(obj[3] === "bar"); + +/* ES v5.1 15.4.4.13.6.d.ii. + Checking behavior when the array is freezed */ +try { + var arr = [0, 1]; + Object.freeze(arr); + Array.prototype.unshift.call(arr, 2, 3); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} + +/* ES v5.1 15.4.4.13.6.e.i. + Checking behavior when the array has only one property and bigger length */ +try { + var arr = { length : 9 }; + Object.defineProperty(arr, '6', { value : 2 }); + Array.prototype.unshift.call(arr, 2, 3); + assert(false); +} catch (e) { + assert(e instanceof TypeError); +} diff --git a/tests/jerry/es2015/array-prototype-find.js b/tests/jerry/es2015/array-prototype-find.js index c238cc4ebd..a034c56da0 100644 --- a/tests/jerry/es2015/array-prototype-find.js +++ b/tests/jerry/es2015/array-prototype-find.js @@ -135,3 +135,14 @@ try { // Checking behavior when the there are more than 2 arguments assert (array.find (function (e) { return e < 2 }, {}, 8, 4, 5, 6, 6) === 1); + +function func (element) { + return element > 8; +} + +/* ES v6.0 22.1.3.8.8.c + Checking behavior when the first element deletes the second */ +function f() { delete arr[1]; }; +var arr = [0, 1, 2, 3]; +Object.defineProperty(arr, '0', { 'get' : f }); +Array.prototype.find.call(arr, func);